Skip to content
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

Make inspector details subtree depth configurable. #39085

Merged
merged 4 commits into from Aug 28, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
38 changes: 30 additions & 8 deletions packages/flutter/lib/src/widgets/widget_inspector.dart
Expand Up @@ -1089,9 +1089,19 @@ mixin WidgetInspectorService {
name: 'getRootWidgetSummaryTree',
callback: _getRootWidgetSummaryTree,
);
_registerServiceExtensionWithArg(
registerServiceExtension(
name: 'getDetailsSubtree',
callback: _getDetailsSubtree,
callback: (Map<String, String> parameters) async {
assert(parameters.containsKey('objectGroup'));
final String subtreeDepth = parameters['subtreeDepth'];
return <String, Object>{
'result': _getDetailsSubtree(
parameters['arg'],
parameters['objectGroup'],
subtreeDepth != null ? int.parse(subtreeDepth) : 2,
),
};
},
);
_registerServiceExtensionWithArg(
name: 'getSelectedRenderObject',
Expand Down Expand Up @@ -1603,15 +1613,27 @@ mixin WidgetInspectorService {
/// [DiagnosticsNode] object that `diagnosticsNodeId` references providing
/// information needed for the details subtree view.
///
/// The number of levels of the subtree that should be returned is specified
/// by the [subtreeDepth] parameter. This value defaults to 2 for backwards
/// compatibility.
///
/// See also:
///
/// * [getChildrenDetailsSubtree], a method to get children of a node
/// in the details subtree.
String getDetailsSubtree(String id, String groupName) {
return _safeJsonEncode(_getDetailsSubtree( id, groupName));
}

Map<String, Object> _getDetailsSubtree(String id, String groupName) {
String getDetailsSubtree(
kenzieschmoll marked this conversation as resolved.
Show resolved Hide resolved
String id,
String groupName, {
int subtreeDepth = 2,
}) {
return _safeJsonEncode(_getDetailsSubtree( id, groupName, subtreeDepth));
}

Map<String, Object> _getDetailsSubtree(
String id,
String groupName,
int subtreeDepth,
) {
final DiagnosticsNode root = toObject(id);
if (root == null) {
return null;
Expand All @@ -1621,7 +1643,7 @@ mixin WidgetInspectorService {
_SerializationDelegate(
groupName: groupName,
summaryTree: false,
subtreeDepth: 2, // TODO(jacobr): make subtreeDepth configurable.
subtreeDepth: subtreeDepth,
includeProperties: true,
service: this,
),
Expand Down
61 changes: 38 additions & 23 deletions packages/flutter/test/widgets/widget_inspector_test.dart
Expand Up @@ -253,14 +253,14 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
}

Future<Object> testExtension(String name, Map<String, String> arguments) async {
expect(extensions.containsKey(name), isTrue);
expect(extensions, contains(name));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for cleaning this up!

// Encode and decode to JSON to match behavior using a real service
// extension where only JSON is allowed.
return json.decode(json.encode(await extensions[name](arguments)))['result'];
}

Future<String> testBoolExtension(String name, Map<String, String> arguments) async {
expect(extensions.containsKey(name), isTrue);
expect(extensions, contains(name));
// Encode and decode to JSON to match behavior using a real service
// extension where only JSON is allowed.
return json.decode(json.encode(await extensions[name](arguments)))['enabled'];
Expand Down Expand Up @@ -371,7 +371,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final InspectorSelection selection = getInspectorState().selection;
expect(paragraphText(selection.current), equals('TOP'));
final RenderObject topButton = find.byKey(topButtonKey).evaluate().first.renderObject;
expect(selection.candidates.contains(topButton), isTrue);
expect(selection.candidates, contains(topButton));

await tester.tap(find.text('TOP'));
expect(log, equals(<String>['top']));
Expand Down Expand Up @@ -906,7 +906,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final List<DiagnosticsNode> children = node.getChildren();
expect(children.length, 1);
final ErrorDescription child = children[0];
expect(child.valueToString().contains(Uri.parse(pubRootTest).path), true);
expect(child.valueToString(), contains(Uri.parse(pubRootTest).path));
} else {
expect(nodes[2].runtimeType, ErrorDescription);
final ErrorDescription node = nodes[2];
Expand Down Expand Up @@ -967,7 +967,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final List<DiagnosticsNode> children = node.getChildren();
expect(children.length, 1);
final ErrorDescription child = children[0];
expect(child.valueToString().contains(Uri.parse(pubRootTest).path), true);
expect(child.valueToString(), contains(Uri.parse(pubRootTest).path));
} else {
expect(nodes[1].runtimeType, ErrorDescription);
final ErrorDescription node = nodes[1];
Expand Down Expand Up @@ -1264,7 +1264,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
for (Map<String, Object> propertyJson in propertiesJson) {
final Object property = service.toObject(propertyJson['objectId']);
expect(property, isInstanceOf<DiagnosticsNode>());
expect(expectedProperties.contains(property), isTrue);
expect(expectedProperties, contains(property));
}
}
});
Expand Down Expand Up @@ -1297,12 +1297,27 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(service.toObject(childJson['valueId']), equals(children[i].value));
expect(service.toObject(childJson['objectId']), isInstanceOf<DiagnosticsNode>());
final List<Object> propertiesJson = childJson['properties'];
for (Map<String, Object> propertyJson in propertiesJson) {
expect(propertyJson, isNot(contains('children')));
}
final DiagnosticsNode diagnosticsNode = service.toObject(childJson['objectId']);
final List<DiagnosticsNode> expectedProperties = diagnosticsNode.getProperties();
for (Map<String, Object> propertyJson in propertiesJson) {
final Object property = service.toObject(propertyJson['objectId']);
expect(property, isInstanceOf<DiagnosticsNode>());
expect(expectedProperties.contains(property), isTrue);
expect(expectedProperties, contains(property));
}
}

final Map<String, Object> deepSubtreeJson = await service.testExtension(
'getDetailsSubtree',
<String, String>{'arg': id, 'objectGroup': group, 'subtreeDepth': '3'},
);
final List<Object> deepChildrenJson = deepSubtreeJson['children'];
for(Map<String, Object> childJson in deepChildrenJson) {
final List<Object> propertiesJson = childJson['properties'];
for (Map<String, Object> propertyJson in propertiesJson) {
expect(propertyJson, contains('children'));
}
}
});
Expand All @@ -1319,15 +1334,15 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final String id = service.toId(diagnostic, group);
final Map<String, Object> subtreeJson = await service.testExtension('getDetailsSubtree', <String, String>{'arg': id, 'objectGroup': group});
expect(subtreeJson['objectId'], equals(id));
expect(subtreeJson.containsKey('children'), isTrue);
expect(subtreeJson, contains('children'));
final List<Object> propertiesJson = subtreeJson['properties'];
expect(propertiesJson.length, equals(1));
final Map<String, Object> relatedProperty = propertiesJson.first;
expect(relatedProperty['name'], equals('related'));
expect(relatedProperty['description'], equals('CyclicDiagnostic-b'));
expect(relatedProperty.containsKey('isDiagnosticableValue'), isTrue);
expect(relatedProperty.containsKey('children'), isFalse);
expect(relatedProperty.containsKey('properties'), isTrue);
expect(relatedProperty, contains('isDiagnosticableValue'));
expect(relatedProperty, isNot(contains('children')));
expect(relatedProperty, contains('properties'));
final List<Object> relatedWidgetProperties = relatedProperty['properties'];
expect(relatedWidgetProperties.length, equals(1));
final Map<String, Object> nestedRelatedProperty = relatedWidgetProperties.first;
Expand All @@ -1336,9 +1351,9 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
// which we already included as the root node as that would indicate a
// cycle.
expect(nestedRelatedProperty['description'], equals('CyclicDiagnostic-a'));
expect(nestedRelatedProperty.containsKey('isDiagnosticableValue'), isTrue);
expect(nestedRelatedProperty.containsKey('properties'), isFalse);
expect(nestedRelatedProperty.containsKey('children'), isFalse);
expect(nestedRelatedProperty, contains('isDiagnosticableValue'));
expect(nestedRelatedProperty, isNot(contains('properties')));
expect(nestedRelatedProperty, isNot(contains('children')));
});

