From 52de4215b527cb6a692b26d3075dd978a0c58c00 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Tue, 23 Jul 2013 21:34:34 +0400 Subject: [PATCH] Introduce VirtualFileFinder interface Provide different implementations in Cli and Ide --- .../cli/jvm/compiler/JetCoreEnvironment.java | 11 ++- .../jet/cli/jvm/compiler/ClassPath.java | 23 ++++++ .../vfilefinder/CliVirtualFileFinder.java | 72 +++++++++++++++++++ .../java/vfilefinder/VirtualFileFinder.java | 17 +++++ idea/src/META-INF/plugin.xml | 3 + .../vfilefinder/IDEVirtualFileFinder.java | 43 +++++++++++ 6 files changed, 167 insertions(+), 2 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/cli/jvm/compiler/ClassPath.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/vfilefinder/CliVirtualFileFinder.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/vfilefinder/VirtualFileFinder.java create mode 100644 idea/src/org/jetbrains/jet/plugin/vfilefinder/IDEVirtualFileFinder.java diff --git a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/JetCoreEnvironment.java b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/JetCoreEnvironment.java index ab57dfb4a0f..318d9686172 100644 --- a/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/JetCoreEnvironment.java +++ b/compiler/cli/src/org/jetbrains/jet/cli/jvm/compiler/JetCoreEnvironment.java @@ -51,7 +51,8 @@ import org.jetbrains.jet.lang.parsing.JetParserDefinition; import org.jetbrains.jet.lang.parsing.JetScriptDefinitionProvider; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.java.JetFilesProvider; -import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; +import org.jetbrains.jet.lang.resolve.java.vfilefinder.CliVirtualFileFinder; +import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder; import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.utils.PathUtil; @@ -67,6 +68,7 @@ public class JetCoreEnvironment { private final JavaCoreApplicationEnvironment applicationEnvironment; private final JavaCoreProjectEnvironment projectEnvironment; private final List sourceFiles = new ArrayList(); + private final ClassPath classPath = new ClassPath(); private final CoreExternalAnnotationsManager annotationsManager; @@ -123,7 +125,10 @@ public class JetCoreEnvironment { addSources(path); } - JetScriptDefinitionProvider.getInstance(project).addScriptDefinitions(configuration.getList(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY)); + JetScriptDefinitionProvider.getInstance(project).addScriptDefinitions( + configuration.getList(CommonConfigurationKeys.SCRIPT_DEFINITIONS_KEY)); + + project.registerService(VirtualFileFinder.class, new CliVirtualFileFinder(classPath)); } public CompilerConfiguration getConfiguration() { @@ -194,6 +199,7 @@ public class JetCoreEnvironment { return; } projectEnvironment.addJarToClassPath(path); + classPath.add(jarFile); } else { VirtualFile root = applicationEnvironment.getLocalFileSystem().findFileByPath(path.getAbsolutePath()); @@ -202,6 +208,7 @@ public class JetCoreEnvironment { return; } projectEnvironment.addSourcesToClasspath(root); + classPath.add(root); } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/cli/jvm/compiler/ClassPath.java b/compiler/frontend.java/src/org/jetbrains/jet/cli/jvm/compiler/ClassPath.java new file mode 100644 index 00000000000..0864f2aaeec --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/cli/jvm/compiler/ClassPath.java @@ -0,0 +1,23 @@ +package org.jetbrains.jet.cli.jvm.compiler; + +import com.intellij.openapi.vfs.VirtualFile; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public final class ClassPath implements Iterable { + + @NotNull + private final List roots = new ArrayList(); + + @Override + public Iterator iterator() { + return roots.iterator(); + } + + public void add(@NotNull VirtualFile root) { + roots.add(root); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/vfilefinder/CliVirtualFileFinder.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/vfilefinder/CliVirtualFileFinder.java new file mode 100644 index 00000000000..08d00f88c5e --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/vfilefinder/CliVirtualFileFinder.java @@ -0,0 +1,72 @@ +package org.jetbrains.jet.lang.resolve.java.vfilefinder; + +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.cli.jvm.compiler.ClassPath; +import org.jetbrains.jet.lang.resolve.java.resolver.KotlinClassFileHeader; +import org.jetbrains.jet.lang.resolve.name.FqName; + +public class CliVirtualFileFinder implements VirtualFileFinder { + + @NotNull + private final ClassPath classPath; + + public CliVirtualFileFinder(@NotNull ClassPath path) { + classPath = path; + } + + + @Nullable + @Override + public VirtualFile find(@NotNull FqName className, @NotNull GlobalSearchScope scope) { + //TODO: use scope + return find(className); + } + + @Nullable + @Override + public VirtualFile find(@NotNull FqName className) { + for (VirtualFile root : classPath) { + VirtualFile fileInRoot = findFileInRoot(className.asString(), root); + if (fileInRoot != null) { + return fileInRoot; + } + } + return null; + } + + //NOTE: copied with some changes from CoreJavaFileManager + @Nullable + private static VirtualFile findFileInRoot(@NotNull String qName, @NotNull VirtualFile root) { + String pathRest = qName; + VirtualFile cur = root; + + while (true) { + int dot = pathRest.indexOf('.'); + if (dot < 0) break; + + String pathComponent = pathRest.substring(0, dot); + VirtualFile child = cur.findChild(pathComponent); + + if (child == null) break; + pathRest = pathRest.substring(dot + 1); + cur = child; + } + + String className = pathRest.replace('.', '$'); + VirtualFile vFile = cur.findChild(className + ".class"); + if (vFile != null) { + if (!vFile.isValid()) { + //TODO: log + return null; + } + //NOTE: currently we use VirtualFileFinder to find Kotlin binaries only + if (KotlinClassFileHeader.readKotlinHeaderFromClassFile(vFile).getType() != KotlinClassFileHeader.HeaderType.NONE) { + return vFile; + } + } + return null; + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/vfilefinder/VirtualFileFinder.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/vfilefinder/VirtualFileFinder.java new file mode 100644 index 00000000000..cfea6e00d24 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/vfilefinder/VirtualFileFinder.java @@ -0,0 +1,17 @@ +package org.jetbrains.jet.lang.resolve.java.vfilefinder; + +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.name.FqName; + +public interface VirtualFileFinder { + + @Nullable + VirtualFile find(@NotNull FqName className, @NotNull GlobalSearchScope scope); + //NOTE: uses all scope by default + //TODO: should be removed, scope should always be passed + @Nullable + VirtualFile find(@NotNull FqName className); +} diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 091439bdeef..25197088b5a 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -88,6 +88,9 @@ + + diff --git a/idea/src/org/jetbrains/jet/plugin/vfilefinder/IDEVirtualFileFinder.java b/idea/src/org/jetbrains/jet/plugin/vfilefinder/IDEVirtualFileFinder.java new file mode 100644 index 00000000000..4230959252d --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/vfilefinder/IDEVirtualFileFinder.java @@ -0,0 +1,43 @@ +package org.jetbrains.jet.plugin.vfilefinder; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.indexing.FileBasedIndex; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.vfilefinder.VirtualFileFinder; +import org.jetbrains.jet.lang.resolve.name.FqName; + +import java.util.Collection; + +public final class IDEVirtualFileFinder implements VirtualFileFinder { + + private static final Logger LOG = Logger.getInstance(IDEVirtualFileFinder.class); + + @NotNull private final Project project; + + public IDEVirtualFileFinder(@NotNull Project project) { + this.project = project; + } + + @Nullable + @Override + public VirtualFile find(@NotNull FqName className, @NotNull GlobalSearchScope scope) { + Collection files = FileBasedIndex.getInstance().getContainingFiles(KotlinClassFileIndex.KEY, className, scope); + if (files.isEmpty()) { + return null; + } + if (files.size() > 1) { + LOG.warn("There are " + files.size() + " classes with same fqName: " + className + " found."); + } + return files.iterator().next(); + } + + @Nullable + @Override + public VirtualFile find(@NotNull FqName className) { + return find(className, GlobalSearchScope.allScope(project)); + } +}