Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(848)

Unified Diff: pkg/analyzer/lib/src/generated/error_verifier.dart

Issue 2738113002: Add strong mode error for mixins defining conflicting private names (issue 28809) (Closed)
Patch Set: Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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].
« no previous file with comments | « pkg/analyzer/lib/src/error/codes.dart ('k') | pkg/analyzer/test/generated/compile_time_error_code_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698