Пример #1
0
  public FlowInfo analyseCode(BlockScope currentScope, FlowContext flowContext, FlowInfo flowInfo) {
    boolean nonStatic = !this.binding.isStatic();
    boolean wasInsideAssert =
        ((flowContext.tagBits & FlowContext.HIDE_NULL_COMPARISON_WARNING) != 0);
    flowInfo =
        this.receiver
            .analyseCode(currentScope, flowContext, flowInfo, nonStatic)
            .unconditionalInits();
    // recording the closing of AutoCloseable resources:
    boolean analyseResources = currentScope.compilerOptions().analyseResourceLeaks;
    if (analyseResources && CharOperation.equals(TypeConstants.CLOSE, this.selector)) {
      FakedTrackingVariable trackingVariable =
          FakedTrackingVariable.getCloseTrackingVariable(this.receiver);
      if (trackingVariable
          != null) { // null happens if receiver is not a local variable or not an AutoCloseable
        if (trackingVariable.methodScope == currentScope.methodScope()) {
          trackingVariable.markClose(flowInfo, flowContext);
        } else {
          trackingVariable.markClosedInNestedMethod();
        }
      }
    }
    if (nonStatic) {
      this.receiver.checkNPE(currentScope, flowContext, flowInfo);
      // https://bugs.eclipse.org/bugs/show_bug.cgi?id=318682
      if (this.receiver.isThis()) {
        // accessing non-static method without an object
        currentScope.resetDeclaringClassMethodStaticFlag(this.binding.declaringClass);
      }
    } else if (this.receiver.isThis()) {
      if ((this.receiver.bits & ASTNode.IsImplicitThis) == 0) {
        // explicit this receiver, not allowed in static context
        currentScope.resetEnclosingMethodStaticFlag();
      }
    }

    FlowInfo conditionFlowInfo;
    if (this.arguments != null) {
      int length = this.arguments.length;
      for (int i = 0; i < length; i++) {
        Expression argument = this.arguments[i];
        if ((argument.implicitConversion & TypeIds.UNBOXING) != 0) {
          argument.checkNPE(currentScope, flowContext, flowInfo);
        }
        if (this.receiver.resolvedType != null
            && this.receiver.resolvedType.id == TypeIds.T_OrgEclipseCoreRuntimeAssert
            && argument.resolvedType != null
            && argument.resolvedType.id == TypeIds.T_boolean) {
          Constant cst = argument.optimizedBooleanConstant();
          boolean isOptimizedTrueAssertion =
              cst != Constant.NotAConstant && cst.booleanValue() == true;
          boolean isOptimizedFalseAssertion =
              cst != Constant.NotAConstant && cst.booleanValue() == false;
          flowContext.tagBits |= FlowContext.HIDE_NULL_COMPARISON_WARNING;
          conditionFlowInfo = argument.analyseCode(currentScope, flowContext, flowInfo.copy());
          if (!wasInsideAssert) {
            flowContext.tagBits &= ~FlowContext.HIDE_NULL_COMPARISON_WARNING;
          }
          UnconditionalFlowInfo assertWhenTrueInfo =
              conditionFlowInfo.initsWhenTrue().unconditionalInits();
          FlowInfo assertInfo = conditionFlowInfo.initsWhenFalse();
          if (isOptimizedTrueAssertion) {
            assertInfo.setReachMode(FlowInfo.UNREACHABLE_OR_DEAD);
          }
          if (!isOptimizedFalseAssertion) {
            // if assertion is not false for sure, only then it makes sense to carry the flow info
            // ahead.
            // if the code does reach ahead, it means the assert didn't cause an exit, and so
            // the expression inside it shouldn't change the prior flowinfo
            // viz. org.eclipse.core.runtime.Assert.isLegal(false && o != null)

            // keep the merge from the initial code for the definite assignment
            // analysis, tweak the null part to influence nulls downstream
            flowInfo =
                flowInfo
                    .mergedWith(assertInfo.nullInfoLessUnconditionalCopy())
                    .addInitializationsFrom(assertWhenTrueInfo.discardInitializationInfo());
          }
        } else {
          flowInfo = argument.analyseCode(currentScope, flowContext, flowInfo).unconditionalInits();
        }
        if (analyseResources) {
          // if argument is an AutoCloseable insert info that it *may* be closed (by the target
          // method, i.e.)
          flowInfo =
              FakedTrackingVariable.markPassedToOutside(currentScope, argument, flowInfo, false);
        }
      }
      analyseArguments(currentScope, flowContext, flowInfo, this.binding, this.arguments);
    }
    ReferenceBinding[] thrownExceptions;
    if ((thrownExceptions = this.binding.thrownExceptions) != Binding.NO_EXCEPTIONS) {
      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
        thrownExceptions =
            currentScope.environment().convertToRawTypes(this.binding.thrownExceptions, true, true);
      }
      // must verify that exceptions potentially thrown by this expression are caught in the method
      flowContext.checkExceptionHandlers(thrownExceptions, this, flowInfo.copy(), currentScope);
      // TODO (maxime) the copy above is needed because of a side effect into
      //               checkExceptionHandlers; consider protecting there instead of here;
      //               NullReferenceTest#test0510
    }
    manageSyntheticAccessIfNecessary(currentScope, flowInfo);
    return flowInfo;
  }