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]. |