-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
error origins #529
error origins #529
Changes from 15 commits
4b7ed6f
939ea86
cac2039
233c0f4
800d7a3
9e3d560
1103363
b704304
3df98ef
594f748
357eaeb
bb0841e
0ad6814
8f4adcb
eef1888
644644d
9b5b78f
11a1f68
5ca9ae0
9e6655e
86cbeca
4118d64
6352e4e
66b3b4d
8c4cff4
1f112c6
e60f181
9edda38
0cbfd9e
287ee6e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -54,24 +54,23 @@ export class Interpreter { | |||||
} | ||||||
|
||||||
public evaluateAst(ast: Ast, formulaAddress: SimpleCellAddress): InterpreterValue { | ||||||
const val = this.evaluateAstWithoutPostoprocessing(ast, formulaAddress) | ||||||
let val = this.evaluateAstWithoutPostoprocessing(ast, formulaAddress) | ||||||
if (typeof val === 'number') { | ||||||
if (isNumberOverflow(val)) { | ||||||
return new CellError(ErrorType.NUM, ErrorMessage.NaN) | ||||||
val = new CellError(ErrorType.NUM, ErrorMessage.NaN) | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Isn't the
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure, but the reason behind There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Shouldn't all functions return the correct error? We're patching the error object just to avoid fixing this in the right places or there is some way to create an error that don't know it's origin? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I've refactored it slightly to make the field private.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. getter/setter are ok, but my main idea was that Once created it cannot be altered, especially the origin address. Having this editable is IMO a risk. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's not getter/setter, its getter and (setter that only sets it once, if the value is not present yet). So I don't see any risk here. Also, keep in mind that this value is supplementary one, it does not affect outcome of calculation, only provides debugging info. |
||||||
} else { | ||||||
return fixNegativeZero(val) | ||||||
val = fixNegativeZero(val) | ||||||
} | ||||||
} else { | ||||||
return val | ||||||
} | ||||||
return wrapperForAddress(val, formulaAddress) | ||||||
} | ||||||
/** | ||||||
* Calculates cell value from formula abstract syntax tree | ||||||
* | ||||||
* @param formula - abstract syntax tree of formula | ||||||
* @param formulaAddress - address of the cell in which formula is located | ||||||
*/ | ||||||
public evaluateAstWithoutPostoprocessing(ast: Ast, formulaAddress: SimpleCellAddress): InterpreterValue { | ||||||
private evaluateAstWithoutPostoprocessing(ast: Ast, formulaAddress: SimpleCellAddress): InterpreterValue { | ||||||
switch (ast.type) { | ||||||
case AstNodeType.EMPTY: { | ||||||
return EmptyValue | ||||||
|
@@ -322,3 +321,9 @@ function wrapperBinary<T extends InterpreterValue>(op: (a: T, b: T) => Interpret | |||||
} | ||||||
} | ||||||
|
||||||
function wrapperForAddress(val: InterpreterValue, adr: SimpleCellAddress): InterpreterValue { | ||||||
if(val instanceof CellError) { | ||||||
val.address = val.address ?? adr | ||||||
} | ||||||
return val | ||||||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import {toEqualError} from './toEqualError' | ||
|
||
beforeAll(() => { | ||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore | ||
// @ts-ignore | ||
spyOn = jest.spyOn | ||
expect.extend(toEqualError) | ||
}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can't we add this to the main CC @swistach There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know that present setup looks a littlebit strange, but there were some problems and type definition clashes otherwise. If you now how to simplify this setup to be able to work locally with jest in IntelliJ and debugger and not break jasmine at the same time, feel free to correct it. I failed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Discussed offline. I will try to describe problem behind it in PR description. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @wojciechczerniak I've added reminders in tsconfigs and updated PR description. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
type CustomMatcherResult = jest.CustomMatcherResult | ||
type ExpectExtendMap = jest.ExpectExtendMap | ||
|
||
declare global { | ||
namespace jest { | ||
interface Matchers<R, T> { | ||
toEqualError(expected: any): CustomMatcherResult, | ||
} | ||
} | ||
} | ||
|
||
export const toEqualError: ExpectExtendMap = {toEqualError(received: any, expected: any): CustomMatcherResult { | ||
let result = false | ||
izulin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (typeof received === 'object' && typeof expected === 'object') { | ||
result = this.equals( | ||
{...received, address: undefined}, | ||
{...expected, address: undefined} | ||
) | ||
} else { | ||
result = this.equals(received, expected) | ||
} | ||
return { | ||
pass: result, | ||
message: () => (result ? '' : `Expected ${received} to be match ${expected}.`) | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
export { toContainEqualMatcher } from './toContainEqual' | ||
export { toMatchObjectMatcher } from './toMatchObject' | ||
export { toEqualErrorMatcher } from './toEqualError' |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
type CustomMatcher = jasmine.CustomMatcher | ||
type CustomMatcherFactories = jasmine.CustomMatcherFactories | ||
type CustomMatcherResult = jasmine.CustomMatcherResult | ||
type MatchersUtil = jasmine.MatchersUtil | ||
|
||
declare global { | ||
namespace jasmine { | ||
interface Matchers<T> { | ||
toEqualError(expected: any, expectationFailOutput?: string): boolean, | ||
} | ||
} | ||
} | ||
|
||
export const toEqualErrorMatcher: CustomMatcherFactories = { | ||
toEqualError: function(util: MatchersUtil): CustomMatcher { | ||
return { | ||
compare: function(received: any, expected: any): CustomMatcherResult { | ||
let result | ||
if (typeof received === 'object' && typeof expected === 'object') { | ||
result = util.equals( | ||
{...received, address: undefined}, | ||
{...expected, address: undefined} | ||
) | ||
} else { | ||
result = util.equals(received, expected) | ||
} | ||
return { | ||
pass: result, | ||
message: result ? '' : `Expected ${JSON.stringify(received, null, 2)} to match ${JSON.stringify(expected, null, 2)}.` | ||
} | ||
}, | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO shouldn't be optional, and should be readonly. Set once and propagated. Do we need to edit it later?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, errors are sometimes created in a context that lacks address, and this value is supplemented later.
Right now this address is set in a single place in an interpreter.