diff --git a/idea/src/META-INF/maven.xml b/idea/src/META-INF/maven.xml
index 6f76714ba14..c43b790fb22 100644
--- a/idea/src/META-INF/maven.xml
+++ b/idea/src/META-INF/maven.xml
@@ -3,4 +3,12 @@
+
+
+
+
+
+ org.jetbrains.kotlin.idea.configuration.KotlinImporterComponent
+
+
diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinMavenImporter.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinMavenImporter.kt
new file mode 100644
index 00000000000..67f957eaca6
--- /dev/null
+++ b/idea/src/org/jetbrains/kotlin/idea/configuration/KotlinMavenImporter.kt
@@ -0,0 +1,139 @@
+/*
+ * 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.configuration
+
+import com.intellij.openapi.components.*
+import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
+import com.intellij.openapi.module.Module
+import org.jdom.Element
+import org.jetbrains.idea.maven.importing.MavenImporter
+import org.jetbrains.idea.maven.importing.MavenRootModelAdapter
+import org.jetbrains.idea.maven.model.MavenPlugin
+import org.jetbrains.idea.maven.project.MavenProject
+import org.jetbrains.idea.maven.project.MavenProjectChanges
+import org.jetbrains.idea.maven.project.MavenProjectsProcessorTask
+import org.jetbrains.idea.maven.project.MavenProjectsTree
+import org.jetbrains.jps.model.java.JavaSourceRootType
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType
+import java.io.File
+import java.util.*
+
+private val KotlinPluginGroupId = "org.jetbrains.kotlin"
+private val KotlinPluginArtifactId = "kotlin-maven-plugin"
+private val KotlinPluginSourceDirsConfig = "sourceDirs"
+
+class KotlinMavenImporter : MavenImporter(KotlinPluginGroupId, KotlinPluginArtifactId) {
+ override fun preProcess(module: Module, mavenProject: MavenProject, changes: MavenProjectChanges, modifiableModelsProvider: IdeModifiableModelsProvider) {
+ }
+
+ override fun process(modifiableModelsProvider: IdeModifiableModelsProvider,
+ module: Module,
+ rootModel: MavenRootModelAdapter,
+ mavenModel: MavenProjectsTree,
+ mavenProject: MavenProject,
+ changes: MavenProjectChanges,
+ mavenProjectToModuleName: MutableMap,
+ postTasks: MutableList) {
+
+ if (changes.plugins) {
+ contributeSourceDirectories(mavenProject, module, rootModel)
+ }
+ }
+
+ // TODO in theory it should work like this but it doesn't as it couldn't unmark source roots that are not roots anymore.
+ // I believe this is something should be done by the underlying maven importer implementation or somewhere else in the IDEA
+ // For now there is a contributeSourceDirectories implementation that deals with the issue
+ // see https://youtrack.jetbrains.com/issue/IDEA-148280
+
+ // override fun collectSourceRoots(mavenProject: MavenProject, result: PairConsumer>) {
+ // for ((type, dir) in collectSourceDirectories(mavenProject)) {
+ // val jpsType: JpsModuleSourceRootType<*> = when (type) {
+ // SourceType.PROD -> JavaSourceRootType.SOURCE
+ // SourceType.TEST -> JavaSourceRootType.TEST_SOURCE
+ // }
+ //
+ // result.consume(dir, jpsType)
+ // }
+ // }
+
+ private fun contributeSourceDirectories(mavenProject: MavenProject, module: Module, rootModel: MavenRootModelAdapter) {
+ val directories = collectSourceDirectories(mavenProject)
+
+ val toBeAdded = directories.map { it.second }.toSet()
+ val state = module.kotlinImporterComponent
+
+ for ((type, dir) in directories) {
+ if (rootModel.getSourceFolder(File(dir)) == null) {
+ val jpsType: JpsModuleSourceRootType<*> = when (type) {
+ SourceType.TEST -> JavaSourceRootType.TEST_SOURCE
+ SourceType.PROD -> JavaSourceRootType.SOURCE
+ }
+
+ rootModel.addSourceFolder(dir, jpsType)
+ }
+ }
+
+ state.addedSources.filter { it !in toBeAdded }.forEach {
+ rootModel.unregisterAll(it, true, true)
+ state.addedSources.remove(it)
+ }
+ state.addedSources.addAll(toBeAdded)
+ }
+
+ private fun collectSourceDirectories(mavenProject: MavenProject): List> =
+ mavenProject.plugins.filter { it.isKotlinPlugin() }.flatMap { plugin ->
+ plugin.configurationElement.sourceDirectories().map { SourceType.PROD to it } +
+ plugin.executions.flatMap { execution -> execution.configurationElement.sourceDirectories().map { execution.sourceType() to it } }
+ }.distinct()
+}
+
+private fun MavenPlugin.isKotlinPlugin() = groupId == KotlinPluginGroupId && artifactId == KotlinPluginArtifactId
+private fun Element?.sourceDirectories(): List = this?.getChildren(KotlinPluginSourceDirsConfig)?.flatMap { it.children ?: emptyList() }?.map { it.textTrim } ?: emptyList()
+private fun MavenPlugin.Execution.sourceType() =
+ goals.map { if (isTestGoalName(it)) SourceType.TEST else SourceType.PROD }
+ .distinct()
+ .singleOrNull() ?: SourceType.PROD
+
+private fun isTestGoalName(goalName: String) = goalName.startsWith("test-")
+
+private enum class SourceType {
+ PROD, TEST
+}
+
+@State(name = "AutoImportedSourceRoots",
+ storages = arrayOf(
+ Storage(id = "other", file = StoragePathMacros.MODULE_FILE)
+ ))
+class KotlinImporterComponent : PersistentStateComponent {
+ class State(var directories: List = ArrayList())
+
+ val addedSources = Collections.synchronizedSet(HashSet())
+
+ override fun loadState(state: KotlinImporterComponent.State?) {
+ addedSources.clear()
+ if (state != null) {
+ addedSources.addAll(state.directories)
+ }
+ }
+
+ override fun getState(): KotlinImporterComponent.State {
+ return KotlinImporterComponent.State(addedSources.sorted())
+ }
+}
+
+private val Module.kotlinImporterComponent: KotlinImporterComponent
+ get() = getComponent(KotlinImporterComponent::class.java) ?: throw IllegalStateException("No maven importer state configured")
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt b/idea/tests/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt
new file mode 100644
index 00000000000..751268755cf
--- /dev/null
+++ b/idea/tests/org/jetbrains/kotlin/idea/maven/KotlinMavenImporterTest.kt
@@ -0,0 +1,391 @@
+/*
+ * 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.maven
+
+import org.jetbrains.kotlin.idea.configuration.KotlinImporterComponent
+import java.io.File
+
+class KotlinMavenImporterTest : MavenImportingTestCase() {
+ private val kotlinVersion = "1.0.0-beta-2423"
+
+ override fun setUp() {
+ super.setUp()
+ repositoryPath = File(myDir, "repo").path
+ createStdProjectFolders()
+ }
+
+ fun testSimpleKotlinProject() {
+ importProject("""
+ test
+ project
+ 1.0.0
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ $kotlinVersion
+
+
+ """)
+
+ assertModules("project")
+ assertImporterStatePresent()
+ assertSources("project", "src/main/java")
+ }
+
+ fun testWithSpecifiedSourceRoot() {
+ createProjectSubDir("src/main/kotlin")
+
+ importProject("""
+ test
+ project
+ 1.0.0
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ $kotlinVersion
+
+
+
+
+ src/main/kotlin
+
+ """)
+
+ assertModules("project")
+ assertImporterStatePresent()
+ assertSources("project", "src/main/kotlin")
+ }
+
+ fun testWithCustomSourceDirs() {
+ createProjectSubDirs("src/main/kotlin", "src/main/kotlin.jvm", "src/test/kotlin", "src/test/kotlin.jvm")
+
+ importProject("""
+ test
+ project
+ 1.0.0
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ $kotlinVersion
+
+
+
+
+ src/main/kotlin
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ src/main/kotlin
+ src/main/kotlin.jvm
+
+
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+ src/test/kotlin
+ src/test/kotlin.jvm
+
+
+
+
+
+
+
+ """)
+
+ assertModules("project")
+ assertImporterStatePresent()
+
+ assertSources("project", "src/main/kotlin", "src/main/kotlin.jvm")
+ assertTestSources("project", "src/test/java", "src/test/kotlin", "src/test/kotlin.jvm")
+ }
+
+ fun testReImportRemoveDir() {
+ createProjectSubDirs("src/main/kotlin", "src/main/kotlin.jvm", "src/test/kotlin", "src/test/kotlin.jvm")
+
+ importProject("""
+ test
+ project
+ 1.0.0
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ $kotlinVersion
+
+
+
+
+ src/main/kotlin
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ src/main/kotlin
+ src/main/kotlin.jvm
+
+
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+ src/test/kotlin
+ src/test/kotlin.jvm
+
+
+
+
+
+
+
+ """)
+
+ assertModules("project")
+ assertImporterStatePresent()
+
+ assertSources("project", "src/main/kotlin", "src/main/kotlin.jvm")
+ assertTestSources("project", "src/test/java", "src/test/kotlin", "src/test/kotlin.jvm")
+
+ // reimport
+ importProject("""
+ test
+ project
+ 1.0.0
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ $kotlinVersion
+
+
+
+
+ src/main/kotlin
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ src/main/kotlin
+
+
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+ src/test/kotlin
+ src/test/kotlin.jvm
+
+
+
+
+
+
+
+ """)
+
+ assertSources("project", "src/main/kotlin")
+ assertTestSources("project", "src/test/java", "src/test/kotlin", "src/test/kotlin.jvm")
+ }
+
+ fun testReImportAddDir() {
+ createProjectSubDirs("src/main/kotlin", "src/main/kotlin.jvm", "src/test/kotlin", "src/test/kotlin.jvm")
+
+ importProject("""
+ test
+ project
+ 1.0.0
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ $kotlinVersion
+
+
+
+
+ src/main/kotlin
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ src/main/kotlin
+
+
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+ src/test/kotlin
+ src/test/kotlin.jvm
+
+
+
+
+
+
+
+ """)
+
+ assertModules("project")
+ assertImporterStatePresent()
+
+ assertSources("project", "src/main/kotlin")
+ assertTestSources("project", "src/test/java", "src/test/kotlin", "src/test/kotlin.jvm")
+
+ // reimport
+ importProject("""
+ test
+ project
+ 1.0.0
+
+
+
+ org.jetbrains.kotlin
+ kotlin-stdlib
+ $kotlinVersion
+
+
+
+
+ src/main/kotlin
+
+
+
+ org.jetbrains.kotlin
+ kotlin-maven-plugin
+
+
+
+ compile
+ compile
+
+ compile
+
+
+
+ src/main/kotlin
+ src/main/kotlin.jvm
+
+
+
+
+
+ test-compile
+ test-compile
+
+ test-compile
+
+
+
+ src/test/kotlin
+ src/test/kotlin.jvm
+
+
+
+
+
+
+
+ """)
+
+ assertSources("project", "src/main/kotlin", "src/main/kotlin.jvm")
+ assertTestSources("project", "src/test/java", "src/test/kotlin", "src/test/kotlin.jvm")
+ }
+
+ private fun assertImporterStatePresent() {
+ assertNotNull("Kotlin importer component is not present", myTestFixture.module.getComponent(KotlinImporterComponent::class.java))
+ }
+}
\ No newline at end of file
diff --git a/idea/tests/org/jetbrains/kotlin/idea/maven/MavenImportingTestCase.java b/idea/tests/org/jetbrains/kotlin/idea/maven/MavenImportingTestCase.java
new file mode 100644
index 00000000000..d89262a94da
--- /dev/null
+++ b/idea/tests/org/jetbrains/kotlin/idea/maven/MavenImportingTestCase.java
@@ -0,0 +1,585 @@
+/*
+ * 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.maven;
+
+import com.intellij.compiler.server.BuildManager;
+import com.intellij.openapi.application.AccessToken;
+import com.intellij.openapi.application.ApplicationManager;
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.module.Module;
+import com.intellij.openapi.module.ModuleManager;
+import com.intellij.openapi.progress.EmptyProgressIndicator;
+import com.intellij.openapi.projectRoots.Sdk;
+import com.intellij.openapi.projectRoots.impl.JavaAwareProjectJdkTableImpl;
+import com.intellij.openapi.roots.*;
+import com.intellij.openapi.roots.impl.libraries.ProjectLibraryTable;
+import com.intellij.openapi.roots.libraries.Library;
+import com.intellij.openapi.ui.Messages;
+import com.intellij.openapi.ui.TestDialog;
+import com.intellij.openapi.util.AsyncResult;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VfsUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.newvfs.impl.VfsRootAccess;
+import com.intellij.testFramework.IdeaTestUtil;
+import com.intellij.util.Consumer;
+import com.intellij.util.PathUtil;
+import com.intellij.util.ui.UIUtil;
+import org.jetbrains.annotations.NonNls;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.idea.maven.execution.*;
+import org.jetbrains.idea.maven.model.MavenArtifact;
+import org.jetbrains.idea.maven.model.MavenExplicitProfiles;
+import org.jetbrains.idea.maven.project.*;
+import org.jetbrains.idea.maven.server.MavenServerManager;
+import org.jetbrains.jps.model.java.JavaResourceRootType;
+import org.jetbrains.jps.model.java.JavaSourceRootProperties;
+import org.jetbrains.jps.model.java.JavaSourceRootType;
+import org.jetbrains.jps.model.module.JpsModuleSourceRootType;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.*;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public abstract class MavenImportingTestCase extends MavenTestCase {
+ protected MavenProjectsTree myProjectsTree;
+ protected MavenProjectsManager myProjectsManager;
+ private File myGlobalSettingsFile;
+
+ @Override
+ protected void setUp() throws Exception {
+ VfsRootAccess.allowRootAccess(PathManager.getConfigPath());
+ super.setUp();
+ myGlobalSettingsFile =
+ MavenWorkspaceSettingsComponent.getInstance(myProject).getSettings().generalSettings.getEffectiveGlobalSettingsIoFile();
+ if (myGlobalSettingsFile != null) {
+ VfsRootAccess.allowRootAccess(myGlobalSettingsFile.getAbsolutePath());
+ }
+ }
+
+ @Override
+ protected void setUpInWriteAction() throws Exception {
+ super.setUpInWriteAction();
+ myProjectsManager = MavenProjectsManager.getInstance(myProject);
+ removeFromLocalRepository("test");
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ try {
+ if (myGlobalSettingsFile != null) {
+ VfsRootAccess.disallowRootAccess(myGlobalSettingsFile.getAbsolutePath());
+ }
+ VfsRootAccess.disallowRootAccess(PathManager.getConfigPath());
+ Messages.setTestDialog(TestDialog.DEFAULT);
+ removeFromLocalRepository("test");
+ FileUtil.delete(BuildManager.getInstance().getBuildSystemDirectory());
+ }
+ finally {
+ super.tearDown();
+ }
+ }
+
+ protected void assertModules(String... expectedNames) {
+ Module[] actual = ModuleManager.getInstance(myProject).getModules();
+ List actualNames = new ArrayList();
+
+ for (Module m : actual) {
+ actualNames.add(m.getName());
+ }
+
+ assertUnorderedElementsAreEqual(actualNames, expectedNames);
+ }
+
+ protected void assertContentRoots(String moduleName, String... expectedRoots) {
+ List actual = new ArrayList();
+ for (ContentEntry e : getContentRoots(moduleName)) {
+ actual.add(e.getUrl());
+ }
+
+ for (int i = 0; i < expectedRoots.length; i++) {
+ expectedRoots[i] = VfsUtil.pathToUrl(expectedRoots[i]);
+ }
+
+ assertUnorderedPathsAreEqual(actual, Arrays.asList(expectedRoots));
+ }
+
+ protected void assertSources(String moduleName, String... expectedSources) {
+ doAssertContentFolders(moduleName, JavaSourceRootType.SOURCE, expectedSources);
+ }
+
+ protected void assertGeneratedSources(String moduleName, String... expectedSources) {
+ ContentEntry contentRoot = getContentRoot(moduleName);
+ List folders = new ArrayList();
+ for (SourceFolder folder : contentRoot.getSourceFolders(JavaSourceRootType.SOURCE)) {
+ JavaSourceRootProperties properties = folder.getJpsElement().getProperties(JavaSourceRootType.SOURCE);
+ assertNotNull(properties);
+ if (properties.isForGeneratedSources()) {
+ folders.add(folder);
+ }
+ }
+ doAssertContentFolders(contentRoot, folders, expectedSources);
+ }
+
+ protected void assertResources(String moduleName, String... expectedSources) {
+ doAssertContentFolders(moduleName, JavaResourceRootType.RESOURCE, expectedSources);
+ }
+
+ protected void assertTestSources(String moduleName, String... expectedSources) {
+ doAssertContentFolders(moduleName, JavaSourceRootType.TEST_SOURCE, expectedSources);
+ }
+
+ protected void assertTestResources(String moduleName, String... expectedSources) {
+ doAssertContentFolders(moduleName, JavaResourceRootType.TEST_RESOURCE, expectedSources);
+ }
+
+ protected void assertExcludes(String moduleName, String... expectedExcludes) {
+ ContentEntry contentRoot = getContentRoot(moduleName);
+ doAssertContentFolders(contentRoot, Arrays.asList(contentRoot.getExcludeFolders()), expectedExcludes);
+ }
+
+ protected void assertContentRootExcludes(String moduleName, String contentRoot, String... expectedExcudes) {
+ ContentEntry root = getContentRoot(moduleName, contentRoot);
+ doAssertContentFolders(root, Arrays.asList(root.getExcludeFolders()), expectedExcudes);
+ }
+
+ private void doAssertContentFolders(String moduleName, @NotNull JpsModuleSourceRootType> rootType, String... expected) {
+ ContentEntry contentRoot = getContentRoot(moduleName);
+ doAssertContentFolders(contentRoot, contentRoot.getSourceFolders(rootType), expected);
+ }
+
+ private static void doAssertContentFolders(ContentEntry e, final List extends ContentFolder> folders, String... expected) {
+ List actual = new ArrayList();
+ for (ContentFolder f : folders) {
+ String rootUrl = e.getUrl();
+ String folderUrl = f.getUrl();
+
+ if (folderUrl.startsWith(rootUrl)) {
+ int length = rootUrl.length() + 1;
+ folderUrl = folderUrl.substring(Math.min(length, folderUrl.length()));
+ }
+
+ actual.add(folderUrl);
+ }
+
+ assertOrderedElementsAreEqual(actual, Arrays.asList(expected));
+ }
+
+ protected void assertModuleOutput(String moduleName, String output, String testOutput) {
+ CompilerModuleExtension e = getCompilerExtension(moduleName);
+
+ assertFalse(e.isCompilerOutputPathInherited());
+ assertEquals(output, getAbsolutePath(e.getCompilerOutputUrl()));
+ assertEquals(testOutput, getAbsolutePath(e.getCompilerOutputUrlForTests()));
+ }
+
+ private static String getAbsolutePath(String path) {
+ path = VfsUtil.urlToPath(path);
+ path = PathUtil.getCanonicalPath(path);
+ return FileUtil.toSystemIndependentName(path);
+ }
+
+ protected void assertProjectOutput(String module) {
+ assertTrue(getCompilerExtension(module).isCompilerOutputPathInherited());
+ }
+
+ protected CompilerModuleExtension getCompilerExtension(String module) {
+ ModuleRootManager m = getRootManager(module);
+ return CompilerModuleExtension.getInstance(m.getModule());
+ }
+
+ protected void assertModuleLibDep(String moduleName, String depName) {
+ assertModuleLibDep(moduleName, depName, null);
+ }
+
+ protected void assertModuleLibDep(String moduleName, String depName, String classesPath) {
+ assertModuleLibDep(moduleName, depName, classesPath, null, null);
+ }
+
+ protected void assertModuleLibDep(String moduleName, String depName, String classesPath, String sourcePath, String javadocPath) {
+ LibraryOrderEntry lib = getModuleLibDep(moduleName, depName);
+
+ assertModuleLibDepPath(lib, OrderRootType.CLASSES, classesPath == null ? null : Collections.singletonList(classesPath));
+ assertModuleLibDepPath(lib, OrderRootType.SOURCES, sourcePath == null ? null : Collections.singletonList(sourcePath));
+ assertModuleLibDepPath(lib, JavadocOrderRootType.getInstance(), javadocPath == null ? null : Collections.singletonList(javadocPath));
+ }
+
+ protected void assertModuleLibDep(String moduleName,
+ String depName,
+ List classesPaths,
+ List sourcePaths,
+ List javadocPaths) {
+ LibraryOrderEntry lib = getModuleLibDep(moduleName, depName);
+
+ assertModuleLibDepPath(lib, OrderRootType.CLASSES, classesPaths);
+ assertModuleLibDepPath(lib, OrderRootType.SOURCES, sourcePaths);
+ assertModuleLibDepPath(lib, JavadocOrderRootType.getInstance(), javadocPaths);
+ }
+
+ private static void assertModuleLibDepPath(LibraryOrderEntry lib, OrderRootType type, List paths) {
+ if (paths == null) return;
+ assertUnorderedPathsAreEqual(Arrays.asList(lib.getRootUrls(type)), paths);
+ // also check the library because it may contain slight different set of urls (e.g. with duplicates)
+ assertUnorderedPathsAreEqual(Arrays.asList(lib.getLibrary().getUrls(type)), paths);
+ }
+
+ protected void assertModuleLibDepScope(String moduleName, String depName, DependencyScope scope) {
+ LibraryOrderEntry dep = getModuleLibDep(moduleName, depName);
+ assertEquals(scope, dep.getScope());
+ }
+
+ private LibraryOrderEntry getModuleLibDep(String moduleName, String depName) {
+ return getModuleDep(moduleName, depName, LibraryOrderEntry.class);
+ }
+
+ protected void assertModuleLibDeps(String moduleName, String... expectedDeps) {
+ assertModuleDeps(moduleName, LibraryOrderEntry.class, expectedDeps);
+ }
+
+ protected void assertExportedDeps(String moduleName, String... expectedDeps) {
+ final List actual = new ArrayList();
+
+ getRootManager(moduleName).orderEntries().withoutSdk().withoutModuleSourceEntries().exportedOnly().process(new RootPolicy