mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
let psi file become invalid when its original file is invalid
because otherwise clients call getOriginalFile and end up with invalid PSI
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
package com.intellij.java.psi;
|
||||
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.application.WriteAction;
|
||||
import com.intellij.openapi.application.ex.PathManagerEx;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.io.IoTestUtil;
|
||||
@@ -461,4 +462,23 @@ public class ClsPsiTest extends LightIdeaTestCase {
|
||||
LeakHunter.checkLeak(dbl, ClassElement.class, element -> element.getPsi().getUserData(ClsElementImpl.COMPILED_ELEMENT) == dbl);
|
||||
assertFalse(hash1 == ((ClsClassImpl)dbl).getMirror().hashCode());
|
||||
}
|
||||
|
||||
public void testMirrorBecomesInvalidTogetherWithCls() throws IOException {
|
||||
File testFile = IoTestUtil.createTestFile("TestClass.class");
|
||||
File file1 = new File(PathManagerEx.getTestDataPath() + TEST_DATA_PATH + "/1_TestClass.class");
|
||||
FileUtil.copy(file1, testFile);
|
||||
VirtualFile copyVFile = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(testFile);
|
||||
|
||||
ClsFileImpl clsFile = (ClsFileImpl)PsiManager.getInstance(getProject()).findFile(copyVFile);
|
||||
PsiElement mirror = clsFile.getMirror();
|
||||
|
||||
assertTrue(clsFile.isValid());
|
||||
assertTrue(mirror.isValid());
|
||||
|
||||
WriteAction.run(() -> copyVFile.delete(this));
|
||||
assertFalse(clsFile.isValid());
|
||||
assertFalse(mirror.isValid());
|
||||
assertTrue(PsiInvalidElementAccessException.findOutInvalidationReason(mirror)
|
||||
.contains(PsiInvalidElementAccessException.findOutInvalidationReason(clsFile)));
|
||||
}
|
||||
}
|
||||
@@ -107,7 +107,12 @@ public class PsiInvalidElementAccessException extends RuntimeException implement
|
||||
@Nullable
|
||||
private static Object getPsiInvalidationTrace(@NotNull PsiElement element) {
|
||||
Object trace = getInvalidationTrace(element);
|
||||
return trace != null || element instanceof PsiFile ? trace : findInvalidationTrace(element.getNode());
|
||||
if (trace != null) return trace;
|
||||
|
||||
if (element instanceof PsiFile) {
|
||||
return getInvalidationTrace(((PsiFile)element).getOriginalFile());
|
||||
}
|
||||
return findInvalidationTrace(element.getNode());
|
||||
}
|
||||
|
||||
private static String getMessageWithReason(@NotNull PsiElement element,
|
||||
@@ -120,7 +125,7 @@ public class PsiInvalidElementAccessException extends RuntimeException implement
|
||||
trace != null ? "see attachment" :
|
||||
"no info";
|
||||
try {
|
||||
reason += " because: " + reason(element);
|
||||
reason += " because: " + findOutInvalidationReason(element);
|
||||
}
|
||||
catch (PsiInvalidElementAccessException ignore) {
|
||||
}
|
||||
@@ -161,7 +166,7 @@ public class PsiInvalidElementAccessException extends RuntimeException implement
|
||||
|
||||
@NonNls
|
||||
@NotNull
|
||||
private static String reason(@NotNull PsiElement root) {
|
||||
public static String findOutInvalidationReason(@NotNull PsiElement root) {
|
||||
if (root == PsiUtilCore.NULL_PSI_ELEMENT) return "NULL_PSI_ELEMENT";
|
||||
|
||||
PsiElement element = root instanceof PsiFile ? root : root.getParent();
|
||||
@@ -170,6 +175,7 @@ public class PsiInvalidElementAccessException extends RuntimeException implement
|
||||
if (root instanceof StubBasedPsiElement) {
|
||||
StubElement stub = ((StubBasedPsiElement)root).getStub();
|
||||
while (stub != null) {
|
||||
//noinspection StringConcatenationInLoop
|
||||
m += "\n each stub=" + stub;
|
||||
if (stub instanceof PsiFileStub) {
|
||||
m += "; fileStub.psi=" + stub.getPsi() + "; reason=" + ((PsiFileStub)stub).getInvalidationReason();
|
||||
@@ -190,10 +196,15 @@ public class PsiInvalidElementAccessException extends RuntimeException implement
|
||||
if (!provider.isPhysical()) {
|
||||
PsiElement context = file.getContext();
|
||||
if (context != null && !context.isValid()) {
|
||||
return "invalid context: " + reason(context);
|
||||
return "invalid context: " + findOutInvalidationReason(context);
|
||||
}
|
||||
}
|
||||
|
||||
PsiFile original = file.getOriginalFile();
|
||||
if (original != file && !original.isValid()) {
|
||||
return "invalid original: " + findOutInvalidationReason(original);
|
||||
}
|
||||
|
||||
PsiManager manager = file.getManager();
|
||||
if (manager.getProject().isDisposed()) return "project is disposed";
|
||||
|
||||
|
||||
@@ -162,6 +162,9 @@ public abstract class PsiFileImpl extends ElementBase implements PsiFileEx, PsiF
|
||||
// but some VFS listeners receive the same events before that and ask PsiFile.isValid
|
||||
return false;
|
||||
}
|
||||
if (myOriginalFile != null && !myOriginalFile.isValid()) {
|
||||
return false;
|
||||
}
|
||||
return !myInvalidated;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user