Unverified Commit b81165d2 authored by Devon Carew's avatar Devon Carew Committed by GitHub

refactor the widget rebuild service protocol event format (#86896)

refactor the widget rebuild service protocol event format
parent 3823e015
......@@ -2122,6 +2122,7 @@ class _ElementLocationStatsTracker {
'events': events,
};
// Encode the new locations using the older encoding.
if (newLocations.isNotEmpty) {
// Add all newly used location ids to the JSON.
final Map<String, List<int>> locationsJson = <String, List<int>>{};
......@@ -2136,21 +2137,26 @@ class _ElementLocationStatsTracker {
json['newLocations'] = locationsJson;
}
// Add in a data structure for the location names.
// Encode the new locations using the newer encoding (as of v2.4.0).
if (newLocations.isNotEmpty) {
final Map<String, Map<int, String>> namesJson = <String, Map<int, String>>{};
final Map<String, Map<String, List<Object?>>> fileLocationsMap = <String, Map<String, List<Object?>>>{};
for (final _LocationCount entry in newLocations) {
final _Location location = entry.location;
final Map<int, String> jsonForFile = namesJson.putIfAbsent(
location.file,
() => <int, String>{},
final Map<String, List<Object?>> locations = fileLocationsMap.putIfAbsent(
location.file, () => <String, List<Object?>>{
'ids': <int>[],
'lines': <int>[],
'columns': <int>[],
'names': <String?>[],
},
);
final String? name = location.name;
if (name != null) {
jsonForFile[entry.id] = name;
}
locations['ids']!.add(entry.id);
locations['lines']!.add(location.line);
locations['columns']!.add(location.column);
locations['names']!.add(location.name);
}
json['newLocationsNames'] = namesJson;
json['locations'] = fileLocationsMap;
}
resetCounts();
......
......@@ -135,17 +135,17 @@ class CyclicDiagnostic extends DiagnosticableTree {
class _CreationLocation {
_CreationLocation({
required this.id,
required this.file,
required this.line,
required this.column,
required this.id,
this.name,
required this.name,
});
final int id;
final String file;
final int line;
final int column;
final int id;
String? name;
}
......@@ -1887,6 +1887,13 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(await service.testExtension('getSelectedWidget', <String, String>{'objectGroup': 'my-group'}), contains('createdByLocalProject'));
}, skip: !WidgetInspectorService.instance.isWidgetCreationTracked() || isBrowser); // Test requires --track-widget-creation flag.
Map<Object, Object?> removeLastEvent(List<Map<Object, Object?>> events) {
final Map<Object, Object?> event = events.removeLast();
// Verify that the event is json encodable.
json.encode(event);
return event;
}
testWidgets('ext.flutter.inspector.trackRebuildDirtyWidgets', (WidgetTester tester) async {
service.rebuildCount = 0;
......@@ -1922,7 +1929,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
await tester.pump();
expect(rebuildEvents.length, equals(1));
Map<Object, Object?> event = rebuildEvents.removeLast();
Map<Object, Object?> event = removeLastEvent(rebuildEvents);
expect(event['startTime'], isA<int>());
List<int> data = event['events']! as List<int>;
expect(data.length, equals(14));
......@@ -1931,20 +1938,22 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(newLocations, isNotNull);
expect(newLocations.length, equals(1));
expect(newLocations.keys.first, equals(file));
final Map<String, Map<int, String>> newLocationsNames = event['newLocationsNames']! as Map<String, Map<int, String>>;
expect(newLocationsNames, isNotNull);
expect(newLocationsNames.length, equals(1));
expect(newLocationsNames.keys.first, equals(file));
Map<String, Map<String, List<Object?>>> fileLocationsMap = event['locations']! as Map<String, Map<String, List<Object?>>>;
expect(fileLocationsMap, isNotNull);
expect(fileLocationsMap.length, equals(1));
expect(fileLocationsMap.keys.first, equals(file));
final List<int> locationsForFile = newLocations[file]!;
expect(locationsForFile.length, equals(21));
final int numLocationEntries = locationsForFile.length ~/ 3;
expect(numLocationEntries, equals(numDataEntries));
final Map<String, List<Object?>> locations = fileLocationsMap[file]!;
expect(locations.length, equals(4));
expect(locations['ids']!.length, equals(7));
final Map<int, _CreationLocation> knownLocations = <int, _CreationLocation>{};
_addToKnownLocationsMap(
knownLocations: knownLocations,
newLocations: newLocations,
newLocationsNames: newLocationsNames,
newLocations: fileLocationsMap,
);
int totalCount = 0;
int maxCount = 0;
......@@ -1968,12 +1977,12 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
state.updateTime(); // Triggers a rebuild.
await tester.pump();
expect(rebuildEvents.length, equals(1));
event = rebuildEvents.removeLast();
event = removeLastEvent(rebuildEvents);
expect(event['startTime'], isA<int>());
data = event['events']! as List<int>;
// No new locations were rebuilt.
expect(event, isNot(contains('newLocations')));
expect(event, isNot(contains('newLocationsNames')));
expect(event, isNot(contains('locations')));
// There were two rebuilds: one for the ClockText element itself and one
// for its child.
......@@ -2007,12 +2016,12 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
await tester.pump();
expect(rebuildEvents.length, equals(1));
event = rebuildEvents.removeLast();
event = removeLastEvent(rebuildEvents);
expect(event['startTime'], isA<int>());
data = event['events']! as List<int>;
// No new locations were rebuilt.
expect(event, isNot(contains('newLocations')));
expect(event, isNot(contains('newLocationsNames')));
expect(event, isNot(contains('locations')));
expect(data.length, equals(4));
id = data[0];
......@@ -2044,12 +2053,12 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
await tester.pump();
expect(rebuildEvents.length, equals(1));
event = rebuildEvents.removeLast();
event = removeLastEvent(rebuildEvents);
expect(event['startTime'], isA<int>());
data = event['events']! as List<int>;
// No new locations were rebuilt.
expect(event, isNot(contains('newLocations')));
expect(event, isNot(contains('newLocationsNames')));
expect(event, isNot(contains('locations')));
expect(data.length, equals(4));
id = data[0];
......@@ -2062,10 +2071,11 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
state.stopClock();
await tester.pump();
expect(rebuildEvents.length, equals(1));
event = rebuildEvents.removeLast();
event = removeLastEvent(rebuildEvents);
expect(event['startTime'], isA<int>());
data = event['events']! as List<int>;
newLocations = event['newLocations']! as Map<String, List<int>>;
fileLocationsMap = event['locations']! as Map<String, Map<String, List<Object?>>>;
expect(data.length, equals(4));
// The second pair in data is the previously unseen rebuild location.
......@@ -2076,8 +2086,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(knownLocations, isNot(contains(id)));
_addToKnownLocationsMap(
knownLocations: knownLocations,
newLocations: newLocations,
newLocationsNames: newLocationsNames,
newLocations: fileLocationsMap,
);
// Verify the rebuild location was included in the newLocations data.
expect(knownLocations, contains(id));
......@@ -2133,7 +2142,7 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
await tester.pump();
expect(repaintEvents.length, equals(1));
Map<Object, Object?> event = repaintEvents.removeLast();
Map<Object, Object?> event = removeLastEvent(repaintEvents);
expect(event['startTime'], isA<int>());
List<int> data = event['events']! as List<int>;
expect(data.length, equals(18));
......@@ -2142,21 +2151,22 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
expect(newLocations, isNotNull);
expect(newLocations.length, equals(1));
expect(newLocations.keys.first, equals(file));
final Map<String, Map<int, String>> newLocationsNames = event['newLocationsNames']! as Map<String, Map<int, String>>;
expect(newLocationsNames, isNotNull);
expect(newLocationsNames.length, equals(1));
expect(newLocationsNames.keys.first, equals(file));
final Map<String, Map<String, List<Object?>>> fileLocationsMap = event['locations']! as Map<String, Map<String, List<Object?>>>;
expect(fileLocationsMap, isNotNull);
expect(fileLocationsMap.length, equals(1));
expect(fileLocationsMap.keys.first, equals(file));
final List<int> locationsForFile = newLocations[file]!;
expect(locationsForFile.length, equals(27));
final int numLocationEntries = locationsForFile.length ~/ 3;
expect(numLocationEntries, equals(numDataEntries));
final Map<String, List<Object?>> locations = fileLocationsMap[file]!;
expect(locations.length, equals(4));
expect(locations['ids']!.length, equals(9));
final Map<int, _CreationLocation> knownLocations =
<int, _CreationLocation>{};
final Map<int, _CreationLocation> knownLocations = <int, _CreationLocation>{};
_addToKnownLocationsMap(
knownLocations: knownLocations,
newLocations: newLocations,
newLocationsNames: newLocationsNames,
newLocations: fileLocationsMap,
);
int totalCount = 0;
int maxCount = 0;
......@@ -2180,12 +2190,12 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
state.updateTime(); // Triggers a rebuild.
await tester.pump();
expect(repaintEvents.length, equals(1));
event = repaintEvents.removeLast();
event = removeLastEvent(repaintEvents);
expect(event['startTime'], isA<int>());
data = event['events']! as List<int>;
// No new locations were rebuilt.
expect(event, isNot(contains('newLocations')));
expect(event, isNot(contains('newLocationsNames')));
expect(event, isNot(contains('locations')));
// Triggering a rebuild of one widget in this app causes the whole app
// to repaint.
......@@ -3040,23 +3050,23 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
void _addToKnownLocationsMap({
required Map<int, _CreationLocation> knownLocations,
required Map<String, List<int>> newLocations,
required Map<String, Map<int, String>> newLocationsNames,
required Map<String, Map<String, List<Object?>>> newLocations,
}) {
newLocations.forEach((String file, List<int> entries) {
assert(entries.length % 3 == 0);
for (int i = 0; i < entries.length; i += 3) {
final int id = entries[i];
final int line = entries[i + 1];
final int column = entries[i + 2];
assert(!knownLocations.containsKey(id));
knownLocations[id] =
_CreationLocation(file: file, line: line, column: column, id: id);
newLocations.forEach((String file, Map<String, List<Object?>> entries) {
final List<int> ids = entries['ids']!.cast<int>();
final List<int> lines = entries['lines']!.cast<int>();
final List<int> columns = entries['columns']!.cast<int>();
final List<String> names = entries['names']!.cast<String>();
for (int i = 0; i < ids.length; i++) {
final int id = ids[i];
knownLocations[id] = _CreationLocation(
id: id,
file: file,
line: lines[i],
column: columns[i],
name: names[i],
);
}
});
newLocationsNames.forEach((String file, Map<int, String> namesInfo) {
namesInfo.forEach((int id, String name) {
knownLocations[id]!.name = name;
});
});
}
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