Esempio n. 1
0
  private static void checkAlternateBinding(
      BlockScope scope,
      Expression receiver,
      TypeBinding receiverType,
      MethodBinding binding,
      Expression[] arguments,
      TypeBinding[] originalArgumentTypes,
      TypeBinding[] alternateArgumentTypes,
      final InvocationSite invocationSite) {
    InvocationSite fakeInvocationSite =
        new InvocationSite() {
          public TypeBinding[] genericTypeArguments() {
            return null;
          }

          public boolean isSuperAccess() {
            return invocationSite.isSuperAccess();
          }

          public boolean isTypeAccess() {
            return invocationSite.isTypeAccess();
          }

          public void setActualReceiverType(ReferenceBinding actualReceiverType) {
            /* ignore */
          }

          public void setDepth(int depth) {
            /* ignore */
          }

          public void setFieldIndex(int depth) {
            /* ignore */
          }

          public int sourceStart() {
            return 0;
          }

          public int sourceEnd() {
            return 0;
          }
        };
    MethodBinding bindingIfNoCast;
    if (binding.isConstructor()) {
      bindingIfNoCast =
          scope.getConstructor(
              (ReferenceBinding) receiverType, alternateArgumentTypes, fakeInvocationSite);
    } else {
      bindingIfNoCast =
          receiver.isImplicitThis()
              ? scope.getImplicitMethod(
                  binding.selector, alternateArgumentTypes, fakeInvocationSite)
              : scope.getMethod(
                  receiverType, binding.selector, alternateArgumentTypes, fakeInvocationSite);
    }
    if (bindingIfNoCast == binding) {
      int argumentLength = originalArgumentTypes.length;
      if (binding.isVarargs()) {
        int paramLength = binding.parameters.length;
        if (paramLength == argumentLength) {
          int varargsIndex = paramLength - 1;
          ArrayBinding varargsType = (ArrayBinding) binding.parameters[varargsIndex];
          TypeBinding lastArgType = alternateArgumentTypes[varargsIndex];
          // originalType may be compatible already, but cast mandated
          // to clarify between varargs/non-varargs call
          if (varargsType.dimensions != lastArgType.dimensions()) {
            return;
          }
          if (lastArgType.isCompatibleWith(varargsType.elementsType())
              && lastArgType.isCompatibleWith(varargsType)) {
            return;
          }
        }
      }
      for (int i = 0; i < argumentLength; i++) {
        if (originalArgumentTypes[i] != alternateArgumentTypes[i]) {
          scope.problemReporter().unnecessaryCast((CastExpression) arguments[i]);
        }
      }
    }
  }
