diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml
index 00df0658049..a7049fcc191 100644
--- a/idea/src/META-INF/plugin.xml
+++ b/idea/src/META-INF/plugin.xml
@@ -29,6 +29,12 @@
+
+
+ org.jetbrains.jet.plugin.project.K2JSModuleComponent
+
+
+
diff --git a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java
index c66cdc96710..0b6e3213ad5 100644
--- a/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java
+++ b/idea/src/org/jetbrains/jet/plugin/compiler/JetCompiler.java
@@ -26,7 +26,6 @@ import com.intellij.openapi.compiler.CompileScope;
import com.intellij.openapi.compiler.TranslatingCompiler;
import com.intellij.openapi.compiler.ex.CompileContextEx;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.JdkUtil;
import com.intellij.openapi.projectRoots.Sdk;
@@ -61,8 +60,8 @@ public class JetCompiler implements TranslatingCompiler {
if (!(virtualFile.getFileType() instanceof JetFileType)) {
return false;
}
- Project project = compileContext.getProject();
- if (project != null && JsModuleDetector.isJsProject(project)) {
+ Module module = compileContext.getModuleByFile(virtualFile);
+ if (module != null && JsModuleDetector.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 dc8589e46fe..20b7f6831f6 100644
--- a/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java
+++ b/idea/src/org/jetbrains/jet/plugin/compiler/K2JSCompiler.java
@@ -51,11 +51,11 @@ public final class K2JSCompiler implements TranslatingCompiler {
if (!(file.getFileType() instanceof JetFileType)) {
return false;
}
- Project project = context.getProject();
- if (project == null) {
+ Module module = context.getModuleByFile(file);
+ if (module == null) {
return false;
}
- return JsModuleDetector.isJsProject(project);
+ return JsModuleDetector.isJsModule(module);
}
@Override
@@ -142,14 +142,14 @@ public final class K2JSCompiler implements TranslatingCompiler {
}
private static void addLibLocationAndTarget(@NotNull Project project, @NotNull ArrayList args) {
- Pair data = JsModuleDetector.getLibLocationAndTargetForProject(project);
- if (data.first != null) {
+ Pair libLocationAndTarget = JsModuleDetector.getLibLocationAndTargetForProject(project);
+ if (libLocationAndTarget.first != null) {
args.add("-libzip");
- args.add(data.first);
+ args.add(libLocationAndTarget.first);
}
- if (data.second != null) {
+ if (libLocationAndTarget.second != null) {
args.add("-target");
- args.add(data.second);
+ args.add(libLocationAndTarget.second);
}
}
diff --git a/idea/src/org/jetbrains/jet/plugin/k2jsrun/K2JSRunnerUtils.java b/idea/src/org/jetbrains/jet/plugin/k2jsrun/K2JSRunnerUtils.java
index b0b73a5dfdc..65ff421aa7b 100644
--- a/idea/src/org/jetbrains/jet/plugin/k2jsrun/K2JSRunnerUtils.java
+++ b/idea/src/org/jetbrains/jet/plugin/k2jsrun/K2JSRunnerUtils.java
@@ -69,6 +69,7 @@ public final class K2JSRunnerUtils {
@NotNull
public static Module getJsModule(@NotNull Project project) {
+ //TODO Should not be there, we should know what module we are in
Module[] modules = ModuleManager.getInstance(project).getModules();
if (modules.length != 1) {
throw new UnsupportedOperationException("Kotlin to JavaScript translator temporarily does not support multiple modules.");
diff --git a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java
index 5173e6d91c7..f89015e9dd7 100644
--- a/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java
+++ b/idea/src/org/jetbrains/jet/plugin/libraries/JetSourceNavigationHelper.java
@@ -71,7 +71,7 @@ public class JetSourceNavigationHelper {
}
final Project project = declaration.getProject();
final List libraryFiles = findAllSourceFilesWhichContainIdentifier(declaration);
- BindingContext bindingContext = AnalyzerFacadeProvider.getAnalyzerFacadeForProject(project).analyzeFiles(
+ BindingContext bindingContext = AnalyzerFacadeProvider.getAnalyzerFacadeForProject().analyzeFiles(
project,
libraryFiles,
Collections.emptyList(),
diff --git a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java
index 84ec04b4ce5..4d75740f9a2 100644
--- a/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java
+++ b/idea/src/org/jetbrains/jet/plugin/project/AnalyzerFacadeProvider.java
@@ -16,31 +16,64 @@
package org.jetbrains.jet.plugin.project;
-import com.intellij.openapi.project.Project;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.roots.ProjectFileIndex;
+import com.intellij.openapi.vfs.VirtualFile;
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.k2js.analyze.AnalyzerFacadeForJS;
/**
* @author Pavel Talanov
*/
public final class AnalyzerFacadeProvider {
+ private final static Logger LOG = Logger.getInstance(AnalyzerFacade.class);
+
private AnalyzerFacadeProvider() {
}
@NotNull
public static AnalyzerFacade getAnalyzerFacadeForFile(@NotNull JetFile file) {
- return getAnalyzerFacadeForProject(file.getProject());
+ VirtualFile virtualFile = file.getVirtualFile();
+ if (virtualFile == null) {
+ logErrorIfNotTests("No virtual file for " + file.getName() + " with text:\n" + file.getText());
+ return getDefaultAnalyzerFacade();
+ }
+ Module moduleForFile = ProjectFileIndex.SERVICE.getInstance(file.getProject()).getModuleForFile(virtualFile);
+ if (moduleForFile == null) {
+ logErrorIfNotTests("File " + virtualFile.getPath() + " is not under any module. Cannot determine which facade to use.");
+ return getDefaultAnalyzerFacade();
+ }
+ return getAnalyzerFacadeForModule(moduleForFile);
+ }
+
+ private static void logErrorIfNotTests(@NotNull String message) {
+ if (!ApplicationManager.getApplication().isUnitTestMode()) {
+ LOG.error(message);
+ }
}
@NotNull
- public static AnalyzerFacade getAnalyzerFacadeForProject(@NotNull Project project) {
- if (JsModuleDetector.isJsProject(project)) {
+ private static AnalyzerFacade getDefaultAnalyzerFacade() {
+ LOG.info("Using default analyzer facade");
+ return AnalyzerFacadeForJVM.INSTANCE;
+ }
+
+ @NotNull
+ private static AnalyzerFacade getAnalyzerFacadeForModule(@NotNull Module module) {
+ if (JsModuleDetector.isJsModule(module)) {
return JSAnalyzerFacadeForIDEA.INSTANCE;
}
return AnalyzerFacadeForJVM.INSTANCE;
}
+
+ //TODO should remove all calls to this method
+ @NotNull
+ public static AnalyzerFacade getAnalyzerFacadeForProject() {
+ return AnalyzerFacadeForJVM.INSTANCE;
+ }
}
diff --git a/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java b/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java
index dbf3e862692..7cf1ce91429 100644
--- a/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java
+++ b/idea/src/org/jetbrains/jet/plugin/project/JsModuleDetector.java
@@ -16,77 +16,47 @@
package org.jetbrains.jet.plugin.project;
-import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.roots.ProjectRootManager;
+import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.Pair;
-import com.intellij.openapi.util.io.FileUtil;
-import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.io.IOException;
-import java.io.InputStream;
-
/**
* @author Pavel Talanov
*
* This class has utility functions to determine whether the project (or module) is js project.
*/
public final class JsModuleDetector {
-
- public static final String INDICATION_FILE_NAME = ".kotlin-js";
-
private JsModuleDetector() {
}
- public static boolean isJsProject(@NotNull Project project) {
- return findIndicationFileInContentRoots(project) != null;
+ public static boolean isJsModule(@NotNull Module module) {
+ return K2JSModuleComponent.getInstance(module).isJavaScriptModule();
+ }
+
+ @NotNull
+ public static Pair getLibLocationAndTargetForProject(@NotNull Project project) {
+ Module module = getJSModule(project);
+ if (module == null) {
+ return Pair.empty();
+ }
+ K2JSModuleComponent jsModuleComponent = K2JSModuleComponent.getInstance(module);
+ String pathToJavaScriptLibrary = jsModuleComponent.getPathToJavaScriptLibrary();
+ String basePath = ModuleRootManager.getInstance(module).getContentRoots()[0].getPath();
+ return Pair.create(basePath + pathToJavaScriptLibrary, jsModuleComponent.getEcmaVersion().toString());
}
@Nullable
- public static VirtualFile findIndicationFileInContentRoots(@NotNull Project project) {
- VirtualFile[] roots = ProjectRootManager.getInstance(project).getContentRoots();
- for (VirtualFile root : roots) {
- for (VirtualFile child : root.getChildren()) {
- if (child.getName().equals(INDICATION_FILE_NAME)) {
- return child;
- }
+ private static Module getJSModule(@NotNull Project project) {
+ Module[] modules = ModuleManager.getInstance(project).getModules();
+ for (Module module : modules) {
+ if (isJsModule(module)) {
+ return module;
}
}
return null;
}
-
- //TODO: refactor
- @NotNull
- public static Pair getLibLocationAndTargetForProject(@NotNull Project project) {
- VirtualFile indicationFile = findIndicationFileInContentRoots(project);
- Logger logger = Logger.getInstance(JsModuleDetector.class);
- if (indicationFile == null) {
- logger.error("Indication file not found for project " + project.getName());
- return Pair.empty();
- }
-
- try {
- InputStream stream = indicationFile.getInputStream();
- String text = FileUtil.loadTextAndClose(stream);
- if (text.isEmpty()) {
- logger.error("Indication file is corrupted for project " + project.getName());
- return Pair.empty();
- }
- String[] lines = text.split("\n");
- if (lines.length == 0) {
- logger.error("Indication file " + indicationFile.getPath() + "is empty");
- return Pair.empty();
- }
- String pathToLibFile = lines[0];
- String version = lines.length >= 2 ? lines[1] : null;
- String pathToIndicationFileLocation = indicationFile.getParent().getPath();
- return new Pair(pathToIndicationFileLocation + "/" + pathToLibFile, version);
- }
- catch (IOException e) {
- logger.error("Could not open file " + indicationFile.getPath());
- return Pair.empty();
- }
- }
}
diff --git a/idea/src/org/jetbrains/jet/plugin/project/K2JSModuleComponent.java b/idea/src/org/jetbrains/jet/plugin/project/K2JSModuleComponent.java
new file mode 100644
index 00000000000..1ef482548c6
--- /dev/null
+++ b/idea/src/org/jetbrains/jet/plugin/project/K2JSModuleComponent.java
@@ -0,0 +1,127 @@
+/*
+ * Copyright 2010-2012 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.intellij.openapi.components.PersistentStateComponent;
+import com.intellij.openapi.components.State;
+import com.intellij.openapi.components.Storage;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleComponent;
+import com.intellij.openapi.roots.impl.storage.ClasspathStorage;
+import com.intellij.util.xmlb.XmlSerializerUtil;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+import org.jetbrains.k2js.config.EcmaVersion;
+
+/**
+ * @author Pavel Talanov
+ */
+@State(
+ name = "K2JSModule",
+ storages = @Storage(
+ id = ClasspathStorage.DEFAULT_STORAGE,
+ file = "$MODULE_FILE$"
+ )
+)
+public final class K2JSModuleComponent implements ModuleComponent, PersistentStateComponent {
+
+ @NotNull
+ public static K2JSModuleComponent getInstance(@NotNull Module module) {
+ return module.getComponent(K2JSModuleComponent.class);
+ }
+
+ private boolean isJavaScriptModule;
+
+ @Nullable
+ private String pathToJavaScriptLibrary;
+
+ @NotNull
+ private EcmaVersion ecmaVersion;
+
+ @NotNull
+ public EcmaVersion getEcmaVersion() {
+ return ecmaVersion;
+ }
+
+ public K2JSModuleComponent() {
+ this.isJavaScriptModule = false;
+ this.pathToJavaScriptLibrary = null;
+ this.ecmaVersion = EcmaVersion.defaultVersion();
+ }
+
+ public void setEcmaVersion(@NotNull EcmaVersion ecmaVersion) {
+ this.ecmaVersion = ecmaVersion;
+ }
+
+ public boolean isJavaScriptModule() {
+ return isJavaScriptModule;
+ }
+
+ public void setJavaScriptModule(boolean javaScriptModule) {
+ isJavaScriptModule = javaScriptModule;
+ }
+
+ @Nullable
+ public String getPathToJavaScriptLibrary() {
+ return pathToJavaScriptLibrary;
+ }
+
+ public void setPathToJavaScriptLibrary(@Nullable String pathToJavaScriptLibrary) {
+ this.pathToJavaScriptLibrary = pathToJavaScriptLibrary;
+ }
+
+ @Override
+ public void projectOpened() {
+ //do nothing
+ }
+
+ @Override
+ public void projectClosed() {
+ //do nothing
+ }
+
+ @Override
+ public void moduleAdded() {
+ //do nothing
+ }
+
+ @Override
+ public void initComponent() {
+ //do nothing
+ }
+
+ @Override
+ public void disposeComponent() {
+ //do nothing
+ }
+
+ @NotNull
+ @Override
+ public String getComponentName() {
+ return "Kotlin to JavaScript module configuration";
+ }
+
+ @Override
+ public K2JSModuleComponent getState() {
+ return this;
+ }
+
+ @Override
+ public void loadState(K2JSModuleComponent state) {
+ XmlSerializerUtil.copyBean(state, this);
+ }
+}
diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java
index 0b873b1259c..25a5b52de47 100644
--- a/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java
+++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ConfigureKotlinLibraryNotificationProvider.java
@@ -56,7 +56,7 @@ import javax.swing.*;
import java.io.File;
import java.io.IOException;
-import static org.jetbrains.jet.plugin.project.JsModuleDetector.isJsProject;
+import static org.jetbrains.jet.plugin.project.JsModuleDetector.isJsModule;
public class ConfigureKotlinLibraryNotificationProvider implements EditorNotifications.Provider {
private static final Key KEY = Key.create("configure.kotlin.library");
@@ -86,7 +86,7 @@ public class ConfigureKotlinLibraryNotificationProvider implements EditorNotific
if (isMavenModule(module)) return null;
- if (isJsProject(myProject)) return null;
+ if (isJsModule(module)) return null;
GlobalSearchScope scope = module.getModuleWithDependenciesAndLibrariesScope(false);
if (JavaPsiFacade.getInstance(myProject).findClass("jet.JetObject", scope) == null) {
@@ -178,7 +178,7 @@ public class ConfigureKotlinLibraryNotificationProvider implements EditorNotific
}
private void setUpJSModule(@NotNull Module module) {
- JsModuleSetUp.doSetUpModule(module.getProject(), new Runnable() {
+ JsModuleSetUp.doSetUpModule(module, new Runnable() {
@Override
public void run() {
updateNotifications();
diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/JsModuleSetUp.java b/idea/src/org/jetbrains/jet/plugin/quickfix/JsModuleSetUp.java
index b2bc6a2b8fb..388c6dd3ab1 100644
--- a/idea/src/org/jetbrains/jet/plugin/quickfix/JsModuleSetUp.java
+++ b/idea/src/org/jetbrains/jet/plugin/quickfix/JsModuleSetUp.java
@@ -20,14 +20,11 @@ import com.intellij.notification.Notification;
import com.intellij.notification.NotificationType;
import com.intellij.notification.Notifications;
import com.intellij.openapi.module.Module;
-import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ModuleRootManager;
-import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import org.jetbrains.jet.plugin.k2jsrun.K2JSRunnerUtils;
-import org.jetbrains.jet.plugin.project.JsModuleDetector;
+import org.jetbrains.jet.plugin.project.K2JSModuleComponent;
import org.jetbrains.jet.utils.PathUtil;
import java.io.File;
@@ -45,13 +42,13 @@ public final class JsModuleSetUp {
private JsModuleSetUp() {
}
- public static void doSetUpModule(@Nullable Project project, @NotNull Runnable continuation) {
- if (project == null) {
- notifyFailure("Internal error: Project not found.");
+ public static void doSetUpModule(@Nullable Module module, @NotNull Runnable continuation) {
+ if (module == null) {
+ notifyFailure("Internal error: Module not found.");
return;
}
- File rootDir = getRootDir(project);
+ File rootDir = getRootDir(module);
if (!rootDir.isDirectory()) {
notifyFailure("Internal error: Broken content root.");
return;
@@ -59,19 +56,11 @@ public final class JsModuleSetUp {
if (!copyJsLibFiles(rootDir)) return;
- File file = new File(rootDir, JsModuleDetector.INDICATION_FILE_NAME);
- if (file.exists()) {
- notifyInfo("File " + file.getName() + " already exists.");
- // If the notification in the editor did not disappear due to
- // slow file system events, this will remove the notification
- // when the user clicks for the second time
- refreshRootDir(project, continuation);
- return;
- }
+ K2JSModuleComponent jsModuleComponent = K2JSModuleComponent.getInstance(module);
+ jsModuleComponent.setJavaScriptModule(true);
+ jsModuleComponent.setPathToJavaScriptLibrary("/lib/" + PathUtil.JS_LIB_JAR_NAME);
- createIndicationFile(file);
-
- refreshRootDir(project, continuation);
+ refreshRootDir(module, continuation);
}
private static boolean copyJsLibFiles(@NotNull File rootDir) {
@@ -85,19 +74,10 @@ public final class JsModuleSetUp {
return doCopyJsLibFiles(Arrays.asList(jsLibJarPath, jsLibJsPath), rootDir);
}
- private static void refreshRootDir(@NotNull Project project, @NotNull Runnable continuation) {
+ private static void refreshRootDir(@NotNull Module project, @NotNull Runnable continuation) {
getContentRoot(project).refresh(true, true, continuation);
}
- private static void createIndicationFile(@NotNull File file) {
- try {
- FileUtil.writeToFile(file, "lib/" + PathUtil.JS_LIB_JAR_NAME);
- }
- catch (IOException e) {
- notifyFailure("Failed to write file " + file.getName());
- }
- }
-
private static boolean doCopyJsLibFiles(@NotNull List files, @NotNull File rootDir) {
try {
File lib = new File(rootDir, "lib");
@@ -113,14 +93,13 @@ public final class JsModuleSetUp {
}
@NotNull
- private static File getRootDir(@NotNull Project project) {
- VirtualFile contentRoot = getContentRoot(project);
+ private static File getRootDir(@NotNull Module module) {
+ VirtualFile contentRoot = getContentRoot(module);
return new File(contentRoot.getPath());
}
@NotNull
- private static VirtualFile getContentRoot(@NotNull Project project) {
- Module module = K2JSRunnerUtils.getJsModule(project);
+ private static VirtualFile getContentRoot(@NotNull Module module) {
return ModuleRootManager.getInstance(module).getContentRoots()[0];
}
@@ -129,10 +108,4 @@ public final class JsModuleSetUp {
message,
NotificationType.ERROR));
}
-
- public static void notifyInfo(@NotNull String message) {
- Notifications.Bus.notify(new Notification("Set Up Kotlin to JavaScript Module", "Information",
- message,
- NotificationType.INFORMATION));
- }
}
diff --git a/idea/src/org/jetbrains/jet/plugin/run/JetRunConfigurationProducer.java b/idea/src/org/jetbrains/jet/plugin/run/JetRunConfigurationProducer.java
index b6c72cbb6e3..f237d4942f5 100644
--- a/idea/src/org/jetbrains/jet/plugin/run/JetRunConfigurationProducer.java
+++ b/idea/src/org/jetbrains/jet/plugin/run/JetRunConfigurationProducer.java
@@ -59,7 +59,7 @@ public class JetRunConfigurationProducer extends RuntimeConfigurationProducer im
return null;
}
- if (JsModuleDetector.isJsProject(module.getProject())) {
+ if (JsModuleDetector.isJsModule(module)) {
return null;
}