コード例 #1
0
 /** Check all typeArguments for illegal null annotations on base types. */
 protected void checkIllegalNullAnnotations(Scope scope, TypeReference[] typeArguments) {
   if (scope.environment().usesNullTypeAnnotations() && typeArguments != null) {
     for (int i = 0; i < typeArguments.length; i++) {
       TypeReference arg = typeArguments[i];
       if (arg.resolvedType != null) arg.checkIllegalNullAnnotation(scope);
     }
   }
 }
コード例 #2
0
 public boolean canUseDiamond(String[] parameterTypes, char[] fullyQualifiedTypeName) {
   TypeBinding guessedType = null;
   char[][] cn = CharOperation.splitOn('.', fullyQualifiedTypeName);
   Scope scope = this.assistScope;
   if (scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_7) return false;
   // If no LHS or return type expected, then we can safely use diamond
   char[][] expectedTypekeys = this.completionContext.getExpectedTypesKeys();
   if (expectedTypekeys == null || expectedTypekeys.length == 0) return true;
   // Next, find out whether any of the constructor parameters are the same as one of the
   // class type variables. If yes, diamond cannot be used.
   TypeReference ref;
   if (cn.length == 1) {
     ref = new SingleTypeReference(cn[0], 0);
   } else {
     ref = new QualifiedTypeReference(cn, new long[cn.length]);
   }
   // {ObjectTeams: protect call into the compiler
   try (Config config =
       Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true)) {
     // orig:
     switch (scope.kind) {
       case Scope.METHOD_SCOPE:
       case Scope.BLOCK_SCOPE:
         guessedType = ref.resolveType((BlockScope) scope);
         break;
       case Scope.CLASS_SCOPE:
         guessedType = ref.resolveType((ClassScope) scope);
         break;
     }
     // :giro
   }
   // SH}
   if (guessedType != null && guessedType.isValidBinding()) {
     // the erasure must be used because guessedType can be a RawTypeBinding
     guessedType = guessedType.erasure();
     TypeVariableBinding[] typeVars = guessedType.typeVariables();
     for (int i = 0; i < parameterTypes.length; i++) {
       for (int j = 0; j < typeVars.length; j++) {
         if (CharOperation.equals(parameterTypes[i].toCharArray(), typeVars[j].sourceName))
           return false;
       }
     }
     return true;
   }
   return false;
 }
コード例 #3
0
 public InstanceOfExpression(Expression expression, TypeReference type) {
   this.expression = expression;
   this.type = type;
   type.bits |= IgnoreRawTypeCheck; // https://bugs.eclipse.org/bugs/show_bug.cgi?id=282141
   this.bits |= INSTANCEOF << OperatorSHIFT;
   this.sourceStart = expression.sourceStart;
   this.sourceEnd = type.sourceEnd;
 }
コード例 #4
0
ファイル: MethodSpec.java プロジェクト: eclipse/objectteams
  /**
   * Resolve and bind arguments, return type.
   *
   * @param scope used for resolving. Newly bound arguments are entered here.
   * @param isBaseSide TODO
   */
  public void resolveTypes(CallinCalloutScope scope, boolean isBaseSide) {
    if (this.typeParameters != null) {
      for (int i = 0, length = this.typeParameters.length; i < length; i++) {
        if (isBaseSide)
          scope.problemReporter().illegalMappingRHSTypeParameter(this.typeParameters[i]);
        else this.typeParameters[i].resolve(scope);
      }
      if (!isBaseSide) scope.connectTypeVariables(this.typeParameters, true);
    }
    TypeBinding[] types = Binding.NO_PARAMETERS;
    if (this.arguments != null) {
      types = new TypeBinding[this.arguments.length];
      for (int i = 0; i < this.arguments.length; i++) {
        TypeReference type = this.arguments[i].type;
        if (isBaseSide) type.setBaseclassDecapsulation(DecapsulationState.ALLOWED);
        types[i] = type.resolveType(scope);
        if (types[i] != null) {
          type.resolvedType =
              types[i] =
                  RoleTypeCreator.maybeWrapUnqualifiedRoleType(scope, types[i], this.arguments[i]);
        } else {
          // ensure we have a type set!
          types[i] = type.resolvedType; // a ProblemBinding !?
          if (types[i] == null)
            types[i] =
                new ProblemReferenceBinding(type.getTypeName(), null, ProblemReasons.NotFound);
        }

        // record in scope, needed for role types anchored to an argument
        // (all arguments must be bound in order!)
        this.arguments[i].bind(scope, types[i], false);
      }
    }
    if (this.hasSignature) this.argNeedsTranslation = new boolean[types.length];
    if (this.returnType != null) {
      if (isBaseSide) this.returnType.setBaseclassDecapsulation(DecapsulationState.ALLOWED);
      this.returnType.resolve(scope);
      if (this.returnType.resolvedType != null)
        this.returnType.resolvedType =
            RoleTypeCreator.maybeWrapUnqualifiedRoleType(
                scope, this.returnType.resolvedType, this.returnType);
    }
    this.parameters = types;
  }
コード例 #5
0
 private TypeBinding nullMismatchOnBound(
     TypeParameter parameter,
     TypeBinding boundType,
     long superNullTagBits,
     long nullTagBits,
     Scope scope) {
   // not finding bound should be considered a compiler bug
   TypeReference bound = findBound(boundType, parameter);
   Annotation ann = bound.findAnnotation(superNullTagBits);
   if (ann != null) {
     // explicit annotation: error
     scope.problemReporter().contradictoryNullAnnotationsOnBounds(ann, nullTagBits);
     this.tagBits &= ~TagBits.AnnotationNullMASK;
   } else {
     // implicit annotation: let the new one override
     return boundType.withoutToplevelNullAnnotation();
   }
   return boundType;
 }
コード例 #6
0
ファイル: Eclipse.java プロジェクト: barneypitt/lombok
  /**
   * Checks if the provided annotation type is likely to be the intended type for the given
   * annotation node.
   *
   * <p>This is a guess, but a decent one.
   */
  public static boolean annotationTypeMatches(
      Class<? extends java.lang.annotation.Annotation> type, Node node) {
    if (node.getKind() != Kind.ANNOTATION) return false;
    TypeReference typeRef = ((Annotation) node.get()).type;
    if (typeRef == null || typeRef.getTypeName() == null) return false;
    String typeName = toQualifiedName(typeRef.getTypeName());

    TypeLibrary library = new TypeLibrary();
    library.addType(type.getName());
    TypeResolver resolver =
        new TypeResolver(library, node.getPackageDeclaration(), node.getImportStatements());
    Collection<String> typeMatches = resolver.findTypeMatches(node, typeName);

    for (String match : typeMatches) {
      if (match.equals(type.getName())) return true;
    }

    return false;
  }
コード例 #7
0
 /** Give 2 clones! */
 private Expression longToIntForHashCode(Expression ref1, Expression ref2, ASTNode source) {
   int pS = source.sourceStart, pE = source.sourceEnd;
   /* (int)(ref >>> 32 ^ ref) */
   IntLiteral int32 = new IntLiteral("32".toCharArray(), pS, pE);
   Eclipse.setGeneratedBy(int32, source);
   BinaryExpression higherBits =
       new BinaryExpression(ref1, int32, OperatorIds.UNSIGNED_RIGHT_SHIFT);
   Eclipse.setGeneratedBy(higherBits, source);
   BinaryExpression xorParts = new BinaryExpression(ref2, higherBits, OperatorIds.XOR);
   Eclipse.setGeneratedBy(xorParts, source);
   TypeReference intRef = TypeReference.baseTypeReference(TypeIds.T_int, 0);
   intRef.sourceStart = pS;
   intRef.sourceEnd = pE;
   Eclipse.setGeneratedBy(intRef, source);
   CastExpression expr = new CastExpression(xorParts, intRef);
   expr.sourceStart = pS;
   expr.sourceEnd = pE;
   Eclipse.setGeneratedBy(expr, source);
   return expr;
 }
コード例 #8
0
  public StringBuffer printStatement(int indent, StringBuffer output) {

    printIndent(indent, output);
    printModifiers(this.modifiers, output);
    type.print(0, output).append(' ').append(this.name);
    if (initialization != null) {
      output.append(" = "); // $NON-NLS-1$
      initialization.printExpression(indent, output);
    }
    return output.append(';');
  }
コード例 #9
0
  public void traverse(ASTVisitor visitor, BlockScope scope) {

    if (visitor.visit(this, scope)) {
      int dimensionsLength = dimensions.length;
      type.traverse(visitor, scope);
      for (int i = 0; i < dimensionsLength; i++) {
        if (dimensions[i] != null) dimensions[i].traverse(visitor, scope);
      }
      if (initializer != null) initializer.traverse(visitor, scope);
    }
    visitor.endVisit(this, scope);
  }
コード例 #10
0
  private MethodDeclaration createCanEqual(EclipseNode type, ASTNode source) {
    /* public boolean canEqual(final java.lang.Object other) {
     *     return other instanceof MyType;
     * }
     */
    int pS = source.sourceStart;
    int pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;

    char[] otherName = "other".toCharArray();

    MethodDeclaration method =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(method, source);
    method.modifiers = EclipseHandlerUtil.toEclipseModifier(AccessLevel.PUBLIC);
    method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
    method.returnType.sourceStart = pS;
    method.returnType.sourceEnd = pE;
    Eclipse.setGeneratedBy(method.returnType, source);
    method.selector = "canEqual".toCharArray();
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    TypeReference objectRef =
        new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {p, p, p});
    Eclipse.setGeneratedBy(objectRef, source);
    method.arguments = new Argument[] {new Argument(otherName, 0, objectRef, Modifier.FINAL)};
    method.arguments[0].sourceStart = pS;
    method.arguments[0].sourceEnd = pE;
    Eclipse.setGeneratedBy(method.arguments[0], source);

    SingleNameReference otherRef = new SingleNameReference(otherName, p);
    Eclipse.setGeneratedBy(otherRef, source);

    SingleTypeReference typeReference =
        new SingleTypeReference(((TypeDeclaration) type.get()).name, p);
    Eclipse.setGeneratedBy(typeReference, source);

    InstanceOfExpression instanceOf = new InstanceOfExpression(otherRef, typeReference);
    instanceOf.sourceStart = pS;
    instanceOf.sourceEnd = pE;
    Eclipse.setGeneratedBy(instanceOf, source);

    ReturnStatement returnStatement = new ReturnStatement(instanceOf, pS, pE);
    Eclipse.setGeneratedBy(returnStatement, source);

    method.statements = new Statement[] {returnStatement};
    return method;
  }