Esempio n. 2
0
  public TypeBinding resolveType(BlockScope scope) {
    // Answer the signature return type
    // Base type promotion

    this.constant = Constant.NotAConstant;
    boolean receiverCast = false, argsContainCast = false;
    if (this.receiver instanceof CastExpression) {
      this.receiver.bits |= DisableUnnecessaryCastCheck; // will check later on
      receiverCast = true;
    }
    this.actualReceiverType = this.receiver.resolveType(scope);
    if (receiverCast && this.actualReceiverType != null) {
      // due to change of declaring class with receiver type, only identity cast should be notified
      if (((CastExpression) this.receiver).expression.resolvedType == this.actualReceiverType) {
        scope.problemReporter().unnecessaryCast((CastExpression) this.receiver);
      }
    }
    // resolve type arguments (for generic constructor call)
    if (this.typeArguments != null) {
      int length = this.typeArguments.length;
      boolean argHasError = false; // typeChecks all arguments
      this.genericTypeArguments = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        if ((this.genericTypeArguments[i] =
                this.typeArguments[i].resolveType(scope, true /* check bounds*/))
            == null) {
          argHasError = true;
        }
      }
      if (argHasError) {
        return null;
      }
    }
    // will check for null after args are resolved
    TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
    if (this.arguments != null) {
      boolean argHasError = false; // typeChecks all arguments
      int length = this.arguments.length;
      argumentTypes = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        Expression argument = this.arguments[i];
        if (argument instanceof CastExpression) {
          argument.bits |= DisableUnnecessaryCastCheck; // will check later on
          argsContainCast = true;
        }
        if ((argumentTypes[i] = this.arguments[i].resolveType(scope)) == null) argHasError = true;
      }
      if (argHasError) {
        if (this.actualReceiverType instanceof ReferenceBinding) {
          // record any selector match, for clients who may still need hint about possible method
          // match
          this.binding =
              scope.findMethod(
                  (ReferenceBinding) this.actualReceiverType,
                  this.selector,
                  new TypeBinding[] {},
                  this);
        }
        return null;
      }
    }
    if (this.actualReceiverType == null) {
      return null;
    }
    // base type cannot receive any message
    if (this.actualReceiverType.isBaseType()) {
      scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
      return null;
    }

    this.binding =
        this.receiver.isImplicitThis()
            ? scope.getImplicitMethod(this.selector, argumentTypes, this)
            : scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this);
    if (!this.binding.isValidBinding()) {
      if (this.binding instanceof ProblemMethodBinding
          && ((ProblemMethodBinding) this.binding).problemId() == ProblemReasons.NotVisible) {
        if (this.evaluationContext.declaringTypeName != null) {
          this.delegateThis =
              scope.getField(scope.enclosingSourceType(), EvaluationConstants.DELEGATE_THIS, this);
          if (this.delegateThis
              == null) { // if not found then internal error, field should have been found
            this.constant = Constant.NotAConstant;
            scope.problemReporter().invalidMethod(this, this.binding);
            return null;
          }
        } else {
          this.constant = Constant.NotAConstant;
          scope.problemReporter().invalidMethod(this, this.binding);
          return null;
        }
        CodeSnippetScope localScope = new CodeSnippetScope(scope);
        MethodBinding privateBinding =
            this.receiver instanceof CodeSnippetThisReference
                    && ((CodeSnippetThisReference) this.receiver).isImplicit
                ? localScope.getImplicitMethod(
                    (ReferenceBinding) this.delegateThis.type, this.selector, argumentTypes, this)
                : localScope.getMethod(this.delegateThis.type, this.selector, argumentTypes, this);
        if (!privateBinding.isValidBinding()) {
          if (this.binding.declaringClass == null) {
            if (this.actualReceiverType instanceof ReferenceBinding) {
              this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
            } else { // really bad error ....
              scope
                  .problemReporter()
                  .errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
              return null;
            }
          }
          scope.problemReporter().invalidMethod(this, this.binding);
          return null;
        } else {
          this.binding = privateBinding;
        }
      } else {
        if (this.binding.declaringClass == null) {
          if (this.actualReceiverType instanceof ReferenceBinding) {
            this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
          } else { // really bad error ....
            scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
            return null;
          }
        }
        scope.problemReporter().invalidMethod(this, this.binding);
        return null;
      }
    }
    if (!this.binding.isStatic()) {
      // the "receiver" must not be a type, in other words, a NameReference that the TC has bound to
      // a Type
      if (this.receiver instanceof NameReference
          && (((NameReference) this.receiver).bits & Binding.TYPE) != 0) {
        scope.problemReporter().mustUseAStaticMethod(this, this.binding);
      } else {
        // handle indirect inheritance thru variable secondary bound
        // receiver may receive generic cast, as part of implicit conversion
        TypeBinding oldReceiverType = this.actualReceiverType;
        this.actualReceiverType =
            this.actualReceiverType.getErasureCompatibleType(this.binding.declaringClass);
        this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType);
        if (this.actualReceiverType != oldReceiverType
            && this.receiver.postConversionType(scope)
                != this
                    .actualReceiverType) { // record need for explicit cast at codegen since
                                           // receiver could not handle it
          this.bits |= NeedReceiverGenericCast;
        }
      }
    }
    if (checkInvocationArguments(
        scope,
        this.receiver,
        this.actualReceiverType,
        this.binding,
        this.arguments,
        argumentTypes,
        argsContainCast,
        this)) {
      this.bits |= ASTNode.Unchecked;
    }

    // -------message send that are known to fail at compile time-----------
    if (this.binding.isAbstract()) {
      if (this.receiver.isSuper()) {
        scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding);
      }
      // abstract private methods cannot occur nor abstract static............
    }
    if (isMethodUseDeprecated(this.binding, scope, true))
      scope.problemReporter().deprecatedMethod(this.binding, this);

    // from 1.5 compliance on, array#clone() returns the array type (but binding still shows Object)
    if (this.actualReceiverType.isArrayType()
        && this.binding.parameters == Binding.NO_PARAMETERS
        && scope.compilerOptions().complianceLevel >= ClassFileConstants.JDK1_5
        && CharOperation.equals(this.binding.selector, CLONE)) {
      this.resolvedType = this.actualReceiverType;
    } else {
      TypeBinding returnType = this.binding.returnType;

      if (returnType != null) {
        if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) {
          returnType = scope.environment().convertToRawType(returnType.erasure(), true);
        }
        returnType = returnType.capture(scope, this.sourceEnd);
      }
      this.resolvedType = returnType;
    }
    return this.resolvedType;
  }
