예제 #1
0
 @Nullable
 private DfaRelationValue compareToNull(DfaValue dfaVar, boolean negated) {
   DfaConstValue dfaNull = myFactory.getConstFactory().getNull();
   return myFactory
       .getRelationFactory()
       .createRelation(dfaVar, dfaNull, JavaTokenType.EQEQ, negated);
 }
예제 #2
0
 private DfaValue handleFlush(DfaVariableValue flushed, DfaValue value) {
   if (value instanceof DfaVariableValue
       && (value == flushed
           || myFactory.getVarFactory().getAllQualifiedBy(flushed).contains(value))) {
     Nullness nullability =
         isNotNull(value)
             ? Nullness.NOT_NULL
             : ((DfaVariableValue) value).getInherentNullability();
     return myFactory.createTypeValue(((DfaVariableValue) value).getVariableType(), nullability);
   }
   return value;
 }
 protected boolean checkNotNullable(
     DfaMemoryState state, DfaValue value, NullabilityProblem problem, PsiElement anchor) {
   boolean notNullable = state.checkNotNullable(value);
   if (notNullable
       && problem != NullabilityProblem.passingNullableArgumentToNonAnnotatedParameter) {
     DfaValueFactory factory = ((DfaMemoryStateImpl) state).getFactory();
     state.applyCondition(
         factory
             .getRelationFactory()
             .createRelation(value, factory.getConstFactory().getNull(), NE, false));
   }
   return notNullable;
 }
예제 #4
0
  @Override
  public boolean isNotNull(DfaValue dfaVar) {
    if (dfaVar instanceof DfaConstValue) return ((DfaConstValue) dfaVar).getValue() != null;
    if (dfaVar instanceof DfaBoxedValue) return true;
    if (dfaVar instanceof DfaTypeValue) return ((DfaTypeValue) dfaVar).isNotNull();
    if (dfaVar instanceof DfaVariableValue) {
      if (getVariableState((DfaVariableValue) dfaVar).isNotNull()) return true;

      DfaConstValue constantValue = getConstantValue((DfaVariableValue) dfaVar);
      if (constantValue != null && constantValue.getValue() != null) return true;
    }

    DfaConstValue dfaNull = myFactory.getConstFactory().getNull();
    int c1Index = getEqClassIndex(dfaVar);
    int c2Index = getEqClassIndex(dfaNull);
    if (c1Index < 0 || c2Index < 0) {
      return false;
    }

    long[] pairs = myDistinctClasses.toArray();
    for (long pair : pairs) {
      if (c1Index == low(pair) && c2Index == high(pair)
          || c1Index == high(pair) && c2Index == low(pair)) {
        return true;
      }
    }

    return false;
  }
 private DfaValue getDfaContractReturnValue(
     MethodContract contract, MethodCallInstruction instruction, DfaValueFactory factory) {
   switch (contract.returnValue) {
     case NULL_VALUE:
       return factory.getConstFactory().getNull();
     case NOT_NULL_VALUE:
       return factory.createTypeValue(instruction.getResultType(), Nullness.NOT_NULL);
     case TRUE_VALUE:
       return factory.getConstFactory().getTrue();
     case FALSE_VALUE:
       return factory.getConstFactory().getFalse();
     case THROW_EXCEPTION:
       return factory.getConstFactory().getContractFail();
     default:
       return getMethodResultValue(instruction, null, factory);
   }
 }
예제 #6
0
  private boolean applyBoxedRelation(
      @NotNull DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
    if (!TypeConversionUtil.isPrimitiveAndNotNull(dfaLeft.getVariableType())) return true;

    DfaBoxedValue.Factory boxedFactory = myFactory.getBoxedFactory();
    DfaValue boxedLeft = boxedFactory.createBoxed(dfaLeft);
    DfaValue boxedRight = boxedFactory.createBoxed(dfaRight);
    return boxedLeft == null || boxedRight == null || applyRelation(boxedLeft, boxedRight, negated);
  }
