public void manageSyntheticAccessIfNecessary(BlockScope currentScope, FlowInfo flowInfo) {
    if ((flowInfo.tagBits & FlowInfo.UNREACHABLE_OR_DEAD) == 0) {
      // need assertion flag: $assertionsDisabled on outer most source clas
      // (in case of static member of interface, will use the outermost static member - bug 22334)
      SourceTypeBinding outerMostClass = currentScope.enclosingSourceType();
      while (outerMostClass.isLocalType()) {
        ReferenceBinding enclosing = outerMostClass.enclosingType();
        if (enclosing == null || enclosing.isInterface()) break;
        outerMostClass = (SourceTypeBinding) enclosing;
      }
      this.assertionSyntheticFieldBinding = outerMostClass.addSyntheticFieldForAssert(currentScope);

      // find <clinit> and enable assertion support
      TypeDeclaration typeDeclaration = outerMostClass.scope.referenceType();
      AbstractMethodDeclaration[] methods = typeDeclaration.methods;
      for (int i = 0, max = methods.length; i < max; i++) {
        AbstractMethodDeclaration method = methods[i];
        if (method.isClinit()) {
          ((Clinit) method)
              .setAssertionSupport(
                  this.assertionSyntheticFieldBinding,
                  currentScope.compilerOptions().sourceLevel < ClassFileConstants.JDK1_5);
          break;
        }
      }
    }
  }
  private TypeBinding getTypeFromSignature(String typeSignature, Scope scope) {
    TypeBinding assignableTypeBinding = null;

    TypeVariableBinding[] typeVariables = Binding.NO_TYPE_VARIABLES;
    ReferenceContext referenceContext = scope.referenceContext();
    if (referenceContext instanceof AbstractMethodDeclaration) {
      AbstractMethodDeclaration methodDeclaration = (AbstractMethodDeclaration) referenceContext;
      TypeParameter[] typeParameters = methodDeclaration.typeParameters();
      if (typeParameters != null && typeParameters.length > 0) {
        int length = typeParameters.length;
        int count = 0;
        typeVariables = new TypeVariableBinding[length];
        for (int i = 0; i < length; i++) {
          if (typeParameters[i].binding != null) {
            typeVariables[count++] = typeParameters[i].binding;
          }
        }

        if (count != length) {
          System.arraycopy(
              typeVariables, 0, typeVariables = new TypeVariableBinding[count], 0, count);
        }
      }
    }

    CompilationUnitDeclaration previousUnitBeingCompleted =
        this.lookupEnvironment.unitBeingCompleted;
    this.lookupEnvironment.unitBeingCompleted = this.compilationUnitDeclaration;
    // {ObjectTeams: protect call into the compiler
    /* orig:
    try {
    :giro */
    try (Config config =
        Dependencies.setup(this, this.parser, this.lookupEnvironment, true, true)) {
      // orig:

      SignatureWrapper wrapper =
          new SignatureWrapper(replacePackagesDot(typeSignature.toCharArray()));
      // FIXME(stephan): do we interpret type annotations here?
      assignableTypeBinding =
          this.lookupEnvironment.getTypeFromTypeSignature(
              wrapper,
              typeVariables,
              this.assistScope.enclosingClassScope().referenceContext.binding,
              null,
              ITypeAnnotationWalker.EMPTY_ANNOTATION_WALKER);
      assignableTypeBinding =
          BinaryTypeBinding.resolveType(assignableTypeBinding, this.lookupEnvironment, true);
    } catch (AbortCompilation e) {
      assignableTypeBinding = null;
    } finally {
      this.lookupEnvironment.unitBeingCompleted = previousUnitBeingCompleted;
    }
    return assignableTypeBinding;
  }
    @Override
    public void process(CompilationUnitDeclaration cud, int i) {
      super.process(cud, i);
      ClassFile[] classFiles = cud.compilationResult().getClassFiles();
      Map<ClassFile, CompiledClass> results = new LinkedHashMap<ClassFile, CompiledClass>();
      for (ClassFile classFile : classFiles) {
        createCompiledClass(classFile, results);
      }
      List<CompiledClass> compiledClasses = new ArrayList<CompiledClass>(results.values());
      addBinaryTypes(compiledClasses);

      ICompilationUnit icu = cud.compilationResult().compilationUnit;
      Adapter adapter = (Adapter) icu;
      CompilationUnitBuilder builder = adapter.getBuilder();

      // TODO this code was added for the arquillian gwt extension
      if (cud.types != null) {
        for (TypeDeclaration type : cud.types) {
          if (type.methods != null) {
            if (isAnnotationPresent(RunWith.class.getSimpleName(), type.annotations)) {
              Set<AbstractMethodDeclaration> filteredMethods =
                  new HashSet<AbstractMethodDeclaration>();
              boolean match = false;
              for (AbstractMethodDeclaration decl : type.methods) {
                if (decl.annotations != null) {
                  // TODO make this configurable
                  if ((isAnnotationPresent(RunAsGwtClient.class.getSimpleName(), decl.annotations)
                          || isAnnotationPresent(
                              RunAsGwtClient.class.getSimpleName(), type.annotations))
                      && !isAnnotationPresent(Deployment.class.getSimpleName(), decl.annotations)) {
                    filteredMethods.add(decl);
                  } else {
                    match = true;
                    System.out.println("Ignoring non-translatable method:\n" + decl.toString());
                  }
                }
              }
              if (match) {
                type.methods =
                    filteredMethods.toArray(new AbstractMethodDeclaration[filteredMethods.size()]);
              }
            }
          }
        }
      }

      processor.process(builder, cud, compiledClasses);
    }
