From e61d97c6e1269835e53fd67bbbd509825ac795f8 Mon Sep 17 00:00:00 2001 From: Bas Leijdekkers Date: Wed, 29 Jun 2022 12:42:36 +0200 Subject: [PATCH] global inspections: build reference only once per element GitOrigin-RevId: c7665b3fecc5cd8ea181ad7e844c191af1267dab --- .../reference/RefClassImpl.java | 25 +++++----- .../reference/RefFieldImpl.java | 1 - .../RefFunctionalExpressionImpl.java | 1 - .../reference/RefImplicitConstructorImpl.java | 4 +- .../reference/RefJavaFileImpl.java | 47 +++++++++---------- .../reference/RefJavaModuleImpl.java | 2 - .../reference/RefMethodImpl.java | 2 - .../codeInspection/reference/RefElement.java | 4 ++ .../reference/RefElementImpl.java | 20 ++++++-- .../reference/RefManagerImpl.java | 5 +- 10 files changed, 59 insertions(+), 52 deletions(-) diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java index 2e827fb87908..1d082f3fa6fe 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefClassImpl.java @@ -71,7 +71,7 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { for (UClass innerClass : innerClasses) { final PsiElement psi = innerClass.getSourcePsi(); if (psi != null) { - final RefClass refInnerClass = (RefClass)manager.getReference(psi); + final RefElement refInnerClass = manager.getReference(psi); if (refInnerClass != null) { addChild(refInnerClass); if (!innerClass.isStatic()) utilityClass = false; @@ -121,17 +121,17 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { boolean memberSeen = false; for (UField uField : uFields) { - final RefField field = ObjectUtils.tryCast(getRefManager().getReference(uField.getSourcePsi()), RefField.class); + final RefField field = ObjectUtils.tryCast(manager.getReference(uField.getSourcePsi()), RefField.class); if (field != null) { memberSeen = true; addChild(field); if (!uField.isStatic() || uField instanceof UEnumConstant) utilityClass = false; } } - RefMethod varargConstructor = null; + RefMethodImpl varargConstructor = null; boolean constructorSeen = false; for (UMethod uMethod : uMethods) { - RefMethod refMethod = ObjectUtils.tryCast(getRefManager().getReference(uMethod.getSourcePsi()), RefMethod.class); + RefMethodImpl refMethod = ObjectUtils.tryCast(manager.getReference(uMethod.getSourcePsi()), RefMethodImpl.class); if (refMethod != null) { addChild(refMethod); @@ -143,7 +143,7 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { } if (parameters.isEmpty()) { - setDefaultConstructor((RefMethodImpl)refMethod); + setDefaultConstructor(refMethod); } else if (parameters.size() == 1) { PsiElement parameterPsi = parameters.get(0).getJavaPsi(); @@ -169,7 +169,7 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { synchronized (this) { if (varargConstructor != null && myDefaultConstructor == null) { - setDefaultConstructor((RefMethodImpl)varargConstructor); + setDefaultConstructor(varargConstructor); } } @@ -312,8 +312,6 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { } } refUtil.addReferencesTo(uClass, this, uClass.getUastSuperTypes().toArray(UElementKt.EMPTY_ARRAY)); - - getRefManager().fireBuildReferences(this); } } @@ -321,7 +319,8 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { public void accept(final @NotNull RefVisitor visitor) { if (visitor instanceof RefJavaVisitor) { ApplicationManager.getApplication().runReadAction(() -> ((RefJavaVisitor)visitor).visitClass(this)); - } else { + } + else { super.accept(visitor); } } @@ -333,7 +332,7 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { return myBases instanceof Set ? (Set)myBases : Collections.singleton((RefClass)myBases); } - private synchronized void addBaseClass(RefClass refClass){ + private synchronized void addBaseClass(RefClass refClass) { if (myBases == null) { myBases = refClass; } @@ -405,7 +404,7 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { void addTypeReference(RefJavaElement from) { if (from != null) { synchronized (this) { - if (myInTypeReferences == null){ + if (myInTypeReferences == null) { myInTypeReferences = new HashSet<>(1); } myInTypeReferences.add(from); @@ -461,7 +460,7 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { static @Nullable RefClass classFromExternalName(RefManager manager, String externalName) { - return (RefClass) manager.getReference(ClassUtil.findPsiClass(PsiManager.getInstance(manager.getProject()), externalName)); + return (RefClass)manager.getReference(ClassUtil.findPsiClass(PsiManager.getInstance(manager.getProject()), externalName)); } @Override @@ -559,7 +558,7 @@ public final class RefClassImpl extends RefJavaElementImpl implements RefClass { @Override synchronized void addOutTypeReference(RefClass refClass) { - if (myOutTypeReferences == null){ + if (myOutTypeReferences == null) { myOutTypeReferences = new HashSet<>(); } myOutTypeReferences.add(refClass); diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java index 351838a3b4d2..21128ce1d12c 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFieldImpl.java @@ -170,7 +170,6 @@ public class RefFieldImpl extends RefJavaElementImpl implements RefField { } refUtil.addTypeReference(uField, uField.getType(), getRefManager(), this); - getRefManager().fireBuildReferences(this); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFunctionalExpressionImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFunctionalExpressionImpl.java index 2fb71d94f29a..e27ad563e6b6 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFunctionalExpressionImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefFunctionalExpressionImpl.java @@ -76,7 +76,6 @@ public class RefFunctionalExpressionImpl extends RefJavaElementImpl implements R addReference(parameter, parameter.getPsiElement(), element, false, true, null); } } - getRefManager().fireBuildReferences(this); } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java index d1aaa001a54b..1ef23a844300 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefImplicitConstructorImpl.java @@ -21,9 +21,7 @@ public class RefImplicitConstructorImpl extends RefMethodImpl implements RefImpl } @Override - public void buildReferences() { - getRefManager().fireBuildReferences(this); - } + public void buildReferences() {} @Override public boolean isSuspicious() { diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java index a87066575528..360ddfedd455 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaFileImpl.java @@ -16,35 +16,34 @@ public class RefJavaFileImpl extends RefFileImpl { public void buildReferences() { PsiFile file = getPsiElement(); if (file != null && PsiPackage.PACKAGE_INFO_FILE.equals(file.getName())) { - PsiPackageStatement packageStatement = ((PsiJavaFile)file).getPackageStatement(); - if (packageStatement != null) { - packageStatement.accept(new JavaRecursiveElementWalkingVisitor() { - @Override - public void visitReferenceElement(@NotNull PsiJavaCodeReferenceElement reference) { - super.visitReferenceElement(reference); + PsiPackageStatement packageStatement = ((PsiJavaFile)file).getPackageStatement(); + if (packageStatement != null) { + packageStatement.accept(new JavaRecursiveElementWalkingVisitor() { + @Override + public void visitReferenceElement(@NotNull PsiJavaCodeReferenceElement reference) { + super.visitReferenceElement(reference); + processReference(reference.resolve()); + } + + @Override + public void visitNameValuePair(@NotNull PsiNameValuePair pair) { + super.visitNameValuePair(pair); + PsiReference reference = pair.getReference(); + if (reference != null) { processReference(reference.resolve()); } + } - @Override - public void visitNameValuePair(@NotNull PsiNameValuePair pair) { - super.visitNameValuePair(pair); - PsiReference reference = pair.getReference(); - if (reference != null) { - processReference(reference.resolve()); - } + private void processReference(PsiElement element) { + RefElement refElement = getRefManager().getReference(element); + if (refElement instanceof RefJavaElementImpl) { + addOutReference(refElement); + ((RefJavaElementImpl)refElement).markReferenced(RefJavaFileImpl.this, false, true, null); } - - private void processReference(PsiElement element) { - RefElement refElement = getRefManager().getReference(element); - if (refElement instanceof RefJavaElementImpl) { - addOutReference(refElement); - ((RefJavaElementImpl)refElement).markReferenced(RefJavaFileImpl.this, false, true, null); - } - } - }); - } + } + }); } - getRefManager().fireBuildReferences(this); + } } @Override diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java index 8aba9102ff91..82aa44f193e8 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaModuleImpl.java @@ -207,8 +207,6 @@ public final class RefJavaModuleImpl extends RefElementImpl implements RefJavaMo buildExportsReferences(javaModule); buildProvidesReferences(javaModule); buildUsesReferences(javaModule); - - getRefManager().fireBuildReferences(this); } } diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java index f7a356000824..b46169a2dd57 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefMethodImpl.java @@ -293,8 +293,6 @@ public class RefMethodImpl extends RefJavaElementImpl implements RefMethod { setBodyEmpty(isOnlyCallsSuper() || !isExternalOverride() && isEmptyExpression(method.getUastBody())); refUtil.addTypeReference(method, method.getReturnType(), getRefManager(), this); - - getRefManager().fireBuildReferences(this); } private void collectUncaughtExceptions(@NotNull PsiMethod method) { diff --git a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefElement.java b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefElement.java index 553e2b7a5997..ba59119d1aad 100644 --- a/platform/analysis-api/src/com/intellij/codeInspection/reference/RefElement.java +++ b/platform/analysis-api/src/com/intellij/codeInspection/reference/RefElement.java @@ -43,6 +43,10 @@ public interface RefElement extends RefEntity { default void buildReferences() {} + default boolean areReferencesBuilt() { + return false; + } + /** * Checks if a chain of references exists from one of the entry points to this element. * diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefElementImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefElementImpl.java index 3790dc260230..a7c462102ae2 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefElementImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefElementImpl.java @@ -25,11 +25,12 @@ import java.util.List; public abstract class RefElementImpl extends RefEntityImpl implements RefElement, WritableRefElement { protected static final Logger LOG = Logger.getInstance(RefElement.class); - private static final int IS_DELETED_MASK = 0b10000; - private static final int IS_INITIALIZED_MASK = 0b100000; - private static final int IS_REACHABLE_MASK = 0b1000000; - private static final int IS_ENTRY_MASK = 0b10000000; - private static final int IS_PERMANENT_ENTRY_MASK = 0b1_00000000; + private static final int IS_DELETED_MASK = 0b10000; // 5th bit + private static final int IS_INITIALIZED_MASK = 0b100000; // 6th bit + private static final int IS_REACHABLE_MASK = 0b1000000; // 7th bit + private static final int IS_ENTRY_MASK = 0b10000000; // 8th bit + private static final int IS_PERMANENT_ENTRY_MASK = 0b1_00000000; // 9th bit + private static final int REFERENCES_BUILT_MASK = 0b10_00000000; // 10th bit private final SmartPsiElementPointer myID; @@ -192,6 +193,15 @@ public abstract class RefElementImpl extends RefEntityImpl implements RefElement } } + public void setReferencesBuilt(boolean built) { + setFlag(built, REFERENCES_BUILT_MASK); + } + + @Override + public boolean areReferencesBuilt() { + return checkFlag(REFERENCES_BUILT_MASK); + } + public void setEntry(boolean entry) { setFlag(entry, IS_ENTRY_MASK); } diff --git a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java index 39764235730b..0ef51310b944 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java @@ -198,7 +198,7 @@ public class RefManagerImpl extends RefManager { } } - public void fireBuildReferences(RefElement refElement) { + private void fireBuildReferences(RefElement refElement) { for (RefGraphAnnotator annotator : myGraphAnnotators) { annotator.onReferencesBuild(refElement); } @@ -427,9 +427,12 @@ public class RefManagerImpl extends RefManager { } public void buildReferences(RefElement element) { + if (element.areReferencesBuilt()) return; + ((RefElementImpl)element).setReferencesBuilt(true); executeTask(() -> { element.initializeIfNeeded(); element.buildReferences(); + fireBuildReferences(element); }); }