예제 #7
0
 private void updateVarStateOnComparison(@NotNull DfaVariableValue dfaVar, DfaValue value) {
   if (!isUnknownState(dfaVar)) {
     if (value instanceof DfaConstValue && ((DfaConstValue) value).getValue() == null) {
       setVariableState(dfaVar, getVariableState(dfaVar).withNullability(Nullness.NULLABLE));
     } else if (isNotNull(value) && !isNotNull(dfaVar)) {
       setVariableState(dfaVar, getVariableState(dfaVar).withNullability(Nullness.UNKNOWN));
       applyRelation(dfaVar, myFactory.getConstFactory().getNull(), true);
     }
   }
 }
예제 #8
0
  @Override
  public boolean isNull(DfaValue dfaValue) {
    if (dfaValue instanceof DfaConstValue) return ((DfaConstValue) dfaValue).getValue() == null;

    if (dfaValue instanceof DfaVariableValue) {
      int c1Index = getEqClassIndex(dfaValue);
      return c1Index >= 0 && c1Index == getEqClassIndex(myFactory.getConstFactory().getNull());
    }

    return false;
  }
예제 #9
0
 private void removeFromMap(int id, int index) {
   id = unwrap(myFactory.getValue(id)).getID();
   int[] classes = myIdToEqClassesIndices.get(id);
   if (classes != null) {
     int i = ArrayUtil.indexOf(classes, index);
     if (i != -1) {
       classes = ArrayUtil.remove(classes, i);
       myIdToEqClassesIndices.put(id, classes);
     }
   }
 }
예제 #10
0
 private void addToMap(int id, int index) {
   id = unwrap(myFactory.getValue(id)).getID();
   int[] classes = myIdToEqClassesIndices.get(id);
   if (classes == null) {
     classes = new int[] {index};
     myIdToEqClassesIndices.put(id, classes);
   } else {
     classes = ArrayUtil.append(classes, index);
     myIdToEqClassesIndices.put(id, classes);
   }
 }
  @Nullable
  private DfaInstructionState[] handleRelationBinop(
      BinopInstruction instruction,
      DataFlowRunner runner,
      DfaMemoryState memState,
      DfaValue dfaRight,
      DfaValue dfaLeft) {
    DfaValueFactory factory = runner.getFactory();
    final Instruction next = runner.getInstruction(instruction.getIndex() + 1);
    DfaRelationValue dfaRelation =
        factory
            .getRelationFactory()
            .createRelation(dfaLeft, dfaRight, instruction.getOperationSign(), false);
    if (dfaRelation == null) {
      return null;
    }

    myCanBeNullInInstanceof.add(instruction);

    ArrayList<DfaInstructionState> states = new ArrayList<DfaInstructionState>();

    final DfaMemoryState trueCopy = memState.createCopy();
    if (trueCopy.applyCondition(dfaRelation)) {
      trueCopy.push(factory.getConstFactory().getTrue());
      instruction.setTrueReachable();
      states.add(new DfaInstructionState(next, trueCopy));
    }

    //noinspection UnnecessaryLocalVariable
    DfaMemoryState falseCopy = memState;
    if (falseCopy.applyCondition(dfaRelation.createNegated())) {
      falseCopy.push(factory.getConstFactory().getFalse());
      instruction.setFalseReachable();
      states.add(new DfaInstructionState(next, falseCopy));
      if (instruction instanceof InstanceofInstruction && !falseCopy.isNull(dfaLeft)) {
        myUsefulInstanceofs.add((InstanceofInstruction) instruction);
      }
    }

    return states.toArray(new DfaInstructionState[states.size()]);
  }
  @Override
  public DfaInstructionState[] visitTypeCast(
      TypeCastInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
    final DfaValueFactory factory = runner.getFactory();
    DfaValue dfaExpr = factory.createValue(instruction.getCasted());
    if (dfaExpr != null) {
      DfaTypeValue dfaType =
          (DfaTypeValue) factory.createTypeValue(instruction.getCastTo(), Nullness.UNKNOWN);
      DfaRelationValue dfaInstanceof =
          factory.getRelationFactory().createRelation(dfaExpr, dfaType, INSTANCEOF_KEYWORD, false);
      if (dfaInstanceof != null && !memState.applyInstanceofOrNull(dfaInstanceof)) {
        onInstructionProducesCCE(instruction);
      }
    }

    if (instruction.getCastTo() instanceof PsiPrimitiveType) {
      memState.push(runner.getFactory().getBoxedFactory().createUnboxed(memState.pop()));
    }

    return nextInstruction(instruction, runner, memState);
  }
예제 #13
0
  @Override
  public boolean applyCondition(DfaValue dfaCond) {
    if (dfaCond instanceof DfaUnknownValue) return true;
    if (dfaCond instanceof DfaUnboxedValue) {
      DfaVariableValue dfaVar = ((DfaUnboxedValue) dfaCond).getVariable();
      boolean isNegated = dfaVar.isNegated();
      DfaVariableValue dfaNormalVar = isNegated ? dfaVar.createNegated() : dfaVar;
      final DfaValue boxedTrue =
          myFactory.getBoxedFactory().createBoxed(myFactory.getConstFactory().getTrue());
      return applyRelationCondition(
          myFactory
              .getRelationFactory()
              .createRelation(dfaNormalVar, boxedTrue, JavaTokenType.EQEQ, isNegated));
    }
    if (dfaCond instanceof DfaVariableValue) {
      DfaVariableValue dfaVar = (DfaVariableValue) dfaCond;
      boolean isNegated = dfaVar.isNegated();
      DfaVariableValue dfaNormalVar = isNegated ? dfaVar.createNegated() : dfaVar;
      DfaConstValue dfaTrue = myFactory.getConstFactory().getTrue();
      return applyRelationCondition(
          myFactory
              .getRelationFactory()
              .createRelation(dfaNormalVar, dfaTrue, JavaTokenType.EQEQ, isNegated));
    }

    if (dfaCond instanceof DfaConstValue) {
      return dfaCond == myFactory.getConstFactory().getTrue()
          || dfaCond != myFactory.getConstFactory().getFalse();
    }

    if (!(dfaCond instanceof DfaRelationValue)) return true;

    return applyRelationCondition((DfaRelationValue) dfaCond);
  }
예제 #14
0
  @Override
  public void setVarValue(DfaVariableValue var, DfaValue value) {
    if (var == value) return;

    value = handleFlush(var, value);
    flushVariable(var);

    if (value instanceof DfaUnknownValue) {
      setVariableState(var, getVariableState(var).withNullable(false));
      return;
    }

    setVariableState(var, getVariableState(var).withValue(value));
    if (value instanceof DfaTypeValue) {
      setVariableState(
          var, getVariableState(var).withNullability(((DfaTypeValue) value).getNullness()));
      DfaRelationValue dfaInstanceof =
          myFactory
              .getRelationFactory()
              .createRelation(var, value, JavaTokenType.INSTANCEOF_KEYWORD, false);
      if (((DfaTypeValue) value).isNotNull()) {
        applyCondition(dfaInstanceof);
      } else {
        applyInstanceofOrNull(dfaInstanceof);
      }
    } else {
      DfaRelationValue dfaEqual =
          myFactory.getRelationFactory().createRelation(var, value, JavaTokenType.EQEQ, false);
      if (dfaEqual == null) return;
      applyCondition(dfaEqual);

      if (value instanceof DfaVariableValue) {
        setVariableState(var, getVariableState((DfaVariableValue) value));
      }
    }

    if (getVariableState(var).isNotNull()) {
      applyCondition(compareToNull(var, true));
    }
  }
  @Override
  public DfaInstructionState[] visitAssign(
      AssignInstruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
    DfaValue dfaSource = memState.pop();
    DfaValue dfaDest = memState.pop();

    if (dfaDest instanceof DfaVariableValue) {
      DfaVariableValue var = (DfaVariableValue) dfaDest;

      DfaValueFactory factory = runner.getFactory();
      if (dfaSource instanceof DfaVariableValue
          && factory.getVarFactory().getAllQualifiedBy(var).contains(dfaSource)) {
        Nullness nullability =
            memState.isNotNull(dfaSource)
                ? Nullness.NOT_NULL
                : ((DfaVariableValue) dfaSource).getInherentNullability();
        dfaSource =
            factory.createTypeValue(((DfaVariableValue) dfaSource).getVariableType(), nullability);
      }

      if (var.getInherentNullability() == Nullness.NOT_NULL) {
        checkNotNullable(
            memState,
            dfaSource,
            NullabilityProblem.assigningToNotNull,
            instruction.getRExpression());
      }
      final PsiModifierListOwner psi = var.getPsiVariable();
      if (!(psi instanceof PsiField) || !psi.hasModifierProperty(PsiModifier.VOLATILE)) {
        memState.setVarValue(var, dfaSource);
      }
    } else if (dfaDest instanceof DfaTypeValue && ((DfaTypeValue) dfaDest).isNotNull()) {
      checkNotNullable(
          memState, dfaSource, NullabilityProblem.assigningToNotNull, instruction.getRExpression());
    }

    memState.push(dfaDest);

    return nextInstruction(instruction, runner, memState);
  }
