Do not send count and offset params when requesting the entire object (#5356)
diff --git a/packages/devtools_app/lib/src/shared/diagnostics/dart_object_node.dart b/packages/devtools_app/lib/src/shared/diagnostics/dart_object_node.dart index 50955c6..c05ee47 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/dart_object_node.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/dart_object_node.dart
@@ -241,13 +241,9 @@ final value = this.value; if (value is InstanceRef) { - if (value.kind != null && - (isList(value) || - value.kind == InstanceKind.kMap || - value.kind == InstanceKind.kRecord || - isSet)) { - return value.length ?? 0; - } + final instanceLength = value.length; + if (instanceLength == null) return 0; + return instanceLength - offset; } return 0; @@ -255,6 +251,20 @@ int? _childCount; + bool get isPartialObject { + final value = this.value; + // Only instance kinds can be partial: + if (value is InstanceRef) { + // Only instance kinds with a length property can be partial. See: + // https://api.flutter.dev/flutter/vm_service/Instance/length.html + final instanceLength = value.length; + if (instanceLength == null) return false; + return offset != 0 || childCount < instanceLength; + } + + return false; + } + // TODO(elliette): Can remove this workaround once DWDS correctly returns // InstanceKind.kSet for the kind of `Sets`. See: // https://github.com/dart-lang/webdev/issues/2001
diff --git a/packages/devtools_app/lib/src/shared/diagnostics/helpers.dart b/packages/devtools_app/lib/src/shared/diagnostics/helpers.dart index 3810983..f2de0e7 100644 --- a/packages/devtools_app/lib/src/shared/diagnostics/helpers.dart +++ b/packages/devtools_app/lib/src/shared/diagnostics/helpers.dart
@@ -16,11 +16,22 @@ required ObjRef value, DartObjectNode? variable, }) async { + // Don't include the offset and count parameters if we are not fetching a + // partial object. Offset and count parameters are only necessary to request + // subranges of the following instance kinds: + // https://api.flutter.dev/flutter/vm_service/VmServiceInterface/getObject.html + if (variable == null || !variable.isPartialObject) { + return await serviceManager.service!.getObject( + isolateRef!.id!, + value.id!, + ); + } + return await serviceManager.service!.getObject( isolateRef!.id!, value.id!, - offset: variable?.offset, - count: variable?.childCount, + offset: variable.offset, + count: variable.childCount, ); }
diff --git a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md index 9ae7f4b..99e94e3 100644 --- a/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md +++ b/packages/devtools_app/release_notes/NEXT_RELEASE_NOTES.md
@@ -23,7 +23,7 @@ TODO: Remove this section if there are not any general updates. ## Debugger updates -TODO: Remove this section if there are not any general updates. +* Fix a bug where variable inspection for instances sometimes showed no children. - [#5356](https://github.com/flutter/devtools/pull/5356) ## Network profiler updates TODO: Remove this section if there are not any general updates.
diff --git a/packages/devtools_app/test/debugger/association_variable_test.dart b/packages/devtools_app/test/debugger/association_variable_test.dart index 790f16d..6ae05c0 100644 --- a/packages/devtools_app/test/debugger/association_variable_test.dart +++ b/packages/devtools_app/test/debugger/association_variable_test.dart
@@ -65,7 +65,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 2)) + when(manager.service!.getObject(isolateId, objectId)) .thenAnswer((_) async { return instance; }); @@ -113,7 +113,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 2)) + when(manager.service!.getObject(isolateId, objectId)) .thenAnswer((_) async { return instance; }); @@ -161,7 +161,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 2)) + when(manager.service!.getObject(isolateId, objectId)) .thenAnswer((_) async { return instance; });
diff --git a/packages/devtools_app/test/debugger/debugger_screen_variables_test.dart b/packages/devtools_app/test/debugger/debugger_screen_variables_test.dart index 75fec88..67c7f41 100644 --- a/packages/devtools_app/test/debugger/debugger_screen_variables_test.dart +++ b/packages/devtools_app/test/debugger/debugger_screen_variables_test.dart
@@ -7,7 +7,6 @@ import 'package:devtools_app/src/screens/debugger/debugger_screen.dart'; import 'package:devtools_app/src/service/service_manager.dart'; import 'package:devtools_app/src/shared/config_specific/ide_theme/ide_theme.dart'; -import 'package:devtools_app/src/shared/diagnostics/dart_object_node.dart'; import 'package:devtools_app/src/shared/diagnostics/tree_builder.dart'; import 'package:devtools_app/src/shared/globals.dart'; import 'package:devtools_app/src/shared/notifications.dart'; @@ -16,7 +15,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:mockito/mockito.dart'; -import 'package:vm_service/vm_service.dart'; + +import '../test_infra/utils/variable_utils.dart'; void main() { late FakeServiceManager fakeServiceManager; @@ -45,8 +45,8 @@ .thenReturn(ValueNotifier<int>(0)); debuggerController = createMockDebuggerControllerWithDefaults(); - _resetRef(); - _resetRoot(); + resetRef(); + resetRoot(); }); Future<void> pumpDebuggerScreen( @@ -61,16 +61,61 @@ ); } + Future<void> verifyGroupings( + WidgetTester tester, { + required Finder parentFinder, + }) async { + final group0To9999Finder = find.selectableTextContaining('[0 - 9999]'); + final group10000To19999Finder = + find.selectableTextContaining('[10000 - 19999]'); + final group230000To239999Finder = + find.selectableTextContaining('[230000 - 239999]'); + final group240000To243620Finder = + find.selectableTextContaining('[240000 - 243620]'); + + final group0To99Finder = find.selectableTextContaining('[0 - 99]'); + final group100To199Finder = find.selectableTextContaining('[100 - 199]'); + final group200To299Finder = find.selectableTextContaining('[200 - 299]'); + + // Initially the parent variable is not expanded. + expect(parentFinder, findsOneWidget); + expect(group0To9999Finder, findsNothing); + expect(group10000To19999Finder, findsNothing); + expect(group230000To239999Finder, findsNothing); + expect(group240000To243620Finder, findsNothing); + + // Expand the parent variable. + await tester.tap(parentFinder); + await tester.pump(); + expect(group0To9999Finder, findsOneWidget); + expect(group10000To19999Finder, findsOneWidget); + expect(group230000To239999Finder, findsOneWidget); + expect(group240000To243620Finder, findsOneWidget); + + // Initially group [0 - 9999] is not expanded. + expect(group0To99Finder, findsNothing); + expect(group100To199Finder, findsNothing); + expect(group200To299Finder, findsNothing); + + // Expand group [0 - 9999]. + await tester.tap(group0To9999Finder); + await tester.pump(); + expect(group0To99Finder, findsOneWidget); + expect(group100To199Finder, findsOneWidget); + expect(group200To299Finder, findsOneWidget); + } + testWidgetsWithWindowSize( 'Variables shows items', windowSize, (WidgetTester tester) async { fakeServiceManager.appState.setVariables( [ - _buildListVariable(), - _buildMapVariable(), - _buildStringVariable('test str'), - _buildBooleanVariable(true), + buildListVariable(), + buildMapVariable(), + buildStringVariable('test str'), + buildBooleanVariable(true), + buildSetVariable(), ], ); await pumpDebuggerScreen(tester, debuggerController); @@ -120,6 +165,20 @@ await tester.pump(); expect(mapElement1Finder, findsOneWidget); expect(mapElement2Finder, findsOneWidget); + + // Expect a tooltip for the set instance. + final setFinder = find.selectableText('Root 5: Set (2 items)'); + expect(setFinder, findsOneWidget); + + // Initially set is not expanded. + expect(find.selectableTextContaining('set value 0'), findsNothing); + expect(find.selectableTextContaining('set value 1'), findsNothing); + + // Expand set + await tester.tap(setFinder); + await tester.pump(); + expect(find.selectableTextContaining('set value 0'), findsOneWidget); + expect(find.selectableTextContaining('set value 1'), findsOneWidget); }, ); @@ -127,7 +186,7 @@ 'Children in large list variables are grouped', windowSize, (WidgetTester tester) async { - final list = _buildParentListVariable(length: 380250); + final list = buildParentListVariable(length: 243621); await buildVariablesTree(list); final appState = serviceManager.appState; @@ -135,48 +194,8 @@ await pumpDebuggerScreen(tester, debuggerController); - final listFinder = find.selectableText('Root 1: List (380,250 items)'); - final group0To9999Finder = find.selectableTextContaining('[0 - 9999]'); - final group10000To19999Finder = - find.selectableTextContaining('[10000 - 19999]'); - final group370000To379999Finder = - find.selectableTextContaining('[370000 - 379999]'); - final group380000To380249Finder = - find.selectableTextContaining('[380000 - 380249]'); - - final group370000To370099Finder = - find.selectableTextContaining('[370000 - 370099]'); - final group370100To370199Finder = - find.selectableTextContaining('[370100 - 370199]'); - final group370200To370299Finder = - find.selectableTextContaining('[370200 - 370299]'); - - // Initially list is not expanded. - expect(listFinder, findsOneWidget); - expect(group0To9999Finder, findsNothing); - expect(group10000To19999Finder, findsNothing); - expect(group370000To379999Finder, findsNothing); - expect(group380000To380249Finder, findsNothing); - - // Expand list. - await tester.tap(listFinder); - await tester.pump(); - expect(group0To9999Finder, findsOneWidget); - expect(group10000To19999Finder, findsOneWidget); - expect(group370000To379999Finder, findsOneWidget); - expect(group380000To380249Finder, findsOneWidget); - - // Initially group [370000 - 379999] is not expanded. - expect(group370000To370099Finder, findsNothing); - expect(group370100To370199Finder, findsNothing); - expect(group370200To370299Finder, findsNothing); - - // Expand group [370000 - 379999]. - await tester.tap(group370000To379999Finder); - await tester.pump(); - expect(group370000To370099Finder, findsOneWidget); - expect(group370100To370199Finder, findsOneWidget); - expect(group370200To370299Finder, findsOneWidget); + final listFinder = find.selectableText('Root 1: List (243,621 items)'); + await verifyGroupings(tester, parentFinder: listFinder); }, ); @@ -184,7 +203,7 @@ 'Children in large map variables are grouped', windowSize, (WidgetTester tester) async { - final map = _buildParentMapVariable(length: 243621); + final map = buildParentMapVariable(length: 243621); await buildVariablesTree(map); final appState = serviceManager.appState; @@ -192,214 +211,25 @@ await pumpDebuggerScreen(tester, debuggerController); - final listFinder = find.selectableText('Root 1: Map (243,621 items)'); - final group0To9999Finder = find.selectableTextContaining('[0 - 9999]'); - final group10000To19999Finder = - find.selectableTextContaining('[10000 - 19999]'); - final group230000To239999Finder = - find.selectableTextContaining('[230000 - 239999]'); - final group240000To243620Finder = - find.selectableTextContaining('[240000 - 243620]'); - - final group0To99Finder = find.selectableTextContaining('[0 - 99]'); - final group100To199Finder = find.selectableTextContaining('[100 - 199]'); - final group200To299Finder = find.selectableTextContaining('[200 - 299]'); - - // Initially map is not expanded. - expect(listFinder, findsOneWidget); - expect(group0To9999Finder, findsNothing); - expect(group10000To19999Finder, findsNothing); - expect(group230000To239999Finder, findsNothing); - expect(group240000To243620Finder, findsNothing); - - // Expand map. - await tester.tap(listFinder); - await tester.pump(); - expect(group0To9999Finder, findsOneWidget); - expect(group10000To19999Finder, findsOneWidget); - expect(group230000To239999Finder, findsOneWidget); - expect(group240000To243620Finder, findsOneWidget); - - // Initially group [0 - 9999] is not expanded. - expect(group0To99Finder, findsNothing); - expect(group100To199Finder, findsNothing); - expect(group200To299Finder, findsNothing); - - // Expand group [0 - 9999]. - await tester.tap(group0To9999Finder); - await tester.pump(); - expect(group0To99Finder, findsOneWidget); - expect(group100To199Finder, findsOneWidget); - expect(group200To299Finder, findsOneWidget); + final mapFinder = find.selectableText('Root 1: Map (243,621 items)'); + await verifyGroupings(tester, parentFinder: mapFinder); }, ); -} -final _libraryRef = LibraryRef( - name: 'some library', - uri: 'package:foo/foo.dart', - id: 'lib-id-1', -); + testWidgetsWithWindowSize( + 'Children in large set variables are grouped', + windowSize, + (WidgetTester tester) async { + final set = buildParentSetVariable(length: 243621); + await buildVariablesTree(set); -final _isolateRef = IsolateRef( - id: '433', - number: '1', - name: 'my-isolate', - isSystemIsolate: false, -); + final appState = serviceManager.appState; + appState.setVariables([set]); -int _refNumber = 0; + await pumpDebuggerScreen(tester, debuggerController); -String _incrementRef() { - _refNumber++; - return 'ref$_refNumber'; -} - -void _resetRef() { - _refNumber = 0; -} - -int _rootNumber = 0; - -String _incrementRoot() { - _rootNumber++; - return 'Root $_rootNumber'; -} - -void _resetRoot() { - _rootNumber = 0; -} - -DartObjectNode _buildParentListVariable({int length = 2}) { - return DartObjectNode.create( - BoundVariable( - name: _incrementRoot(), - value: InstanceRef( - id: _incrementRef(), - kind: InstanceKind.kList, - classRef: ClassRef( - name: '_GrowableList', - id: _incrementRef(), - library: _libraryRef, - ), - length: length, - ), - ), - _isolateRef, - ); -} - -DartObjectNode _buildListVariable({int length = 2}) { - final listVariable = _buildParentListVariable(length: length); - - for (int i = 0; i < length; i++) { - listVariable.addChild( - DartObjectNode.create( - BoundVariable( - name: '$i', - value: InstanceRef( - id: _incrementRef(), - kind: InstanceKind.kInt, - classRef: ClassRef( - name: 'Integer', - id: _incrementRef(), - library: _libraryRef, - ), - valueAsString: '$i', - valueAsStringIsTruncated: false, - ), - ), - _isolateRef, - ), - ); - } - - return listVariable; -} - -DartObjectNode _buildParentMapVariable({int length = 2}) { - return DartObjectNode.create( - BoundVariable( - name: _incrementRoot(), - value: InstanceRef( - id: _incrementRef(), - kind: InstanceKind.kMap, - classRef: ClassRef( - name: '_InternalLinkedHashmap', - id: _incrementRef(), - library: _libraryRef, - ), - length: length, - ), - ), - _isolateRef, - ); -} - -DartObjectNode _buildMapVariable({int length = 2}) { - final mapVariable = _buildParentMapVariable(length: length); - - for (int i = 0; i < length; i++) { - mapVariable.addChild( - DartObjectNode.create( - BoundVariable( - name: "['key${i + 1}']", - value: InstanceRef( - id: _incrementRef(), - kind: InstanceKind.kDouble, - classRef: ClassRef( - name: 'Double', - id: _incrementRef(), - library: _libraryRef, - ), - valueAsString: '${i + 1}.0', - valueAsStringIsTruncated: false, - ), - ), - _isolateRef, - ), - ); - } - - return mapVariable; -} - -DartObjectNode _buildStringVariable(String value) { - return DartObjectNode.create( - BoundVariable( - name: _incrementRoot(), - value: InstanceRef( - id: _incrementRef(), - kind: InstanceKind.kString, - classRef: ClassRef( - name: 'String', - id: _incrementRef(), - library: _libraryRef, - ), - valueAsString: value, - valueAsStringIsTruncated: true, - ), - ), - _isolateRef, - ); -} - -DartObjectNode _buildBooleanVariable(bool value) { - return DartObjectNode.create( - BoundVariable( - name: _incrementRoot(), - value: InstanceRef( - id: _incrementRef(), - kind: InstanceKind.kBool, - classRef: ClassRef( - name: 'Boolean', - id: _incrementRef(), - library: _libraryRef, - ), - valueAsString: '$value', - valueAsStringIsTruncated: false, - ), - ), - _isolateRef, + final setFinder = find.selectableText('Root 1: Set (243,621 items)'); + await verifyGroupings(tester, parentFinder: setFinder); + }, ); }
diff --git a/packages/devtools_app/test/debugger/records_variable_test.dart b/packages/devtools_app/test/debugger/records_variable_test.dart index 9497ef4..2e7954b 100644 --- a/packages/devtools_app/test/debugger/records_variable_test.dart +++ b/packages/devtools_app/test/debugger/records_variable_test.dart
@@ -82,8 +82,6 @@ manager.service!.getObject( isolateId, objectId, - offset: 0, - count: 3, ), ).thenAnswer((_) async { return instance;
diff --git a/packages/devtools_app/test/debugger/typed_data_variable_test.dart b/packages/devtools_app/test/debugger/typed_data_variable_test.dart index f64f7e0..b7c80f2 100644 --- a/packages/devtools_app/test/debugger/typed_data_variable_test.dart +++ b/packages/devtools_app/test/debugger/typed_data_variable_test.dart
@@ -51,8 +51,7 @@ isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -81,8 +80,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -111,8 +109,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -141,8 +138,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -174,7 +170,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) + when(manager.service!.getObject(isolateId, objectId)) .thenAnswer((_) async { return instance; }); @@ -206,8 +202,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -236,8 +231,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -266,8 +260,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -299,7 +292,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) + when(manager.service!.getObject(isolateId, objectId)) .thenAnswer((_) async { return instance; }); @@ -332,8 +325,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -362,8 +354,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -393,8 +384,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); await buildVariablesTree(variable); @@ -430,8 +420,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; }); @@ -465,8 +454,7 @@ ), isolateRef, ); - when(manager.service!.getObject(isolateId, objectId, offset: 0, count: 4)) - .thenAnswer((_) async { + when(manager.service!.getObject(isolateId, objectId)).thenAnswer((_) async { return instance; });
diff --git a/packages/devtools_app/test/shared/dart_object_node_test.dart b/packages/devtools_app/test/shared/dart_object_node_test.dart new file mode 100644 index 0000000..3aa661c --- /dev/null +++ b/packages/devtools_app/test/shared/dart_object_node_test.dart
@@ -0,0 +1,108 @@ +// Copyright 2023 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:flutter_test/flutter_test.dart'; + +import '../test_infra/utils/variable_utils.dart'; + +void main() { + setUp(() { + resetRef(); + resetRoot(); + }); + + group('map instances', () { + test('entire map', () { + final map = buildMapVariable(length: 3); + expect(map.childCount, equals(3)); + expect(map.isPartialObject, isFalse); + }); + + test('map grouping with offset', () { + final mapGrouping = buildMapGroupingVariable( + length: 10, + offset: 2, + count: 4, + ); + expect(mapGrouping.childCount, equals(4)); + expect(mapGrouping.isPartialObject, isTrue); + }); + + test('map grouping no offset', () { + final mapGrouping = buildMapGroupingVariable( + length: 10, + offset: 0, + count: 4, + ); + expect(mapGrouping.childCount, equals(4)); + expect(mapGrouping.isPartialObject, isTrue); + }); + }); + + group('list instances', () { + test('entire list', () { + final list = buildListVariable(length: 3); + expect(list.childCount, equals(3)); + expect(list.isPartialObject, isFalse); + }); + test('list grouping with offset', () { + final listGrouping = buildListGroupingVariable( + length: 10, + offset: 2, + count: 4, + ); + expect(listGrouping.childCount, equals(4)); + expect(listGrouping.isPartialObject, isTrue); + }); + test('list grouping no offset', () { + final listGrouping = buildListGroupingVariable( + length: 10, + offset: 0, + count: 4, + ); + expect(listGrouping.childCount, equals(4)); + expect(listGrouping.isPartialObject, isTrue); + }); + }); + + group('set instances', () { + test('entire set', () { + final set = buildSetVariable(length: 3); + expect(set.childCount, equals(3)); + expect(set.isPartialObject, isFalse); + }); + + test('set grouping with offset', () { + final setGrouping = buildSetGroupingVariable( + length: 10, + offset: 2, + count: 4, + ); + expect(setGrouping.childCount, equals(4)); + expect(setGrouping.isPartialObject, isTrue); + }); + + test('set grouping no offset', () { + final setGrouping = buildSetGroupingVariable( + length: 10, + offset: 0, + count: 4, + ); + expect(setGrouping.childCount, equals(4)); + expect(setGrouping.isPartialObject, isTrue); + }); + }); + + test('booleans', () { + final boolean = buildBooleanVariable(true); + expect(boolean.childCount, equals(0)); + expect(boolean.isPartialObject, isFalse); + }); + + test('strings', () { + final str = buildStringVariable('Hello there!'); + expect(str.childCount, equals(0)); + expect(str.isPartialObject, isFalse); + }); +}
diff --git a/packages/devtools_app/test/test_infra/utils/variable_utils.dart b/packages/devtools_app/test/test_infra/utils/variable_utils.dart new file mode 100644 index 0000000..35fb7d2 --- /dev/null +++ b/packages/devtools_app/test/test_infra/utils/variable_utils.dart
@@ -0,0 +1,274 @@ +// Copyright 2023 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +import 'package:devtools_app/src/shared/diagnostics/dart_object_node.dart'; +import 'package:devtools_app/src/shared/diagnostics/generic_instance_reference.dart'; + +import 'package:vm_service/vm_service.dart'; + +import '../../debugger/typed_data_variable_test.dart'; + +void resetRef() { + _refNumber = 0; +} + +void resetRoot() { + _rootNumber = 0; +} + +DartObjectNode buildParentListVariable({int length = 2}) { + return DartObjectNode.create( + BoundVariable( + name: _incrementRoot(), + value: _buildInstanceRefForList(length: length), + ), + _isolateRef, + ); +} + +DartObjectNode buildListVariable({int length = 2}) { + final listVariable = buildParentListVariable(length: length); + + for (int i = 0; i < length; i++) { + listVariable.addChild( + DartObjectNode.create( + BoundVariable( + name: '$i', + value: InstanceRef( + id: _incrementRef(), + kind: InstanceKind.kInt, + classRef: ClassRef( + name: 'Integer', + id: _incrementRef(), + library: _libraryRef, + ), + valueAsString: '$i', + valueAsStringIsTruncated: false, + ), + ), + _isolateRef, + ), + ); + } + + return listVariable; +} + +DartObjectNode buildListGroupingVariable({ + required int length, + required int offset, + required int count, +}) { + return DartObjectNode.grouping( + GenericInstanceRef( + isolateRef: isolateRef, + value: _buildInstanceRefForList(length: length), + ), + offset: offset, + count: count, + ); +} + +DartObjectNode buildParentMapVariable({int length = 2}) { + return DartObjectNode.create( + BoundVariable( + name: _incrementRoot(), + value: _buildInstanceRefForMap(length: length), + ), + _isolateRef, + ); +} + +DartObjectNode buildMapVariable({int length = 2}) { + final mapVariable = buildParentMapVariable(length: length); + + for (int i = 0; i < length; i++) { + mapVariable.addChild( + DartObjectNode.create( + BoundVariable( + name: "['key${i + 1}']", + value: InstanceRef( + id: _incrementRef(), + kind: InstanceKind.kDouble, + classRef: ClassRef( + name: 'Double', + id: _incrementRef(), + library: _libraryRef, + ), + valueAsString: '${i + 1}.0', + valueAsStringIsTruncated: false, + ), + ), + _isolateRef, + ), + ); + } + + return mapVariable; +} + +DartObjectNode buildMapGroupingVariable({ + required int length, + required int offset, + required int count, +}) { + return DartObjectNode.grouping( + GenericInstanceRef( + isolateRef: isolateRef, + value: _buildInstanceRefForMap(length: length), + ), + offset: offset, + count: count, + ); +} + +DartObjectNode buildParentSetVariable({int length = 2}) { + return DartObjectNode.create( + BoundVariable( + name: _incrementRoot(), + value: _buildInstanceRefForSet(length: length), + ), + _isolateRef, + ); +} + +DartObjectNode buildSetVariable({int length = 2}) { + final setVariable = buildParentSetVariable(length: length); + + for (int i = 0; i < length; i++) { + setVariable.addChild( + DartObjectNode.fromValue( + value: InstanceRef( + id: _incrementRef(), + kind: InstanceKind.kString, + classRef: ClassRef( + name: 'String', + id: _incrementRef(), + library: _libraryRef, + ), + valueAsString: 'set value $i', + valueAsStringIsTruncated: false, + ), + isolateRef: _isolateRef, + ), + ); + } + + return setVariable; +} + +DartObjectNode buildSetGroupingVariable({ + required int length, + required int offset, + required int count, +}) { + return DartObjectNode.grouping( + GenericInstanceRef( + isolateRef: isolateRef, + value: _buildInstanceRefForSet(length: length), + ), + offset: offset, + count: count, + ); +} + +DartObjectNode buildStringVariable(String value) { + return DartObjectNode.create( + BoundVariable( + name: _incrementRoot(), + value: InstanceRef( + id: _incrementRef(), + kind: InstanceKind.kString, + classRef: ClassRef( + name: 'String', + id: _incrementRef(), + library: _libraryRef, + ), + valueAsString: value, + valueAsStringIsTruncated: true, + ), + ), + _isolateRef, + ); +} + +DartObjectNode buildBooleanVariable(bool value) { + return DartObjectNode.create( + BoundVariable( + name: _incrementRoot(), + value: InstanceRef( + id: _incrementRef(), + kind: InstanceKind.kBool, + classRef: ClassRef( + name: 'Boolean', + id: _incrementRef(), + library: _libraryRef, + ), + valueAsString: '$value', + valueAsStringIsTruncated: false, + ), + ), + _isolateRef, + ); +} + +InstanceRef _buildInstanceRefForMap({required int length}) => InstanceRef( + id: _incrementRef(), + kind: InstanceKind.kMap, + classRef: ClassRef( + name: '_InternalLinkedHashmap', + id: _incrementRef(), + library: _libraryRef, + ), + length: length, + ); + +InstanceRef _buildInstanceRefForList({required int length}) => InstanceRef( + id: _incrementRef(), + kind: InstanceKind.kList, + classRef: ClassRef( + name: '_GrowableList', + id: _incrementRef(), + library: _libraryRef, + ), + length: length, + ); + +InstanceRef _buildInstanceRefForSet({required int length}) => InstanceRef( + id: _incrementRef(), + kind: InstanceKind.kSet, + classRef: ClassRef( + name: '_Set', + id: _incrementRef(), + library: _libraryRef, + ), + length: length, + ); + +final _libraryRef = LibraryRef( + name: 'some library', + uri: 'package:foo/foo.dart', + id: 'lib-id-1', +); + +final _isolateRef = IsolateRef( + id: '433', + number: '1', + name: 'my-isolate', + isSystemIsolate: false, +); + +int _refNumber = 0; + +String _incrementRef() { + _refNumber++; + return 'ref$_refNumber'; +} + +int _rootNumber = 0; + +String _incrementRoot() { + _rootNumber++; + return 'Root $_rootNumber'; +}