diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java index 31c35c617dcc..25baddb42d11 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClassFileDecompiler.java @@ -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); diff --git a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java index 685bffafcf89..a64de9938bd0 100644 --- a/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java +++ b/java/java-psi-impl/src/com/intellij/psi/impl/compiled/ClsFileImpl.java @@ -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 implements PsiJavaFile, PsiFileWithStubSupport, PsiFileEx, Queryable, PsiClassOwnerEx, PsiCompiledFile { private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.compiled.ClsFileImpl"); + private static final Key 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 } 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 @Override public void run() { setMirror(mirrorTreeElement); + putUserData(CLS_DOCUMENT_LINK_KEY, document); } }); } @@ -515,6 +524,7 @@ public class ClsFileImpl extends ClsRepositoryPsiElement ClsPackageStatementImpl packageStatement = new ClsPackageStatementImpl(this); synchronized (myMirrorLock) { + putUserData(CLS_DOCUMENT_LINK_KEY, null); myMirrorFileElement = null; myPackageStatement = packageStatement; } diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/ReuseTestV1.class b/java/java-tests/testData/psi/cls/mirror/pkg/ReuseTestV1.class new file mode 100644 index 000000000000..3dcddcb1c9b0 Binary files /dev/null and b/java/java-tests/testData/psi/cls/mirror/pkg/ReuseTestV1.class differ diff --git a/java/java-tests/testData/psi/cls/mirror/pkg/ReuseTestV2.class b/java/java-tests/testData/psi/cls/mirror/pkg/ReuseTestV2.class new file mode 100644 index 000000000000..bc0344f51fe7 Binary files /dev/null and b/java/java-tests/testData/psi/cls/mirror/pkg/ReuseTestV2.class differ diff --git a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java index c88c8c28c102..30dc1c8417e6 100644 --- a/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java +++ b/java/java-tests/testSrc/com/intellij/psi/ClsMirrorBuildingTest.java @@ -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());