예제 #16
0
  @Override
  public boolean checkNotNullable(DfaValue value) {
    if (value == myFactory.getConstFactory().getNull()) return false;
    if (value instanceof DfaTypeValue && ((DfaTypeValue) value).isNullable()) return false;

    if (value instanceof DfaVariableValue) {
      DfaVariableValue varValue = (DfaVariableValue) value;
      if (varValue.getVariableType() instanceof PsiPrimitiveType) return true;
      if (isNotNull(varValue)) return true;
      if (getVariableState(varValue).isNullable()) return false;
    }
    return true;
  }
예제 #17
0
  @Override
  public void flushVariable(@NotNull final DfaVariableValue variable) {
    List<DfaValue> updatedStack = ContainerUtil.map(myStack, value -> handleFlush(variable, value));
    myStack.clear();
    for (DfaValue value : updatedStack) {
      myStack.push(value);
    }

    doFlush(variable, false);
    flushDependencies(variable);
    myUnknownVariables.remove(variable);
    myUnknownVariables.removeAll(myFactory.getVarFactory().getAllQualifiedBy(variable));
    myCachedHash = null;
  }
예제 #18
0
  private boolean applyUnboxedRelation(
      @NotNull DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
    PsiType type = dfaLeft.getVariableType();
    if (!TypeConversionUtil.isPrimitiveWrapper(type)) {
      return true;
    }
    if (negated) {
      // from the fact "wrappers are not the same" it does not follow that "unboxed values are not
      // equal"
      return true;
    }

    DfaBoxedValue.Factory boxedFactory = myFactory.getBoxedFactory();
    DfaValue unboxedLeft = boxedFactory.createUnboxed(dfaLeft);
    DfaValue unboxedRight = boxedFactory.createUnboxed(dfaRight);
    return applyRelation(unboxedLeft, unboxedRight, false)
        && checkCompareWithBooleanLiteral(unboxedLeft, unboxedRight, false);
  }
