mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
let cls mirror AST be gc-able
This commit is contained in:
@@ -21,11 +21,14 @@ import com.intellij.lang.Language;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.codeStyle.JavaCodeStyleSettingsFacade;
|
||||
import com.intellij.psi.impl.PsiElementBase;
|
||||
import com.intellij.psi.impl.smartPointers.AnchorTypeInfo;
|
||||
import com.intellij.psi.impl.smartPointers.SelfElementInfo;
|
||||
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
|
||||
import com.intellij.psi.impl.source.tree.TreeElement;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
@@ -44,7 +47,7 @@ public abstract class ClsElementImpl extends PsiElementBase implements PsiCompil
|
||||
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClsElementImpl");
|
||||
|
||||
private volatile PsiElement myMirror;
|
||||
private volatile Pair<TextRange, AnchorTypeInfo> myMirror;
|
||||
|
||||
@Override
|
||||
@NotNull
|
||||
@@ -154,12 +157,9 @@ public abstract class ClsElementImpl extends PsiElementBase implements PsiCompil
|
||||
|
||||
@Override
|
||||
public PsiElement getMirror() {
|
||||
PsiElement mirror = myMirror;
|
||||
if (mirror == null) {
|
||||
((ClsFileImpl)getContainingFile()).getMirror();
|
||||
mirror = myMirror;
|
||||
}
|
||||
return mirror;
|
||||
PsiFile mirrorFile = ((ClsFileImpl)getContainingFile()).getMirror().getContainingFile();
|
||||
Pair<TextRange, AnchorTypeInfo> mirror = myMirror;
|
||||
return mirror == null ? null : SelfElementInfo.findElementInside(mirrorFile, mirror.first, mirror.second);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -268,7 +268,7 @@ public abstract class ClsElementImpl extends PsiElementBase implements PsiCompil
|
||||
|
||||
PsiElement psi = element.getPsi();
|
||||
psi.putUserData(COMPILED_ELEMENT, this);
|
||||
myMirror = psi;
|
||||
myMirror = Pair.create(element.getTextRange(), AnchorTypeInfo.obtainInfo(psi, JavaLanguage.INSTANCE));
|
||||
}
|
||||
|
||||
protected static <T extends PsiElement> void setMirror(@Nullable T stub, @Nullable T mirror) throws InvalidMirrorException {
|
||||
|
||||
@@ -42,7 +42,6 @@ import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.compiled.ClassFileDecompilers;
|
||||
import com.intellij.psi.impl.CheckUtil;
|
||||
import com.intellij.psi.impl.DebugUtil;
|
||||
import com.intellij.psi.impl.JavaPsiImplementationHelper;
|
||||
import com.intellij.psi.impl.PsiFileEx;
|
||||
@@ -76,6 +75,7 @@ import org.jetbrains.org.objectweb.asm.ClassReader;
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ref.Reference;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -99,7 +99,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
|
||||
private final FileViewProvider myViewProvider;
|
||||
private final boolean myIsForDecompiling;
|
||||
private volatile SoftReference<StubTree> myStub;
|
||||
private volatile TreeElement myMirrorFileElement;
|
||||
private volatile Reference<TreeElement> myMirrorFileElement;
|
||||
private volatile ClsPackageStatementImpl myPackageStatement;
|
||||
private boolean myIsPhysical = true;
|
||||
private boolean myInvalidated;
|
||||
@@ -382,10 +382,10 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
|
||||
|
||||
@Override
|
||||
public PsiElement getMirror() {
|
||||
TreeElement mirrorTreeElement = myMirrorFileElement;
|
||||
TreeElement mirrorTreeElement = SoftReference.dereference(myMirrorFileElement);
|
||||
if (mirrorTreeElement == null) {
|
||||
synchronized (myMirrorLock) {
|
||||
mirrorTreeElement = myMirrorFileElement;
|
||||
mirrorTreeElement = SoftReference.dereference(myMirrorFileElement);
|
||||
if (mirrorTreeElement == null) {
|
||||
VirtualFile file = getVirtualFile();
|
||||
PsiClass[] classes = getClasses();
|
||||
@@ -417,7 +417,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
|
||||
}
|
||||
|
||||
((PsiFileImpl)mirror).setOriginalFile(this);
|
||||
myMirrorFileElement = mirrorTreeElement;
|
||||
myMirrorFileElement = new SoftReference<TreeElement>(mirrorTreeElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,17 @@ import com.intellij.openapi.util.io.IoTestUtil;
|
||||
import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.impl.compiled.ClsClassImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsElementImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl;
|
||||
import com.intellij.psi.impl.compiled.ClsParameterImpl;
|
||||
import com.intellij.psi.impl.java.stubs.PsiMethodStub;
|
||||
import com.intellij.psi.impl.source.tree.java.ClassElement;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import com.intellij.psi.util.PsiUtil;
|
||||
import com.intellij.testFramework.LeakHunter;
|
||||
import com.intellij.testFramework.LightIdeaTestCase;
|
||||
import com.intellij.util.GCUtil;
|
||||
import com.intellij.util.ObjectUtils;
|
||||
import com.intellij.util.indexing.FileBasedIndex;
|
||||
|
||||
@@ -436,4 +441,15 @@ public class ClsPsiTest extends LightIdeaTestCase {
|
||||
assertTrue(String.valueOf(clsFile), clsFile instanceof ClsFileImpl);
|
||||
return (PsiJavaFile)clsFile;
|
||||
}
|
||||
|
||||
public void testClsPsiDoesNotHoldStrongReferencesToMirrorAST() {
|
||||
PsiClass dbl = getJavaFacade().findClass(Double.class.getName(), myScope);
|
||||
assertNotNull(dbl);
|
||||
int hash1 = ((ClsClassImpl)dbl).getMirror().hashCode();
|
||||
assertEquals(dbl, ((ClsClassImpl)dbl).getMirror().getUserData(ClsElementImpl.COMPILED_ELEMENT));
|
||||
|
||||
GCUtil.tryGcSoftlyReachableObjects();
|
||||
LeakHunter.checkLeak(dbl, ClassElement.class, element -> element.getPsi().getUserData(ClsElementImpl.COMPILED_ELEMENT) == dbl);
|
||||
assertFalse(hash1 == ((ClsClassImpl)dbl).getMirror().hashCode());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user