testWidgets('ext.flutter.inspector.getRootWidgetSummaryTree', (WidgetTester tester) async {
Expand Down Expand Up @@ -1682,7 +1697,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final int count = data[i + 1];
totalCount += count;
maxCount = max(maxCount, count);
expect(knownLocations.containsKey(id), isTrue);
expect(knownLocations, contains(id));
}
expect(totalCount, equals(27));
// The creation locations that were rebuilt the most were rebuilt 6 times
Expand All @@ -1701,7 +1716,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(event['startTime'], isInstanceOf<int>());
data = event['events'];
// No new locations were rebuilt.
expect(event.containsKey('newLocations'), isFalse);
expect(event, isNot(contains('newLocations')));

// There were two rebuilds: one for the ClockText element itself and one
// for its child.
Expand Down Expand Up @@ -1737,7 +1752,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(event['startTime'], isInstanceOf<int>());
data = event['events'];
// No new locations were rebuilt.
expect(event.containsKey('newLocations'), isFalse);
expect(event, isNot(contains('newLocations')));

expect(data.length, equals(4));
id = data[0];
Expand Down Expand Up @@ -1771,7 +1786,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(event['startTime'], isInstanceOf<int>());
data = event['events'];
// No new locations were rebuilt.
expect(event.containsKey('newLocations'), isFalse);
expect(event, isNot(contains('newLocations')));

expect(data.length, equals(4));
id = data[0];
Expand All @@ -1795,13 +1810,13 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
count = data[3];
expect(count, equals(1));
// Verify the rebuild location is new.
expect(knownLocations.containsKey(id), isFalse);
expect(knownLocations, isNot(contains(id)));
addToKnownLocationsMap(
knownLocations: knownLocations,
newLocations: newLocations,
);
// Verify the rebuild location was included in the newLocations data.
expect(knownLocations.containsKey(id), isTrue);
expect(knownLocations, contains(id));

// Turn off rebuild counts.
expect(
Expand Down Expand Up @@ -1884,7 +1899,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final int count = data[i + 1];
totalCount += count;
maxCount = max(maxCount, count);
expect(knownLocations.containsKey(id), isTrue);
expect(knownLocations, contains(id));
}
expect(totalCount, equals(34));
// The creation locations that were rebuilt the most were rebuilt 6 times
Expand All @@ -1903,7 +1918,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(event['startTime'], isInstanceOf<int>());
data = event['events'];
// No new locations were rebuilt.
expect(event.containsKey('newLocations'), isFalse);
expect(event, isNot(contains('newLocations')));

// Triggering a a rebuild of one widget in this app causes the whole app
// to repaint.
Expand Down Expand Up @@ -2657,7 +2672,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
}
}
visitChildren(detailedChildren);
expect(appBars.single.containsKey('children'), isFalse);
expect(appBars.single, isNot(contains('children')));
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // Test requires --track-widget-creation flag.
}
}
Expand Down