예제 #19
0
 private boolean checkCompareWithBooleanLiteral(
     DfaValue dfaLeft, DfaValue dfaRight, boolean negated) {
   if (dfaRight instanceof DfaConstValue) {
     Object constVal = ((DfaConstValue) dfaRight).getValue();
     if (constVal instanceof Boolean) {
       DfaConstValue negVal =
           myFactory
               .getConstFactory()
               .createFromValue(!((Boolean) constVal).booleanValue(), PsiType.BOOLEAN, null);
       if (!applyRelation(dfaLeft, negVal, !negated)) {
         return false;
       }
       if (!applyRelation(dfaLeft.createNegated(), negVal, negated)) {
         return false;
       }
     }
   }
   return true;
 }
  @NotNull
  private DfaValue getMethodResultValue(
      MethodCallInstruction instruction,
      @Nullable DfaValue qualifierValue,
      DfaValueFactory factory) {
    DfaValue precalculated = instruction.getPrecalculatedReturnValue();
    if (precalculated != null) {
      return precalculated;
    }

    final PsiType type = instruction.getResultType();
    final MethodCallInstruction.MethodType methodType = instruction.getMethodType();

    if (methodType == MethodCallInstruction.MethodType.UNBOXING) {
      return factory.getBoxedFactory().createUnboxed(qualifierValue);
    }

    if (methodType == MethodCallInstruction.MethodType.BOXING) {
      DfaValue boxed = factory.getBoxedFactory().createBoxed(qualifierValue);
      return boxed == null ? factory.createTypeValue(type, Nullness.NOT_NULL) : boxed;
    }

    if (methodType == MethodCallInstruction.MethodType.CAST) {
      assert qualifierValue != null;
      if (qualifierValue instanceof DfaConstValue) {
        Object casted =
            TypeConversionUtil.computeCastTo(((DfaConstValue) qualifierValue).getValue(), type);
        return factory
            .getConstFactory()
            .createFromValue(casted, type, ((DfaConstValue) qualifierValue).getConstant());
      }
      return qualifierValue;
    }

    if (type != null && (type instanceof PsiClassType || type.getArrayDimensions() > 0)) {
      Nullness nullability = myReturnTypeNullability.get(instruction);
      if (nullability == Nullness.UNKNOWN && factory.isUnknownMembersAreNullable()) {
        nullability = Nullness.NULLABLE;
      }
      return factory.createTypeValue(type, nullability);
    }
    return DfaUnknownValue.getInstance();
  }
예제 #21
0
  void doFlush(@NotNull DfaVariableValue varPlain, boolean markUnknown) {
    DfaVariableValue varNegated = varPlain.getNegatedValue();

    final int idPlain = varPlain.getID();
    final int idNegated = varNegated == null ? -1 : varNegated.getID();

    int[] classes = myIdToEqClassesIndices.get(idPlain);
    int[] negatedClasses = myIdToEqClassesIndices.get(idNegated);
    int[] result =
        ArrayUtil.mergeArrays(
            ObjectUtils.notNull(classes, ArrayUtil.EMPTY_INT_ARRAY),
            ObjectUtils.notNull(negatedClasses, ArrayUtil.EMPTY_INT_ARRAY));

    int interruptCount = 0;

    for (int varClassIndex : result) {
      EqClass varClass = myEqClasses.get(varClassIndex);
      if ((++interruptCount & 0xf) == 0) {
        ProgressManager.checkCanceled();
      }

      varClass = new EqClass(varClass);
      myEqClasses.set(varClassIndex, varClass);
      for (int id : varClass.toNativeArray()) {
        int idUnwrapped;
        if (id == idPlain
            || id == idNegated
            || (idUnwrapped = unwrap(myFactory.getValue(id)).getID()) == idPlain
            || idUnwrapped == idNegated) {
          varClass.removeValue(id);
        }
      }

      if (varClass.isEmpty()) {
        myEqClasses.set(varClassIndex, null);

        for (TLongIterator iterator = myDistinctClasses.iterator(); iterator.hasNext(); ) {
          long pair = iterator.next();
          if (low(pair) == varClassIndex || high(pair) == varClassIndex) {
            iterator.remove();
          }
        }
      } else if (varClass.containsConstantsOnly()) {
        for (TLongIterator iterator = myDistinctClasses.iterator(); iterator.hasNext(); ) {
          long pair = iterator.next();
          if (low(pair) == varClassIndex && myEqClasses.get(high(pair)).containsConstantsOnly()
              || high(pair) == varClassIndex
                  && myEqClasses.get(low(pair)).containsConstantsOnly()) {
            iterator.remove();
          }
        }
      }
    }

    removeAllFromMap(idPlain);
    removeAllFromMap(idNegated);
    myVariableStates.remove(varPlain);
    if (varNegated != null) {
      myVariableStates.remove(varNegated);
    }
    if (markUnknown) {
      myUnknownVariables.add(varPlain);
    }
    myCachedNonTrivialEqClasses = null;
    myCachedDistinctClassPairs = null;
    myCachedHash = null;
  }