コード例 #11
0
  /** Record the thrown exception type bindings in the corresponding type references. */
  public void bindThrownExceptions() {

    if (this.thrownExceptions != null
        && this.binding != null
        && this.binding.thrownExceptions != null) {
      int thrownExceptionLength = this.thrownExceptions.length;
      int length = this.binding.thrownExceptions.length;
      if (length == thrownExceptionLength) {
        for (int i = 0; i < length; i++) {
          this.thrownExceptions[i].resolvedType = this.binding.thrownExceptions[i];
        }
      } else {
        int bindingIndex = 0;
        for (int i = 0; i < thrownExceptionLength && bindingIndex < length; i++) {
          TypeReference thrownException = this.thrownExceptions[i];
          ReferenceBinding thrownExceptionBinding = this.binding.thrownExceptions[bindingIndex];
          char[][] bindingCompoundName = thrownExceptionBinding.compoundName;
          if (bindingCompoundName == null) continue; // skip problem case
          if (thrownException instanceof SingleTypeReference) {
            // single type reference
            int lengthName = bindingCompoundName.length;
            char[] thrownExceptionTypeName = thrownException.getTypeName()[0];
            if (CharOperation.equals(
                thrownExceptionTypeName, bindingCompoundName[lengthName - 1])) {
              thrownException.resolvedType = thrownExceptionBinding;
              bindingIndex++;
            }
          } else {
            // qualified type reference
            if (CharOperation.equals(thrownException.getTypeName(), bindingCompoundName)) {
              thrownException.resolvedType = thrownExceptionBinding;
              bindingIndex++;
            }
          }
        }
      }
    }
  }
コード例 #12
0
ファイル: JavaSourceParser.java プロジェクト: hammoum/gwt
  /**
   * Compares an unresolved JDT type to a TypeOracle type to see if they match.
   *
   * @param jdtType
   * @param toType
   * @return true if the two type objects resolve to the same
   */
  private static boolean typeMatches(TypeReference jdtType, JType toType) {
    List<char[]> toNameComponents = getClassChain(toType.getQualifiedBinaryName());
    int toLen = toNameComponents.size();
    char[][] jdtNameComponents = jdtType.getTypeName();
    int jdtLen = jdtNameComponents.length;
    int maxToCompare = Math.min(toLen, jdtLen);

    // compare from the end
    for (int i = 1; i <= maxToCompare; ++i) {
      if (!Arrays.equals(jdtNameComponents[jdtLen - i], toNameComponents.get(toLen - i))) {
        return false;
      }
    }
    return true;
  }
コード例 #13
0
  public StringBuffer printExpression(int indent, StringBuffer output) {

    output.append("new "); // $NON-NLS-1$
    type.print(0, output);
    for (int i = 0; i < dimensions.length; i++) {
      if (dimensions[i] == null) output.append("[]"); // $NON-NLS-1$
      else {
        output.append('[');
        dimensions[i].printExpression(0, output);
        output.append(']');
      }
    }
    if (initializer != null) initializer.printExpression(0, output);
    return output;
  }
コード例 #14
0
  protected static boolean hasEmptyName(TypeReference reference, ASTNode assistNode) {
    if (reference == null) return false;

    // https://bugs.eclipse.org/bugs/show_bug.cgi?id=397070
    if (reference != assistNode
        && reference.sourceStart <= assistNode.sourceStart
        && assistNode.sourceEnd <= reference.sourceEnd) return false;

    if (reference instanceof CompletionOnSingleTypeReference
        || reference instanceof CompletionOnQualifiedTypeReference
        || reference instanceof CompletionOnParameterizedQualifiedTypeReference) {
      char[][] typeName = reference.getTypeName();
      if (typeName[typeName.length - 1].length == 0) return true;
    }
    if (reference instanceof ParameterizedSingleTypeReference) {
      ParameterizedSingleTypeReference parameterizedReference =
          (ParameterizedSingleTypeReference) reference;
      TypeReference[] typeArguments = parameterizedReference.typeArguments;
      if (typeArguments != null) {
        for (int i = 0; i < typeArguments.length; i++) {
          if (hasEmptyName(typeArguments[i], assistNode)) return true;
        }
      }
    } else if (reference instanceof ParameterizedQualifiedTypeReference) {
      ParameterizedQualifiedTypeReference parameterizedReference =
          (ParameterizedQualifiedTypeReference) reference;
      TypeReference[][] typeArguments = parameterizedReference.typeArguments;
      if (typeArguments != null) {
        for (int i = 0; i < typeArguments.length; i++) {
          if (typeArguments[i] != null) {
            for (int j = 0; j < typeArguments[i].length; j++) {
              if (hasEmptyName(typeArguments[i][j], assistNode)) return true;
            }
          }
        }
      }
    }
    return false;
  }
コード例 #15
0
ファイル: HandleToString.java プロジェクト: Reder/lombok
  private MethodDeclaration createToString(
      EclipseNode type,
      Collection<EclipseNode> fields,
      boolean includeFieldNames,
      boolean callSuper,
      ASTNode source,
      FieldAccess fieldAccess) {
    String typeName = getTypeName(type);
    char[] suffix = ")".toCharArray();
    String infixS = ", ";
    char[] infix = infixS.toCharArray();
    int pS = source.sourceStart, pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;
    final int PLUS = OperatorIds.PLUS;

    char[] prefix;

    if (callSuper) {
      prefix = (typeName + "(super=").toCharArray();
    } else if (fields.isEmpty()) {
      prefix = (typeName + "()").toCharArray();
    } else if (includeFieldNames) {
      prefix =
          (typeName
                  + "("
                  + new String(((FieldDeclaration) fields.iterator().next().get()).name)
                  + "=")
              .toCharArray();
    } else {
      prefix = (typeName + "(").toCharArray();
    }

    boolean first = true;
    Expression current = new StringLiteral(prefix, pS, pE, 0);
    Eclipse.setGeneratedBy(current, source);

    if (callSuper) {
      MessageSend callToSuper = new MessageSend();
      callToSuper.sourceStart = pS;
      callToSuper.sourceEnd = pE;
      Eclipse.setGeneratedBy(callToSuper, source);
      callToSuper.receiver = new SuperReference(pS, pE);
      Eclipse.setGeneratedBy(callToSuper, source);
      callToSuper.selector = "toString".toCharArray();
      current = new BinaryExpression(current, callToSuper, PLUS);
      Eclipse.setGeneratedBy(current, source);
      first = false;
    }

    for (EclipseNode field : fields) {
      TypeReference fType = getFieldType(field, fieldAccess);
      Expression fieldAccessor = createFieldAccessor(field, fieldAccess, source);

      Expression ex;
      if (fType.dimensions() > 0) {
        MessageSend arrayToString = new MessageSend();
        arrayToString.sourceStart = pS;
        arrayToString.sourceEnd = pE;
        arrayToString.receiver =
            generateQualifiedNameRef(
                source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
        arrayToString.arguments = new Expression[] {fieldAccessor};
        Eclipse.setGeneratedBy(arrayToString.arguments[0], source);
        if (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(fType.getLastToken()))) {
          arrayToString.selector = "deepToString".toCharArray();
        } else {
          arrayToString.selector = "toString".toCharArray();
        }
        ex = arrayToString;
      } else {
        ex = fieldAccessor;
      }
      Eclipse.setGeneratedBy(ex, source);

      if (first) {
        current = new BinaryExpression(current, ex, PLUS);
        current.sourceStart = pS;
        current.sourceEnd = pE;
        Eclipse.setGeneratedBy(current, source);
        first = false;
        continue;
      }

      StringLiteral fieldNameLiteral;
      if (includeFieldNames) {
        char[] namePlusEqualsSign = (infixS + field.getName() + "=").toCharArray();
        fieldNameLiteral = new StringLiteral(namePlusEqualsSign, pS, pE, 0);
      } else {
        fieldNameLiteral = new StringLiteral(infix, pS, pE, 0);
      }
      Eclipse.setGeneratedBy(fieldNameLiteral, source);
      current = new BinaryExpression(current, fieldNameLiteral, PLUS);
      Eclipse.setGeneratedBy(current, source);
      current = new BinaryExpression(current, ex, PLUS);
      Eclipse.setGeneratedBy(current, source);
    }
    if (!first) {
      StringLiteral suffixLiteral = new StringLiteral(suffix, pS, pE, 0);
      Eclipse.setGeneratedBy(suffixLiteral, source);
      current = new BinaryExpression(current, suffixLiteral, PLUS);
      Eclipse.setGeneratedBy(current, source);
    }

    ReturnStatement returnStatement = new ReturnStatement(current, pS, pE);
    Eclipse.setGeneratedBy(returnStatement, source);

    MethodDeclaration method =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(method, source);
    method.modifiers = toEclipseModifier(AccessLevel.PUBLIC);
    method.returnType =
        new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p, p, p});
    Eclipse.setGeneratedBy(method.returnType, source);
    method.annotations =
        new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
    method.arguments = null;
    method.selector = "toString".toCharArray();
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    method.statements = new Statement[] {returnStatement};
    return method;
  }
コード例 #16
0
 // expression.implicitConversion holds the cast for baseType casting
 public CastExpression(Expression expression, TypeReference type) {
   this.expression = expression;
   this.type = type;
   type.bits |= ASTNode.IgnoreRawTypeCheck; // no need to worry about raw type usage
 }
コード例 #17
0
  private MethodDeclaration createHashCode(
      EclipseNode type,
      Collection<EclipseNode> fields,
      boolean callSuper,
      ASTNode source,
      FieldAccess fieldAccess) {
    int pS = source.sourceStart, pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;

    MethodDeclaration method =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(method, source);

    method.modifiers = EclipseHandlerUtil.toEclipseModifier(AccessLevel.PUBLIC);
    method.returnType = TypeReference.baseTypeReference(TypeIds.T_int, 0);
    Eclipse.setGeneratedBy(method.returnType, source);
    method.annotations =
        new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
    method.selector = "hashCode".toCharArray();
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    method.arguments = null;

    List<Statement> statements = new ArrayList<Statement>();
    List<Expression> intoResult = new ArrayList<Expression>();

    final char[] PRIME = "PRIME".toCharArray();
    final char[] RESULT = "result".toCharArray();
    final boolean isEmpty = fields.isEmpty();

    /* final int PRIME = 31; */ {
      /* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */
      if (!isEmpty || callSuper) {
        LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE);
        Eclipse.setGeneratedBy(primeDecl, source);
        primeDecl.modifiers |= Modifier.FINAL;
        primeDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
        primeDecl.type.sourceStart = pS;
        primeDecl.type.sourceEnd = pE;
        Eclipse.setGeneratedBy(primeDecl.type, source);
        primeDecl.initialization = new IntLiteral("31".toCharArray(), pS, pE);
        Eclipse.setGeneratedBy(primeDecl.initialization, source);
        statements.add(primeDecl);
      }
    }

    /* int result = 1; */ {
      LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE);
      Eclipse.setGeneratedBy(resultDecl, source);
      resultDecl.initialization = new IntLiteral("1".toCharArray(), pS, pE);
      Eclipse.setGeneratedBy(resultDecl.initialization, source);
      resultDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
      resultDecl.type.sourceStart = pS;
      resultDecl.type.sourceEnd = pE;
      Eclipse.setGeneratedBy(resultDecl.type, source);
      statements.add(resultDecl);
    }

    if (callSuper) {
      MessageSend callToSuper = new MessageSend();
      Eclipse.setGeneratedBy(callToSuper, source);
      callToSuper.sourceStart = pS;
      callToSuper.sourceEnd = pE;
      callToSuper.receiver = new SuperReference(pS, pE);
      Eclipse.setGeneratedBy(callToSuper.receiver, source);
      callToSuper.selector = "hashCode".toCharArray();
      intoResult.add(callToSuper);
    }

    int tempCounter = 0;
    for (EclipseNode field : fields) {
      TypeReference fType = getFieldType(field, fieldAccess);
      char[] token = fType.getLastToken();
      Expression fieldAccessor = createFieldAccessor(field, fieldAccess, source);
      if (fType.dimensions() == 0 && token != null) {
        if (Arrays.equals(TypeConstants.FLOAT, token)) {
          /* Float.floatToIntBits(fieldName) */
          MessageSend floatToIntBits = new MessageSend();
          floatToIntBits.sourceStart = pS;
          floatToIntBits.sourceEnd = pE;
          Eclipse.setGeneratedBy(floatToIntBits, source);
          floatToIntBits.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_FLOAT);
          floatToIntBits.selector = "floatToIntBits".toCharArray();
          floatToIntBits.arguments = new Expression[] {fieldAccessor};
          intoResult.add(floatToIntBits);
        } else if (Arrays.equals(TypeConstants.DOUBLE, token)) {
          /* longToIntForHashCode(Double.doubleToLongBits(fieldName)) */
          MessageSend doubleToLongBits = new MessageSend();
          doubleToLongBits.sourceStart = pS;
          doubleToLongBits.sourceEnd = pE;
          Eclipse.setGeneratedBy(doubleToLongBits, source);
          doubleToLongBits.receiver =
              generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_DOUBLE);
          doubleToLongBits.selector = "doubleToLongBits".toCharArray();
          doubleToLongBits.arguments = new Expression[] {fieldAccessor};
          final char[] tempName = ("temp" + ++tempCounter).toCharArray();
          LocalDeclaration tempVar = new LocalDeclaration(tempName, pS, pE);
          Eclipse.setGeneratedBy(tempVar, source);
          tempVar.initialization = doubleToLongBits;
          tempVar.type = TypeReference.baseTypeReference(TypeIds.T_long, 0);
          tempVar.type.sourceStart = pS;
          tempVar.type.sourceEnd = pE;
          Eclipse.setGeneratedBy(tempVar.type, source);
          tempVar.modifiers = Modifier.FINAL;
          statements.add(tempVar);
          SingleNameReference copy1 = new SingleNameReference(tempName, p);
          Eclipse.setGeneratedBy(copy1, source);
          SingleNameReference copy2 = new SingleNameReference(tempName, p);
          Eclipse.setGeneratedBy(copy2, source);
          intoResult.add(longToIntForHashCode(copy1, copy2, source));
        } else if (Arrays.equals(TypeConstants.BOOLEAN, token)) {
          /* booleanField ? 1231 : 1237 */
          IntLiteral int1231 = new IntLiteral("1231".toCharArray(), pS, pE);
          Eclipse.setGeneratedBy(int1231, source);
          IntLiteral int1237 = new IntLiteral("1237".toCharArray(), pS, pE);
          Eclipse.setGeneratedBy(int1237, source);
          ConditionalExpression int1231or1237 =
              new ConditionalExpression(fieldAccessor, int1231, int1237);
          Eclipse.setGeneratedBy(int1231or1237, source);
          intoResult.add(int1231or1237);
        } else if (Arrays.equals(TypeConstants.LONG, token)) {
          intoResult.add(
              longToIntForHashCode(
                  fieldAccessor, createFieldAccessor(field, fieldAccess, source), source));
        } else if (BUILT_IN_TYPES.contains(new String(token))) {
          intoResult.add(fieldAccessor);
        } else /* objects */ {
          /* this.fieldName == null ? 0 : this.fieldName.hashCode() */
          MessageSend hashCodeCall = new MessageSend();
          hashCodeCall.sourceStart = pS;
          hashCodeCall.sourceEnd = pE;
          Eclipse.setGeneratedBy(hashCodeCall, source);
          hashCodeCall.receiver = createFieldAccessor(field, fieldAccess, source);
          hashCodeCall.selector = "hashCode".toCharArray();
          NullLiteral nullLiteral = new NullLiteral(pS, pE);
          Eclipse.setGeneratedBy(nullLiteral, source);
          EqualExpression objIsNull =
              new EqualExpression(fieldAccessor, nullLiteral, OperatorIds.EQUAL_EQUAL);
          Eclipse.setGeneratedBy(objIsNull, source);
          IntLiteral int0 = new IntLiteral("0".toCharArray(), pS, pE);
          Eclipse.setGeneratedBy(int0, source);
          ConditionalExpression nullOrHashCode =
              new ConditionalExpression(objIsNull, int0, hashCodeCall);
          nullOrHashCode.sourceStart = pS;
          nullOrHashCode.sourceEnd = pE;
          Eclipse.setGeneratedBy(nullOrHashCode, source);
          intoResult.add(nullOrHashCode);
        }
      } else if (fType.dimensions() > 0 && token != null) {
        /* Arrays.deepHashCode(array)  //just hashCode for simple arrays */
        MessageSend arraysHashCodeCall = new MessageSend();
        arraysHashCodeCall.sourceStart = pS;
        arraysHashCodeCall.sourceEnd = pE;
        Eclipse.setGeneratedBy(arraysHashCodeCall, source);
        arraysHashCodeCall.receiver =
            generateQualifiedNameRef(
                source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
        if (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) {
          arraysHashCodeCall.selector = "deepHashCode".toCharArray();
        } else {
          arraysHashCodeCall.selector = "hashCode".toCharArray();
        }
        arraysHashCodeCall.arguments = new Expression[] {fieldAccessor};
        intoResult.add(arraysHashCodeCall);
      }
    }

    /* fold each intoResult entry into:
    result = result * PRIME + (item); */ {
      for (Expression ex : intoResult) {
        SingleNameReference resultRef = new SingleNameReference(RESULT, p);
        Eclipse.setGeneratedBy(resultRef, source);
        SingleNameReference primeRef = new SingleNameReference(PRIME, p);
        Eclipse.setGeneratedBy(primeRef, source);
        BinaryExpression multiplyByPrime =
            new BinaryExpression(resultRef, primeRef, OperatorIds.MULTIPLY);
        multiplyByPrime.sourceStart = pS;
        multiplyByPrime.sourceEnd = pE;
        Eclipse.setGeneratedBy(multiplyByPrime, source);
        BinaryExpression addItem = new BinaryExpression(multiplyByPrime, ex, OperatorIds.PLUS);
        addItem.sourceStart = pS;
        addItem.sourceEnd = pE;
        Eclipse.setGeneratedBy(addItem, source);
        resultRef = new SingleNameReference(RESULT, p);
        Eclipse.setGeneratedBy(resultRef, source);
        Assignment assignment = new Assignment(resultRef, addItem, pE);
        assignment.sourceStart = pS;
        assignment.sourceEnd = pE;
        Eclipse.setGeneratedBy(assignment, source);
        statements.add(assignment);
      }
    }

    /* return result; */ {
      SingleNameReference resultRef = new SingleNameReference(RESULT, p);
      Eclipse.setGeneratedBy(resultRef, source);
      ReturnStatement returnStatement = new ReturnStatement(resultRef, pS, pE);
      Eclipse.setGeneratedBy(returnStatement, source);
      statements.add(returnStatement);
    }
    method.statements = statements.toArray(new Statement[statements.size()]);
    return method;
  }