Esempio n. 3
0
  public static TypeBinding resolveType(
      TypeBinding resolvedType, MessageSend methodCall, BlockScope scope) {
    List<Extension> extensions = new ArrayList<Extension>();
    TypeDeclaration decl = scope.classScope().referenceContext;

    EclipseNode owningType = null;

    for (EclipseNode typeNode = getTypeNode(decl);
        typeNode != null;
        typeNode = upToType(typeNode)) {
      Annotation ann = getAnnotation(ExtensionMethod.class, typeNode);
      if (ann != null) {
        extensions.addAll(
            0, getApplicableExtensionMethods(typeNode, ann, methodCall.receiver.resolvedType));
        if (owningType == null) owningType = typeNode;
      }
    }

    boolean skip = false;

    if (methodCall.receiver instanceof ThisReference
        && (((ThisReference) methodCall.receiver).bits & ASTNode.IsImplicitThis) != 0) skip = true;
    if (methodCall.receiver instanceof SuperReference) skip = true;
    if (methodCall.receiver instanceof NameReference) {
      Binding binding = ((NameReference) methodCall.receiver).binding;
      if (binding instanceof TypeBinding) skip = true;
    }

    if (!skip)
      for (Extension extension : extensions) {
        if (!extension.suppressBaseMethods && !(methodCall.binding instanceof ProblemMethodBinding))
          continue;
        for (MethodBinding extensionMethod : extension.extensionMethods) {
          if (!Arrays.equals(methodCall.selector, extensionMethod.selector)) continue;
          MessageSend_postponedErrors.clear(methodCall);
          if (methodCall.receiver instanceof ThisReference) {
            methodCall.receiver.bits &= ~ASTNode.IsImplicitThis;
          }
          List<Expression> arguments = new ArrayList<Expression>();
          arguments.add(methodCall.receiver);
          if (methodCall.arguments != null) arguments.addAll(Arrays.asList(methodCall.arguments));
          List<TypeBinding> argumentTypes = new ArrayList<TypeBinding>();
          for (Expression argument : arguments) {
            if (argument.resolvedType != null) argumentTypes.add(argument.resolvedType);
            // TODO: Instead of just skipping nulls entirely, there is probably a 'unresolved type'
            // placeholder. THAT is what we ought to be adding here!
          }
          Expression[] originalArgs = methodCall.arguments;
          methodCall.arguments = arguments.toArray(new Expression[0]);
          MethodBinding fixedBinding =
              scope.getMethod(
                  extensionMethod.declaringClass,
                  methodCall.selector,
                  argumentTypes.toArray(new TypeBinding[0]),
                  methodCall);
          if (fixedBinding instanceof ProblemMethodBinding) {
            methodCall.arguments = originalArgs;
            if (fixedBinding.declaringClass != null) {
              scope.problemReporter().invalidMethod(methodCall, fixedBinding);
            }
          } else {
            for (int i = 0, iend = arguments.size(); i < iend; i++) {
              Expression arg = arguments.get(i);
              if (fixedBinding.parameters[i].isArrayType() != arg.resolvedType.isArrayType()) break;
              if (arg instanceof MessageSend) {
                ((MessageSend) arg).valueCast = arg.resolvedType;
              }
              if (!fixedBinding.parameters[i].isBaseType() && arg.resolvedType.isBaseType()) {
                int id = arg.resolvedType.id;
                arg.implicitConversion = TypeIds.BOXING | (id + (id << 4)); // magic see TypeIds
              } else if (fixedBinding.parameters[i].isBaseType()
                  && !arg.resolvedType.isBaseType()) {
                int id = fixedBinding.parameters[i].id;
                arg.implicitConversion = TypeIds.UNBOXING | (id + (id << 4)); // magic see TypeIds
              }
            }

            methodCall.receiver = createNameRef(extensionMethod.declaringClass, methodCall);
            methodCall.actualReceiverType = extensionMethod.declaringClass;
            methodCall.binding = fixedBinding;
            methodCall.resolvedType = methodCall.binding.returnType;
          }
          return methodCall.resolvedType;
        }
      }

    PostponedError error = MessageSend_postponedErrors.get(methodCall);
    if (error != null) error.fire();

    MessageSend_postponedErrors.clear(methodCall);
    return resolvedType;
  }
