mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
DFA instruction visitor refactoring wave#5 fixes
ResultOfInstruction
This commit is contained in:
@@ -207,6 +207,16 @@ public class CFGBuilder {
|
|||||||
return add(new ObjectOfInstruction());
|
return add(new ObjectOfInstruction());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate instructions to bind top-of-stack value to the given expression. Stack remains unchanged.
|
||||||
|
*
|
||||||
|
* @param expression expression to bind top-of-stack value to
|
||||||
|
* @return this builder
|
||||||
|
*/
|
||||||
|
public CFGBuilder resultOf(PsiExpression expression) {
|
||||||
|
return add(new ResultOfInstruction(expression));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate instructions to perform an Class.isInstance operation
|
* Generate instructions to perform an Class.isInstance operation
|
||||||
* <p>
|
* <p>
|
||||||
|
|||||||
+3
@@ -1512,6 +1512,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
|||||||
addInstruction(new GotoInstruction(getEndOffset(operands[operands.length - 1])));
|
addInstruction(new GotoInstruction(getEndOffset(operands[operands.length - 1])));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (shortCircuit) {
|
||||||
|
addInstruction(new ResultOfInstruction(expression));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
|
@Override public void visitClassObjectAccessExpression(PsiClassObjectAccessExpression expression) {
|
||||||
|
|||||||
+1
@@ -243,6 +243,7 @@ final class DataFlowInstructionVisitor extends StandardInstructionVisitor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static boolean shouldCollectBooleanResult(PsiExpression expression) {
|
private static boolean shouldCollectBooleanResult(PsiExpression expression) {
|
||||||
|
if (expression instanceof PsiLiteralExpression) return false;
|
||||||
PsiType type = expression.getType();
|
PsiType type = expression.getType();
|
||||||
if (type == null || !PsiType.BOOLEAN.isAssignableFrom(type)) return false;
|
if (type == null || !PsiType.BOOLEAN.isAssignableFrom(type)) return false;
|
||||||
if (expression instanceof PsiPrefixExpression || expression instanceof PsiPolyadicExpression) {
|
if (expression instanceof PsiPrefixExpression || expression instanceof PsiPolyadicExpression) {
|
||||||
|
|||||||
+5
@@ -147,6 +147,11 @@ public abstract class InstructionVisitor {
|
|||||||
return nextInstruction(instruction, runner, state);
|
return nextInstruction(instruction, runner, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public DfaInstructionState[] visitResultOf(ResultOfInstruction instruction, DataFlowRunner runner, DfaMemoryState state) {
|
||||||
|
pushExpressionResult(state.pop(), instruction, state);
|
||||||
|
return nextInstruction(instruction, runner, state);
|
||||||
|
}
|
||||||
|
|
||||||
protected static DfaInstructionState[] nextInstruction(Instruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
|
protected static DfaInstructionState[] nextInstruction(Instruction instruction, DataFlowRunner runner, DfaMemoryState memState) {
|
||||||
return new DfaInstructionState[]{new DfaInstructionState(runner.getInstruction(instruction.getIndex() + 1), memState)};
|
return new DfaInstructionState[]{new DfaInstructionState(runner.getInstruction(instruction.getIndex() + 1), memState)};
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -101,7 +101,7 @@ public class StandardInstructionVisitor extends InstructionVisitor {
|
|||||||
checkNotNullable(memState, dfaSource, kind.problem(rValue));
|
checkNotNullable(memState, dfaSource, kind.problem(rValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
memState.push(dfaDest);
|
pushExpressionResult(dfaDest, instruction, memState);
|
||||||
flushArrayOnUnknownAssignment(instruction, runner.getFactory(), dfaDest, memState);
|
flushArrayOnUnknownAssignment(instruction, runner.getFactory(), dfaDest, memState);
|
||||||
|
|
||||||
return nextInstruction(instruction, runner, memState);
|
return nextInstruction(instruction, runner, memState);
|
||||||
|
|||||||
+7
-6
@@ -81,11 +81,10 @@ public class OptionalChainInliner implements CallInliner {
|
|||||||
.ifNotNull()
|
.ifNotNull()
|
||||||
.swap() // stack: .. optValue, elseValue
|
.swap() // stack: .. optValue, elseValue
|
||||||
.end()
|
.end()
|
||||||
.pop();
|
.pop()
|
||||||
})
|
.resultOf(call);
|
||||||
.register(OPTIONAL_OR_NULL, (builder, call) -> {
|
|
||||||
// no op!
|
|
||||||
})
|
})
|
||||||
|
.register(OPTIONAL_OR_NULL, CFGBuilder::resultOf)
|
||||||
.register(OPTIONAL_OR_ELSE_GET, (builder, call) -> {
|
.register(OPTIONAL_OR_ELSE_GET, (builder, call) -> {
|
||||||
PsiExpression fn = call.getArgumentList().getExpressions()[0];
|
PsiExpression fn = call.getArgumentList().getExpressions()[0];
|
||||||
builder
|
builder
|
||||||
@@ -94,7 +93,8 @@ public class OptionalChainInliner implements CallInliner {
|
|||||||
.ifNull()
|
.ifNull()
|
||||||
.pop()
|
.pop()
|
||||||
.invokeFunction(0, fn)
|
.invokeFunction(0, fn)
|
||||||
.end();
|
.end()
|
||||||
|
.resultOf(call);
|
||||||
})
|
})
|
||||||
.register(OPTIONAL_IF_PRESENT, (builder, call) -> {
|
.register(OPTIONAL_IF_PRESENT, (builder, call) -> {
|
||||||
PsiExpression fn = call.getArgumentList().getExpressions()[0];
|
PsiExpression fn = call.getArgumentList().getExpressions()[0];
|
||||||
@@ -106,7 +106,8 @@ public class OptionalChainInliner implements CallInliner {
|
|||||||
.elseBranch()
|
.elseBranch()
|
||||||
.pop()
|
.pop()
|
||||||
.pushUnknown()
|
.pushUnknown()
|
||||||
.end();
|
.end()
|
||||||
|
.resultOf(call);
|
||||||
});
|
});
|
||||||
|
|
||||||
private static final CallMapper<BiConsumer<CFGBuilder, PsiExpression>> INTERMEDIATE_MAPPER =
|
private static final CallMapper<BiConsumer<CFGBuilder, PsiExpression>> INTERMEDIATE_MAPPER =
|
||||||
|
|||||||
+9
-1
@@ -24,10 +24,11 @@ import com.intellij.codeInspection.dataFlow.value.DfaValue;
|
|||||||
import com.intellij.psi.PsiAssignmentExpression;
|
import com.intellij.psi.PsiAssignmentExpression;
|
||||||
import com.intellij.psi.PsiExpression;
|
import com.intellij.psi.PsiExpression;
|
||||||
import com.intellij.psi.PsiVariable;
|
import com.intellij.psi.PsiVariable;
|
||||||
|
import com.intellij.util.ObjectUtils;
|
||||||
import org.jetbrains.annotations.Contract;
|
import org.jetbrains.annotations.Contract;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
public class AssignInstruction extends Instruction {
|
public class AssignInstruction extends Instruction implements ExpressionPushingInstruction {
|
||||||
private final PsiExpression myRExpression;
|
private final PsiExpression myRExpression;
|
||||||
private final PsiExpression myLExpression;
|
private final PsiExpression myLExpression;
|
||||||
@Nullable private final DfaValue myAssignedValue;
|
@Nullable private final DfaValue myAssignedValue;
|
||||||
@@ -70,6 +71,13 @@ public class AssignInstruction extends Instruction {
|
|||||||
return "ASSIGN";
|
return "ASSIGN";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public PsiAssignmentExpression getExpression() {
|
||||||
|
if(myRExpression== null) return null;
|
||||||
|
return ObjectUtils.tryCast(myRExpression.getParent(), PsiAssignmentExpression.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Contract("null -> null")
|
@Contract("null -> null")
|
||||||
@Nullable
|
@Nullable
|
||||||
private static PsiExpression getLeftHandOfAssignment(PsiExpression rExpression) {
|
private static PsiExpression getLeftHandOfAssignment(PsiExpression rExpression) {
|
||||||
|
|||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package com.intellij.codeInspection.dataFlow.instructions;
|
||||||
|
|
||||||
|
import com.intellij.codeInspection.dataFlow.DataFlowRunner;
|
||||||
|
import com.intellij.codeInspection.dataFlow.DfaInstructionState;
|
||||||
|
import com.intellij.codeInspection.dataFlow.DfaMemoryState;
|
||||||
|
import com.intellij.codeInspection.dataFlow.InstructionVisitor;
|
||||||
|
import com.intellij.psi.PsiExpression;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public class ResultOfInstruction extends Instruction implements ExpressionPushingInstruction {
|
||||||
|
@NotNull
|
||||||
|
private final PsiExpression myExpression;
|
||||||
|
|
||||||
|
public ResultOfInstruction(@NotNull PsiExpression expression) {
|
||||||
|
myExpression = expression;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DfaInstructionState[] accept(DataFlowRunner runner, DfaMemoryState stateBefore, InstructionVisitor visitor) {
|
||||||
|
return visitor.visitResultOf(this, runner, stateBefore);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "RESULT_OF "+myExpression.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
@Override
|
||||||
|
public PsiExpression getExpression() {
|
||||||
|
return myExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
void test(String type) {
|
||||||
|
if(type != null && (type.equals("foo") | type.equals("bar"))) {
|
||||||
|
System.out.println("Who knows");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -41,7 +41,7 @@ class S {
|
|||||||
}
|
}
|
||||||
public void te5(boolean b){
|
public void te5(boolean b){
|
||||||
Boolean c = Boolean.TRUE;
|
Boolean c = Boolean.TRUE;
|
||||||
boolean o = <warning descr="Condition 'b||c' is always 'true'">b||<warning descr="Condition 'c' is always 'true' when reached">c</warning></warning>;
|
boolean o = b||<warning descr="Condition 'c' is always 'true' when reached">c</warning>;
|
||||||
if (<warning descr="Condition 'o' is always 'true'">o</warning>) {
|
if (<warning descr="Condition 'o' is always 'true'">o</warning>) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
class Test {
|
||||||
|
void test(String type) {
|
||||||
|
boolean uint = false;
|
||||||
|
if ("int".equals(type) || (uint = "uint".equals(type))) {
|
||||||
|
System.out.println("possible");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -622,4 +622,6 @@ public class DataFlowInspectionTest extends DataFlowInspectionTestCase {
|
|||||||
public void testEqualsInLoopNotTooComplex() { doTest(); }
|
public void testEqualsInLoopNotTooComplex() { doTest(); }
|
||||||
public void testEqualsWithItself() { doTest(); }
|
public void testEqualsWithItself() { doTest(); }
|
||||||
public void testBoxingBoolean() { doTest(); }
|
public void testBoxingBoolean() { doTest(); }
|
||||||
|
public void testOrWithAssignment() { doTest(); }
|
||||||
|
public void testAndAndWithOr() { doTest(); }
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user