Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
f04fd43f
Commit
f04fd43f
authored
Mar 07, 2016
by
Ian Hickson
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #2461 from Hixie/ErrorWidget
Include more details in the Red Box of Doom
parents
a1535d05
826b13bd
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
99 additions
and
13 deletions
+99
-13
debug.dart
packages/flutter/lib/src/material/debug.dart
+6
-2
debug.dart
packages/flutter/lib/src/rendering/debug.dart
+0
-3
error.dart
packages/flutter/lib/src/rendering/error.dart
+73
-4
framework.dart
packages/flutter/lib/src/widgets/framework.dart
+19
-3
widget_tester.dart
packages/flutter_test/lib/src/widget_tester.dart
+1
-1
No files found.
packages/flutter/lib/src/material/debug.dart
View file @
f04fd43f
...
...
@@ -13,12 +13,14 @@ bool debugCheckHasMaterial(BuildContext context) {
Element
element
=
context
;
throw
new
WidgetError
(
'No Material widget found.
\n
'
'
${context.widget}
widgets require a Material widget ancestor.
\n
'
'
${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.
\n
'
'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.
\n
'
'The specific widget that could not find a Material ancestor was:
\n
'
'
${context.widget}
'
'The ownership chain for the affected widget is:
\n
'
'
${element.debugGetOwnershipChain(10)}
'
);
...
...
@@ -35,7 +37,9 @@ bool debugCheckHasScaffold(BuildContext context) {
Element
element
=
context
;
throw
new
WidgetError
(
'No Scaffold widget found.
\n
'
'
${context.widget}
widgets require a Scaffold widget ancestor.
\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}
'
'The ownership chain for the affected widget is:
\n
'
'
${element.debugGetOwnershipChain(10)}
'
);
...
...
packages/flutter/lib/src/rendering/debug.dart
View file @
f04fd43f
...
...
@@ -53,9 +53,6 @@ bool debugPaintPointersEnabled = false;
/// The color to use when reporting pointers.
int
debugPaintPointersColorValue
=
0x00BBBB
;
/// The color to use when painting [RenderErrorBox] objects in checked mode.
Color
debugErrorBoxColor
=
const
Color
(
0xFFFF0000
);
/// Overlay a rotating set of colors when repainting layers in checked mode.
bool
debugRepaintRainbowEnabled
=
false
;
...
...
packages/flutter/lib/src/rendering/error.dart
View file @
f04fd43f
...
...
@@ -2,15 +2,56 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import
'dart:ui'
as
ui
show
Paragraph
,
ParagraphBuilder
,
ParagraphStyle
,
TextStyle
;
import
'box.dart'
;
import
'debug.dart'
;
import
'object.dart'
;
const
double
_kMaxWidth
=
100000.0
;
const
double
_kMaxHeight
=
100000.0
;
/// A render object used as a placeholder when an error occurs
/// A render object used as a placeholder when an error occurs.
///
/// The box will be painted in the color given by the
/// [RenderErrorBox.backgroundColor] static property.
///
/// A message can be provided. To simplify the class and thus help reduce the
/// likelihood of this class itself being the source of errors, the message
/// cannot be changed once the object has been created. If provided, the text
/// will be painted on top of the background, using the styles given by the
/// [RenderErrorBox.textStyle] and [RenderErrorBox.paragraphStyle] static
/// properties.
///
/// Again to help simplify the class, this box tries to be 100000.0 pixels wide
/// and high, to approximate being infinitely high but without using infinities.
class
RenderErrorBox
extends
RenderBox
{
/// Constructs a RenderErrorBox render object.
///
/// A message can optionally be provided. If a message is provided, an attempt
/// will be made to render the message when the box paints.
RenderErrorBox
([
this
.
message
=
''
])
{
try
{
if
(
message
!=
''
)
{
// This class is intentionally doing things using the low-level
// primitives to avoid depending on any subsystems that may have ended
// up in an unstable state -- after all, this class is mainly used when
// things have gone wrong.
//
// Generally, the much better way to draw text in a RenderObject is to
// use the TextPainter class. If you're looking for code to crib from,
// see the paragraph.dart file and the RenderParagraph class.
ui
.
ParagraphBuilder
builder
=
new
ui
.
ParagraphBuilder
();
builder
.
pushStyle
(
textStyle
);
builder
.
addText
(
message
);
_paragraph
=
builder
.
build
(
paragraphStyle
);
}
}
catch
(
e
)
{
}
}
/// The message to attempt to display at paint time.
final
String
message
;
ui
.
Paragraph
_paragraph
;
double
getMinIntrinsicWidth
(
BoxConstraints
constraints
)
{
return
constraints
.
constrainWidth
(
0.0
);
...
...
@@ -36,8 +77,36 @@ class RenderErrorBox extends RenderBox {
size
=
constraints
.
constrain
(
const
Size
(
_kMaxWidth
,
_kMaxHeight
));
}
/// The color to use when painting the background of [RenderErrorBox] objects.
static
Color
backgroundColor
=
const
Color
(
0xF0900000
);
/// The text style to use when painting [RenderErrorBox] objects.
static
ui
.
TextStyle
textStyle
=
new
ui
.
TextStyle
(
color:
const
Color
(
0xFFFFFF00
),
fontFamily:
'monospace'
,
fontSize:
7.0
);
/// The paragraph style to use when painting [RenderErrorBox] objects.
static
ui
.
ParagraphStyle
paragraphStyle
=
new
ui
.
ParagraphStyle
(
lineHeight:
0.25
// TODO(ianh): https://github.com/flutter/flutter/issues/2460 will affect this
);
void
paint
(
PaintingContext
context
,
Offset
offset
)
{
context
.
canvas
.
drawRect
(
offset
&
size
,
new
Paint
()
..
color
=
debugErrorBoxColor
);
try
{
context
.
canvas
.
drawRect
(
offset
&
size
,
new
Paint
()
..
color
=
backgroundColor
);
if
(
_paragraph
!=
null
)
{
// See the comment in the RenderErrorBox constructor. This is not the
// code you want to be copying and pasting. :-)
if
(
parent
is
RenderBox
)
{
RenderBox
parentBox
=
parent
;
_paragraph
.
maxWidth
=
parentBox
.
size
.
width
;
}
else
{
_paragraph
.
maxWidth
=
size
.
width
;
}
_paragraph
.
layout
();
_paragraph
.
paint
(
context
.
canvas
,
offset
);
}
}
catch
(
e
)
{
}
}
}
packages/flutter/lib/src/widgets/framework.dart
View file @
f04fd43f
...
...
@@ -1016,8 +1016,24 @@ abstract class Element<T extends Widget> implements BuildContext {
}
}
/// A widget that renders an exception's message. This widget is used when a
/// build function fails, to help with determining where the problem lies.
/// Exceptions are also logged to the console, which you can read using `flutter
/// logs`. The console will also include additional information such as the
/// stack trace for the exception.
class
ErrorWidget
extends
LeafRenderObjectWidget
{
RenderBox
createRenderObject
()
=>
new
RenderErrorBox
();
ErrorWidget
(
Object
exception
)
:
message
=
_stringify
(
exception
),
super
(
key:
new
UniqueKey
());
final
String
message
;
static
String
_stringify
(
Object
exception
)
{
try
{
return
exception
.
toString
();
}
catch
(
e
)
{
}
return
'Error'
;
}
RenderBox
createRenderObject
()
=>
new
RenderErrorBox
(
message
);
}
typedef
void
BuildScheduler
(
BuildableElement
element
);
...
...
@@ -1224,7 +1240,7 @@ abstract class ComponentElement<T extends Widget> extends BuildableElement<T> {
});
}
catch
(
e
,
stack
)
{
_debugReportException
(
'building
$_widget
'
,
e
,
stack
);
built
=
new
ErrorWidget
();
built
=
new
ErrorWidget
(
e
);
}
finally
{
// We delay marking the element as clean until after calling _builder so
// that attempts to markNeedsBuild() during build() will be ignored.
...
...
@@ -1236,7 +1252,7 @@ abstract class ComponentElement<T extends Widget> extends BuildableElement<T> {
assert
(
_child
!=
null
);
}
catch
(
e
,
stack
)
{
_debugReportException
(
'building
$_widget
'
,
e
,
stack
);
built
=
new
ErrorWidget
();
built
=
new
ErrorWidget
(
e
);
_child
=
updateChild
(
null
,
built
,
slot
);
}
}
...
...
packages/flutter_test/lib/src/widget_tester.dart
View file @
f04fd43f
...
...
@@ -78,7 +78,7 @@ class WidgetTester extends Instrumentation {
super
(
binding:
_SteppedWidgetFlutterBinding
.
ensureInitialized
())
{
timeDilation
=
1.0
;
ui
.
window
.
onBeginFrame
=
null
;
runApp
(
new
ErrorWidget
(
));
// flush out the last build entirely
runApp
(
new
Container
(
key:
new
UniqueKey
()
));
// flush out the last build entirely
}
final
FakeAsync
async
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment