| 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 8ec4c7a50ec681cb73458ae9d1ce28d6dfef849d..1b300028225fec21fc7d2dc9992d24e82af759ef 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
|
| @@ -614,10 +614,6 @@ public class ErrorVerifier extends RecursiveASTVisitor<Void> {
|
| } else {
|
| checkForNewWithUndefinedConstructor(node);
|
| }
|
| - // TODO(jwren) Email Luke to make this determination: Should we always call all checks, if not,
|
| - // which order should they be called in?
|
| - // (Should we provide as many errors as possible, or try to be as concise as possible?)
|
| - checkForTypeArgumentNotMatchingBounds(node, constructorName.getElement(), typeName);
|
| }
|
| return super.visitInstanceCreationExpression(node);
|
| }
|
| @@ -803,6 +799,12 @@ public class ErrorVerifier extends RecursiveASTVisitor<Void> {
|
| }
|
|
|
| @Override
|
| + public Void visitTypeName(TypeName node) {
|
| + checkForTypeArgumentNotMatchingBounds(node);
|
| + return super.visitTypeName(node);
|
| + }
|
| +
|
| + @Override
|
| public Void visitTypeParameter(TypeParameter node) {
|
| checkForBuiltInIdentifierAsName(
|
| node.getName(),
|
| @@ -3988,42 +3990,46 @@ public class ErrorVerifier extends RecursiveASTVisitor<Void> {
|
| }
|
|
|
| /**
|
| - * This verifies that the type arguments in the passed instance creation expression are all within
|
| - * their bounds as specified by the class element where the constructor [that is being invoked] is
|
| - * declared.
|
| + * This verifies that the type arguments in the passed type name are all within their bounds.
|
| *
|
| - * @param node the instance creation expression to evaluate
|
| - * @param typeName the {@link TypeName} of the {@link ConstructorName} from the
|
| - * {@link InstanceCreationExpression}, this is the AST node that the error is attached to
|
| - * @param constructorElement the {@link ConstructorElement} from the instance creation expression
|
| + * @param node the {@link TypeName} to evaluate
|
| * @return {@code true} if and only if an error code is generated on the passed node
|
| * @see StaticTypeWarningCode#TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
|
| */
|
| - private boolean checkForTypeArgumentNotMatchingBounds(InstanceCreationExpression node,
|
| - ConstructorElement constructorElement, TypeName typeName) {
|
| - if (typeName.getTypeArguments() != null && constructorElement != null) {
|
| - NodeList<TypeName> typeNameArgList = typeName.getTypeArguments().getArguments();
|
| - TypeVariableElement[] boundingElts = constructorElement.getEnclosingElement().getTypeVariables();
|
| - // Loop through only all of the elements of the shorter of our two arrays. (Note: This
|
| - // will only happen these tokens have the WRONG_NUMBER_OF_TYPE_ARGUMENTS error code too.)
|
| - int loopThroughIndex = Math.min(typeNameArgList.size(), boundingElts.length);
|
| - for (int i = 0; i < loopThroughIndex; i++) {
|
| - TypeName argTypeName = typeNameArgList.get(i);
|
| - Type argType = argTypeName.getType();
|
| - Type boundType = boundingElts[i].getBound();
|
| - if (argType != null && boundType != null) {
|
| - if (!argType.isSubtypeOf(boundType)) {
|
| - errorReporter.reportError(
|
| - StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
|
| - argTypeName,
|
| - argTypeName.getName(),
|
| - boundingElts[i].getDisplayName());
|
| - return true;
|
| - }
|
| + private boolean checkForTypeArgumentNotMatchingBounds(TypeName node) {
|
| + if (node.getTypeArguments() == null) {
|
| + return false;
|
| + }
|
| + TypeVariableElement[] boundingElts = null;
|
| + Type type = node.getType();
|
| + if (type == null) {
|
| + return false;
|
| + }
|
| + Element element = type.getElement();
|
| + if (element instanceof ClassElement) {
|
| + boundingElts = ((ClassElement) element).getTypeVariables();
|
| + } else {
|
| + return false;
|
| + }
|
| + NodeList<TypeName> typeNameArgList = node.getTypeArguments().getArguments();
|
| + int loopThroughIndex = Math.min(typeNameArgList.size(), boundingElts.length);
|
| + boolean foundError = false;
|
| + for (int i = 0; i < loopThroughIndex; i++) {
|
| + TypeName argTypeName = typeNameArgList.get(i);
|
| + Type argType = argTypeName.getType();
|
| + Type boundType = boundingElts[i].getBound();
|
| + if (argType != null && boundType != null) {
|
| + if (!argType.isSubtypeOf(boundType)) {
|
| + errorReporter.reportError(
|
| + StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS,
|
| + argTypeName,
|
| + argTypeName.getName(),
|
| + boundingElts[i].getBound().getDisplayName());
|
| + foundError = true;
|
| }
|
| }
|
| }
|
| - return false;
|
| + return foundError;
|
| }
|
|
|
| /**
|
|
|