diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java index 986792786fbc..9706e45196b6 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/CFGBuilder.java @@ -235,7 +235,7 @@ public class CFGBuilder { * @param relation relation to use for comparison * @return this builder */ - private CFGBuilder compare(IElementType relation) { + CFGBuilder compare(IElementType relation) { return add(new BinopInstruction(relation, null, PsiType.BOOLEAN)); } @@ -415,6 +415,49 @@ public class CFGBuilder { return add(new AssignInstruction(null, null)); } + /** + * Generate instructions to assign given source value to the given target value. Stack remains unchanged. + * May skip generating instructions if target is not writable (e.g. not a variable) + * + * @param target target to write + * @param source source value + * @return this builder + */ + public CFGBuilder assignAndPop(DfaValue target, DfaValue source) { + if (target instanceof DfaVariableValue) { + if (source == DfaUnknownValue.getInstance()) { + add(new FlushVariableInstruction((DfaVariableValue)target)); + } else { + pushForWrite((DfaVariableValue)target).push(source).assign().pop(); + } + } + return this; + } + + /** + * Generate instructions to assign given source value to the given target value and leave the result on stack. + *
+ * Stack before: ... + *
+ * Stack after: ... target + * + * @param target target to write + * @param source source value + * @return this builder + */ + public CFGBuilder assign(DfaValue target, DfaValue source) { + if (target instanceof DfaVariableValue) { + if (source == DfaUnknownValue.getInstance()) { + add(new FlushVariableInstruction((DfaVariableValue)target)).push(target); + } else { + pushForWrite((DfaVariableValue)target).push(source).assign(); + } + } else { + push(source); + } + return this; + } + /** * Generate instructions to assign top stack value to the specified variable *
@@ -638,8 +681,7 @@ public class CFGBuilder {
ConditionalGotoInstruction condGoto = new ConditionalGotoInstruction(null, false, null);
condGoto.setOffset(myAnalyzer.getInstructionCount());
myBranches.add(() -> pushUnknown().add(condGoto));
- DfaValue loopElement = factory.createCommonValue(expressions);
- pushForWrite(targetVariable).push(loopElement).assign();
+ assign(targetVariable, factory.createCommonValue(expressions));
} else {
push(factory.getConstFactory().getSentinel());
for (PsiExpression expression : expressions) {
diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/inliner/CollectionFactoryInliner.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/inliner/CollectionFactoryInliner.java
index a7bcc2aca5d5..e66bdff26b01 100644
--- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/inliner/CollectionFactoryInliner.java
+++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/inliner/CollectionFactoryInliner.java
@@ -104,13 +104,10 @@ public class CollectionFactoryInliner implements CallInliner {
builder.push(result);
} else {
DfaVariableValue variableValue = builder.createTempVariable(call.getType());
- builder.pushForWrite(variableValue) // tmpVar =