don't intermix final fields with different qualifiers in dfa (IDEA-91417)

This commit is contained in:
peter
2012-09-12 14:19:40 +02:00
parent 23ed389536
commit ff8a4f1e49
8 changed files with 59 additions and 48 deletions
@@ -73,6 +73,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
public DfaMemoryStateImpl createCopy() {
DfaMemoryStateImpl newState = createNew();
//noinspection unchecked
newState.myStack = (Stack<DfaValue>)myStack.clone();
newState.myDistinctClasses = new TLongHashSet(myDistinctClasses.toArray());
newState.myEqClasses = new ArrayList<SortedIntSet>();
@@ -359,7 +360,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
return cacheable((DfaConstValue)valueToWrap);
}
if (valueToWrap instanceof DfaVariableValue) {
if (PsiType.BOOLEAN.equals(((DfaVariableValue)valueToWrap).getPsiVariable().getType())) return true;
if (PsiType.BOOLEAN.equals(((DfaVariableValue)valueToWrap).getVariableType())) return true;
for (DfaValue value : getEqClassesFor(valueToWrap)) {
if (value instanceof DfaConstValue && cacheable((DfaConstValue)value)) return true;
}
@@ -405,8 +406,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
SortedIntSet c1 = myEqClasses.get(c1Index);
SortedIntSet c2 = myEqClasses.get(c2Index);
Set<PsiVariable> vars = new THashSet<PsiVariable>();
Set<PsiVariable> negatedvars = new THashSet<PsiVariable>();
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());
@@ -419,13 +420,15 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
if (dfaValue instanceof DfaConstValue) nConst++;
if (dfaValue instanceof DfaVariableValue) {
DfaVariableValue variableValue = (DfaVariableValue)dfaValue;
PsiVariable variable = variableValue.getPsiVariable();
Set<PsiVariable> set = variableValue.isNegated() ? negatedvars : vars;
set.add(variable);
if (variableValue.isNegated()) {
negatedVars.add(variableValue.createNegated());
} else {
vars.add(variableValue);
}
}
if (nConst > 1) return false;
}
if (ContainerUtil.intersects(vars, negatedvars)) return false;
if (ContainerUtil.intersects(vars, negatedVars)) return false;
TLongArrayList c2Pairs = new TLongArrayList();
long[] distincts = myDistinctClasses.toArray();
@@ -461,7 +464,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
private static int low(long l) {
return (int)(l & 0xFFFFFFFF);
return (int)l;
}
private static int high(long l) {
@@ -631,8 +634,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
}
if (dfaLeft instanceof DfaVariableValue) {
PsiVariable psiVariable = ((DfaVariableValue)dfaLeft).getPsiVariable();
if (TypeConversionUtil.isPrimitiveWrapper(psiVariable.getType())
PsiType type = ((DfaVariableValue)dfaLeft).getVariableType();
if (TypeConversionUtil.isPrimitiveWrapper(type)
&& (!isNegated // from the fact (wrappers are not the same) does not follow (unboxed values are not equals)
|| dfaRight instanceof DfaConstValue || dfaRight instanceof DfaBoxedValue && ((DfaBoxedValue)dfaRight).getWrappedValue() instanceof DfaConstValue)
){
@@ -640,7 +643,7 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
dfaRight = myFactory.getBoxedFactory().createUnboxed(dfaRight);
result &= applyRelation(dfaLeft, dfaRight, isNegated);
}
else if (TypeConversionUtil.isPrimitiveAndNotNull(psiVariable.getType())){
else if (TypeConversionUtil.isPrimitiveAndNotNull(type)){
dfaLeft = myFactory.getBoxedFactory().createBoxed(dfaLeft);
dfaRight = myFactory.getBoxedFactory().createBoxed(dfaRight);
if (dfaLeft != null && dfaRight != null) {
@@ -697,11 +700,8 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
}
public boolean applyNotNull(DfaValue value) {
if (value instanceof DfaVariableValue) {
PsiVariable variable = ((DfaVariableValue)value).getPsiVariable();
if (variable != null && variable.getType() instanceof PsiPrimitiveType) {
return true;
}
if (value instanceof DfaVariableValue && ((DfaVariableValue)value).getVariableType() instanceof PsiPrimitiveType) {
return true;
}
return checkNotNullable(value) && applyCondition(compareToNull(value, true));
@@ -253,12 +253,12 @@ public class DfaUtil {
ValuableDataFlowRunner.ValuableDfaVariableState state = (ValuableDataFlowRunner.ValuableDfaVariableState)entry.getValue();
DfaVariableValue variableValue = entry.getKey();
final PsiExpression psiExpression = state.myExpression;
if (psiExpression != null) {
if (psiExpression != null && variableValue.getQualifier() == null) {
myValues.put(variableValue.getPsiVariable(), psiExpression);
}
}
DfaValue value = instruction.getValue();
if (value instanceof DfaVariableValue) {
if (value instanceof DfaVariableValue && ((DfaVariableValue)value).getQualifier() == null) {
if (memState.isNotNull((DfaVariableValue)value)) {
myNotNulls.add(((DfaVariableValue)value).getPsiVariable());
}
@@ -43,10 +43,8 @@ public class DfaVariableState implements Cloneable {
private final Set<DfaTypeValue> myNotInstanceofValues;
private boolean myNullable = false;
private final boolean myVariableIsDeclaredNotNull;
private final PsiVariable myVar;
public DfaVariableState(@Nullable PsiVariable var) {
myVar = var;
myInstanceofValues = new HashSet<DfaTypeValue>();
myNotInstanceofValues = new HashSet<DfaTypeValue>();
myNullable = var != null && (NullableNotNullManager.isNullable(var) || isNullableInitialized(var, true));
@@ -82,7 +80,6 @@ public class DfaVariableState implements Cloneable {
}
protected DfaVariableState(final DfaVariableState toClone) {
myVar = toClone.myVar;
myInstanceofValues = new THashSet<DfaTypeValue>(toClone.myInstanceofValues);
myNotInstanceofValues = new THashSet<DfaTypeValue>(toClone.myNotInstanceofValues);
myNullable = toClone.myNullable;
@@ -178,10 +175,6 @@ public class DfaVariableState implements Cloneable {
myNullable = nullable;
}
public PsiVariable getVariable() {
return myVar;
}
public void setValue(DfaValue value) {
}
@@ -127,7 +127,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
if (qualifier instanceof DfaVariableValue) {
final DfaNotNullValue.Factory factory = runner.getFactory().getNotNullFactory();
memState.setVarValue((DfaVariableValue)qualifier, factory.create(((DfaVariableValue)qualifier).getPsiVariable().getType()));
memState.setVarValue((DfaVariableValue)qualifier, factory.create(((DfaVariableValue)qualifier).getVariableType()));
}
}
@@ -168,7 +168,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
if (args.length <= parametersNotNull.length && revIdx < parametersNotNull.length && parametersNotNull[revIdx] && !memState.applyNotNull(arg)) {
onPassingNullParameter(runner, args[revIdx]);
if (arg instanceof DfaVariableValue) {
memState.setVarValue((DfaVariableValue)arg, factory.create(((DfaVariableValue)arg).getPsiVariable().getType()));
memState.setVarValue((DfaVariableValue)arg, factory.create(((DfaVariableValue)arg).getVariableType()));
}
}
}
@@ -183,7 +183,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
onInstructionProducesNPE(instruction, runner);
}
if (qualifier instanceof DfaVariableValue) {
memState.setVarValue((DfaVariableValue)qualifier, factory.create(((DfaVariableValue)qualifier).getPsiVariable().getType()));
memState.setVarValue((DfaVariableValue)qualifier, factory.create(((DfaVariableValue)qualifier).getVariableType()));
}
}
@@ -15,9 +15,8 @@
*/
package com.intellij.codeInspection.dataFlow.value;
import com.intellij.psi.PsiVariable;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.HashMap;
import gnu.trove.THashMap;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -43,7 +42,6 @@ public class DfaBoxedValue extends DfaValue {
public static class Factory {
private final Map<Object, DfaBoxedValue> cachedValues = new HashMap<Object, DfaBoxedValue>();
private final Map<Object, DfaBoxedValue> cachedNegatedValues = new HashMap<Object, DfaBoxedValue>();
private final DfaValueFactory myFactory;
public Factory(DfaValueFactory factory) {
@@ -55,19 +53,16 @@ public class DfaBoxedValue extends DfaValue {
if (valueToWrap instanceof DfaUnboxedValue) return ((DfaUnboxedValue)valueToWrap).getVariable();
Object o = valueToWrap instanceof DfaConstValue
? ((DfaConstValue)valueToWrap).getValue()
: valueToWrap instanceof DfaVariableValue ? ((DfaVariableValue)valueToWrap).getPsiVariable() : null;
: valueToWrap instanceof DfaVariableValue ? valueToWrap : null;
if (o == null) return null;
Map<Object, DfaBoxedValue> map = valueToWrap instanceof DfaVariableValue && ((DfaVariableValue)valueToWrap).isNegated() ? cachedNegatedValues : cachedValues;
DfaBoxedValue boxedValue = map.get(o);
DfaBoxedValue boxedValue = cachedValues.get(o);
if (boxedValue == null) {
boxedValue = new DfaBoxedValue(valueToWrap, myFactory);
map.put(o, boxedValue);
cachedValues.put(o, boxedValue = new DfaBoxedValue(valueToWrap, myFactory));
}
return boxedValue;
}
private final Map<PsiVariable, DfaUnboxedValue> cachedUnboxedValues = new THashMap<PsiVariable, DfaUnboxedValue>();
private final Map<PsiVariable, DfaUnboxedValue> cachedNegatedUnboxedValues = new THashMap<PsiVariable, DfaUnboxedValue>();
private final Map<DfaVariableValue, DfaUnboxedValue> cachedUnboxedValues = ContainerUtil.newTroveMap();
@NotNull
public DfaValue createUnboxed(DfaValue value) {
@@ -78,20 +73,15 @@ public class DfaBoxedValue extends DfaValue {
if (value == value.myFactory.getConstFactory().getNull()) return DfaUnknownValue.getInstance();
return value;
}
DfaValue result;
if (value instanceof DfaVariableValue) {
PsiVariable var = ((DfaVariableValue)value).getPsiVariable();
Map<PsiVariable, DfaUnboxedValue> map = ((DfaVariableValue)value).isNegated() ? cachedNegatedUnboxedValues : cachedUnboxedValues;
result = map.get(var);
DfaVariableValue var = (DfaVariableValue)value;
DfaUnboxedValue result = cachedUnboxedValues.get(var);
if (result == null) {
result = new DfaUnboxedValue((DfaVariableValue)value, myFactory);
map.put(var, (DfaUnboxedValue)result);
cachedUnboxedValues.put(var, result = new DfaUnboxedValue(var, myFactory));
}
return result;
}
else {
result = DfaUnknownValue.getInstance();
}
return result;
return DfaUnknownValue.getInstance();
}
}
@@ -24,6 +24,7 @@
*/
package com.intellij.codeInspection.dataFlow.value;
import com.intellij.psi.PsiType;
import com.intellij.psi.PsiVariable;
import com.intellij.util.containers.HashMap;
import com.intellij.util.containers.MultiMap;
@@ -110,6 +111,11 @@ public class DfaVariableValue extends DfaValue {
return myVariable;
}
@Nullable
public PsiType getVariableType() {
return myVariable == null ? null : myVariable.getType();
}
public boolean isNegated() {
return myIsNegated;
}
@@ -0,0 +1,21 @@
public class BrokenAlignment {
private static boolean dominates(final WatchRequestImpl request, final WatchRequestImpl other) {
if (request.myToWatchRecursively) {
return other.myRootPath.startsWith(request.myRootPath);
}
return !other.myToWatchRecursively && request.myRootPath.equals(other.myRootPath);
}
private static class WatchRequestImpl {
private final boolean myToWatchRecursively;
private final String myRootPath = "";
private WatchRequestImpl(boolean toWatchRecursively) {
myToWatchRecursively = toWatchRecursively;
}
}
}
@@ -80,6 +80,7 @@ public class DataFlowInspectionFixtureTest extends JavaCodeInsightFixtureTestCas
public void testNotGreaterIsNotEquals() throws Throwable { doTest(); }
public void testChainedFinalFieldsDfa() throws Throwable { doTest(); }
public void testFinalFieldsDifferentInstances() throws Throwable { doTest(); }
public void testChainedFinalFieldAccessorsDfa() throws Throwable { doTest(); }
}