KotlinWithLibraryConfigurator: J2K

This commit is contained in:
Dmitry Jemerov
2017-03-30 17:42:38 +02:00
parent 2059a052c9
commit 00d3141ba2
2 changed files with 349 additions and 420 deletions
@@ -114,6 +114,6 @@ public class KotlinJavaModuleConfigurator extends KotlinWithLibraryConfigurator
} }
public static KotlinJavaModuleConfigurator getInstance() { public static KotlinJavaModuleConfigurator getInstance() {
return Extensions.findExtension(Companion.getEP_NAME(), KotlinJavaModuleConfigurator.class); return Extensions.findExtension(KotlinProjectConfigurator.Companion.getEP_NAME(), KotlinJavaModuleConfigurator.class);
} }
} }
@@ -14,587 +14,516 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlin.idea.configuration; package org.jetbrains.kotlin.idea.configuration
import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.module.Module; import com.intellij.openapi.module.Module
import com.intellij.openapi.module.ModuleManager; import com.intellij.openapi.module.ModuleManager
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.*
import com.intellij.openapi.roots.libraries.Library; 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.libraries.LibraryTablesRegistrar; import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainer; import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory
import com.intellij.openapi.roots.ui.configuration.projectRoot.LibrariesContainerFactory; import com.intellij.openapi.ui.Messages
import com.intellij.openapi.ui.Messages; import com.intellij.openapi.util.Ref
import com.intellij.openapi.util.Ref; import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.vfs.VfsUtil; import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.util.Processor
import com.intellij.openapi.vfs.VirtualFile; import org.jetbrains.annotations.Contract
import com.intellij.util.Processor; import org.jetbrains.kotlin.idea.KotlinPluginUtil
import org.jetbrains.annotations.Contract; import org.jetbrains.kotlin.idea.framework.ui.CreateLibraryDialogWithModules
import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.framework.ui.FileUIUtils
import org.jetbrains.annotations.Nullable; import java.io.File
import org.jetbrains.kotlin.idea.KotlinPluginUtil; import java.util.*
import org.jetbrains.kotlin.idea.framework.ui.CreateLibraryDialogWithModules;
import org.jetbrains.kotlin.idea.framework.ui.FileUIUtils;
import java.io.File; abstract class KotlinWithLibraryConfigurator internal constructor() : KotlinProjectConfigurator {
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
public abstract class KotlinWithLibraryConfigurator implements KotlinProjectConfigurator { protected abstract val libraryName: String
public static final String DEFAULT_LIBRARY_DIR = "lib";
@NotNull protected abstract val messageForOverrideDialog: String
protected abstract String getLibraryName();
@NotNull protected abstract val dialogTitle: String
protected abstract String getMessageForOverrideDialog();
@NotNull protected abstract val libraryCaption: String
protected abstract String getDialogTitle();
@NotNull abstract val existingJarFiles: RuntimeLibraryFiles
protected abstract String getLibraryCaption();
@NotNull protected abstract fun getOldSourceRootUrl(library: Library): String?
public abstract RuntimeLibraryFiles getExistingJarFiles();
@Nullable override fun getStatus(module: Module): ConfigureKotlinStatus {
protected abstract String getOldSourceRootUrl(@NotNull Library library);
@NotNull
@Override
public ConfigureKotlinStatus getStatus(@NotNull Module module) {
if (!isApplicable(module)) { if (!isApplicable(module)) {
return ConfigureKotlinStatus.NON_APPLICABLE; return ConfigureKotlinStatus.NON_APPLICABLE
} }
if (isConfigured(module)) { if (isConfigured(module)) {
return ConfigureKotlinStatus.CONFIGURED; return ConfigureKotlinStatus.CONFIGURED
} }
return ConfigureKotlinStatus.CAN_BE_CONFIGURED; return ConfigureKotlinStatus.CAN_BE_CONFIGURED
} }
protected static boolean isApplicable(@NotNull Module module) { abstract fun isConfigured(module: Module): Boolean
return !KotlinPluginUtil.isAndroidGradleModule(module) &&
!KotlinPluginUtil.isMavenModule(module) &&
!KotlinPluginUtil.isGradleModule(module);
}
protected abstract boolean isConfigured(@NotNull Module module); @JvmSuppressWildcards
override fun configure(project: Project, excludeModules: Collection<Module>) {
val defaultPathToJar = getDefaultPathToJarFile(project)
val showPathToJarPanel = needToChooseJarPath(project)
@Override var nonConfiguredModules = if (!ApplicationManager.getApplication().isUnitTestMode)
public void configure(@NotNull Project project, Collection<Module> excludeModules) { getNonConfiguredModules(project, this)
String defaultPathToJar = getDefaultPathToJarFile(project); else
boolean showPathToJarPanel = needToChooseJarPath(project); Arrays.asList(*ModuleManager.getInstance(project).modules)
nonConfiguredModules -= excludeModules
List<Module> nonConfiguredModules = var modulesToConfigure = nonConfiguredModules
!ApplicationManager.getApplication().isUnitTestMode() ? var copyLibraryIntoPath: String? = null
ConfigureKotlinInProjectUtilsKt.getNonConfiguredModules(project, this) :
Arrays.asList(ModuleManager.getInstance(project).getModules());
nonConfiguredModules.removeAll(excludeModules);
List<Module> modulesToConfigure = nonConfiguredModules; if (nonConfiguredModules.size > 1 || showPathToJarPanel) {
String copyLibraryIntoPath = null; val dialog = CreateLibraryDialogWithModules(
if (nonConfiguredModules.size() > 1 || showPathToJarPanel) {
CreateLibraryDialogWithModules dialog = new CreateLibraryDialogWithModules(
project, this, defaultPathToJar, showPathToJarPanel, project, this, defaultPathToJar, showPathToJarPanel,
getDialogTitle(), dialogTitle,
getLibraryCaption(), libraryCaption,
excludeModules); excludeModules)
if (!ApplicationManager.getApplication().isUnitTestMode()) { if (!ApplicationManager.getApplication().isUnitTestMode) {
dialog.show(); dialog.show()
if (!dialog.isOK()) return; if (!dialog.isOK) return
} }
else { else {
dialog.close(0); dialog.close(0)
} }
modulesToConfigure = dialog.getModulesToConfigure(); modulesToConfigure = dialog.modulesToConfigure
copyLibraryIntoPath = dialog.getCopyIntoPath(); copyLibraryIntoPath = dialog.copyIntoPath
} }
List<Module> finalModulesToConfigure = modulesToConfigure; val finalModulesToConfigure = modulesToConfigure
String finalCopyLibraryIntoPath = copyLibraryIntoPath; val finalCopyLibraryIntoPath = copyLibraryIntoPath
NotificationMessageCollector collector = NotificationMessageCollectorKt.createConfigureKotlinNotificationCollector(project); val collector = createConfigureKotlinNotificationCollector(project)
for (Module module : finalModulesToConfigure) { for (module in finalModulesToConfigure) {
configureModuleWithLibrary(module, defaultPathToJar, finalCopyLibraryIntoPath, collector); configureModuleWithLibrary(module, defaultPathToJar, finalCopyLibraryIntoPath, collector)
} }
collector.showNotification(); collector.showNotification()
} }
public void configureSilently(@NotNull Project project) { fun configureSilently(project: Project) {
String defaultPathToJar = getDefaultPathToJarFile(project); val defaultPathToJar = getDefaultPathToJarFile(project)
NotificationMessageCollector collector = NotificationMessageCollectorKt.createConfigureKotlinNotificationCollector(project); val collector = createConfigureKotlinNotificationCollector(project)
for (Module module : ModuleManager.getInstance(project).getModules()) { for (module in ModuleManager.getInstance(project).modules) {
configureModuleWithLibrary(module, defaultPathToJar, null, collector); configureModuleWithLibrary(module, defaultPathToJar, null, collector)
} }
} }
protected void configureModuleWithLibrary( protected fun configureModuleWithLibrary(
@NotNull Module module, module: Module,
@NotNull String defaultPath, defaultPath: String,
@Nullable String pathFromDialog, pathFromDialog: String?,
@NotNull NotificationMessageCollector collector collector: NotificationMessageCollector
) { ) {
Project project = module.getProject(); val project = module.project
RuntimeLibraryFiles files = getExistingJarFiles(); val files = existingJarFiles
LibraryState libraryState = getLibraryState(project); val libraryState = getLibraryState(project)
String dirToCopyJar = getPathToCopyFileTo(project, OrderRootType.CLASSES, defaultPath, pathFromDialog); val dirToCopyJar = getPathToCopyFileTo(project, OrderRootType.CLASSES, defaultPath, pathFromDialog)
FileState runtimeState = val runtimeState = getJarState(project, files.getRuntimeDestination(dirToCopyJar), OrderRootType.CLASSES, pathFromDialog == null)
getJarState(project, files.getRuntimeDestination(dirToCopyJar), OrderRootType.CLASSES, pathFromDialog == null);
configureModuleWithLibraryClasses(module, libraryState, runtimeState, dirToCopyJar, collector); configureModuleWithLibraryClasses(module, libraryState, runtimeState, dirToCopyJar, collector)
Library library = getKotlinLibrary(project); val library = getKotlinLibrary(project) ?: return
if (library == null) return; val dirToCopySourcesJar = getPathToCopyFileTo(project, OrderRootType.SOURCES, defaultPath, pathFromDialog)
val sourcesState = getJarState(project, files.getRuntimeSourcesDestination(dirToCopySourcesJar), OrderRootType.SOURCES,
pathFromDialog == null)
String dirToCopySourcesJar = getPathToCopyFileTo(project, OrderRootType.SOURCES, defaultPath, pathFromDialog); configureModuleWithLibrarySources(library, sourcesState, dirToCopySourcesJar, collector)
FileState sourcesState = getJarState(project, files.getRuntimeSourcesDestination(dirToCopySourcesJar), OrderRootType.SOURCES,
pathFromDialog == null);
configureModuleWithLibrarySources(library, sourcesState, dirToCopySourcesJar, collector);
} }
protected void configureModuleWithLibraryClasses( fun configureModuleWithLibraryClasses(
@NotNull Module module, module: Module,
@NotNull LibraryState libraryState, libraryState: LibraryState,
@NotNull FileState jarState, jarState: FileState,
@NotNull String dirToCopyJarTo, dirToCopyJarTo: String,
@NotNull NotificationMessageCollector collector collector: NotificationMessageCollector
) { ) {
Project project = module.getProject(); val project = module.project
RuntimeLibraryFiles files = getExistingJarFiles(); val files = existingJarFiles
File runtimeJar = files.getRuntimeJar(); val runtimeJar = files.runtimeJar
File reflectJar = files.getReflectJar(); val reflectJar = files.reflectJar
switch (libraryState) { when (libraryState) {
case LIBRARY: KotlinWithLibraryConfigurator.LibraryState.LIBRARY -> when (jarState) {
switch (jarState) { KotlinWithLibraryConfigurator.FileState.EXISTS -> {
case EXISTS: { }
break; KotlinWithLibraryConfigurator.FileState.COPY -> {
} copyFileToDir(runtimeJar, dirToCopyJarTo, collector)
case COPY: { if (reflectJar != null) {
copyFileToDir(runtimeJar, dirToCopyJarTo, collector); copyFileToDir(reflectJar, dirToCopyJarTo, collector)
if (reflectJar != null) {
copyFileToDir(reflectJar, dirToCopyJarTo, collector);
}
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; KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> {
case NON_CONFIGURED_LIBRARY: throw IllegalStateException(
switch (jarState) { "Kotlin library exists, so path to copy should be hidden in configuration dialog and jar should be copied using path in library table")
case EXISTS: {
addJarsToExistingLibrary(
project, files.getRuntimeDestination(dirToCopyJarTo), files.getReflectDestination(dirToCopyJarTo), collector
);
break;
}
case COPY: {
File copiedRuntimeJar = copyFileToDir(runtimeJar, dirToCopyJarTo, collector);
File copiedReflectJar = copyFileToDir(reflectJar, dirToCopyJarTo, collector);
addJarsToExistingLibrary(project, copiedRuntimeJar, copiedReflectJar, collector);
break;
}
case DO_NOT_COPY: {
addJarsToExistingLibrary(project, runtimeJar, reflectJar, collector);
break;
}
} }
break; }
case NEW_LIBRARY: KotlinWithLibraryConfigurator.LibraryState.NON_CONFIGURED_LIBRARY -> when (jarState) {
switch (jarState) { KotlinWithLibraryConfigurator.FileState.EXISTS -> {
case EXISTS: { addJarsToExistingLibrary(
addJarsToNewLibrary( project, files.getRuntimeDestination(dirToCopyJarTo), files.getReflectDestination(dirToCopyJarTo), collector
project, files.getRuntimeDestination(dirToCopyJarTo), files.getReflectDestination(dirToCopyJarTo), collector )
);
break;
}
case COPY: {
File copiedRuntimeJar = copyFileToDir(runtimeJar, dirToCopyJarTo, collector);
File copiedReflectJar = copyFileToDir(reflectJar, dirToCopyJarTo, collector);
addJarsToNewLibrary(project, copiedRuntimeJar, copiedReflectJar, collector);
break;
}
case DO_NOT_COPY: {
addJarsToNewLibrary(project, runtimeJar, reflectJar, collector);
break;
}
} }
break; KotlinWithLibraryConfigurator.FileState.COPY -> {
val copiedRuntimeJar = copyFileToDir(runtimeJar, dirToCopyJarTo, collector)
val copiedReflectJar = copyFileToDir(reflectJar, dirToCopyJarTo, collector)
addJarsToExistingLibrary(project, copiedRuntimeJar!!, copiedReflectJar, collector)
}
KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> {
addJarsToExistingLibrary(project, runtimeJar, reflectJar, collector)
}
}
KotlinWithLibraryConfigurator.LibraryState.NEW_LIBRARY -> when (jarState) {
KotlinWithLibraryConfigurator.FileState.EXISTS -> {
addJarsToNewLibrary(
project, files.getRuntimeDestination(dirToCopyJarTo), files.getReflectDestination(dirToCopyJarTo), collector
)
}
KotlinWithLibraryConfigurator.FileState.COPY -> {
val copiedRuntimeJar = copyFileToDir(runtimeJar, dirToCopyJarTo, collector)
val copiedReflectJar = copyFileToDir(reflectJar, dirToCopyJarTo, collector)
addJarsToNewLibrary(project, copiedRuntimeJar!!, copiedReflectJar, collector)
}
KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> {
addJarsToNewLibrary(project, runtimeJar, reflectJar, collector)
}
}
} }
addLibraryToModuleIfNeeded(module, collector); addLibraryToModuleIfNeeded(module, collector)
} }
protected void configureModuleWithLibrarySources( protected fun configureModuleWithLibrarySources(
@NotNull Library library, library: Library,
@NotNull FileState jarState, jarState: FileState,
@Nullable String dirToCopyJarTo, dirToCopyJarTo: String?,
@NotNull NotificationMessageCollector collector collector: NotificationMessageCollector
) { ) {
RuntimeLibraryFiles files = getExistingJarFiles(); val files = existingJarFiles
File runtimeSourcesJar = files.getRuntimeSourcesJar(); val runtimeSourcesJar = files.runtimeSourcesJar
switch (jarState) { when (jarState) {
case EXISTS: { KotlinWithLibraryConfigurator.FileState.EXISTS -> {
if (dirToCopyJarTo != null) { if (dirToCopyJarTo != null) {
addSourcesToLibraryIfNeeded(library, files.getRuntimeSourcesDestination(dirToCopyJarTo), collector); addSourcesToLibraryIfNeeded(library, files.getRuntimeSourcesDestination(dirToCopyJarTo), collector)
} }
break;
} }
case COPY: { KotlinWithLibraryConfigurator.FileState.COPY -> {
assert dirToCopyJarTo != null : "Path to copy should be non-null"; assert(dirToCopyJarTo != null) { "Path to copy should be non-null" }
File file = copyFileToDir(runtimeSourcesJar, dirToCopyJarTo, collector); val file = copyFileToDir(runtimeSourcesJar, dirToCopyJarTo!!, collector)
addSourcesToLibraryIfNeeded(library, file, collector); addSourcesToLibraryIfNeeded(library, file!!, collector)
break;
} }
case DO_NOT_COPY: { KotlinWithLibraryConfigurator.FileState.DO_NOT_COPY -> {
addSourcesToLibraryIfNeeded(library, runtimeSourcesJar, collector); addSourcesToLibraryIfNeeded(library, runtimeSourcesJar, collector)
break;
} }
} }
} }
@Nullable fun getKotlinLibrary(project: Project): Library? {
public Library getKotlinLibrary(@NotNull Project project) { val librariesContainer = LibrariesContainerFactory.createContainer(project)
LibrariesContainer librariesContainer = LibrariesContainerFactory.createContainer(project); for (library in librariesContainer.getLibraries(LibrariesContainer.LibraryLevel.PROJECT)) {
for (Library library : librariesContainer.getLibraries(LibrariesContainer.LibraryLevel.PROJECT)) {
if (isKotlinLibrary(project, library)) { if (isKotlinLibrary(project, library)) {
return library; return library
} }
} }
for (Library library : librariesContainer.getLibraries(LibrariesContainer.LibraryLevel.GLOBAL)) { for (library in librariesContainer.getLibraries(LibrariesContainer.LibraryLevel.GLOBAL)) {
if (isKotlinLibrary(project, library)) { if (isKotlinLibrary(project, library)) {
return library; return library
} }
} }
return null; return null
} }
@Contract("!null, _, _ -> !null") @Contract("!null, _, _ -> !null")
@Nullable fun copyFileToDir(file: File?, toDir: String, collector: NotificationMessageCollector): File? {
public File copyFileToDir(@Nullable File file, @NotNull String toDir, @NotNull NotificationMessageCollector collector) { if (file == null) return null
if (file == null) return null;
File copy = FileUIUtils.copyWithOverwriteDialog(getMessageForOverrideDialog(), toDir, file); val copy = FileUIUtils.copyWithOverwriteDialog(messageForOverrideDialog, toDir, file)
if (copy != null) { if (copy != null) {
collector.addMessage(file.getName() + " was copied to " + toDir); collector.addMessage(file.name + " was copied to " + toDir)
} }
return copy; return copy
} }
@Nullable protected fun getPathFromLibrary(project: Project, type: OrderRootType): String? {
protected String getPathFromLibrary(@NotNull Project project, @NotNull OrderRootType type) { return getPathFromLibrary(getKotlinLibrary(project), type)
return getPathFromLibrary(getKotlinLibrary(project), type);
} }
@Nullable private fun addLibraryToModuleIfNeeded(module: Module, collector: NotificationMessageCollector) {
protected static String getPathFromLibrary(@Nullable Library library, @NotNull OrderRootType type) { val expectedDependencyScope = getDependencyScope(module)
if (library == null) return null; val kotlinLibrary = getKotlinLibrary(module)
String[] libraryFiles = library.getUrls(type);
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;
}
protected static boolean addSourcesToLibraryIfNeeded(
@NotNull Library library,
@NotNull File file,
@NotNull NotificationMessageCollector collector
) {
String[] librarySourceRoots = library.getUrls(OrderRootType.SOURCES);
String librarySourceRoot = VfsUtil.getUrlForLibraryRoot(file);
for (String sourceRoot : librarySourceRoots) {
if (sourceRoot.equals(librarySourceRoot)) return false;
}
final Library.ModifiableModel model = library.getModifiableModel();
model.addRoot(librarySourceRoot, OrderRootType.SOURCES);
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
model.commit();
}
});
collector.addMessage("Source root '" + librarySourceRoot + "' was added to " + library.getName() + " library");
return true;
}
private void addLibraryToModuleIfNeeded(Module module, NotificationMessageCollector collector) {
DependencyScope expectedDependencyScope = getDependencyScope(module);
Library kotlinLibrary = getKotlinLibrary(module);
if (kotlinLibrary == null) { if (kotlinLibrary == null) {
Library library = getKotlinLibrary(module.getProject()); val library = getKotlinLibrary(module.project) ?: error("Kotlin project library should exists")
assert library != null : "Kotlin project library should exists";
ModuleRootModificationUtil.addDependency(module, library, expectedDependencyScope, false); ModuleRootModificationUtil.addDependency(module, library, expectedDependencyScope, false)
collector.addMessage(library.getName() + " library was added to module " + module.getName()); collector.addMessage(library.name + " library was added to module " + module.name)
} }
else { else {
LibraryOrderEntry libraryEntry = findLibraryOrderEntry(ModuleRootManager.getInstance(module).getOrderEntries(), kotlinLibrary); val libraryEntry = findLibraryOrderEntry(ModuleRootManager.getInstance(module).orderEntries, kotlinLibrary)
if (libraryEntry != null) { if (libraryEntry != null) {
DependencyScope libraryDependencyScope = libraryEntry.getScope(); val libraryDependencyScope = libraryEntry.scope
if (!expectedDependencyScope.equals(libraryDependencyScope)) { if (expectedDependencyScope != libraryDependencyScope) {
libraryEntry.setScope(expectedDependencyScope); libraryEntry.scope = expectedDependencyScope
collector.addMessage( collector.addMessage(
kotlinLibrary.getName() + " library scope has changed from " + libraryDependencyScope + kotlinLibrary.name + " library scope has changed from " + libraryDependencyScope +
" to " + expectedDependencyScope + " for module " + module.getName()); " to " + expectedDependencyScope + " for module " + module.name)
} }
} }
} }
} }
@Nullable private fun addJarsToExistingLibrary(project: Project, runtimeJar: File, reflectJar: File?, collector: NotificationMessageCollector) {
private static LibraryOrderEntry findLibraryOrderEntry(@NotNull OrderEntry[] orderEntries, @NotNull Library library) { val library = getKotlinLibrary(project) ?: error("Kotlin library should present, instead createNewLibrary should be invoked")
for (OrderEntry orderEntry : orderEntries) {
if (orderEntry instanceof LibraryOrderEntry && library.equals(((LibraryOrderEntry)orderEntry).getLibrary())) {
return (LibraryOrderEntry)orderEntry;
}
}
return null; val model = library.modifiableModel
} model.addRoot(VfsUtil.getUrlForLibraryRoot(runtimeJar), OrderRootType.CLASSES)
@NotNull
private static DependencyScope getDependencyScope(@NotNull Module module) {
if (ConfigureKotlinInProjectUtilsKt.hasKotlinFilesOnlyInTests(module)) {
return DependencyScope.TEST;
}
return DependencyScope.COMPILE;
}
private void addJarsToExistingLibrary(@NotNull Project project, @NotNull File runtimeJar, @Nullable File reflectJar, @NotNull NotificationMessageCollector collector) {
Library library = getKotlinLibrary(project);
assert library != null : "Kotlin library should present, instead createNewLibrary should be invoked";
final Library.ModifiableModel model = library.getModifiableModel();
model.addRoot(VfsUtil.getUrlForLibraryRoot(runtimeJar), OrderRootType.CLASSES);
if (reflectJar != null) { if (reflectJar != null) {
model.addRoot(VfsUtil.getUrlForLibraryRoot(reflectJar), OrderRootType.CLASSES); model.addRoot(VfsUtil.getUrlForLibraryRoot(reflectJar), OrderRootType.CLASSES)
} }
ApplicationManager.getApplication().runWriteAction(new Runnable() { ApplicationManager.getApplication().runWriteAction { model.commit() }
@Override
public void run() {
model.commit();
}
});
collector.addMessage(library.getName() + " library was configured"); collector.addMessage(library.name!! + " library was configured")
} }
private void addJarsToNewLibrary( private fun addJarsToNewLibrary(
@NotNull Project project, project: Project,
@NotNull final File runtimeJar, runtimeJar: File,
@Nullable final File reflectJar, reflectJar: File?,
@NotNull NotificationMessageCollector collector collector: NotificationMessageCollector
) { ) {
final LibraryTable table = LibraryTablesRegistrar.getInstance().getLibraryTable(project); val table = LibraryTablesRegistrar.getInstance().getLibraryTable(project)
final Ref<Library> library = new Ref<Library>(); val library = Ref<Library>()
ApplicationManager.getApplication().runWriteAction(new Runnable() { ApplicationManager.getApplication().runWriteAction {
@Override library.set(table.createLibrary(libraryName))
public void run() { val model = library.get().modifiableModel
library.set(table.createLibrary(getLibraryName())); model.addRoot(VfsUtil.getUrlForLibraryRoot(runtimeJar), OrderRootType.CLASSES)
Library.ModifiableModel model = library.get().getModifiableModel(); if (reflectJar != null) {
model.addRoot(VfsUtil.getUrlForLibraryRoot(runtimeJar), OrderRootType.CLASSES); model.addRoot(VfsUtil.getUrlForLibraryRoot(reflectJar), OrderRootType.CLASSES)
if (reflectJar != null) {
model.addRoot(VfsUtil.getUrlForLibraryRoot(reflectJar), OrderRootType.CLASSES);
}
model.commit();
} }
}); model.commit()
collector.addMessage(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 final Module module) {
final Ref<Library> result = Ref.create(null);
OrderEnumerator.orderEntries(module).forEachLibrary(new Processor<Library>() {
@Override
public boolean process(Library library) {
if (isKotlinLibrary(module.getProject(), library)) {
result.set(library);
return false;
}
return true;
}
});
return result.get();
}
protected boolean isKotlinLibrary(@NotNull Project project, @NotNull Library library) {
if (getLibraryName().equals(library.getName())) {
return true;
} }
String fileName = getExistingJarFiles().getRuntimeJar().getName(); collector.addMessage(library.get().name!! + " library was created")
}
for (VirtualFile root : library.getFiles(OrderRootType.CLASSES)) { private fun isProjectLibraryWithoutPathsPresent(project: Project): Boolean {
if (root.getName().equals(fileName)) { val library = getKotlinLibrary(project)
return true; return library != null && library.getUrls(OrderRootType.CLASSES).size == 0
}
private fun isProjectLibraryPresent(project: Project): Boolean {
val library = getKotlinLibrary(project)
return library != null && library.getUrls(OrderRootType.CLASSES).size > 0
}
private fun getKotlinLibrary(module: Module): Library? {
val result = Ref.create<Library>(null)
OrderEnumerator.orderEntries(module).forEachLibrary(Processor<Library> { library ->
if (isKotlinLibrary(module.project, library)) {
result.set(library)
return@Processor false
}
true
})
return result.get()
}
protected open fun isKotlinLibrary(project: Project, library: Library): Boolean {
if (libraryName == library.name) {
return true
}
val fileName = existingJarFiles.runtimeJar.name
for (root in library.getFiles(OrderRootType.CLASSES)) {
if (root.name == fileName) {
return true
} }
} }
return false; return false
} }
protected boolean needToChooseJarPath(@NotNull Project project) { protected fun needToChooseJarPath(project: Project): Boolean {
String defaultPath = getDefaultPathToJarFile(project); val defaultPath = getDefaultPathToJarFile(project)
return !isProjectLibraryPresent(project) && !getExistingJarFiles().getRuntimeDestination(defaultPath).exists(); return !isProjectLibraryPresent(project) && !existingJarFiles.getRuntimeDestination(defaultPath).exists()
} }
protected String getDefaultPathToJarFile(@NotNull Project project) { protected open fun getDefaultPathToJarFile(project: Project): String {
return FileUIUtils.createRelativePath(project, project.getBaseDir(), DEFAULT_LIBRARY_DIR); return FileUIUtils.createRelativePath(project, project.baseDir, DEFAULT_LIBRARY_DIR)
} }
protected void showError(@NotNull String message) { protected fun showError(message: String) {
Messages.showErrorDialog(message, getMessageForOverrideDialog()); Messages.showErrorDialog(message, messageForOverrideDialog)
} }
protected enum FileState { enum class FileState {
EXISTS, EXISTS,
COPY, COPY,
DO_NOT_COPY DO_NOT_COPY
} }
protected enum LibraryState { enum class LibraryState {
LIBRARY, LIBRARY,
NON_CONFIGURED_LIBRARY, NON_CONFIGURED_LIBRARY,
NEW_LIBRARY, NEW_LIBRARY
} }
@NotNull fun getLibraryState(project: Project): LibraryState {
protected LibraryState getLibraryState(@NotNull Project project) {
if (isProjectLibraryPresent(project)) { if (isProjectLibraryPresent(project)) {
return LibraryState.LIBRARY; return LibraryState.LIBRARY
} }
else if (isProjectLibraryWithoutPathsPresent(project)) { else if (isProjectLibraryWithoutPathsPresent(project)) {
return LibraryState.NON_CONFIGURED_LIBRARY; return LibraryState.NON_CONFIGURED_LIBRARY
} }
return LibraryState.NEW_LIBRARY; return LibraryState.NEW_LIBRARY
} }
@NotNull protected fun getJarState(
protected FileState getJarState( project: Project,
@NotNull Project project, targetFile: File,
@NotNull File targetFile, jarType: OrderRootType,
@NotNull OrderRootType jarType, useBundled: Boolean
boolean useBundled ): FileState {
) {
if (targetFile.exists()) { if (targetFile.exists()) {
return FileState.EXISTS; return FileState.EXISTS
} }
else if (getPathFromLibrary(project, jarType) != null) { else if (getPathFromLibrary(project, jarType) != null) {
return FileState.COPY; return FileState.COPY
} }
else if (useBundled) { else if (useBundled) {
return FileState.DO_NOT_COPY; return FileState.DO_NOT_COPY
} }
else { else {
return FileState.COPY; return FileState.COPY
} }
} }
@NotNull private fun getPathToCopyFileTo(
private String getPathToCopyFileTo( project: Project,
@NotNull Project project, jarType: OrderRootType,
@NotNull OrderRootType jarType, defaultDir: String,
@NotNull String defaultDir, pathFromDialog: String?
@Nullable String pathFromDialog ): String {
) {
if (pathFromDialog != null) { if (pathFromDialog != null) {
return pathFromDialog; return pathFromDialog
} }
String pathFromLibrary = getPathFromLibrary(project, jarType); val pathFromLibrary = getPathFromLibrary(project, jarType)
if (pathFromLibrary != null) { if (pathFromLibrary != null) {
return pathFromLibrary; return pathFromLibrary
} }
return defaultDir; return defaultDir
} }
protected File assertFileExists(@NotNull File file) { protected fun assertFileExists(file: File): File {
if (!file.exists()) { if (!file.exists()) {
showError("Couldn't find file: " + file.getPath()); showError("Couldn't find file: " + file.path)
} }
return file; return file
} }
public void copySourcesToPathFromLibrary(@NotNull Library library, @NotNull NotificationMessageCollector collector) { fun copySourcesToPathFromLibrary(library: Library, collector: NotificationMessageCollector) {
String dirToJarFromLibrary = getPathFromLibrary(library, OrderRootType.SOURCES); val dirToJarFromLibrary = getPathFromLibrary(library, OrderRootType.SOURCES) ?: error("Directory to file from library should be non null")
assert dirToJarFromLibrary != null : "Directory to file from library should be non null";
copyFileToDir(getExistingJarFiles().getRuntimeSourcesJar(), dirToJarFromLibrary, collector); copyFileToDir(existingJarFiles.runtimeSourcesJar, dirToJarFromLibrary, collector)
} }
public boolean changeOldSourcesPathIfNeeded(@NotNull Library library, @NotNull NotificationMessageCollector collector) { fun changeOldSourcesPathIfNeeded(library: Library, collector: NotificationMessageCollector): Boolean {
if (!removeOldSourcesRootIfNeeded(library, collector)) { if (!removeOldSourcesRootIfNeeded(library, collector)) {
return false; return false
} }
String parentDir = getPathFromLibrary(library, OrderRootType.CLASSES); val parentDir = getPathFromLibrary(library, OrderRootType.CLASSES) ?: error("Parent dir for classes jar should exists for Kotlin library")
assert parentDir != null : "Parent dir for classes jar should exists for Kotlin library";
return addSourcesToLibraryIfNeeded(library, getExistingJarFiles().getRuntimeSourcesDestination(parentDir), collector); return addSourcesToLibraryIfNeeded(library, existingJarFiles.getRuntimeSourcesDestination(parentDir), collector)
} }
protected boolean removeOldSourcesRootIfNeeded(@NotNull Library library, @NotNull NotificationMessageCollector collector) { protected fun removeOldSourcesRootIfNeeded(library: Library, collector: NotificationMessageCollector): Boolean {
String oldLibrarySourceRoot = getOldSourceRootUrl(library); val oldLibrarySourceRoot = getOldSourceRootUrl(library)
String[] librarySourceRoots = library.getUrls(OrderRootType.SOURCES); val librarySourceRoots = library.getUrls(OrderRootType.SOURCES)
for (String sourceRoot : librarySourceRoots) { for (sourceRoot in librarySourceRoots) {
if (sourceRoot.equals(oldLibrarySourceRoot)) { if (sourceRoot == oldLibrarySourceRoot) {
final Library.ModifiableModel model = library.getModifiableModel(); val model = library.modifiableModel
model.removeRoot(oldLibrarySourceRoot, OrderRootType.SOURCES); model.removeRoot(oldLibrarySourceRoot!!, OrderRootType.SOURCES)
ApplicationManager.getApplication().runWriteAction(new Runnable() { ApplicationManager.getApplication().runWriteAction { model.commit() }
@Override
public void run() {
model.commit();
}
});
collector.addMessage("Source root '" + oldLibrarySourceRoot + "' was removed for " + library.getName() + " library"); collector.addMessage("Source root '" + oldLibrarySourceRoot + "' was removed for " + library.name + " library")
return true; return true
} }
} }
return false; return false
} }
KotlinWithLibraryConfigurator() { companion object {
val DEFAULT_LIBRARY_DIR = "lib"
protected fun isApplicable(module: Module): Boolean {
return !KotlinPluginUtil.isAndroidGradleModule(module) &&
!KotlinPluginUtil.isMavenModule(module) &&
!KotlinPluginUtil.isGradleModule(module)
}
protected fun getPathFromLibrary(library: Library?, type: OrderRootType): String? {
if (library == null) return null
val libraryFiles = library.getUrls(type)
if (libraryFiles.size < 1) return null
val pathToJarInLib = VfsUtilCore.urlToPath(libraryFiles[0])
val parentDir = VfsUtil.getParentDir(VfsUtil.getParentDir(pathToJarInLib)) ?: return null
val parentDirFile = File(parentDir)
if (!parentDirFile.exists() && !parentDirFile.mkdirs()) {
return null
}
return parentDir
}
protected fun addSourcesToLibraryIfNeeded(
library: Library,
file: File,
collector: NotificationMessageCollector
): Boolean {
val librarySourceRoots = library.getUrls(OrderRootType.SOURCES)
val librarySourceRoot = VfsUtil.getUrlForLibraryRoot(file)
for (sourceRoot in librarySourceRoots) {
if (sourceRoot == librarySourceRoot) return false
}
val model = library.modifiableModel
model.addRoot(librarySourceRoot, OrderRootType.SOURCES)
ApplicationManager.getApplication().runWriteAction { model.commit() }
collector.addMessage("Source root '" + librarySourceRoot + "' was added to " + library.name + " library")
return true
}
private fun findLibraryOrderEntry(orderEntries: Array<OrderEntry>, library: Library): LibraryOrderEntry? {
for (orderEntry in orderEntries) {
if (orderEntry is LibraryOrderEntry && library == orderEntry.library) {
return orderEntry
}
}
return null
}
private fun getDependencyScope(module: Module): DependencyScope {
if (hasKotlinFilesOnlyInTests(module)) {
return DependencyScope.TEST
}
return DependencyScope.COMPILE
}
} }
} }