From b12c9892ec3c18646fb7f39d5376257eb641fc8d Mon Sep 17 00:00:00 2001 From: Robert Sesek Date: Sun, 15 Mar 2020 15:19:47 -0400 Subject: [PATCH] First cut at a Trace system. --- src/core/Form.ts | 2 ++ src/core/Line.ts | 28 +++++++++++++++---- src/core/Trace.ts | 61 +++++++++++++++++++++++++++++++++++++++++ src/fed2019/Form8949.ts | 3 ++ 4 files changed, 88 insertions(+), 6 deletions(-) create mode 100644 src/core/Trace.ts diff --git a/src/core/Form.ts b/src/core/Form.ts index 4f3124b..6515753 100644 --- a/src/core/Form.ts +++ b/src/core/Form.ts @@ -5,6 +5,7 @@ import Person from './Person'; import TaxReturn from './TaxReturn'; +import Trace from './Trace'; import { Line } from './Line'; import { InconsistencyError, NotFoundError } from './Errors'; @@ -53,6 +54,7 @@ export default abstract class Form }, if (!(name in this._input)) { throw new NotFoundError(`No input with key ${name} on form ${this.name}`); } + Trace.add(`${this.name}-input-${name}`); return this._input[name]; } diff --git a/src/core/Line.ts b/src/core/Line.ts index b0d6515..ca5dd00 100644 --- a/src/core/Line.ts +++ b/src/core/Line.ts @@ -4,6 +4,7 @@ // SPDX-License-Identifier: GPL-3.0-only import TaxReturn from './TaxReturn'; +import Trace from './Trace'; import Form, { FormClass } from './Form'; export abstract class Line { @@ -38,7 +39,10 @@ export class ComputedLine extends Line { } value(tr: TaxReturn): T { - return this._compute(tr); + const trace = new Trace(this); + const value = this._compute(tr); + trace.end(); + return value; } }; @@ -61,10 +65,14 @@ export class ReferenceLine, } value(tr: TaxReturn): T { + const trace = new Trace(this); const form: F = tr.findForm(this._form); - if (this._fallback !== undefined && !form) + if (this._fallback !== undefined && !form) { + trace.end(); return this._fallback; + } const value: T = form.getValue(tr, this._line); + trace.end(); return value; } }; @@ -82,9 +90,14 @@ export class InputLine extends Line } value(tr: TaxReturn): U[T] { - if (!this.form.hasInput(this._input) && this._fallback !== undefined) + const trace = new Trace(this); + if (!this.form.hasInput(this._input) && this._fallback !== undefined) { + trace.end(); return this._fallback; - return this.form.getInput(this._input); + } + const value = this.form.getInput(this._input); + trace.end(); + return value; } }; @@ -95,14 +108,17 @@ export class AccumulatorLine, private _line: L; constructor(form: FormClass, line: L, description?: string) { - super(description || `Accumulator F${form}.L${line}`); + super(description || `Accumulator F${form.name}.L${line}`); this._form = form; this._line = line; } value(tr): number { + const trace = new Trace(this); const forms: F[] = tr.findForms(this._form); - return sumLineOfForms(tr, forms, this._line); + const value = sumLineOfForms(tr, forms, this._line); + trace.end(); + return value; } }; diff --git a/src/core/Trace.ts b/src/core/Trace.ts new file mode 100644 index 0000000..b94fac8 --- /dev/null +++ b/src/core/Trace.ts @@ -0,0 +1,61 @@ +// Copyright 2020 Blue Static +// This program is free software licensed under the GNU General Public License, +// version 3.0. The full text of the license can be found in LICENSE.txt. +// SPDX-License-Identifier: GPL-3.0-only + +import { Line } from './Line'; + +var current: Trace = null; + +var traces: Trace[] = []; + +export default class Trace { + private _stack: Set[] = []; + private _index = 0; + private _name: string; + + constructor(line: Line) { + this._name = this._formatLine(line); + const s = new Set(); + + s.add(`Start: ${this._name}`); + + if (current === null) { + current = this; + } else { + ++current._index; + } + + current._stack.push(s); + } + + static add(id: string) { + if (current === null) + return; + current._stack[current._index].add(id); + } + + end() { + --current._index; + if (current === this) { + current = null; + traces.push(this); + } + } + + get traceList(): readonly string[][] { + return this._stack.map(s => [...s.values()]); + } + + private _formatLine(line: Line): string { + if (line.form === undefined) + return `${line.constructor.name} (${line.description})`; + return `${line.form.name}-${line.id} (${line.description})`; + } +}; + +export function getLastTraceList(): readonly string[][] { + if (traces.length == 0) + return null; + return traces[traces.length - 1].traceList; +} diff --git a/src/fed2019/Form8949.ts b/src/fed2019/Form8949.ts index ea9b266..53e5c21 100644 --- a/src/fed2019/Form8949.ts +++ b/src/fed2019/Form8949.ts @@ -3,6 +3,7 @@ // version 3.0. The full text of the license can be found in LICENSE.txt. // SPDX-License-Identifier: GPL-3.0-only +import Trace from '../core/Trace'; import { Form, Person, TaxReturn } from '../core'; import { Line, InputLine, ComputedLine, sumLineOfForms } from '../core/Line'; @@ -64,6 +65,7 @@ class Form8949Line extends Line { } value(tr: TaxReturn): Form8949Total { + const trace = new Trace(this); const f1099bs = matching1099Bs(tr, this._box); const proceeds = sumLineOfForms(tr, f1099bs, '1d'); const costBasis = sumLineOfForms(tr, f1099bs, '1e'); @@ -72,6 +74,7 @@ class Form8949Line extends Line { f8949.getInput('adjustments') .filter(a => f1099bs.includes(a.entry)) .reduce((acc, curr) => acc + curr.amount, 0); + trace.end(); return { proceeds, costBasis, -- 2.22.5