コード例 #18
0
 public TypeReference getTypeReference(int dim) {
   /* build a Reference on a variable that may be qualified or not
    * This variable is a type reference and dim will be its dimensions
    */
   Annotation[][] annotationsOnDimensions = null;
   TypeReference ref;
   int length = this.identifierLengthStack[this.identifierLengthPtr--];
   if (length < 0) { // flag for precompiled type reference on base types
     annotationsOnDimensions = getAnnotationsOnDimensions(dim);
     ref = TypeReference.baseTypeReference(-length, dim, annotationsOnDimensions);
     ref.sourceStart = this.intStack[this.intPtr--];
     if (dim == 0) {
       ref.sourceEnd = this.intStack[this.intPtr--];
     } else {
       this.intPtr--; // no need to use this position as it is an array
       ref.sourceEnd = this.rBracketPosition;
     }
     if (this.reportReferenceInfo) {
       this.requestor.acceptTypeReference(
           ref.getParameterizedTypeName(), ref.sourceStart, ref.sourceEnd);
     }
   } else {
     int numberOfIdentifiers =
         this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
     if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
       // generic type
       ref = getTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
       if (this.reportReferenceInfo) {
         if (length == 1 && numberOfIdentifiers == 1) {
           ParameterizedSingleTypeReference parameterizedSingleTypeReference =
               (ParameterizedSingleTypeReference) ref;
           this.requestor.acceptTypeReference(
               parameterizedSingleTypeReference.token,
               parameterizedSingleTypeReference.sourceStart);
         } else {
           ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference =
               (ParameterizedQualifiedTypeReference) ref;
           this.requestor.acceptTypeReference(
               parameterizedQualifiedTypeReference.tokens,
               parameterizedQualifiedTypeReference.sourceStart,
               parameterizedQualifiedTypeReference.sourceEnd);
         }
       }
     } else if (length == 1) {
       // single type reference
       this.genericsLengthPtr--; // pop the 0
       if (dim == 0) {
         ref =
             new SingleTypeReference(
                 this.identifierStack[this.identifierPtr],
                 this.identifierPositionStack[this.identifierPtr--]);
         if (this.reportReferenceInfo) {
           this.requestor.acceptTypeReference(((SingleTypeReference) ref).token, ref.sourceStart);
         }
       } else {
         annotationsOnDimensions = getAnnotationsOnDimensions(dim);
         ref =
             new ArrayTypeReference(
                 this.identifierStack[this.identifierPtr],
                 dim,
                 annotationsOnDimensions,
                 this.identifierPositionStack[this.identifierPtr--]);
         ref.sourceEnd = this.endPosition;
         if (annotationsOnDimensions != null) {
           ref.bits |= ASTNode.HasTypeAnnotations;
         }
         if (this.reportReferenceInfo) {
           this.requestor.acceptTypeReference(((ArrayTypeReference) ref).token, ref.sourceStart);
         }
       }
     } else { // Qualified type reference
       this.genericsLengthPtr--;
       char[][] tokens = new char[length][];
       this.identifierPtr -= length;
       long[] positions = new long[length];
       System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
       System.arraycopy(
           this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
       if (dim == 0) {
         ref = new QualifiedTypeReference(tokens, positions);
         if (this.reportReferenceInfo) {
           this.requestor.acceptTypeReference(
               ((QualifiedTypeReference) ref).tokens, ref.sourceStart, ref.sourceEnd);
         }
       } else {
         annotationsOnDimensions = getAnnotationsOnDimensions(dim);
         ref = new ArrayQualifiedTypeReference(tokens, dim, annotationsOnDimensions, positions);
         ref.sourceEnd = this.endPosition;
         if (annotationsOnDimensions != null) {
           ref.bits |= ASTNode.HasTypeAnnotations;
         }
         if (this.reportReferenceInfo) {
           this.requestor.acceptTypeReference(
               ((ArrayQualifiedTypeReference) ref).tokens, ref.sourceStart, ref.sourceEnd);
         }
       }
     }
   }
   int levels = ref.getAnnotatableLevels();
   for (int i = levels - 1; i >= 0; i--) {
     if ((length = this.typeAnnotationLengthStack[this.typeAnnotationLengthPtr--]) != 0) {
       if (ref.annotations == null) ref.annotations = new Annotation[levels][];
       System.arraycopy(
           this.typeAnnotationStack,
           (this.typeAnnotationPtr -= length) + 1,
           ref.annotations[i] = new Annotation[length],
           0,
           length);
       if (i == 0) {
         ref.sourceStart = ref.annotations[0][0].sourceStart;
       }
       ref.bits |= ASTNode.HasTypeAnnotations;
     }
   }
   return ref;
 }
コード例 #19
0
  private MethodDeclaration createEquals(
      EclipseNode type,
      Collection<EclipseNode> fields,
      boolean callSuper,
      ASTNode source,
      FieldAccess fieldAccess,
      boolean needsCanEqual) {
    int pS = source.sourceStart;
    int pE = source.sourceEnd;
    long p = (long) pS << 32 | pE;
    TypeDeclaration typeDecl = (TypeDeclaration) type.get();

    MethodDeclaration method =
        new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
    Eclipse.setGeneratedBy(method, source);
    method.modifiers = EclipseHandlerUtil.toEclipseModifier(AccessLevel.PUBLIC);
    method.returnType = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
    method.returnType.sourceStart = pS;
    method.returnType.sourceEnd = pE;
    Eclipse.setGeneratedBy(method.returnType, source);
    method.annotations =
        new Annotation[] {makeMarkerAnnotation(TypeConstants.JAVA_LANG_OVERRIDE, source)};
    method.selector = "equals".toCharArray();
    method.thrownExceptions = null;
    method.typeParameters = null;
    method.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
    method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
    method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
    TypeReference objectRef =
        new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, new long[] {p, p, p});
    Eclipse.setGeneratedBy(objectRef, source);
    method.arguments =
        new Argument[] {new Argument(new char[] {'o'}, 0, objectRef, Modifier.FINAL)};
    method.arguments[0].sourceStart = pS;
    method.arguments[0].sourceEnd = pE;
    Eclipse.setGeneratedBy(method.arguments[0], source);

    List<Statement> statements = new ArrayList<Statement>();

    /* if (o == this) return true; */ {
      SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p);
      Eclipse.setGeneratedBy(oRef, source);
      ThisReference thisRef = new ThisReference(pS, pE);
      Eclipse.setGeneratedBy(thisRef, source);
      EqualExpression otherEqualsThis = new EqualExpression(oRef, thisRef, OperatorIds.EQUAL_EQUAL);
      Eclipse.setGeneratedBy(otherEqualsThis, source);

      TrueLiteral trueLiteral = new TrueLiteral(pS, pE);
      Eclipse.setGeneratedBy(trueLiteral, source);
      ReturnStatement returnTrue = new ReturnStatement(trueLiteral, pS, pE);
      Eclipse.setGeneratedBy(returnTrue, source);
      IfStatement ifOtherEqualsThis = new IfStatement(otherEqualsThis, returnTrue, pS, pE);
      Eclipse.setGeneratedBy(ifOtherEqualsThis, source);
      statements.add(ifOtherEqualsThis);
    }

    /* if (!(o instanceof MyType) return false; */ {
      SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p);
      Eclipse.setGeneratedBy(oRef, source);

      SingleTypeReference typeReference = new SingleTypeReference(typeDecl.name, p);
      Eclipse.setGeneratedBy(typeReference, source);

      InstanceOfExpression instanceOf = new InstanceOfExpression(oRef, typeReference);
      instanceOf.sourceStart = pS;
      instanceOf.sourceEnd = pE;
      Eclipse.setGeneratedBy(instanceOf, source);

      Expression notInstanceOf = new UnaryExpression(instanceOf, OperatorIds.NOT);
      Eclipse.setGeneratedBy(notInstanceOf, source);

      FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
      Eclipse.setGeneratedBy(falseLiteral, source);

      ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE);
      Eclipse.setGeneratedBy(returnFalse, source);

      IfStatement ifNotInstanceOf = new IfStatement(notInstanceOf, returnFalse, pS, pE);
      Eclipse.setGeneratedBy(ifNotInstanceOf, source);
      statements.add(ifNotInstanceOf);
    }

    char[] otherName = "other".toCharArray();

    /* MyType<?> other = (MyType<?>) o; */ {
      if (!fields.isEmpty() || needsCanEqual) {
        LocalDeclaration other = new LocalDeclaration(otherName, pS, pE);
        other.modifiers |= ClassFileConstants.AccFinal;
        Eclipse.setGeneratedBy(other, source);
        char[] typeName = typeDecl.name;
        Expression targetType;
        if (typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0) {
          targetType = new SingleNameReference(((TypeDeclaration) type.get()).name, p);
          Eclipse.setGeneratedBy(targetType, source);
          other.type = new SingleTypeReference(typeName, p);
          Eclipse.setGeneratedBy(other.type, source);
        } else {
          TypeReference[] typeArgs = new TypeReference[typeDecl.typeParameters.length];
          for (int i = 0; i < typeArgs.length; i++) {
            typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
            typeArgs[i].sourceStart = pS;
            typeArgs[i].sourceEnd = pE;
            Eclipse.setGeneratedBy(typeArgs[i], source);
          }
          targetType = new ParameterizedSingleTypeReference(typeName, typeArgs, 0, p);
          Eclipse.setGeneratedBy(targetType, source);
          other.type =
              new ParameterizedSingleTypeReference(typeName, copyTypes(typeArgs, source), 0, p);
          Eclipse.setGeneratedBy(other.type, source);
        }
        NameReference oRef = new SingleNameReference(new char[] {'o'}, p);
        Eclipse.setGeneratedBy(oRef, source);
        other.initialization = new CastExpression(oRef, targetType);
        Eclipse.setGeneratedBy(other.initialization, source);
        statements.add(other);
      }
    }

    /* if (!other.canEqual((java.lang.Object) this)) return false; */ {
      if (needsCanEqual) {
        MessageSend otherCanEqual = new MessageSend();
        otherCanEqual.sourceStart = pS;
        otherCanEqual.sourceEnd = pE;
        Eclipse.setGeneratedBy(otherCanEqual, source);
        otherCanEqual.receiver = new SingleNameReference(otherName, p);
        Eclipse.setGeneratedBy(otherCanEqual.receiver, source);
        otherCanEqual.selector = "canEqual".toCharArray();

        ThisReference thisReference = new ThisReference(pS, pE);
        Eclipse.setGeneratedBy(thisReference, source);
        CastExpression castThisRef =
            new CastExpression(
                thisReference, generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_OBJECT));
        Eclipse.setGeneratedBy(castThisRef, source);
        castThisRef.sourceStart = pS;
        castThisRef.sourceEnd = pE;

        otherCanEqual.arguments = new Expression[] {castThisRef};

        Expression notOtherCanEqual = new UnaryExpression(otherCanEqual, OperatorIds.NOT);
        Eclipse.setGeneratedBy(notOtherCanEqual, source);

        FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
        Eclipse.setGeneratedBy(falseLiteral, source);

        ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE);
        Eclipse.setGeneratedBy(returnFalse, source);

        IfStatement ifNotCanEqual = new IfStatement(notOtherCanEqual, returnFalse, pS, pE);
        Eclipse.setGeneratedBy(ifNotCanEqual, source);

        statements.add(ifNotCanEqual);
      }
    }

    /* if (!super.equals(o)) return false; */
    if (callSuper) {
      MessageSend callToSuper = new MessageSend();
      callToSuper.sourceStart = pS;
      callToSuper.sourceEnd = pE;
      Eclipse.setGeneratedBy(callToSuper, source);
      callToSuper.receiver = new SuperReference(pS, pE);
      Eclipse.setGeneratedBy(callToSuper.receiver, source);
      callToSuper.selector = "equals".toCharArray();
      SingleNameReference oRef = new SingleNameReference(new char[] {'o'}, p);
      Eclipse.setGeneratedBy(oRef, source);
      callToSuper.arguments = new Expression[] {oRef};
      Expression superNotEqual = new UnaryExpression(callToSuper, OperatorIds.NOT);
      Eclipse.setGeneratedBy(superNotEqual, source);
      FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
      Eclipse.setGeneratedBy(falseLiteral, source);
      ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE);
      Eclipse.setGeneratedBy(returnFalse, source);
      IfStatement ifSuperEquals = new IfStatement(superNotEqual, returnFalse, pS, pE);
      Eclipse.setGeneratedBy(ifSuperEquals, source);
      statements.add(ifSuperEquals);
    }

    for (EclipseNode field : fields) {
      TypeReference fType = getFieldType(field, fieldAccess);
      char[] token = fType.getLastToken();
      Expression thisFieldAccessor = createFieldAccessor(field, fieldAccess, source);
      Expression otherFieldAccessor = createFieldAccessor(field, fieldAccess, source, otherName);

      if (fType.dimensions() == 0 && token != null) {
        if (Arrays.equals(TypeConstants.FLOAT, token)) {
          statements.add(
              generateCompareFloatOrDouble(
                  thisFieldAccessor, otherFieldAccessor, "Float".toCharArray(), source));
        } else if (Arrays.equals(TypeConstants.DOUBLE, token)) {
          statements.add(
              generateCompareFloatOrDouble(
                  thisFieldAccessor, otherFieldAccessor, "Double".toCharArray(), source));
        } else if (BUILT_IN_TYPES.contains(new String(token))) {
          EqualExpression fieldsNotEqual =
              new EqualExpression(thisFieldAccessor, otherFieldAccessor, OperatorIds.NOT_EQUAL);
          Eclipse.setGeneratedBy(fieldsNotEqual, source);
          FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
          Eclipse.setGeneratedBy(falseLiteral, source);
          ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE);
          Eclipse.setGeneratedBy(returnStatement, source);
          IfStatement ifStatement = new IfStatement(fieldsNotEqual, returnStatement, pS, pE);
          Eclipse.setGeneratedBy(ifStatement, source);
          statements.add(ifStatement);
        } else /* objects */ {
          NullLiteral nullLiteral = new NullLiteral(pS, pE);
          Eclipse.setGeneratedBy(nullLiteral, source);
          EqualExpression fieldIsNull =
              new EqualExpression(thisFieldAccessor, nullLiteral, OperatorIds.EQUAL_EQUAL);
          nullLiteral = new NullLiteral(pS, pE);
          Eclipse.setGeneratedBy(nullLiteral, source);
          EqualExpression otherFieldIsntNull =
              new EqualExpression(otherFieldAccessor, nullLiteral, OperatorIds.NOT_EQUAL);
          MessageSend equalsCall = new MessageSend();
          equalsCall.sourceStart = pS;
          equalsCall.sourceEnd = pE;
          Eclipse.setGeneratedBy(equalsCall, source);
          equalsCall.receiver = createFieldAccessor(field, fieldAccess, source);
          equalsCall.selector = "equals".toCharArray();
          Expression equalsArg = createFieldAccessor(field, fieldAccess, source, otherName);
          CastExpression castEqualsArg =
              new CastExpression(
                  equalsArg, generateQualifiedNameRef(source, TypeConstants.JAVA_LANG_OBJECT));
          Eclipse.setGeneratedBy(castEqualsArg, source);
          castEqualsArg.sourceStart = pS;
          castEqualsArg.sourceEnd = pE;
          equalsCall.arguments = new Expression[] {castEqualsArg};
          UnaryExpression fieldsNotEqual = new UnaryExpression(equalsCall, OperatorIds.NOT);
          fieldsNotEqual.sourceStart = pS;
          fieldsNotEqual.sourceEnd = pE;
          Eclipse.setGeneratedBy(fieldsNotEqual, source);
          ConditionalExpression fullEquals =
              new ConditionalExpression(fieldIsNull, otherFieldIsntNull, fieldsNotEqual);
          fullEquals.sourceStart = pS;
          fullEquals.sourceEnd = pE;
          Eclipse.setGeneratedBy(fullEquals, source);
          FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
          Eclipse.setGeneratedBy(falseLiteral, source);
          ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE);
          Eclipse.setGeneratedBy(returnStatement, source);
          IfStatement ifStatement = new IfStatement(fullEquals, returnStatement, pS, pE);
          Eclipse.setGeneratedBy(ifStatement, source);
          statements.add(ifStatement);
        }
      } else if (fType.dimensions() > 0 && token != null) {
        MessageSend arraysEqualCall = new MessageSend();
        arraysEqualCall.sourceStart = pS;
        arraysEqualCall.sourceEnd = pE;
        Eclipse.setGeneratedBy(arraysEqualCall, source);
        arraysEqualCall.receiver =
            generateQualifiedNameRef(
                source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray());
        if (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(token))) {
          arraysEqualCall.selector = "deepEquals".toCharArray();
        } else {
          arraysEqualCall.selector = "equals".toCharArray();
        }
        arraysEqualCall.arguments = new Expression[] {thisFieldAccessor, otherFieldAccessor};
        UnaryExpression arraysNotEqual = new UnaryExpression(arraysEqualCall, OperatorIds.NOT);
        arraysNotEqual.sourceStart = pS;
        arraysNotEqual.sourceEnd = pE;
        Eclipse.setGeneratedBy(arraysNotEqual, source);
        FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
        Eclipse.setGeneratedBy(falseLiteral, source);
        ReturnStatement returnStatement = new ReturnStatement(falseLiteral, pS, pE);
        Eclipse.setGeneratedBy(returnStatement, source);
        IfStatement ifStatement = new IfStatement(arraysNotEqual, returnStatement, pS, pE);
        Eclipse.setGeneratedBy(ifStatement, source);
        statements.add(ifStatement);
      }
    }

    /* return true; */ {
      TrueLiteral trueLiteral = new TrueLiteral(pS, pE);
      Eclipse.setGeneratedBy(trueLiteral, source);
      ReturnStatement returnStatement = new ReturnStatement(trueLiteral, pS, pE);
      Eclipse.setGeneratedBy(returnStatement, source);
      statements.add(returnStatement);
    }
    method.statements = statements.toArray(new Statement[statements.size()]);
    return method;
  }
コード例 #20
0
 public TypeReference getTypeReference(int dim) {
   /* build a Reference on a variable that may be qualified or not
    * This variable is a type reference and dim will be its dimensions
    */
   int length = this.identifierLengthStack[this.identifierLengthPtr--];
   if (length < 0) { // flag for precompiled type reference on base types
     TypeReference ref = TypeReference.baseTypeReference(-length, dim);
     ref.sourceStart = this.intStack[this.intPtr--];
     if (dim == 0) {
       ref.sourceEnd = this.intStack[this.intPtr--];
     } else {
       this.intPtr--; // no need to use this position as it is an array
       ref.sourceEnd = this.endPosition;
     }
     if (this.reportReferenceInfo) {
       this.requestor.acceptTypeReference(
           ref.getParameterizedTypeName(), ref.sourceStart, ref.sourceEnd);
     }
     return ref;
   } else {
     int numberOfIdentifiers =
         this.genericsIdentifiersLengthStack[this.genericsIdentifiersLengthPtr--];
     if (length != numberOfIdentifiers || this.genericsLengthStack[this.genericsLengthPtr] != 0) {
       // generic type
       TypeReference ref = getTypeReferenceForGenericType(dim, length, numberOfIdentifiers);
       if (this.reportReferenceInfo) {
         if (length == 1 && numberOfIdentifiers == 1) {
           ParameterizedSingleTypeReference parameterizedSingleTypeReference =
               (ParameterizedSingleTypeReference) ref;
           this.requestor.acceptTypeReference(
               parameterizedSingleTypeReference.token,
               parameterizedSingleTypeReference.sourceStart);
         } else {
           ParameterizedQualifiedTypeReference parameterizedQualifiedTypeReference =
               (ParameterizedQualifiedTypeReference) ref;
           this.requestor.acceptTypeReference(
               parameterizedQualifiedTypeReference.tokens,
               parameterizedQualifiedTypeReference.sourceStart,
               parameterizedQualifiedTypeReference.sourceEnd);
         }
       }
       return ref;
     } else if (length == 1) {
       // single variable reference
       this.genericsLengthPtr--; // pop the 0
       if (dim == 0) {
         SingleTypeReference ref =
             new SingleTypeReference(
                 this.identifierStack[this.identifierPtr],
                 this.identifierPositionStack[this.identifierPtr--]);
         if (this.reportReferenceInfo) {
           this.requestor.acceptTypeReference(ref.token, ref.sourceStart);
         }
         return ref;
       } else {
         ArrayTypeReference ref =
             new ArrayTypeReference(
                 this.identifierStack[this.identifierPtr],
                 dim,
                 this.identifierPositionStack[this.identifierPtr--]);
         ref.sourceEnd = this.endPosition;
         if (this.reportReferenceInfo) {
           this.requestor.acceptTypeReference(ref.token, ref.sourceStart);
         }
         return ref;
       }
     } else { // Qualified variable reference
       this.genericsLengthPtr--;
       char[][] tokens = new char[length][];
       this.identifierPtr -= length;
       long[] positions = new long[length];
       System.arraycopy(this.identifierStack, this.identifierPtr + 1, tokens, 0, length);
       System.arraycopy(
           this.identifierPositionStack, this.identifierPtr + 1, positions, 0, length);
       if (dim == 0) {
         QualifiedTypeReference ref = new QualifiedTypeReference(tokens, positions);
         if (this.reportReferenceInfo) {
           this.requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
         }
         return ref;
       } else {
         ArrayQualifiedTypeReference ref = new ArrayQualifiedTypeReference(tokens, dim, positions);
         ref.sourceEnd = this.endPosition;
         if (this.reportReferenceInfo) {
           this.requestor.acceptTypeReference(ref.tokens, ref.sourceStart, ref.sourceEnd);
         }
         return ref;
       }
     }
   }
 }
