-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Add more structure to errors (continuation of #34684) #42640
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
Merged
Merged
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
eb161e6
Add structured errors in Animations, TabView, ChangeNotifier
94478b3
Add structured error on MaterialPageRoute, BoxBorder, DecorationImage…
711b050
Add structured errors in Debug
3eb06f3
Fix test errors
2eb2df2
Add structured errors in Scaffold and Stepper
f5941f0
Add structured errors in part of Rendering Layer
6683118
Fix failing test due to FloatingPoint precision
6c14773
Fix failing tests due to precision error and not using final
73c4c52
Fix failing test due to floating precision error with RegEx instead
c2544b3
Add structured error in CustomLayout and increase test coverage
0275a37
Add structured error & its test in ListBody
8dbadb8
Add structured error in ProxyBox and increase test coverage
9894d10
Add structured error message in Viewport
7397706
Fix styles and add more assertions on ErrorHint and DiagnosticProperty
94015d9
Add structured error in scheduler/binding and scheduler/ticker
aecce8c
Add structured error in AssetBundle and TextInput
bc64537
Add structured errors in several widgets #1
cbbd90e
Remove unused import
3c0dd4a
Add assertions on hint messages
724c74a
Fix catch spacing
96c9edc
Add structured error in several widgets part 2 and increase code cove…
b406592
Add structured error in flutter_test/widget_tester
d6ed3af
Fix floating precision accuracy by using RegExp
dd245a7
Remove todo to add tests in Scaffold showBottomSheet
2408110
Fix reviews by indenting lines and fixing the assertion orders
128631b
Fix failing tests due to renaming class
72bab51
Try skipping the NetworkBundleTest
31f82f4
Merge branch 'master' of github.com:flutter/flutter into structured-e…
1cbc5c3
Remove leading space in material/debug error hint
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2,6 +2,7 @@ | |
| // Use of this source code is governed by a BSD-style license that can be | ||
| // found in the LICENSE file. | ||
|
|
||
| import 'package:flutter/foundation.dart'; | ||
| import 'package:flutter/widgets.dart'; | ||
|
|
||
| import 'material.dart'; | ||
|
|
@@ -24,45 +25,26 @@ import 'scaffold.dart' show Scaffold; | |
| bool debugCheckHasMaterial(BuildContext context) { | ||
| assert(() { | ||
| if (context.widget is! Material && context.ancestorWidgetOfExactType(Material) == null) { | ||
| final StringBuffer message = StringBuffer(); | ||
| message.writeln('No Material widget found.'); | ||
| message.writeln( | ||
| '${context.widget.runtimeType} widgets require a Material ' | ||
| 'widget ancestor.' | ||
| throw FlutterError.fromParts(<DiagnosticsNode>[ | ||
| ErrorSummary('No Material widget found.'), | ||
| ErrorDescription( | ||
| '${context.widget.runtimeType} widgets require a Material ' | ||
| 'widget ancestor.\n' | ||
| 'In material design, most widgets are conceptually "printed" on ' | ||
| 'a sheet of material. In Flutter\'s material library, that ' | ||
| 'material is represented by the Material widget. It is the ' | ||
| 'Material widget that renders ink splashes, for instance. ' | ||
| 'Because of this, many material library widgets require that ' | ||
| 'there be a Material widget in the tree above them.' | ||
| ), | ||
| ErrorHint( | ||
| 'To introduce a Material widget, you can either directly ' | ||
| 'include one, or use a widget that contains Material itself, ' | ||
| 'such as a Card, Dialog, Drawer, or Scaffold.', | ||
| ), | ||
| ...context.describeMissingAncestor(expectedAncestorType: Material) | ||
| ] | ||
| ); | ||
| message.writeln( | ||
| 'In material design, most widgets are conceptually "printed" on ' | ||
| 'a sheet of material. In Flutter\'s material library, that ' | ||
| 'material is represented by the Material widget. It is the ' | ||
| 'Material widget that renders ink splashes, for instance. ' | ||
| 'Because of this, many material library widgets require that ' | ||
| 'there be a Material widget in the tree above them.' | ||
| ); | ||
| message.writeln( | ||
| 'To introduce a Material widget, you can either directly ' | ||
| 'include one, or use a widget that contains Material itself, ' | ||
| 'such as a Card, Dialog, Drawer, or Scaffold.' | ||
| ); | ||
| message.writeln( | ||
| 'The specific widget that could not find a Material ancestor was:' | ||
| ); | ||
| message.writeln(' ${context.widget}'); | ||
| final List<Widget> ancestors = <Widget>[]; | ||
| context.visitAncestorElements((Element element) { | ||
| ancestors.add(element.widget); | ||
| return true; | ||
| }); | ||
| if (ancestors.isNotEmpty) { | ||
| message.write('The ancestors of this widget were:'); | ||
| for (Widget ancestor in ancestors) | ||
| message.write('\n $ancestor'); | ||
| } else { | ||
| message.writeln( | ||
| 'This widget is the root of the tree, so it has no ' | ||
| 'ancestors, let alone a "Material" ancestor.' | ||
| ); | ||
| } | ||
| throw FlutterError(message.toString()); | ||
| } | ||
| return true; | ||
| }()); | ||
|
|
@@ -87,42 +69,24 @@ bool debugCheckHasMaterial(BuildContext context) { | |
| bool debugCheckHasMaterialLocalizations(BuildContext context) { | ||
| assert(() { | ||
| if (Localizations.of<MaterialLocalizations>(context, MaterialLocalizations) == null) { | ||
| final StringBuffer message = StringBuffer(); | ||
| message.writeln('No MaterialLocalizations found.'); | ||
| message.writeln( | ||
| '${context.widget.runtimeType} widgets require MaterialLocalizations ' | ||
| 'to be provided by a Localizations widget ancestor.' | ||
| ); | ||
| message.writeln( | ||
| 'Localizations are used to generate many different messages, labels,' | ||
| 'and abbreviations which are used by the material library. ' | ||
| ); | ||
| message.writeln( | ||
| 'To introduce a MaterialLocalizations, either use a ' | ||
| ' MaterialApp at the root of your application to include them ' | ||
| 'automatically, or add a Localization widget with a ' | ||
| 'MaterialLocalizations delegate.' | ||
| ); | ||
| message.writeln( | ||
| 'The specific widget that could not find a MaterialLocalizations ancestor was:' | ||
| ); | ||
| message.writeln(' ${context.widget}'); | ||
| final List<Widget> ancestors = <Widget>[]; | ||
| context.visitAncestorElements((Element element) { | ||
| ancestors.add(element.widget); | ||
| return true; | ||
| }); | ||
| if (ancestors.isNotEmpty) { | ||
| message.write('The ancestors of this widget were:'); | ||
| for (Widget ancestor in ancestors) | ||
| message.write('\n $ancestor'); | ||
| } else { | ||
| message.writeln( | ||
| 'This widget is the root of the tree, so it has no ' | ||
| 'ancestors, let alone a "Localizations" ancestor.' | ||
| ); | ||
| } | ||
| throw FlutterError(message.toString()); | ||
| throw FlutterError.fromParts(<DiagnosticsNode>[ | ||
| ErrorSummary('No MaterialLocalizations found.'), | ||
| ErrorDescription( | ||
| '${context.widget.runtimeType} widgets require MaterialLocalizations ' | ||
| 'to be provided by a Localizations widget ancestor.' | ||
| ), | ||
| ErrorDescription( | ||
| 'Localizations are used to generate many different messages, labels,' | ||
| 'and abbreviations which are used by the material library.' | ||
| ), | ||
| ErrorHint( | ||
| 'To introduce a MaterialLocalizations, either use a ' | ||
| 'MaterialApp at the root of your application to include them ' | ||
| 'automatically, or add a Localization widget with a ' | ||
| 'MaterialLocalizations delegate.' | ||
| ), | ||
| ...context.describeMissingAncestor(expectedAncestorType: MaterialLocalizations) | ||
| ]); | ||
| } | ||
| return true; | ||
| }()); | ||
|
|
@@ -145,17 +109,15 @@ bool debugCheckHasMaterialLocalizations(BuildContext context) { | |
| bool debugCheckHasScaffold(BuildContext context) { | ||
| assert(() { | ||
| if (context.widget is! Scaffold && context.ancestorWidgetOfExactType(Scaffold) == null) { | ||
| final Element element = context; | ||
| throw FlutterError( | ||
| 'No Scaffold widget found.\n' | ||
| '${context.widget.runtimeType} widgets require a Scaffold widget ancestor.\n' | ||
| 'The Specific widget that could not find a Scaffold ancestor was:\n' | ||
| ' ${context.widget}\n' | ||
| 'The ownership chain for the affected widget is:\n' | ||
| ' ${element.debugGetCreatorChain(10)}\n' | ||
| throw FlutterError.fromParts(<DiagnosticsNode>[ | ||
| ErrorSummary('No Scaffold widget found.'), | ||
| ErrorDescription('${context.widget.runtimeType} widgets require a Scaffold widget ancestor.'), | ||
| ...context.describeMissingAncestor(expectedAncestorType: Scaffold), | ||
|
Contributor
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. @munificent being able to use |
||
| ErrorHint( | ||
| 'Typically, the Scaffold widget is introduced by the MaterialApp or ' | ||
| 'WidgetsApp widget at the top of your application widget tree.' | ||
| ); | ||
| ) | ||
| ]); | ||
| } | ||
| return true; | ||
| }()); | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back 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.
I thought FlutterError would automatically take its first line and use it as a summary and use the rest as a description, is that not the case?
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 I believe so too, this is actually redundant change
cc: @jacob314
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 go ahead and revert this change as part of your followup cleanup CL.