From 7fc977293060c51994159379dcbb2f8e39a7acb5 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 7 Jan 2014 13:03:51 +0400 Subject: [PATCH] Direct instantiations of VirtualFileKotlinClass are replaced by access to caching service --- .../jvm/compiler/CliVirtualFileFinder.java | 4 ++-- .../kotlin/VirtualFileKotlinClassFinder.java | 20 ++++++++++++++++++- .../resolve/kotlin/KotlinClassFinder.java | 14 +++++++++++++ .../caches/JetFromJavaDescriptorHelper.java | 5 ++++- .../libraries/DecompiledDataFactory.java | 5 +++-- .../libraries/DecompiledNavigationUtils.java | 2 +- .../jet/plugin/libraries/DecompiledUtils.java | 9 ++++++--- .../JetContentBasedFileSubstitutor.java | 8 ++++---- ...yPackageFragmentClsStubBuilderFactory.java | 5 ++++- .../vfilefinder/KotlinClassFileIndex.java | 6 ++++-- 10 files changed, 61 insertions(+), 17 deletions(-) diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliVirtualFileFinder.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliVirtualFileFinder.java index e7deb61a329..3938f25e895 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliVirtualFileFinder.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/CliVirtualFileFinder.java @@ -46,7 +46,7 @@ public class CliVirtualFileFinder extends VirtualFileKotlinClassFinder implement //NOTE: copied with some changes from CoreJavaFileManager @Nullable - private static VirtualFile findFileInRoot(@NotNull String qName, @NotNull VirtualFile root) { + private VirtualFile findFileInRoot(@NotNull String qName, @NotNull VirtualFile root) { String pathRest = qName; VirtualFile cur = root; @@ -70,7 +70,7 @@ public class CliVirtualFileFinder extends VirtualFileKotlinClassFinder implement return null; } //NOTE: currently we use VirtualFileFinder to find Kotlin binaries only - if (KotlinClassHeader.read(new VirtualFileKotlinClass(vFile)) != null) { + if (KotlinClassHeader.read(createKotlinClass(vFile)) != null) { return vFile; } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClassFinder.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClassFinder.java index 224432b42ac..72bdc7b031f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClassFinder.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/kotlin/VirtualFileKotlinClassFinder.java @@ -17,16 +17,34 @@ package org.jetbrains.jet.lang.resolve.kotlin; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.util.containers.SLRUCache; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.name.FqName; public abstract class VirtualFileKotlinClassFinder implements VirtualFileFinder { + // This cache must be small: we only query the same file a few times in a row (from different places) + private final SLRUCache cache = new SLRUCache(2, 2) { + @NotNull + @Override + public KotlinJvmBinaryClass createValue(VirtualFile virtualFile) { + return new VirtualFileKotlinClass(virtualFile); + } + }; + @Nullable @Override public KotlinJvmBinaryClass findKotlinClass(@NotNull FqName fqName) { VirtualFile file = findVirtualFile(fqName); - return file == null ? null : new VirtualFileKotlinClass(file); + return file == null ? null : createKotlinClass(file); + } + + @Override + @NotNull + public KotlinJvmBinaryClass createKotlinClass(@NotNull VirtualFile file) { + synchronized (cache) { + return cache.get(file); + } } } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/KotlinClassFinder.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/KotlinClassFinder.java index a243bd383e3..9fda1a0afbc 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/KotlinClassFinder.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/KotlinClassFinder.java @@ -16,11 +16,25 @@ package org.jetbrains.jet.lang.resolve.kotlin; +import com.intellij.openapi.components.ServiceManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.name.FqName; public interface KotlinClassFinder { + + class SERVICE { + @NotNull + public static KotlinClassFinder getInstance(@NotNull Project project) { + return ServiceManager.getService(project, KotlinClassFinder.class); + } + } + @Nullable KotlinJvmBinaryClass findKotlinClass(@NotNull FqName fqName); + + @NotNull + KotlinJvmBinaryClass createKotlinClass(@NotNull VirtualFile virtualFile); } diff --git a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java index 1f5ae9def21..47ac4f5c0f4 100644 --- a/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/caches/JetFromJavaDescriptorHelper.java @@ -29,6 +29,8 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.descriptors.serialization.*; import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.resolve.java.JavaResolverPsiUtils; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass; import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader; @@ -117,7 +119,8 @@ public class JetFromJavaDescriptorHelper { private static String[] getAnnotationDataForKotlinClass(@NotNull PsiClass psiClass) { VirtualFile virtualFile = getVirtualFileForPsiClass(psiClass); if (virtualFile != null) { - KotlinClassHeader header = KotlinClassHeader.read(new VirtualFileKotlinClass(virtualFile)); + KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(psiClass.getProject()).createKotlinClass(virtualFile); + KotlinClassHeader header = KotlinClassHeader.read(kotlinClass); if (header instanceof SerializedDataHeader) { return ((SerializedDataHeader) header).getAnnotationData(); } diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java index bf7f1eb512a..a7fce506432 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledDataFactory.java @@ -28,7 +28,8 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.MemberComparator; import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; -import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -67,7 +68,7 @@ public final class DecompiledDataFactory { InjectorForJavaDescriptorResolver injector = InjectorForJavaDescriptorResolverUtil.create(project, new BindingTraceContext()); this.javaDescriptorResolver = injector.getJavaDescriptorResolver(); - VirtualFileKotlinClass kotlinClass = new VirtualFileKotlinClass(classFile); + KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(project).createKotlinClass(classFile); this.classFqName = kotlinClass.getClassName().getFqNameForClassNameWithoutDollars(); KotlinClassHeader header = KotlinClassHeader.read(kotlinClass); diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java index 7dd2f59a82b..cf9f7f6a0f2 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledNavigationUtils.java @@ -58,7 +58,7 @@ public final class DecompiledNavigationUtils { DeclarationDescriptor effectiveReferencedDescriptor = getEffectiveReferencedDescriptor(referencedDescriptor); VirtualFile virtualFile = findVirtualFileContainingDescriptor(project, effectiveReferencedDescriptor); - if (virtualFile == null || !DecompiledUtils.isKotlinCompiledFile(virtualFile)) return null; + if (virtualFile == null || !DecompiledUtils.isKotlinCompiledFile(project, virtualFile)) return null; JetDecompiledData data = JetDecompiledData.getDecompiledData(virtualFile, project); JetDeclaration jetDeclaration = data.getDeclarationForDescriptor(effectiveReferencedDescriptor); diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java index bb2c7a8c5d1..9b599973439 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/DecompiledUtils.java @@ -17,20 +17,23 @@ package org.jetbrains.jet.plugin.libraries; import com.intellij.openapi.fileTypes.StdFileTypes; +import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader; public final class DecompiledUtils { - public static boolean isKotlinCompiledFile(@NotNull VirtualFile file) { + public static boolean isKotlinCompiledFile(@NotNull Project project, @NotNull VirtualFile file) { if (!StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) { return false; } //TODO: check index - return KotlinClassHeader.read(new VirtualFileKotlinClass(file)) instanceof SerializedDataHeader; + KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(project).createKotlinClass(file); + return KotlinClassHeader.read(kotlinClass) instanceof SerializedDataHeader; } private DecompiledUtils() { diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java index 3686484d3d5..5cf073e388b 100644 --- a/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java +++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetContentBasedFileSubstitutor.java @@ -67,7 +67,7 @@ public final class JetContentBasedFileSubstitutor implements ContentBasedClassFi } @Override - public boolean isApplicable(@Nullable Project project, @NotNull final VirtualFile file) { + public boolean isApplicable(@Nullable final Project project, @NotNull final VirtualFile file) { if (project == null) { return false; } @@ -76,7 +76,7 @@ public final class JetContentBasedFileSubstitutor implements ContentBasedClassFi DumbService.getInstance(project).runWhenSmart(new Runnable() { @Override public void run() { - if (DecompiledUtils.isKotlinCompiledFile(file)) { + if (DecompiledUtils.isKotlinCompiledFile(project, file)) { FileDocumentManager docManager = FileDocumentManager.getInstance(); docManager.getDocument(file); // force getting document because it can be collected docManager.reloadFiles(file); @@ -86,13 +86,13 @@ public final class JetContentBasedFileSubstitutor implements ContentBasedClassFi return false; } - return DecompiledUtils.isKotlinCompiledFile(file); + return DecompiledUtils.isKotlinCompiledFile(project, file); } @NotNull @Override public String obtainFileText(Project project, VirtualFile file) { - if (file != null && DecompiledUtils.isKotlinCompiledFile(file)) { + if (file != null && DecompiledUtils.isKotlinCompiledFile(project, file)) { JetDecompiledData data = JetDecompiledData.getDecompiledData(file, project); deferredDocumentBinding.put(file, data.getFile()); diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java b/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java index 45d088a1ae7..f9f4fc72eb3 100644 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java @@ -25,6 +25,7 @@ import com.intellij.psi.stubs.PsiFileStub; import com.intellij.util.cls.ClsFormatException; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass; import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.PackageFragmentClassHeader; @@ -34,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.kotlin.header.PackageFragmentClassHeader; * in completion, go-to-class, etc. */ public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFactory { + @Nullable @Override public PsiFileStub buildFileStub(VirtualFile file, byte[] bytes) throws ClsFormatException { @@ -44,7 +46,8 @@ public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFac public boolean canBeProcessed(VirtualFile file, byte[] bytes) { if (file.getName().contains(PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-") && StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) { - return KotlinClassHeader.read(new VirtualFileKotlinClass(file)) instanceof PackageFragmentClassHeader; + KotlinJvmBinaryClass kotlinClass = new VirtualFileKotlinClass(file); + return KotlinClassHeader.read(kotlinClass) instanceof PackageFragmentClassHeader; } return false; } diff --git a/idea/src/org/jetbrains/jet/plugin/vfilefinder/KotlinClassFileIndex.java b/idea/src/org/jetbrains/jet/plugin/vfilefinder/KotlinClassFileIndex.java index 11854e86783..110e7f6aff0 100644 --- a/idea/src/org/jetbrains/jet/plugin/vfilefinder/KotlinClassFileIndex.java +++ b/idea/src/org/jetbrains/jet/plugin/vfilefinder/KotlinClassFileIndex.java @@ -22,7 +22,8 @@ import com.intellij.openapi.vfs.VirtualFile; import com.intellij.util.indexing.*; import com.intellij.util.io.KeyDescriptor; import org.jetbrains.annotations.NotNull; -import org.jetbrains.jet.lang.resolve.kotlin.VirtualFileKotlinClass; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinClassFinder; +import org.jetbrains.jet.lang.resolve.kotlin.KotlinJvmBinaryClass; import org.jetbrains.jet.lang.resolve.kotlin.header.IncompatibleAnnotationHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader; import org.jetbrains.jet.lang.resolve.name.FqName; @@ -75,7 +76,8 @@ public final class KotlinClassFileIndex extends ScalarIndexExtension { @Override public Map map(FileContent inputData) { try { - VirtualFileKotlinClass kotlinClass = new VirtualFileKotlinClass(inputData.getFile()); + KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(inputData.getProject()) + .createKotlinClass(inputData.getFile()); KotlinClassHeader header = KotlinClassHeader.read(kotlinClass); if (header != null && !(header instanceof IncompatibleAnnotationHeader)) { return Collections.singletonMap(kotlinClass.getClassName().getFqNameForClassNameWithoutDollars(), null);