Unverified Commit 1ceffd28 authored by Kenzie Schmoll's avatar Kenzie Schmoll Committed by GitHub

Only show devtools deep links for render overflow errors (#74916)

parent 129003f0
......@@ -2873,12 +2873,19 @@ bool _isDebugCreator(DiagnosticsNode node) => node is DiagnosticsDebugCreator;
/// in [WidgetsBinding.initInstances].
Iterable<DiagnosticsNode> transformDebugCreator(Iterable<DiagnosticsNode> properties) sync* {
final List<DiagnosticsNode> pending = <DiagnosticsNode>[];
ErrorSummary? errorSummary;
for (final DiagnosticsNode node in properties) {
if (node is ErrorSummary) {
errorSummary = node;
break;
}
}
bool foundStackTrace = false;
for (final DiagnosticsNode node in properties) {
if (!foundStackTrace && node is DiagnosticsStackTrace)
foundStackTrace = true;
if (_isDebugCreator(node)) {
yield* _parseDiagnosticsNode(node)!;
yield* _parseDiagnosticsNode(node, errorSummary)!;
} else {
if (foundStackTrace) {
pending.add(node);
......@@ -2893,15 +2900,21 @@ Iterable<DiagnosticsNode> transformDebugCreator(Iterable<DiagnosticsNode> proper
/// Transform the input [DiagnosticsNode].
///
/// Return null if input [DiagnosticsNode] is not applicable.
Iterable<DiagnosticsNode>? _parseDiagnosticsNode(DiagnosticsNode node) {
Iterable<DiagnosticsNode>? _parseDiagnosticsNode(
DiagnosticsNode node,
ErrorSummary? errorSummary,
) {
if (!_isDebugCreator(node))
return null;
final DebugCreator debugCreator = node.value! as DebugCreator;
final Element element = debugCreator.element;
return _describeRelevantUserCode(element);
return _describeRelevantUserCode(element, errorSummary);
}
Iterable<DiagnosticsNode> _describeRelevantUserCode(Element element) {
Iterable<DiagnosticsNode> _describeRelevantUserCode(
Element element,
ErrorSummary? errorSummary,
) {
if (!WidgetInspectorService.instance.isWidgetCreationTracked()) {
return <DiagnosticsNode>[
ErrorDescription(
......@@ -2912,20 +2925,38 @@ Iterable<DiagnosticsNode> _describeRelevantUserCode(Element element) {
ErrorSpacer(),
];
}
bool isOverflowError() {
if (errorSummary != null && errorSummary.value.isNotEmpty) {
final Object summary = errorSummary.value.first;
if (summary is String && summary.startsWith('A RenderFlex overflowed by')) {
return true;
}
}
return false;
}
final List<DiagnosticsNode> nodes = <DiagnosticsNode>[];
bool processElement(Element target) {
// TODO(chunhtai): should print out all the widgets that are about to cross
// package boundaries.
if (debugIsLocalCreationLocation(target)) {
DiagnosticsNode? devToolsDiagnostic;
final String? devToolsInspectorUri =
WidgetInspectorService.instance._devToolsInspectorUriForElement(target);
if (devToolsInspectorUri != null) {
devToolsDiagnostic = DevToolsDeepLinkProperty(
'To inspect this widget in Flutter DevTools, visit: $devToolsInspectorUri',
devToolsInspectorUri,
);
// TODO(kenz): once the inspector is better at dealing with broken trees,
// we can enable deep links for more errors than just RenderFlex overflow
// errors. See https://github.com/flutter/flutter/issues/74918.
if (isOverflowError()) {
final String? devToolsInspectorUri =
WidgetInspectorService.instance._devToolsInspectorUriForElement(target);
if (devToolsInspectorUri != null) {
devToolsDiagnostic = DevToolsDeepLinkProperty(
'To inspect this widget in Flutter DevTools, visit: $devToolsInspectorUri',
devToolsInspectorUri,
);
}
}
nodes.addAll(<DiagnosticsNode>[
......
......@@ -1044,6 +1044,101 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(nodes[4].runtimeType, DiagnosticsStackTrace);
}, skip: WidgetInspectorService.instance.isWidgetCreationTracked()); // Test requires --no-track-widget-creation flag.
testWidgets('test transformDebugCreator will add DevToolsDeepLinkProperty for overflow errors', (WidgetTester tester) async {
activeDevToolsServerAddress = 'http://127.0.0.1:9100';
connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/';
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Stack(
children: const <Widget>[
Text('a'),
Text('b', textDirection: TextDirection.ltr),
Text('c', textDirection: TextDirection.ltr),
],
),
),
);
final Element elementA = find.text('a').evaluate().first;
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
builder.add(ErrorSummary('A RenderFlex overflowed by 273 pixels on the bottom'));
builder.add(DiagnosticsDebugCreator(DebugCreator(elementA)));
builder.add(StringProperty('dummy2', 'value'));
final List<DiagnosticsNode> nodes = List<DiagnosticsNode>.from(transformDebugCreator(builder.properties));
expect(nodes.length, 6);
expect(nodes[0].runtimeType, ErrorSummary);
expect(nodes[1].runtimeType, DiagnosticsBlock);
expect(nodes[2].runtimeType, ErrorSpacer);
expect(nodes[3].runtimeType, DevToolsDeepLinkProperty);
expect(nodes[4].runtimeType, ErrorSpacer);
expect(nodes[5].runtimeType, StringProperty);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked());
testWidgets('test transformDebugCreator will not add DevToolsDeepLinkProperty for non-overflow errors', (WidgetTester tester) async {
activeDevToolsServerAddress = 'http://127.0.0.1:9100';
connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/';
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Stack(
children: const <Widget>[
Text('a'),
Text('b', textDirection: TextDirection.ltr),
Text('c', textDirection: TextDirection.ltr),
],
),
),
);
final Element elementA = find.text('a').evaluate().first;
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
builder.add(ErrorSummary('some other error'));
builder.add(DiagnosticsDebugCreator(DebugCreator(elementA)));
builder.add(StringProperty('dummy2', 'value'));
final List<DiagnosticsNode> nodes = List<DiagnosticsNode>.from(transformDebugCreator(builder.properties));
expect(nodes.length, 4);
expect(nodes[0].runtimeType, ErrorSummary);
expect(nodes[1].runtimeType, DiagnosticsBlock);
expect(nodes[2].runtimeType, ErrorSpacer);
expect(nodes[3].runtimeType, StringProperty);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked());
testWidgets('test transformDebugCreator will not add DevToolsDeepLinkProperty if devtoolsServerAddress is unavailable', (WidgetTester tester) async {
activeDevToolsServerAddress = null;
connectedVmServiceUri = 'http://127.0.0.1:55269/798ay5al_FM=/';
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: Stack(
children: const <Widget>[
Text('a'),
Text('b', textDirection: TextDirection.ltr),
Text('c', textDirection: TextDirection.ltr),
],
),
),
);
final Element elementA = find.text('a').evaluate().first;
final DiagnosticPropertiesBuilder builder = DiagnosticPropertiesBuilder();
builder.add(ErrorSummary('A RenderFlex overflowed by 273 pixels on the bottom'));
builder.add(DiagnosticsDebugCreator(DebugCreator(elementA)));
builder.add(StringProperty('dummy2', 'value'));
final List<DiagnosticsNode> nodes = List<DiagnosticsNode>.from(transformDebugCreator(builder.properties));
expect(nodes.length, 4);
expect(nodes[0].runtimeType, ErrorSummary);
expect(nodes[1].runtimeType, DiagnosticsBlock);
expect(nodes[2].runtimeType, ErrorSpacer);
expect(nodes[3].runtimeType, StringProperty);
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked());
testWidgets('WidgetInspectorService setPubRootDirectories', (WidgetTester tester) async {
await tester.pumpWidget(
Directionality(
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment