Пример #1
0
  protected void consumeMethodInvocationName() {
    // MethodInvocation ::= Name '(' ArgumentListopt ')'

    if (this.scanner.startPosition >= this.codeSnippetStart
        && this.scanner.startPosition <= this.codeSnippetEnd + 1 + this.lineSeparatorLength // 14838
        && isTopLevelType()) {

      // when the name is only an identifier...we have a message send to "this" (implicit)

      MessageSend m = newMessageSend();
      m.sourceEnd = this.rParenPos;
      m.sourceStart =
          (int) ((m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr]) >>> 32);
      m.selector = this.identifierStack[this.identifierPtr--];
      if (this.identifierLengthStack[this.identifierLengthPtr] == 1) {
        m.receiver = new CodeSnippetThisReference(0, 0, this.evaluationContext, true);
        this.identifierLengthPtr--;
      } else {
        this.identifierLengthStack[this.identifierLengthPtr]--;
        m.receiver = getUnspecifiedReference();
        m.sourceStart = m.receiver.sourceStart;
      }
      pushOnExpressionStack(m);
    } else {
      super.consumeMethodInvocationName();
    }
  }
 @Override
 public boolean checkVisibility(MethodSpec spec, ReferenceBinding baseType) {
   if (!super.checkVisibility(spec, baseType)) return false;
   if (isReplaceCallin()) {
     // create a faked invocationSite:
     MessageSend anticipatedBaseCall = new MessageSend();
     anticipatedBaseCall.receiver =
         new SingleNameReference("<fake>".toCharArray(), 0); // $NON-NLS-1$
     anticipatedBaseCall.receiver.resolvedType = anticipatedBaseCall.actualReceiverType = baseType;
     if (!spec.resolvedMethod.canBeSeenBy(baseType, anticipatedBaseCall, this.scope.classScope())
         && (spec.resolvedMethod.modifiers & ClassFileConstants.AccProtected)
             == 0) // protected is not a warning
     this.scope.problemReporter().callinDecapsulation(spec, this.scope);
   }
   return true;
 }
Пример #3
0
 private IfStatement generateCompareFloatOrDouble(
     Expression thisRef, Expression otherRef, char[] floatOrDouble, ASTNode source) {
   int pS = source.sourceStart, pE = source.sourceEnd;
   /* if (Float.compare(fieldName, other.fieldName) != 0) return false */
   MessageSend floatCompare = new MessageSend();
   floatCompare.sourceStart = pS;
   floatCompare.sourceEnd = pE;
   Eclipse.setGeneratedBy(floatCompare, source);
   floatCompare.receiver =
       generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.LANG, floatOrDouble);
   floatCompare.selector = "compare".toCharArray();
   floatCompare.arguments = new Expression[] {thisRef, otherRef};
   IntLiteral int0 = new IntLiteral(new char[] {'0'}, pS, pE);
   Eclipse.setGeneratedBy(int0, source);
   EqualExpression ifFloatCompareIsNot0 =
       new EqualExpression(floatCompare, int0, OperatorIds.NOT_EQUAL);
   ifFloatCompareIsNot0.sourceStart = pS;
   ifFloatCompareIsNot0.sourceEnd = pE;
   Eclipse.setGeneratedBy(ifFloatCompareIsNot0, source);
   FalseLiteral falseLiteral = new FalseLiteral(pS, pE);
   Eclipse.setGeneratedBy(falseLiteral, source);
   ReturnStatement returnFalse = new ReturnStatement(falseLiteral, pS, pE);
   Eclipse.setGeneratedBy(returnFalse, source);
   IfStatement ifStatement = new IfStatement(ifFloatCompareIsNot0, returnFalse, pS, pE);
   Eclipse.setGeneratedBy(ifStatement, source);
   return ifStatement;
 }
Пример #4
0
  protected void consumeMethodInvocationSuper() {
    // MethodInvocation ::= 'super' '.' 'Identifier' '(' ArgumentListopt ')'

    MessageSend m = newMessageSend();
    m.sourceStart = this.intStack[this.intPtr--];
    m.sourceEnd = this.rParenPos;
    m.nameSourcePosition = this.identifierPositionStack[this.identifierPtr];
    m.selector = this.identifierStack[this.identifierPtr--];
    this.identifierLengthPtr--;
    m.receiver =
        new CodeSnippetSuperReference(m.sourceStart, this.endPosition, this.evaluationContext);
    pushOnExpressionStack(m);
  }
Пример #5
0
  public TypeBinding resolveType(BlockScope scope) {
    // compute a new constant if the cast is effective

    this.constant = Constant.NotAConstant;
    this.implicitConversion = TypeIds.T_undefined;

    boolean exprContainCast = false;

    TypeBinding castType = this.resolvedType = this.type.resolveType(scope);
    if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_8) {
      this.expression.setExpressionContext(CASTING_CONTEXT);
      if (this.expression instanceof FunctionalExpression) {
        this.expression.setExpectedType(this.resolvedType);
        this.bits |= ASTNode.DisableUnnecessaryCastCheck;
      }
    }
    if (this.expression instanceof CastExpression) {
      this.expression.bits |= ASTNode.DisableUnnecessaryCastCheck;
      exprContainCast = true;
    }
    TypeBinding expressionType = this.expression.resolveType(scope);
    if (this.expression instanceof MessageSend) {
      MessageSend messageSend = (MessageSend) this.expression;
      MethodBinding methodBinding = messageSend.binding;
      if (methodBinding != null && methodBinding.isPolymorphic()) {
        messageSend.binding =
            scope
                .environment()
                .updatePolymorphicMethodReturnType(
                    (PolymorphicMethodBinding) methodBinding, castType);
        if (TypeBinding.notEquals(expressionType, castType)) {
          expressionType = castType;
          this.bits |= ASTNode.DisableUnnecessaryCastCheck;
        }
      }
    }
    if (castType != null) {
      if (expressionType != null) {

        boolean nullAnnotationMismatch =
            scope.compilerOptions().isAnnotationBasedNullAnalysisEnabled
                && NullAnnotationMatching.analyse(castType, expressionType, -1).isAnyMismatch();

        boolean isLegal =
            checkCastTypesCompatibility(scope, castType, expressionType, this.expression);
        if (isLegal) {
          this.expression.computeConversion(scope, castType, expressionType);
          if ((this.bits & ASTNode.UnsafeCast) != 0) { // unsafe cast
            if (scope.compilerOptions().reportUnavoidableGenericTypeProblems
                || !(expressionType.isRawType()
                    && this.expression.forcedToBeRaw(scope.referenceContext()))) {
              scope.problemReporter().unsafeCast(this, scope);
            }
          } else if (nullAnnotationMismatch) {
            // report null annotation issue at medium priority
            scope.problemReporter().unsafeNullnessCast(this, scope);
          } else {
            if (castType.isRawType()
                && scope.compilerOptions().getSeverity(CompilerOptions.RawTypeReference)
                    != ProblemSeverities.Ignore) {
              scope.problemReporter().rawTypeReference(this.type, castType);
            }
            if ((this.bits & (ASTNode.UnnecessaryCast | ASTNode.DisableUnnecessaryCastCheck))
                == ASTNode.UnnecessaryCast) { // unnecessary cast
              if (!isIndirectlyUsed()) // used for generic type inference or boxing ?
              scope.problemReporter().unnecessaryCast(this);
            }
          }
        } else { // illegal cast
          if ((castType.tagBits & TagBits.HasMissingType) == 0) { // no complaint if secondary error
            scope.problemReporter().typeCastError(this, castType, expressionType);
          }
          this.bits |= ASTNode.DisableUnnecessaryCastCheck; // disable further secondary diagnosis
        }
      }
      this.resolvedType =
          castType.capture(
              scope,
              this.type.sourceStart,
              this.type
                  .sourceEnd); // make it unique, a cast expression shares source end with the
                               // expression.
      if (exprContainCast) {
        checkNeedForCastCast(scope, this);
      }
    }
    return this.resolvedType;
  }
 /** Returns whether the code gen will use an invoke virtual for this message send or not. */
 protected boolean isVirtualInvoke(MethodBinding method, MessageSend messageSend) {
   return !method.isStatic() && !method.isPrivate() && !messageSend.isSuperAccess();
 }
Пример #7
0
  public static TypeBinding resolveType(
      TypeBinding resolvedType, MessageSend methodCall, BlockScope scope) {
    List<Extension> extensions = new ArrayList<Extension>();
    TypeDeclaration decl = scope.classScope().referenceContext;

    EclipseNode owningType = null;

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

    boolean skip = false;

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

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

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

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

    MessageSend_postponedErrors.clear(methodCall);
    return resolvedType;
  }
Пример #8
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;
  }
Пример #9
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;
  }
Пример #10
0
  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;
  }