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

Edit mixin private properties #3010

Merged
merged 11 commits into from
May 12, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -415,14 +415,26 @@ Future<List<ObjectField>> _parseFields(
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,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import 'package:flutter/material.dart';
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';

Expand Down Expand Up @@ -80,7 +81,7 @@ class _MyAppState extends State<MyApp> {
}
}

class Counter extends ChangeNotifier {
class Counter with ChangeNotifier, Mixin {
int _count = 0;
int get count => _count;

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
mixin Mixin {
// ignore: unused_field, prefer_final_fields, the property is used for testing
int _privateMixinProperty = 0;
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,41 @@ Future<void> runProviderControllerTests(FlutterTestEnvironment env) async {
}, 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);
Expand Down Expand Up @@ -282,6 +317,8 @@ Future<void> runProviderControllerTests(FlutterTestEnvironment env) async {
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,
Expand All @@ -290,6 +327,17 @@ Future<void> runProviderControllerTests(FlutterTestEnvironment env) async {
.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,
Expand Down