예제 #22
0
 private void removeAllFromMap(int id) {
   if (id < 0) return;
   id = unwrap(myFactory.getValue(id)).getID();
   myIdToEqClassesIndices.remove(id);
 }
예제 #23
0
  private boolean uniteClasses(int c1Index, int c2Index) {
    EqClass c1 = myEqClasses.get(c1Index);
    EqClass c2 = myEqClasses.get(c2Index);

    Set<DfaVariableValue> vars = ContainerUtil.newTroveSet();
    Set<DfaVariableValue> negatedVars = ContainerUtil.newTroveSet();
    int[] cs = new int[c1.size() + c2.size()];
    c1.set(0, cs, 0, c1.size());
    c2.set(0, cs, c1.size(), c2.size());

    int nConst = 0;
    for (int c : cs) {
      DfaValue dfaValue = unwrap(myFactory.getValue(c));
      if (dfaValue instanceof DfaConstValue) nConst++;
      if (dfaValue instanceof DfaVariableValue) {
        DfaVariableValue variableValue = (DfaVariableValue) dfaValue;
        if (variableValue.isNegated()) {
          negatedVars.add(variableValue.createNegated());
        } else {
          vars.add(variableValue);
        }
      }
      if (nConst > 1) return false;
    }
    if (ContainerUtil.intersects(vars, negatedVars)) return false;

    TLongArrayList c2Pairs = new TLongArrayList();
    long[] distincts = myDistinctClasses.toArray();
    for (long distinct : distincts) {
      int pc1 = low(distinct);
      int pc2 = high(distinct);
      boolean addedToC1 = false;

      if (pc1 == c1Index || pc2 == c1Index) {
        addedToC1 = true;
      }

      if (pc1 == c2Index || pc2 == c2Index) {
        if (addedToC1) return false;
        c2Pairs.add(distinct);
      }
    }

    EqClass newClass = new EqClass(c1);

    myEqClasses.set(c1Index, newClass);
    for (int i = 0; i < c2.size(); i++) {
      int c = c2.get(i);
      newClass.add(c);
      removeFromMap(c, c2Index);
      addToMap(c, c1Index);
    }

    for (int i = 0; i < c2Pairs.size(); i++) {
      long c = c2Pairs.get(i);
      myDistinctClasses.remove(c);
      myDistinctClasses.add(createPair(c1Index, low(c) == c2Index ? high(c) : low(c)));
    }
    myEqClasses.set(c2Index, null);

    return true;
  }
  private List<DfaMemoryState> addContractResults(
      DfaValue[] argValues,
      MethodContract contract,
      List<DfaMemoryState> states,
      MethodCallInstruction instruction,
      DfaValueFactory factory,
      Set<DfaMemoryState> finalStates) {
    DfaConstValue.Factory constFactory = factory.getConstFactory();
    List<DfaMemoryState> falseStates = ContainerUtil.newArrayList();
    for (int i = 0; i < argValues.length; i++) {
      DfaValue argValue = argValues[i];
      MethodContract.ValueConstraint constraint = contract.arguments[i];
      DfaConstValue expectedValue = constraint.getComparisonValue(factory);
      if (expectedValue == null) continue;

      boolean invertCondition = constraint.shouldUseNonEqComparison();
      DfaValue condition =
          factory
              .getRelationFactory()
              .createRelation(argValue, expectedValue, EQEQ, invertCondition);
      if (condition == null) {
        if (!(argValue instanceof DfaConstValue)) {
          for (DfaMemoryState state : states) {
            falseStates.add(state.createCopy());
          }
          continue;
        }
        condition =
            constFactory.createFromValue(
                (argValue == expectedValue) != invertCondition, PsiType.BOOLEAN, null);
      }

      List<DfaMemoryState> nextStates = ContainerUtil.newArrayList();
      for (DfaMemoryState state : states) {
        boolean unknownVsNull =
            expectedValue == constFactory.getNull()
                && argValue instanceof DfaVariableValue
                && ((DfaMemoryStateImpl) state)
                        .getVariableState((DfaVariableValue) argValue)
                        .getNullability()
                    == Nullness.UNKNOWN;
        DfaMemoryState falseCopy = state.createCopy();
        if (state.applyCondition(condition)) {
          if (unknownVsNull && !invertCondition) {
            state.markEphemeral();
          }
          nextStates.add(state);
        }
        if (falseCopy.applyCondition(condition.createNegated())) {
          if (unknownVsNull && invertCondition) {
            falseCopy.markEphemeral();
          }
          falseStates.add(falseCopy);
        }
      }
      states = nextStates;
    }

    for (DfaMemoryState state : states) {
      state.push(getDfaContractReturnValue(contract, instruction, factory));
      finalStates.add(state);
    }

    return falseStates;
  }
