mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Patterns resolve: stop at switch label; filter by name before doing control flow analysis when possible (IDEA-229846)
Review ID: IDEA-CR-56992 GitOrigin-RevId: 4264da45582f5d38e3b5630184d8ab762f30575b
This commit is contained in:
committed by
intellij-monorepo-bot
parent
1a2437cb71
commit
43e64e1c56
@@ -8,6 +8,10 @@ import org.jetbrains.annotations.Nullable;
|
||||
* A variable declared within the pattern
|
||||
*/
|
||||
public interface PsiPatternVariable extends PsiVariable {
|
||||
@NotNull
|
||||
@Override
|
||||
String getName();
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
PsiTypeElement getTypeElement();
|
||||
|
||||
+29
-2
@@ -239,15 +239,42 @@ public class PsiCodeBlockImpl extends LazyParseablePsiElement implements PsiCode
|
||||
final ElementClassHint elementClassHint = processor.getHint(ElementClassHint.KEY);
|
||||
final String name = hint.getName(state);
|
||||
if ((elementClassHint == null || elementClassHint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) && classesSet.contains(name)) {
|
||||
return PsiScopesUtil.walkChildrenScopes(this, processor, state, lastParent, place);
|
||||
return walkChildren(processor, state, lastParent, place);
|
||||
}
|
||||
if ((elementClassHint == null || elementClassHint.shouldProcess(ElementClassHint.DeclarationKind.VARIABLE)) && variablesSet.contains(name)) {
|
||||
return PsiScopesUtil.walkChildrenScopes(this, processor, state, lastParent, place);
|
||||
return walkChildren(processor, state, lastParent, place);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return walkChildren(processor, state, lastParent, place);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean walkChildren(@NotNull PsiScopeProcessor processor,
|
||||
@NotNull ResolveState state,
|
||||
PsiElement lastParent,
|
||||
@NotNull PsiElement place) {
|
||||
if (!(getParent() instanceof PsiSwitchBlock)) {
|
||||
return PsiScopesUtil.walkChildrenScopes(this, processor, state, lastParent, place);
|
||||
}
|
||||
PsiElement child = null;
|
||||
if (lastParent != null && lastParent.getParent() == this) {
|
||||
child = lastParent.getPrevSibling();
|
||||
if (child == null) return true; // first element
|
||||
}
|
||||
|
||||
if (child == null) {
|
||||
child = ((PsiElement)this).getLastChild();
|
||||
}
|
||||
|
||||
while (child != null) {
|
||||
if (child instanceof PsiSwitchLabelStatementBase) {
|
||||
state = PatternResolveState.WHEN_NONE.putInto(state);
|
||||
}
|
||||
if (!child.processDeclarations(processor, state, null, place)) return false;
|
||||
child = child.getPrevSibling();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+1
@@ -197,6 +197,7 @@ public class PsiConditionalExpressionImpl extends ExpressionPsiElement implement
|
||||
@NotNull ResolveState state,
|
||||
PsiElement lastParent,
|
||||
@NotNull PsiElement place) {
|
||||
if (lastParent == null) return true;
|
||||
ElementClassHint elementClassHint = processor.getHint(ElementClassHint.KEY);
|
||||
if (elementClassHint != null && !elementClassHint.shouldProcess(ElementClassHint.DeclarationKind.VARIABLE)) return true;
|
||||
PsiExpression condition = getCondition();
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.intellij.psi.impl.source.tree.CompositePsiElement;
|
||||
import com.intellij.psi.impl.source.tree.ElementType;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
import com.intellij.psi.scope.NameHint;
|
||||
import com.intellij.psi.scope.PatternResolveState;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.tree.ChildRoleBase;
|
||||
@@ -209,6 +210,7 @@ public class PsiIfStatementImpl extends CompositePsiElement implements PsiIfStat
|
||||
PsiStatement thenBranch = getThenBranch();
|
||||
PsiStatement elseBranch = getElseBranch();
|
||||
if (lastParent == null) {
|
||||
if (state.get(PatternResolveState.KEY) == PatternResolveState.WHEN_NONE) return true;
|
||||
PsiScopeProcessor conditionProcessor;
|
||||
if (state.get(PatternResolveState.KEY) == PatternResolveState.WHEN_BOTH) {
|
||||
conditionProcessor = processor;
|
||||
@@ -216,6 +218,10 @@ public class PsiIfStatementImpl extends CompositePsiElement implements PsiIfStat
|
||||
else {
|
||||
conditionProcessor = (element, s) -> {
|
||||
LOG.assertTrue(element instanceof PsiPatternVariable);
|
||||
final NameHint hint = processor.getHint(NameHint.KEY);
|
||||
if (hint != null && !((PsiPatternVariable)element).getName().equals(hint.getName(s))) {
|
||||
return true;
|
||||
}
|
||||
ControlFlow flow;
|
||||
try {
|
||||
flow = ControlFlowFactory.getInstance(getProject()).getControlFlow(
|
||||
|
||||
+6
@@ -22,6 +22,7 @@ import com.intellij.psi.impl.PsiImplUtil;
|
||||
import com.intellij.psi.impl.source.Constants;
|
||||
import com.intellij.psi.impl.source.tree.ChildRole;
|
||||
import com.intellij.psi.scope.ElementClassHint;
|
||||
import com.intellij.psi.scope.NameHint;
|
||||
import com.intellij.psi.scope.PatternResolveState;
|
||||
import com.intellij.psi.scope.PsiScopeProcessor;
|
||||
import com.intellij.psi.tree.ChildRoleBase;
|
||||
@@ -137,10 +138,15 @@ public class PsiWhileStatementImpl extends PsiLoopStatementImpl implements PsiWh
|
||||
@NotNull ResolveState state,
|
||||
@NotNull PsiElement place,
|
||||
@NotNull PsiConditionalLoopStatement loop) {
|
||||
if (state.get(PatternResolveState.KEY) == PatternResolveState.WHEN_NONE) return true;
|
||||
PsiExpression condition = loop.getCondition();
|
||||
if (condition == null) return true;
|
||||
PsiScopeProcessor conditionProcessor = (element, s) -> {
|
||||
assert element instanceof PsiPatternVariable;
|
||||
final NameHint hint = processor.getHint(NameHint.KEY);
|
||||
if (hint != null && !((PsiPatternVariable)element).getName().equals(hint.getName(s))) {
|
||||
return true;
|
||||
}
|
||||
PatternResolveState resolveState = PatternResolveState.stateAtParent((PsiPatternVariable)element, condition);
|
||||
if (resolveState == PatternResolveState.WHEN_TRUE ||
|
||||
!PsiTreeUtil
|
||||
|
||||
@@ -6,7 +6,7 @@ import com.intellij.psi.*;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public enum PatternResolveState {
|
||||
WHEN_TRUE, WHEN_FALSE, WHEN_BOTH;
|
||||
WHEN_TRUE, WHEN_FALSE, WHEN_BOTH, WHEN_NONE;
|
||||
|
||||
public static final Key<PatternResolveState> KEY = Key.create("JavaPatternDeclarationHint");
|
||||
|
||||
@@ -20,10 +20,8 @@ public enum PatternResolveState {
|
||||
return WHEN_FALSE;
|
||||
case WHEN_FALSE:
|
||||
return WHEN_TRUE;
|
||||
case WHEN_BOTH:
|
||||
return WHEN_BOTH;
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected value: " + this);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
class X {
|
||||
void test(Object obj, int x) {
|
||||
switch (x) {
|
||||
case 1:
|
||||
if (!(obj instanceof String s)) return;
|
||||
System.out.println(s.trim());
|
||||
case 2:
|
||||
if (!(obj instanceof Number s)) return;
|
||||
System.out.println(s.longValue());
|
||||
case 3:
|
||||
System.out.println(<error descr="Cannot resolve symbol 's'">s</error>);
|
||||
}
|
||||
}
|
||||
|
||||
void testWhile(Object obj, int x) {
|
||||
switch (x) {
|
||||
case 1:
|
||||
while(!(obj instanceof String s)) {
|
||||
obj = getNextObject();
|
||||
}
|
||||
System.out.println(s.trim());
|
||||
case 2:
|
||||
System.out.println(<error descr="Cannot resolve symbol 's'">s</error>.trim());
|
||||
}
|
||||
}
|
||||
|
||||
native Object getNextObject();
|
||||
}
|
||||
+3
@@ -27,6 +27,9 @@ public class LightPatternsHighlightingTest extends LightJavaCodeInsightFixtureTe
|
||||
public void testInstanceOfControlFlow() {
|
||||
doTest();
|
||||
}
|
||||
public void testInstanceOfInSwitch() {
|
||||
doTest();
|
||||
}
|
||||
public void testReassignPatternVariable() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user