-
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
Conversation
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.
I have to request a review from @swistach for the tests configuration changes
src/Cell.ts
Outdated
@@ -112,6 +112,7 @@ export class CellError { | |||
constructor( | |||
public readonly type: ErrorType, | |||
public readonly message?: string, | |||
public address?: SimpleCellAddress, |
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.
Do we need to edit it later?
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.
// @ts-ignore | ||
spyOn = jest.spyOn | ||
expect.extend(toEqualError) | ||
}) |
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.
Can't we add this to the main bootstrap.ts
? Now we have two, one clearly marked as jest
the other unknown. We should follow a convention one way or another.
CC @swistach
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.
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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
@wojciechczerniak I've added reminders in tsconfigs and updated PR description.
"extends": "../tsconfig", | ||
"include": ["../src", "../test"], | ||
"exclude": [] | ||
} |
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.
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.
See my comment above #529 (comment)
src/interpreter/Interpreter.ts
Outdated
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 comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't the wrapperForAddress
reason why the error address is not private? We could pass it to the constructor right here without wrapping it later
val = new CellError(ErrorType.NUM, ErrorMessage.NaN) | |
return new CellError(ErrorType.NUM, ErrorMessage.NaN, formulaAddress) |
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.
sure, but the reason behind wrapperForAddress
is to fix whatever comes from evaluation, even in nested, recursive calls
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.
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 comment
The reason will be displayed to describe this comment to others. Learn more.
I've refactored it slightly to make the field private.
To answer your question:
- I'm not sure whether in every place the constructor of CellError is called, we have formulaAddress in the context (there might be some obscure case that would require ugly refactor)
- Adding it here, in a single place, is a minimal change to code that made this feature work, and thus it's much easier to make sure the logic is correctly added in every evaluation.
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.
getter/setter are ok, but my main idea was that CellError
is immutable.
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 comment
The 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.
expect(engine.getCellValue(adr('A1'))).toEqualError(detailedErrorWithOrigin(ErrorType.NA, 'Sheet1!A1')) | ||
expect(engine.getCellValue(adr('B1'))).toEqualError(detailedErrorWithOrigin(ErrorType.NA, 'Sheet1!A1')) | ||
}) | ||
}) |
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.
Please add a few more test cases.
Does it work with Named Expressions (they are in -1
worksheet)?
Does it work with a function, nested function?
With operators?
Between two worksheets?
CRUD operations? (I guess that removing sheet/column will create a new #REF error anyway)
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.
Added some tests. This logic is orthogonal to CRUDs, so any fault here would be fault in CRUDs, and should be tested with CRUDs.
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.
Yeah, true 👍 Thanks for the tests. I've seen that we support all those scenarios, just wanted avoid regressions in the future.
@swistach Nevermind! Let's talk it over |
This pull request fixes 8 alerts when merging 66b3b4d into 7152125 - view on LGTM.com fixed alerts:
|
This pull request fixes 8 alerts when merging 8c4cff4 into 7152125 - view on LGTM.com fixed alerts:
|
@wojciechczerniak CellError address is now immutable. Please see new tests for CYCLE resolving. Also, namedExpression + Error address tests were using improper matcher... |
This pull request introduces 1 alert and fixes 8 when merging 1f112c6 into 7152125 - view on LGTM.com new alerts:
fixed alerts:
|
This pull request introduces 1 alert and fixes 8 when merging e60f181 into 7152125 - view on LGTM.com new alerts:
fixed alerts:
|
This pull request fixes 8 alerts when merging 0cbfd9e into c1630f0 - view on LGTM.com fixed alerts:
|
This pull request fixes 8 alerts when merging 287ee6e into c1630f0 - view on LGTM.com fixed alerts:
|
Codecov Report
@@ Coverage Diff @@
## develop #529 +/- ##
========================================
Coverage 97.23% 97.23%
========================================
Files 155 156 +1
Lines 29429 29466 +37
Branches 3575 3583 +8
========================================
+ Hits 28614 28651 +37
Misses 809 809
Partials 6 6
|
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.
Thanks 🏆
Context
Errors should preserve the original cell that triggers them.
How has this been tested?
Adds a new feature: CellError type carries the address of the original cell that produced the error.
Additionally, exporting/serialization produces nicely human-readable addresses. So we can have following tests:
We also add custom matchers for jest/jasmine, so the test can be written simply:
An example of a usecase is to track the 'sources' of error in the spreadsheet:
Custom matchers setup
In order to compare detailed errors without refactoring all unit tests, new matcher
toEqualError
was introduced. Defining new matcher for bothjest
andjasmine
turned out to be tricky as there is type definition clash.Current setup looks like this:
Jest matchers and additional boostrap file are defined in separate catalog to easily exclude them in jasmine tsconfig (
tsconfig.test.json
). Otherwisejasmine
will complain during the tests.For some reason using
tsconfig.jest.json
in main directory didn't do the job. Neither VSC nor IJ were able to detect new matchers correctly. Workaround was to move this file to./test/tsconfig.json
. It is crucial for local development and debugging as it overrides types definition to usejest
ones.This allows to run
jest
andjasmine
tests and debug tests locally. Hopefully this will simplify someday.Types of changes
Related issue(s):
Checklist: