diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java index ba1ce134746..fb7cda0acf1 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java @@ -34,7 +34,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.cli.common.messages.MessageCollector; import org.jetbrains.jet.compiler.runner.*; import org.jetbrains.jet.plugin.JetFileType; -import org.jetbrains.jet.plugin.project.JsModuleDetector; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; import java.io.File; import java.io.IOException; @@ -50,7 +50,7 @@ public class JetCompiler implements TranslatingCompiler { return false; } Module module = compileContext.getModuleByFile(virtualFile); - if (module != null && JsModuleDetector.isJsModule(module)) { + if (module != null && KotlinFrameworkDetector.isJsModule(module)) { return false; } return true; diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java index 1a24c284f61..43f7ca7d1eb 100644 --- a/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java +++ b/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java @@ -42,7 +42,7 @@ import org.jetbrains.jet.compiler.runner.CompilerEnvironment; import org.jetbrains.jet.compiler.runner.CompilerRunnerUtil; import org.jetbrains.jet.compiler.runner.OutputItemsCollectorImpl; import org.jetbrains.jet.plugin.JetFileType; -import org.jetbrains.jet.plugin.project.JsModuleDetector; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; import java.io.File; import java.io.PrintStream; @@ -63,7 +63,7 @@ public final class K2JSCompiler implements TranslatingCompiler { if (module == null) { return false; } - return JsModuleDetector.isJsModule(module); + return KotlinFrameworkDetector.isJsModule(module); } @Override @@ -178,7 +178,7 @@ public final class K2JSCompiler implements TranslatingCompiler { } private static void addLibLocationAndTarget(@NotNull Module module, @NotNull ArrayList args) { - Pair, String> libLocationAndTarget = JsModuleDetector.getLibLocationAndTargetForProject(module); + Pair, String> libLocationAndTarget = KotlinFrameworkDetector.getLibLocationAndTargetForProject(module); StringBuilder sb = StringBuilderSpinAllocator.alloc(); AccessToken token = ReadAction.start(); diff --git a/idea/src/org/jetbrains/jet/plugin/completion/JetTypesCompletionHelper.java b/idea/src/org/jetbrains/jet/plugin/completion/JetTypesCompletionHelper.java index ffd130746de..2a1536f3529 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/JetTypesCompletionHelper.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/JetTypesCompletionHelper.java @@ -28,8 +28,8 @@ import org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.plugin.caches.JetShortNamesCache; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; import org.jetbrains.jet.plugin.libraries.DecompiledDataFactory; -import org.jetbrains.jet.plugin.project.JsModuleDetector; public class JetTypesCompletionHelper { private JetTypesCompletionHelper() {} @@ -45,7 +45,7 @@ public class JetTypesCompletionHelper { jetCompletionResult.addAllElements(namesCache.getJetClassesDescriptors( jetCompletionResult.getShortNameFilter(), jetCompletionResult.getResolveSession())); - if (!JsModuleDetector.isJsModule((JetFile) parameters.getOriginalFile())) { + if (!KotlinFrameworkDetector.isJsModule((JetFile) parameters.getOriginalFile())) { addAdaptedJavaCompletion(parameters,jetCompletionResult); } } diff --git a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.java b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.java index 3c95830b35c..d737654b832 100644 --- a/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/completion/handlers/JetClassInsertHandler.java @@ -27,7 +27,7 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.plugin.completion.JetLookupObject; -import org.jetbrains.jet.plugin.project.JsModuleDetector; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; import org.jetbrains.jet.plugin.quickfix.ImportInsertHelper; public class JetClassInsertHandler implements InsertHandler { @@ -60,7 +60,7 @@ public class JetClassInsertHandler implements InsertHandler { if (targetElement != null) { ImportInsertHelper.addImportDirectiveOrChangeToFqName(fqn, jetFile, context.getStartOffset(), targetElement); } - else if (JsModuleDetector.isJsModule(jetFile)) { + else if (KotlinFrameworkDetector.isJsModule(jetFile)) { ImportInsertHelper.addImportDirective(fqn, jetFile); } } diff --git a/idea/src/org/jetbrains/jet/plugin/framework/KotlinFrameworkDetector.java b/idea/src/org/jetbrains/jet/plugin/framework/KotlinFrameworkDetector.java new file mode 100644 index 00000000000..d01a11aeee7 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/KotlinFrameworkDetector.java @@ -0,0 +1,113 @@ +package org.jetbrains.jet.plugin.framework; + +import com.intellij.ProjectTopics; +import com.intellij.openapi.application.*; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleUtilCore; +import com.intellij.openapi.progress.ProcessCanceledException; +import com.intellij.openapi.project.DumbService; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.*; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.util.Computable; +import com.intellij.openapi.util.Key; +import com.intellij.openapi.util.Pair; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.psi.util.CachedValue; +import com.intellij.psi.util.CachedValueProvider; +import com.intellij.psi.util.CachedValuesManager; +import com.intellij.psi.util.PsiModificationTracker; +import com.intellij.ui.EditorNotifications; +import com.intellij.util.Alarm; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.analyzer.AnalyzeExhaust; +import org.jetbrains.jet.lang.psi.JetFile; +import org.jetbrains.jet.plugin.util.ApplicationUtils; +import org.jetbrains.jet.plugin.versions.KotlinLibrariesNotificationProvider; +import org.jetbrains.jet.plugin.versions.KotlinRuntimeLibraryUtil; +import org.jetbrains.jet.utils.KotlinPathsFromHomeDir; +import org.jetbrains.jet.utils.PathUtil; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; + +public class KotlinFrameworkDetector { + private static final Key> IS_KOTLIN_JS_MODULE = Key.create("IS_KOTLIN_JS_MODULE"); + private static final Key> IS_KOTLIN_JAVA_MODULE = Key.create("IS_KOTLIN_JAVA_MODULE"); + + private KotlinFrameworkDetector() { + } + + public static boolean isJsModule(@NotNull JetFile file) { + Module module = ModuleUtilCore.findModuleForPsiElement(file); + return module != null && isJsModule(module); + } + + public static boolean isJavaModule(@NotNull final Module module) { + CachedValue result = module.getUserData(IS_KOTLIN_JAVA_MODULE); + if (result == null) { + result = CachedValuesManager.getManager(module.getProject()).createCachedValue(new CachedValueProvider() { + @Override + public Result compute() { + GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false); + return Result.create(KotlinRuntimeLibraryUtil.getKotlinRuntimeMarkerClass(scope) != null, + ProjectRootModificationTracker.getInstance(module.getProject())); + } + }, false); + + module.putUserData(IS_KOTLIN_JAVA_MODULE, result); + } + + return result.getValue(); + } + + private static Boolean checkModuleHasJavaScriptLibrary(final Module module) { + final Ref found = Ref.create(Boolean.FALSE); + + ApplicationManager.getApplication().runReadAction(new Runnable() { + @Override + public void run() { + ModuleRootManager.getInstance(module).orderEntries().librariesOnly().forEachLibrary(new Processor() { + @Override + public boolean process(Library library) { + String libraryName = library.getName(); + if (libraryName != null && libraryName.contains(PathUtil.JS_LIB_JAR_NAME)) { + found.set(Boolean.TRUE); + return false; + } + return true; + } + }); + } + }); + + return found.get(); + } + + public static boolean isJsModule(@NotNull final Module module) { + CachedValue result = module.getUserData(IS_KOTLIN_JS_MODULE); + if (result == null) { + result = CachedValuesManager.getManager(module.getProject()).createCachedValue(new CachedValueProvider() { + @Override + public Result compute() { + return Result.create(checkModuleHasJavaScriptLibrary(module), + ProjectRootModificationTracker.getInstance(module.getProject())); + } + }, false); + + module.putUserData(IS_KOTLIN_JS_MODULE, result); + } + + return result.getValue(); + } + + public static Pair, String> getLibLocationAndTargetForProject(Module module) { + return Pair., String>create(new ArrayList(), "ecma3"); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java index b6920d9d66e..fa4976fddb6 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java +++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java @@ -24,6 +24,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.analyzer.AnalyzerFacade; import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.resolve.java.AnalyzerFacadeForJVM; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; public final class AnalyzerFacadeProvider { @@ -54,7 +55,7 @@ public final class AnalyzerFacadeProvider { @NotNull private static AnalyzerFacade getAnalyzerFacadeForModule(@NotNull Module module) { - if (JsModuleDetector.isJsModule(module)) { + if (KotlinFrameworkDetector.isJsModule(module)) { return JSAnalyzerFacadeForIDEA.INSTANCE; } return AnalyzerFacadeForJVM.INSTANCE; diff --git a/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java b/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java index 600f3d39c47..167156417bc 100644 --- a/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java +++ b/idea/src/org/jetbrains/jet/plugin/project/IDEAConfig.java @@ -21,10 +21,10 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.k2js.config.EcmaVersion; import org.jetbrains.k2js.config.LibrarySourcesConfig; -import static org.jetbrains.jet.plugin.project.JsModuleDetector.getLibLocationAndTargetForProject; +import java.util.ArrayList; public final class IDEAConfig extends LibrarySourcesConfig { public IDEAConfig(@NotNull Project project) { - super(project, "default", getLibLocationAndTargetForProject(project).first, EcmaVersion.defaultVersion()); + super(project, "default", new ArrayList(), EcmaVersion.defaultVersion()); } } diff --git a/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java b/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java deleted file mode 100644 index 115db3d80e8..00000000000 --- a/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2010-2013 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.jet.plugin.project; - -import com.google.common.collect.Lists; -import com.intellij.openapi.module.Module; -import com.intellij.openapi.module.ModuleManager; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.ProjectRootManager; -import com.intellij.openapi.util.Pair; -import com.intellij.openapi.vfs.VirtualFile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.psi.JetFile; - -import java.util.List; - -/** - * This class has utility functions to determine whether the project (or module) is js project. - */ -public final class JsModuleDetector { - private JsModuleDetector() { - } - - public static boolean isJsModule(@NotNull Module module) { - // TODO: fix - return false; - } - - public static boolean isJsModule(@NotNull JetFile file) { - VirtualFile virtualFile = file.getOriginalFile().getVirtualFile(); - if (virtualFile != null) { - Module module = ProjectRootManager.getInstance(file.getProject()).getFileIndex().getModuleForFile(virtualFile); - if (module != null) { - return isJsModule(module); - } - } - - return false; - } - - @NotNull - public static Pair, String> getLibLocationAndTargetForProject(@NotNull Project project) { - Module module = getJSModule(project); - if (module == null) { - return Pair.empty(); - } - else { - return getLibLocationAndTargetForProject(module); - } - } - - @NotNull - public static Pair, String> getLibLocationAndTargetForProject(@NotNull Module module) { - throw new IllegalStateException("Under construction"); - //K2JSModuleComponent jsModuleComponent = K2JSModuleComponent.getInstance(module); - //String pathToJavaScriptLibrary = jsModuleComponent.getPathToJavaScriptLibrary(); - //String basePath = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath(); - //List pathsToJSLib = Lists.newArrayList(); - //if (pathToJavaScriptLibrary != null) { - // pathsToJSLib.add(basePath + pathToJavaScriptLibrary); - //} - //return Pair.create(pathsToJSLib, jsModuleComponent.getEcmaVersion().toString()); - } - - @Nullable - private static Module getJSModule(@NotNull Project project) { - Module[] modules = ModuleManager.getInstance(project).getModules(); - for (Module module : modules) { - if (isJsModule(module)) { - return module; - } - } - return null; - } -} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java index 5a1b96a3d5a..6e954d20056 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ImportClassAndFunFix.java @@ -52,7 +52,7 @@ import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.plugin.JetBundle; import org.jetbrains.jet.plugin.actions.JetAddImportAction; import org.jetbrains.jet.plugin.caches.JetShortNamesCache; -import org.jetbrains.jet.plugin.project.JsModuleDetector; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import org.jetbrains.jet.plugin.util.JetPsiHeuristicsUtil; @@ -162,7 +162,7 @@ public class ImportClassAndFunFix extends JetHintAction public static Collection getClassNames(@NotNull String referenceName, @NotNull JetFile file, @NotNull KotlinCodeAnalyzer analyzer) { Set possibleResolveNames = Sets.newHashSet(); - if (!JsModuleDetector.isJsModule(file)) { + if (!KotlinFrameworkDetector.isJsModule(file)) { possibleResolveNames.addAll(getClassesFromCache(referenceName, file)); } else { @@ -199,7 +199,7 @@ public class ImportClassAndFunFix extends JetHintAction } private static PsiShortNamesCache getShortNamesCache(@NotNull JetFile jetFile) { - if (JsModuleDetector.isJsModule(jetFile)) { + if (KotlinFrameworkDetector.isJsModule(jetFile)) { return JetShortNamesCache.getKotlinInstance(jetFile.getProject()); } diff --git a/idea/src/org/jetbrains/jet/plugin/run/JetRunConfigurationProducer.java b/idea/src/org/jetbrains/jet/plugin/run/JetRunConfigurationProducer.java index 0c9273f2b07..fb98345074a 100644 --- a/idea/src/org/jetbrains/jet/plugin/run/JetRunConfigurationProducer.java +++ b/idea/src/org/jetbrains/jet/plugin/run/JetRunConfigurationProducer.java @@ -31,9 +31,8 @@ import org.jetbrains.jet.lang.psi.JetFile; import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.name.FqName; -import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.plugin.JetMainDetector; -import org.jetbrains.jet.plugin.project.JsModuleDetector; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; public class JetRunConfigurationProducer extends RuntimeConfigurationProducer implements Cloneable { @Nullable @@ -56,7 +55,7 @@ public class JetRunConfigurationProducer extends RuntimeConfigurationProducer im return null; } - if (JsModuleDetector.isJsModule(module)) { + if (KotlinFrameworkDetector.isJsModule(module)) { return null; } diff --git a/idea/src/org/jetbrains/jet/plugin/versions/KotlinRuntimeLibraryUtil.java b/idea/src/org/jetbrains/jet/plugin/versions/KotlinRuntimeLibraryUtil.java index 32482a4437e..9e1bef61389 100644 --- a/idea/src/org/jetbrains/jet/plugin/versions/KotlinRuntimeLibraryUtil.java +++ b/idea/src/org/jetbrains/jet/plugin/versions/KotlinRuntimeLibraryUtil.java @@ -20,7 +20,6 @@ import com.google.common.base.Predicate; import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import com.google.common.collect.Sets; -import com.intellij.facet.impl.DefaultFacetsProvider; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.project.Project; @@ -28,10 +27,7 @@ import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.projectRoots.SdkModificator; import com.intellij.openapi.roots.AnnotationOrderRootType; import com.intellij.openapi.roots.ModuleRootManager; -import com.intellij.openapi.roots.OrderRootType; import com.intellij.openapi.roots.ProjectFileIndex; -import com.intellij.openapi.roots.libraries.Library; -import com.intellij.openapi.roots.libraries.LibraryTable; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.io.FileUtil; import com.intellij.openapi.vfs.JarFileSystem; @@ -46,13 +42,13 @@ import com.intellij.util.Processor; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.indexing.FileBasedIndex; import com.intellij.util.indexing.ID; -import com.intellij.util.text.UniqueNameGenerator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; import org.jetbrains.jet.utils.PathUtil; import java.io.File; @@ -62,8 +58,6 @@ import java.util.Set; import java.util.jar.Attributes; import java.util.jar.JarFile; -import static org.jetbrains.jet.plugin.project.JsModuleDetector.isJsModule; - public class KotlinRuntimeLibraryUtil { public static final String LIBRARY_NAME = "KotlinRuntime"; public static final String KOTLIN_RUNTIME_JAR = "kotlin-runtime.jar"; @@ -138,7 +132,7 @@ public class KotlinRuntimeLibraryUtil { } public static boolean isModuleAlreadyConfigured(Module module) { - return isMavenModule(module) || isJsModule(module) || isWithJavaModule(module); + return isMavenModule(module) || KotlinFrameworkDetector.isJsModule(module) || KotlinFrameworkDetector.isJavaModule(module); } private static boolean isMavenModule(@NotNull Module module) { @@ -147,15 +141,8 @@ public class KotlinRuntimeLibraryUtil { return "true".equals(module.getOptionValue("org.jetbrains.idea.maven.project.MavenProjectsManager.isMavenModule")); } - private static boolean isWithJavaModule(Module module) { - // Can find a reference to kotlin class in module scope - GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false); - - return getKotlinRuntimeMarkerClass(scope) != null; - } - @Nullable - private static PsiClass getKotlinRuntimeMarkerClass(@NotNull GlobalSearchScope scope) { + public static PsiClass getKotlinRuntimeMarkerClass(@NotNull GlobalSearchScope scope) { FqName kotlinPackageFqName = FqName.topLevel(Name.identifier("kotlin")); String kotlinPackageClassFqName = PackageClassUtils.getPackageClassFqName(kotlinPackageFqName).getFqName(); @@ -176,29 +163,6 @@ public class KotlinRuntimeLibraryUtil { return null; } - public static boolean isLibraryCanBeUsedAsJavaRuntime(@Nullable Library library) { - if (library == null) { - return false; - } - - for (VirtualFile root : library.getFiles(OrderRootType.CLASSES)) { - if (root.getName().equals(KOTLIN_RUNTIME_JAR)) { - return true; - } - } - - return false; - } - - private static String getUniqueLibraryName(final String baseName, final LibraryTable.ModifiableModel model) { - return UniqueNameGenerator.generateUniqueName(baseName, "", "", " (", ")", new Condition() { - @Override - public boolean value(String s) { - return model.getLibraryByName(s) == null; - } - }); - } - public static void updateRuntime( @NotNull final Project project, @NotNull final Runnable jarNotFoundHandler