Example #4
0
 /**
  * Find all methods which have the requested name.
  *
  * <p>{@code <clinit>} is not supported.
  *
  * @param type JDT type declaration
  * @param name name of methods to find
  * @return list of matching methods
  */
 private static List<AbstractMethodDeclaration> findNamedMethods(
     TypeDeclaration type, String name) {
   List<AbstractMethodDeclaration> matching = new ArrayList<AbstractMethodDeclaration>();
   boolean isCtor = "<init>".equals(name);
   char[] nameArray = name.toCharArray();
   for (AbstractMethodDeclaration method : type.methods) {
     if ((isCtor && method.isConstructor())
         || (!isCtor
             && !method.isConstructor()
             && !method.isClinit()
             && Arrays.equals(method.selector, nameArray))) {
       matching.add(method);
     }
   }
   return matching;
 }
Example #5
0
  private static void computeDietRange0(TypeDeclaration[] types, RangeResult result) {
    for (int j = 0; j < types.length; j++) {
      // members
      TypeDeclaration[] memberTypeDeclarations = types[j].memberTypes;
      if (memberTypeDeclarations != null && memberTypeDeclarations.length > 0) {
        computeDietRange0(types[j].memberTypes, result);
      }
      // methods
      AbstractMethodDeclaration[] methods = types[j].methods;
      if (methods != null) {
        int length = methods.length;
        for (int i = 0; i < length; i++) {
          AbstractMethodDeclaration method = methods[i];
          if (containsIgnoredBody(method)) {
            if (containsErrorInSignature(method)) {
              method.errorInSignature = true;
              result.addInterval(
                  method.declarationSourceStart, method.declarationSourceEnd, IGNORE);
            } else {
              int flags = method.sourceEnd + 1 == method.bodyStart ? LBRACE_MISSING : NO_FLAG;
              result.addInterval(method.bodyStart, method.bodyEnd, flags);
            }
          }
        }
      }

      // initializers
      FieldDeclaration[] fields = types[j].fields;
      if (fields != null) {
        int length = fields.length;
        for (int i = 0; i < length; i++) {
          if (fields[i] instanceof Initializer) {
            Initializer initializer = (Initializer) fields[i];
            if (initializer.declarationSourceEnd == initializer.bodyEnd) {
              initializer.errorInSignature = true;
              result.addInterval(
                  initializer.declarationSourceStart, initializer.declarationSourceEnd, IGNORE);
            } else {
              result.addInterval(initializer.bodyStart, initializer.bodyEnd);
            }
          }
        }
      }
    }
  }
Example #6
0
 public static boolean containsIgnoredBody(AbstractMethodDeclaration method) {
   return !method.isDefaultConstructor()
       && !method.isClinit()
       && (method.modifiers & CompilerModifiers.AccSemicolonBody) == 0;
 }
