示例#1
0
 /**
  * Record that a nullity mismatch was detected against an annotated type reference.
  *
  * @param currentScope scope for error reporting
  * @param expression the expression violating the specification
  * @param providedType the type of the provided value, i.e., either expression or an element
  *     thereof (in ForeachStatements)
  * @param expectedType the declared type of the spec'ed variable, for error reporting.
  * @param flowInfo the flowInfo observed when visiting expression
  * @param nullStatus the null status of expression at the current location
  * @param annotationStatus status from type annotation analysis, or null
  */
 public void recordNullityMismatch(
     BlockScope currentScope,
     Expression expression,
     TypeBinding providedType,
     TypeBinding expectedType,
     FlowInfo flowInfo,
     int nullStatus,
     NullAnnotationMatching annotationStatus) {
   if (providedType == null) {
     return; // assume type error was already reported
   }
   if (expression.localVariableBinding()
       != null) { // flowContext cannot yet handle non-localvar expressions (e.g., fields)
     // find the inner-most flowContext that might need deferred handling:
     FlowContext currentContext = this;
     while (currentContext != null) {
       // some flow contexts implement deferred checking, should we participate in that?
       int isInsideAssert = 0x0;
       if ((this.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0) {
         isInsideAssert = FlowContext.HIDE_NULL_COMPARISON_WARNING;
       }
       if (currentContext.internalRecordNullityMismatch(
           expression,
           providedType,
           flowInfo,
           nullStatus,
           expectedType,
           ASSIGN_TO_NONNULL | isInsideAssert)) return;
       currentContext = currentContext.parent;
     }
   }
   // no reason to defer, so report now:
   if (annotationStatus != null)
     currentScope
         .problemReporter()
         .nullityMismatchingTypeAnnotation(
             expression, providedType, expectedType, annotationStatus);
   else
     currentScope
         .problemReporter()
         .nullityMismatch(
             expression,
             providedType,
             expectedType,
             nullStatus,
             currentScope.environment().getNonNullAnnotationName());
 }
示例#2
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);
    }
  }