コード例 #21
0
  private TypeBinding internalResolveLeafType(
      Scope scope, ReferenceBinding enclosingType, boolean checkBounds) {
    ReferenceBinding currentType;
    if (enclosingType == null) {
      this.resolvedType = scope.getType(this.token);
      if (this.resolvedType.isValidBinding()) {
        currentType = (ReferenceBinding) this.resolvedType;
      } else {
        reportInvalidType(scope);
        switch (this.resolvedType.problemId()) {
          case ProblemReasons.NotFound:
          case ProblemReasons.NotVisible:
          case ProblemReasons.InheritedNameHidesEnclosingName:
            TypeBinding type = this.resolvedType.closestMatch();
            if (type instanceof ReferenceBinding) {
              currentType = (ReferenceBinding) type;
              break;
            }
            // $FALL-THROUGH$ - unable to complete type binding, but still resolve type arguments
          default:
            boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
            int argLength = this.typeArguments.length;
            for (int i = 0; i < argLength; i++) {
              TypeReference typeArgument = this.typeArguments[i];
              if (isClassScope) {
                typeArgument.resolveType((ClassScope) scope);
              } else {
                typeArgument.resolveType((BlockScope) scope, checkBounds);
              }
            }
            return null;
        }
        // be resilient, still attempt resolving arguments
      }
      enclosingType = currentType.enclosingType(); // if member type
      if (enclosingType != null) {
        enclosingType =
            currentType.isStatic()
                ? (ReferenceBinding)
                    scope
                        .environment()
                        .convertToRawType(
                            enclosingType, false /*do not force conversion of enclosing types*/)
                : scope.environment().convertToParameterizedType(enclosingType);
        currentType =
            scope
                .environment()
                .createParameterizedType(
                    (ReferenceBinding) currentType.erasure(), null /* no arg */, enclosingType);
      }
    } else { // resolving member type (relatively to enclosingType)
      this.resolvedType = currentType = scope.getMemberType(this.token, enclosingType);
      if (!this.resolvedType.isValidBinding()) {
        scope.problemReporter().invalidEnclosingType(this, currentType, enclosingType);
        return null;
      }
      if (isTypeUseDeprecated(currentType, scope))
        scope.problemReporter().deprecatedType(currentType, this);
      ReferenceBinding currentEnclosing = currentType.enclosingType();
      if (currentEnclosing != null && currentEnclosing.erasure() != enclosingType.erasure()) {
        enclosingType =
            currentEnclosing; // inherited member type, leave it associated with its enclosing
                              // rather than subtype
      }
    }

    // check generic and arity
    boolean isClassScope = scope.kind == Scope.CLASS_SCOPE;
    TypeReference keep = null;
    if (isClassScope) {
      keep = ((ClassScope) scope).superTypeReference;
      ((ClassScope) scope).superTypeReference = null;
    }
    int argLength = this.typeArguments.length;
    TypeBinding[] argTypes = new TypeBinding[argLength];
    boolean argHasError = false;
    ReferenceBinding currentOriginal = (ReferenceBinding) currentType.original();
    for (int i = 0; i < argLength; i++) {
      TypeReference typeArgument = this.typeArguments[i];
      TypeBinding argType =
          isClassScope
              ? typeArgument.resolveTypeArgument((ClassScope) scope, currentOriginal, i)
              : typeArgument.resolveTypeArgument((BlockScope) scope, currentOriginal, i);
      this.bits |= (typeArgument.bits & ASTNode.HasTypeAnnotations);
      if (argType == null) {
        argHasError = true;
      } else {
        if (typeArgument.annotations != null)
          argTypes[i] =
              captureTypeAnnotations(scope, enclosingType, argType, typeArgument.annotations[0]);
        else argTypes[i] = argType;
      }
    }
    if (argHasError) {
      return null;
    }
    if (isClassScope) {
      ((ClassScope) scope).superTypeReference = keep;
      if (((ClassScope) scope).detectHierarchyCycle(currentOriginal, this)) return null;
    }

    final boolean isDiamond = (this.bits & ASTNode.IsDiamond) != 0;
    TypeVariableBinding[] typeVariables = currentOriginal.typeVariables();
    if (typeVariables == Binding.NO_TYPE_VARIABLES) { // non generic invoked with arguments
      boolean isCompliant15 =
          scope.compilerOptions().originalSourceLevel >= ClassFileConstants.JDK1_5;
      if ((currentOriginal.tagBits & TagBits.HasMissingType) == 0) {
        if (isCompliant15) { // below 1.5, already reported as syntax error
          this.resolvedType = currentType;
          scope
              .problemReporter()
              .nonGenericTypeCannotBeParameterized(0, this, currentType, argTypes);
          return null;
        }
      }
      // resilience do not rebuild a parameterized type unless compliance is allowing it
      if (!isCompliant15) {
        if (!this.resolvedType.isValidBinding()) return currentType;
        return this.resolvedType = currentType;
      }
      // if missing generic type, and compliance >= 1.5, then will rebuild a parameterized binding
    } else if (argLength != typeVariables.length) {
      if (!isDiamond) { // check arity, IsDiamond never set for 1.6-
        scope.problemReporter().incorrectArityForParameterizedType(this, currentType, argTypes);
        return null;
      }
    } else if (!currentType.isStatic()) {
      ReferenceBinding actualEnclosing = currentType.enclosingType();
      if (actualEnclosing != null && actualEnclosing.isRawType()) {
        scope
            .problemReporter()
            .rawMemberTypeCannotBeParameterized(
                this,
                scope.environment().createRawType(currentOriginal, actualEnclosing),
                argTypes);
        return null;
      }
    }

    ParameterizedTypeBinding parameterizedType =
        scope.environment().createParameterizedType(currentOriginal, argTypes, enclosingType);
    // check argument type compatibility for non <> cases - <> case needs no bounds check, we will
    // scream foul if needed during inference.
    if (!isDiamond) {
      if (checkBounds) // otherwise will do it in Scope.connectTypeVariables() or generic method
                       // resolution
      parameterizedType.boundCheck(scope, this.typeArguments);
      else scope.deferBoundCheck(this);
    }
    if (isTypeUseDeprecated(parameterizedType, scope))
      reportDeprecatedType(parameterizedType, scope);

    if (!this.resolvedType.isValidBinding()) {
      return parameterizedType;
    }
    return this.resolvedType = parameterizedType;
  }
