-
Notifications
You must be signed in to change notification settings - Fork 29.7k
StackTrace parser, fix assertion error message #48343
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
Conversation
| final StackTrace sampleStack = await getSampleStack(); | ||
|
|
||
| test('Error reporting - pretest', () async { | ||
| setUp(() async { |
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.
Because we need this before any individual test. When we eventually randomize our tests this will be important.
| }; | ||
| }); | ||
|
|
||
| tearDown(() async { |
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.
Ditto. Without these changes, none of these tests can be run independently.
|
|
||
| @override | ||
| bool operator ==(Object other) { | ||
| return other is StackFrame && |
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.
we should compare the runtimeType here; see style guide for a template
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.
Done. We should update our style guide - @a14n changed the way this works for removing the avoid_as lint and this + the runtimeType check is actually the convention used now.
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 don't hesitate to update the style guide.
| } | ||
|
|
||
| @override | ||
| String toString() => '$runtimeType{#$number, $packageScheme:$package/$packagePath:$line:$column, className: $className, method: $method}'; |
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.
trivial nit: ( instead of { is our convention
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.
Done
|
If you want to overachieve even more, there's other code in the framework that does stack parsing, like |
|
|
||
| @override | ||
| String toString() => '$runtimeType{#$number, $packageScheme:$package/$packagePath:$line:$column, className: $className, method: $method}'; | ||
| } |
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.
would be nice to have a way to print a frame in a manner that matches what the compiler does, so that you could take a List, filter it, then reprint it and it would come out in the same format as the original, just with some frames omitted.
also, check that this works on web and in AOT mode -- maybe the web stack has differently-shaped stack traces, and I know the AOT compiler has different details (e.g. omits line numbers in some cases?).
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 believe the line number thing was fixed (saw issues for that), but I'll check.
We could also just stuff the whole original string into the object instead of reconstructing it.
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.
AOT is missing columns. Will fix.
goderbauer
left a comment
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.
NICE!
| /// final List<StackFrame> currentFrames = StackFrame.fromStackTrace(StackTrace.current); | ||
| /// ``` | ||
| /// | ||
| /// To create a traversable parsed stack. |
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 believe all text that's outside the dart code block will render above the code in dart docs. So this may look awkward there. I would rephrase this to have the prose text all above the code.
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.
done.
|
|
||
| /// A stack frame representing an asynchronous suspension. | ||
| static const StackFrame asynchronousSuspension = StackFrame( | ||
| -1, |
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.
Should this also be a named parameter? (currently, I'd have to click through to StackFrame to learn what the -1 means.)
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 had it as named but it felt awkward. I could make it named again.
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.
you could also just use nulls, fwiw.
|
I've updated this for defaultStackFilter. |
|
This pull request is not suitable for automatic merging in its current state.
|
|
I may want to add one more thing to this before landing. I think we should keep the original source line - it would make resolving #4174 easier |
|
You can also just do that in a separate PR (e.g. as part of #4174 if you're interested in that one). |
|
Yeah I'll do that in a separate PR. I'm not sure I'll actually need the source line, but since the parsing is lossy it seems useful to have. Parsing stack traces shouldn't need to worry too much about an extra copy of a string anyway. |
| @@ -0,0 +1,230 @@ | |||
| // Copyright 2014 The Flutter Authors. All rights reserved. | |||
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.
2020?
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.
All files in this repo are dated to 2014 to keep things consistent
| ? RegExp(r'^(package:.+) (\d+):(\d+)\s+(.+)$') | ||
| : RegExp(r'^(.+) (\d+):(\d+)\s+(.+)$'); | ||
| final Match match = parser.firstMatch(line); | ||
| assert(match != null, 'Expecgted $line to match $parser.'); |
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.
typo: Expected
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.
Saw this right after landing :( will open a PR to fix, thanks for catching that
| column == other.column && | ||
| className == other.className && | ||
| method == other.method && | ||
| source == other.source; |
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.
If I promoted a style it would be to prefer something like:
return other is StackFrame
&& other.number == number
&& other.package == package
&& other.line == line
...(starting line with && other.)
It's the pattern mostly used inside operator== methods.
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.
This is what the style guide actually now says - I just did it wrong here. I'll update it in the other PR.
|
|
||
| test('Identifies user fault', () { | ||
| // User fault because they called `new Text(null)` from their own code. | ||
| final StackTrace stack = StackTrace.fromString('''#0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:42:39) |
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.
The first line could also be on a newline for readability (the new line followin ''' in multiline string is ignored)
| test('Identifies our fault', () { | ||
| // Our fault because we should either have an assertion in `text_helper.dart` | ||
| // or we should make sure not to pass bad values into new Text. | ||
| final StackTrace stack = StackTrace.fromString('''#0 _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:42:39) |
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.
ditto
Description
Adds a StackTrace parser (fixes #4021) and fixes up the way we print out "this is likely a bug in the framework" message (fixes #18412).
The main goal here is to change the way we print out requests to file a bug on assertion errors. It currently always prints that message because Dart has changed the way it throws assertions (there's an additional frame before the one we used to look for). However, even fixing that still isn't quite right. The new logic here will only print the message on an
AssertionErrorthat has at least two frames of framework code before any other user code - the idea being that we either need to add a new assert to the framework, or stop violating our own asserts in such a case.Related Issues
#4021
#18412
Tests
I added the following tests:
Tests for stack parsing
Tests for checking our fault/not our fault on stack traces.
Checklist
Before you create this PR confirm that it meets all requirements listed below by checking the relevant checkboxes (
[x]). This will ensure a smooth and quick review process.///).flutter analyze --flutter-repo) does not report any problems on my PR.Breaking Change
Did any tests fail when you ran them? Please read Handling breaking changes.