Example #7
0
  public void checkExceptionHandlers(
      TypeBinding[] raisedExceptions, ASTNode location, FlowInfo flowInfo, BlockScope scope) {
    // check that all the argument exception types are handled
    // JDK Compatible implementation - when an exception type is thrown,
    // all related catch blocks are marked as reachable... instead of those only
    // until the point where it is safely handled (Smarter - see comment at the end)
    int remainingCount; // counting the number of remaining unhandled exceptions
    int raisedCount; // total number of exceptions raised
    if ((raisedExceptions == null) || ((raisedCount = raisedExceptions.length) == 0)) return;
    remainingCount = raisedCount;

    // duplicate the array of raised exceptions since it will be updated
    // (null replaces any handled exception)
    System.arraycopy(
        raisedExceptions, 0, (raisedExceptions = new TypeBinding[raisedCount]), 0, raisedCount);
    FlowContext traversedContext = this;

    ArrayList abruptlyExitedLoops = null;
    while (traversedContext != null) {
      SubRoutineStatement sub;
      if (((sub = traversedContext.subroutine()) != null) && sub.isSubRoutineEscaping()) {
        // traversing a non-returning subroutine means that all unhandled
        // exceptions will actually never get sent...
        return;
      }
      // filter exceptions that are locally caught from the innermost enclosing
      // try statement to the outermost ones.
      if (traversedContext instanceof ExceptionHandlingFlowContext) {
        ExceptionHandlingFlowContext exceptionContext =
            (ExceptionHandlingFlowContext) traversedContext;
        ReferenceBinding[] caughtExceptions;
        if ((caughtExceptions = exceptionContext.handledExceptions) != Binding.NO_EXCEPTIONS) {
          int caughtCount = caughtExceptions.length;
          boolean[] locallyCaught = new boolean[raisedCount]; // at most

          for (int caughtIndex = 0; caughtIndex < caughtCount; caughtIndex++) {
            ReferenceBinding caughtException = caughtExceptions[caughtIndex];
            for (int raisedIndex = 0; raisedIndex < raisedCount; raisedIndex++) {
              TypeBinding raisedException;
              if ((raisedException = raisedExceptions[raisedIndex]) != null) {
                FlowInfo exceptionFlow = flowInfo;
                int state =
                    caughtException == null
                        ? Scope.EQUAL_OR_MORE_SPECIFIC /* any exception */
                        : Scope.compareTypes(raisedException, caughtException);
                if (abruptlyExitedLoops != null
                    && caughtException != null
                    && state != Scope.NOT_RELATED) {
                  for (int i = 0, abruptlyExitedLoopsCount = abruptlyExitedLoops.size();
                      i < abruptlyExitedLoopsCount;
                      i++) {
                    LoopingFlowContext loop = (LoopingFlowContext) abruptlyExitedLoops.get(i);
                    loop.recordCatchContextOfEscapingException(
                        exceptionContext, caughtException, flowInfo);
                  }
                  exceptionFlow =
                      FlowInfo.DEAD_END; // don't use flow info on first round, flow info will be
                  // evaluated during loopback simulation
                }
                switch (state) {
                  case Scope.EQUAL_OR_MORE_SPECIFIC:
                    exceptionContext.recordHandlingException(
                        caughtException,
                        exceptionFlow.unconditionalInits(),
                        raisedException,
                        raisedException, // precise exception that will be caught
                        location,
                        locallyCaught[raisedIndex]);
                    // was already definitely caught ?
                    if (!locallyCaught[raisedIndex]) {
                      locallyCaught[raisedIndex] = true;
                      // remember that this exception has been definitely caught
                      remainingCount--;
                    }
                    break;
                  case Scope.MORE_GENERIC:
                    exceptionContext.recordHandlingException(
                        caughtException,
                        exceptionFlow.unconditionalInits(),
                        raisedException,
                        caughtException,
                        location,
                        false);
                    // was not caught already per construction
                }
              }
            }
          }
          // remove locally caught exceptions from the remaining ones
          for (int i = 0; i < raisedCount; i++) {
            if (locallyCaught[i]) {
              raisedExceptions[i] = null; // removed from the remaining ones.
            }
          }
        }
        // method treatment for unchecked exceptions
        if (exceptionContext.isMethodContext) {
          for (int i = 0; i < raisedCount; i++) {
            TypeBinding raisedException;
            if ((raisedException = raisedExceptions[i]) != null) {
              if (raisedException.isUncheckedException(false)) {
                remainingCount--;
                raisedExceptions[i] = null;
              }
            }
          }
          boolean shouldMergeUnhandledException =
              exceptionContext instanceof ExceptionInferenceFlowContext;
          // anonymous constructors are allowed to throw any exceptions (their thrown exceptions
          // clause will be fixed up later as per JLS 8.6).
          if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration) {
            AbstractMethodDeclaration method =
                (AbstractMethodDeclaration) exceptionContext.associatedNode;
            if (method.isConstructor() && method.binding.declaringClass.isAnonymousType())
              shouldMergeUnhandledException = true;
          }
          if (shouldMergeUnhandledException) {
            for (int i = 0; i < raisedCount; i++) {
              TypeBinding raisedException;
              if ((raisedException = raisedExceptions[i]) != null) {
                exceptionContext.mergeUnhandledException(raisedException);
              }
            }
            return; // no need to complain, will fix up constructor/lambda exceptions
          }
          break; // not handled anywhere, thus jump to error handling
        }
      } else if (traversedContext instanceof LoopingFlowContext) {
        if (abruptlyExitedLoops == null) {
          abruptlyExitedLoops = new ArrayList(5);
        }
        abruptlyExitedLoops.add(traversedContext);
      }
      if (remainingCount == 0) return;

      traversedContext.recordReturnFrom(flowInfo.unconditionalInits());

      if (traversedContext instanceof InsideSubRoutineFlowContext) {
        ASTNode node = traversedContext.associatedNode;
        if (node instanceof TryStatement) {
          TryStatement tryStatement = (TryStatement) node;
          flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
        }
      }
      traversedContext = traversedContext.getLocalParent();
    }
    // if reaches this point, then there are some remaining unhandled exception types.
    nextReport:
    for (int i = 0; i < raisedCount; i++) {
      TypeBinding exception;
      if ((exception = raisedExceptions[i]) != null) {
        // only one complaint if same exception declared to be thrown more than once
        for (int j = 0; j < i; j++) {
          if (TypeBinding.equalsEquals(raisedExceptions[j], exception))
            continue nextReport; // already reported
        }
        scope.problemReporter().unhandledException(exception, location);
      }
    }
  }