Esempio n. 4
0
  public TypeBinding resolveType(BlockScope scope) {
    // Answer the signature return type
    // Base type promotion

    this.constant = Constant.NotAConstant;
    boolean receiverCast = false, argsContainCast = false;
    if (this.receiver instanceof CastExpression) {
      this.receiver.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
      receiverCast = true;
    }
    this.actualReceiverType = this.receiver.resolveType(scope);
    boolean receiverIsType =
        this.receiver instanceof NameReference
            && (((NameReference) this.receiver).bits & Binding.TYPE) != 0;
    if (receiverCast && this.actualReceiverType != null) {
      // due to change of declaring class with receiver type, only identity cast should be notified
      if (((CastExpression) this.receiver).expression.resolvedType == this.actualReceiverType) {
        scope.problemReporter().unnecessaryCast((CastExpression) this.receiver);
      }
    }
    // resolve type arguments (for generic constructor call)
    if (this.typeArguments != null) {
      int length = this.typeArguments.length;
      boolean argHasError =
          scope.compilerOptions().sourceLevel
              < ClassFileConstants.JDK1_5; // typeChecks all arguments
      this.genericTypeArguments = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        TypeReference typeReference = this.typeArguments[i];
        if ((this.genericTypeArguments[i] =
                typeReference.resolveType(scope, true /* check bounds*/))
            == null) {
          argHasError = true;
        }
        if (argHasError && typeReference instanceof Wildcard) {
          scope.problemReporter().illegalUsageOfWildcard(typeReference);
        }
      }
      if (argHasError) {
        if (this.arguments != null) { // still attempt to resolve arguments
          for (int i = 0, max = this.arguments.length; i < max; i++) {
            this.arguments[i].resolveType(scope);
          }
        }
        return null;
      }
    }
    // will check for null after args are resolved
    TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
    if (this.arguments != null) {
      boolean argHasError = false; // typeChecks all arguments
      int length = this.arguments.length;
      argumentTypes = new TypeBinding[length];
      for (int i = 0; i < length; i++) {
        Expression argument = this.arguments[i];
        if (argument instanceof CastExpression) {
          argument.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
          argsContainCast = true;
        }
        if ((argumentTypes[i] = argument.resolveType(scope)) == null) {
          argHasError = true;
        }
      }
      if (argHasError) {
        if (this.actualReceiverType instanceof ReferenceBinding) {
          //  record a best guess, for clients who need hint about possible method match
          TypeBinding[] pseudoArgs = new TypeBinding[length];
          for (int i = length; --i >= 0; )
            pseudoArgs[i] =
                argumentTypes[i] == null
                    ? TypeBinding.NULL
                    : argumentTypes[i]; // replace args with errors with null type
          this.binding =
              this.receiver.isImplicitThis()
                  ? scope.getImplicitMethod(this.selector, pseudoArgs, this)
                  : scope.findMethod(
                      (ReferenceBinding) this.actualReceiverType, this.selector, pseudoArgs, this);
          if (this.binding != null && !this.binding.isValidBinding()) {
            MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch;
            // record the closest match, for clients who may still need hint about possible method
            // match
            if (closestMatch != null) {
              if (closestMatch.original().typeVariables
                  != Binding.NO_TYPE_VARIABLES) { // generic method
                // shouldn't return generic method outside its context, rather convert it to raw
                // method (175409)
                closestMatch =
                    scope
                        .environment()
                        .createParameterizedGenericMethod(
                            closestMatch.original(), (RawTypeBinding) null);
              }
              this.binding = closestMatch;
              MethodBinding closestMatchOriginal = closestMatch.original();
              if (closestMatchOriginal.isOrEnclosedByPrivateType()
                  && !scope.isDefinedInMethod(closestMatchOriginal)) {
                // ignore cases where method is used from within inside itself (e.g. direct
                // recursions)
                closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
              }
            }
          }
        }
        return null;
      }
    }
    if (this.actualReceiverType == null) {
      return null;
    }
    // base type cannot receive any message
    if (this.actualReceiverType.isBaseType()) {
      scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
      return null;
    }
    this.binding =
        this.receiver.isImplicitThis()
            ? scope.getImplicitMethod(this.selector, argumentTypes, this)
            : scope.getMethod(this.actualReceiverType, this.selector, argumentTypes, this);
    if (!this.binding.isValidBinding()) {
      if (this.binding.declaringClass == null) {
        if (this.actualReceiverType instanceof ReferenceBinding) {
          this.binding.declaringClass = (ReferenceBinding) this.actualReceiverType;
        } else {
          scope.problemReporter().errorNoMethodFor(this, this.actualReceiverType, argumentTypes);
          return null;
        }
      }
      // https://bugs.eclipse.org/bugs/show_bug.cgi?id=245007 avoid secondary errors in case of
      // missing super type for anonymous classes ...
      ReferenceBinding declaringClass = this.binding.declaringClass;
      boolean avoidSecondary =
          declaringClass != null
              && declaringClass.isAnonymousType()
              && declaringClass.superclass() instanceof MissingTypeBinding;
      if (!avoidSecondary) scope.problemReporter().invalidMethod(this, this.binding);
      MethodBinding closestMatch = ((ProblemMethodBinding) this.binding).closestMatch;
      switch (this.binding.problemId()) {
        case ProblemReasons.Ambiguous:
          break; // no resilience on ambiguous
        case ProblemReasons.NotVisible:
        case ProblemReasons.NonStaticReferenceInConstructorInvocation:
        case ProblemReasons.NonStaticReferenceInStaticContext:
        case ProblemReasons.ReceiverTypeNotVisible:
        case ProblemReasons.ParameterBoundMismatch:
          // only steal returnType in cases listed above
          if (closestMatch != null) this.resolvedType = closestMatch.returnType;
          break;
      }
      // record the closest match, for clients who may still need hint about possible method match
      if (closestMatch != null) {
        this.binding = closestMatch;
        MethodBinding closestMatchOriginal = closestMatch.original();
        if (closestMatchOriginal.isOrEnclosedByPrivateType()
            && !scope.isDefinedInMethod(closestMatchOriginal)) {
          // ignore cases where method is used from within inside itself (e.g. direct recursions)
          closestMatchOriginal.modifiers |= ExtraCompilerModifiers.AccLocallyUsed;
        }
      }
      return (this.resolvedType != null
              && (this.resolvedType.tagBits & TagBits.HasMissingType) == 0)
          ? this.resolvedType
          : null;
    }
    final CompilerOptions compilerOptions = scope.compilerOptions();
    if (compilerOptions.complianceLevel <= ClassFileConstants.JDK1_6
        && this.binding.isPolymorphic()) {
      scope.problemReporter().polymorphicMethodNotBelow17(this);
      return null;
    }

    if (((this.bits & ASTNode.InsideExpressionStatement) != 0) && this.binding.isPolymorphic()) {
      // we only set the return type to be void if this method invocation is used inside an
      // expression statement
      this.binding =
          scope
              .environment()
              .updatePolymorphicMethodReturnType(
                  (PolymorphicMethodBinding) this.binding, TypeBinding.VOID);
    }
    if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
      scope.problemReporter().missingTypeInMethod(this, this.binding);
    }
    if (!this.binding.isStatic()) {
      // the "receiver" must not be a type
      if (receiverIsType) {
        scope.problemReporter().mustUseAStaticMethod(this, this.binding);
        if (this.actualReceiverType.isRawType()
            && (this.receiver.bits & ASTNode.IgnoreRawTypeCheck) == 0
            && compilerOptions.getSeverity(CompilerOptions.RawTypeReference)
                != ProblemSeverities.Ignore) {
          scope.problemReporter().rawTypeReference(this.receiver, this.actualReceiverType);
        }
      } else {
        // handle indirect inheritance thru variable secondary bound
        // receiver may receive generic cast, as part of implicit conversion
        TypeBinding oldReceiverType = this.actualReceiverType;
        this.actualReceiverType =
            this.actualReceiverType.getErasureCompatibleType(this.binding.declaringClass);
        this.receiver.computeConversion(scope, this.actualReceiverType, this.actualReceiverType);
        if (this.actualReceiverType != oldReceiverType
            && this.receiver.postConversionType(scope)
                != this
                    .actualReceiverType) { // record need for explicit cast at codegen since
                                           // receiver could not handle it
          this.bits |= NeedReceiverGenericCast;
        }
      }
    } else {
      // static message invoked through receiver? legal but unoptimal (optional warning).
      if (!(this.receiver.isImplicitThis() || this.receiver.isSuper() || receiverIsType)) {
        scope.problemReporter().nonStaticAccessToStaticMethod(this, this.binding);
      }
      if (!this.receiver.isImplicitThis()
          && this.binding.declaringClass != this.actualReceiverType) {
        scope.problemReporter().indirectAccessToStaticMethod(this, this.binding);
      }
    }
    if (checkInvocationArguments(
        scope,
        this.receiver,
        this.actualReceiverType,
        this.binding,
        this.arguments,
        argumentTypes,
        argsContainCast,
        this)) {
      this.bits |= ASTNode.Unchecked;
    }

    // -------message send that are known to fail at compile time-----------
    if (this.binding.isAbstract()) {
      if (this.receiver.isSuper()) {
        scope.problemReporter().cannotDireclyInvokeAbstractMethod(this, this.binding);
      }
      // abstract private methods cannot occur nor abstract static............
    }
    if (isMethodUseDeprecated(this.binding, scope, true))
      scope.problemReporter().deprecatedMethod(this.binding, this);

    // from 1.5 source level on, array#clone() returns the array type (but binding still shows
    // Object)
    if (this.binding == scope.environment().arrayClone
        && compilerOptions.sourceLevel >= ClassFileConstants.JDK1_5) {
      this.resolvedType = this.actualReceiverType;
    } else {
      TypeBinding returnType;
      if ((this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null) {
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=277643, align with javac on JLS 15.12.2.6
        returnType = this.binding.returnType;
        if (returnType != null) {
          returnType = scope.environment().convertToRawType(returnType.erasure(), true);
        }
      } else {
        returnType = this.binding.returnType;
        if (returnType != null) {
          returnType = returnType.capture(scope, this.sourceEnd);
        }
      }
      this.resolvedType = returnType;
    }
    if (this.receiver.isSuper()
        && compilerOptions.getSeverity(CompilerOptions.OverridingMethodWithoutSuperInvocation)
            != ProblemSeverities.Ignore) {
      final ReferenceContext referenceContext = scope.methodScope().referenceContext;
      if (referenceContext instanceof AbstractMethodDeclaration) {
        final AbstractMethodDeclaration abstractMethodDeclaration =
            (AbstractMethodDeclaration) referenceContext;
        MethodBinding enclosingMethodBinding = abstractMethodDeclaration.binding;
        if (enclosingMethodBinding.isOverriding()
            && CharOperation.equals(this.binding.selector, enclosingMethodBinding.selector)
            && this.binding.areParametersEqual(enclosingMethodBinding)) {
          abstractMethodDeclaration.bits |= ASTNode.OverridingMethodWithSupercall;
        }
      }
    }
    if (this.typeArguments != null
        && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
      scope
          .problemReporter()
          .unnecessaryTypeArgumentsForMethodInvocation(
              this.binding, this.genericTypeArguments, this.typeArguments);
    }
    return (this.resolvedType.tagBits & TagBits.HasMissingType) == 0 ? this.resolvedType : null;
  }