| Index: pkg/analyzer/lib/src/generated/error_verifier.dart
|
| diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
|
| index 1fa5eae09db4805cfbc74551a068dbc160ea4184..2c9ef54c5f7ee17ab91159945af24c7247291277 100644
|
| --- a/pkg/analyzer/lib/src/generated/error_verifier.dart
|
| +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
|
| @@ -486,6 +486,9 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
| _checkImplementsSuperClass(node);
|
| _checkImplementsFunctionWithoutCall(node);
|
| _checkForMixinHasNoConstructors(node);
|
| + if (_options.strongMode) {
|
| + _checkForMixinWithConflictingPrivateMember(node);
|
| + }
|
| }
|
| }
|
| visitClassDeclarationIncrementally(node);
|
| @@ -4899,6 +4902,80 @@ class ErrorVerifier extends RecursiveAstVisitor<Object> {
|
| }
|
|
|
| /**
|
| + * Check for the declaration of a mixin from a library other than the current
|
| + * library that defines a private member that conflicts with a private name
|
| + * from the same library but from a superclass or a different mixin.
|
| + */
|
| + void _checkForMixinWithConflictingPrivateMember(ClassDeclaration node) {
|
| + WithClause withClause = node.withClause;
|
| + if (withClause == null) {
|
| + return;
|
| + }
|
| + DartType declaredSupertype = node.extendsClause?.superclass?.type;
|
| + if (declaredSupertype is! InterfaceType) {
|
| + return;
|
| + }
|
| + InterfaceType superclass = declaredSupertype;
|
| + Map<LibraryElement, Map<String, String>> mixedInNames =
|
| + <LibraryElement, Map<String, String>>{};
|
| +
|
| + /**
|
| + * Report an error and return `true` if the given [name] is a private name
|
| + * (which is defined in the given [library]) and it conflicts with another
|
| + * definition of that name inherited from the superclass.
|
| + */
|
| + bool isConflictingName(
|
| + String name, LibraryElement library, TypeName typeName) {
|
| + if (Identifier.isPrivateName(name)) {
|
| + Map<String, String> names =
|
| + mixedInNames.putIfAbsent(library, () => <String, String>{});
|
| + if (names.containsKey(name)) {
|
| + _errorReporter.reportErrorForNode(
|
| + CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION,
|
| + typeName,
|
| + [name, typeName.name.name, names[name]]);
|
| + return true;
|
| + }
|
| + names[name] = typeName.name.name;
|
| + ExecutableElement inheritedMember =
|
| + superclass.lookUpMethod(name, library) ??
|
| + superclass.lookUpGetter(name, library) ??
|
| + superclass.lookUpSetter(name, library);
|
| + if (inheritedMember != null) {
|
| + _errorReporter.reportErrorForNode(
|
| + CompileTimeErrorCode.PRIVATE_COLLISION_IN_MIXIN_APPLICATION,
|
| + typeName, [
|
| + name,
|
| + typeName.name.name,
|
| + inheritedMember.enclosingElement.name
|
| + ]);
|
| + return true;
|
| + }
|
| + }
|
| + return false;
|
| + }
|
| +
|
| + for (TypeName mixinType in withClause.mixinTypes) {
|
| + DartType type = mixinType.type;
|
| + if (type is InterfaceType) {
|
| + LibraryElement library = type.element.library;
|
| + if (library != _currentLibrary) {
|
| + for (PropertyAccessorElement accessor in type.accessors) {
|
| + if (isConflictingName(accessor.name, library, mixinType)) {
|
| + return;
|
| + }
|
| + }
|
| + for (MethodElement method in type.methods) {
|
| + if (isConflictingName(method.name, library, mixinType)) {
|
| + return;
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| + }
|
| +
|
| + /**
|
| * Verify that the given [constructor] has at most one 'super' initializer.
|
| *
|
| * See [CompileTimeErrorCode.MULTIPLE_SUPER_INITIALIZERS].
|
|
|