Example #8
0
  /**
   * @param isExceptionOnAutoClose This is for checking exception handlers for exceptions raised
   *     during the auto close of resources inside a try with resources statement. (Relevant for
   *     source levels 1.7 and above only)
   */
  public void checkExceptionHandlers(
      TypeBinding raisedException,
      ASTNode location,
      FlowInfo flowInfo,
      BlockScope scope,
      boolean isExceptionOnAutoClose) {
    // LIGHT-VERSION OF THE EQUIVALENT WITH AN ARRAY OF EXCEPTIONS
    // check that all the argument exception types are handled
    // JDK Compatible implementation - when an exception type is thrown,
    // all related catch blocks are marked as reachable... instead of those only
    // until the point where it is safely handled (Smarter - see comment at the end)
    FlowContext traversedContext = this;
    ArrayList abruptlyExitedLoops = null;
    if (scope.compilerOptions().sourceLevel >= ClassFileConstants.JDK1_7
        && location instanceof ThrowStatement) {
      Expression throwExpression = ((ThrowStatement) location).exception;
      LocalVariableBinding throwArgBinding = throwExpression.localVariableBinding();
      if (throwExpression
              instanceof SingleNameReference // https://bugs.eclipse.org/bugs/show_bug.cgi?id=350361
          && throwArgBinding instanceof CatchParameterBinding
          && throwArgBinding.isEffectivelyFinal()) {
        CatchParameterBinding parameter = (CatchParameterBinding) throwArgBinding;
        checkExceptionHandlers(parameter.getPreciseTypes(), location, flowInfo, scope);
        return;
      }
    }
    while (traversedContext != null) {
      SubRoutineStatement sub;
      if (((sub = traversedContext.subroutine()) != null) && sub.isSubRoutineEscaping()) {
        // traversing a non-returning subroutine means that all unhandled
        // exceptions will actually never get sent...
        return;
      }

      // filter exceptions that are locally caught from the innermost enclosing
      // try statement to the outermost ones.
      if (traversedContext instanceof ExceptionHandlingFlowContext) {
        ExceptionHandlingFlowContext exceptionContext =
            (ExceptionHandlingFlowContext) traversedContext;
        ReferenceBinding[] caughtExceptions;
        if ((caughtExceptions = exceptionContext.handledExceptions) != Binding.NO_EXCEPTIONS) {
          boolean definitelyCaught = false;
          for (int caughtIndex = 0, caughtCount = caughtExceptions.length;
              caughtIndex < caughtCount;
              caughtIndex++) {
            ReferenceBinding caughtException = caughtExceptions[caughtIndex];
            FlowInfo exceptionFlow = flowInfo;
            int state =
                caughtException == null
                    ? Scope.EQUAL_OR_MORE_SPECIFIC /* any exception */
                    : Scope.compareTypes(raisedException, caughtException);
            if (abruptlyExitedLoops != null
                && caughtException != null
                && state != Scope.NOT_RELATED) {
              for (int i = 0, abruptlyExitedLoopsCount = abruptlyExitedLoops.size();
                  i < abruptlyExitedLoopsCount;
                  i++) {
                LoopingFlowContext loop = (LoopingFlowContext) abruptlyExitedLoops.get(i);
                loop.recordCatchContextOfEscapingException(
                    exceptionContext, caughtException, flowInfo);
              }
              exceptionFlow =
                  FlowInfo
                      .DEAD_END; // don't use flow info on first round, flow info will be evaluated
              // during loopback simulation
            }
            switch (state) {
              case Scope.EQUAL_OR_MORE_SPECIFIC:
                exceptionContext.recordHandlingException(
                    caughtException,
                    exceptionFlow.unconditionalInits(),
                    raisedException,
                    raisedException, // precise exception that will be caught
                    location,
                    definitelyCaught);
                // was it already definitely caught ?
                definitelyCaught = true;
                break;
              case Scope.MORE_GENERIC:
                exceptionContext.recordHandlingException(
                    caughtException,
                    exceptionFlow.unconditionalInits(),
                    raisedException,
                    caughtException,
                    location,
                    false);
                // was not caught already per construction
            }
          }
          if (definitelyCaught) return;
        }
        // method treatment for unchecked exceptions
        if (exceptionContext.isMethodContext) {
          if (raisedException.isUncheckedException(false)) return;
          boolean shouldMergeUnhandledExceptions =
              exceptionContext instanceof ExceptionInferenceFlowContext;

          // anonymous constructors are allowed to throw any exceptions (their thrown exceptions
          // clause will be fixed up later as per JLS 8.6).
          if (exceptionContext.associatedNode instanceof AbstractMethodDeclaration) {
            AbstractMethodDeclaration method =
                (AbstractMethodDeclaration) exceptionContext.associatedNode;
            if (method.isConstructor() && method.binding.declaringClass.isAnonymousType())
              shouldMergeUnhandledExceptions = true;
          }
          if (shouldMergeUnhandledExceptions) {
            exceptionContext.mergeUnhandledException(raisedException);
            return; // no need to complain, will fix up constructor/lambda exceptions
          }
          break; // not handled anywhere, thus jump to error handling
        }
      } else if (traversedContext instanceof LoopingFlowContext) {
        if (abruptlyExitedLoops == null) {
          abruptlyExitedLoops = new ArrayList(5);
        }
        abruptlyExitedLoops.add(traversedContext);
      }

      traversedContext.recordReturnFrom(flowInfo.unconditionalInits());

      if (!isExceptionOnAutoClose) {
        if (traversedContext instanceof InsideSubRoutineFlowContext) {
          ASTNode node = traversedContext.associatedNode;
          if (node instanceof TryStatement) {
            TryStatement tryStatement = (TryStatement) node;
            flowInfo.addInitializationsFrom(tryStatement.subRoutineInits); // collect inits
          }
        }
      }
      traversedContext = traversedContext.getLocalParent();
    }
    // if reaches this point, then there are some remaining unhandled exception types.
    if (isExceptionOnAutoClose) {
      scope.problemReporter().unhandledExceptionFromAutoClose(raisedException, location);
    } else {
      scope.problemReporter().unhandledException(raisedException, location);
    }
  }
 /**
  * For predicates the parser doesn't know if they are static, update the method once we know the
  * role method is indeed static. Updates declaration, binding and scope for both class- and
  * interface-part.
  */
 private void makeMethodStatic(AbstractMethodDeclaration method) {
   method.modifiers |= ClassFileConstants.AccStatic;
   if (method.binding != null) method.binding.modifiers |= ClassFileConstants.AccStatic;
   if (method.scope != null) method.scope.isStatic = true;
   if (method.interfacePartMethod != null) makeMethodStatic(method.interfacePartMethod);
 }
