diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 625735db99e..17e6d17f898 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -413,5 +413,11 @@ + + + + + + diff --git a/idea/src/org/jetbrains/jet/plugin/configuration/ConfigureKotlinInProjectUtils.java b/idea/src/org/jetbrains/jet/plugin/configuration/ConfigureKotlinInProjectUtils.java new file mode 100644 index 00000000000..aa6ab2a9264 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/configuration/ConfigureKotlinInProjectUtils.java @@ -0,0 +1,171 @@ +/* + * 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.configuration; + +import com.beust.jcommander.internal.Lists; +import com.google.common.collect.Sets; +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationListener; +import com.intellij.notification.NotificationType; +import com.intellij.notification.Notifications; +import com.intellij.openapi.extensions.Extensions; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.search.FileTypeIndex; +import com.intellij.psi.search.GlobalSearchScope; +import com.intellij.util.Function; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.JetFileType; + +import javax.swing.event.HyperlinkEvent; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Set; + +public class ConfigureKotlinInProjectUtils { + + public static boolean isProjectConfigured(@NotNull Project project) { + Collection modules = getModulesWithKotlinFiles(project); + for (Module module : modules) { + if (!isModuleConfigured(module)) { + return false; + } + } + return true; + } + + public static boolean isModuleConfigured(@NotNull Module module) { + Set configurators = getApplicableConfigurators(module); + for (KotlinProjectConfigurator configurator : configurators) { + if (configurator.isConfigured(module)) { + return true; + } + } + return false; + } + + public static boolean hasKotlinFiles(@NotNull Module module) { + return !FileTypeIndex.getFiles(JetFileType.INSTANCE, GlobalSearchScope.moduleScope(module)).isEmpty(); + } + + public static Collection getModulesWithKotlinFiles(@NotNull Project project) { + List modulesWithKotlin = Lists.newArrayList(); + for (Module module : ModuleManager.getInstance(project).getModules()) { + if (hasKotlinFiles(module)) { + modulesWithKotlin.add(module); + } + } + return modulesWithKotlin; + } + + public static void showConfigureKotlinNotificationIfNeeded(@NotNull Module module) { + if (isModuleConfigured(module)) return; + + showConfigureKotlinNotification(module.getProject()); + } + + public static void showConfigureKotlinNotificationIfNeeded(@NotNull Project project) { + if (isProjectConfigured(project)) return; + + showConfigureKotlinNotification(project); + } + + private static void showConfigureKotlinNotification(final Project project) { + Collection configurators = getApplicableConfigurators(project); + + String links = StringUtil.join(configurators, new Function() { + @Override + public String fun(KotlinProjectConfigurator configurator) { + return getLink(configurator); + } + }, " "); + + Notifications.Bus.notify( + new Notification("Configure Kotlin", + "Kotlin file(s) found in your project.", + "Configure Kotlin:\n" + links, + NotificationType.ERROR, new NotificationListener() { + @Override + public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) { + if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + KotlinProjectConfigurator configurator = getConfiguratorByName(event.getDescription()); + if (configurator == null) { + throw new AssertionError("Missed action: " + event.getDescription()); + } + configurator.configure(project); + notification.expire(); + } + } + }), project); + } + + @NotNull + public static Collection getApplicableConfigurators(@NotNull Project project) { + Set applicableConfigurators = Sets.newHashSet(); + for (KotlinProjectConfigurator configurator : Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME)) { + for (Module module : getNonConfiguredModules(project, configurator)) { + if (configurator.isApplicable(module)) { + applicableConfigurators.add(configurator); + } + } + } + return applicableConfigurators; + } + + @NotNull + public static Set getApplicableConfigurators(@NotNull Module module) { + Set applicableConfigurators = Sets.newHashSet(); + for (KotlinProjectConfigurator configurator : Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME)) { + if (configurator.isApplicable(module)) { + applicableConfigurators.add(configurator); + } + } + return applicableConfigurators; + } + + @Nullable + public static KotlinProjectConfigurator getConfiguratorByName(@NotNull String name) { + for (KotlinProjectConfigurator configurator : Extensions.getExtensions(KotlinProjectConfigurator.EP_NAME)) { + if (configurator.getName().equals(name)) { + return configurator; + } + } + return null; + } + + public static List getNonConfiguredModules(@NotNull Project project, @NotNull KotlinProjectConfigurator configurator) { + Collection modules = getModulesWithKotlinFiles(project); + List result = new ArrayList(modules.size()); + for (Module module : modules) { + if (configurator.isApplicable(module) && !configurator.isConfigured(module)) { + result.add(module); + } + } + return result; + } + @NotNull + public static String getLink(@NotNull KotlinProjectConfigurator configurator) { + return StringUtil.join("", configurator.getPresentableText(), ""); + } + + private ConfigureKotlinInProjectUtils() { + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/configuration/KotlinJavaModuleConfigurator.java b/idea/src/org/jetbrains/jet/plugin/configuration/KotlinJavaModuleConfigurator.java new file mode 100644 index 00000000000..92a6a1f58bd --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/configuration/KotlinJavaModuleConfigurator.java @@ -0,0 +1,99 @@ +package org.jetbrains.jet.plugin.configuration; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.vfs.VfsUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.plugin.framework.JavaRuntimeLibraryDescription; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; +import org.jetbrains.jet.plugin.framework.ui.CreateJavaLibraryDialogWithModules; +import org.jetbrains.jet.utils.PathUtil; + +import java.io.File; +import java.util.List; + +public class KotlinJavaModuleConfigurator extends KotlinWithLibraryConfigurator { + public static final String NAME = "java"; + + @Override + public boolean isConfigured(@NotNull Module module) { + return KotlinFrameworkDetector.isJavaKotlinModule(module); + } + + @NotNull + @Override + protected String getLibraryName() { + return JavaRuntimeLibraryDescription.LIBRARY_NAME; + } + + @NotNull + @Override + protected String getJarName() { + return PathUtil.KOTLIN_JAVA_RUNTIME_JAR; + } + + @Override + protected void addRootsToLibrary(@NotNull Library.ModifiableModel library, @NotNull File jarFile) { + String libraryRoot = VfsUtil.getUrlForLibraryRoot(jarFile); + library.addRoot(libraryRoot, OrderRootType.CLASSES); + library.addRoot(libraryRoot + "src", OrderRootType.SOURCES); + } + + @NotNull + @Override + protected String getMessageForOverrideDialog() { + return JavaRuntimeLibraryDescription.JAVA_RUNTIME_LIBRARY_CREATION; + } + + @NotNull + @Override + public String getPresentableText() { + return "As Java project"; + } + + @NotNull + @Override + public String getName() { + return NAME; + } + + @Override + public void configure(@NotNull Project project) { + String defaultPath = getDefaultPathToJarFile(project); + boolean showPathPanelForJava = needToChooseJarPath(project); + + List nonConfiguredModules = ConfigureKotlinInProjectUtils.getNonConfiguredModules(project, this); + + CreateJavaLibraryDialogWithModules dialog = + new CreateJavaLibraryDialogWithModules(project, nonConfiguredModules, defaultPath, showPathPanelForJava); + dialog.show(); + + if (!dialog.isOK()) return; + + for (Module module : dialog.getModulesToConfigure()) { + configureModuleWithLibrary(module, defaultPath, dialog.getCopyIntoPath()); + } + } + + @Override + @NotNull + public File getExistedJarFile() { + File result; + if (ApplicationManager.getApplication().isUnitTestMode()) { + result = PathUtil.getKotlinPathsForDistDirectory().getRuntimePath(); + } + else { + result = PathUtil.getKotlinPathsForIdeaPlugin().getRuntimePath(); + } + if (!result.exists()) { + showError("Jar file wasn't found in " + result.getPath()); + } + return result; + } + + KotlinJavaModuleConfigurator() { + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/configuration/KotlinJsModuleConfigurator.java b/idea/src/org/jetbrains/jet/plugin/configuration/KotlinJsModuleConfigurator.java new file mode 100644 index 00000000000..028cf50b832 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/configuration/KotlinJsModuleConfigurator.java @@ -0,0 +1,153 @@ +package org.jetbrains.jet.plugin.configuration; + +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.vfs.VfsUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.framework.JSLibraryStdDescription; +import org.jetbrains.jet.plugin.framework.KotlinFrameworkDetector; +import org.jetbrains.jet.plugin.framework.ui.CreateJavaScriptLibraryDialogWithModules; +import org.jetbrains.jet.plugin.framework.ui.FileUIUtils; +import org.jetbrains.jet.utils.PathUtil; + +import java.io.File; +import java.util.List; + +public class KotlinJsModuleConfigurator extends KotlinWithLibraryConfigurator { + public static final String NAME = "js"; + + @NotNull + @Override + public String getName() { + return NAME; + } + + @NotNull + @Override + public String getPresentableText() { + return "As JavaScript project"; + } + + @Override + public boolean isConfigured(@NotNull Module module) { + if (KotlinFrameworkDetector.isJsKotlinModule(module)) { + String pathFromLibrary = getPathToJarFromLibrary(module.getProject()); + return pathFromLibrary != null && getJarFile(pathFromLibrary).exists(); + } + return false; + } + + @NotNull + @Override + protected String getLibraryName() { + return JSLibraryStdDescription.LIBRARY_NAME; + } + + @NotNull + @Override + protected String getJarName() { + return PathUtil.JS_LIB_JAR_NAME; + } + + @Override + protected void addRootsToLibrary(@NotNull Library.ModifiableModel library, @NotNull File jarFile) { + String libraryRoot = VfsUtil.getUrlForLibraryRoot(jarFile); + library.addRoot(libraryRoot, OrderRootType.CLASSES); + library.addRoot(libraryRoot, OrderRootType.SOURCES); + } + + @NotNull + @Override + protected String getMessageForOverrideDialog() { + return JSLibraryStdDescription.JAVA_SCRIPT_LIBRARY_CREATION; + } + + @NotNull + @Override + public File getExistedJarFile() { + File result; + if (ApplicationManager.getApplication().isUnitTestMode()) { + result = PathUtil.getKotlinPathsForDistDirectory().getJsLibJarPath(); + } + else { + result = PathUtil.getKotlinPathsForIdeaPlugin().getJsLibJarPath(); + } + if (!result.exists()) { + showError("Jar file wasn't found in " + result.getPath()); + } + return result; + } + + @Override + public void configure(@NotNull Project project) { + String defaultPathToJar = getDefaultPathToJarFile(project); + String defaultPathToJsFile = getDefaultPathToJsFile(project); + + boolean showPathToJarPanel = needToChooseJarPath(project); + boolean showPathToJsFilePanel = needToChooseJsFilePath(project); + + List nonConfiguredModules = ConfigureKotlinInProjectUtils.getNonConfiguredModules(project, this); + + CreateJavaScriptLibraryDialogWithModules dialog = + new CreateJavaScriptLibraryDialogWithModules(project, nonConfiguredModules, + defaultPathToJar, defaultPathToJsFile, + showPathToJarPanel, showPathToJsFilePanel); + dialog.show(); + + if (!dialog.isOK()) return; + + for (Module module : dialog.getModulesToConfigure()) { + configureModuleWithLibrary(module, defaultPathToJar, dialog.getCopyLibraryIntoPath()); + } + configureModuleWithJsFile(defaultPathToJsFile, dialog.getCopyJsIntoPath()); + } + + public static boolean isJsFilePresent(@NotNull String dir) { + String runtimeJarFileName = dir + "/" + PathUtil.JS_LIB_JAR_NAME; + return new File(runtimeJarFileName).exists(); + } + + @NotNull + public File getJsFile() { + File result; + if (ApplicationManager.getApplication().isUnitTestMode()) { + result = PathUtil.getKotlinPathsForDistDirectory().getJsLibJsPath(); + } + else { + result = PathUtil.getKotlinPathsForIdeaPlugin().getJsLibJsPath(); + } + if (!result.exists()) { + showError("Jar file wasn't found in " + result.getPath()); + } + return result; + } + + private static boolean needToChooseJsFilePath(@NotNull Project project) { + String defaultPath = FileUIUtils.createRelativePath(project, project.getBaseDir(), "script"); + return !isJsFilePresent(defaultPath); + } + + @NotNull + private static String getDefaultPathToJsFile(@NotNull Project project) { + return FileUIUtils.createRelativePath(project, project.getBaseDir(), "script"); + } + + protected void configureModuleWithJsFile( + @NotNull String defaultPath, + @Nullable String pathToJsFromDialog + ) { + boolean isJsFilePresent = isJsFilePresent(defaultPath); + if (isJsFilePresent) return; + + if (pathToJsFromDialog != null) { + copyFileToDir(getJsFile(), pathToJsFromDialog); + } + } + + KotlinJsModuleConfigurator() { + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/configuration/KotlinProjectConfigurator.java b/idea/src/org/jetbrains/jet/plugin/configuration/KotlinProjectConfigurator.java new file mode 100644 index 00000000000..7cd6c3ad796 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/configuration/KotlinProjectConfigurator.java @@ -0,0 +1,20 @@ +package org.jetbrains.jet.plugin.configuration; + +import com.intellij.openapi.extensions.ExtensionPointName; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; + +public interface KotlinProjectConfigurator { + ExtensionPointName EP_NAME = ExtensionPointName.create("org.jetbrains.kotlin.projectConfigurator"); + + boolean isConfigured(@NotNull Module module); + + boolean isApplicable(@NotNull Module module); + + void configure(Project project); + + @NotNull String getPresentableText(); + + @NotNull String getName(); +} diff --git a/idea/src/org/jetbrains/jet/plugin/configuration/KotlinWithLibraryConfigurator.java b/idea/src/org/jetbrains/jet/plugin/configuration/KotlinWithLibraryConfigurator.java new file mode 100644 index 00000000000..ab85bed751f --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/configuration/KotlinWithLibraryConfigurator.java @@ -0,0 +1,333 @@ +package org.jetbrains.jet.plugin.configuration; + +import com.intellij.notification.Notification; +import com.intellij.notification.NotificationType; +import com.intellij.openapi.application.ApplicationManager; +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.roots.ModuleRootModificationUtil; +import com.intellij.openapi.roots.OrderEnumerator; +import com.intellij.openapi.roots.OrderRootType; +import com.intellij.openapi.roots.libraries.Library; +import com.intellij.openapi.roots.libraries.LibraryTable; +import com.intellij.openapi.roots.libraries.LibraryTablesRegistrar; +import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; +import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory; +import com.intellij.openapi.ui.Messages; +import com.intellij.openapi.util.Ref; +import com.intellij.openapi.vfs.VfsUtil; +import com.intellij.openapi.vfs.VfsUtilCore; +import com.intellij.util.Processor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.framework.ui.FileUIUtils; + +import java.io.File; + +import static com.intellij.notification.Notifications.Bus; + +public abstract class KotlinWithLibraryConfigurator implements KotlinProjectConfigurator { + + @NotNull + protected abstract String getLibraryName(); + + @NotNull + protected abstract String getJarName(); + + @NotNull + protected abstract String getMessageForOverrideDialog(); + + @NotNull + protected abstract File getExistedJarFile(); + + protected abstract void addRootsToLibrary(@NotNull Library.ModifiableModel library, @NotNull File jarFile); + + @Override + public boolean isApplicable(@NotNull Module module) { + return true; + } + + public boolean isJarPresent(@NotNull String dir) { + return getJarInDir(dir).exists(); + } + + public File getJarInDir(@NotNull String dir) { + String runtimeJarFileName = dir + "/" + getJarName(); + return new File(runtimeJarFileName); + } + + protected void configureModuleWithLibrary( + @NotNull Module module, + @NotNull LibraryState libraryState, + @NotNull FileState jarState, + @Nullable String dirWithJar + ) { + Project project = module.getProject(); + + switch (libraryState) { + case LIBRARY: + switch (jarState) { + case EXISTS: { + break; + } + case COPY: { + String pathToJarFromLibrary = getPathToJarFromLibrary(project); + if (pathToJarFromLibrary != null) { + copyJarToDir(pathToJarFromLibrary); + } + else { + showError("Cannot copy jar to root for " + getLibraryName() + " library"); + } + break; + } + case DO_NOT_COPY: { + throw new IllegalStateException( + "Kotlin library exists, so path to copy should be hidden in configuration dialog and jar should be copied using path in library table"); + } + } + break; + case NON_CONFIGURED_LIBRARY: + switch (jarState) { + case EXISTS: { + assert dirWithJar != + null : "Jar file exists, so dirWithJar must be non-null: should be default path to lib directory"; + addJarToExistedLibrary(project, getJarFile(dirWithJar)); + break; + } + case COPY: { + assert dirWithJar != null : "Path to copy should be visible in configuration dialog and must be non-null"; + File file = copyJarToDir(dirWithJar); + addJarToExistedLibrary(project, file); + break; + } + case DO_NOT_COPY: { + addJarToExistedLibrary(project, getExistedJarFile()); + break; + } + } + break; + case NEW_LIBRARY: + switch (jarState) { + case EXISTS: { + assert dirWithJar != + null : "Jar file exists, so dirWithJar must be non-null: should be default path to lib directory"; + addJarToNewLibrary(project, getJarFile(dirWithJar)); + break; + } + case COPY: { + assert dirWithJar != null : "Path to copy should be visible in configuration dialog and must be non-null"; + File file = copyJarToDir(dirWithJar); + addJarToNewLibrary(project, file); + break; + } + case DO_NOT_COPY: { + addJarToNewLibrary(project, getExistedJarFile()); + break; + } + } + break; + } + addLibraryToModuleIfNeeded(module); + } + + private void addLibraryToModuleIfNeeded(Module module) { + if (getKotlinLibrary(module) == null) { + Library library = getKotlinLibrary(module.getProject()); + assert library != null : "Kotlin project library should exists"; + ModuleRootModificationUtil.addDependency(module, library); + showInfoNotification(library.getName() + " library was added to module " + module.getName()); + } + } + + @Nullable + protected String getPathToJarFromLibrary(Project project) { + Library library = getKotlinLibrary(project); + if (library == null) return null; + + String[] libraryFiles = library.getUrls(OrderRootType.CLASSES); + if (libraryFiles.length < 1) return null; + + String pathToJarInLib = VfsUtilCore.urlToPath(libraryFiles[0]); + String parentDir = VfsUtil.getParentDir(VfsUtil.getParentDir(pathToJarInLib)); + if (parentDir == null) return null; + + File parentDirFile = new File(parentDir); + if (!parentDirFile.exists() && !parentDirFile.mkdirs()) { + return null; + } + return parentDir; + } + + @NotNull + protected File getJarFile(@NotNull String dirToJar) { + return new File(dirToJar + "/" + getJarName()); + } + + protected void configureModuleWithLibrary( + @NotNull Module module, + @NotNull String defaultPath, + @Nullable String pathFromDialog + ) { + Project project = module.getProject(); + + FileState runtimeState = getJarState(project, defaultPath, pathFromDialog); + LibraryState libraryState = getLibraryState(project); + String dirToCopyJar = isJarPresent(defaultPath) ? defaultPath : pathFromDialog; + + configureModuleWithLibrary(module, libraryState, runtimeState, dirToCopyJar); + } + + private void addJarToExistedLibrary(@NotNull Project project, @NotNull File jarFile) { + Library library = getKotlinLibrary(project); + assert library != null : "Kotlin library should present, instead createNewLibrary should be invoked"; + final Library.ModifiableModel model = library.getModifiableModel(); + addRootsToLibrary(model, jarFile); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + model.commit(); + } + }); + showInfoNotification(library.getName() + " library was configured"); + } + + private void addJarToNewLibrary( + @NotNull Project project, + @NotNull final File jarFile + ) { + final LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTable(project); + final Ref library = new Ref(); + ApplicationManager.getApplication().runWriteAction(new Runnable() { + @Override + public void run() { + library.set(table.createLibrary(getLibraryName())); + Library.ModifiableModel model = library.get().getModifiableModel(); + addRootsToLibrary(model, jarFile); + model.commit(); + } + }); + + showInfoNotification(library.get().getName() + " library was created"); + } + + private boolean isProjectLibraryWithoutPathsPresent(@NotNull Project project) { + Library library = getKotlinLibrary(project); + return library != null && library.getUrls(OrderRootType.CLASSES).length == 0; + } + + private boolean isProjectLibraryPresent(@NotNull Project project) { + Library library = getKotlinLibrary(project); + return library != null && library.getUrls(OrderRootType.CLASSES).length > 0; + } + + @Nullable + private Library getKotlinLibrary(@NotNull Module module) { + final Ref result = Ref.create(null); + OrderEnumerator.orderEntries(module).forEachLibrary(new Processor() { + @Override + public boolean process(Library library) { + if (isKotlinLibrary(library)) { + result.set(library); + return false; + } + return true; + } + }); + return result.get(); + } + + @Nullable + private Library getKotlinLibrary(@NotNull Project project) { + LibrariesContainer librariesContainer = LibrariesContainerFactory.createContainer(project); + for (Library library : librariesContainer.getLibraries(LibrariesContainer.LibraryLevel.PROJECT)) { + if (isKotlinLibrary(library)) { + return library; + } + } + for (Library library : librariesContainer.getLibraries(LibrariesContainer.LibraryLevel.GLOBAL)) { + if (isKotlinLibrary(library)) { + return library; + } + } + return null; + } + + private boolean isKotlinLibrary(@NotNull Library library) { + return getLibraryName().equals(library.getName()); + } + + public File copyJarToDir(@NotNull String toDir) { + return copyFileToDir(getExistedJarFile(), toDir); + } + + public File copyFileToDir(@NotNull File file, @NotNull String toDir) { + File copy = FileUIUtils.copyWithOverwriteDialog(getMessageForOverrideDialog(), toDir, file); + if (copy != null) { + showInfoNotification(file.getName() + " was copied to " + toDir); + } + return copy; + } + + private static void showInfoNotification(@NotNull String message) { + Bus.notify(new Notification("Configure Kotlin", "Configure Kotlin", message, NotificationType.INFORMATION)); + } + + protected boolean needToChooseJarPath(@NotNull Project project) { + String defaultPath = getDefaultPathToJarFile(project); + return !isProjectLibraryPresent(project) && !isJarPresent(defaultPath); + } + + protected static String getDefaultPathToJarFile(@NotNull Project project) { + return FileUIUtils.createRelativePath(project, project.getBaseDir(), "lib"); + } + + protected void showError(@NotNull String message) { + Messages.showErrorDialog(message, getMessageForOverrideDialog()); + } + + protected static enum FileState { + EXISTS, + COPY, + DO_NOT_COPY + } + + protected static enum LibraryState { + LIBRARY, + NON_CONFIGURED_LIBRARY, + NEW_LIBRARY, + } + + @NotNull + protected LibraryState getLibraryState(@NotNull Project project) { + if (isProjectLibraryPresent(project)) { + return LibraryState.LIBRARY; + } + else if (isProjectLibraryWithoutPathsPresent(project)) { + return LibraryState.NON_CONFIGURED_LIBRARY; + } + return LibraryState.NEW_LIBRARY; + } + + @NotNull + protected FileState getJarState( + @NotNull Project project, + @NotNull String defaultPath, + @Nullable String pathFromDialog + ) { + String pathFormLibrary = getPathToJarFromLibrary(project); + if (isJarPresent(defaultPath) || + (pathFromDialog != null && isJarPresent(pathFromDialog)) || + (pathFormLibrary != null && getJarFile(pathFormLibrary).exists())) { + return FileState.EXISTS; + } + else if (pathFromDialog == null) { + return FileState.DO_NOT_COPY; + } + else { + return FileState.COPY; + } + } + + KotlinWithLibraryConfigurator() { + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryCreateOptions.java b/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryCreateOptions.java index c18e1b04f70..ff0b08d81f5 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryCreateOptions.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryCreateOptions.java @@ -19,20 +19,6 @@ package org.jetbrains.jet.plugin.framework; import org.jetbrains.annotations.Nullable; public interface JSLibraryCreateOptions { - JSLibraryCreateOptions DEFAULT = new JSLibraryCreateOptions() { - @Nullable - @Override - public String getCopyJsIntoPath() { - return null; - } - - @Nullable - @Override - public String getCopyLibraryIntoPath() { - return null; - } - }; - @Nullable String getCopyJsIntoPath(); diff --git a/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdDescription.java b/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdDescription.java index 7e08c849abb..a5c7f84c764 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdDescription.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/JSLibraryStdDescription.java @@ -23,27 +23,28 @@ import com.intellij.openapi.roots.libraries.LibraryKind; import com.intellij.openapi.roots.libraries.NewLibraryConfiguration; import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription; import com.intellij.openapi.roots.ui.configuration.libraryEditor.LibraryEditor; -import com.intellij.openapi.ui.Messages; import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.configuration.ConfigureKotlinInProjectUtils; +import org.jetbrains.jet.plugin.configuration.KotlinJsModuleConfigurator; import org.jetbrains.jet.plugin.framework.ui.CreateJavaScriptLibraryDialog; import org.jetbrains.jet.plugin.framework.ui.FileUIUtils; -import org.jetbrains.jet.utils.KotlinPaths; -import org.jetbrains.jet.utils.PathUtil; import javax.swing.*; import java.io.File; -import java.util.HashMap; -import java.util.Map; import java.util.Set; +import static org.jetbrains.jet.plugin.configuration.ConfigureKotlinInProjectUtils.getConfiguratorByName; +import static org.jetbrains.jet.plugin.configuration.KotlinJsModuleConfigurator.NAME; +import static org.jetbrains.jet.plugin.framework.ui.FileUIUtils.createRelativePath; + public class JSLibraryStdDescription extends CustomLibraryDescription { public static final LibraryKind KOTLIN_JAVASCRIPT_KIND = LibraryKind.create("kotlin-js-stdlib"); public static final String LIBRARY_NAME = "KotlinJavaScript"; - private static final String JAVA_SCRIPT_LIBRARY_CREATION = "JavaScript Library Creation"; + public static final String JAVA_SCRIPT_LIBRARY_CREATION = "JavaScript Library Creation"; private static final Set libraryKinds = Sets.newHashSet(KOTLIN_JAVASCRIPT_KIND); @NotNull @@ -55,56 +56,58 @@ public class JSLibraryStdDescription extends CustomLibraryDescription { @Nullable @Override public NewLibraryConfiguration createNewLibrary(@NotNull JComponent parentComponent, @Nullable VirtualFile contextDirectory) { - CreateJavaScriptLibraryDialog dialog = new CreateJavaScriptLibraryDialog(null, "Create Kotlin JavaScript Library", contextDirectory); + KotlinJsModuleConfigurator configurator = (KotlinJsModuleConfigurator) getConfiguratorByName(NAME); + assert configurator != null : "Cannot find configurator with name " + NAME; + + String defaultPathToJsFileDir = createRelativePath(null, contextDirectory, "script"); + String defaultPathToJarFileDir = createRelativePath(null, contextDirectory, "lib"); + + boolean jsFilePresent = KotlinJsModuleConfigurator.isJsFilePresent(defaultPathToJsFileDir); + boolean jarFilePresent = configurator.isJarPresent(defaultPathToJarFileDir); + + if (jarFilePresent && jsFilePresent) { + return createConfiguration(configurator.getJarInDir(defaultPathToJarFileDir)); + } + + CreateJavaScriptLibraryDialog dialog = + new CreateJavaScriptLibraryDialog(defaultPathToJarFileDir, defaultPathToJsFileDir, !jarFilePresent, !jsFilePresent); dialog.show(); - if (dialog.isOK()) { - return createNewLibrary(parentComponent, PathUtil.getKotlinPathsForIdeaPlugin(), dialog); + if (!dialog.isOK()) return null; + + String copyJsFileIntoPath = dialog.getCopyJsIntoPath(); + if (!jsFilePresent && copyJsFileIntoPath != null) { + configurator.copyFileToDir(configurator.getJsFile(), copyJsFileIntoPath); } - return null; + if (jarFilePresent) { + return createConfiguration(configurator.getJarInDir(defaultPathToJarFileDir)); + } + else { + String copyIntoPath = dialog.getCopyLibraryIntoPath(); + if (copyIntoPath != null) { + return createConfiguration(configurator.copyJarToDir(copyIntoPath)); + } + else { + return createConfiguration(configurator.getExistedJarFile()); + } + } } - @Nullable - public NewLibraryConfiguration createNewLibrary(@Nullable JComponent parentComponent, @NotNull KotlinPaths paths, @NotNull JSLibraryCreateOptions options) { - File libraryFile = paths.getJsLibJarPath(); - if (!libraryFile.exists()) { - Messages.showErrorDialog(String.format("JavaScript standard library was not found in %s", paths.getLibPath()), - JAVA_SCRIPT_LIBRARY_CREATION); - return null; - } + public NewLibraryConfiguration createNewLibraryForTests() { + KotlinJsModuleConfigurator configurator = (KotlinJsModuleConfigurator) getConfiguratorByName(NAME); + assert configurator != null : "Cannot find configurator with name " + NAME; - Map copyToPaths = new HashMap(); + return createConfiguration(configurator.getExistedJarFile()); + } - String copyLibraryIntoPath = options.getCopyLibraryIntoPath(); - if (copyLibraryIntoPath != null) { - copyToPaths.put(libraryFile, copyLibraryIntoPath); - } - - String copyJsIntoPath = options.getCopyJsIntoPath(); - if (copyJsIntoPath != null) { - copyToPaths.put(paths.getJsLibJsPath(), copyJsIntoPath); - } - - if (!copyToPaths.isEmpty()) { - assert parentComponent != null : "Copying should be performed only when executed in GUI"; - - Map copiedFiles = FileUIUtils.copyWithOverwriteDialog(parentComponent, JAVA_SCRIPT_LIBRARY_CREATION, copyToPaths); - if (copiedFiles == null) { - return null; - } - - if (copyLibraryIntoPath != null) { - libraryFile = copiedFiles.get(libraryFile); - } - } - - final String libraryFileUrl = VfsUtil.getUrlForLibraryRoot(libraryFile); + private NewLibraryConfiguration createConfiguration(@NotNull File libraryFile) { + final String libraryRoot = VfsUtil.getUrlForLibraryRoot(libraryFile); return new NewLibraryConfiguration(LIBRARY_NAME, getDownloadableLibraryType(), new LibraryVersionProperties()) { @Override public void addRoots(@NotNull LibraryEditor editor) { - editor.addRoot(libraryFileUrl, OrderRootType.CLASSES); - editor.addRoot(libraryFileUrl, OrderRootType.SOURCES); + editor.addRoot(libraryRoot, OrderRootType.CLASSES); + editor.addRoot(libraryRoot, OrderRootType.SOURCES); } }; } diff --git a/idea/src/org/jetbrains/jet/plugin/framework/JavaRuntimeLibraryDescription.java b/idea/src/org/jetbrains/jet/plugin/framework/JavaRuntimeLibraryDescription.java index 6617f8b45ff..7ca6ed431ac 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/JavaRuntimeLibraryDescription.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/JavaRuntimeLibraryDescription.java @@ -28,6 +28,8 @@ import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.configuration.ConfigureKotlinInProjectUtils; +import org.jetbrains.jet.plugin.configuration.KotlinJavaModuleConfigurator; import org.jetbrains.jet.plugin.framework.ui.CreateJavaLibraryDialog; import org.jetbrains.jet.plugin.framework.ui.FileUIUtils; import org.jetbrains.jet.utils.KotlinPaths; @@ -41,7 +43,7 @@ public class JavaRuntimeLibraryDescription extends CustomLibraryDescription { public static final LibraryKind KOTLIN_JAVA_RUNTIME_KIND = LibraryKind.create("kotlin-java-runtime"); public static final String LIBRARY_NAME = "KotlinJavaRuntime"; - private static final String JAVA_RUNTIME_LIBRARY_CREATION = "Java Runtime Library Creation"; + public static final String JAVA_RUNTIME_LIBRARY_CREATION = "Java Runtime Library Creation"; private static final Set libraryKinds = Sets.newHashSet(KOTLIN_JAVA_RUNTIME_KIND); @NotNull @@ -53,28 +55,26 @@ public class JavaRuntimeLibraryDescription extends CustomLibraryDescription { @Nullable @Override public NewLibraryConfiguration createNewLibrary(@NotNull JComponent parentComponent, @Nullable VirtualFile contextDirectory) { - CreateJavaLibraryDialog dialog = new CreateJavaLibraryDialog(null, "Create Kotlin Java Runtime Library", contextDirectory); - dialog.show(); + KotlinJavaModuleConfigurator configurator = (KotlinJavaModuleConfigurator) ConfigureKotlinInProjectUtils + .getConfiguratorByName(KotlinJavaModuleConfigurator.NAME); + assert configurator != null : "Configurator with name " + KotlinJavaModuleConfigurator.NAME + " should exists"; - if (!dialog.isOK()) return null; + String defaultPathToJarFile = FileUIUtils.createRelativePath(null, contextDirectory, "lib"); - KotlinPaths paths = PathUtil.getKotlinPathsForIdeaPlugin(); + boolean jarFilePresent = configurator.isJarPresent(defaultPathToJarFile); - File libraryFile = paths.getRuntimePath(); - if (!libraryFile.exists()) { - Messages.showErrorDialog( - parentComponent, - String.format("Java Runtime library was not found in '%s'." , paths.getLibPath()), - JAVA_RUNTIME_LIBRARY_CREATION); - return null; + File libraryFile; + if (jarFilePresent) { + libraryFile = configurator.getJarInDir(defaultPathToJarFile); } + else { + CreateJavaLibraryDialog dialog = new CreateJavaLibraryDialog(defaultPathToJarFile); + dialog.show(); - String copyIntoPath = dialog.getCopyIntoPath(); - if (copyIntoPath != null) { - libraryFile = FileUIUtils.copyWithOverwriteDialog(parentComponent, JAVA_RUNTIME_LIBRARY_CREATION, copyIntoPath, libraryFile); - if (libraryFile == null) { - return null; - } + if (!dialog.isOK()) return null; + + String copyIntoPath = dialog.getCopyIntoPath(); + libraryFile = copyIntoPath != null ? configurator.copyJarToDir(copyIntoPath) : configurator.getExistedJarFile(); } final String libraryFileUrl = VfsUtil.getUrlForLibraryRoot(libraryFile); diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/ChooseModulePanel.form b/idea/src/org/jetbrains/jet/plugin/framework/ui/ChooseModulePanel.form new file mode 100644 index 00000000000..6a66942e475 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/ChooseModulePanel.form @@ -0,0 +1,48 @@ + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/ChooseModulePanel.java b/idea/src/org/jetbrains/jet/plugin/framework/ui/ChooseModulePanel.java new file mode 100644 index 00000000000..f19628605ac --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/ChooseModulePanel.java @@ -0,0 +1,101 @@ +/* + * 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.framework.ui; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.util.Function; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.Collections; +import java.util.List; + +public class ChooseModulePanel { + private JPanel contentPane; + private JRadioButton allModulesWithKtRadioButton; + private JRadioButton singleModuleRadioButton; + private JComboBox singleModuleComboBox; + private JSeparator separator; + + @NotNull private final Project project; + @NotNull private final List modules; + + public ChooseModulePanel(@NotNull Project project, @NotNull List modules) { + this.project = project; + this.modules = modules; + + DefaultComboBoxModel comboBoxModel = new DefaultComboBoxModel(); + + for (Module module : modules) { + comboBoxModel.addElement(module.getName()); + } + + singleModuleComboBox.setModel(comboBoxModel); + singleModuleRadioButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateComponents(); + } + }); + allModulesWithKtRadioButton.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + updateComponents(); + } + }); + String fullList = StringUtil.join(modules, new Function() { + @Override + public String fun(Module module) { + return module.getName(); + } + }, ", "); + + allModulesWithKtRadioButton.setText(allModulesWithKtRadioButton.getText() + StringUtil.shortenTextWithEllipsis(fullList, 80, 0)); + + ButtonGroup modulesGroup = new ButtonGroup(); + modulesGroup.add(allModulesWithKtRadioButton); + modulesGroup.add(singleModuleRadioButton); + allModulesWithKtRadioButton.setSelected(true); + + separator.setVisible(false); + + updateComponents(); + } + + public void showSeparator() { + separator.setVisible(true); + } + + public JComponent getContentPane() { + return contentPane; + } + + private void updateComponents() { + singleModuleComboBox.setEnabled(singleModuleRadioButton.isSelected()); + } + + public List getModulesToConfigure() { + if (allModulesWithKtRadioButton.isSelected()) return modules; + String selectedItem = (String) singleModuleComboBox.getSelectedItem(); + return Collections.singletonList(ModuleManager.getInstance(project).findModuleByName(selectedItem)); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialog.java b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialog.java index d5642a2245f..d1d795387e0 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialog.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialog.java @@ -16,67 +16,12 @@ package org.jetbrains.jet.plugin.framework.ui; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.plugin.JetPluginUtil; -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class CreateJavaLibraryDialog extends DialogWrapper { - private final CopyIntoPanel copyIntoPanel; - - private JPanel contentPane; - private JCheckBox copyLibraryCheckbox; - private JPanel copyIntoPanelPlace; - private JLabel compilerTextLabel; - - public CreateJavaLibraryDialog(@Nullable Project project, @NotNull String title, VirtualFile contextDirectory) { - super(project); - - setTitle(title); - - init(); - - compilerTextLabel.setText(compilerTextLabel.getText() + " - " + JetPluginUtil.getPluginVersion()); - - copyIntoPanel = new CopyIntoPanel(project, FileUIUtils.createRelativePath(project, contextDirectory, "lib")); - copyIntoPanel.addValidityListener(new ValidityListener() { - @Override - public void validityChanged(boolean isValid) { - updateComponents(); - } - }); - copyIntoPanelPlace.add(copyIntoPanel.getContentPane(), BorderLayout.CENTER); - - copyLibraryCheckbox.addActionListener(new ActionListener() { - @Override - public void actionPerformed(@NotNull ActionEvent e) { - updateComponents(); - } - }); +public class CreateJavaLibraryDialog extends CreateJavaLibraryDialogBase { + public CreateJavaLibraryDialog(@NotNull String defaultPath) { + super(null, defaultPath); updateComponents(); } - - @Nullable - public String getCopyIntoPath() { - return copyIntoPanel.getPath(); - } - - private void updateComponents() { - copyIntoPanel.setEnabled(copyLibraryCheckbox.isSelected()); - setOKActionEnabled(!copyIntoPanel.hasErrors()); - } - - @Nullable - @Override - protected JComponent createCenterPanel() { - return contentPane; - } } diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialog.form b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogBase.form similarity index 85% rename from idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialog.form rename to idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogBase.form index e6284803204..de2ec87c6eb 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialog.form +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogBase.form @@ -1,6 +1,6 @@ -
- + + @@ -10,13 +10,13 @@ - + - + @@ -48,6 +48,14 @@ + + + + + + + + diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogBase.java b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogBase.java new file mode 100644 index 00000000000..cea3481a29d --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogBase.java @@ -0,0 +1,85 @@ +/* + * 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.framework.ui; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.JetPluginUtil; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public abstract class CreateJavaLibraryDialogBase extends DialogWrapper { + protected final CopyIntoPanel copyIntoPanel; + + protected JPanel contentPane; + protected JCheckBox copyLibraryCheckbox; + protected JPanel copyIntoPanelPlace; + protected JLabel compilerTextLabel; + protected JPanel chooseModulesPanelPlace; + + public CreateJavaLibraryDialogBase( + @Nullable Project project, + @NotNull String defaultPath + ) { + super(project); + + setTitle("Create Kotlin Java Runtime Library"); + + init(); + + compilerTextLabel.setText(compilerTextLabel.getText() + " - " + JetPluginUtil.getPluginVersion()); + + copyIntoPanel = new CopyIntoPanel(project, defaultPath); + copyIntoPanel.addValidityListener(new ValidityListener() { + @Override + public void validityChanged(boolean isValid) { + updateComponents(); + } + }); + + copyIntoPanelPlace.add(copyIntoPanel.getContentPane(), BorderLayout.CENTER); + + copyLibraryCheckbox.addActionListener(new ActionListener() { + @Override + public void actionPerformed(@NotNull ActionEvent e) { + updateComponents(); + } + }); + } + + protected void updateComponents() { + copyIntoPanel.setEnabled(copyLibraryCheckbox.isSelected()); + setOKActionEnabled(!copyIntoPanel.hasErrors()); + } + + @Nullable + public String getCopyIntoPath() { + return copyLibraryCheckbox.isSelected() ? copyIntoPanel.getPath() : null; + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + return contentPane; + } + +} diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogWithModules.java b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogWithModules.java new file mode 100644 index 00000000000..abb1d6a2075 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaLibraryDialogWithModules.java @@ -0,0 +1,57 @@ +/* + * 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.framework.ui; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; +import java.awt.*; +import java.util.List; + +public class CreateJavaLibraryDialogWithModules extends CreateJavaLibraryDialogBase { + + private final ChooseModulePanel chooseModulePanel; + + public CreateJavaLibraryDialogWithModules( + @NotNull Project project, + @NotNull List modules, + @NotNull String defaultPath, + boolean showPathPanel + ) { + super(project, defaultPath); + + chooseModulePanel = new ChooseModulePanel(project, modules); + chooseModulesPanelPlace.add(chooseModulePanel.getContentPane(), BorderLayout.CENTER); + + if (!showPathPanel) { + copyIntoPanelPlace.setVisible(false); + copyLibraryCheckbox.setVisible(false); + } + else { + chooseModulePanel.showSeparator(); + } + + updateComponents(); + } + + public List getModulesToConfigure() { + return chooseModulePanel.getModulesToConfigure(); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialog.java b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialog.java index 212233cff6a..8547a684c5b 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialog.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialog.java @@ -16,92 +16,18 @@ package org.jetbrains.jet.plugin.framework.ui; -import com.intellij.openapi.project.Project; -import com.intellij.openapi.ui.DialogWrapper; -import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.plugin.JetPluginUtil; import org.jetbrains.jet.plugin.framework.JSLibraryCreateOptions; -import javax.swing.*; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class CreateJavaScriptLibraryDialog extends DialogWrapper implements JSLibraryCreateOptions { - private final CopyIntoPanel copyJSIntoPanel; - private final CopyIntoPanel copyLibraryIntoPanel; - - private JPanel contentPane; - private JCheckBox copyLibraryCheckbox; - private JCheckBox copyJSRuntimeCheckbox; - private JPanel copyJSIntoPanelPlace; - private JPanel copyHeadersIntoPanelPlace; - private JLabel compilerTextLabel; - - public CreateJavaScriptLibraryDialog(@Nullable Project project, @NotNull String title, VirtualFile contextDirectory) { - super(project); - - setTitle(title); - - init(); - - compilerTextLabel.setText(compilerTextLabel.getText() + " - " + JetPluginUtil.getPluginVersion()); - - copyJSIntoPanel = new CopyIntoPanel(project, FileUIUtils.createRelativePath(project, contextDirectory, "script"), "Script directory:"); - copyJSIntoPanel.addValidityListener(new ValidityListener() { - @Override - public void validityChanged(boolean isValid) { - updateComponents(); - } - }); - copyJSIntoPanelPlace.add(copyJSIntoPanel.getContentPane(), BorderLayout.CENTER); - - copyLibraryIntoPanel = new CopyIntoPanel(project, FileUIUtils.createRelativePath(project, contextDirectory, "lib"), "&Lib directory:"); - copyLibraryIntoPanel.addValidityListener(new ValidityListener() { - @Override - public void validityChanged(boolean isValid) { - updateComponents(); - } - }); - copyHeadersIntoPanelPlace.add(copyLibraryIntoPanel.getContentPane(), BorderLayout.CENTER); - - ActionListener updateComponentsListener = new ActionListener() { - @Override - public void actionPerformed(@NotNull ActionEvent e) { - updateComponents(); - } - }; - - copyLibraryCheckbox.addActionListener(updateComponentsListener); - copyJSRuntimeCheckbox.addActionListener(updateComponentsListener); +public class CreateJavaScriptLibraryDialog extends CreateJavaScriptLibraryDialogBase implements JSLibraryCreateOptions { + public CreateJavaScriptLibraryDialog( + @NotNull String defaultPathToJar, + @NotNull String defaultPathToJsFile, + boolean showPathToJarPanel, + boolean showPathToJsFilePanel + ) { + super(null, defaultPathToJar, defaultPathToJsFile, showPathToJarPanel, showPathToJsFilePanel); updateComponents(); } - - @Override - @Nullable - public String getCopyJsIntoPath() { - return copyJSIntoPanel.getPath(); - } - - @Override - @Nullable - public String getCopyLibraryIntoPath() { - return copyLibraryIntoPanel.getPath(); - } - - private void updateComponents() { - copyLibraryIntoPanel.setEnabled(copyLibraryCheckbox.isSelected()); - copyJSIntoPanel.setEnabled(copyJSRuntimeCheckbox.isSelected()); - - setOKActionEnabled(!(copyJSIntoPanel.hasErrors() || copyLibraryIntoPanel.hasErrors())); - } - - @Nullable - @Override - protected JComponent createCenterPanel() { - return contentPane; - } } diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialog.form b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogBase.form similarity index 81% rename from idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialog.form rename to idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogBase.form index 571603b46b8..7ac8871c90b 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialog.form +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogBase.form @@ -1,6 +1,6 @@ - - + + @@ -10,18 +10,18 @@ - + - + - + @@ -30,7 +30,7 @@ - + @@ -39,7 +39,7 @@ - + @@ -47,7 +47,7 @@ - + @@ -65,6 +65,14 @@ + + + + + + + + diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogBase.java b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogBase.java new file mode 100644 index 00000000000..1446969d132 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogBase.java @@ -0,0 +1,119 @@ +/* + * 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.framework.ui; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.ui.DialogWrapper; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.plugin.JetPluginUtil; +import org.jetbrains.jet.plugin.framework.JSLibraryCreateOptions; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +public abstract class CreateJavaScriptLibraryDialogBase extends DialogWrapper implements JSLibraryCreateOptions { + protected final CopyIntoPanel copyJsFilesPanel; + protected final CopyIntoPanel copyJarPanel; + + protected JPanel contentPane; + protected JCheckBox copyJarCheckbox; + protected JCheckBox copyJsFilesCheckbox; + protected JPanel copyJsFilesPanelPlace; + protected JPanel copyJarFilePanelPlace; + protected JLabel compilerTextLabel; + protected JPanel chooseModulesPanelPlace; + + public CreateJavaScriptLibraryDialogBase( + @Nullable Project project, + @NotNull String defaultPathToJar, + @NotNull String defaultPathToJsFile, + boolean showPathToJarPanel, + boolean showPathToJsFilePanel + ) { + super(project); + + setTitle("Create Kotlin JavaScript Library"); + + init(); + + compilerTextLabel.setText(compilerTextLabel.getText() + " - " + JetPluginUtil.getPluginVersion()); + + ValidityListener validityListener = new ValidityListener() { + @Override + public void validityChanged(boolean isValid) { + updateComponents(); + } + }; + + copyJsFilesPanel = new CopyIntoPanel(project, defaultPathToJsFile, "Script directory:"); + copyJsFilesPanel.addValidityListener(validityListener); + copyJsFilesPanelPlace.add(copyJsFilesPanel.getContentPane(), BorderLayout.CENTER); + + copyJarPanel = new CopyIntoPanel(project, defaultPathToJar, "&Lib directory:"); + copyJarPanel.addValidityListener(validityListener); + copyJarFilePanelPlace.add(copyJarPanel.getContentPane(), BorderLayout.CENTER); + + if (!showPathToJarPanel) { + copyJarFilePanelPlace.setVisible(false); + copyJarCheckbox.setVisible(false); + } + + if (!showPathToJsFilePanel) { + copyJsFilesPanelPlace.setVisible(false); + copyJsFilesCheckbox.setVisible(false); + } + + ActionListener updateComponentsListener = new ActionListener() { + @Override + public void actionPerformed(@NotNull ActionEvent e) { + updateComponents(); + } + }; + + copyJarCheckbox.addActionListener(updateComponentsListener); + copyJsFilesCheckbox.addActionListener(updateComponentsListener); + } + + @Override + @Nullable + public String getCopyJsIntoPath() { + if (!copyJsFilesCheckbox.isSelected()) return null; + return copyJsFilesPanel.getPath(); + } + + @Override + @Nullable + public String getCopyLibraryIntoPath() { + return copyJarCheckbox.isSelected() ? copyJarPanel.getPath() : null; + } + + protected void updateComponents() { + copyJarPanel.setEnabled(copyJarCheckbox.isSelected()); + copyJsFilesPanel.setEnabled(copyJsFilesCheckbox.isSelected()); + + setOKActionEnabled(!copyJsFilesPanel.hasErrors() && !copyJarPanel.hasErrors()); + } + + @Nullable + @Override + protected JComponent createCenterPanel() { + return contentPane; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogWithModules.java b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogWithModules.java new file mode 100644 index 00000000000..a0440a12510 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/CreateJavaScriptLibraryDialogWithModules.java @@ -0,0 +1,54 @@ +/* + * 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.framework.ui; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.project.Project; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.plugin.framework.JSLibraryCreateOptions; + +import java.awt.*; +import java.util.List; + +public class CreateJavaScriptLibraryDialogWithModules extends CreateJavaScriptLibraryDialogBase implements JSLibraryCreateOptions { + + private final ChooseModulePanel chooseModulePanel; + + public CreateJavaScriptLibraryDialogWithModules( + @NotNull Project project, + @NotNull List modules, + @NotNull String defaultPathToJar, + @NotNull String defaultPathToJsFile, + boolean showPathToJarPanel, + boolean showPathToJsFilePanel + ) { + super(project, defaultPathToJar, defaultPathToJsFile, showPathToJarPanel, showPathToJsFilePanel); + + chooseModulePanel = new ChooseModulePanel(project, modules); + chooseModulesPanelPlace.add(chooseModulePanel.getContentPane(), BorderLayout.CENTER); + + if (showPathToJarPanel || showPathToJsFilePanel) { + chooseModulePanel.showSeparator(); + } + + updateComponents(); + } + + public List getModulesToConfigure() { + return chooseModulePanel.getModulesToConfigure(); + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/framework/ui/FileUIUtils.java b/idea/src/org/jetbrains/jet/plugin/framework/ui/FileUIUtils.java index 53a26011b51..3b175e26e42 100644 --- a/idea/src/org/jetbrains/jet/plugin/framework/ui/FileUIUtils.java +++ b/idea/src/org/jetbrains/jet/plugin/framework/ui/FileUIUtils.java @@ -43,11 +43,11 @@ public class FileUIUtils { @Nullable public static File copyWithOverwriteDialog( - @NotNull Component parent, @NotNull String messagesTitle, @NotNull String destinationFolder, - @NotNull File file) { - Map copiedFiles = copyWithOverwriteDialog(parent, messagesTitle, ImmutableMap.of(file, destinationFolder)); + @NotNull File file + ) { + Map copiedFiles = copyWithOverwriteDialog(messagesTitle, ImmutableMap.of(file, destinationFolder)); if (copiedFiles == null) { return null; } @@ -60,7 +60,6 @@ public class FileUIUtils { @Nullable public static Map copyWithOverwriteDialog( - @NotNull Component parent, @NotNull String messagesTitle, @NotNull Map filesWithDestinations ) { @@ -131,7 +130,7 @@ public class FileUIUtils { LocalFileSystem.getInstance().refreshAndFindFileByIoFile(sourceToTarget.getValue()); } catch (IOException e) { - Messages.showErrorDialog(parent, "Error with copy file " + sourceToTarget.getKey().getName(), messagesTitle + ". Error"); + Messages.showErrorDialog("Error with copy file " + sourceToTarget.getKey().getName(), messagesTitle + ". Error"); return null; } } diff --git a/idea/testData/configuration/jsLibrary/module1.iml b/idea/testData/configuration/jsLibrary/module1.iml new file mode 100644 index 00000000000..72749645ae1 --- /dev/null +++ b/idea/testData/configuration/jsLibrary/module1.iml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/idea/testData/configuration/jsLibrary/projectFile.ipr b/idea/testData/configuration/jsLibrary/projectFile.ipr new file mode 100644 index 00000000000..85479678f10 --- /dev/null +++ b/idea/testData/configuration/jsLibrary/projectFile.ipr @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/idea/testData/configuration/jsLibraryWithoutPaths/module1.iml b/idea/testData/configuration/jsLibraryWithoutPaths/module1.iml new file mode 100644 index 00000000000..72749645ae1 --- /dev/null +++ b/idea/testData/configuration/jsLibraryWithoutPaths/module1.iml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/idea/testData/configuration/jsLibraryWithoutPaths/projectFile.ipr b/idea/testData/configuration/jsLibraryWithoutPaths/projectFile.ipr new file mode 100644 index 00000000000..bcccccf0007 --- /dev/null +++ b/idea/testData/configuration/jsLibraryWithoutPaths/projectFile.ipr @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/idea/testData/configuration/library/module1.iml b/idea/testData/configuration/library/module1.iml new file mode 100644 index 00000000000..c7649d2d5da --- /dev/null +++ b/idea/testData/configuration/library/module1.iml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/idea/testData/configuration/library/projectFile.ipr b/idea/testData/configuration/library/projectFile.ipr new file mode 100644 index 00000000000..94cd3996705 --- /dev/null +++ b/idea/testData/configuration/library/projectFile.ipr @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/idea/testData/configuration/libraryWithoutPaths/module1.iml b/idea/testData/configuration/libraryWithoutPaths/module1.iml new file mode 100644 index 00000000000..c7649d2d5da --- /dev/null +++ b/idea/testData/configuration/libraryWithoutPaths/module1.iml @@ -0,0 +1,7 @@ + + + + + + + diff --git a/idea/testData/configuration/libraryWithoutPaths/projectFile.ipr b/idea/testData/configuration/libraryWithoutPaths/projectFile.ipr new file mode 100644 index 00000000000..0884c3d943c --- /dev/null +++ b/idea/testData/configuration/libraryWithoutPaths/projectFile.ipr @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + diff --git a/idea/testData/configuration/newLibrary/module1.iml b/idea/testData/configuration/newLibrary/module1.iml new file mode 100644 index 00000000000..5383975ec6e --- /dev/null +++ b/idea/testData/configuration/newLibrary/module1.iml @@ -0,0 +1,5 @@ + + + + + diff --git a/idea/testData/configuration/newLibrary/projectFile.ipr b/idea/testData/configuration/newLibrary/projectFile.ipr new file mode 100644 index 00000000000..f31a10aa042 --- /dev/null +++ b/idea/testData/configuration/newLibrary/projectFile.ipr @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/idea/testData/configuration/twoModules/module1.iml b/idea/testData/configuration/twoModules/module1.iml new file mode 100644 index 00000000000..0c6965c378c --- /dev/null +++ b/idea/testData/configuration/twoModules/module1.iml @@ -0,0 +1,5 @@ + + + + + diff --git a/idea/testData/configuration/twoModules/module2.iml b/idea/testData/configuration/twoModules/module2.iml new file mode 100644 index 00000000000..0c6965c378c --- /dev/null +++ b/idea/testData/configuration/twoModules/module2.iml @@ -0,0 +1,5 @@ + + + + + diff --git a/idea/testData/configuration/twoModules/projectFile.ipr b/idea/testData/configuration/twoModules/projectFile.ipr new file mode 100644 index 00000000000..7a8b42e3b56 --- /dev/null +++ b/idea/testData/configuration/twoModules/projectFile.ipr @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/idea/tests/org/jetbrains/jet/plugin/JetStdJSProjectDescriptor.java b/idea/tests/org/jetbrains/jet/plugin/JetStdJSProjectDescriptor.java index 14d505b356f..eca8fac8a48 100644 --- a/idea/tests/org/jetbrains/jet/plugin/JetStdJSProjectDescriptor.java +++ b/idea/tests/org/jetbrains/jet/plugin/JetStdJSProjectDescriptor.java @@ -25,10 +25,9 @@ import com.intellij.openapi.roots.ModifiableRootModel; import com.intellij.openapi.roots.libraries.NewLibraryConfiguration; import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor; import com.intellij.testFramework.LightProjectDescriptor; -import org.jetbrains.jet.plugin.framework.JSLibraryCreateOptions; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.plugin.framework.JSLibraryStdDescription; import org.jetbrains.jet.testing.ConfigLibraryUtil; -import org.jetbrains.jet.utils.PathUtil; public class JetStdJSProjectDescriptor implements LightProjectDescriptor { public static final JetStdJSProjectDescriptor INSTANCE = new JetStdJSProjectDescriptor(); @@ -44,9 +43,8 @@ public class JetStdJSProjectDescriptor implements LightProjectDescriptor { } @Override - public void configureModule(Module module, ModifiableRootModel model, ContentEntry contentEntry) { - NewLibraryConfiguration configuration = new JSLibraryStdDescription().createNewLibrary( - null, PathUtil.getKotlinPathsForDistDirectory(), JSLibraryCreateOptions.DEFAULT); + public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, ContentEntry contentEntry) { + NewLibraryConfiguration configuration = new JSLibraryStdDescription().createNewLibraryForTests(); assert configuration != null : "Configuration should exist"; diff --git a/idea/tests/org/jetbrains/jet/plugin/configuration/ConfigureKotlinTest.java b/idea/tests/org/jetbrains/jet/plugin/configuration/ConfigureKotlinTest.java new file mode 100644 index 00000000000..b24c19f4f47 --- /dev/null +++ b/idea/tests/org/jetbrains/jet/plugin/configuration/ConfigureKotlinTest.java @@ -0,0 +1,225 @@ +package org.jetbrains.jet.plugin.configuration; + +import com.intellij.openapi.module.Module; +import com.intellij.openapi.module.ModuleManager; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.testFramework.PlatformTestCase; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.utils.PathUtil; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; + +import static org.jetbrains.jet.plugin.configuration.KotlinWithLibraryConfigurator.FileState; +import static org.jetbrains.jet.plugin.configuration.KotlinWithLibraryConfigurator.LibraryState; + +public class ConfigureKotlinTest extends PlatformTestCase { + private static final String BASE_PATH = "idea/testData/configuration/"; + private static final KotlinJavaModuleConfigurator JAVA_CONFIGURATOR = new KotlinJavaModuleConfigurator(); + private static final KotlinJsModuleConfigurator JS_CONFIGURATOR = new KotlinJsModuleConfigurator(); + + public void testNewLibrary_copyJar() { + doTestOneJavaModule(FileState.COPY, LibraryState.NEW_LIBRARY); + } + + public void testNewLibrary_doNotCopyJar() { + doTestOneJavaModule(FileState.DO_NOT_COPY, LibraryState.NEW_LIBRARY); + } + + public void testLibrary_doNotCopyJar() { + try { + doTestOneJavaModule(FileState.DO_NOT_COPY, LibraryState.LIBRARY); + } + catch (IllegalStateException e) { + return; + } + fail("Test should throw IllegalStateException"); + } + + public void testLibraryWithoutPaths_jarExists() { + doTestOneJavaModule(FileState.EXISTS, LibraryState.NON_CONFIGURED_LIBRARY); + } + + public void testNewLibrary_jarExists() { + doTestOneJavaModule(FileState.EXISTS, LibraryState.NEW_LIBRARY); + } + + public void testLibraryWithoutPaths_copyJar() { + doTestOneJavaModule(FileState.COPY, LibraryState.NON_CONFIGURED_LIBRARY); + } + + public void testLibraryWithoutPaths_doNotCopyJar() { + doTestOneJavaModule(FileState.DO_NOT_COPY, LibraryState.NON_CONFIGURED_LIBRARY); + } + + @SuppressWarnings("ConstantConditions") + public void testTwoModules_exists() { + Module[] modules = getModules(); + for (Module module : modules) { + if (module.getName().equals("module1")) { + configure(module, KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY, LibraryState.NEW_LIBRARY, JAVA_CONFIGURATOR); + assertTrue("Module " + module.getName() + " should be configured", JAVA_CONFIGURATOR.isConfigured(module)); + } + else if (module.getName().equals("module2")) { + assertFalse("Module " + module.getName() + " should not be configured", JAVA_CONFIGURATOR.isConfigured(module)); + configure(module, FileState.EXISTS, LibraryState.LIBRARY, JAVA_CONFIGURATOR); + assertTrue("Module " + module.getName() + " should be configured", JAVA_CONFIGURATOR.isConfigured(module)); + } + } + } + + public void testNewLibrary_jarExists_js() { + doTestOneJsModule(FileState.EXISTS, LibraryState.NEW_LIBRARY); + } + + public void testNewLibrary_copyJar_js() { + doTestOneJsModule(FileState.COPY, LibraryState.NEW_LIBRARY); + } + + public void testNewLibrary_doNotCopyJar_js() { + doTestOneJsModule(FileState.DO_NOT_COPY, LibraryState.NEW_LIBRARY); + } + + public void testJsLibrary_doNotCopyJar() { + try { + doTestOneJsModule(FileState.DO_NOT_COPY, LibraryState.LIBRARY); + } + catch (IllegalStateException e) { + return; + } + fail("Test should throw IllegalStateException"); + } + + public void testJsLibraryWithoutPaths_jarExists() { + doTestOneJsModule(FileState.EXISTS, LibraryState.NON_CONFIGURED_LIBRARY); + } + + public void testJsLibraryWithoutPaths_copyJar() { + doTestOneJsModule(FileState.COPY, LibraryState.NON_CONFIGURED_LIBRARY); + } + + public void testJsLibraryWithoutPaths_doNotCopyJar() { + doTestOneJsModule(FileState.DO_NOT_COPY, LibraryState.NON_CONFIGURED_LIBRARY); + } + + private void doTestOneJavaModule(@NotNull FileState jarState, @NotNull LibraryState libraryState) { + doTestOneModule(jarState, libraryState, JAVA_CONFIGURATOR); + assertFalse("Module " + getModule().getName() + " should not be configured as JavaScript Module", + JS_CONFIGURATOR.isConfigured(getModule())); + } + + private void doTestOneJsModule(@NotNull FileState jarState, @NotNull LibraryState libraryState) { + doTestOneModule(jarState, libraryState, JS_CONFIGURATOR); + assertFalse("Module " + getModule().getName() + " should not be configured as Java Module", + JAVA_CONFIGURATOR.isConfigured(getModule())); + } + + private void doTestOneModule(@NotNull FileState jarState, @NotNull LibraryState libraryState, @NotNull KotlinWithLibraryConfigurator configurator) { + Module module = getModule(); + assertEquals("Library state loaded from project files should be " + libraryState, libraryState, configurator.getLibraryState(module.getProject())); + assertFalse("Module " + module.getName() + " should not be configured", configurator.isConfigured(module)); + configure(module, jarState, libraryState, configurator); + assertTrue("Module " + module.getName() + " should be configured", configurator.isConfigured(getModule())); + } + + private static void configure( + @NotNull List modules, + @NotNull FileState runtimeState, + @NotNull LibraryState libraryState, + @NotNull KotlinWithLibraryConfigurator configurator, + @NotNull String jarFromDist, + @NotNull String jarFromTemp + ) { + for (Module module : modules) { + String pathToJar = getPathToJar(runtimeState, jarFromDist, jarFromTemp); + configurator.configureModuleWithLibrary(module, libraryState, runtimeState, pathToJar); + } + } + + @Nullable + private static String getPathToJar(@NotNull FileState runtimeState, @NotNull String jarFromDist, @NotNull String jarFromTemp) { + switch (runtimeState) { + case EXISTS: + return jarFromDist; + case COPY: + return jarFromTemp; + case DO_NOT_COPY: + return null; + } + return null; + } + + private static void configure(@NotNull Module module, @NotNull FileState jarState, @NotNull LibraryState libraryState, @NotNull KotlinProjectConfigurator configurator) { + if (configurator instanceof KotlinJavaModuleConfigurator) { + configure(Collections.singletonList(module), jarState, libraryState, + (KotlinWithLibraryConfigurator) configurator, + getPathToExistentRuntimeJar(), getPathToNonexistentRuntimeJar()); + } + if (configurator instanceof KotlinJsModuleConfigurator) { + configure(Collections.singletonList(module), jarState, libraryState, + (KotlinWithLibraryConfigurator) configurator, + getPathToExistentJsJar(), getPathToNonexistentJsJar()); + } + } + + private static String getPathToNonexistentRuntimeJar() { + String pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.KOTLIN_JAVA_RUNTIME_JAR; + myFilesToDelete.add(new File(pathToTempKotlinRuntimeJar)); + return pathToTempKotlinRuntimeJar; + } + + private static String getPathToNonexistentJsJar() { + String pathToTempKotlinRuntimeJar = FileUtil.getTempDirectory() + "/" + PathUtil.JS_LIB_JAR_NAME; + myFilesToDelete.add(new File(pathToTempKotlinRuntimeJar)); + return pathToTempKotlinRuntimeJar; + } + + private static String getPathToExistentRuntimeJar() { + return PathUtil.getKotlinPathsForDistDirectory().getRuntimePath().getParent(); + } + + private static String getPathToExistentJsJar() { + return PathUtil.getKotlinPathsForDistDirectory().getJsLibJarPath().getParent(); + } + + @Override + public Module getModule() { + Module[] modules = ModuleManager.getInstance(myProject).getModules(); + assert modules.length == 1 : "One module should be loaded " + modules.length; + myModule = modules[0]; + return super.getModule(); + } + + public Module[] getModules() { + return ModuleManager.getInstance(myProject).getModules(); + } + + @Override + protected File getIprFile() throws IOException { + String projectName = getProjectName(); + String projectFilePath = BASE_PATH + projectName + "/projectFile.ipr"; + assertTrue("Project file should exists " + projectFilePath, new File(projectFilePath).exists()); + return new File(projectFilePath); + } + + @Override + protected Project doCreateProject(File projectFile) throws Exception { + return myProjectManager.loadProject(projectFile.getPath()); + } + + private String getProjectName() { + String testName = getTestName(true); + if (testName.contains("_")) { + return testName.substring(0, testName.indexOf("_")); + } + return testName; + } + + @Override + protected void setUpModule() { + } +}