コード例 #22
0
  public TypeBinding resolveType(BlockScope scope) {
    // added for code assist...cannot occur with 'normal' code
    if (this.anonymousType == null && this.enclosingInstance == null) {
      return super.resolveType(scope);
    }

    // Propagate the type checking to the arguments, and checks if the constructor is defined.
    // ClassInstanceCreationExpression ::= Primary '.' 'new' SimpleName '(' ArgumentListopt ')'
    // ClassBodyopt
    // ClassInstanceCreationExpression ::= Name '.' 'new' SimpleName '(' ArgumentListopt ')'
    // ClassBodyopt

    this.constant = Constant.NotAConstant;
    TypeBinding enclosingInstanceType = null;
    ReferenceBinding enclosingInstanceReference = null;
    TypeBinding receiverType = null;
    boolean hasError = false;
    boolean enclosingInstanceContainsCast = false;
    boolean argsContainCast = false;

    if (this.enclosingInstance != null) {
      if (this.enclosingInstance instanceof CastExpression) {
        this.enclosingInstance.bits |= ASTNode.DisableUnnecessaryCastCheck; // will check later on
        enclosingInstanceContainsCast = true;
      }
      if ((enclosingInstanceType = this.enclosingInstance.resolveType(scope)) == null) {
        hasError = true;
      } else if (enclosingInstanceType.isBaseType() || enclosingInstanceType.isArrayType()) {
        scope
            .problemReporter()
            .illegalPrimitiveOrArrayTypeForEnclosingInstance(
                enclosingInstanceType, this.enclosingInstance);
        hasError = true;
      } else if (this.type instanceof QualifiedTypeReference) {
        scope
            .problemReporter()
            .illegalUsageOfQualifiedTypeReference((QualifiedTypeReference) this.type);
        hasError = true;
      } else if (!(enclosingInstanceReference = (ReferenceBinding) enclosingInstanceType)
          .canBeSeenBy(scope)) {
        // https://bugs.eclipse.org/bugs/show_bug.cgi?id=317212
        enclosingInstanceType =
            new ProblemReferenceBinding(
                enclosingInstanceReference.compoundName,
                enclosingInstanceReference,
                ProblemReasons.NotVisible);
        scope.problemReporter().invalidType(this.enclosingInstance, enclosingInstanceType);
        hasError = true;
      } else {
        receiverType =
            ((SingleTypeReference) this.type)
                .resolveTypeEnclosing(scope, (ReferenceBinding) enclosingInstanceType);
        if (receiverType != null && enclosingInstanceContainsCast) {
          CastExpression.checkNeedForEnclosingInstanceCast(
              scope, this.enclosingInstance, enclosingInstanceType, receiverType);
        }
      }
    } else {
      if (this.type == null) {
        // initialization of an enum constant
        receiverType = scope.enclosingSourceType();
      } else {
        receiverType = this.type.resolveType(scope, true /* check bounds*/);
        checkParameterizedAllocation:
        {
          if (receiverType == null || !receiverType.isValidBinding())
            break checkParameterizedAllocation;
          if (this.type
              instanceof
              ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>()
            ReferenceBinding currentType = (ReferenceBinding) receiverType;
            do {
              // isStatic() is answering true for toplevel types
              if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0)
                break checkParameterizedAllocation;
              if (currentType.isRawType()) break checkParameterizedAllocation;
            } while ((currentType = currentType.enclosingType()) != null);
            ParameterizedQualifiedTypeReference qRef =
                (ParameterizedQualifiedTypeReference) this.type;
            for (int i = qRef.typeArguments.length - 2; i >= 0; i--) {
              if (qRef.typeArguments[i] != null) {
                scope
                    .problemReporter()
                    .illegalQualifiedParameterizedTypeAllocation(this.type, receiverType);
                break;
              }
            }
          }
        }
      }
    }
    if (receiverType == null || !receiverType.isValidBinding()) {
      hasError = true;
    }

    // resolve type arguments (for generic constructor call)
    final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0;
    if (this.typeArguments != null) {
      int length = this.typeArguments.length;
      boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5;
      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 (isDiamond) {
        scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments);
        return null;
      }
      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) {
      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) {
          hasError = true;
        }
      }
    }

    // limit of fault-tolerance
    if (hasError) {
      /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case.
        No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do
        not return the partially resolved type.
      */
      if (isDiamond) {
        return null; // not the partially cooked this.resolvedType
      }
      if (receiverType instanceof ReferenceBinding) {
        ReferenceBinding referenceReceiver = (ReferenceBinding) receiverType;
        if (receiverType.isValidBinding()) {
          // record a best guess, for clients who need hint about possible contructor match
          int length = this.arguments == null ? 0 : this.arguments.length;
          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 = scope.findMethod(referenceReceiver, TypeConstants.INIT, 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;
              }
            }
          }
        }
        if (this.anonymousType != null) {
          // insert anonymous type in scope (see
          // https://bugs.eclipse.org/bugs/show_bug.cgi?id=210070)
          scope.addAnonymousType(this.anonymousType, referenceReceiver);
          this.anonymousType.resolve(scope);
          return this.resolvedType = this.anonymousType.binding;
        }
      }
      return this.resolvedType = receiverType;
    }
    if (this.anonymousType == null) {
      // qualified allocation with no anonymous type
      if (!receiverType.canBeInstantiated()) {
        scope.problemReporter().cannotInstantiate(this.type, receiverType);
        return this.resolvedType = receiverType;
      }
      if (isDiamond) {
        TypeBinding[] inferredTypes =
            inferElidedTypes(
                ((ParameterizedTypeBinding) receiverType).genericType(),
                receiverType.enclosingType(),
                argumentTypes,
                scope);
        if (inferredTypes == null) {
          scope.problemReporter().cannotInferElidedTypes(this);
          return this.resolvedType = null;
        }
        receiverType =
            this.type.resolvedType =
                scope
                    .environment()
                    .createParameterizedType(
                        ((ParameterizedTypeBinding) receiverType).genericType(),
                        inferredTypes,
                        ((ParameterizedTypeBinding) receiverType).enclosingType());
      }
      ReferenceBinding allocationType = (ReferenceBinding) receiverType;
      if ((this.binding = scope.getConstructor(allocationType, argumentTypes, this))
          .isValidBinding()) {
        if (isMethodUseDeprecated(this.binding, scope, true)) {
          scope.problemReporter().deprecatedMethod(this.binding, this);
        }
        if (checkInvocationArguments(
            scope,
            null,
            allocationType,
            this.binding,
            this.arguments,
            argumentTypes,
            argsContainCast,
            this)) {
          this.bits |= ASTNode.Unchecked;
        }
        if (this.typeArguments != null
            && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
          scope
              .problemReporter()
              .unnecessaryTypeArgumentsForMethodInvocation(
                  this.binding, this.genericTypeArguments, this.typeArguments);
        }
      } else {
        if (this.binding.declaringClass == null) {
          this.binding.declaringClass = allocationType;
        }
        if (this.type != null && !this.type.resolvedType.isValidBinding()) {
          // problem already got signaled on type reference, do not report secondary problem
          return null;
        }
        scope.problemReporter().invalidConstructor(this, this.binding);
        return this.resolvedType = receiverType;
      }
      if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
        scope.problemReporter().missingTypeInConstructor(this, this.binding);
      }
      if (!isDiamond && receiverType.isParameterizedTypeWithActualArguments()) {
        checkTypeArgumentRedundancy(
            (ParameterizedTypeBinding) receiverType,
            receiverType.enclosingType(),
            argumentTypes,
            scope);
      }
      // The enclosing instance must be compatible with the innermost enclosing type
      ReferenceBinding expectedType = this.binding.declaringClass.enclosingType();
      if (expectedType
          != enclosingInstanceType) // must call before computeConversion() and typeMismatchError()
      scope.compilationUnitScope().recordTypeConversion(expectedType, enclosingInstanceType);
      if (enclosingInstanceType.isCompatibleWith(expectedType)
          || scope.isBoxingCompatibleWith(enclosingInstanceType, expectedType)) {
        this.enclosingInstance.computeConversion(scope, expectedType, enclosingInstanceType);
        return this.resolvedType = receiverType;
      }
      scope
          .problemReporter()
          .typeMismatchError(enclosingInstanceType, expectedType, this.enclosingInstance, null);
      return this.resolvedType = receiverType;
    } else {
      if (isDiamond) {
        scope.problemReporter().diamondNotWithAnoymousClasses(this.type);
        return null;
      }
    }
    ReferenceBinding superType = (ReferenceBinding) receiverType;
    if (superType.isTypeVariable()) {
      superType =
          new ProblemReferenceBinding(
              new char[][] {superType.sourceName()},
              superType,
              ProblemReasons.IllegalSuperTypeVariable);
      scope.problemReporter().invalidType(this, superType);
      return null;
    } else if (this.type != null && superType.isEnum()) { // tolerate enum constant body
      scope.problemReporter().cannotInstantiate(this.type, superType);
      return this.resolvedType = superType;
    }
    // anonymous type scenario
    // an anonymous class inherits from java.lang.Object when declared "after" an interface
    ReferenceBinding anonymousSuperclass =
        superType.isInterface() ? scope.getJavaLangObject() : superType;
    // insert anonymous type in scope
    scope.addAnonymousType(this.anonymousType, superType);
    this.anonymousType.resolve(scope);

    // find anonymous super constructor
    this.resolvedType = this.anonymousType.binding; // 1.2 change
    if ((this.resolvedType.tagBits & TagBits.HierarchyHasProblems) != 0) {
      return null; // stop secondary errors
    }
    MethodBinding inheritedBinding = scope.getConstructor(anonymousSuperclass, argumentTypes, this);
    if (!inheritedBinding.isValidBinding()) {
      if (inheritedBinding.declaringClass == null) {
        inheritedBinding.declaringClass = anonymousSuperclass;
      }
      if (this.type != null && !this.type.resolvedType.isValidBinding()) {
        // problem already got signaled on type reference, do not report secondary problem
        return null;
      }
      scope.problemReporter().invalidConstructor(this, inheritedBinding);
      return this.resolvedType;
    }
    if ((inheritedBinding.tagBits & TagBits.HasMissingType) != 0) {
      scope.problemReporter().missingTypeInConstructor(this, inheritedBinding);
    }
    if (this.enclosingInstance != null) {
      ReferenceBinding targetEnclosing = inheritedBinding.declaringClass.enclosingType();
      if (targetEnclosing == null) {
        scope
            .problemReporter()
            .unnecessaryEnclosingInstanceSpecification(this.enclosingInstance, superType);
        return this.resolvedType;
      } else if (!enclosingInstanceType.isCompatibleWith(targetEnclosing)
          && !scope.isBoxingCompatibleWith(enclosingInstanceType, targetEnclosing)) {
        scope
            .problemReporter()
            .typeMismatchError(
                enclosingInstanceType, targetEnclosing, this.enclosingInstance, null);
        return this.resolvedType;
      }
      this.enclosingInstance.computeConversion(scope, targetEnclosing, enclosingInstanceType);
    }
    if (this.arguments != null) {
      if (checkInvocationArguments(
          scope,
          null,
          anonymousSuperclass,
          inheritedBinding,
          this.arguments,
          argumentTypes,
          argsContainCast,
          this)) {
        this.bits |= ASTNode.Unchecked;
      }
    }
    if (this.typeArguments != null
        && inheritedBinding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
      scope
          .problemReporter()
          .unnecessaryTypeArgumentsForMethodInvocation(
              inheritedBinding, this.genericTypeArguments, this.typeArguments);
    }
    // Update the anonymous inner class : superclass, interface
    this.binding =
        this.anonymousType.createDefaultConstructorWithBinding(
            inheritedBinding,
            (this.bits & ASTNode.Unchecked) != 0 && this.genericTypeArguments == null);
    return this.resolvedType;
  }
コード例 #23
0
 public ClassLiteralAccess(int sourceEnd, TypeReference type) {
   this.type = type;
   type.bits |= IgnoreRawTypeCheck; // no need to worry about raw type usage
   this.sourceStart = type.sourceStart;
   this.sourceEnd = sourceEnd;
 }
コード例 #24
0
ファイル: JsniReferenceResolver.java プロジェクト: qffan/gwt
 private boolean containsLong(final TypeReference type, ClassScope scope) {
   return type != null && JsniReferenceResolver.this.containsLong(type.resolveType(scope));
 }
コード例 #25
0
ファイル: JsniReferenceResolver.java プロジェクト: qffan/gwt
 private String typeString(TypeReference type) {
   return type.toString();
 }
コード例 #26
0
  public TypeBinding resolveType(BlockScope scope) {

    // Build an array type reference using the current dimensions
    // The parser does not check for the fact that dimension may be null
    // only at the -end- like new int [4][][]. The parser allows new int[][4][]
    // so this must be checked here......(this comes from a reduction to LL1 grammar)

    TypeBinding referenceType = type.resolveType(scope, true /* check bounds*/);

    // will check for null after dimensions are checked
    constant = Constant.NotAConstant;
    if (referenceType == VoidBinding) {
      scope.problemReporter().cannotAllocateVoidArray(this);
      referenceType = null;
    }

    // check the validity of the dimension syntax (and test for all null dimensions)
    int explicitDimIndex = -1;
    loop:
    for (int i = dimensions.length; --i >= 0; ) {
      if (dimensions[i] != null) {
        if (explicitDimIndex < 0) explicitDimIndex = i;
      } else if (explicitDimIndex > 0) {
        // should not have an empty dimension before an non-empty one
        scope.problemReporter().incorrectLocationForNonEmptyDimension(this, explicitDimIndex);
        break loop;
      }
    }

    // explicitDimIndex < 0 says if all dimensions are nulled
    // when an initializer is given, no dimension must be specified
    if (initializer == null) {
      if (explicitDimIndex < 0) {
        scope.problemReporter().mustDefineDimensionsOrInitializer(this);
      }
      // allow new List<?>[5] - only check for generic array when no initializer, since also checked
      // inside initializer resolution
      if (referenceType != null && !referenceType.isReifiable()) {
        scope.problemReporter().illegalGenericArray(referenceType, this);
      }
    } else if (explicitDimIndex >= 0) {
      scope.problemReporter().cannotDefineDimensionsAndInitializer(this);
    }

    // dimensions resolution
    for (int i = 0; i <= explicitDimIndex; i++) {
      if (dimensions[i] != null) {
        TypeBinding dimensionType = dimensions[i].resolveTypeExpecting(scope, IntBinding);
        if (dimensionType != null) {
          dimensions[i].computeConversion(scope, IntBinding, dimensionType);
        }
      }
    }

    // building the array binding
    if (referenceType != null) {
      if (dimensions.length > 255) {
        scope.problemReporter().tooManyDimensions(this);
      }
      this.resolvedType = scope.createArrayType(referenceType, dimensions.length);

      // check the initializer
      if (initializer != null) {
        if ((initializer.resolveTypeExpecting(scope, this.resolvedType)) != null)
          initializer.binding = (ArrayBinding) this.resolvedType;
      }
    }
    return this.resolvedType;
  }
