mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Properly implement flatMap with non-inlineable function (IDEA-200094)
Also more precise deletion of temporary variables
This commit is contained in:
+22
-1
@@ -175,10 +175,31 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
private void finishElement(PsiElement element) {
|
||||
myCurrentFlow.finishElement(element);
|
||||
if (element instanceof PsiStatement && !(element instanceof PsiReturnStatement)) {
|
||||
addInstruction(new FinishElementInstruction(element));
|
||||
List<DfaVariableValue> synthetics = getSynthetics(element);
|
||||
FinishElementInstruction instruction = new FinishElementInstruction(element);
|
||||
instruction.getVarsToFlush().addAll(synthetics);
|
||||
addInstruction(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private List<DfaVariableValue> getSynthetics(PsiElement element) {
|
||||
int startOffset = myCurrentFlow.getStartOffset(element).getInstructionOffset();
|
||||
List<DfaVariableValue> synthetics = new ArrayList<>();
|
||||
for (DfaValue value : myFactory.getValues()) {
|
||||
if (value instanceof DfaVariableValue) {
|
||||
DfaVariableValue var = (DfaVariableValue)value;
|
||||
DfaVariableSource source = var.getSource();
|
||||
if (source instanceof Synthetic) {
|
||||
if (((Synthetic)source).myLocation >= startOffset) {
|
||||
synthetics.add(var);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return synthetics;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitErrorElement(PsiErrorElement element) {
|
||||
throw new CannotAnalyzeException();
|
||||
|
||||
@@ -161,6 +161,4 @@ public interface DfaMemoryState {
|
||||
boolean isEphemeral();
|
||||
|
||||
boolean isEmptyStack();
|
||||
|
||||
void cleanUpTempVariables();
|
||||
}
|
||||
|
||||
-6
@@ -606,12 +606,6 @@ public class DfaMemoryStateImpl implements DfaMemoryState {
|
||||
return myStack.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cleanUpTempVariables() {
|
||||
List<DfaVariableValue> values = ContainerUtil.filter(myVariableStates.keySet(), ControlFlowAnalyzer::isTempVariable);
|
||||
values.forEach(this::flushVariable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean castTopOfStack(@NotNull DfaPsiType type) {
|
||||
DfaValue value = unwrap(peek());
|
||||
|
||||
+10
-7
@@ -415,7 +415,7 @@ public class StreamChainInliner implements CallInliner {
|
||||
void before(CFGBuilder builder) {
|
||||
if (myStreamSource == null) {
|
||||
PsiExpression arg = myCall.getArgumentList().getExpressions()[0];
|
||||
builder.pushExpression(arg).checkNotNull(arg, NullabilityProblemKind.passingNullableToNotNullParameter).pop();
|
||||
builder.evaluateFunction(arg);
|
||||
}
|
||||
super.before(builder);
|
||||
}
|
||||
@@ -426,13 +426,16 @@ public class StreamChainInliner implements CallInliner {
|
||||
builder.assignTo(myParameter).pop();
|
||||
buildStreamCFG(builder, myChain, myStreamSource);
|
||||
} else {
|
||||
PsiExpression arg = myCall.getArgumentList().getExpressions()[0];
|
||||
PsiType outType = StreamApiUtil.getStreamElementType(myCall.getType());
|
||||
builder.pop()
|
||||
.pushUnknown()
|
||||
.ifConditionIs(true)
|
||||
.doWhileUnknown()
|
||||
.push(builder.getFactory().createTypeValue(outType, Nullability.UNKNOWN))
|
||||
.chain(myNext::iteration)
|
||||
builder.invokeFunction(1, arg, Nullability.NULLABLE)
|
||||
.ifNotNull()
|
||||
.pushUnknown()
|
||||
.ifConditionIs(true)
|
||||
.doWhileUnknown()
|
||||
.push(builder.getFactory().createTypeValue(outType, Nullability.UNKNOWN))
|
||||
.chain(myNext::iteration)
|
||||
.end()
|
||||
.end()
|
||||
.end();
|
||||
}
|
||||
|
||||
-1
@@ -43,7 +43,6 @@ public class FinishElementInstruction extends Instruction {
|
||||
state.flushVariable(value);
|
||||
}
|
||||
}
|
||||
state.cleanUpTempVariables();
|
||||
return nextInstruction(runner, state);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
import java.util.*;
|
||||
import java.util.stream.*;
|
||||
|
||||
// IDEA-200094
|
||||
class Main {
|
||||
void flatMapAlwaysNull(List<String> input) {
|
||||
List<String> side = new ArrayList<>();
|
||||
long count = input.stream().<String>flatMap(e -> {
|
||||
if(!e.isEmpty()) side.add(e);
|
||||
return null;
|
||||
}).count();
|
||||
if (side.isEmpty()) {} // not known
|
||||
if (<warning descr="Condition 'count > 0' is always 'false'">count > 0</warning>) {}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Main().myMethod();
|
||||
}
|
||||
|
||||
private void myMethod() {
|
||||
List<Integer> numberOne = Collections.singletonList(1);
|
||||
List<Integer> collectionBeingModifiedSometimes = new ArrayList<>();
|
||||
|
||||
List<Integer> numberTwo = numberOne.stream().flatMap(entry -> {
|
||||
if (Math.random() > 0.5) {
|
||||
collectionBeingModifiedSometimes.add(999);
|
||||
}
|
||||
return Stream.of(entry * 2);
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
String text = collectionBeingModifiedSometimes.size() == 0 ? "empty" : "nonempty";
|
||||
System.out.println("" + numberOne + " " + numberTwo + " " + text);
|
||||
}
|
||||
}
|
||||
@@ -243,4 +243,5 @@ public class DataFlowInspection8Test extends DataFlowInspectionTestCase {
|
||||
doTest();
|
||||
}
|
||||
public void testObjectsEquals() { doTest(); }
|
||||
public void testFlatMapSideEffect() { doTest(); }
|
||||
}
|
||||
Reference in New Issue
Block a user