mirror of
https://gitflic.ru/project/openide/openide.git
synced 2025-12-15 02:59:33 +07:00
DfaAssist: support while and do-while loops
GitOrigin-RevId: 2061e3ea64f9091060770c5bfa08c70f6921ad54
This commit is contained in:
committed by
intellij-monorepo-bot
parent
6e12ae7e93
commit
eb1143abcf
@@ -40,14 +40,14 @@ class DebuggerDfaRunner extends DataFlowRunner {
|
||||
CommonClassNames.JAVA_UTIL_LINKED_LIST,
|
||||
CommonClassNames.JAVA_UTIL_HASH_MAP,
|
||||
"java.util.TreeMap");
|
||||
private final @NotNull PsiCodeBlock myBody;
|
||||
private final @NotNull PsiElement myBody;
|
||||
private final @NotNull PsiStatement myStatement;
|
||||
private final @NotNull Project myProject;
|
||||
private final @Nullable ControlFlow myFlow;
|
||||
private final @Nullable DfaInstructionState myStartingState;
|
||||
private final long myModificationStamp;
|
||||
|
||||
DebuggerDfaRunner(@NotNull PsiCodeBlock body, @NotNull PsiStatement statement, @NotNull StackFrame frame) {
|
||||
DebuggerDfaRunner(@NotNull PsiElement body, @NotNull PsiStatement statement, @NotNull StackFrame frame) {
|
||||
super(body.getProject(), body.getParent() instanceof PsiClassInitializer ? ((PsiClassInitializer)body.getParent()).getContainingClass() : body);
|
||||
myBody = body;
|
||||
myStatement = statement;
|
||||
|
||||
@@ -5,6 +5,7 @@ import com.intellij.codeInsight.hints.presentation.MenuOnClickPresentation;
|
||||
import com.intellij.codeInsight.hints.presentation.PresentationFactory;
|
||||
import com.intellij.codeInsight.hints.presentation.PresentationRenderer;
|
||||
import com.intellij.codeInspection.dataFlow.RunnerResult;
|
||||
import com.intellij.debugger.DebuggerBundle;
|
||||
import com.intellij.debugger.SourcePosition;
|
||||
import com.intellij.debugger.engine.DebugProcessImpl;
|
||||
import com.intellij.debugger.engine.SuspendContextImpl;
|
||||
@@ -185,7 +186,7 @@ public class DfaAssist implements DebuggerContextListener {
|
||||
if (!locationMatches(element, frame.location())) return null;
|
||||
PsiStatement statement = getAnchorStatement(element);
|
||||
if (statement == null) return null;
|
||||
PsiCodeBlock body = getCodeBlock(statement);
|
||||
PsiElement body = getCodeBlock(statement);
|
||||
if (body == null) return null;
|
||||
DebuggerDfaRunner runner = new DebuggerDfaRunner(body, statement, frame);
|
||||
return runner.isValid() ? runner : null;
|
||||
@@ -233,7 +234,10 @@ public class DfaAssist implements DebuggerContextListener {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static PsiCodeBlock getCodeBlock(@NotNull PsiStatement statement) {
|
||||
private static PsiElement getCodeBlock(@NotNull PsiStatement statement) {
|
||||
if (statement instanceof PsiWhileStatement || statement instanceof PsiDoWhileStatement) {
|
||||
return statement;
|
||||
}
|
||||
PsiElement e = statement;
|
||||
while (e != null && !(e instanceof PsiClass) && !(e instanceof PsiFileSystemItem)) {
|
||||
e = e.getParent();
|
||||
@@ -243,8 +247,14 @@ public class DfaAssist implements DebuggerContextListener {
|
||||
// We cannot properly restore context if we started from finally, so let's analyze just finally block
|
||||
parent instanceof PsiTryStatement && ((PsiTryStatement)parent).getFinallyBlock() == e ||
|
||||
parent instanceof PsiBlockStatement && parent.getParent() instanceof PsiLoopStatement) {
|
||||
return (PsiCodeBlock)e;
|
||||
if (parent.getParent() instanceof PsiDoWhileStatement) {
|
||||
return parent.getParent();
|
||||
}
|
||||
return e;
|
||||
}
|
||||
}
|
||||
if (e instanceof PsiDoWhileStatement) {
|
||||
return e;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -254,7 +264,8 @@ public class DfaAssist implements DebuggerContextListener {
|
||||
private final DebuggerContextImpl myContext;
|
||||
|
||||
private TurnOffDfaProcessorAction(DebuggerContextImpl context) {
|
||||
super("Turn Off Dataflow Assist", "Switch off dataflow aided debugging for this session", AllIcons.Actions.Cancel);
|
||||
super(DebuggerBundle.message("action.TurnOffDfaAssist.text"),
|
||||
DebuggerBundle.message("action.TurnOffDfaAssist.description"), AllIcons.Actions.Cancel);
|
||||
myContext = context;
|
||||
}
|
||||
@Override
|
||||
|
||||
@@ -61,6 +61,15 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
private final Map<String, ExceptionTransfer> myExceptionCache;
|
||||
private ExpressionBlockContext myExpressionBlockContext;
|
||||
|
||||
/**
|
||||
* @param valueFactory factory to create values
|
||||
* @param codeFragment code fragment to analyze:
|
||||
* normally a PsiCodeBlock or PsiExpression.
|
||||
* If PsiWhileStatement or PsiDoWhileStatement then only one loop iteration will be analyzed
|
||||
* (similar to analyzing the loop body, but condition is analyzed as well).
|
||||
* If PsiClass then class initializers + field initializers will be analyzed
|
||||
* @param inlining if true inlining is performed for known method calls
|
||||
*/
|
||||
ControlFlowAnalyzer(final DfaValueFactory valueFactory, @NotNull PsiElement codeFragment, boolean inlining) {
|
||||
myInlining = inlining;
|
||||
myFactory = valueFactory;
|
||||
@@ -429,7 +438,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
@Override public void visitContinueStatement(PsiContinueStatement statement) {
|
||||
startElement(statement);
|
||||
PsiStatement continuedStatement = statement.findContinuedStatement();
|
||||
if (continuedStatement instanceof PsiLoopStatement && PsiTreeUtil.isAncestor(myCodeFragment, continuedStatement, false)) {
|
||||
if (continuedStatement instanceof PsiLoopStatement && PsiTreeUtil.isAncestor(myCodeFragment, continuedStatement, true)) {
|
||||
PsiStatement body = ((PsiLoopStatement)continuedStatement).getBody();
|
||||
controlTransfer(new InstructionTransfer(getEndOffset(body), getVariablesInside(body)), getTrapsInsideElement(body));
|
||||
} else {
|
||||
@@ -449,9 +458,13 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
if (condition != null) {
|
||||
condition.accept(this);
|
||||
generateBoxingUnboxingInstructionFor(condition, PsiType.BOOLEAN);
|
||||
if (statement == myCodeFragment) {
|
||||
addInstruction(new PopInstruction());
|
||||
} else {
|
||||
addInstruction(new ConditionalGotoInstruction(getStartOffset(statement), false, condition));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
finishElement(statement);
|
||||
}
|
||||
@@ -1172,7 +1185,9 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
body.accept(this);
|
||||
}
|
||||
|
||||
if (statement != myCodeFragment) {
|
||||
addInstruction(new GotoInstruction(getStartOffset(statement)));
|
||||
}
|
||||
|
||||
finishElement(statement);
|
||||
}
|
||||
|
||||
@@ -536,3 +536,5 @@ action.AnActionButton.text.import=Import
|
||||
action.AnActionButton.description.import=Import
|
||||
action.AnActionButton.text.export=Export
|
||||
action.AnActionButton.description.export=Export
|
||||
action.TurnOffDfaAssist.text=Turn Off Data Flow Assist
|
||||
action.TurnOffDfaAssist.description=Switch off data flow aided debugging for this session
|
||||
|
||||
Reference in New Issue
Block a user