Edit mixin private properties (#3010)
diff --git a/packages/devtools_app/lib/src/provider/instance_viewer/instance_providers.dart b/packages/devtools_app/lib/src/provider/instance_viewer/instance_providers.dart index 601a466..420bc43 100644 --- a/packages/devtools_app/lib/src/provider/instance_viewer/instance_providers.dart +++ b/packages/devtools_app/lib/src/provider/instance_viewer/instance_providers.dart
@@ -415,14 +415,26 @@ final fields = instance.fields.map((field) async { final owner = await eval.getClass(field.decl.owner, isAlive); - final ownerPackageName = tryParsePackageName(owner.library.uri); + String ownerUri; + String ownerName; + if (owner.mixin == null) { + ownerUri = owner.library.uri; + ownerName = owner.name; + } else { + final mixinClass = await eval.getClass(owner.mixin.typeClass, isAlive); + + ownerUri = mixinClass.library.uri; + ownerName = mixinClass.name; + } + + final ownerPackageName = tryParsePackageName(ownerUri); return ObjectField( name: field.decl.name, isFinal: field.decl.isFinal, ref: parseSentinel<InstanceRef>(field.value), - ownerName: owner.name, - ownerUri: owner.library.uri, + ownerName: ownerName, + ownerUri: ownerUri, eval: await ref.watch(libraryEvalProvider(owner.library.uri).future), isDefinedByDependency: ownerPackageName != appName, );
diff --git a/packages/devtools_testing/fixtures/provider_app/lib/main.dart b/packages/devtools_testing/fixtures/provider_app/lib/main.dart index f18e8f2..41658c4 100644 --- a/packages/devtools_testing/fixtures/provider_app/lib/main.dart +++ b/packages/devtools_testing/fixtures/provider_app/lib/main.dart
@@ -9,6 +9,7 @@ import 'package:provider/provider.dart'; import 'package:provider/single_child_widget.dart'; +import 'mixin.dart'; // ignore: unused_import, allows the tests to use functions from tester.dart import 'tester.dart'; @@ -80,7 +81,7 @@ } } -class Counter extends ChangeNotifier { +class Counter with ChangeNotifier, Mixin { int _count = 0; int get count => _count;
diff --git a/packages/devtools_testing/fixtures/provider_app/lib/mixin.dart b/packages/devtools_testing/fixtures/provider_app/lib/mixin.dart new file mode 100644 index 0000000..45bbc3e --- /dev/null +++ b/packages/devtools_testing/fixtures/provider_app/lib/mixin.dart
@@ -0,0 +1,4 @@ +mixin Mixin { + // ignore: unused_field, prefer_final_fields, the property is used for testing + int _privateMixinProperty = 0; +}
diff --git a/packages/devtools_testing/lib/provider/provider_controller_test.dart b/packages/devtools_testing/lib/provider/provider_controller_test.dart index e7f92a5..ee8a935 100644 --- a/packages/devtools_testing/lib/provider/provider_controller_test.dart +++ b/packages/devtools_testing/lib/provider/provider_controller_test.dart
@@ -106,6 +106,41 @@ }, timeout: const Timeout.factor(8), skip: true); group('Provider controllers', () { + test('can mutate private properties from mixins', () async { + final container = ProviderContainer(); + addTearDown(container.dispose); + + final sub = container.listen( + rawInstanceProvider( + const InstancePath.fromProviderId('0').pathForChild( + const PathToProperty.objectProperty( + name: '_privateMixinProperty', + ownerUri: 'package:provider_app/mixin.dart', + ownerName: 'Mixin', + ), + ), + ).future, + ); + + var instance = await sub.read(); + + expect( + instance, + isA<NumInstance>().having((e) => e.displayString, 'displayString', '0'), + ); + + await instance.setter('42'); + + // read the instance again since it should have changed + instance = await sub.read(); + + expect( + instance, + isA<NumInstance>() + .having((e) => e.displayString, 'displayString', '42'), + ); + }); + test('rawSortedProviderNodesProvider', () async { final container = ProviderContainer(); addTearDown(container.dispose); @@ -282,6 +317,8 @@ isA<ObjectField>() .having((e) => e.ownerName, 'ownerName', 'Counter') .having((e) => e.name, 'name', '_count') + .having((e) => e.ownerUri, 'ownerUri', + 'package:provider_app/main.dart') .having((e) => e.isFinal, 'isFinal', false) .having((e) => e.isPrivate, 'isPrivate', true) .having((e) => e.isDefinedByDependency, @@ -290,6 +327,17 @@ .having( (e) => e.ownerName, 'ownerName', 'ChangeNotifier') .having((e) => e.name, 'name', '_listeners') + .having((e) => e.ownerUri, 'ownerUri', + 'package:flutter/src/foundation/change_notifier.dart') + .having((e) => e.isFinal, 'isFinal', false) + .having((e) => e.isPrivate, 'isPrivate', true) + .having((e) => e.isDefinedByDependency, + 'isDefinedByDependency', true), + isA<ObjectField>() + .having((e) => e.ownerName, 'ownerName', 'Mixin') + .having((e) => e.name, 'name', '_privateMixinProperty') + .having((e) => e.ownerUri, 'ownerUri', + 'package:provider_app/mixin.dart') .having((e) => e.isFinal, 'isFinal', false) .having((e) => e.isPrivate, 'isPrivate', true) .having((e) => e.isDefinedByDependency,