From 3fc9bf958957b1f213692fb4dbd4fd33897c052e Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 27 Dec 2019 15:29:46 +0700 Subject: [PATCH] PsiUtil#isJvmLocalVariable GitOrigin-RevId: 39baed9559ca58e00c405eec5fe57be1f3c6384f --- .../codeInspection/dataFlow/NullabilityUtil.java | 3 +++ .../dataFlow/value/DfaExpressionFactory.java | 6 ++---- .../util/duplicates/DuplicatesFinder.java | 2 +- .../completion/PreferByKindWeigher.java | 2 +- .../completion/scope/JavaCompletionProcessor.java | 2 +- .../codeInsight/daemon/JavaRainbowVisitor.java | 5 +++-- ...AllCanBeReplacedWithConstructorInspection.java | 2 +- .../ComplexityCalculator.java | 2 +- .../DuplicateExpressionsInspection.java | 2 +- .../extractMethod/ExtractMethodProcessor.java | 3 +++ .../InlineParameterExpressionProcessor.java | 2 +- .../BaseExpressionToFieldHandler.java | 2 +- .../introduceParameter/OldReferenceResolver.java | 3 ++- .../JavaUnresolvableLocalCollisionDetector.java | 4 ++++ .../src/com/intellij/psi/util/PsiUtil.java | 15 +++++++++++++++ .../tree/java/PsiReferenceExpressionImpl.java | 2 +- .../JavaVariableConflictResolver.java | 7 +++++-- ...ditionCoveredByFurtherConditionInspection.java | 1 + 18 files changed, 47 insertions(+), 18 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityUtil.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityUtil.java index 6ca26566604c..21952a921c56 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityUtil.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/NullabilityUtil.java @@ -185,6 +185,9 @@ public class NullabilityUtil { if (expression instanceof PsiReferenceExpression) { PsiReferenceExpression ref = (PsiReferenceExpression)expression; PsiElement target = (ref).resolve(); + if (target instanceof PsiPatternVariable) { + return Nullability.NOT_NULL; // currently all pattern variables are not-null + } if (target instanceof PsiLocalVariable || target instanceof PsiParameter) { PsiElement block = PsiUtil.getVariableCodeBlock((PsiVariable)target, null); // Do not trust the declared nullability of local variable/parameter if it's reassigned as nullability designates diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaExpressionFactory.java b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaExpressionFactory.java index 5d8d9ba38fb5..5ce447376c36 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaExpressionFactory.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/dataFlow/value/DfaExpressionFactory.java @@ -352,9 +352,7 @@ public class DfaExpressionFactory { @Override public boolean isStable() { - return myVariable instanceof PsiLocalVariable || - myVariable instanceof PsiParameter || - myVariable.hasModifierProperty(PsiModifier.FINAL); + return PsiUtil.isJvmLocalVariable(myVariable) || myVariable.hasModifierProperty(PsiModifier.FINAL); } @NotNull @@ -364,7 +362,7 @@ public class DfaExpressionFactory { PsiType type = getType(ObjectUtils.tryCast(qualifier, DfaVariableValue.class)); return factory.getObjectType(type, DfaPsiUtil.getElementNullability(type, myVariable)); } - if (myVariable instanceof PsiLocalVariable || myVariable instanceof PsiParameter || + if (PsiUtil.isJvmLocalVariable(myVariable) || (myVariable instanceof PsiField && myVariable.hasModifierProperty(PsiModifier.STATIC) && (!myVariable.hasModifierProperty(PsiModifier.FINAL) || !DfaUtil.hasInitializationHacks((PsiField)myVariable)))) { return factory.getVarFactory().createVariableValue(this); diff --git a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java index ed8edb98b6e8..a42e08381944 100644 --- a/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java +++ b/java/java-analysis-impl/src/com/intellij/refactoring/util/duplicates/DuplicatesFinder.java @@ -516,7 +516,7 @@ public class DuplicatesFinder { return match.putDeclarationCorrespondence(resolveResult1, resolveResult2); } if (resolveResult1 instanceof PsiVariable && myEffectivelyLocal.contains((PsiVariable)resolveResult1)) { - return (resolveResult2 instanceof PsiLocalVariable || resolveResult2 instanceof PsiParameter) && + return PsiUtil.isJvmLocalVariable(resolveResult2) && match.putDeclarationCorrespondence(resolveResult1, resolveResult2); } PsiElement qualifier2 = candidate.getQualifier(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java index 0a93a79606b7..79395d671508 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/PreferByKindWeigher.java @@ -230,7 +230,7 @@ public class PreferByKindWeigher extends LookupElementWeigher { final JavaChainLookupElement chain = item.as(JavaChainLookupElement.CLASS_CONDITION_KEY); if (chain != null) { Object qualifier = chain.getQualifier().getObject(); - if (qualifier instanceof PsiLocalVariable || qualifier instanceof PsiParameter) { + if (qualifier instanceof PsiVariable && PsiUtil.isJvmLocalVariable((PsiVariable)qualifier)) { return MyResult.variable; } if (qualifier instanceof PsiField) { diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java index 955b0a5fce61..f9366ad6ddfc 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/scope/JavaCompletionProcessor.java @@ -141,7 +141,7 @@ public class JavaCompletionProcessor implements PsiScopeProcessor, ElementClassH if (element instanceof PsiVariable) { String name = ((PsiVariable)element).getName(); if (myShadowedNames.contains(name)) return true; - if (element instanceof PsiLocalVariable || element instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(element)) { myShadowedNames.add(name); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/JavaRainbowVisitor.java b/java/java-impl/src/com/intellij/codeInsight/daemon/JavaRainbowVisitor.java index 5750415e1440..9dc4483b67bb 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/JavaRainbowVisitor.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/JavaRainbowVisitor.java @@ -22,6 +22,7 @@ import com.intellij.psi.*; import com.intellij.psi.impl.source.javadoc.PsiDocParamRef; import com.intellij.psi.javadoc.PsiDocTagValue; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -57,10 +58,10 @@ public class JavaRainbowVisitor extends RainbowVisitor { if (rainbowElement == null || resolved == null) { return null; } - if (resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(resolved)) { String name = ((PsiVariable)resolved).getName(); if (name != null) { - return getInfo(context, rainbowElement, name, resolved instanceof PsiLocalVariable + return getInfo(context, rainbowElement, name, resolved instanceof PsiLocalVariable || resolved instanceof PsiPatternVariable ? JavaHighlightingColors.LOCAL_VARIABLE_ATTRIBUTES : rainbowElement instanceof PsiDocTagValue ? JavaHighlightingColors.DOC_COMMENT_TAG_VALUE diff --git a/java/java-impl/src/com/intellij/codeInspection/CollectionAddAllCanBeReplacedWithConstructorInspection.java b/java/java-impl/src/com/intellij/codeInspection/CollectionAddAllCanBeReplacedWithConstructorInspection.java index 9dd5cd0993c9..59245b6b8720 100644 --- a/java/java-impl/src/com/intellij/codeInspection/CollectionAddAllCanBeReplacedWithConstructorInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/CollectionAddAllCanBeReplacedWithConstructorInspection.java @@ -180,7 +180,7 @@ public class CollectionAddAllCanBeReplacedWithConstructorInspection extends Abst @Override public void visitReferenceExpression(PsiReferenceExpression expression) { final PsiElement resolved = expression.resolve(); - if (resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(resolved)) { PsiVariable variable = (PsiVariable) resolved; final LocalSearchScope useScope = (LocalSearchScope)variable.getUseScope(); if (!useScope.containsRange(newExpressionContainingFile, newExpressionTextRange)) { diff --git a/java/java-impl/src/com/intellij/codeInspection/duplicateExpressions/ComplexityCalculator.java b/java/java-impl/src/com/intellij/codeInspection/duplicateExpressions/ComplexityCalculator.java index da7646852fce..5c6f41ee815b 100644 --- a/java/java-impl/src/com/intellij/codeInspection/duplicateExpressions/ComplexityCalculator.java +++ b/java/java-impl/src/com/intellij/codeInspection/duplicateExpressions/ComplexityCalculator.java @@ -113,7 +113,7 @@ class ComplexityCalculator { return QUALIFIER; } int w = REFERENCE; - if (resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(resolved)) { w = IDENTIFIER; } else if (resolved instanceof PsiField) { diff --git a/java/java-impl/src/com/intellij/codeInspection/duplicateExpressions/DuplicateExpressionsInspection.java b/java/java-impl/src/com/intellij/codeInspection/duplicateExpressions/DuplicateExpressionsInspection.java index e40700e8470b..8c91c110fd58 100644 --- a/java/java-impl/src/com/intellij/codeInspection/duplicateExpressions/DuplicateExpressionsInspection.java +++ b/java/java-impl/src/com/intellij/codeInspection/duplicateExpressions/DuplicateExpressionsInspection.java @@ -187,7 +187,7 @@ public class DuplicateExpressionsInspection extends LocalInspectionTool { super.visitReferenceElement(reference); PsiElement resolved = reference.resolve(); - if (resolved instanceof PsiLocalVariable || resolved instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(resolved)) { variables.add((PsiVariable)resolved); } else if (resolved instanceof PsiVariable && !((PsiVariable)resolved).hasModifierProperty(PsiModifier.FINAL)) { diff --git a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java index 0c8b17b76229..e617160d0d4a 100644 --- a/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/extractMethod/ExtractMethodProcessor.java @@ -1721,6 +1721,9 @@ public class ExtractMethodProcessor implements MatchProvider { if (variableName == null) return Nullability.UNKNOWN; PsiElement methodOrLambdaBody = null; + if (variable instanceof PsiPatternVariable) { + return Nullability.NOT_NULL; + } if (variable instanceof PsiLocalVariable || variable instanceof PsiParameter) { final PsiParameterListOwner methodOrLambda = PsiTreeUtil.getParentOfType(variable, PsiMethod.class, PsiLambdaExpression.class); if (methodOrLambda != null) { diff --git a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java index c9020da1db7c..0e2171c4fb69 100644 --- a/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inline/InlineParameterExpressionProcessor.java @@ -106,7 +106,7 @@ public class InlineParameterExpressionProcessor extends BaseRefactoringProcessor if (i != parameterIndex && arguments[i] instanceof PsiReferenceExpression) { final PsiReferenceExpression referenceExpression = (PsiReferenceExpression)arguments[i]; final PsiElement element = referenceExpression.resolve(); - if (element instanceof PsiLocalVariable || element instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(element)) { final PsiParameter param = myMethod.getParameterList().getParameters()[i]; final PsiExpression paramRef = JavaPsiFacade.getElementFactory(myMethod.getProject()).createExpressionFromText(param.getName(), myMethod); diff --git a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java index 5942d793112b..683309ee0854 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceField/BaseExpressionToFieldHandler.java @@ -942,7 +942,7 @@ public abstract class BaseExpressionToFieldHandler extends IntroduceHandlerBase @Override public void visitReferenceExpression(PsiReferenceExpression expression) { final PsiElement psiElement = expression.resolve(); - if ((psiElement instanceof PsiLocalVariable || psiElement instanceof PsiParameter) && + if ((PsiUtil.isJvmLocalVariable(psiElement)) && !PsiTreeUtil.isAncestor(myInitializer, psiElement, false)) { myElementReference = expression; } diff --git a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java index 631e106f6aa9..46cca13664cd 100644 --- a/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java +++ b/java/java-impl/src/com/intellij/refactoring/introduceParameter/OldReferenceResolver.java @@ -24,6 +24,7 @@ import com.intellij.psi.*; import com.intellij.psi.codeStyle.CodeStyleManager; import com.intellij.psi.codeStyle.JavaCodeStyleManager; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.psi.util.PsiUtil; import com.intellij.refactoring.IntroduceParameterRefactoring; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.util.IncorrectOperationException; @@ -305,7 +306,7 @@ public class OldReferenceResolver { private static PsiElement getClassContainingResolve(final JavaResolveResult result) { final PsiElement elem = result.getElement(); if (elem != null) { - if (elem instanceof PsiLocalVariable || elem instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(elem)) { return PsiTreeUtil.getParentOfType(elem, PsiClass.class); } else { diff --git a/java/java-impl/src/com/intellij/refactoring/rename/JavaUnresolvableLocalCollisionDetector.java b/java/java-impl/src/com/intellij/refactoring/rename/JavaUnresolvableLocalCollisionDetector.java index dac504b439e9..5f3a6e667049 100644 --- a/java/java-impl/src/com/intellij/refactoring/rename/JavaUnresolvableLocalCollisionDetector.java +++ b/java/java-impl/src/com/intellij/refactoring/rename/JavaUnresolvableLocalCollisionDetector.java @@ -17,6 +17,7 @@ package com.intellij.refactoring.rename; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.*; +import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.refactoring.util.RefactoringUtil; import com.intellij.usageView.UsageInfo; @@ -43,6 +44,9 @@ public class JavaUnresolvableLocalCollisionDetector { anchor = element.getParent(); } } + else if (element instanceof PsiPatternVariable) { + scope = ((LocalSearchScope)element.getUseScope()).getScope()[0]; + } else { // element is a PsiParameter scope = ((PsiParameter)element).getDeclarationScope(); diff --git a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java index bfba46a0d644..fedefdb1c988 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PsiUtil.java @@ -22,6 +22,7 @@ import com.intellij.psi.infos.MethodCandidateInfo.ApplicabilityLevel; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.meta.PsiMetaData; import com.intellij.psi.meta.PsiMetaOwner; +import com.intellij.psi.search.LocalSearchScope; import com.intellij.psi.search.ProjectScope; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; @@ -316,6 +317,9 @@ public final class PsiUtil extends PsiUtilCore { codeBlock = ((PsiLambdaExpression)declarationScope).getBody(); } } + else if (variable instanceof PsiPatternVariable) { + codeBlock = ((LocalSearchScope)variable.getUseScope()).getScope()[0]; + } else if (variable instanceof PsiResourceVariable) { final PsiElement resourceList = variable.getParent(); return resourceList != null ? resourceList.getParent() : null; // use try statement as topmost @@ -1404,4 +1408,15 @@ public final class PsiUtil extends PsiUtilCore { return psiClass != null && psiClass.getManager().areElementsEquivalent( psiClass, JavaPsiFacade.getElementFactory(psiClass.getProject()).getArrayClass(getLanguageLevel(psiClass))); } + + /** + * @param variable variable to test + * @return true if variable corresponds to JVM local variable defined inside the method + */ + @Contract("null -> false") + public static boolean isJvmLocalVariable(PsiElement variable) { + return variable instanceof PsiLocalVariable || + variable instanceof PsiParameter || + variable instanceof PsiPatternVariable; + } } \ No newline at end of file diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java index 468ffd2674f0..c375fb5c42c8 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/source/tree/java/PsiReferenceExpressionImpl.java @@ -505,7 +505,7 @@ public class PsiReferenceExpressionImpl extends ExpressionPsiElement implements } private boolean ensureNonShadowedVariable(@NotNull PsiVariable element) { - if (element instanceof PsiLocalVariable || element instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(element)) { myVarNames.add(element.getName()); } return !(element instanceof PsiField) || !myVarNames.contains(element.getName()); diff --git a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaVariableConflictResolver.java b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaVariableConflictResolver.java index e7ebcaa6f0bd..d3066dff8f40 100644 --- a/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaVariableConflictResolver.java +++ b/java/java-psi-impl/src/com/intellij/psi/scope/conflictResolvers/JavaVariableConflictResolver.java @@ -1,9 +1,12 @@ // Copyright 2000-2017 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.psi.scope.conflictResolvers; -import com.intellij.psi.*; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiField; import com.intellij.psi.infos.CandidateInfo; import com.intellij.psi.scope.PsiConflictResolver; +import com.intellij.psi.util.PsiUtil; import org.jetbrains.annotations.NotNull; import java.util.List; @@ -28,7 +31,7 @@ public class JavaVariableConflictResolver implements PsiConflictResolver{ final PsiElement otherElement = candidate.getElement(); if (!(otherElement instanceof PsiField)) { - if (otherElement instanceof PsiLocalVariable || otherElement instanceof PsiParameter) { + if (PsiUtil.isJvmLocalVariable(otherElement)) { return candidate; } else { diff --git a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConditionCoveredByFurtherConditionInspection.java b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConditionCoveredByFurtherConditionInspection.java index 8231d136cf20..10895b5b16cd 100644 --- a/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConditionCoveredByFurtherConditionInspection.java +++ b/plugins/InspectionGadgets/src/com/siyeh/ig/controlflow/ConditionCoveredByFurtherConditionInspection.java @@ -146,6 +146,7 @@ public class ConditionCoveredByFurtherConditionInspection extends AbstractBaseJa return false; } PsiVariable psi = ObjectUtils.tryCast(var.getPsiVariable(), PsiVariable.class); + if (psi instanceof PsiPatternVariable) return true; if (psi instanceof PsiLocalVariable || psi instanceof PsiParameter) { PsiElement block = PsiUtil.getVariableCodeBlock(psi, null); return block == null || !HighlightControlFlowUtil.isEffectivelyFinal(psi, block, null);