예제 #25
0
  private boolean applyRelationCondition(@NotNull DfaRelationValue dfaRelation) {
    DfaValue dfaLeft = dfaRelation.getLeftOperand();
    DfaValue dfaRight = dfaRelation.getRightOperand();
    if (dfaLeft instanceof DfaUnknownValue || dfaRight instanceof DfaUnknownValue) return true;

    boolean isNegated = dfaRelation.isNegated();
    if (dfaLeft instanceof DfaTypeValue
        && ((DfaTypeValue) dfaLeft).isNotNull()
        && dfaRight == myFactory.getConstFactory().getNull()) {
      return isNegated;
    }

    if (dfaRight instanceof DfaTypeValue) {
      if (dfaLeft instanceof DfaVariableValue) {
        DfaVariableValue dfaVar = (DfaVariableValue) dfaLeft;
        if (isUnknownState(dfaVar)) return true;

        if (!dfaRelation.isInstanceOf()) {
          if (((DfaTypeValue) dfaRight).isNotNull() && isNull(dfaVar)) {
            return isNegated;
          }
          return true;
        }

        if (isNegated) {
          DfaVariableState newState =
              getVariableState(dfaVar).withNotInstanceofValue((DfaTypeValue) dfaRight);
          if (newState != null) {
            setVariableState(dfaVar, newState);
            return true;
          }
          return !getVariableState(dfaVar).isNotNull()
              && applyRelation(dfaVar, myFactory.getConstFactory().getNull(), false);
        }
        if (applyRelation(dfaVar, myFactory.getConstFactory().getNull(), true)) {
          DfaVariableState newState =
              getVariableState(dfaVar).withInstanceofValue((DfaTypeValue) dfaRight);
          if (newState != null) {
            setVariableState(dfaVar, newState);
            return true;
          }
        }
        return false;
      }
      return true;
    }

    if (isEffectivelyNaN(dfaLeft) || isEffectivelyNaN(dfaRight)) {
      applyEquivalenceRelation(dfaRelation, dfaLeft, dfaRight);
      return isNegated;
    }
    if (canBeNaN(dfaLeft) && canBeNaN(dfaRight)) {
      if (dfaLeft == dfaRight
          && dfaLeft instanceof DfaVariableValue
          && !(((DfaVariableValue) dfaLeft).getVariableType() instanceof PsiPrimitiveType)) {
        return !isNegated;
      }

      applyEquivalenceRelation(dfaRelation, dfaLeft, dfaRight);
      return true;
    }

    return applyEquivalenceRelation(dfaRelation, dfaLeft, dfaRight);
  }
예제 #26
0
 void flushDependencies(@NotNull DfaVariableValue variable) {
   for (DfaVariableValue dependent : myFactory.getVarFactory().getAllQualifiedBy(variable)) {
     doFlush(dependent, false);
   }
 }