mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
notnull
This commit is contained in:
+2
-1
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -63,6 +63,7 @@ public class ExpressionTypeMemoryState extends DfaMemoryStateImpl {
|
||||
super(toCopy);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DfaMemoryStateImpl createCopy() {
|
||||
final ExpressionTypeMemoryState copy = new ExpressionTypeMemoryState(this);
|
||||
|
||||
+5
-4
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,10 +17,10 @@ package com.intellij.codeInsight.guess.impl;
|
||||
|
||||
import com.intellij.codeInsight.guess.GuessManager;
|
||||
import com.intellij.codeInspection.dataFlow.*;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.PushInstruction;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.TypeCastInstruction;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.InstanceofInstruction;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.MethodCallInstruction;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.PushInstruction;
|
||||
import com.intellij.codeInspection.dataFlow.instructions.TypeCastInstruction;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaInstanceofValue;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
@@ -31,8 +31,8 @@ import com.intellij.psi.search.PsiElementProcessorAdapter;
|
||||
import com.intellij.psi.search.SearchScope;
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
||||
import com.intellij.psi.search.searches.ReferencesSearch;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import gnu.trove.THashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
@@ -151,6 +151,7 @@ public class GuessManagerImpl extends GuessManager {
|
||||
}
|
||||
|
||||
DataFlowRunner runner = new DataFlowRunner() {
|
||||
@NotNull
|
||||
@Override
|
||||
protected DfaMemoryState createMemoryState() {
|
||||
return new ExpressionTypeMemoryState(getFactory());
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2014 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -25,6 +25,7 @@ import com.intellij.codeInspection.dataFlow.value.DfaValueFactory;
|
||||
import com.intellij.codeInspection.dataFlow.value.DfaVariableValue;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -39,7 +40,7 @@ class ContractChecker extends DataFlowRunner {
|
||||
private final Set<PsiElement> myNonViolations = ContainerUtil.newHashSet();
|
||||
private final Set<PsiElement> myFailures = ContainerUtil.newHashSet();
|
||||
|
||||
ContractChecker(PsiMethod method, MethodContract contract, final boolean onTheFly) {
|
||||
private ContractChecker(PsiMethod method, MethodContract contract, final boolean onTheFly) {
|
||||
myMethod = method;
|
||||
myContract = contract;
|
||||
myOnTheFly = onTheFly;
|
||||
@@ -77,8 +78,9 @@ class ContractChecker extends DataFlowRunner {
|
||||
return super.shouldCheckTimeLimit();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected DfaInstructionState[] acceptInstruction(InstructionVisitor visitor, DfaInstructionState instructionState) {
|
||||
protected DfaInstructionState[] acceptInstruction(@NotNull InstructionVisitor visitor, @NotNull DfaInstructionState instructionState) {
|
||||
DfaMemoryState memState = instructionState.getMemoryState();
|
||||
if (memState.isEphemeral()) {
|
||||
return DfaInstructionState.EMPTY_ARRAY;
|
||||
|
||||
+29
-21
@@ -52,11 +52,12 @@ public class DataFlowRunner {
|
||||
|
||||
private Instruction[] myInstructions;
|
||||
private final MultiMap<PsiElement, DfaMemoryState> myNestedClosures = new MultiMap<PsiElement, DfaMemoryState>();
|
||||
@NotNull
|
||||
private final DfaValueFactory myValueFactory;
|
||||
|
||||
// Maximum allowed attempts to process instruction. Fail as too complex to process if certain instruction
|
||||
// is executed more than this limit times.
|
||||
public static final int MAX_STATES_PER_BRANCH = 300;
|
||||
static final int MAX_STATES_PER_BRANCH = 300;
|
||||
|
||||
protected DataFlowRunner() {
|
||||
this(false, true);
|
||||
@@ -66,12 +67,13 @@ public class DataFlowRunner {
|
||||
myValueFactory = new DfaValueFactory(honorFieldInitializers, unknownMembersAreNullable);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DfaValueFactory getFactory() {
|
||||
return myValueFactory;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Collection<DfaMemoryState> createInitialStates(@NotNull PsiElement psiBlock, InstructionVisitor visitor) {
|
||||
private Collection<DfaMemoryState> createInitialStates(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
|
||||
PsiClass containingClass = PsiTreeUtil.getParentOfType(psiBlock, PsiClass.class);
|
||||
if (containingClass != null && PsiUtil.isLocalOrAnonymousClass(containingClass)) {
|
||||
final PsiElement parent = containingClass.getParent();
|
||||
@@ -91,16 +93,17 @@ public class DataFlowRunner {
|
||||
return Collections.singletonList(createMemoryState());
|
||||
}
|
||||
|
||||
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, InstructionVisitor visitor) {
|
||||
@NotNull
|
||||
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock, @NotNull InstructionVisitor visitor) {
|
||||
Collection<DfaMemoryState> initialStates = createInitialStates(psiBlock, visitor);
|
||||
return initialStates == null ? RunnerResult.NOT_APPLICABLE : analyzeMethod(psiBlock, visitor, false, initialStates);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock,
|
||||
InstructionVisitor visitor,
|
||||
boolean ignoreAssertions,
|
||||
@NotNull Collection<DfaMemoryState> initialStates) {
|
||||
final RunnerResult analyzeMethod(@NotNull PsiElement psiBlock,
|
||||
@NotNull InstructionVisitor visitor,
|
||||
boolean ignoreAssertions,
|
||||
@NotNull Collection<DfaMemoryState> initialStates) {
|
||||
if (PsiTreeUtil.findChildOfType(psiBlock, OuterLanguageElement.class) != null) return RunnerResult.NOT_APPLICABLE;
|
||||
|
||||
try {
|
||||
@@ -127,7 +130,7 @@ public class DataFlowRunner {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Analyzing code block: " + psiBlock.getText());
|
||||
for (int i = 0; i < myInstructions.length; i++) {
|
||||
LOG.debug(i + ": " + myInstructions[i].toString());
|
||||
LOG.debug(i + ": " + myInstructions[i]);
|
||||
}
|
||||
}
|
||||
//for (int i = 0; i < myInstructions.length; i++) System.out.println(i + ": " + myInstructions[i].toString());
|
||||
@@ -220,10 +223,11 @@ public class DataFlowRunner {
|
||||
private void handleStepOutOfLoop(@NotNull final Instruction prevInstruction,
|
||||
@NotNull Instruction nextInstruction,
|
||||
@NotNull final int[] loopNumber,
|
||||
MultiMap<BranchingInstruction, DfaMemoryState> processedStates,
|
||||
MultiMap<BranchingInstruction, DfaMemoryState> incomingStates,
|
||||
List<DfaInstructionState> inFlightStates,
|
||||
DfaInstructionState[] afterStates, StateQueue queue) {
|
||||
@NotNull MultiMap<BranchingInstruction, DfaMemoryState> processedStates,
|
||||
@NotNull MultiMap<BranchingInstruction, DfaMemoryState> incomingStates,
|
||||
@NotNull List<DfaInstructionState> inFlightStates,
|
||||
@NotNull DfaInstructionState[] afterStates,
|
||||
@NotNull StateQueue queue) {
|
||||
if (loopNumber[prevInstruction.getIndex()] == 0 || inSameLoop(prevInstruction, nextInstruction, loopNumber)) {
|
||||
return;
|
||||
}
|
||||
@@ -247,10 +251,7 @@ public class DataFlowRunner {
|
||||
@Override
|
||||
public boolean process(DfaInstructionState state) {
|
||||
Instruction instruction = state.getInstruction();
|
||||
if (inSameLoop(prevInstruction, instruction, loopNumber)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return !inSameLoop(prevInstruction, instruction, loopNumber);
|
||||
}
|
||||
})) return;
|
||||
|
||||
@@ -276,7 +277,8 @@ public class DataFlowRunner {
|
||||
return !ApplicationManager.getApplication().isUnitTestMode();
|
||||
}
|
||||
|
||||
protected DfaInstructionState[] acceptInstruction(InstructionVisitor visitor, DfaInstructionState instructionState) {
|
||||
@NotNull
|
||||
protected DfaInstructionState[] acceptInstruction(@NotNull InstructionVisitor visitor, @NotNull DfaInstructionState instructionState) {
|
||||
Instruction instruction = instructionState.getInstruction();
|
||||
PsiElement closure = DfaUtil.getClosureInside(instruction);
|
||||
if (closure instanceof PsiClass) {
|
||||
@@ -288,7 +290,7 @@ public class DataFlowRunner {
|
||||
return instruction.accept(this, instructionState.getMemoryState(), visitor);
|
||||
}
|
||||
|
||||
private void registerNestedClosures(DfaInstructionState instructionState, PsiClass nestedClass) {
|
||||
private void registerNestedClosures(@NotNull DfaInstructionState instructionState, @NotNull PsiClass nestedClass) {
|
||||
DfaMemoryState state = instructionState.getMemoryState();
|
||||
for (PsiMethod method : nestedClass.getMethods()) {
|
||||
PsiCodeBlock body = method.getBody();
|
||||
@@ -304,7 +306,7 @@ public class DataFlowRunner {
|
||||
}
|
||||
}
|
||||
|
||||
private void registerNestedClosures(DfaInstructionState instructionState, PsiLambdaExpression expr) {
|
||||
private void registerNestedClosures(@NotNull DfaInstructionState instructionState, @NotNull PsiLambdaExpression expr) {
|
||||
DfaMemoryState state = instructionState.getMemoryState();
|
||||
PsiElement body = expr.getBody();
|
||||
if (body != null) {
|
||||
@@ -312,22 +314,27 @@ public class DataFlowRunner {
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
protected DfaMemoryState createMemoryState() {
|
||||
return new DfaMemoryStateImpl(myValueFactory);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Instruction[] getInstructions() {
|
||||
return myInstructions;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Instruction getInstruction(int index) {
|
||||
return myInstructions[index];
|
||||
}
|
||||
|
||||
public MultiMap<PsiElement, DfaMemoryState> getNestedClosures() {
|
||||
@NotNull
|
||||
MultiMap<PsiElement, DfaMemoryState> getNestedClosures() {
|
||||
return new MultiMap<PsiElement, DfaMemoryState>(myNestedClosures);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Pair<Set<Instruction>,Set<Instruction>> getConstConditionalExpressions() {
|
||||
Set<Instruction> trueSet = new HashSet<Instruction>();
|
||||
Set<Instruction> falseSet = new HashSet<Instruction>();
|
||||
@@ -362,7 +369,8 @@ public class DataFlowRunner {
|
||||
return Pair.create(trueSet, falseSet);
|
||||
}
|
||||
|
||||
private static DfaMemoryStateImpl createClosureState(DfaMemoryState memState) {
|
||||
@NotNull
|
||||
private static DfaMemoryStateImpl createClosureState(@NotNull DfaMemoryState memState) {
|
||||
DfaMemoryStateImpl copy = (DfaMemoryStateImpl)memState.createCopy();
|
||||
copy.flushFields();
|
||||
Set<DfaVariableValue> vars = new HashSet<DfaVariableValue>(copy.getVariableStates().keySet());
|
||||
|
||||
+4
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,6 +30,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* To change this template use Options | File Templates.
|
||||
*/
|
||||
public interface DfaMemoryState {
|
||||
@NotNull
|
||||
DfaMemoryState createCopy();
|
||||
|
||||
DfaValue pop();
|
||||
@@ -40,7 +41,7 @@ public interface DfaMemoryState {
|
||||
|
||||
void setVarValue(DfaVariableValue var, DfaValue value);
|
||||
|
||||
boolean applyInstanceofOrNull(DfaRelationValue dfaCond);
|
||||
boolean applyInstanceofOrNull(@NotNull DfaRelationValue dfaCond);
|
||||
|
||||
boolean applyCondition(DfaValue dfaCond);
|
||||
|
||||
@@ -55,7 +56,7 @@ public interface DfaMemoryState {
|
||||
boolean isNotNull(DfaValue dfaVar);
|
||||
|
||||
@Nullable
|
||||
DfaConstValue getConstantValue(DfaVariableValue value);
|
||||
DfaConstValue getConstantValue(@NotNull DfaVariableValue value);
|
||||
|
||||
/**
|
||||
* Ephemeral means a state that was created when considering a method contract and checking if one of its arguments is null.
|
||||
|
||||
+27
-21
@@ -59,7 +59,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
private final LinkedHashSet<DfaVariableValue> myUnknownVariables;
|
||||
private boolean myEphemeral;
|
||||
|
||||
public DfaMemoryStateImpl(final DfaValueFactory factory) {
|
||||
protected DfaMemoryStateImpl(final DfaValueFactory factory) {
|
||||
myFactory = factory;
|
||||
myDefaultVariableStates = ContainerUtil.newTroveMap();
|
||||
myEqClasses = ContainerUtil.newArrayList();
|
||||
@@ -95,10 +95,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
myCachedHash = toCopy.myCachedHash;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DfaValueFactory getFactory() {
|
||||
return myFactory;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public DfaMemoryStateImpl createCopy() {
|
||||
return new DfaMemoryStateImpl(this);
|
||||
@@ -112,7 +114,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return equalsSuperficially(that) && equalsByUnknownVariables(that) && equalsByRelations(that) && equalsByVariableStates(that);
|
||||
}
|
||||
|
||||
boolean equalsByUnknownVariables(DfaMemoryStateImpl that) {
|
||||
private boolean equalsByUnknownVariables(DfaMemoryStateImpl that) {
|
||||
return myUnknownVariables.equals(that.myUnknownVariables);
|
||||
}
|
||||
|
||||
@@ -178,7 +180,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return hash;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"HardCodedStringLiteral"})
|
||||
@SuppressWarnings("HardCodedStringLiteral")
|
||||
public String toString() {
|
||||
StringBuilder result = new StringBuilder();
|
||||
result.append('<');
|
||||
@@ -285,7 +287,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
|
||||
@Nullable("for boxed values which can't be compared by ==")
|
||||
private Integer getOrCreateEqClassIndex(DfaValue dfaValue) {
|
||||
private Integer getOrCreateEqClassIndex(@NotNull DfaValue dfaValue) {
|
||||
int i = getEqClassIndex(dfaValue);
|
||||
if (i != -1) return i;
|
||||
if (!canBeInRelation(dfaValue) ||
|
||||
@@ -340,7 +342,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
|
||||
|
||||
private static boolean canBeInRelation(DfaValue dfaValue) {
|
||||
private static boolean canBeInRelation(@NotNull DfaValue dfaValue) {
|
||||
DfaValue unwrapped = unwrap(dfaValue);
|
||||
return unwrapped instanceof DfaVariableValue || unwrapped instanceof DfaConstValue;
|
||||
}
|
||||
@@ -393,7 +395,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean canBeReused(final DfaValue dfaValue) {
|
||||
private boolean canBeReused(@NotNull DfaValue dfaValue) {
|
||||
if (dfaValue instanceof DfaBoxedValue) {
|
||||
DfaValue valueToWrap = ((DfaBoxedValue)dfaValue).getWrappedValue();
|
||||
if (valueToWrap instanceof DfaConstValue) {
|
||||
@@ -410,12 +412,12 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean cacheable(DfaConstValue dfaConstValue) {
|
||||
private static boolean cacheable(@NotNull DfaConstValue dfaConstValue) {
|
||||
Object value = dfaConstValue.getValue();
|
||||
return box(value) == box(value);
|
||||
}
|
||||
|
||||
@SuppressWarnings({"UnnecessaryBoxing"})
|
||||
@SuppressWarnings("UnnecessaryBoxing")
|
||||
private static Object box(final Object value) {
|
||||
Object newBoxedValue;
|
||||
if (value instanceof Integer) {
|
||||
@@ -577,7 +579,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public DfaConstValue getConstantValue(DfaVariableValue value) {
|
||||
public DfaConstValue getConstantValue(@NotNull DfaVariableValue value) {
|
||||
int index = getEqClassIndex(value);
|
||||
EqClass ec = index == -1 ? null : myEqClasses.get(index);
|
||||
return ec == null ? null : (DfaConstValue)unwrap(ec.findConstant(true));
|
||||
@@ -594,7 +596,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyInstanceofOrNull(DfaRelationValue dfaCond) {
|
||||
public boolean applyInstanceofOrNull(@NotNull DfaRelationValue dfaCond) {
|
||||
DfaValue left = unwrap(dfaCond.getLeftOperand());
|
||||
|
||||
if (!(left instanceof DfaVariableValue)) return true;
|
||||
@@ -648,7 +650,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return applyRelationCondition((DfaRelationValue)dfaCond);
|
||||
}
|
||||
|
||||
private boolean applyRelationCondition(DfaRelationValue dfaRelation) {
|
||||
private boolean applyRelationCondition(@NotNull DfaRelationValue dfaRelation) {
|
||||
DfaValue dfaLeft = dfaRelation.getLeftOperand();
|
||||
DfaValue dfaRight = dfaRelation.getRightOperand();
|
||||
if (dfaLeft instanceof DfaUnknownValue || dfaRight instanceof DfaUnknownValue) return true;
|
||||
@@ -702,7 +704,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return applyEquivalenceRelation(dfaRelation, dfaLeft, dfaRight);
|
||||
}
|
||||
|
||||
private void updateVarStateOnComparison(DfaVariableValue dfaVar, DfaValue value) {
|
||||
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));
|
||||
@@ -713,7 +715,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean applyEquivalenceRelation(DfaRelationValue dfaRelation, DfaValue dfaLeft, DfaValue dfaRight) {
|
||||
private boolean applyEquivalenceRelation(@NotNull DfaRelationValue dfaRelation, DfaValue dfaLeft, DfaValue dfaRight) {
|
||||
boolean isNegated = dfaRelation.isNonEquality();
|
||||
if (!isNegated && !dfaRelation.isEquality()) {
|
||||
return true;
|
||||
@@ -761,7 +763,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean applyBoxedRelation(DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
|
||||
private boolean applyBoxedRelation(@NotNull DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
|
||||
if (!TypeConversionUtil.isPrimitiveAndNotNull(dfaLeft.getVariableType())) return true;
|
||||
|
||||
DfaBoxedValue.Factory boxedFactory = myFactory.getBoxedFactory();
|
||||
@@ -770,7 +772,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return boxedLeft == null || boxedRight == null || applyRelation(boxedLeft, boxedRight, negated);
|
||||
}
|
||||
|
||||
private boolean applyUnboxedRelation(DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
|
||||
private boolean applyUnboxedRelation(@NotNull DfaVariableValue dfaLeft, DfaValue dfaRight, boolean negated) {
|
||||
PsiType type = dfaLeft.getVariableType();
|
||||
if (!TypeConversionUtil.isPrimitiveWrapper(type)) {
|
||||
return true;
|
||||
@@ -912,7 +914,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
myCachedHash = null;
|
||||
}
|
||||
|
||||
public DfaVariableState getVariableState(DfaVariableValue dfaVar) {
|
||||
DfaVariableState getVariableState(DfaVariableValue dfaVar) {
|
||||
DfaVariableState state = myVariableStates.get(dfaVar);
|
||||
|
||||
if (state == null) {
|
||||
@@ -935,11 +937,13 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return state;
|
||||
}
|
||||
|
||||
protected Map<DfaVariableValue, DfaVariableState> getVariableStates() {
|
||||
@NotNull
|
||||
Map<DfaVariableValue, DfaVariableState> getVariableStates() {
|
||||
return myVariableStates;
|
||||
}
|
||||
|
||||
protected DfaVariableState createVariableState(final DfaVariableValue var) {
|
||||
@NotNull
|
||||
protected DfaVariableState createVariableState(@NotNull DfaVariableValue var) {
|
||||
return new DfaVariableState(var);
|
||||
}
|
||||
|
||||
@@ -958,7 +962,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldMarkUnknown(DfaVariableValue value) {
|
||||
private boolean shouldMarkUnknown(@NotNull DfaVariableValue value) {
|
||||
int eqClassIndex = getEqClassIndex(value);
|
||||
if (eqClassIndex < 0) return false;
|
||||
|
||||
@@ -975,6 +979,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Set<DfaVariableValue> getChangedVariables() {
|
||||
return myVariableStates.keySet();
|
||||
}
|
||||
@@ -999,17 +1004,18 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
myCachedHash = null;
|
||||
}
|
||||
|
||||
public void flushDependencies(DfaVariableValue variable) {
|
||||
void flushDependencies(@NotNull DfaVariableValue variable) {
|
||||
for (DfaVariableValue dependent : myFactory.getVarFactory().getAllQualifiedBy(variable)) {
|
||||
doFlush(dependent, false);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Set<DfaVariableValue> getUnknownVariables() {
|
||||
return myUnknownVariables;
|
||||
}
|
||||
|
||||
void doFlush(DfaVariableValue varPlain, boolean markUnknown) {
|
||||
void doFlush(@NotNull DfaVariableValue varPlain, boolean markUnknown) {
|
||||
DfaVariableValue varNegated = varPlain.getNegatedValue();
|
||||
|
||||
final int idPlain = varPlain.getID();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -155,8 +155,9 @@ public class DfaPsiUtil {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected DfaInstructionState[] acceptInstruction(InstructionVisitor visitor, DfaInstructionState instructionState) {
|
||||
protected DfaInstructionState[] acceptInstruction(@NotNull InstructionVisitor visitor, @NotNull DfaInstructionState instructionState) {
|
||||
Instruction instruction = instructionState.getInstruction();
|
||||
if (isCallExposingNonInitializedFields(instruction) ||
|
||||
instruction instanceof ReturnInstruction && !((ReturnInstruction)instruction).isViaException()) {
|
||||
|
||||
+22
-15
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,18 +40,19 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class DfaVariableState {
|
||||
protected final Set<DfaPsiType> myInstanceofValues;
|
||||
protected final Set<DfaPsiType> myNotInstanceofValues;
|
||||
protected final Nullness myNullability;
|
||||
class DfaVariableState {
|
||||
@NotNull final Set<DfaPsiType> myInstanceofValues;
|
||||
@NotNull final Set<DfaPsiType> myNotInstanceofValues;
|
||||
@NotNull final Nullness myNullability;
|
||||
private final int myHash;
|
||||
|
||||
public DfaVariableState(@NotNull DfaVariableValue dfaVar) {
|
||||
DfaVariableState(@NotNull DfaVariableValue dfaVar) {
|
||||
this(Collections.<DfaPsiType>emptySet(), Collections.<DfaPsiType>emptySet(), dfaVar.getInherentNullability());
|
||||
}
|
||||
|
||||
protected DfaVariableState(Set<DfaPsiType> instanceofValues,
|
||||
Set<DfaPsiType> notInstanceofValues, Nullness nullability) {
|
||||
DfaVariableState(@NotNull Set<DfaPsiType> instanceofValues,
|
||||
@NotNull Set<DfaPsiType> notInstanceofValues,
|
||||
@NotNull Nullness nullability) {
|
||||
myInstanceofValues = instanceofValues;
|
||||
myNotInstanceofValues = notInstanceofValues;
|
||||
myNullability = nullability;
|
||||
@@ -62,7 +63,7 @@ public class DfaVariableState {
|
||||
return myNullability == Nullness.NULLABLE;
|
||||
}
|
||||
|
||||
private boolean checkInstanceofValue(DfaPsiType dfaType) {
|
||||
private boolean checkInstanceofValue(@NotNull DfaPsiType dfaType) {
|
||||
if (myInstanceofValues.contains(dfaType)) return true;
|
||||
|
||||
for (DfaPsiType dfaTypeValue : myNotInstanceofValues) {
|
||||
@@ -77,7 +78,7 @@ public class DfaVariableState {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DfaVariableState withInstanceofValue(DfaTypeValue dfaType) {
|
||||
DfaVariableState withInstanceofValue(@NotNull DfaTypeValue dfaType) {
|
||||
if (dfaType.getDfaType().getPsiType() instanceof PsiPrimitiveType) return this;
|
||||
|
||||
if (checkInstanceofValue(dfaType.getDfaType())) {
|
||||
@@ -103,7 +104,7 @@ public class DfaVariableState {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public DfaVariableState withNotInstanceofValue(DfaTypeValue dfaType) {
|
||||
DfaVariableState withNotInstanceofValue(@NotNull DfaTypeValue dfaType) {
|
||||
if (myNotInstanceofValues.contains(dfaType.getDfaType())) return this;
|
||||
|
||||
for (DfaPsiType dfaTypeValue : myInstanceofValues) {
|
||||
@@ -126,7 +127,8 @@ public class DfaVariableState {
|
||||
return createCopy(myInstanceofValues, newNotInstanceof, myNullability);
|
||||
}
|
||||
|
||||
DfaVariableState withoutType(DfaPsiType type) {
|
||||
@NotNull
|
||||
DfaVariableState withoutType(@NotNull DfaPsiType type) {
|
||||
if (myInstanceofValues.contains(type)) {
|
||||
HashSet<DfaPsiType> newInstanceof = ContainerUtil.newHashSet(myInstanceofValues);
|
||||
newInstanceof.remove(type);
|
||||
@@ -154,7 +156,8 @@ public class DfaVariableState {
|
||||
myNotInstanceofValues.equals(aState.myNotInstanceofValues);
|
||||
}
|
||||
|
||||
protected DfaVariableState createCopy(Set<DfaPsiType> instanceofValues, Set<DfaPsiType> notInstanceofValues, Nullness nullability) {
|
||||
@NotNull
|
||||
protected DfaVariableState createCopy(@NotNull Set<DfaPsiType> instanceofValues, @NotNull Set<DfaPsiType> notInstanceofValues, @NotNull Nullness nullability) {
|
||||
return new DfaVariableState(instanceofValues, notInstanceofValues, nullability);
|
||||
}
|
||||
|
||||
@@ -172,7 +175,8 @@ public class DfaVariableState {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public Nullness getNullability() {
|
||||
@NotNull
|
||||
Nullness getNullability() {
|
||||
return myNullability;
|
||||
}
|
||||
|
||||
@@ -180,14 +184,17 @@ public class DfaVariableState {
|
||||
return myNullability == Nullness.NOT_NULL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
DfaVariableState withNullability(@NotNull Nullness nullness) {
|
||||
return myNullability == nullness ? this : createCopy(myInstanceofValues, myNotInstanceofValues, nullness);
|
||||
}
|
||||
|
||||
public DfaVariableState withNullable(final boolean nullable) {
|
||||
@NotNull
|
||||
DfaVariableState withNullable(final boolean nullable) {
|
||||
return myNullability != Nullness.NOT_NULL ? withNullability(nullable ? Nullness.NULLABLE : Nullness.UNKNOWN) : this;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DfaVariableState withValue(DfaValue value) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2013 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -32,11 +32,11 @@ import java.util.*;
|
||||
* @author peter
|
||||
*/
|
||||
class StateMerger {
|
||||
private final Map<DfaMemoryStateImpl, LinkedHashSet<Fact>> myFacts = ContainerUtil.newIdentityHashMap();
|
||||
private final Map<DfaMemoryStateImpl, Set<Fact>> myFacts = ContainerUtil.newIdentityHashMap();
|
||||
private final Map<DfaMemoryState, Map<DfaVariableValue, DfaMemoryStateImpl>> myCopyCache = ContainerUtil.newIdentityHashMap();
|
||||
|
||||
@Nullable
|
||||
List<DfaMemoryStateImpl> mergeByFacts(List<DfaMemoryStateImpl> states) {
|
||||
List<DfaMemoryStateImpl> mergeByFacts(@NotNull List<DfaMemoryStateImpl> states) {
|
||||
MultiMap<Fact, DfaMemoryStateImpl> statesByFact = MultiMap.createLinked();
|
||||
for (DfaMemoryStateImpl state : states) {
|
||||
ProgressManager.checkCanceled();
|
||||
@@ -84,8 +84,8 @@ class StateMerger {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private MultiMap<Set<Fact>, DfaMemoryStateImpl> mapByUnrelatedFacts(Fact fact,
|
||||
Collection<DfaMemoryStateImpl> states1) {
|
||||
private MultiMap<Set<Fact>, DfaMemoryStateImpl> mapByUnrelatedFacts(@NotNull Fact fact,
|
||||
@NotNull Collection<DfaMemoryStateImpl> states1) {
|
||||
MultiMap<Set<Fact>, DfaMemoryStateImpl> statesByUnrelatedFacts1 = MultiMap.createLinked();
|
||||
for (DfaMemoryStateImpl state : states1) {
|
||||
statesByUnrelatedFacts1.putValue(getUnrelatedFacts(fact, state), state);
|
||||
@@ -93,7 +93,8 @@ class StateMerger {
|
||||
return statesByUnrelatedFacts1;
|
||||
}
|
||||
|
||||
private LinkedHashSet<Fact> getUnrelatedFacts(final Fact fact, DfaMemoryStateImpl state) {
|
||||
@NotNull
|
||||
private LinkedHashSet<Fact> getUnrelatedFacts(@NotNull final Fact fact, @NotNull DfaMemoryStateImpl state) {
|
||||
return new LinkedHashSet<Fact>(ContainerUtil.filter(getFacts(state), new Condition<Fact>() {
|
||||
@Override
|
||||
public boolean value(Fact another) {
|
||||
@@ -102,10 +103,10 @@ class StateMerger {
|
||||
}));
|
||||
}
|
||||
|
||||
private void restoreOtherInequalities(Fact removedFact, Collection<DfaMemoryStateImpl> mergedGroup, DfaMemoryStateImpl state) {
|
||||
private void restoreOtherInequalities(@NotNull Fact removedFact, @NotNull Collection<DfaMemoryStateImpl> mergedGroup, @NotNull DfaMemoryStateImpl state) {
|
||||
Set<DfaConstValue> inequalitiesToRestore = null;
|
||||
for (DfaMemoryStateImpl member : mergedGroup) {
|
||||
LinkedHashSet<Fact> memberFacts = getFacts(member);
|
||||
Set<Fact> memberFacts = getFacts(member);
|
||||
if (memberFacts.contains(removedFact)) {
|
||||
Set<DfaConstValue> otherInequalities = getOtherInequalities(removedFact, memberFacts, member);
|
||||
if (inequalitiesToRestore == null) {
|
||||
@@ -123,7 +124,8 @@ class StateMerger {
|
||||
}
|
||||
}
|
||||
|
||||
private static Set<DfaConstValue> getOtherInequalities(Fact removedFact, LinkedHashSet<Fact> memberFacts, DfaMemoryStateImpl state) {
|
||||
@NotNull
|
||||
private static Set<DfaConstValue> getOtherInequalities(@NotNull Fact removedFact, @NotNull Set<Fact> memberFacts, @NotNull DfaMemoryStateImpl state) {
|
||||
Set<DfaConstValue> otherInequalities = ContainerUtil.newLinkedHashSet();
|
||||
Set<DfaValue> eqValues = ContainerUtil.newHashSet(state.getEquivalentValues((DfaValue)removedFact.myArg));
|
||||
for (Fact candidate : memberFacts) {
|
||||
@@ -136,7 +138,8 @@ class StateMerger {
|
||||
return otherInequalities;
|
||||
}
|
||||
|
||||
private static Set<DfaVariableValue> getAllUnknownVariables(Collection<DfaMemoryStateImpl> complementary) {
|
||||
@NotNull
|
||||
private static Set<DfaVariableValue> getAllUnknownVariables(@NotNull Collection<DfaMemoryStateImpl> complementary) {
|
||||
final Set<DfaVariableValue> toFlush = ContainerUtil.newLinkedHashSet();
|
||||
for (DfaMemoryStateImpl removedState : complementary) {
|
||||
toFlush.addAll(removedState.getUnknownVariables());
|
||||
@@ -144,7 +147,8 @@ class StateMerger {
|
||||
return toFlush;
|
||||
}
|
||||
|
||||
private static DfaMemoryStateImpl withUnknownVariables(DfaMemoryStateImpl original, Set<DfaVariableValue> toFlush) {
|
||||
@NotNull
|
||||
private static DfaMemoryStateImpl withUnknownVariables(@NotNull DfaMemoryStateImpl original, @NotNull Set<DfaVariableValue> toFlush) {
|
||||
DfaMemoryStateImpl copy = original.createCopy();
|
||||
for (DfaVariableValue value : toFlush) {
|
||||
copy.doFlush(value, true);
|
||||
@@ -153,7 +157,7 @@ class StateMerger {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<DfaMemoryStateImpl> mergeByUnknowns(List<DfaMemoryStateImpl> states) {
|
||||
List<DfaMemoryStateImpl> mergeByUnknowns(@NotNull List<DfaMemoryStateImpl> states) {
|
||||
MultiMap<Integer, DfaMemoryStateImpl> byHash = new MultiMap<Integer, DfaMemoryStateImpl>();
|
||||
for (DfaMemoryStateImpl state : states) {
|
||||
ProgressManager.checkCanceled();
|
||||
@@ -181,7 +185,7 @@ class StateMerger {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public List<DfaMemoryStateImpl> mergeByNullability(List<DfaMemoryStateImpl> states) {
|
||||
List<DfaMemoryStateImpl> mergeByNullability(List<DfaMemoryStateImpl> states) {
|
||||
MultiMap<Integer, DfaMemoryStateImpl> byHash = new MultiMap<Integer, DfaMemoryStateImpl>();
|
||||
for (DfaMemoryStateImpl state : states) {
|
||||
ProgressManager.checkCanceled();
|
||||
@@ -217,7 +221,7 @@ class StateMerger {
|
||||
return replacements.getMergeResult();
|
||||
}
|
||||
|
||||
private static boolean mergeUnknowns(Replacements replacements, List<DfaMemoryStateImpl> complementary) {
|
||||
private static boolean mergeUnknowns(@NotNull Replacements replacements, @NotNull List<DfaMemoryStateImpl> complementary) {
|
||||
if (complementary.size() < 2) return false;
|
||||
|
||||
final Set<DfaVariableValue> toFlush = getAllUnknownVariables(complementary);
|
||||
@@ -231,13 +235,14 @@ class StateMerger {
|
||||
});
|
||||
}
|
||||
|
||||
private boolean areEquivalentModuloVar(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue var) {
|
||||
private boolean areEquivalentModuloVar(@NotNull DfaMemoryStateImpl state1, @NotNull DfaMemoryStateImpl state2, @NotNull DfaVariableValue var) {
|
||||
DfaMemoryStateImpl copy1 = copyWithoutVar(state1, var);
|
||||
DfaMemoryStateImpl copy2 = copyWithoutVar(state2, var);
|
||||
return copy2.equalsByRelations(copy1) && copy2.equalsByVariableStates(copy1);
|
||||
}
|
||||
|
||||
private DfaMemoryStateImpl copyWithoutVar(DfaMemoryStateImpl state, DfaVariableValue var) {
|
||||
@NotNull
|
||||
private DfaMemoryStateImpl copyWithoutVar(@NotNull DfaMemoryStateImpl state, @NotNull DfaVariableValue var) {
|
||||
Map<DfaVariableValue, DfaMemoryStateImpl> map = myCopyCache.get(state);
|
||||
if (map == null) {
|
||||
myCopyCache.put(state, map = ContainerUtil.newIdentityHashMap());
|
||||
@@ -251,12 +256,13 @@ class StateMerger {
|
||||
return copy;
|
||||
}
|
||||
|
||||
private static boolean areVarStatesEqualModuloNullability(DfaMemoryStateImpl state1, DfaMemoryStateImpl state2, DfaVariableValue var) {
|
||||
private static boolean areVarStatesEqualModuloNullability(@NotNull DfaMemoryStateImpl state1, @NotNull DfaMemoryStateImpl state2, @NotNull DfaVariableValue var) {
|
||||
return state1.getVariableState(var).withNullability(Nullness.UNKNOWN).equals(state2.getVariableState(var).withNullability(Nullness.UNKNOWN));
|
||||
}
|
||||
|
||||
private LinkedHashSet<Fact> getFacts(DfaMemoryStateImpl state) {
|
||||
LinkedHashSet<Fact> result = myFacts.get(state);
|
||||
@NotNull
|
||||
private Set<Fact> getFacts(@NotNull DfaMemoryStateImpl state) {
|
||||
Set<Fact> result = myFacts.get(state);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
@@ -317,12 +323,13 @@ class StateMerger {
|
||||
private enum FactType { equality, instanceOf }
|
||||
|
||||
private static class Fact {
|
||||
final FactType myType;
|
||||
final DfaVariableValue myVar;
|
||||
final boolean myPositive;
|
||||
final Object myArg; // DfaValue for equality fact, DfaPsiType for instanceOf fact
|
||||
@NotNull final FactType myType;
|
||||
@NotNull private final DfaVariableValue myVar;
|
||||
private final boolean myPositive;
|
||||
@NotNull
|
||||
private final Object myArg; // DfaValue for equality fact, DfaPsiType for instanceOf fact
|
||||
|
||||
private Fact(FactType type, DfaVariableValue var, boolean positive, Object arg) {
|
||||
private Fact(@NotNull FactType type, @NotNull DfaVariableValue var, boolean positive, @NotNull Object arg) {
|
||||
myType = type;
|
||||
myVar = var;
|
||||
myPositive = positive;
|
||||
@@ -358,18 +365,20 @@ class StateMerger {
|
||||
return myVar + " " + (myPositive ? "" : "!") + myType + " " + myArg;
|
||||
}
|
||||
|
||||
static Fact createEqualityFact(DfaVariableValue var, DfaValue val, boolean equal) {
|
||||
@NotNull
|
||||
private static Fact createEqualityFact(@NotNull DfaVariableValue var, @NotNull DfaValue val, boolean equal) {
|
||||
if (val instanceof DfaVariableValue && val.getID() < var.getID()) {
|
||||
return new Fact(FactType.equality, (DfaVariableValue)val, equal, var);
|
||||
}
|
||||
return new Fact(FactType.equality, var, equal, val);
|
||||
}
|
||||
|
||||
Fact getPositiveCounterpart() {
|
||||
@NotNull
|
||||
private Fact getPositiveCounterpart() {
|
||||
return new Fact(myType, myVar, true, myArg);
|
||||
}
|
||||
|
||||
boolean invalidatesFact(Fact another) {
|
||||
boolean invalidatesFact(@NotNull Fact another) {
|
||||
if (another.myType != myType) return false;
|
||||
if (myType == FactType.equality) {
|
||||
return aboutSame(myVar, another.myVar) || aboutSame(myVar, another.myArg);
|
||||
@@ -377,18 +386,18 @@ class StateMerger {
|
||||
return aboutSame(myVar, another.myVar) && aboutSame(myArg, another.myArg);
|
||||
}
|
||||
|
||||
static boolean aboutSame(Object v1, Object v2) {
|
||||
private static boolean aboutSame(Object v1, Object v2) {
|
||||
return normalize(v1) == normalize(v2);
|
||||
}
|
||||
|
||||
static Object normalize(Object value) {
|
||||
private static Object normalize(Object value) {
|
||||
if (value instanceof DfaVariableValue && ((DfaVariableValue)value).isNegated()) {
|
||||
return ((DfaVariableValue)value).createNegated();
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void removeFromState(DfaMemoryStateImpl state) {
|
||||
void removeFromState(@NotNull DfaMemoryStateImpl state) {
|
||||
DfaVariableState varState = state.getVariableState(myVar);
|
||||
if (myType == FactType.equality) {
|
||||
state.flushVariable(myVar);
|
||||
@@ -400,18 +409,18 @@ class StateMerger {
|
||||
}
|
||||
|
||||
private static class Replacements {
|
||||
private final List<DfaMemoryStateImpl> myAllStates;
|
||||
@NotNull private final List<DfaMemoryStateImpl> myAllStates;
|
||||
private final Set<DfaMemoryStateImpl> myRemovedStates = ContainerUtil.newIdentityTroveSet();
|
||||
private final List<DfaMemoryStateImpl> myMerged = ContainerUtil.newArrayList();
|
||||
|
||||
Replacements(List<DfaMemoryStateImpl> allStates) {
|
||||
private Replacements(@NotNull List<DfaMemoryStateImpl> allStates) {
|
||||
myAllStates = allStates;
|
||||
}
|
||||
|
||||
boolean hasMerges() { return !myMerged.isEmpty(); }
|
||||
private boolean hasMerges() { return !myMerged.isEmpty(); }
|
||||
|
||||
@Nullable
|
||||
List<DfaMemoryStateImpl> getMergeResult() {
|
||||
private List<DfaMemoryStateImpl> getMergeResult() {
|
||||
if (hasMerges()) {
|
||||
List<DfaMemoryStateImpl> result = ContainerUtil.newArrayList(myMerged);
|
||||
for (DfaMemoryStateImpl state : myAllStates) {
|
||||
@@ -424,15 +433,15 @@ class StateMerger {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean stripAndMerge(Collection<DfaMemoryStateImpl> group,
|
||||
Function<DfaMemoryStateImpl, DfaMemoryStateImpl> stripper) {
|
||||
private boolean stripAndMerge(@NotNull Collection<DfaMemoryStateImpl> group,
|
||||
@NotNull Function<DfaMemoryStateImpl, DfaMemoryStateImpl> stripper) {
|
||||
if (group.size() <= 1) return false;
|
||||
|
||||
boolean hasMerges = false;
|
||||
MultiMap<DfaMemoryStateImpl, DfaMemoryStateImpl> strippedToOriginals = MultiMap.create();
|
||||
for (DfaMemoryStateImpl original : group) {
|
||||
strippedToOriginals.putValue(stripper.fun(original), original);
|
||||
}
|
||||
boolean hasMerges = false;
|
||||
for (Map.Entry<DfaMemoryStateImpl, Collection<DfaMemoryStateImpl>> entry : strippedToOriginals.entrySet()) {
|
||||
Collection<DfaMemoryStateImpl> merged = entry.getValue();
|
||||
if (merged.size() > 1) {
|
||||
|
||||
+10
-4
@@ -35,19 +35,21 @@ import java.util.Map;
|
||||
public class DfaTypeValue extends DfaValue {
|
||||
public static class Factory {
|
||||
private final Map<DfaPsiType,ArrayList<DfaTypeValue>> myCache = ContainerUtil.newHashMap();
|
||||
@NotNull
|
||||
private final DfaValueFactory myFactory;
|
||||
|
||||
Factory(DfaValueFactory factory) {
|
||||
Factory(@NotNull DfaValueFactory factory) {
|
||||
myFactory = factory;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DfaTypeValue createTypeValue(@NotNull DfaPsiType type, @NotNull Nullness nullness) {
|
||||
DfaTypeValue createTypeValue(@NotNull DfaPsiType type, @NotNull Nullness nullness) {
|
||||
ArrayList<DfaTypeValue> conditions = myCache.get(type);
|
||||
if (conditions == null) {
|
||||
conditions = new ArrayList<DfaTypeValue>();
|
||||
myCache.put(type, conditions);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
for (DfaTypeValue aType : conditions) {
|
||||
if (aType.myNullness == nullness) return aType;
|
||||
}
|
||||
@@ -60,15 +62,18 @@ public class DfaTypeValue extends DfaValue {
|
||||
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private final DfaPsiType myType;
|
||||
@NotNull
|
||||
private final Nullness myNullness;
|
||||
|
||||
private DfaTypeValue(DfaPsiType type, Nullness nullness, DfaValueFactory factory) {
|
||||
private DfaTypeValue(@NotNull DfaPsiType type, @NotNull Nullness nullness, @NotNull DfaValueFactory factory) {
|
||||
super(factory);
|
||||
myType = type;
|
||||
myNullness = nullness;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public DfaPsiType getDfaType() {
|
||||
return myType;
|
||||
}
|
||||
@@ -81,6 +86,7 @@ public class DfaTypeValue extends DfaValue {
|
||||
return myNullness == Nullness.NOT_NULL;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Nullness getNullness() {
|
||||
return myNullness;
|
||||
}
|
||||
|
||||
+3
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -64,7 +64,8 @@ public class DfaValueFactory {
|
||||
return myUnknownMembersAreNullable;
|
||||
}
|
||||
|
||||
public DfaValue createTypeValue(@Nullable PsiType type, Nullness nullability) {
|
||||
@NotNull
|
||||
public DfaValue createTypeValue(@Nullable PsiType type, @NotNull Nullness nullability) {
|
||||
type = TypeConversionUtil.erasure(type);
|
||||
if (type == null) return DfaUnknownValue.getInstance();
|
||||
return getTypeFactory().createTypeValue(internType(type), nullability);
|
||||
|
||||
+5
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2000-2009 JetBrains s.r.o.
|
||||
* Copyright 2000-2015 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -81,10 +81,10 @@ public class DfaVariableValue extends DfaValue {
|
||||
return result;
|
||||
}
|
||||
|
||||
public List<DfaVariableValue> getAllQualifiedBy(DfaVariableValue value) {
|
||||
@NotNull
|
||||
public List<DfaVariableValue> getAllQualifiedBy(@NotNull DfaVariableValue value) {
|
||||
return value.myDependents;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private final PsiModifierListOwner myVariable;
|
||||
@@ -159,6 +159,7 @@ public class DfaVariableValue extends DfaValue {
|
||||
return myQualifier;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Nullness getInherentNullability() {
|
||||
if (myInherentNullability != null) {
|
||||
return myInherentNullability;
|
||||
@@ -167,6 +168,7 @@ public class DfaVariableValue extends DfaValue {
|
||||
return myInherentNullability = calcInherentNullability();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private Nullness calcInherentNullability() {
|
||||
PsiModifierListOwner var = getPsiVariable();
|
||||
Nullness nullability = DfaPsiUtil.getElementNullability(getVariableType(), var);
|
||||
|
||||
Reference in New Issue
Block a user