Support library create with relative paths

#KT-4644 In Progress
This commit is contained in:
Nikolay Krasko
2014-03-17 22:04:13 +04:00
parent 16018ccfe8
commit 8ddbdab8c8
9 changed files with 299 additions and 52 deletions
@@ -1,4 +1,7 @@
<root>
<item name='com.intellij.openapi.vfs.VfsUtil java.lang.String getUrlForLibraryRoot(java.io.File)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
</item>
<item
name='com.intellij.openapi.vfs.VirtualFile com.intellij.openapi.vfs.VirtualFile createChildDirectory(java.lang.Object, java.lang.String)'>
<annotation name='org.jetbrains.annotations.NotNull'/>
@@ -0,0 +1,106 @@
/*
* Copyright 2010-2014 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;
import com.beust.jcommander.internal.Lists;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.roots.ModifiableRootModel;
import com.intellij.openapi.roots.libraries.Library;
import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription;
import com.intellij.openapi.util.io.FileUtil;
import kotlin.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.plugin.configuration.KotlinWithLibraryConfigurator;
import org.jetbrains.jet.plugin.util.projectStructure.ProjectStructurePackage;
import java.io.File;
import java.util.List;
public abstract class CustomLibraryDescriptorWithDefferConfig extends CustomLibraryDescription {
@NotNull
public abstract String getLibraryNamePrefix();
@Nullable
public abstract DeferredCopyFileRequests getCopyFileRequests();
public void finishLibConfiguration(@NotNull Module module, @NotNull ModifiableRootModel rootModel) {
DeferredCopyFileRequests deferredCopyFileRequests = getCopyFileRequests();
if (deferredCopyFileRequests == null) return;
Library library = ProjectStructurePackage.findLibrary(rootModel.orderEntries(), new Function1<Library, Boolean>() {
@Override
public Boolean invoke(@NotNull Library library) {
String name = library.getName();
return name != null && name.startsWith(getLibraryNamePrefix());
}
});
if (library == null) return;
Library.ModifiableModel model = library.getModifiableModel();
try {
deferredCopyFileRequests.performRequests(ProjectStructurePackage.getModuleDir(module), model);
}
finally {
model.commit();
}
}
public static class DeferredCopyFileRequests {
private final List<CopyFileRequest> copyFilesRequests = Lists.newArrayList();
private final KotlinWithLibraryConfigurator configurator;
public DeferredCopyFileRequests(KotlinWithLibraryConfigurator configurator) {
this.configurator = configurator;
}
public void performRequests(@NotNull String relativePath, Library.ModifiableModel model) {
for (CopyFileRequest request : copyFilesRequests) {
String destinationPath = FileUtil.isAbsolute(request.toDir) ?
request.toDir :
new File(relativePath, request.toDir).getPath();
File resultFile = configurator.copyFileToDir(request.file, destinationPath);
if (request.replaceInLib) {
ProjectStructurePackage.replaceFileRoot(model, request.file, resultFile);
}
}
}
public void addCopyRequest(@NotNull File file, @NotNull String copyIntoPath) {
copyFilesRequests.add(new CopyFileRequest(copyIntoPath, file, false));
}
public void addCopyWithReplaceRequest(@NotNull File file, @NotNull String copyIntoPath) {
copyFilesRequests.add(new CopyFileRequest(copyIntoPath, file, true));
}
public static class CopyFileRequest {
private final String toDir;
private final File file;
private final boolean replaceInLib;
public CopyFileRequest(String dir, File file, boolean replaceInLib) {
toDir = dir;
this.file = file;
this.replaceInLib = replaceInLib;
}
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
* Copyright 2010-2014 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.
@@ -39,18 +39,17 @@ public class FrameworksCompatibilityUtils {
public static void suggestRemoveIncompatibleFramework(
@NotNull ModifiableRootModel rootModel,
@NotNull CustomLibraryDescription libraryDescription,
@NotNull Set<? extends LibraryKind> frameworkLibraryKinds,
@NotNull FrameworkType frameworkType
) {
List<OrderEntry> existingEntries = new ArrayList<OrderEntry>();
Set<? extends LibraryKind> kinds = libraryDescription.getSuitableLibraryKinds();
for (OrderEntry entry : rootModel.getOrderEntries()) {
if (!(entry instanceof LibraryOrderEntry)) continue;
Library library = ((LibraryOrderEntry)entry).getLibrary();
if (library == null) continue;
for (LibraryKind kind : kinds) {
for (LibraryKind kind : frameworkLibraryKinds) {
if (LibraryPresentationManager.getInstance().isLibraryOfKind(Arrays.asList(library.getFiles(OrderRootType.CLASSES)), kind)) {
existingEntries.add(entry);
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
* Copyright 2010-2014 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.
@@ -40,12 +40,15 @@ public class JSFrameworkSupportProvider extends FrameworkSupportInModuleProvider
@NotNull
@Override
public FrameworkSupportInModuleConfigurable createConfigurable(@NotNull FrameworkSupportModel model) {
public FrameworkSupportInModuleConfigurable createConfigurable(@NotNull final FrameworkSupportModel model) {
return new FrameworkSupportInModuleConfigurable() {
public JSLibraryStdDescription description;
@Nullable
@Override
public CustomLibraryDescription createLibraryDescription() {
return new JSLibraryStdDescription();
description = new JSLibraryStdDescription(model.getProject());
return description;
}
@Nullable
@@ -66,10 +69,12 @@ public class JSFrameworkSupportProvider extends FrameworkSupportInModuleProvider
@NotNull ModifiableModelsProvider modifiableModelsProvider) {
FrameworksCompatibilityUtils.suggestRemoveIncompatibleFramework(
rootModel,
new JavaRuntimeLibraryDescription(),
JavaRuntimeLibraryDescription.SUITABLE_LIBRARY_KINDS,
JavaFrameworkType.getInstance());
FrameworksCompatibilityUtils.suggestRemoveOldJsLibrary(rootModel);
description.finishLibConfiguration(module, rootModel);
}
};
}
@@ -18,10 +18,10 @@ package org.jetbrains.jet.plugin.framework;
import com.google.common.collect.Sets;
import com.intellij.framework.library.LibraryVersionProperties;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderRootType;
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.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -41,33 +41,59 @@ import static org.jetbrains.jet.plugin.configuration.KotlinJsModuleConfigurator.
import static org.jetbrains.jet.plugin.configuration.KotlinWithLibraryConfigurator.getFileInDir;
import static org.jetbrains.jet.plugin.framework.ui.FileUIUtils.createRelativePath;
public class JSLibraryStdDescription extends CustomLibraryDescription {
public class JSLibraryStdDescription extends CustomLibraryDescriptorWithDefferConfig {
public static final LibraryKind KOTLIN_JAVASCRIPT_KIND = LibraryKind.create("kotlin-js-stdlib");
public static final String LIBRARY_NAME = "KotlinJavaScript";
public static final String JAVA_SCRIPT_LIBRARY_CREATION = "JavaScript Library Creation";
private static final Set<LibraryKind> libraryKinds = Sets.newHashSet(KOTLIN_JAVASCRIPT_KIND);
public static final Set<LibraryKind> SUITABLE_LIBRARY_KINDS = Sets.newHashSet(KOTLIN_JAVASCRIPT_KIND);
private static final String DEFAULT_LIB_DIR_NAME = "lib";
private static final String DEFAULT_SCRIPT_DIR_NAME = "script";
private final boolean useRelativePaths;
private DeferredCopyFileRequests deferredCopyFileRequests;
public JSLibraryStdDescription(@Nullable Project project) {
useRelativePaths = project == null;
}
@NotNull
@Override
public Set<? extends LibraryKind> getSuitableLibraryKinds() {
return libraryKinds;
return SUITABLE_LIBRARY_KINDS;
}
@NotNull
@Override
public String getLibraryNamePrefix() {
return LIBRARY_NAME;
}
@Nullable
@Override
public DeferredCopyFileRequests getCopyFileRequests() {
return deferredCopyFileRequests;
}
@Nullable
@Override
public NewLibraryConfiguration createNewLibrary(@NotNull JComponent parentComponent, @Nullable VirtualFile contextDirectory) {
KotlinJsModuleConfigurator configurator = (KotlinJsModuleConfigurator) getConfiguratorByName(NAME);
assert configurator != null : "Cannot find configurator with name " + NAME;
KotlinJsModuleConfigurator jsConfigurator = (KotlinJsModuleConfigurator) getConfiguratorByName(NAME);
assert jsConfigurator != null : "Cannot find configurator with name " + NAME;
String defaultPathToJsFileDir = createRelativePath(null, contextDirectory, "script");
String defaultPathToJarFileDir = createRelativePath(null, contextDirectory, "lib");
deferredCopyFileRequests = new DeferredCopyFileRequests(jsConfigurator);
String defaultPathToJsFileDir =
useRelativePaths ? DEFAULT_SCRIPT_DIR_NAME : createRelativePath(null, contextDirectory, DEFAULT_SCRIPT_DIR_NAME);
String defaultPathToJarFileDir =
useRelativePaths ? DEFAULT_LIB_DIR_NAME : createRelativePath(null, contextDirectory, DEFAULT_LIB_DIR_NAME);
boolean jsFilePresent = isJsFilePresent(defaultPathToJsFileDir);
boolean jarFilePresent = getFileInDir(configurator.getJarName(), defaultPathToJarFileDir).exists();
boolean jarFilePresent = getFileInDir(jsConfigurator.getJarName(), defaultPathToJarFileDir).exists();
if (jarFilePresent && jsFilePresent) {
return createConfiguration(getFileInDir(configurator.getJarName(), defaultPathToJarFileDir));
return createConfiguration(getFileInDir(jsConfigurator.getJarName(), defaultPathToJarFileDir));
}
CreateJavaScriptLibraryDialog dialog =
@@ -78,21 +104,21 @@ public class JSLibraryStdDescription extends CustomLibraryDescription {
String copyJsFileIntoPath = dialog.getCopyJsIntoPath();
if (!jsFilePresent && copyJsFileIntoPath != null) {
configurator.copyFileToDir(configurator.getJsFile(), copyJsFileIntoPath);
deferredCopyFileRequests.addCopyRequest(jsConfigurator.getJsFile(), copyJsFileIntoPath);
}
if (jarFilePresent) {
return createConfiguration(getFileInDir(configurator.getJarName(), defaultPathToJarFileDir));
return createConfiguration(getFileInDir(jsConfigurator.getJarName(), defaultPathToJarFileDir));
}
else {
String copyIntoPath = dialog.getCopyLibraryIntoPath();
File existedJarFile = configurator.getExistedJarFile();
File existedJarFile = jsConfigurator.getExistedJarFile();
if (copyIntoPath != null) {
return createConfiguration(configurator.copyFileToDir(existedJarFile, copyIntoPath));
}
else {
return createConfiguration(existedJarFile);
deferredCopyFileRequests.addCopyWithReplaceRequest(existedJarFile, copyIntoPath);
}
return createConfiguration(existedJarFile);
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
* Copyright 2010-2014 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.
@@ -40,12 +40,15 @@ public class JavaFrameworkSupportProvider extends FrameworkSupportInModuleProvid
@NotNull
@Override
public FrameworkSupportInModuleConfigurable createConfigurable(@NotNull FrameworkSupportModel model) {
public FrameworkSupportInModuleConfigurable createConfigurable(@NotNull final FrameworkSupportModel model) {
return new FrameworkSupportInModuleConfigurable() {
JavaRuntimeLibraryDescription description = null;
@Nullable
@Override
public CustomLibraryDescription createLibraryDescription() {
return new JavaRuntimeLibraryDescription();
description = new JavaRuntimeLibraryDescription(model.getProject());
return description;
}
@Nullable
@@ -66,8 +69,10 @@ public class JavaFrameworkSupportProvider extends FrameworkSupportInModuleProvid
@NotNull ModifiableModelsProvider modifiableModelsProvider) {
FrameworksCompatibilityUtils.suggestRemoveIncompatibleFramework(
rootModel,
new JSLibraryStdDescription(),
JSLibraryStdDescription.SUITABLE_LIBRARY_KINDS,
JSFrameworkType.getInstance());
description.finishLibConfiguration(module, rootModel);
}
};
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
* Copyright 2010-2014 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.
@@ -18,10 +18,10 @@ package org.jetbrains.jet.plugin.framework;
import com.google.common.collect.Sets;
import com.intellij.framework.library.LibraryVersionProperties;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.OrderRootType;
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.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
@@ -38,37 +38,74 @@ import java.util.Set;
import static org.jetbrains.jet.plugin.configuration.KotlinWithLibraryConfigurator.getFileInDir;
public class JavaRuntimeLibraryDescription extends CustomLibraryDescription {
public class JavaRuntimeLibraryDescription extends CustomLibraryDescriptorWithDefferConfig {
public static final LibraryKind KOTLIN_JAVA_RUNTIME_KIND = LibraryKind.create("kotlin-java-runtime");
public static final String LIBRARY_NAME = "KotlinJavaRuntime";
public static final String JAVA_RUNTIME_LIBRARY_CREATION = "Java Runtime Library Creation";
private static final Set<LibraryKind> libraryKinds = Sets.newHashSet(KOTLIN_JAVA_RUNTIME_KIND);
public static final Set<LibraryKind> SUITABLE_LIBRARY_KINDS = Sets.newHashSet(KOTLIN_JAVA_RUNTIME_KIND);
private static final String DEFAULT_LIB_DIR_NAME = "lib";
private final boolean useRelativePaths;
private DeferredCopyFileRequests deferredCopyFileRequests = null;
/**
* @param project null when project doesn't exist yet (called from project wizard)
*/
public JavaRuntimeLibraryDescription(@Nullable Project project) {
useRelativePaths = project == null;
}
@NotNull
@Override
public Set<? extends LibraryKind> getSuitableLibraryKinds() {
return libraryKinds;
return SUITABLE_LIBRARY_KINDS;
}
@NotNull
@Override
public String getLibraryNamePrefix() {
return LIBRARY_NAME;
}
@Nullable
@Override
public DeferredCopyFileRequests getCopyFileRequests() {
return deferredCopyFileRequests;
}
@Nullable
@Override
public NewLibraryConfiguration createNewLibrary(@NotNull JComponent parentComponent, @Nullable VirtualFile contextDirectory) {
KotlinJavaModuleConfigurator configurator = (KotlinJavaModuleConfigurator) ConfigureKotlinInProjectUtils
.getConfiguratorByName(KotlinJavaModuleConfigurator.NAME);
assert configurator != null : "Configurator with name " + KotlinJavaModuleConfigurator.NAME + " should exists";
KotlinJavaModuleConfigurator jvmConfigurator =
(KotlinJavaModuleConfigurator) ConfigureKotlinInProjectUtils.getConfiguratorByName(KotlinJavaModuleConfigurator.NAME);
assert jvmConfigurator != null : "Configurator with name " + KotlinJavaModuleConfigurator.NAME + " should exists";
String defaultPathToJarFile = FileUIUtils.createRelativePath(null, contextDirectory, "lib");
deferredCopyFileRequests = new DeferredCopyFileRequests(jvmConfigurator);
boolean jarFilePresent = getFileInDir(configurator.getJarName(), defaultPathToJarFile).exists();
String defaultPathToJarFile = useRelativePaths ? DEFAULT_LIB_DIR_NAME
: FileUIUtils.createRelativePath(null, contextDirectory, DEFAULT_LIB_DIR_NAME);
File bundledLibJarFile = jvmConfigurator.getExistedJarFile();
File bundledLibSourcesJarFile = jvmConfigurator.getExistedSourcesJarFile();
File libraryFile;
File librarySrcFile;
if (jarFilePresent) {
libraryFile = getFileInDir(configurator.getJarName(), defaultPathToJarFile);
File sourcesJar = getFileInDir(configurator.getSourcesJarName(), defaultPathToJarFile);
librarySrcFile = sourcesJar.exists() ? sourcesJar
: configurator.copyFileToDir(configurator.getExistedSourcesJarFile(), libraryFile.getParent());
File stdJarInDefaultPath = getFileInDir(jvmConfigurator.getJarName(), defaultPathToJarFile);
if (stdJarInDefaultPath.exists()) {
libraryFile = stdJarInDefaultPath;
File sourcesJar = getFileInDir(jvmConfigurator.getSourcesJarName(), defaultPathToJarFile);
if (sourcesJar.exists()) {
librarySrcFile = sourcesJar;
}
else {
deferredCopyFileRequests.addCopyWithReplaceRequest(bundledLibSourcesJarFile, libraryFile.getParent());
librarySrcFile = bundledLibSourcesJarFile;
}
}
else {
CreateJavaLibraryDialog dialog = new CreateJavaLibraryDialog(defaultPathToJarFile);
@@ -77,18 +114,19 @@ public class JavaRuntimeLibraryDescription extends CustomLibraryDescription {
if (!dialog.isOK()) return null;
String copyIntoPath = dialog.getCopyIntoPath();
if (copyIntoPath != null) {
deferredCopyFileRequests.addCopyWithReplaceRequest(bundledLibJarFile, copyIntoPath);
deferredCopyFileRequests.addCopyWithReplaceRequest(bundledLibSourcesJarFile, copyIntoPath);
}
File existedJarFile = configurator.getExistedJarFile();
libraryFile = copyIntoPath != null ? configurator.copyFileToDir(existedJarFile, copyIntoPath) : existedJarFile;
File existedSourcesJarFile = configurator.getExistedSourcesJarFile();
librarySrcFile = copyIntoPath != null ? configurator.copyFileToDir(existedSourcesJarFile, copyIntoPath) : existedSourcesJarFile;
libraryFile = bundledLibJarFile;
librarySrcFile = bundledLibSourcesJarFile;
}
final String libraryFileUrl = VfsUtil.getUrlForLibraryRoot(libraryFile);
final String libraryFileSrcUrl = VfsUtil.getUrlForLibraryRoot(librarySrcFile);
return new NewLibraryConfiguration(LIBRARY_NAME, getDownloadableLibraryType(), new LibraryVersionProperties()) {
return new NewLibraryConfiguration(LIBRARY_NAME, null, new LibraryVersionProperties()) {
@Override
public void addRoots(@NotNull LibraryEditor editor) {
editor.addRoot(libraryFileUrl, OrderRootType.CLASSES);
@@ -0,0 +1,65 @@
/*
* Copyright 2010-2014 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.util.projectStructure
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.OrderEnumerator
import com.intellij.openapi.roots.OrderEntry
import java.io.File
import com.intellij.openapi.vfs.VfsUtil
import com.intellij.openapi.roots.OrderRootType
public fun Module.findLibrary(predicate: (Library) -> Boolean): Library? = OrderEnumerator.orderEntries(this).findLibrary(predicate)
public fun OrderEnumerator.findLibrary(predicate: (Library) -> Boolean): Library? {
var lib: Library? = null
forEachLibrary { library ->
if (predicate(library!!)) {
lib = library
false
}
else {
true
}
}
return lib
}
public fun Module.getModuleDir(): String = File(getModuleFilePath()).getParent()!!.replace(File.separatorChar, '/')
public fun Library.ModifiableModel.replaceFileRoot(oldFile: File, newFile: File) {
val oldRoot = VfsUtil.getUrlForLibraryRoot(oldFile)
val newRoot = VfsUtil.getUrlForLibraryRoot(newFile)
fun replaceInRootType(rootType: OrderRootType) {
for (url in getUrls(rootType)) {
if (oldRoot == url) {
removeRoot(url, rootType)
addRoot(newRoot, rootType)
}
}
}
replaceInRootType(OrderRootType.CLASSES)
replaceInRootType(OrderRootType.SOURCES)
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
* Copyright 2010-2014 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.
@@ -44,7 +44,7 @@ public class JetStdJSProjectDescriptor implements LightProjectDescriptor {
@Override
public void configureModule(@NotNull Module module, @NotNull ModifiableRootModel model, ContentEntry contentEntry) {
NewLibraryConfiguration configuration = new JSLibraryStdDescription().createNewLibraryForTests();
NewLibraryConfiguration configuration = new JSLibraryStdDescription(module.getProject()).createNewLibraryForTests();
assert configuration != null : "Configuration should exist";