mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
java: ensure PSI/document compatibility for decompiled .class files
This commit is contained in:
@@ -17,8 +17,6 @@ package com.intellij.psi.impl.compiled;
|
||||
|
||||
import com.intellij.openapi.components.ServiceManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.BinaryFileDecompiler;
|
||||
import com.intellij.openapi.project.DefaultProjectFactory;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
@@ -54,17 +52,6 @@ public class ClassFileDecompiler implements BinaryFileDecompiler {
|
||||
if (result != null) return result;
|
||||
}
|
||||
|
||||
return decompileText(file);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public static CharSequence decompileText(@NotNull VirtualFile file) {
|
||||
Document document = FileDocumentManager.getInstance().getCachedDocument(file);
|
||||
if (document != null) {
|
||||
return document.getImmutableCharSequence();
|
||||
}
|
||||
|
||||
ClassFileDecompilers.Decompiler decompiler = ClassFileDecompilers.find(file);
|
||||
if (decompiler instanceof ClassFileDecompilers.Light) {
|
||||
try {
|
||||
return ((ClassFileDecompilers.Light)decompiler).getText(file);
|
||||
|
||||
@@ -24,8 +24,10 @@ import com.intellij.lang.FileASTNode;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.extensions.Extensions;
|
||||
import com.intellij.openapi.extensions.PluginId;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.fileTypes.FileType;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.project.DefaultProjectFactory;
|
||||
@@ -33,6 +35,7 @@ import com.intellij.openapi.roots.FileIndexFacade;
|
||||
import com.intellij.openapi.ui.Queryable;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.Computable;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.ModificationTracker;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
@@ -77,6 +80,8 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
|
||||
implements PsiJavaFile, PsiFileWithStubSupport, PsiFileEx, Queryable, PsiClassOwnerEx, PsiCompiledFile {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClsFileImpl");
|
||||
|
||||
private static final Key<Document> CLS_DOCUMENT_LINK_KEY = Key.create("cls.document.link");
|
||||
|
||||
/** NOTE: you absolutely MUST NOT hold PsiLock under the mirror lock */
|
||||
private final Object myMirrorLock = new Object();
|
||||
private final Object myStubLock = new Object();
|
||||
@@ -342,7 +347,10 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
|
||||
}
|
||||
|
||||
private TreeElement trySetMirror(VirtualFile file, String fileName, boolean usePlugin) {
|
||||
CharSequence mirrorText = ClassFileDecompiler.decompileText(file);
|
||||
final Document document = FileDocumentManager.getInstance().getDocument(file);
|
||||
assert document != null : file.getUrl();
|
||||
|
||||
CharSequence mirrorText = document.getImmutableCharSequence();
|
||||
PsiFileFactory factory = PsiFileFactory.getInstance(getManager().getProject());
|
||||
PsiFile mirror = factory.createFileFromText(fileName, JavaLanguage.INSTANCE, mirrorText, false, false);
|
||||
mirror.putUserData(PsiUtil.FILE_LANGUAGE_LEVEL_KEY, getLanguageLevel());
|
||||
@@ -353,6 +361,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
|
||||
@Override
|
||||
public void run() {
|
||||
setMirror(mirrorTreeElement);
|
||||
putUserData(CLS_DOCUMENT_LINK_KEY, document);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -515,6 +524,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement<PsiClassHolderFileStub>
|
||||
|
||||
ClsPackageStatementImpl packageStatement = new ClsPackageStatementImpl(this);
|
||||
synchronized (myMirrorLock) {
|
||||
putUserData(CLS_DOCUMENT_LINK_KEY, null);
|
||||
myMirrorFileElement = null;
|
||||
myPackageStatement = packageStatement;
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -17,10 +17,12 @@ package com.intellij.psi;
|
||||
|
||||
import com.intellij.JavaTestUtil;
|
||||
import com.intellij.ide.highlighter.JavaFileType;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.fileEditor.FileDocumentManager;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.StandardFileSystems;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.openapi.vfs.VirtualFileSystem;
|
||||
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
|
||||
import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
|
||||
import com.intellij.psi.impl.compiled.ClsFileImpl;
|
||||
@@ -31,6 +33,7 @@ import com.intellij.testFramework.LightIdeaTestCase;
|
||||
import com.intellij.testFramework.PlatformTestUtil;
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
public class ClsMirrorBuildingTest extends LightIdeaTestCase {
|
||||
@@ -107,6 +110,34 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
|
||||
new ClassReader(file.contentsToByteArray()).accept(visitor, ClassReader.SKIP_FRAMES);
|
||||
}
|
||||
|
||||
public void testDocumentReuse() throws IOException {
|
||||
File classFile = new File(FileUtil.getTempDirectory(), "ReuseTest.class");
|
||||
assertTrue(classFile.getPath(), classFile.createNewFile());
|
||||
VirtualFile vFile = StandardFileSystems.local().findFileByPath(classFile.getPath());
|
||||
assertNotNull(classFile.getPath(), vFile);
|
||||
PsiFile psiFile = PsiManager.getInstance(getProject()).findFile(vFile);
|
||||
assertNotNull(psiFile);
|
||||
String testDir = JavaTestUtil.getJavaTestDataPath() + "/psi/cls/mirror/";
|
||||
|
||||
FileUtil.copy(new File(testDir, "pkg/ReuseTestV1.class"), classFile);
|
||||
vFile.refresh(false, false);
|
||||
String text1 = psiFile.getText();
|
||||
assertTrue(text1, text1.contains("private int f1"));
|
||||
assertFalse(text1, text1.contains("private int f2"));
|
||||
Document doc1 = FileDocumentManager.getInstance().getCachedDocument(vFile);
|
||||
assertNotNull(doc1);
|
||||
assertSame(doc1, PsiDocumentManager.getInstance(getProject()).getDocument(psiFile));
|
||||
|
||||
FileUtil.copy(new File(testDir, "pkg/ReuseTestV2.class"), classFile);
|
||||
vFile.refresh(false, false);
|
||||
String text2 = psiFile.getText();
|
||||
assertTrue(text2, text2.contains("private int f1"));
|
||||
assertTrue(text2, text2.contains("private int f2"));
|
||||
Document doc2 = FileDocumentManager.getInstance().getCachedDocument(vFile);
|
||||
assertNotNull(doc2);
|
||||
assertSame(doc2, PsiDocumentManager.getInstance(getProject()).getDocument(psiFile));
|
||||
}
|
||||
|
||||
private void doTest() {
|
||||
doTest(getTestName(false));
|
||||
}
|
||||
@@ -117,8 +148,7 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
|
||||
}
|
||||
|
||||
private static void doTest(String clsPath, String txtPath) {
|
||||
VirtualFileSystem fs = clsPath.contains("!/") ? StandardFileSystems.jar() : StandardFileSystems.local();
|
||||
VirtualFile file = fs.findFileByPath(clsPath);
|
||||
VirtualFile file = (clsPath.contains("!/") ? StandardFileSystems.jar() : StandardFileSystems.local()).findFileByPath(clsPath);
|
||||
assertNotNull(clsPath, file);
|
||||
|
||||
String expected;
|
||||
@@ -126,8 +156,7 @@ public class ClsMirrorBuildingTest extends LightIdeaTestCase {
|
||||
expected = StringUtil.trimTrailing(PlatformTestUtil.loadFileText(txtPath));
|
||||
}
|
||||
catch (IOException e) {
|
||||
fail(e.getMessage());
|
||||
return;
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
assertEquals(expected, ClsFileImpl.decompile(file).toString());
|
||||
|
||||
Reference in New Issue
Block a user