Direct instantiations of VirtualFileKotlinClass are replaced by access to caching service

This commit is contained in:
Andrey Breslav
2014-01-07 13:03:51 +04:00
parent 6c1f579c6d
commit 7fc9772930
10 changed files with 61 additions and 17 deletions
@@ -46,7 +46,7 @@ public class CliVirtualFileFinder extends VirtualFileKotlinClassFinder implement
//NOTE: copied with some changes from CoreJavaFileManager //NOTE: copied with some changes from CoreJavaFileManager
@Nullable @Nullable
private static VirtualFile findFileInRoot(@NotNull String qName, @NotNull VirtualFile root) { private VirtualFile findFileInRoot(@NotNull String qName, @NotNull VirtualFile root) {
String pathRest = qName; String pathRest = qName;
VirtualFile cur = root; VirtualFile cur = root;
@@ -70,7 +70,7 @@ public class CliVirtualFileFinder extends VirtualFileKotlinClassFinder implement
return null; return null;
} }
//NOTE: currently we use VirtualFileFinder to find Kotlin binaries only //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; return vFile;
} }
} }
@@ -17,16 +17,34 @@
package org.jetbrains.jet.lang.resolve.kotlin; package org.jetbrains.jet.lang.resolve.kotlin;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.SLRUCache;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
public abstract class VirtualFileKotlinClassFinder implements VirtualFileFinder { 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<VirtualFile, KotlinJvmBinaryClass> cache = new SLRUCache<VirtualFile, KotlinJvmBinaryClass>(2, 2) {
@NotNull
@Override
public KotlinJvmBinaryClass createValue(VirtualFile virtualFile) {
return new VirtualFileKotlinClass(virtualFile);
}
};
@Nullable @Nullable
@Override @Override
public KotlinJvmBinaryClass findKotlinClass(@NotNull FqName fqName) { public KotlinJvmBinaryClass findKotlinClass(@NotNull FqName fqName) {
VirtualFile file = findVirtualFile(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);
}
} }
} }
@@ -16,11 +16,25 @@
package org.jetbrains.jet.lang.resolve.kotlin; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
public interface KotlinClassFinder { public interface KotlinClassFinder {
class SERVICE {
@NotNull
public static KotlinClassFinder getInstance(@NotNull Project project) {
return ServiceManager.getService(project, KotlinClassFinder.class);
}
}
@Nullable @Nullable
KotlinJvmBinaryClass findKotlinClass(@NotNull FqName fqName); KotlinJvmBinaryClass findKotlinClass(@NotNull FqName fqName);
@NotNull
KotlinJvmBinaryClass createKotlinClass(@NotNull VirtualFile virtualFile);
} }
@@ -29,6 +29,8 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.descriptors.serialization.*; import org.jetbrains.jet.descriptors.serialization.*;
import org.jetbrains.jet.lang.descriptors.ClassKind; import org.jetbrains.jet.lang.descriptors.ClassKind;
import org.jetbrains.jet.lang.resolve.java.JavaResolverPsiUtils; 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.VirtualFileKotlinClass;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader;
@@ -117,7 +119,8 @@ public class JetFromJavaDescriptorHelper {
private static String[] getAnnotationDataForKotlinClass(@NotNull PsiClass psiClass) { private static String[] getAnnotationDataForKotlinClass(@NotNull PsiClass psiClass) {
VirtualFile virtualFile = getVirtualFileForPsiClass(psiClass); VirtualFile virtualFile = getVirtualFileForPsiClass(psiClass);
if (virtualFile != null) { 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) { if (header instanceof SerializedDataHeader) {
return ((SerializedDataHeader) header).getAnnotationData(); return ((SerializedDataHeader) header).getAnnotationData();
} }
@@ -28,7 +28,8 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.BindingTraceContext;
import org.jetbrains.jet.lang.resolve.MemberComparator; import org.jetbrains.jet.lang.resolve.MemberComparator;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver; 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.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -67,7 +68,7 @@ public final class DecompiledDataFactory {
InjectorForJavaDescriptorResolver injector = InjectorForJavaDescriptorResolverUtil.create(project, new BindingTraceContext()); InjectorForJavaDescriptorResolver injector = InjectorForJavaDescriptorResolverUtil.create(project, new BindingTraceContext());
this.javaDescriptorResolver = injector.getJavaDescriptorResolver(); this.javaDescriptorResolver = injector.getJavaDescriptorResolver();
VirtualFileKotlinClass kotlinClass = new VirtualFileKotlinClass(classFile); KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(project).createKotlinClass(classFile);
this.classFqName = kotlinClass.getClassName().getFqNameForClassNameWithoutDollars(); this.classFqName = kotlinClass.getClassName().getFqNameForClassNameWithoutDollars();
KotlinClassHeader header = KotlinClassHeader.read(kotlinClass); KotlinClassHeader header = KotlinClassHeader.read(kotlinClass);
@@ -58,7 +58,7 @@ public final class DecompiledNavigationUtils {
DeclarationDescriptor effectiveReferencedDescriptor = getEffectiveReferencedDescriptor(referencedDescriptor); DeclarationDescriptor effectiveReferencedDescriptor = getEffectiveReferencedDescriptor(referencedDescriptor);
VirtualFile virtualFile = findVirtualFileContainingDescriptor(project, effectiveReferencedDescriptor); 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); JetDecompiledData data = JetDecompiledData.getDecompiledData(virtualFile, project);
JetDeclaration jetDeclaration = data.getDeclarationForDescriptor(effectiveReferencedDescriptor); JetDeclaration jetDeclaration = data.getDeclarationForDescriptor(effectiveReferencedDescriptor);
@@ -17,20 +17,23 @@
package org.jetbrains.jet.plugin.libraries; package org.jetbrains.jet.plugin.libraries;
import com.intellij.openapi.fileTypes.StdFileTypes; import com.intellij.openapi.fileTypes.StdFileTypes;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull; 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.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.SerializedDataHeader;
public final class DecompiledUtils { 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())) { if (!StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) {
return false; return false;
} }
//TODO: check index //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() { private DecompiledUtils() {
@@ -67,7 +67,7 @@ public final class JetContentBasedFileSubstitutor implements ContentBasedClassFi
} }
@Override @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) { if (project == null) {
return false; return false;
} }
@@ -76,7 +76,7 @@ public final class JetContentBasedFileSubstitutor implements ContentBasedClassFi
DumbService.getInstance(project).runWhenSmart(new Runnable() { DumbService.getInstance(project).runWhenSmart(new Runnable() {
@Override @Override
public void run() { public void run() {
if (DecompiledUtils.isKotlinCompiledFile(file)) { if (DecompiledUtils.isKotlinCompiledFile(project, file)) {
FileDocumentManager docManager = FileDocumentManager.getInstance(); FileDocumentManager docManager = FileDocumentManager.getInstance();
docManager.getDocument(file); // force getting document because it can be collected docManager.getDocument(file); // force getting document because it can be collected
docManager.reloadFiles(file); docManager.reloadFiles(file);
@@ -86,13 +86,13 @@ public final class JetContentBasedFileSubstitutor implements ContentBasedClassFi
return false; return false;
} }
return DecompiledUtils.isKotlinCompiledFile(file); return DecompiledUtils.isKotlinCompiledFile(project, file);
} }
@NotNull @NotNull
@Override @Override
public String obtainFileText(Project project, VirtualFile file) { 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); JetDecompiledData data = JetDecompiledData.getDecompiledData(file, project);
deferredDocumentBinding.put(file, data.getFile()); deferredDocumentBinding.put(file, data.getFile());
@@ -25,6 +25,7 @@ import com.intellij.psi.stubs.PsiFileStub;
import com.intellij.util.cls.ClsFormatException; import com.intellij.util.cls.ClsFormatException;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; 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.VirtualFileKotlinClass;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.kotlin.header.PackageFragmentClassHeader; 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. * in completion, go-to-class, etc.
*/ */
public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFactory<PsiJavaFile> { public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFactory<PsiJavaFile> {
@Nullable @Nullable
@Override @Override
public PsiFileStub<PsiJavaFile> buildFileStub(VirtualFile file, byte[] bytes) throws ClsFormatException { public PsiFileStub<PsiJavaFile> buildFileStub(VirtualFile file, byte[] bytes) throws ClsFormatException {
@@ -44,7 +46,8 @@ public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFac
public boolean canBeProcessed(VirtualFile file, byte[] bytes) { public boolean canBeProcessed(VirtualFile file, byte[] bytes) {
if (file.getName().contains(PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-") && if (file.getName().contains(PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-") &&
StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) { 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; return false;
} }
@@ -22,7 +22,8 @@ import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.indexing.*; import com.intellij.util.indexing.*;
import com.intellij.util.io.KeyDescriptor; import com.intellij.util.io.KeyDescriptor;
import org.jetbrains.annotations.NotNull; 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.IncompatibleAnnotationHeader;
import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader; import org.jetbrains.jet.lang.resolve.kotlin.header.KotlinClassHeader;
import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqName;
@@ -75,7 +76,8 @@ public final class KotlinClassFileIndex extends ScalarIndexExtension<FqName> {
@Override @Override
public Map<FqName, Void> map(FileContent inputData) { public Map<FqName, Void> map(FileContent inputData) {
try { try {
VirtualFileKotlinClass kotlinClass = new VirtualFileKotlinClass(inputData.getFile()); KotlinJvmBinaryClass kotlinClass = KotlinClassFinder.SERVICE.getInstance(inputData.getProject())
.createKotlinClass(inputData.getFile());
KotlinClassHeader header = KotlinClassHeader.read(kotlinClass); KotlinClassHeader header = KotlinClassHeader.read(kotlinClass);
if (header != null && !(header instanceof IncompatibleAnnotationHeader)) { if (header != null && !(header instanceof IncompatibleAnnotationHeader)) {
return Collections.singletonMap(kotlinClass.getClassName().getFqNameForClassNameWithoutDollars(), null); return Collections.singletonMap(kotlinClass.getClassName().getFqNameForClassNameWithoutDollars(), null);