Unverified Commit 13f18d5a authored by Kenzie Schmoll's avatar Kenzie Schmoll Committed by GitHub

Make inspector details subtree depth configurable. (#39085)

* Make inspector details subtree depth configurable.
parent 17ebdcf9
...@@ -1089,9 +1089,19 @@ mixin WidgetInspectorService { ...@@ -1089,9 +1089,19 @@ mixin WidgetInspectorService {
name: 'getRootWidgetSummaryTree', name: 'getRootWidgetSummaryTree',
callback: _getRootWidgetSummaryTree, callback: _getRootWidgetSummaryTree,
); );
_registerServiceExtensionWithArg( registerServiceExtension(
name: 'getDetailsSubtree', 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( _registerServiceExtensionWithArg(
name: 'getSelectedRenderObject', name: 'getSelectedRenderObject',
...@@ -1603,15 +1613,27 @@ mixin WidgetInspectorService { ...@@ -1603,15 +1613,27 @@ mixin WidgetInspectorService {
/// [DiagnosticsNode] object that `diagnosticsNodeId` references providing /// [DiagnosticsNode] object that `diagnosticsNodeId` references providing
/// information needed for the details subtree view. /// 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: /// See also:
/// ///
/// * [getChildrenDetailsSubtree], a method to get children of a node /// * [getChildrenDetailsSubtree], a method to get children of a node
/// in the details subtree. /// in the details subtree.
String getDetailsSubtree(String id, String groupName) { String getDetailsSubtree(
return _safeJsonEncode(_getDetailsSubtree( id, groupName)); String id,
String groupName, {
int subtreeDepth = 2,
}) {
return _safeJsonEncode(_getDetailsSubtree( id, groupName, subtreeDepth));
} }
Map<String, Object> _getDetailsSubtree(String id, String groupName) { Map<String, Object> _getDetailsSubtree(
String id,
String groupName,
int subtreeDepth,
) {
final DiagnosticsNode root = toObject(id); final DiagnosticsNode root = toObject(id);
if (root == null) { if (root == null) {
return null; return null;
...@@ -1621,7 +1643,7 @@ mixin WidgetInspectorService { ...@@ -1621,7 +1643,7 @@ mixin WidgetInspectorService {
_SerializationDelegate( _SerializationDelegate(
groupName: groupName, groupName: groupName,
summaryTree: false, summaryTree: false,
subtreeDepth: 2, // TODO(jacobr): make subtreeDepth configurable. subtreeDepth: subtreeDepth,
includeProperties: true, includeProperties: true,
service: this, service: this,
), ),
......
...@@ -253,14 +253,14 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -253,14 +253,14 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
} }
Future<Object> testExtension(String name, Map<String, String> arguments) async { Future<Object> testExtension(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 // Encode and decode to JSON to match behavior using a real service
// extension where only JSON is allowed. // extension where only JSON is allowed.
return json.decode(json.encode(await extensions[name](arguments)))['result']; return json.decode(json.encode(await extensions[name](arguments)))['result'];
} }
Future<String> testBoolExtension(String name, Map<String, String> arguments) async { 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 // Encode and decode to JSON to match behavior using a real service
// extension where only JSON is allowed. // extension where only JSON is allowed.
return json.decode(json.encode(await extensions[name](arguments)))['enabled']; return json.decode(json.encode(await extensions[name](arguments)))['enabled'];
...@@ -371,7 +371,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -371,7 +371,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final InspectorSelection selection = getInspectorState().selection; final InspectorSelection selection = getInspectorState().selection;
expect(paragraphText(selection.current), equals('TOP')); expect(paragraphText(selection.current), equals('TOP'));
final RenderObject topButton = find.byKey(topButtonKey).evaluate().first.renderObject; 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')); await tester.tap(find.text('TOP'));
expect(log, equals(<String>['top'])); expect(log, equals(<String>['top']));
...@@ -906,7 +906,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -906,7 +906,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final List<DiagnosticsNode> children = node.getChildren(); final List<DiagnosticsNode> children = node.getChildren();
expect(children.length, 1); expect(children.length, 1);
final ErrorDescription child = children[0]; final ErrorDescription child = children[0];
expect(child.valueToString().contains(Uri.parse(pubRootTest).path), true); expect(child.valueToString(), contains(Uri.parse(pubRootTest).path));
} else { } else {
expect(nodes[2].runtimeType, ErrorDescription); expect(nodes[2].runtimeType, ErrorDescription);
final ErrorDescription node = nodes[2]; final ErrorDescription node = nodes[2];
...@@ -967,7 +967,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -967,7 +967,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final List<DiagnosticsNode> children = node.getChildren(); final List<DiagnosticsNode> children = node.getChildren();
expect(children.length, 1); expect(children.length, 1);
final ErrorDescription child = children[0]; final ErrorDescription child = children[0];
expect(child.valueToString().contains(Uri.parse(pubRootTest).path), true); expect(child.valueToString(), contains(Uri.parse(pubRootTest).path));
} else { } else {
expect(nodes[1].runtimeType, ErrorDescription); expect(nodes[1].runtimeType, ErrorDescription);
final ErrorDescription node = nodes[1]; final ErrorDescription node = nodes[1];
...@@ -1264,7 +1264,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1264,7 +1264,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
for (Map<String, Object> propertyJson in propertiesJson) { for (Map<String, Object> propertyJson in propertiesJson) {
final Object property = service.toObject(propertyJson['objectId']); final Object property = service.toObject(propertyJson['objectId']);
expect(property, isInstanceOf<DiagnosticsNode>()); expect(property, isInstanceOf<DiagnosticsNode>());
expect(expectedProperties.contains(property), isTrue); expect(expectedProperties, contains(property));
} }
} }
}); });
...@@ -1297,12 +1297,27 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1297,12 +1297,27 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(service.toObject(childJson['valueId']), equals(children[i].value)); expect(service.toObject(childJson['valueId']), equals(children[i].value));
expect(service.toObject(childJson['objectId']), isInstanceOf<DiagnosticsNode>()); expect(service.toObject(childJson['objectId']), isInstanceOf<DiagnosticsNode>());
final List<Object> propertiesJson = childJson['properties']; 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 DiagnosticsNode diagnosticsNode = service.toObject(childJson['objectId']);
final List<DiagnosticsNode> expectedProperties = diagnosticsNode.getProperties(); final List<DiagnosticsNode> expectedProperties = diagnosticsNode.getProperties();
for (Map<String, Object> propertyJson in propertiesJson) { for (Map<String, Object> propertyJson in propertiesJson) {
final Object property = service.toObject(propertyJson['objectId']); final Object property = service.toObject(propertyJson['objectId']);
expect(property, isInstanceOf<DiagnosticsNode>()); 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'));
} }
} }
}); });
...@@ -1319,15 +1334,15 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1319,15 +1334,15 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final String id = service.toId(diagnostic, group); final String id = service.toId(diagnostic, group);
final Map<String, Object> subtreeJson = await service.testExtension('getDetailsSubtree', <String, String>{'arg': id, 'objectGroup': group}); final Map<String, Object> subtreeJson = await service.testExtension('getDetailsSubtree', <String, String>{'arg': id, 'objectGroup': group});
expect(subtreeJson['objectId'], equals(id)); expect(subtreeJson['objectId'], equals(id));
expect(subtreeJson.containsKey('children'), isTrue); expect(subtreeJson, contains('children'));
final List<Object> propertiesJson = subtreeJson['properties']; final List<Object> propertiesJson = subtreeJson['properties'];
expect(propertiesJson.length, equals(1)); expect(propertiesJson.length, equals(1));
final Map<String, Object> relatedProperty = propertiesJson.first; final Map<String, Object> relatedProperty = propertiesJson.first;
expect(relatedProperty['name'], equals('related')); expect(relatedProperty['name'], equals('related'));
expect(relatedProperty['description'], equals('CyclicDiagnostic-b')); expect(relatedProperty['description'], equals('CyclicDiagnostic-b'));
expect(relatedProperty.containsKey('isDiagnosticableValue'), isTrue); expect(relatedProperty, contains('isDiagnosticableValue'));
expect(relatedProperty.containsKey('children'), isFalse); expect(relatedProperty, isNot(contains('children')));
expect(relatedProperty.containsKey('properties'), isTrue); expect(relatedProperty, contains('properties'));
final List<Object> relatedWidgetProperties = relatedProperty['properties']; final List<Object> relatedWidgetProperties = relatedProperty['properties'];
expect(relatedWidgetProperties.length, equals(1)); expect(relatedWidgetProperties.length, equals(1));
final Map<String, Object> nestedRelatedProperty = relatedWidgetProperties.first; final Map<String, Object> nestedRelatedProperty = relatedWidgetProperties.first;
...@@ -1336,9 +1351,9 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1336,9 +1351,9 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
// which we already included as the root node as that would indicate a // which we already included as the root node as that would indicate a
// cycle. // cycle.
expect(nestedRelatedProperty['description'], equals('CyclicDiagnostic-a')); expect(nestedRelatedProperty['description'], equals('CyclicDiagnostic-a'));
expect(nestedRelatedProperty.containsKey('isDiagnosticableValue'), isTrue); expect(nestedRelatedProperty, contains('isDiagnosticableValue'));
expect(nestedRelatedProperty.containsKey('properties'), isFalse); expect(nestedRelatedProperty, isNot(contains('properties')));
expect(nestedRelatedProperty.containsKey('children'), isFalse); expect(nestedRelatedProperty, isNot(contains('children')));
}); });
testWidgets('ext.flutter.inspector.getRootWidgetSummaryTree', (WidgetTester tester) async { testWidgets('ext.flutter.inspector.getRootWidgetSummaryTree', (WidgetTester tester) async {
...@@ -1682,7 +1697,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1682,7 +1697,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final int count = data[i + 1]; final int count = data[i + 1];
totalCount += count; totalCount += count;
maxCount = max(maxCount, count); maxCount = max(maxCount, count);
expect(knownLocations.containsKey(id), isTrue); expect(knownLocations, contains(id));
} }
expect(totalCount, equals(27)); expect(totalCount, equals(27));
// The creation locations that were rebuilt the most were rebuilt 6 times // The creation locations that were rebuilt the most were rebuilt 6 times
...@@ -1701,7 +1716,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1701,7 +1716,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(event['startTime'], isInstanceOf<int>()); expect(event['startTime'], isInstanceOf<int>());
data = event['events']; data = event['events'];
// No new locations were rebuilt. // 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 // There were two rebuilds: one for the ClockText element itself and one
// for its child. // for its child.
...@@ -1737,7 +1752,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1737,7 +1752,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(event['startTime'], isInstanceOf<int>()); expect(event['startTime'], isInstanceOf<int>());
data = event['events']; data = event['events'];
// No new locations were rebuilt. // No new locations were rebuilt.
expect(event.containsKey('newLocations'), isFalse); expect(event, isNot(contains('newLocations')));
expect(data.length, equals(4)); expect(data.length, equals(4));
id = data[0]; id = data[0];
...@@ -1771,7 +1786,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1771,7 +1786,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(event['startTime'], isInstanceOf<int>()); expect(event['startTime'], isInstanceOf<int>());
data = event['events']; data = event['events'];
// No new locations were rebuilt. // No new locations were rebuilt.
expect(event.containsKey('newLocations'), isFalse); expect(event, isNot(contains('newLocations')));
expect(data.length, equals(4)); expect(data.length, equals(4));
id = data[0]; id = data[0];
...@@ -1795,13 +1810,13 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1795,13 +1810,13 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
count = data[3]; count = data[3];
expect(count, equals(1)); expect(count, equals(1));
// Verify the rebuild location is new. // Verify the rebuild location is new.
expect(knownLocations.containsKey(id), isFalse); expect(knownLocations, isNot(contains(id)));
addToKnownLocationsMap( addToKnownLocationsMap(
knownLocations: knownLocations, knownLocations: knownLocations,
newLocations: newLocations, newLocations: newLocations,
); );
// Verify the rebuild location was included in the newLocations data. // Verify the rebuild location was included in the newLocations data.
expect(knownLocations.containsKey(id), isTrue); expect(knownLocations, contains(id));
// Turn off rebuild counts. // Turn off rebuild counts.
expect( expect(
...@@ -1884,7 +1899,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1884,7 +1899,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
final int count = data[i + 1]; final int count = data[i + 1];
totalCount += count; totalCount += count;
maxCount = max(maxCount, count); maxCount = max(maxCount, count);
expect(knownLocations.containsKey(id), isTrue); expect(knownLocations, contains(id));
} }
expect(totalCount, equals(34)); expect(totalCount, equals(34));
// The creation locations that were rebuilt the most were rebuilt 6 times // The creation locations that were rebuilt the most were rebuilt 6 times
...@@ -1903,7 +1918,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -1903,7 +1918,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
expect(event['startTime'], isInstanceOf<int>()); expect(event['startTime'], isInstanceOf<int>());
data = event['events']; data = event['events'];
// No new locations were rebuilt. // 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 // Triggering a a rebuild of one widget in this app causes the whole app
// to repaint. // to repaint.
...@@ -2657,7 +2672,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService { ...@@ -2657,7 +2672,7 @@ class TestWidgetInspectorService extends Object with WidgetInspectorService {
} }
} }
visitChildren(detailedChildren); visitChildren(detailedChildren);
expect(appBars.single.containsKey('children'), isFalse); expect(appBars.single, isNot(contains('children')));
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // Test requires --track-widget-creation flag. }, skip: !WidgetInspectorService.instance.isWidgetCreationTracked()); // Test requires --track-widget-creation flag.
} }
} }
......
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