mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
don't intermix final fields with different qualifiers in dfa (IDEA-91417)
This commit is contained in:
@@ -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) {
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -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;
|
||||
}
|
||||
|
||||
+21
@@ -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(); }
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user