PY-28686: Fix PSI leak in AutoImportQuickFIx

This commit is contained in:
fitermay
2018-03-02 14:57:05 +03:00
committed by Elizaveta Shashkova
parent 270ccae3b7
commit 4ce0cd862f
3 changed files with 36 additions and 24 deletions
@@ -217,7 +217,8 @@ public class AutoImportQuickFix extends LocalQuickFixOnPsiElement implements Hig
public boolean hasProjectImports() {
ProjectFileIndex fileIndex = ProjectFileIndex.SERVICE.getInstance(getStartElement().getProject());
for (ImportCandidateHolder anImport : myImports) {
VirtualFile file = anImport.getFile().getVirtualFile();
PsiFileSystemItem importFile = anImport.getFile();
VirtualFile file = importFile != null ? importFile.getVirtualFile() : null;
if (file != null && fileIndex.isInContent(file)) {
return true;
}
@@ -22,9 +22,7 @@ import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.psi.*;
import com.intellij.psi.util.QualifiedName;
import com.intellij.util.containers.ContainerUtil;
import com.jetbrains.python.psi.*;
@@ -47,10 +45,10 @@ import java.util.List;
*/
// visibility is intentionally package-level
public class ImportCandidateHolder implements Comparable<ImportCandidateHolder> {
private final PsiElement myImportable;
private final PyImportElement myImportElement;
private final PsiFileSystemItem myFile;
private final QualifiedName myPath;
@NotNull private final SmartPsiElementPointer<PsiElement> myImportable;
@Nullable private final SmartPsiElementPointer<PyImportElement> myImportElement;
@NotNull private final SmartPsiElementPointer<PsiFileSystemItem> myFile;
@Nullable private final QualifiedName myPath;
@Nullable private final String myAsName;
/**
@@ -67,9 +65,10 @@ public class ImportCandidateHolder implements Comparable<ImportCandidateHolder>
*/
public ImportCandidateHolder(@NotNull PsiElement importable, @NotNull PsiFileSystemItem file,
@Nullable PyImportElement importElement, @Nullable QualifiedName path, @Nullable String asName) {
myFile = file;
myImportable = importable;
myImportElement = importElement;
SmartPointerManager pointerManager = SmartPointerManager.getInstance(importable.getProject());
myFile = pointerManager.createSmartPsiElementPointer(file);
myImportable = pointerManager.createSmartPsiElementPointer(importable);
myImportElement = importElement != null ? pointerManager.createSmartPsiElementPointer(importElement) : null;
myPath = path;
myAsName = asName;
assert importElement != null || path != null; // one of these must be present
@@ -79,19 +78,20 @@ public class ImportCandidateHolder implements Comparable<ImportCandidateHolder>
@Nullable PyImportElement importElement, @Nullable QualifiedName path) {
this(importable, file, importElement, path, null);
}
@NotNull
@Nullable
public PsiElement getImportable() {
return myImportable;
return myImportable.getElement();
}
@Nullable
public PyImportElement getImportElement() {
return myImportElement;
return myImportElement != null ? myImportElement.getElement() : null;
}
@NotNull
@Nullable
public PsiFileSystemItem getFile() {
return myFile;
return myFile.getElement();
}
@Nullable
@@ -131,16 +131,18 @@ public class ImportCandidateHolder implements Comparable<ImportCandidateHolder>
@NotNull
public String getPresentableText(@NotNull String myName) {
final StringBuilder sb = new StringBuilder(getQualifiedName(myName, myPath, myImportElement));
PyImportElement importElement = getImportElement();
PsiElement importable = getImportable();
final StringBuilder sb = new StringBuilder(getQualifiedName(myName, myPath, importElement));
PsiElement parent = null;
if (myImportElement != null) {
parent = myImportElement.getParent();
if (importElement != null) {
parent = importElement.getParent();
}
if (myImportable instanceof PyFunction) {
if (importable instanceof PyFunction) {
sb.append("()");
}
else if (myImportable instanceof PyClass) {
final List<String> supers = ContainerUtil.mapNotNull(((PyClass)myImportable).getSuperClasses(null),
else if (importable instanceof PyClass) {
final List<String> supers = ContainerUtil.mapNotNull(((PyClass)importable).getSuperClasses(null),
cls -> PyUtil.isObjectClass(cls) ? null : cls.getName());
if (!supers.isEmpty()) {
sb.append("(");
@@ -153,6 +153,9 @@ public class ImportFromExistingAction implements QuestionAction {
final PyElementGenerator gen = PyElementGenerator.getInstance(project);
final PsiFileSystemItem filesystemAnchor = ObjectUtils.chooseNotNull(as(item.getImportable(), PsiFileSystemItem.class), item.getFile());
if (filesystemAnchor == null) {
return;
}
AddImportHelper.ImportPriority priority = AddImportHelper.getImportPriority(myTarget, filesystemAnchor);
PsiFile file = myTarget.getContainingFile();
InjectedLanguageManager manager = InjectedLanguageManager.getInstance(project);
@@ -214,9 +217,12 @@ public class ImportFromExistingAction implements QuestionAction {
private void doWriteAction(final ImportCandidateHolder item) {
PsiElement src = item.getImportable();
if (src == null) {
return;
}
new WriteCommandAction(src.getProject(), PyBundle.message("ACT.CMD.use.import"), myTarget.getContainingFile()) {
@Override
protected void run(@NotNull Result result) throws Throwable {
protected void run(@NotNull Result result) {
doIt(item);
}
}.execute();
@@ -259,7 +265,10 @@ public class ImportFromExistingAction implements QuestionAction {
clear();
ImportCandidateHolder item = (ImportCandidateHolder)value;
setIcon(item.getImportable().getIcon(0));
PsiElement importable = ((ImportCandidateHolder)value).getImportable();
if (importable != null) {
setIcon(importable.getIcon(0));
}
String item_name = item.getPresentableText(myName);
append(item_name, SimpleTextAttributes.REGULAR_ATTRIBUTES);