diff --git a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java index b03f804fdd45..96bb8becf44a 100644 --- a/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java +++ b/java/java-analysis-impl/src/com/intellij/codeInspection/reference/RefJavaManagerImpl.java @@ -23,10 +23,7 @@ import com.intellij.codeInspection.deadCode.UnusedDeclarationInspectionBase; import com.intellij.codeInspection.ex.*; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.Comparing; -import com.intellij.openapi.util.Disposer; -import com.intellij.openapi.util.Ref; -import com.intellij.openapi.util.UserDataCache; +import com.intellij.openapi.util.*; import com.intellij.psi.*; import com.intellij.psi.javadoc.PsiDocComment; import com.intellij.psi.javadoc.PsiDocTag; @@ -164,21 +161,20 @@ public class RefJavaManagerImpl extends RefJavaManager { } @Override - public RefParameter getParameterReference(PsiParameter param, int index) { + public RefParameter getParameterReference(final PsiParameter param, final int index) { LOG.assertTrue(myRefManager.isValidPointForReference(), "References may become invalid after process is finished"); - RefElement ref = myRefManager.getFromRefTable(param); - - if (ref == null) { - ref = new RefParameterImpl(param, index, myRefManager); - ((RefParameterImpl)ref).initialize(); - myRefManager.putToRefTable(param, ref); - } - - return (RefParameter)ref; + + return myRefManager.getFromRefTableOrCache(param, new NullableFactory() { + @Nullable + @Override + public RefParameter create() { + RefParameter ref = new RefParameterImpl(param, index, myRefManager); + ((RefParameterImpl)ref).initialize(); + return ref; + } + }); } - - @Override public void iterate(@NotNull final RefVisitor visitor) { if (myPackages != null) { 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 aa84edc6b21b..b0af3b30cace 100644 --- a/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java +++ b/platform/analysis-impl/src/com/intellij/codeInspection/reference/RefManagerImpl.java @@ -44,12 +44,14 @@ import com.intellij.openapi.project.Project; import com.intellij.openapi.project.ProjectUtilCore; import com.intellij.openapi.util.Computable; import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.NullableFactory; import com.intellij.openapi.util.Segment; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFileManager; import com.intellij.psi.*; import com.intellij.psi.impl.light.LightElement; +import com.intellij.util.Consumer; import com.intellij.util.containers.ContainerUtil; import gnu.trove.THashMap; import org.jdom.Element; @@ -340,11 +342,6 @@ public class RefManagerImpl extends RefManager { return myRefProject; } - @NotNull - public Map getRefTable() { - return myRefTable; - } - @NotNull public List getSortedElements() { LOG.assertTrue(myRefTable != null); @@ -371,7 +368,7 @@ public class RefManagerImpl extends RefManager { public void removeReference(@NotNull RefElement refElem) { myLock.writeLock().lock(); try { - final Map refTable = getRefTable(); + final Map refTable = myRefTable; final PsiElement element = refElem.getElement(); final RefManagerExtension extension = element != null ? getExtension(element.getLanguage()) : null; if (extension != null) { @@ -460,47 +457,41 @@ public class RefManagerImpl extends RefManager { return null; } - RefElement ref = getFromRefTable(elem); - if (ref != null) return ref; - if (!isValidPointForReference()) { - //LOG.assertTrue(true, "References may become invalid after process is finished"); - return null; - } - - final RefElementImpl refElement = ApplicationManager.getApplication().runReadAction(new Computable() { - @Override - @Nullable - public RefElementImpl compute() { - final RefManagerExtension extension = getExtension(elem.getLanguage()); - if (extension != null) { - final RefElement refElement = extension.createRefElement(elem); - if (refElement != null) return (RefElementImpl)refElement; + return getFromRefTableOrCache( + elem, + new NullableFactory() { + @Override + public RefElementImpl create() { + return ApplicationManager.getApplication().runReadAction(new Computable() { + @Override + @Nullable + public RefElementImpl compute() { + final RefManagerExtension extension = getExtension(elem.getLanguage()); + if (extension != null) { + final RefElement refElement = extension.createRefElement(elem); + if (refElement != null) return (RefElementImpl)refElement; + } + if (elem instanceof PsiFile) { + return new RefFileImpl((PsiFile)elem, RefManagerImpl.this); + } + if (elem instanceof PsiDirectory) { + return new RefDirectoryImpl((PsiDirectory)elem, RefManagerImpl.this); + } + return null; + } + }); } - if (elem instanceof PsiFile) { - return new RefFileImpl((PsiFile)elem, RefManagerImpl.this); + }, + new Consumer() { + @Override + public void consume(RefElementImpl element) { + element.initialize(); + for (RefManagerExtension each : myExtensions.values()) { + each.onEntityInitialized(element, elem); + } + fireNodeInitialized(element); } - if (elem instanceof PsiDirectory) { - return new RefDirectoryImpl((PsiDirectory)elem, RefManagerImpl.this); - } - return null; - } - }); - if (refElement == null) return null; - - putToRefTable(elem, refElement); - - ApplicationManager.getApplication().runReadAction(new Runnable() { - @Override - public void run() { - refElement.initialize(); - for (RefManagerExtension extension : myExtensions.values()) { - extension.onEntityInitialized(refElement, elem); - } - fireNodeInitialized(refElement); - } - }); - - return refElement; + }); } private RefManagerExtension getExtension(final Language language) { @@ -509,8 +500,7 @@ public class RefManagerImpl extends RefManager { @Nullable @Override - public - RefEntity getReference(final String type, final String fqName) { + public RefEntity getReference(final String type, final String fqName) { for (RefManagerExtension extension : myExtensions.values()) { final RefEntity refEntity = extension.getReference(type, fqName); if (refEntity != null) return refEntity; @@ -535,38 +525,73 @@ public class RefManagerImpl extends RefManager { return null; } - protected RefElement getFromRefTable(final PsiElement element) { + @Nullable + protected T getFromRefTableOrCache(final PsiElement element, + @NotNull NullableFactory factory) { + return getFromRefTableOrCache(element, factory, null); + } + + @Nullable + protected T getFromRefTableOrCache(final PsiElement element, + @NotNull NullableFactory factory, + @Nullable Consumer whenCached) { + T result; + myLock.readLock().lock(); try { - return getRefTable().get(ApplicationManager.getApplication().runReadAction( - new Computable() { - @Override - public PsiAnchor compute() { - return PsiAnchor.create(element); - } + //noinspection unchecked + result = (T)myRefTable.get(ApplicationManager.getApplication().runReadAction( + new Computable() { + @Override + public PsiAnchor compute() { + return PsiAnchor.create(element); } + } )); } finally { myLock.readLock().unlock(); } - } - protected void putToRefTable(final PsiElement element, final RefElement ref) { + if (result != null) return result; + + if (!isValidPointForReference()) { + //LOG.assertTrue(true, "References may become invalid after process is finished"); + return null; + } + myLock.writeLock().lock(); try { - getRefTable().put(ApplicationManager.getApplication().runReadAction( - new Computable() { - @Override - public PsiAnchor compute() { - return PsiAnchor.create(element); - } + //noinspection unchecked + result = (T)myRefTable.get(ApplicationManager.getApplication().runReadAction( + new Computable() { + @Override + public PsiAnchor compute() { + return PsiAnchor.create(element); } - ), ref); + } + )); + if (result != null) return result; + + result = factory.create(); + if (result == null) return null; + + myRefTable.put(ApplicationManager.getApplication().runReadAction( + new Computable() { + @Override + public PsiAnchor compute() { + return PsiAnchor.create(element); + } + } + ), result); } finally { myLock.writeLock().unlock(); } + + if (whenCached != null) whenCached.consume(result); + + return result; } @Override