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

Unified Diff: editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/verifier/ErrorVerifier.java

Issue 114473004: Fix for 15028. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Nit/cleanup: delete commented out code. Created 7 years 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
« no previous file with comments | « no previous file | editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/resolver/NonErrorResolverTest.java » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/verifier/ErrorVerifier.java
diff --git a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/verifier/ErrorVerifier.java b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/verifier/ErrorVerifier.java
index c53819103dfd19ac98e5d0cfa19e4d4bf944636b..e1b440087bad1d330a591e8c83c044edad7d416b 100644
--- a/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/verifier/ErrorVerifier.java
+++ b/editor/tools/plugins/com.google.dart.engine/src/com/google/dart/engine/internal/verifier/ErrorVerifier.java
@@ -3982,7 +3982,9 @@ public class ErrorVerifier extends RecursiveASTVisitor<Void> {
HashSet<ExecutableElement> missingOverrides = new HashSet<ExecutableElement>();
+ //
// Loop through the set of all executable elements declared in the implicit interface.
+ //
MemberMap membersInheritedFromInterfaces = inheritanceManager.getMapOfMembersInheritedFromInterfaces(enclosingClass);
MemberMap membersInheritedFromSuperclasses = inheritanceManager.getMapOfMembersInheritedFromClasses(enclosingClass);
for (int i = 0; i < membersInheritedFromInterfaces.getSize(); i++) {
@@ -3992,43 +3994,56 @@ public class ErrorVerifier extends RecursiveASTVisitor<Void> {
break;
}
+ // If the element is defined in Object, skip it.
+ if (((ClassElement) executableElt.getEnclosingElement()).getType().isObject()) {
+ continue;
+ }
+
+ // Reference the type of the enclosing class
+ InterfaceType enclosingType = enclosingClass.getType();
+
+ // Check to see if some element is in local enclosing class that matches the name of the
+ // required member.
+ if (isMemberInClassOrMixin(executableElt, enclosingClass)) {
+ // We do not have to verify that this implementation of the found method matches the
+ // required function type: the set of StaticWarningCode.INVALID_METHOD_OVERRIDE_* warnings
+ // break out the different specific situations.
+ continue;
+ }
+
// First check to see if this element was declared in the superclass chain, in which case
// there is already a concrete implementation.
ExecutableElement elt = membersInheritedFromSuperclasses.get(executableElt.getName());
+
+ // Check to see if an element was found in the superclass chain with the correct name.
if (elt != null) {
- if (elt instanceof MethodElement && !((MethodElement) elt).isAbstract()) {
- continue;
- } else if (elt instanceof PropertyAccessorElement
- && !((PropertyAccessorElement) elt).isAbstract()) {
- continue;
+ // Some element was found in the superclass chain that matches the name of the required
+ // member.
+ // If it is not abstract and it is the correct one (types match- the version of this method
+ // that we have has the correct number of parameters, etc), then this class has a valid
+ // implementation of this method, so skip it.
+ if ((elt instanceof MethodElement && !((MethodElement) elt).isAbstract())
+ || (elt instanceof PropertyAccessorElement && !((PropertyAccessorElement) elt).isAbstract())) {
+ // Since we are comparing two function types, we need to do the appropriate type
+ // substitutions first ().
+ FunctionType foundConcreteFT = inheritanceManager.substituteTypeArgumentsInMemberFromInheritance(
+ elt.getType(),
+ executableElt.getName(),
+ enclosingType);
+ FunctionType requiredMemberFT = inheritanceManager.substituteTypeArgumentsInMemberFromInheritance(
+ executableElt.getType(),
+ executableElt.getName(),
+ enclosingType);
+ if (foundConcreteFT.isSubtypeOf(requiredMemberFT)) {
+ continue;
+ }
}
}
- if (executableElt instanceof MethodElement) {
- // Verify that this class has a method which overrides the method from the interface.
- // If a method was inherited from an interface, but is not implemented by either the class
- // or one of its superclasses, then add the inherited method to the missingOverides set.
- if (!methodsInEnclosingClass.contains(memberName)
- && !memberHasConcreteMethodImplementationInSuperclassChain(
- enclosingClass,
- memberName,
- new ArrayList<ClassElement>())) {
- missingOverrides.add(executableElt);
- }
- } else if (executableElt instanceof PropertyAccessorElement) {
- // Verify that this class has a member which overrides the method from the interface.
- // If an accessor was inherited from an interface, but is not implemented by either the
- // class or one of its superclasses, then add the inherited accessor to the missingOverides
- // set.
- if (!accessorsInEnclosingClass.contains(memberName)
- && !memberHasConcreteAccessorImplementationInSuperclassChain(
- enclosingClass,
- memberName,
- new ArrayList<ClassElement>())) {
- missingOverrides.add(executableElt);
- }
- }
+ // The not qualifying concrete executable element was found, add it to the list.
+ missingOverrides.add(executableElt);
}
+ // Now that we have the set of missing overrides, generate a warning on this class
int missingOverridesSize = missingOverrides.size();
if (missingOverridesSize == 0) {
return false;
@@ -5297,6 +5312,56 @@ public class ErrorVerifier extends RecursiveASTVisitor<Void> {
}
/**
+ * Return {@code true} iff the passed {@link ClassElement} has a method, getter or setter that
+ * matches the name of the passed {@link ExecutableElement} in either the class itself, or one of
+ * its' mixins.
+ * <p>
+ * By "match", only the name of the member is tested to match, it does not have to equal or be a
+ * subtype of the passed executable element, this is due to the specific use where this method is
+ * used in {@link #checkForNonAbstractClassInheritsAbstractMember(ClassDeclaration)}.
+ *
+ * @param executableElt the executable to search for in the passed class element
+ * @param classElt the class method to search through the members of
+ * @return {@code true} iff the passed member is found in the passed class element
+ */
+ private boolean isMemberInClassOrMixin(ExecutableElement executableElt, ClassElement classElt) {
+ ExecutableElement foundElt;
+ String executableName = executableElt.getName();
+ if (executableElt instanceof MethodElement) {
+ foundElt = classElt.getMethod(executableName);
+ if (foundElt != null) {
+ return true;
+ }
+ InterfaceType[] mixins = classElt.getMixins();
+ for (int i = 0; i < mixins.length && foundElt == null; i++) {
+ foundElt = mixins[i].getMethod(executableName);
+ }
+ if (foundElt != null) {
+ return true;
+ }
+ } else if (executableElt instanceof PropertyAccessorElement) {
+ foundElt = classElt.getGetter(executableElt.getName());
+ if (foundElt == null) {
+ foundElt = classElt.getSetter(executableName);
+ }
+ if (foundElt != null) {
+ return true;
+ }
+ InterfaceType[] mixins = classElt.getMixins();
+ for (int i = 0; i < mixins.length && foundElt == null; i++) {
+ foundElt = mixins[i].getGetter(executableName);
+ if (foundElt == null) {
+ foundElt = mixins[i].getSetter(executableName);
+ }
+ }
+ if (foundElt != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* @param node the 'this' expression to analyze
* @return {@code true} if the given 'this' expression is in the valid context
*/
@@ -5352,94 +5417,4 @@ public class ErrorVerifier extends RecursiveASTVisitor<Void> {
}
return false;
}
-
- /**
- * Return {@code true} iff the passed {@link ClassElement} has a concrete implementation of the
- * passed accessor name in the superclass chain.
- */
- private boolean memberHasConcreteAccessorImplementationInSuperclassChain(
- ClassElement classElement, String accessorName, ArrayList<ClassElement> superclassChain) {
- if (superclassChain.contains(classElement)) {
- return false;
- } else {
- superclassChain.add(classElement);
- }
- for (PropertyAccessorElement accessor : classElement.getAccessors()) {
- if (accessor.getName().equals(accessorName)) {
- if (!accessor.isAbstract()) {
- return true;
- }
- }
- }
- for (InterfaceType mixinType : classElement.getMixins()) {
- if (mixinType != null) {
- ClassElement mixinElement = mixinType.getElement();
- if (mixinElement != null) {
- for (PropertyAccessorElement accessor : mixinElement.getAccessors()) {
- if (accessor.getName().equals(accessorName)) {
- if (!accessor.isAbstract()) {
- return true;
- }
- }
- }
- }
- }
- }
- InterfaceType superType = classElement.getSupertype();
- if (superType != null) {
- ClassElement superClassElt = superType.getElement();
- if (superClassElt != null) {
- return memberHasConcreteAccessorImplementationInSuperclassChain(
- superClassElt,
- accessorName,
- superclassChain);
- }
- }
- return false;
- }
-
- /**
- * Return {@code true} iff the passed {@link ClassElement} has a concrete implementation of the
- * passed method name in the superclass chain.
- */
- private boolean memberHasConcreteMethodImplementationInSuperclassChain(ClassElement classElement,
- String methodName, ArrayList<ClassElement> superclassChain) {
- if (superclassChain.contains(classElement)) {
- return false;
- } else {
- superclassChain.add(classElement);
- }
- for (MethodElement method : classElement.getMethods()) {
- if (method.getName().equals(methodName)) {
- if (!method.isAbstract()) {
- return true;
- }
- }
- }
- for (InterfaceType mixinType : classElement.getMixins()) {
- if (mixinType != null) {
- ClassElement mixinElement = mixinType.getElement();
- if (mixinElement != null) {
- for (MethodElement method : mixinElement.getMethods()) {
- if (method.getName().equals(methodName)) {
- if (!method.isAbstract()) {
- return true;
- }
- }
- }
- }
- }
- }
- InterfaceType superType = classElement.getSupertype();
- if (superType != null) {
- ClassElement superClassElt = superType.getElement();
- if (superClassElt != null) {
- return memberHasConcreteMethodImplementationInSuperclassChain(
- superClassElt,
- methodName,
- superclassChain);
- }
- }
- return false;
- }
}
« no previous file with comments | « no previous file | editor/tools/plugins/com.google.dart.engine_test/src/com/google/dart/engine/resolver/NonErrorResolverTest.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698