/* * Copyright 2010-2015 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.kotlin.idea.test; import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.module.Module; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.*; import com.intellij.openapi.roots.impl.libraries.LibraryEx; import com.intellij.openapi.roots.libraries.Library; import com.intellij.openapi.roots.ui.configuration.libraryEditor.NewLibraryEditor; import com.intellij.openapi.util.Computable; import com.intellij.openapi.vfs.VfsUtil; import kotlin.jvm.functions.Function0; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt; import org.jetbrains.kotlin.test.InTextDirectivesUtils; import org.jetbrains.kotlin.utils.PathUtil; import java.io.File; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * Helper for configuring kotlin runtime in tested project. */ public class ConfigLibraryUtil { private static final String DEFAULT_JAVA_RUNTIME_LIB_NAME = "JAVA_RUNTIME_LIB_NAME"; private static final String DEFAULT_KOTLIN_TEST_LIB_NAME = "KOTLIN_TEST_LIB_NAME"; private static final String DEFAULT_KOTLIN_JS_STDLIB_NAME = "KOTLIN_JS_STDLIB_NAME"; private ConfigLibraryUtil() { } private static NewLibraryEditor getKotlinRuntimeLibEditor(String libName, File library) { NewLibraryEditor editor = new NewLibraryEditor(); editor.setName(libName); editor.addRoot(VfsUtil.getUrlForLibraryRoot(library), OrderRootType.CLASSES); return editor; } public static void configureKotlinRuntimeAndSdk(Module module, Sdk sdk) { configureSdk(module, sdk); configureKotlinRuntime(module); } public static void configureKotlinJsRuntimeAndSdk(Module module, Sdk sdk) { configureSdk(module, sdk); configureKotlinJsRuntime(module); } public static void configureKotlinRuntime(Module module) { addLibrary(getKotlinRuntimeLibEditor(DEFAULT_JAVA_RUNTIME_LIB_NAME, PathUtil.getKotlinPathsForDistDirectory().getStdlibPath()), module); addLibrary(getKotlinRuntimeLibEditor(DEFAULT_KOTLIN_TEST_LIB_NAME, PathUtil.getKotlinPathsForDistDirectory().getKotlinTestPath()), module); } public static void configureKotlinJsRuntime(Module module) { addLibrary(getKotlinRuntimeLibEditor(DEFAULT_KOTLIN_JS_STDLIB_NAME, PathUtil.getKotlinPathsForDistDirectory().getJsStdLibJarPath()), module); } public static void unConfigureKotlinRuntime(Module module) { removeLibrary(module, DEFAULT_JAVA_RUNTIME_LIB_NAME); removeLibrary(module, DEFAULT_KOTLIN_TEST_LIB_NAME); } public static void unConfigureKotlinRuntimeAndSdk(Module module, Sdk sdk) { configureSdk(module, sdk); unConfigureKotlinRuntime(module); } public static void unConfigureKotlinJsRuntimeAndSdk(Module module, Sdk sdk) { configureSdk(module, sdk); removeLibrary(module, DEFAULT_KOTLIN_JS_STDLIB_NAME); } public static void configureSdk(@NotNull final Module module, @NotNull final Sdk sdk) { ApplicationManager.getApplication().runWriteAction(new Runnable() { @Override public void run() { ModuleRootManager rootManager = ModuleRootManager.getInstance(module); ModifiableRootModel rootModel = rootManager.getModifiableModel(); rootModel.setSdk(sdk); rootModel.commit(); } }); } public static Library addLibrary(final NewLibraryEditor editor, final Module module) { return ApplicationManager.getApplication().runWriteAction(new Computable<Library>() { @Override public Library compute() { ModuleRootManager rootManager = ModuleRootManager.getInstance(module); ModifiableRootModel model = rootManager.getModifiableModel(); Library library = addLibrary(editor, model); model.commit(); return library; } }); } public static Library addLibrary(NewLibraryEditor editor, ModifiableRootModel model) { Library library = model.getModuleLibraryTable().createLibrary(editor.getName()); Library.ModifiableModel libModel = library.getModifiableModel(); editor.applyTo((LibraryEx.ModifiableModelEx) libModel); libModel.commit(); return library; } public static boolean removeLibrary(@NotNull final Module module, @NotNull final String libraryName) { return ApplicationUtilsKt.runWriteAction( new Function0<Boolean>() { @Override public Boolean invoke() { boolean removed = false; ModuleRootManager rootManager = ModuleRootManager.getInstance(module); ModifiableRootModel model = rootManager.getModifiableModel(); for (OrderEntry orderEntry : model.getOrderEntries()) { if (orderEntry instanceof LibraryOrderEntry) { LibraryOrderEntry libraryOrderEntry = (LibraryOrderEntry) orderEntry; Library library = libraryOrderEntry.getLibrary(); if (library != null) { String name = library.getName(); if (name != null && name.equals(libraryName)) { // Dispose attached roots Library.ModifiableModel modifiableModel = library.getModifiableModel(); for (String rootUrl : library.getRootProvider().getUrls(OrderRootType.CLASSES)) { modifiableModel.removeRoot(rootUrl, OrderRootType.CLASSES); } for (String rootUrl : library.getRootProvider().getUrls(OrderRootType.SOURCES)) { modifiableModel.removeRoot(rootUrl, OrderRootType.SOURCES); } modifiableModel.commit(); model.getModuleLibraryTable().removeLibrary(library); removed = true; break; } } } } model.commit(); return removed; } } ); } public static void addLibrary(@NotNull Module module, @NotNull String libraryName, @NotNull String rootPath, @NotNull String[] jarPaths) { NewLibraryEditor editor = new NewLibraryEditor(); editor.setName(libraryName); for (String jarPath : jarPaths) { editor.addRoot(VfsUtil.getUrlForLibraryRoot(new File(rootPath, jarPath)), OrderRootType.CLASSES); } addLibrary(editor, module); } public static void configureLibraries(@NotNull Module module, String rootPath, List<String> libraryInfos) { for (String libraryInfo : libraryInfos) { int i = libraryInfo.indexOf('@'); String libraryName = libraryInfo.substring(0, i); String[] jarPaths = libraryInfo.substring(i + 1).split(";"); addLibrary(module, libraryName, rootPath, jarPaths); } } public static void unconfigureLibrariesByName(@NotNull Module module, List<String> libraryNames) { for (Iterator<String> iterator = libraryNames.iterator(); iterator.hasNext(); ) { String libraryName = iterator.next(); if (removeLibrary(module, libraryName)) { iterator.remove(); } } if (!libraryNames.isEmpty()) throw new AssertionError("Couldn't find the following libraries: " + libraryNames); } public static void unconfigureLibrariesByInfo(@NotNull Module module, List<String> libraryInfos) { List<String> libraryNames = new ArrayList<String>(); for (String libraryInfo : libraryInfos) { libraryNames.add(libraryInfo.substring(0, libraryInfo.indexOf('@'))); } unconfigureLibrariesByName(module, libraryNames); } public static void configureLibrariesByDirective(@NotNull Module module, String rootPath, String fileText) { configureLibraries(module, rootPath, InTextDirectivesUtils.findListWithPrefixes(fileText, "// CONFIGURE_LIBRARY: ")); } public static void unconfigureLibrariesByDirective(@NotNull Module module, String fileText) { List<String> libraryNames = new ArrayList<String>(); for (String libInfo : InTextDirectivesUtils.findListWithPrefixes(fileText, "// CONFIGURE_LIBRARY: ")) { libraryNames.add(libInfo.substring(0, libInfo.indexOf('@'))); } for (String libraryName : InTextDirectivesUtils.findListWithPrefixes(fileText, "// UNCONFIGURE_LIBRARY: ")) { libraryNames.add(libraryName); } unconfigureLibrariesByName(module, libraryNames); } }