コード例 #27
0
  public TypeBinding resolveType(BlockScope scope) {
    // Propagate the type checking to the arguments, and check if the constructor is defined.
    this.constant = Constant.NotAConstant;
    if (this.type == null) {
      // initialization of an enum constant
      this.resolvedType = scope.enclosingReceiverType();
    } else {
      this.resolvedType = this.type.resolveType(scope, true /* check bounds*/);
      checkParameterizedAllocation:
      {
        if (this.type
            instanceof ParameterizedQualifiedTypeReference) { // disallow new X<String>.Y<Integer>()
          ReferenceBinding currentType = (ReferenceBinding) this.resolvedType;
          if (currentType == null) return currentType;
          do {
            // isStatic() is answering true for toplevel types
            if ((currentType.modifiers & ClassFileConstants.AccStatic) != 0)
              break checkParameterizedAllocation;
            if (currentType.isRawType()) break checkParameterizedAllocation;
          } while ((currentType = currentType.enclosingType()) != null);
          ParameterizedQualifiedTypeReference qRef =
              (ParameterizedQualifiedTypeReference) this.type;
          for (int i = qRef.typeArguments.length - 2; i >= 0; i--) {
            if (qRef.typeArguments[i] != null) {
              scope
                  .problemReporter()
                  .illegalQualifiedParameterizedTypeAllocation(this.type, this.resolvedType);
              break;
            }
          }
        }
      }
    }
    // will check for null after args are resolved

    final boolean isDiamond = this.type != null && (this.type.bits & ASTNode.IsDiamond) != 0;
    // resolve type arguments (for generic constructor call)
    if (this.typeArguments != null) {
      int length = this.typeArguments.length;
      boolean argHasError = scope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5;
      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 (isDiamond) {
        scope.problemReporter().diamondNotWithExplicitTypeArguments(this.typeArguments);
        return null;
      }
      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;
      }
    }

    // buffering the arguments' types
    boolean argsContainCast = false;
    TypeBinding[] argumentTypes = Binding.NO_PARAMETERS;
    if (this.arguments != null) {
      boolean argHasError = false;
      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] = argument.resolveType(scope)) == null) {
          argHasError = true;
        }
      }
      if (argHasError) {
        /* https://bugs.eclipse.org/bugs/show_bug.cgi?id=345359, if arguments have errors, completely bail out in the <> case.
          No meaningful type resolution is possible since inference of the elided types is fully tied to argument types. Do
          not return the partially resolved type.
        */
        if (isDiamond) {
          return null; // not the partially cooked this.resolvedType
        }
        if (this.resolvedType instanceof ReferenceBinding) {
          // record a best guess, for clients who need hint about possible constructor 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 =
              scope.findMethod(
                  (ReferenceBinding) this.resolvedType, TypeConstants.INIT, 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 this.resolvedType;
      }
    }
    if (this.resolvedType == null || !this.resolvedType.isValidBinding()) {
      return null;
    }

    // null type denotes fake allocation for enum constant inits
    if (this.type != null && !this.resolvedType.canBeInstantiated()) {
      scope.problemReporter().cannotInstantiate(this.type, this.resolvedType);
      return this.resolvedType;
    }
    if (isDiamond) {
      TypeBinding[] inferredTypes =
          inferElidedTypes(
              ((ParameterizedTypeBinding) this.resolvedType).genericType(),
              null,
              argumentTypes,
              scope);
      if (inferredTypes == null) {
        scope.problemReporter().cannotInferElidedTypes(this);
        return this.resolvedType = null;
      }
      this.resolvedType =
          this.type.resolvedType =
              scope
                  .environment()
                  .createParameterizedType(
                      ((ParameterizedTypeBinding) this.resolvedType).genericType(),
                      inferredTypes,
                      ((ParameterizedTypeBinding) this.resolvedType).enclosingType());
    }
    ReferenceBinding allocationType = (ReferenceBinding) this.resolvedType;
    if (!(this.binding = scope.getConstructor(allocationType, argumentTypes, this))
        .isValidBinding()) {
      if (this.binding.declaringClass == null) {
        this.binding.declaringClass = allocationType;
      }
      if (this.type != null && !this.type.resolvedType.isValidBinding()) {
        return null;
      }
      scope.problemReporter().invalidConstructor(this, this.binding);
      return this.resolvedType;
    }
    if ((this.binding.tagBits & TagBits.HasMissingType) != 0) {
      scope.problemReporter().missingTypeInConstructor(this, this.binding);
    }
    if (isMethodUseDeprecated(this.binding, scope, true))
      scope.problemReporter().deprecatedMethod(this.binding, this);
    if (checkInvocationArguments(
        scope,
        null,
        allocationType,
        this.binding,
        this.arguments,
        argumentTypes,
        argsContainCast,
        this)) {
      this.bits |= ASTNode.Unchecked;
    }
    if (this.typeArguments != null
        && this.binding.original().typeVariables == Binding.NO_TYPE_VARIABLES) {
      scope
          .problemReporter()
          .unnecessaryTypeArgumentsForMethodInvocation(
              this.binding, this.genericTypeArguments, this.typeArguments);
    }
    if (!isDiamond && this.resolvedType.isParameterizedTypeWithActualArguments()) {
      checkTypeArgumentRedundancy(
          (ParameterizedTypeBinding) this.resolvedType, null, argumentTypes, scope);
    }
    final CompilerOptions compilerOptions = scope.compilerOptions();
    if (compilerOptions.isAnnotationBasedNullAnalysisEnabled
        && (this.binding.tagBits & TagBits.IsNullnessKnown) == 0) {
      new ImplicitNullAnnotationVerifier(
              scope.environment(), compilerOptions.inheritNullAnnotations)
          .checkImplicitNullAnnotations(this.binding, null /*srcMethod*/, false, scope);
    }
    return allocationType;
  }
コード例 #28
0
ファイル: ASTNode.java プロジェクト: beefeather/ohl
 /** Figures if @Deprecated annotation is specified, do not resolve entire annotations. */
 public static void resolveDeprecatedAnnotations(
     BlockScope scope, Annotation[] annotations, Binding recipient) {
   if (recipient != null) {
     int kind = recipient.kind();
     if (annotations != null) {
       int length;
       if ((length = annotations.length) >= 0) {
         switch (kind) {
           case Binding.PACKAGE:
             PackageBinding packageBinding = (PackageBinding) recipient;
             if ((packageBinding.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return;
             break;
           case Binding.TYPE:
           case Binding.GENERIC_TYPE:
             ReferenceBinding type = (ReferenceBinding) recipient;
             if ((type.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return;
             break;
           case Binding.METHOD:
             MethodBinding method = (MethodBinding) recipient;
             if ((method.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return;
             break;
           case Binding.FIELD:
             FieldBinding field = (FieldBinding) recipient;
             if ((field.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return;
             break;
           case Binding.LOCAL:
             LocalVariableBinding local = (LocalVariableBinding) recipient;
             if ((local.tagBits & TagBits.DeprecatedAnnotationResolved) != 0) return;
             break;
           default:
             return;
         }
         for (int i = 0; i < length; i++) {
           TypeReference annotationTypeRef = annotations[i].type;
           // only resolve type name if 'Deprecated' last token
           if (!CharOperation.equals(
               TypeConstants.JAVA_LANG_DEPRECATED[2], annotationTypeRef.getLastToken())) return;
           TypeBinding annotationType = annotations[i].type.resolveType(scope);
           if (annotationType != null
               && annotationType.isValidBinding()
               && annotationType.id == TypeIds.T_JavaLangDeprecated) {
             switch (kind) {
               case Binding.PACKAGE:
                 PackageBinding packageBinding = (PackageBinding) recipient;
                 packageBinding.tagBits |=
                     (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
                 return;
               case Binding.TYPE:
               case Binding.GENERIC_TYPE:
               case Binding.TYPE_PARAMETER:
                 ReferenceBinding type = (ReferenceBinding) recipient;
                 type.tagBits |=
                     (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
                 return;
               case Binding.METHOD:
                 MethodBinding method = (MethodBinding) recipient;
                 method.tagBits |=
                     (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
                 return;
               case Binding.FIELD:
                 FieldBinding field = (FieldBinding) recipient;
                 field.tagBits |=
                     (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
                 return;
               case Binding.LOCAL:
                 LocalVariableBinding local = (LocalVariableBinding) recipient;
                 local.tagBits |=
                     (TagBits.AnnotationDeprecated | TagBits.DeprecatedAnnotationResolved);
                 return;
               default:
                 return;
             }
           }
         }
       }
     }
     switch (kind) {
       case Binding.PACKAGE:
         PackageBinding packageBinding = (PackageBinding) recipient;
         packageBinding.tagBits |= TagBits.DeprecatedAnnotationResolved;
         return;
       case Binding.TYPE:
       case Binding.GENERIC_TYPE:
       case Binding.TYPE_PARAMETER:
         ReferenceBinding type = (ReferenceBinding) recipient;
         type.tagBits |= TagBits.DeprecatedAnnotationResolved;
         return;
       case Binding.METHOD:
         MethodBinding method = (MethodBinding) recipient;
         method.tagBits |= TagBits.DeprecatedAnnotationResolved;
         return;
       case Binding.FIELD:
         FieldBinding field = (FieldBinding) recipient;
         field.tagBits |= TagBits.DeprecatedAnnotationResolved;
         return;
       case Binding.LOCAL:
         LocalVariableBinding local = (LocalVariableBinding) recipient;
         local.tagBits |= TagBits.DeprecatedAnnotationResolved;
         return;
       default:
         return;
     }
   }
 }
コード例 #29
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;
  }