Example #10
0
  /*
   * Update the corresponding parse node from parser state which
   * is about to disappear because of restarting recovery
   */
  public void updateFromParserState() {
    // if parent is null then recovery already occured in diet parser.
    if (this.bodyStartsAtHeaderEnd() && this.parent != null) {
      Parser parser = this.parser();
      /* might want to recover arguments or thrown exceptions */
      if (parser.listLength > 0 && parser.astLengthPtr > 0) { // awaiting interface type references
        /* has consumed the arguments - listed elements must be thrown exceptions */
        if (methodDeclaration.sourceEnd == parser.rParenPos) {

          // protection for bugs 15142
          int length = parser.astLengthStack[parser.astLengthPtr];
          int astPtr = parser.astPtr - length;
          boolean canConsume = astPtr >= 0;
          if (canConsume) {
            if ((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) {
              canConsume = false;
            }
            for (int i = 1, max = length + 1; i < max; i++) {
              if (!(parser.astStack[astPtr + i] instanceof TypeReference)) {
                canConsume = false;
              }
            }
          }
          if (canConsume) {
            parser.consumeMethodHeaderThrowsClause();
            // will reset typeListLength to zero
            // thus this check will only be performed on first errorCheck after void foo() throws X,
            // Y,
          } else {
            parser.listLength = 0;
          }
        } else {
          /* has not consumed arguments yet, listed elements must be arguments */
          if (parser.currentToken == TokenNameLPAREN || parser.currentToken == TokenNameSEMICOLON) {
            /* if currentToken is parenthesis this last argument is a method/field signature */
            parser.astLengthStack[parser.astLengthPtr]--;
            parser.astPtr--;
            parser.listLength--;
            parser.currentToken = 0;
          }
          int argLength = parser.astLengthStack[parser.astLengthPtr];
          int argStart = parser.astPtr - argLength + 1;
          boolean needUpdateRParenPos =
              parser.rParenPos < parser.lParenPos; // 12387 : rParenPos will be used

          // remove unfinished annotation nodes
          MemberValuePair[] memberValuePairs = null;
          while (argLength > 0 && parser.astStack[parser.astPtr] instanceof MemberValuePair) {
            System.arraycopy(
                parser.astStack,
                argStart,
                memberValuePairs = new MemberValuePair[argLength],
                0,
                argLength);
            parser.astLengthPtr--;
            parser.astPtr -= argLength;

            argLength = parser.astLengthStack[parser.astLengthPtr];
            argStart = parser.astPtr - argLength + 1;
            needUpdateRParenPos = true;
          }

          // to compute bodyStart, and thus used to set next checkpoint.
          int count;
          for (count = 0; count < argLength; count++) {
            ASTNode aNode = parser.astStack[argStart + count];
            if (aNode instanceof Argument) {
              Argument argument = (Argument) aNode;
              /* cannot be an argument if non final */
              char[][] argTypeName = argument.type.getTypeName();
              if ((argument.modifiers & ~ClassFileConstants.AccFinal) != 0
                  || (argTypeName.length == 1
                      && CharOperation.equals(argTypeName[0], TypeBinding.VOID.sourceName()))) {
                parser.astLengthStack[parser.astLengthPtr] = count;
                parser.astPtr = argStart + count - 1;
                parser.listLength = count;
                parser.currentToken = 0;
                break;
              }
              if (needUpdateRParenPos) parser.rParenPos = argument.sourceEnd + 1;
            } else {
              parser.astLengthStack[parser.astLengthPtr] = count;
              parser.astPtr = argStart + count - 1;
              parser.listLength = count;
              parser.currentToken = 0;
              break;
            }
          }
          if (parser.listLength > 0 && parser.astLengthPtr > 0) {

            // protection for bugs 15142
            int length = parser.astLengthStack[parser.astLengthPtr];
            int astPtr = parser.astPtr - length;
            boolean canConsume = astPtr >= 0;
            if (canConsume) {
              if ((!(parser.astStack[astPtr] instanceof AbstractMethodDeclaration))) {
                canConsume = false;
              }
              for (int i = 1, max = length + 1; i < max; i++) {
                if (!(parser.astStack[astPtr + i] instanceof Argument)) {
                  canConsume = false;
                }
              }
            }
            if (canConsume) {
              parser.consumeMethodHeaderRightParen();
              /* fix-up positions, given they were updated against rParenPos, which did not get set */
              if (parser.currentElement
                  == this) { // parameter addition might have added an awaiting (no return type)
                             // method - see 1FVXQZ4 */
                methodDeclaration.sourceEnd =
                    methodDeclaration.arguments[methodDeclaration.arguments.length - 1].sourceEnd;
                methodDeclaration.bodyStart = methodDeclaration.sourceEnd + 1;
                parser.lastCheckPoint = methodDeclaration.bodyStart;
              }
            }
          }

          if (memberValuePairs != null) {
            System.arraycopy(
                memberValuePairs, 0, parser.astStack, parser.astPtr + 1, memberValuePairs.length);
            parser.astPtr += memberValuePairs.length;
            parser.astLengthStack[++parser.astLengthPtr] = memberValuePairs.length;
          }
        }
      }
    }
  }
Example #11
0
  public AbstractMethodDeclaration updatedMethodDeclaration() {
    /* update annotations */
    if (modifiers != 0) {
      this.methodDeclaration.modifiers |= modifiers;
      if (this.modifiersStart < this.methodDeclaration.declarationSourceStart) {
        this.methodDeclaration.declarationSourceStart = modifiersStart;
      }
    }
    /* update annotations */
    if (annotationCount > 0) {
      int existingCount =
          methodDeclaration.annotations == null ? 0 : methodDeclaration.annotations.length;
      Annotation[] annotationReferences = new Annotation[existingCount + annotationCount];
      if (existingCount > 0) {
        System.arraycopy(
            methodDeclaration.annotations, 0, annotationReferences, annotationCount, existingCount);
      }
      for (int i = 0; i < annotationCount; i++) {
        annotationReferences[i] = annotations[i].updatedAnnotationReference();
      }
      methodDeclaration.annotations = annotationReferences;

      int start = this.annotations[0].annotation.sourceStart;
      if (start < this.methodDeclaration.declarationSourceStart) {
        this.methodDeclaration.declarationSourceStart = start;
      }
    }

    if (methodBody != null) {
      Block block = methodBody.updatedBlock();
      if (block != null) {
        methodDeclaration.statements = block.statements;

        if (methodDeclaration.declarationSourceEnd == 0) {
          methodDeclaration.declarationSourceEnd = block.sourceEnd;
          methodDeclaration.bodyEnd = block.sourceEnd;
        }

        /* first statement might be an explict constructor call destinated to a special slot */
        if (methodDeclaration.isConstructor()) {
          ConstructorDeclaration constructor = (ConstructorDeclaration) methodDeclaration;
          if (methodDeclaration.statements != null
              && methodDeclaration.statements[0] instanceof ExplicitConstructorCall) {
            constructor.constructorCall = (ExplicitConstructorCall) methodDeclaration.statements[0];
            int length = methodDeclaration.statements.length;
            System.arraycopy(
                methodDeclaration.statements,
                1,
                (methodDeclaration.statements = new Statement[length - 1]),
                0,
                length - 1);
          }
          if (constructor.constructorCall == null) { // add implicit constructor call
            constructor.constructorCall = SuperReference.implicitSuperConstructorCall();
          }
        }
      }
    } else {
      if (methodDeclaration.declarationSourceEnd == 0) {
        if (methodDeclaration.sourceEnd + 1 == methodDeclaration.bodyStart) {
          // right brace is missing
          methodDeclaration.declarationSourceEnd = methodDeclaration.sourceEnd;
          methodDeclaration.bodyStart = methodDeclaration.sourceEnd;
          methodDeclaration.bodyEnd = methodDeclaration.sourceEnd;
        } else {
          methodDeclaration.declarationSourceEnd = methodDeclaration.bodyStart;
          methodDeclaration.bodyEnd = methodDeclaration.bodyStart;
        }
      }
    }
    if (localTypeCount > 0) methodDeclaration.bits |= ASTNode.HasLocalType;
    return methodDeclaration;
  }
Example #12
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;
  }