Maven: extract maven support to the separate module

This commit is contained in:
Sergey Mashkov
2016-04-01 17:49:28 +03:00
parent dfaba1d0aa
commit fc197cd616
64 changed files with 221 additions and 55 deletions
+24
View File
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/resources" type="java-resource" />
</content>
<orderEntry type="jdk" jdkName="1.8" jdkType="JavaSDK" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="idea-full" level="project" />
<orderEntry type="module" module-name="idea" />
<orderEntry type="library" scope="PROVIDED" name="maven" level="project" />
<orderEntry type="module" module-name="frontend" />
<orderEntry type="library" name="kotlin-runtime" level="project" />
<orderEntry type="library" scope="TEST" name="kotlin-test" level="project" />
<orderEntry type="module" module-name="js.frontend" />
<orderEntry type="module" module-name="util.runtime" />
<orderEntry type="module" module-name="frontend.java" />
<orderEntry type="library" scope="TEST" name="kotlin-reflect" level="project" />
<orderEntry type="module" module-name="tests-common" scope="TEST" />
</component>
</module>
@@ -0,0 +1,5 @@
<html>
<body>
This intention moves source directory from execution's configuration to build the corresponding source directory tag
</body>
</html>
@@ -0,0 +1,6 @@
<html>
<body>
This intention moves source directory from build source directory tag
to the corresponding kotlin-maven-plugin execution's configuration
</body>
</html>
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2016 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.module.Module;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.dom.model.MavenDomPlugin;
import org.jetbrains.kotlin.resolve.TargetPlatform;
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
public class KotlinJavaMavenConfigurator extends KotlinMavenConfigurator {
private static final String NAME = "maven";
public static final String STD_LIB_ID = "kotlin-stdlib";
private static final String TEST_LIB_ID = "kotlin-test-junit";
private static final String PRESENTABLE_TEXT = "Maven";
public KotlinJavaMavenConfigurator() {
super(STD_LIB_ID, TEST_LIB_ID, true, NAME, PRESENTABLE_TEXT);
}
@Override
protected boolean isKotlinModule(@NotNull Module module) {
return ConfigureKotlinInProjectUtilsKt.hasKotlinJvmRuntimeInScope(module);
}
@Override
protected boolean isRelevantGoal(@NotNull String goalName) {
return goalName.equals(PomFile.KotlinGoals.INSTANCE.getCompile());
}
@Override
protected void createExecutions(@NotNull PomFile pomFile, @NotNull MavenDomPlugin kotlinPlugin, @NotNull Module module) {
createExecution(pomFile, kotlinPlugin, module, false);
createExecution(pomFile, kotlinPlugin, module, true);
}
@NotNull
@Override
protected String getGoal(boolean isTest) {
return isTest ? PomFile.KotlinGoals.INSTANCE.getTestCompile() : PomFile.KotlinGoals.INSTANCE.getCompile();
}
@NotNull
@Override
public TargetPlatform getTargetPlatform() {
return JvmPlatform.INSTANCE;
}
}
@@ -0,0 +1,70 @@
/*
* Copyright 2010-2016 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.module.Module;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.dom.model.MavenDomPlugin;
import org.jetbrains.kotlin.js.resolve.JsPlatform;
import org.jetbrains.kotlin.resolve.TargetPlatform;
public class KotlinJavascriptMavenConfigurator extends KotlinMavenConfigurator {
private static final String NAME = "js maven";
public static final String STD_LIB_ID = "kotlin-js-library";
private static final String JS_GOAL = "js";
private static final String JS_TEST_GOAL = "test-js";
private static final String JS_EXECUTION_ID = "js";
private static final String PRESENTABLE_TEXT = "JavaScript Maven - experimental";
public KotlinJavascriptMavenConfigurator() {
super(STD_LIB_ID, null, false, NAME, PRESENTABLE_TEXT);
}
@Override
protected boolean isKotlinModule(@NotNull Module module) {
return ConfigureKotlinInProjectUtilsKt.hasKotlinJsRuntimeInScope(module);
}
@Override
protected boolean isRelevantGoal(@NotNull String goalName) {
return goalName.equals(PomFile.KotlinGoals.INSTANCE.getJs());
}
@Override
protected void createExecutions(@NotNull PomFile pomFile, @NotNull MavenDomPlugin kotlinPlugin, @NotNull Module module) {
createExecution(pomFile, kotlinPlugin, module, false);
createExecution(pomFile, kotlinPlugin, module, true);
}
@NotNull
@Override
protected String getExecutionId(boolean isTest) {
return JS_EXECUTION_ID + (isTest ? "-test" : "");
}
@NotNull
@Override
protected String getGoal(boolean isTest) {
return isTest ? JS_TEST_GOAL : JS_GOAL;
}
@NotNull
@Override
public TargetPlatform getTargetPlatform() {
return JsPlatform.INSTANCE;
}
}
@@ -0,0 +1,106 @@
/*
* Copyright 2010-2016 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.google.gson.JsonElement
import com.google.gson.JsonParser
import com.intellij.util.net.HttpConfigurable
import org.jetbrains.idea.maven.dom.MavenVersionComparable
import org.jetbrains.idea.maven.indices.MavenArchetypesProvider
import org.jetbrains.idea.maven.model.MavenArchetype
import org.jetbrains.kotlin.idea.KotlinPluginUtil
import org.jetbrains.kotlin.utils.ifEmpty
import java.net.HttpURLConnection
import java.net.URLEncoder
import java.util.concurrent.TimeUnit
class KotlinMavenArchetypesProvider(val kotlinPluginVersion: String) : MavenArchetypesProvider {
constructor() : this(KotlinPluginUtil.getPluginVersion())
val VERSIONS_LIST_URL = mavenSearchUrl("org.jetbrains.kotlin", packaging = "maven-archetype", rowsLimit = 1000)
private val versionPrefix by lazy { """^\d+\.\d+\.""".toRegex().find(kotlinPluginVersion)?.value ?: "1.0." }
private val archetypesBlocking by lazy {
try {
loadVersions().ifEmpty { defaultArchetypes() }
} catch (t: Throwable) {
defaultArchetypes()
}
}
override fun getArchetypes() = archetypesBlocking.toMutableList()
private fun defaultArchetypes() = listOf(MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.0.0", null, null))
private fun loadVersions(): List<MavenArchetype> {
return connectAndApply(VERSIONS_LIST_URL) { urlConnection ->
urlConnection.inputStream.bufferedReader().use { reader ->
extractVersions(JsonParser().parse(reader))
}
}
}
internal fun extractVersions(root: JsonElement) =
root.asJsonObject.get("response")
.asJsonObject.get("docs")
.asJsonArray
.map { it.asJsonObject }
.map { MavenArchetype(it.get("g").asString, it.get("a").asString, it.get("v").asString, null, null) }
.filter { it.version?.startsWith(versionPrefix) ?: false }
.groupBy { it.groupId + ":" + it.artifactId }
.mapValues { chooseVersion(it.value) }
.mapNotNull { it.value }
private fun chooseVersion(versions: List<MavenArchetype>): MavenArchetype? {
return versions.maxBy { MavenVersionComparable(it.version) }
}
private fun mavenSearchUrl(group: String, artifactId: String? = null, version: String? = null, packaging: String? = null, rowsLimit: Int = 20): String {
val q = listOf(
"g" to group,
"a" to artifactId,
"v" to version,
"p" to packaging
)
.filter { it.second != null }
.map { "${it.first}:\"${it.second}\"" }
.joinToString(separator = " AND ")
return "http://search.maven.org/solrsearch/select?q=${q.encodeURL()}&core=gav&rows=$rowsLimit&wt=json"
}
private fun <R> connectAndApply(url: String, timeoutSeconds: Int = 15, block: (HttpURLConnection) -> R): R {
return HttpConfigurable.getInstance().openHttpConnection(url).use { urlConnection ->
val timeout = TimeUnit.SECONDS.toMillis(timeoutSeconds.toLong()).toInt()
urlConnection.connectTimeout = timeout
urlConnection.readTimeout = timeout
urlConnection.connect()
block(urlConnection)
}
}
private fun <R> HttpURLConnection.use(block: (HttpURLConnection) -> R): R =
try {
block(this)
}
finally {
disconnect()
}
private fun String.encodeURL() = URLEncoder.encode(this, "UTF-8")
}
@@ -0,0 +1,258 @@
/*
* Copyright 2010-2016 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.codeInsight.CodeInsightUtilCore;
import com.intellij.ide.actions.OpenFileAction;
import com.intellij.ide.highlighter.JavaFileType;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleUtilCore;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.WritingAccessProvider;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import com.intellij.psi.search.FileTypeIndex;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.psi.xml.XmlFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.idea.maven.dom.MavenDomUtil;
import org.jetbrains.idea.maven.dom.model.MavenDomPlugin;
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel;
import org.jetbrains.idea.maven.model.MavenId;
import org.jetbrains.idea.maven.model.MavenPlugin;
import org.jetbrains.idea.maven.project.MavenProject;
import org.jetbrains.idea.maven.project.MavenProjectsManager;
import org.jetbrains.idea.maven.utils.MavenArtifactScope;
import org.jetbrains.kotlin.idea.KotlinPluginUtil;
import org.jetbrains.kotlin.idea.framework.ui.ConfigureDialogWithModulesAndVersion;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public abstract class KotlinMavenConfigurator implements KotlinProjectConfigurator {
public static final String NAME = "maven";
public static final String GROUP_ID = "org.jetbrains.kotlin";
public static final String MAVEN_PLUGIN_ID = "kotlin-maven-plugin";
private static final String KOTLIN_VERSION_PROPERTY = "kotlin.version";
private static final String TEST_COMPILE_EXECUTION_ID = "test-compile";
private static final String COMPILE_EXECUTION_ID = "compile";
private final String stdlibArtifactId;
private final String testArtifactId;
private final boolean addJunit;
private final String name;
private final String presentableText;
protected KotlinMavenConfigurator(@NotNull String stdlibArtifactId, @Nullable String testArtifactId, boolean addJunit, @NotNull String name, @NotNull String presentableText) {
this.stdlibArtifactId = stdlibArtifactId;
this.testArtifactId = testArtifactId;
this.addJunit = addJunit;
this.name = name;
this.presentableText = presentableText;
}
@Override
public boolean isApplicable(@NotNull Module module) {
return KotlinPluginUtil.isMavenModule(module);
}
@NotNull
@Override
public String getPresentableText() {
return presentableText;
}
@NotNull
@Override
public String getName() {
return name;
}
@Override
public boolean isConfigured(@NotNull Module module) {
if (!isKotlinModule(module)) {
return false;
}
PsiFile psi = findModulePomFile(module);
if (psi == null
|| !psi.isValid()
|| !(psi instanceof XmlFile)
|| psi.getVirtualFile() == null
|| MavenDomUtil.getMavenDomProjectModel(module.getProject(), psi.getVirtualFile()) == null) {
return false;
}
MavenProject mavenProject = MavenProjectsManager.getInstance(module.getProject()).findProject(module);
if (mavenProject == null) {
return false;
}
MavenPlugin plugin = mavenProject.findPlugin(GROUP_ID, MAVEN_PLUGIN_ID);
if (plugin == null) {
return false;
}
if (plugin.getExecutions() != null) {
for (MavenPlugin.Execution execution : plugin.getExecutions()) {
if (execution.getGoals() != null) {
for (String goal : execution.getGoals()) {
if (goal != null && isRelevantGoal(goal)) {
return true;
}
}
}
}
}
return false;
}
@Override
public void configure(@NotNull Project project, Collection<Module> excludeModules) {
ConfigureDialogWithModulesAndVersion dialog =
new ConfigureDialogWithModulesAndVersion(project, this, excludeModules);
dialog.show();
if (!dialog.isOK()) return;
NotificationMessageCollector collector = NotificationMessageCollectorKt.createConfigureKotlinNotificationCollector(project);
for (Module module : MavenModulesRelationshipKt.excludeMavenChildrenModules(project, dialog.getModulesToConfigure())) {
PsiFile file = findModulePomFile(module);
if (file != null && canConfigureFile(file)) {
changePomFile(module, file, dialog.getKotlinVersion(), collector);
OpenFileAction.openFile(file.getVirtualFile(), project);
}
else {
showErrorMessage(project, "Cannot find pom.xml for module " + module.getName());
}
}
collector.showNotification();
}
protected abstract boolean isKotlinModule(@NotNull Module module);
protected abstract boolean isRelevantGoal(@NotNull String goalName);
protected abstract void createExecutions(@NotNull PomFile pomFile, @NotNull MavenDomPlugin kotlinPlugin, @NotNull Module module);
@NotNull
protected abstract String getGoal(boolean isTest);
@NotNull
protected String getExecutionId(boolean isTest) {
return isTest ? TEST_COMPILE_EXECUTION_ID : COMPILE_EXECUTION_ID;
}
protected void changePomFile(
@NotNull final Module module,
final @NotNull PsiFile file,
@NotNull final String version,
@NotNull NotificationMessageCollector collector
) {
VirtualFile virtualFile = file.getVirtualFile();
assert virtualFile != null : "Virtual file should exists for psi file " + file.getName();
MavenDomProjectModel domModel = MavenDomUtil.getMavenDomProjectModel(module.getProject(), virtualFile);
if (domModel == null) {
showErrorMessage(module.getProject(), null);
return;
}
new WriteCommandAction(file.getProject()) {
@Override
protected void run(@NotNull Result result) {
PomFile pom = new PomFile((XmlFile) file);
pom.addProperty(KOTLIN_VERSION_PROPERTY, version);
pom.addDependency(new MavenId(GROUP_ID, stdlibArtifactId, "${" + KOTLIN_VERSION_PROPERTY + "}"), MavenArtifactScope.COMPILE, null, false, null);
if (testArtifactId != null) {
pom.addDependency(new MavenId(GROUP_ID, testArtifactId, "${" + KOTLIN_VERSION_PROPERTY + "}"), MavenArtifactScope.TEST, null, false, null);
}
if (addJunit) {
pom.addDependency(new MavenId("junit", "junit", "4.12"), MavenArtifactScope.TEST, null, false, null);
}
if (isSnapshot(version)) {
pom.addLibraryRepository(ConfigureKotlinInProjectUtilsKt.SNAPSHOT_REPOSITORY, true, false);
pom.addPluginRepository(ConfigureKotlinInProjectUtilsKt.SNAPSHOT_REPOSITORY, true, false);
}
if (ConfigureKotlinInProjectUtilsKt.isEap(version)) {
pom.addLibraryRepository(ConfigureKotlinInProjectUtilsKt.EAP_REPOSITORY, true, false);
pom.addPluginRepository(ConfigureKotlinInProjectUtilsKt.EAP_REPOSITORY, true, false);
}
MavenDomPlugin plugin = pom.addPlugin(new MavenId(GROUP_ID, MAVEN_PLUGIN_ID, "${" + KOTLIN_VERSION_PROPERTY + "}"));
createExecutions(pom, plugin, module);
CodeInsightUtilCore.forcePsiPostprocessAndRestoreElement(file);
}
}.execute();
collector.addMessage(virtualFile.getPath() + " was modified");
}
protected void createExecution(
@NotNull PomFile pomFile,
@NotNull MavenDomPlugin kotlinPlugin,
@NotNull Module module,
boolean isTest
) {
pomFile.addKotlinExecution(module, kotlinPlugin, getExecutionId(isTest), PomFile.Companion.getPhase(hasJavaFiles(module), isTest), isTest,
Collections.singletonList(getGoal(isTest)));
}
private static boolean hasJavaFiles(@NotNull Module module) {
return !FileTypeIndex.getFiles(JavaFileType.INSTANCE, GlobalSearchScope.moduleScope(module)).isEmpty();
}
@Nullable
private static PsiFile findModulePomFile(@NotNull Module module) {
List<VirtualFile> files = MavenProjectsManager.getInstance(module.getProject()).getProjectsFiles();
for (VirtualFile file : files) {
Module fileModule = ModuleUtilCore.findModuleForFile(file, module.getProject());
if (!module.equals(fileModule)) continue;
PsiFile psiFile = PsiManager.getInstance(module.getProject()).findFile(file);
if (psiFile == null) continue;
if (!MavenDomUtil.isProjectFile(psiFile)) continue;
return psiFile;
}
return null;
}
private static boolean isSnapshot(@NotNull String version) {
return version.contains("SNAPSHOT");
}
private static boolean canConfigureFile(@NotNull PsiFile file) {
return WritingAccessProvider.isPotentiallyWritable(file.getVirtualFile(), null);
}
private static void showErrorMessage(@NotNull Project project, @Nullable String message) {
Messages.showErrorDialog(project,
"<html>Couldn't configure kotlin-maven plugin automatically.<br/>" +
(message != null ? message : "") +
"See manual installation instructions <a href=\"http://confluence.jetbrains.com/display/Kotlin/Kotlin+Build+Tools#KotlinBuildTools-Maven\">here</a></html>",
"Configure Kotlin-Maven Plugin");
}
}
@@ -0,0 +1,142 @@
/*
* Copyright 2010-2016 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.PersistentStateComponent
import com.intellij.openapi.components.State
import com.intellij.openapi.components.Storage
import com.intellij.openapi.components.StoragePathMacros
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<MavenProject, String>,
postTasks: MutableList<MavenProjectsProcessorTask>) {
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<String, JpsModuleSourceRootType<*>>) {
// 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<Pair<SourceType, String>> =
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<String> = 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<KotlinImporterComponent.State> {
class State(var directories: List<String> = ArrayList())
val addedSources = Collections.synchronizedSet(HashSet<String>())
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")
@@ -0,0 +1,200 @@
/*
* Copyright 2010-2016 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.codeInspection.LocalQuickFix
import com.intellij.codeInspection.ProblemDescriptor
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.lang.annotation.HighlightSeverity
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.psi.search.FileTypeIndex
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.xml.XmlFile
import com.intellij.util.xml.DomFileElement
import com.intellij.util.xml.highlighting.DomElementAnnotationHolder
import com.intellij.util.xml.highlighting.DomElementsInspection
import org.jetbrains.idea.maven.dom.model.MavenDomGoal
import org.jetbrains.idea.maven.dom.model.MavenDomPlugin
import org.jetbrains.idea.maven.dom.model.MavenDomPluginExecution
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel
import org.jetbrains.idea.maven.model.MavenId
import org.jetbrains.idea.maven.model.MavenPlugin
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.idea.maven.utils.MavenArtifactScope
import org.jetbrains.kotlin.idea.KotlinFileType
import java.util.*
class KotlinMavenPluginPhaseInspection : DomElementsInspection<MavenDomProjectModel>(MavenDomProjectModel::class.java) {
override fun getStaticDescription() = "The inspecition's purpose is to check Maven pom and kotlin maven plugin configuration"
override fun checkFileElement(domFileElement: DomFileElement<MavenDomProjectModel>?, holder: DomElementAnnotationHolder?) {
if (domFileElement == null || holder == null) {
return
}
val module = domFileElement.module ?: return
val manager = MavenProjectsManager.getInstance(module.project)
val mavenProject = manager.findProject(module) ?: return
val pom = PomFile(domFileElement.file)
val hasJavaFiles = module.hasJavaFiles()
// all executions including inherited
val executions = mavenProject.plugins
.filter { it.isKotlinMavenPlugin() }
.flatMap { it.executions }
val allGoalsSet: Set<String> = executions.flatMapTo(HashSet()) { it.goals }
val hasJvmExecution = PomFile.KotlinGoals.Compile in allGoalsSet || PomFile.KotlinGoals.TestCompile in allGoalsSet
val hasJsExecution = PomFile.KotlinGoals.Js in allGoalsSet || PomFile.KotlinGoals.TestJs in allGoalsSet
val pomKotlinPlugins = pom.findKotlinPlugins()
for (kotlinPlugin in pomKotlinPlugins) {
if (PomFile.KotlinGoals.Compile !in allGoalsSet && PomFile.KotlinGoals.Js !in allGoalsSet) {
val fixes = if (hasJavaFiles) {
arrayOf(AddExecutionLocalFix(domFileElement.file, module, kotlinPlugin, PomFile.KotlinGoals.Compile))
}
else {
arrayOf(AddExecutionLocalFix(domFileElement.file, module, kotlinPlugin, PomFile.KotlinGoals.Compile),
AddExecutionLocalFix(domFileElement.file, module, kotlinPlugin, PomFile.KotlinGoals.Js))
}
holder.createProblem(kotlinPlugin.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"Kotlin plugin has no compile executions",
*fixes)
}
else {
if (hasJavaFiles) {
pom.findExecutions(kotlinPlugin, PomFile.KotlinGoals.Compile).notAtPhase(PomFile.DefaultPhases.ProcessSources).forEach { badExecution ->
holder.createProblem(badExecution.phase.createStableCopy(),
HighlightSeverity.WARNING,
"Kotlin plugin should run before javac so kotlin classes could be visible from Java",
FixExecutionPhaseLocalFix(badExecution, PomFile.DefaultPhases.ProcessSources))
}
pom.findExecutions(kotlinPlugin, PomFile.KotlinGoals.Js, PomFile.KotlinGoals.TestJs).forEach { badExecution ->
holder.createProblem(badExecution.goals.goals.first { it.isJsGoal() }.createStableCopy(),
HighlightSeverity.WARNING,
"JavaScript goal configured for module with Java files")
}
}
val stdlibDependencies = mavenProject.findDependencies(KotlinJavaMavenConfigurator.GROUP_ID, KotlinJavaMavenConfigurator.STD_LIB_ID)
val jsDependencies = mavenProject.findDependencies(KotlinJavaMavenConfigurator.GROUP_ID, KotlinJavascriptMavenConfigurator.STD_LIB_ID)
if (hasJvmExecution && stdlibDependencies.isEmpty()) {
holder.createProblem(kotlinPlugin.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"Kotlin JVM compiler configured but no ${KotlinJavaMavenConfigurator.STD_LIB_ID} dependency",
FixAddStdlibLocalFix(domFileElement.file, KotlinJavaMavenConfigurator.STD_LIB_ID, kotlinPlugin.version.rawText))
}
if (hasJsExecution && jsDependencies.isEmpty()) {
holder.createProblem(kotlinPlugin.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"Kotlin JavaScript compiler configured but no ${KotlinJavascriptMavenConfigurator.STD_LIB_ID} dependency",
FixAddStdlibLocalFix(domFileElement.file, KotlinJavascriptMavenConfigurator.STD_LIB_ID, kotlinPlugin.version.rawText))
}
}
}
val stdlibDependencies = pom.findDependencies(MavenId(KotlinJavaMavenConfigurator.GROUP_ID, KotlinJavaMavenConfigurator.STD_LIB_ID, null))
if (!hasJvmExecution && stdlibDependencies.isNotEmpty()) {
stdlibDependencies.forEach { dep ->
holder.createProblem(dep.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"You have ${dep.artifactId} configured but no corresponding plugin execution",
ConfigurePluginExecutionLocalFix(module, domFileElement.file, PomFile.KotlinGoals.Compile, dep.version.rawText))
}
}
val stdlibJsDependencies = pom.findDependencies(MavenId(KotlinJavaMavenConfigurator.GROUP_ID, KotlinJavascriptMavenConfigurator.STD_LIB_ID, null))
if (!hasJsExecution && stdlibJsDependencies.isNotEmpty()) {
stdlibJsDependencies.forEach { dep ->
holder.createProblem(dep.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"You have ${dep.artifactId} configured but no corresponding plugin execution",
ConfigurePluginExecutionLocalFix(module, domFileElement.file, PomFile.KotlinGoals.Js, dep.version.rawText))
}
}
pom.findKotlinExecutions().filter {
it.goals.goals.any { it.rawText == PomFile.KotlinGoals.Compile || it.rawText == PomFile.KotlinGoals.Js }
&& it.goals.goals.any { it.rawText == PomFile.KotlinGoals.TestCompile || it.rawText == PomFile.KotlinGoals.TestJs }
}.forEach { badExecution ->
holder.createProblem(badExecution.goals.createStableCopy(),
HighlightSeverity.WEAK_WARNING,
"It is not recommended to have both test and compile goals in the same execution")
}
}
private class AddExecutionLocalFix(val file: XmlFile, val module: Module, val kotlinPlugin: MavenDomPlugin, val goal: String) : LocalQuickFix {
override fun getName() = "Create $goal execution"
override fun getFamilyName() = "Kotlin"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val pom = PomFile(file)
pom.addKotlinExecution(module, kotlinPlugin, goal, PomFile.getPhase(module.hasJavaFiles(), false), false, listOf(goal))
}
}
private class FixExecutionPhaseLocalFix(val execution: MavenDomPluginExecution, val newPhase: String) : LocalQuickFix {
override fun getName() = "Change phase to $newPhase"
override fun getFamilyName() = "Kotlin"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
execution.phase.value = newPhase
}
}
private class FixAddStdlibLocalFix(val pomFile: XmlFile, val id: String, val version: String?) : LocalQuickFix {
override fun getName() = "Add $id dependency"
override fun getFamilyName() = "Kotlin"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val file = PomFile(pomFile)
file.addDependency(MavenId(KotlinJavaMavenConfigurator.GROUP_ID, id, version), MavenArtifactScope.COMPILE)
}
}
private class ConfigurePluginExecutionLocalFix(val module: Module, val xmlFile: XmlFile, val goal: String, val version: String?) : LocalQuickFix {
override fun getName() = "Create $goal execution of kotlin-maven-compiler"
override fun getFamilyName() = "Kotlin"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
val pom = PomFile(xmlFile)
val plugin = pom.addKotlinPlugin(version)
pom.addKotlinExecution(module, plugin, "compile", PomFile.getPhase(module.hasJavaFiles(), false), false, listOf(goal))
}
}
}
fun Module.hasJavaFiles(): Boolean {
return FileTypeIndex.containsFileOfType(JavaFileType.INSTANCE, GlobalSearchScope.moduleScope(this))
}
private fun MavenPlugin.isKotlinMavenPlugin() = groupId == KotlinMavenConfigurator.GROUP_ID
&& artifactId == KotlinMavenConfigurator.MAVEN_PLUGIN_ID
private fun MavenDomGoal.isJsGoal() = rawText == PomFile.KotlinGoals.Js || rawText == PomFile.KotlinGoals.TestJs
private fun List<MavenDomPluginExecution>.atPhase(phase: String) = filter { it.phase.stringValue == phase }
private fun List<MavenDomPluginExecution>.notAtPhase(phase: String) = filter { it.phase.stringValue != phase }
@@ -0,0 +1,146 @@
/*
* Copyright 2010-2016 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.codeInsight.daemon.HighlightDisplayKey
import com.intellij.codeInsight.daemon.QuickFixActionRegistrar
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.codeInsight.intention.LowPriorityAction
import com.intellij.codeInsight.quickfix.UnresolvedReferenceQuickFixProvider
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.module.ModuleUtilCore
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.openapi.util.Condition
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiFile
import com.intellij.psi.PsiManager
import com.intellij.psi.SmartPsiElementPointer
import com.intellij.psi.xml.XmlFile
import org.jetbrains.idea.maven.dom.MavenDomUtil
import org.jetbrains.idea.maven.indices.MavenArtifactSearchDialog
import org.jetbrains.idea.maven.project.MavenProjectsManager
import org.jetbrains.idea.maven.utils.MavenArtifactScope
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.core.quickfix.QuickFixUtil
import org.jetbrains.kotlin.idea.quickfix.IntentionActionPriority
import org.jetbrains.kotlin.idea.quickfix.KotlinIntentionActionFactoryWithDelegate
import org.jetbrains.kotlin.idea.quickfix.QuickFixWithDelegateFactory
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.psi.KtImportDirective
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtSimpleNameExpression
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import java.util.*
class KotlinMavenUnresolvedReferenceQuickFixProvider : UnresolvedReferenceQuickFixProvider<KtSimpleNameReference>() {
override fun getReferenceClass(): Class<KtSimpleNameReference> = KtSimpleNameReference::class.java
override fun registerFixes(ref: KtSimpleNameReference, registrar: QuickFixActionRegistrar) {
val module = ModuleUtilCore.findModuleForPsiElement(ref.expression) ?: return
if (!MavenProjectsManager.getInstance(module.project).isMavenizedModule(module)) {
return
}
val expression = ref.expression
val importDirective = expression.getParentOfType<KtImportDirective>(true)
val name = if (importDirective != null) {
if (importDirective.isAllUnder) {
null
} else {
importDirective.importedFqName?.asString()
}
}
else {
val typeReference = expression.getParentOfType<KtTypeReference>(true)
val referenced = typeReference?.text ?: expression.getReferencedName()
expression.getContainingKtFile()
.importDirectives
.firstOrNull { !it.isAllUnder && it.aliasName == referenced || it.importedFqName?.shortName()?.asString() == referenced }
?.let { it.importedFqName?.asString() }
?: referenced
}
if (name != null) {
registrar.register(AddMavenDependencyQuickFix(name, expression.createSmartPointer()))
}
}
}
class AddMavenDependencyQuickFix(val className: String, val smartPsiElementPointer: SmartPsiElementPointer<KtSimpleNameExpression>) : IntentionAction, LowPriorityAction {
override fun getText() = "Add dependency..."
override fun getFamilyName() = "Kotlin"
override fun startInWriteAction() = false
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile?) =
smartPsiElementPointer.element.let { it != null && it.isValid } && file != null && MavenDomUtil.findContainingProject(file) != null
override fun invoke(project: Project, editor: Editor?, file: PsiFile?) {
if (editor == null || file == null) {
return
}
val virtualFile = file.originalFile.virtualFile ?: return
val mavenProject = MavenDomUtil.findContainingProject(file) ?: return
val xmlFile = PsiManager.getInstance(project).findFile(mavenProject.file) as? XmlFile ?: return
val ids = MavenArtifactSearchDialog.searchForClass(project, className)
if (ids.isEmpty()) return
runWriteAction {
val isTestSource = ProjectRootManager.getInstance(project).fileIndex.isInTestSourceContent(virtualFile)
val scope = if (isTestSource) MavenArtifactScope.TEST else null
val pom = PomFile(xmlFile)
ids.forEach {
pom.addDependency(it, scope)
}
}
}
}
object PlatformUnresolvedProvider : KotlinIntentionActionFactoryWithDelegate<KtNameReferenceExpression, String>() {
override fun getElementOfInterest(diagnostic: Diagnostic) = QuickFixUtil.getParentElementOfType(diagnostic, KtNameReferenceExpression::class.java)
override fun extractFixData(element: KtNameReferenceExpression, diagnostic: Diagnostic) = element.getReferencedName()
override fun createFixes(originalElementPointer: SmartPsiElementPointer<KtNameReferenceExpression>, diagnostic: Diagnostic, quickFixDataFactory: () -> String?): List<QuickFixWithDelegateFactory> {
val result = ArrayList<QuickFixWithDelegateFactory>()
originalElementPointer.element?.references?.filterIsInstance<KtSimpleNameReference>()?.firstOrNull()?.let { reference ->
UnresolvedReferenceQuickFixProvider.registerReferenceFixes(reference, object: QuickFixActionRegistrar {
override fun register(action: IntentionAction) {
result.add(QuickFixWithDelegateFactory(IntentionActionPriority.LOW) { action } )
}
override fun register(fixRange: TextRange, action: IntentionAction, key: HighlightDisplayKey?) {
register(action)
}
override fun unregister(condition: Condition<IntentionAction>) {
}
})
}
return result
}
}
@@ -0,0 +1,144 @@
/*
* Copyright 2010-2016 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.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiFile
import com.intellij.util.xml.DomElement
import com.intellij.util.xml.DomUtil
import com.intellij.util.xml.actions.generate.AbstractDomGenerateProvider
import com.intellij.util.xml.ui.actions.generate.GenerateDomElementAction
import org.jetbrains.idea.maven.dom.MavenDomUtil
import org.jetbrains.idea.maven.dom.model.MavenDomDependency
import org.jetbrains.idea.maven.dom.model.MavenDomPlugin
import org.jetbrains.idea.maven.dom.model.MavenDomProjectModel
import org.jetbrains.idea.maven.model.MavenId
import org.jetbrains.kotlin.psi.psiUtil.endOffset
class GenerateMavenCompileExecutionAction : PomFileActionBase(KotlinMavenExecutionProvider("compile", PomFile.DefaultPhases.Compile))
class GenerateMavenTestCompileExecutionAction : PomFileActionBase(KotlinMavenExecutionProvider("test-compile", PomFile.DefaultPhases.TestCompile))
class GenerateMavenPluginAction : PomFileActionBase(KotlinMavenPluginProvider())
private val DefaultKotlinVersion = "\${kotlin.version}"
open class PomFileActionBase(generateProvider: AbstractDomGenerateProvider<*>) : GenerateDomElementAction(generateProvider) {
override fun isValidForFile(project: Project, editor: Editor, file: PsiFile): Boolean {
return MavenDomUtil.isMavenFile(file) && super.isValidForFile(project, editor, file)
}
override fun startInWriteAction() = true
}
private class KotlinMavenPluginProvider : AbstractDomGenerateProvider<MavenDomPlugin>("kotlin-maven-plugin-provider", MavenDomPlugin::class.java) {
override fun generate(parent: DomElement?, editor: Editor?): MavenDomPlugin? {
if (parent !is MavenDomProjectModel) {
return null
}
val knownVersion = parent.dependencies.dependencies.firstOrNull { it.isKotlinStdlib() }?.version?.rawText
val version = when {
knownVersion == null -> DefaultKotlinVersion
knownVersion.isRangeVersion() -> knownVersion.getRangeClosedEnd() ?: DefaultKotlinVersion
else -> knownVersion
}
val pom = PomFile(DomUtil.getFile(parent))
val plugin = pom.addPlugin(MavenId(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID, version))
val range = plugin.version.ensureTagExists().value.textRange
if (editor != null) {
editor.caretModel.moveToOffset(range.endOffset)
editor.selectionModel.setSelection(range.startOffset, range.endOffset)
}
return plugin
}
override fun getElementToNavigate(t: MavenDomPlugin?) = null
override fun getParentDomElement(project: Project?, editor: Editor?, file: PsiFile?): DomElement? {
if (project == null || editor == null || file == null) {
return null
}
return DomUtil.getContextElement(editor)?.findProject()
}
override fun isAvailableForElement(contextElement: DomElement): Boolean {
val parent = contextElement.findProject() ?: return false
return parent.build.plugins.plugins.none { plugin -> plugin.isKotlinMavenPlugin() }
}
}
private class KotlinMavenExecutionProvider(val goal: String, val phase: String) : AbstractDomGenerateProvider<MavenDomPlugin>("kotlin-maven-execution-provider", MavenDomPlugin::class.java) {
override fun generate(parent: DomElement?, editor: Editor?): MavenDomPlugin? {
if (parent !is MavenDomPlugin) {
return null
}
val file = PomFile(DomUtil.getFile(parent))
val execution = file.addExecution(parent, goal, phase, listOf(goal))
if (editor != null) {
editor.caretModel.moveToOffset(execution.ensureXmlElementExists().endOffset)
}
return parent
}
override fun getElementToNavigate(t: MavenDomPlugin?) = null
override fun getParentDomElement(project: Project?, editor: Editor?, file: PsiFile?): DomElement? {
if (project == null || editor == null || file == null) {
return null
}
return DomUtil.getContextElement(editor)?.findPlugin()
}
override fun isAvailableForElement(contextElement: DomElement): Boolean {
val plugin = contextElement.findPlugin()
return plugin != null
&& plugin.isKotlinMavenPlugin()
&& plugin.executions.executions.none { it.goals.goals.any { it.rawText == goal } }
}
}
private fun String.getRangeClosedEnd(): String? = when {
startsWith("[") -> substringBefore(',', "").drop(1).trimEnd()
endsWith("]") -> substringAfterLast(',', "").dropLast(1).trimStart()
else -> null
}
private fun Char.isRangeStart() = this == '[' || this == '('
private fun Char.isRangeEnd() = this == ']' || this == ')'
private fun String.isRangeVersion() = length > 2 && this[0].isRangeStart() && last().isRangeEnd()
private fun DomElement.findProject(): MavenDomProjectModel? = this as? MavenDomProjectModel ?: DomUtil.getParentOfType(this, MavenDomProjectModel::class.java, true)
private fun DomElement.findPlugin(): MavenDomPlugin? = this as? MavenDomPlugin ?: DomUtil.getParentOfType(this, MavenDomPlugin::class.java, true)
private fun MavenDomPlugin.isKotlinMavenPlugin() = groupId.stringValue == KotlinMavenConfigurator.GROUP_ID
&& artifactId.stringValue == KotlinMavenConfigurator.MAVEN_PLUGIN_ID
private fun MavenDomDependency.isKotlinStdlib() = groupId.stringValue == KotlinMavenConfigurator.GROUP_ID
&& artifactId.stringValue == KotlinJavaMavenConfigurator.STD_LIB_ID
@@ -0,0 +1,66 @@
/*
* Copyright 2010-2016 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.module.Module
import com.intellij.openapi.project.Project
import org.jetbrains.idea.maven.model.MavenId
import org.jetbrains.idea.maven.project.MavenProject
import org.jetbrains.idea.maven.project.MavenProjectsManager
import java.util.*
/**
* Analyze maven modules graph and exclude all children from the [selectedModules] so only
* topmost modules of [selectedModules] will remain.
*
* Example:
*
*
* - root
* - module1
* - module2
* - module2.1
* - module2.2
* - module3
*
*
* so `excludeMavenChildrenModules(project, listOf(module2, module2.2, module1)` -> `listOf(module1, module2)`
*
*/
fun excludeMavenChildrenModules(project: Project, selectedModules: List<Module>): List<Module> {
val mavenManager = MavenProjectsManager.getInstance(project)
val projectsById = mavenManager.projects.associateBy { it.mavenId }
val selectedProjects = selectedModules.mapNotNull { mavenManager.findProject(it) }
val selectedIds = selectedProjects.mapTo(HashSet()) { it.mavenId }
val excluded = HashSet<MavenId>(selectedProjects.size)
for (m in selectedProjects) {
if (m.mavenId !in excluded) {
var current: MavenProject? = m
while (current != null) {
if (current.mavenId in excluded || (current != m && current.mavenId in selectedIds)) {
excluded.add(m.mavenId)
break
}
current = current.parentId?.let { projectsById[it] }
}
}
}
return selectedProjects.filter { it.mavenId !in excluded }.mapNotNull { mavenManager.findModule(it) }
}
@@ -0,0 +1,157 @@
/*
* Copyright 2010-2016 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.codeInsight.intention.PsiElementBaseIntentionAction
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.psi.PsiElement
import com.intellij.psi.xml.XmlElement
import com.intellij.psi.xml.XmlFile
import com.intellij.psi.xml.XmlTag
import com.intellij.util.xml.DomManager
import com.intellij.util.xml.GenericDomValue
import org.jetbrains.idea.maven.dom.MavenDomUtil
import org.jetbrains.idea.maven.dom.model.MavenDomBuild
import org.jetbrains.idea.maven.dom.model.MavenDomPluginExecution
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
class MavenPluginSourcesMoveToExecutionIntention : PsiElementBaseIntentionAction() {
override fun getFamilyName() = "Move to compile execution"
override fun getText() = familyName
override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean {
val file = element.containingFile
if (file == null || !MavenDomUtil.isMavenFile(file) || element !is XmlElement) {
return false
}
val tag = element.getParentOfType<XmlTag>(false) ?: return false
val domElement = DomManager.getDomManager(project).getDomElement(tag) ?: return false
if (domElement !is GenericDomValue<*>) {
return false
}
val pom = PomFile(file as XmlFile)
if (domElement.getParentOfType(MavenDomBuild::class.java, false)?.sourceDirectory === domElement) {
return pom.findKotlinExecutions(PomFile.KotlinGoals.Compile, PomFile.KotlinGoals.Js).isNotEmpty()
}
if (domElement.getParentOfType(MavenDomBuild::class.java, false)?.testSourceDirectory === domElement) {
return pom.findKotlinExecutions(PomFile.KotlinGoals.TestCompile, PomFile.KotlinGoals.TestJs).isNotEmpty()
}
return false
}
override fun startInWriteAction() = true
override fun invoke(project: Project, editor: Editor, element: PsiElement) {
val xmlFile = element.containingFile as? XmlFile ?: return
val pomFile = PomFile(xmlFile)
val tag = element.getParentOfType<XmlTag>(false) ?: return
val domElement = DomManager.getDomManager(project).getDomElement(tag) as? GenericDomValue<*> ?: return
val dir = domElement.rawText ?: return
val relevantExecutions = if (domElement.getParentOfType(MavenDomBuild::class.java, false)?.sourceDirectory === domElement) {
pomFile.findKotlinExecutions(PomFile.KotlinGoals.Compile, PomFile.KotlinGoals.Js)
} else if (domElement.getParentOfType(MavenDomBuild::class.java, false)?.testSourceDirectory === domElement) {
pomFile.findKotlinExecutions(PomFile.KotlinGoals.TestCompile, PomFile.KotlinGoals.TestJs)
} else {
emptyList()
}
if (relevantExecutions.isNotEmpty()) {
relevantExecutions.forEach { execution ->
val existingSourceDirs = pomFile.executionSourceDirs(execution)
pomFile.executionSourceDirs(execution, (existingSourceDirs + dir).distinct(), true)
}
domElement.undefine()
}
}
}
class MavenPluginSourcesMoveToBuild : PsiElementBaseIntentionAction() {
override fun getFamilyName() = "Move to build>sourceDirectory tag"
override fun getText() = familyName
override fun isAvailable(project: Project, editor: Editor, element: PsiElement): Boolean {
return tryInvoke(project, element)
}
override fun startInWriteAction() = true
override fun invoke(project: Project, editor: Editor, element: PsiElement) {
tryInvoke(project, element) { pom, dir, execution, build ->
pom.executionSourceDirs(execution, listOf(dir))
}
}
private fun tryInvoke(project: Project, element: PsiElement, block: (pom: PomFile, dir: String, execution: MavenDomPluginExecution, build: MavenDomBuild) -> Unit = { p, d, e, b -> }): Boolean {
val file = element.containingFile
if (file == null || !MavenDomUtil.isMavenFile(file) || (element !is XmlElement && element.parent !is XmlElement)) {
return false
}
val tag = element.getParentOfType<XmlTag>(false) ?: return false
val domElement = DomManager.getDomManager(project).getDomElement(tag) ?: return false
val execution = domElement.getParentOfType(MavenDomPluginExecution::class.java, false) ?: return false
tag.parentsWithSelf
.takeWhile { it != execution.xmlElement }
.filterIsInstance<XmlTag>()
.firstOrNull { it.localName == "sourceDirs" } ?: return false
val pom = PomFile(element.containingFile as XmlFile)
val sourceDirsToMove = pom.executionSourceDirs(execution)
if (sourceDirsToMove.size != 1) {
return false
}
val build = execution.getParentOfType(MavenDomBuild::class.java, false) ?: return false
var couldMove = 0
if (shouldMoveCompileSourceRoot(execution)) {
if (!build.sourceDirectory.exists() || build.sourceDirectory.stringValue == sourceDirsToMove.single()) {
couldMove ++
}
}
if (shouldMoveTestSourceRoot(execution)) {
if (!build.testSourceDirectory.exists() || build.testSourceDirectory.stringValue == sourceDirsToMove.single()) {
couldMove ++
}
}
if (couldMove == 1) {
block(pom, sourceDirsToMove.single(), execution, build)
return true
} else {
return false
}
}
private fun shouldMoveCompileSourceRoot(execution: MavenDomPluginExecution) =
execution.goals.goals.any { it.stringValue == PomFile.KotlinGoals.Compile || it.stringValue == PomFile.KotlinGoals.Js }
private fun shouldMoveTestSourceRoot(execution: MavenDomPluginExecution) =
execution.goals.goals.any { it.stringValue == PomFile.KotlinGoals.TestCompile || it.stringValue == PomFile.KotlinGoals.TestJs }
}
@@ -0,0 +1,458 @@
/*
* Copyright 2010-2016 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.module.Module
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.SourceFolder
import com.intellij.openapi.vfs.VfsUtilCore
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiElementVisitor
import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.XmlElementFactory
import com.intellij.psi.xml.XmlFile
import com.intellij.psi.xml.XmlTag
import com.intellij.psi.xml.XmlText
import com.intellij.util.xml.GenericDomValue
import org.jetbrains.idea.maven.dom.MavenDomElement
import org.jetbrains.idea.maven.dom.MavenDomUtil
import org.jetbrains.idea.maven.dom.model.*
import org.jetbrains.idea.maven.model.MavenId
import org.jetbrains.idea.maven.utils.MavenArtifactScope
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
import java.util.*
class PomFile(val xmlFile: XmlFile) {
private val domModel = MavenDomUtil.getMavenDomProjectModel(xmlFile.project, xmlFile.virtualFile) ?: throw IllegalStateException("No DOM model found for pom ${xmlFile.name}")
private val nodesByName = HashMap<String, XmlTag>()
private val projectElement: XmlTag
init {
var projectElement: XmlTag? = null
xmlFile.document?.accept(object : PsiElementVisitor() {
override fun visitElement(element: PsiElement) {
super.visitElement(element)
if (element is XmlTag && element.localName in recommendedElementsOrder) {
nodesByName[element.localName] = element
}
else if (element is XmlTag && element.localName == "project") {
projectElement = element
element.acceptChildren(this)
}
else {
element.acceptChildren(this)
}
}
})
require(projectElement != null) { "pom file should have project element" }
this.projectElement = projectElement!!
}
fun addProperty(name: String, value: String) {
val properties = ensureElement(projectElement, "properties")
val existing = properties.children.filterIsInstance<XmlTag>().filter { it.localName == name }
if (existing.isNotEmpty()) {
for (tag in existing) {
val textNode = tag.children.filterIsInstance<XmlText>().firstOrNull()
if (textNode != null) {
textNode.value = value
}
else {
tag.replace(projectElement.createChildTag(name, value))
}
}
}
else {
properties.add(projectElement.createChildTag(name, value))
}
}
fun addDependency(artifact: MavenId, scope: MavenArtifactScope? = null, classifier: String? = null, optional: Boolean = false, systemPath: String? = null): MavenDomDependency {
require(systemPath == null || scope == MavenArtifactScope.SYSTEM) { "systemPath is only applicable for system scope dependency" }
require(artifact.groupId != null) { "groupId shouldn't be null" }
require(artifact.artifactId != null) { "artifactId shouldn't be null" }
ensureDependencies()
val versionless = artifact.withNoVersion()
val dependency = domModel.dependencies.dependencies.firstOrNull { it.matches(versionless) } ?: domModel.dependencies.addDependency()
dependency.groupId.stringValue = artifact.groupId
dependency.artifactId.stringValue = artifact.artifactId
dependency.version.stringValue = artifact.version
dependency.classifier.stringValue = classifier
if (scope != null && scope != MavenArtifactScope.COMPILE) {
dependency.scope.stringValue = scope.name.toLowerCase()
}
if (optional) {
dependency.optional.value = optional
}
dependency.systemPath.stringValue = systemPath
dependency.ensureTagExists()
return dependency
}
fun addKotlinPlugin(version: String?) = addPlugin(MavenId(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID, version))
fun addPlugin(artifact: MavenId): MavenDomPlugin {
ensureBuild()
val groupArtifact = artifact.withNoVersion()
val plugin = domModel.build.plugins.plugins.firstOrNull { it.matches(groupArtifact) } ?: domModel.build.plugins.addPlugin()
plugin.groupId.stringValue = artifact.groupId
plugin.artifactId.stringValue = artifact.artifactId
if (artifact.version != null) {
plugin.version.stringValue = artifact.version
}
plugin.ensureTagExists()
return plugin
}
fun findKotlinPlugins() = domModel.build.plugins.plugins.filter { it.isKotlinMavenPlugin() }
fun findKotlinExecutions(vararg goals: String) = findKotlinExecutions().filter { it.goals.goals.any { it.rawText in goals } }
fun findKotlinExecutions() = findKotlinPlugins().flatMap { it.executions.executions }
fun findExecutions(plugin: MavenDomPlugin) = plugin.executions.executions
fun findExecutions(plugin: MavenDomPlugin, vararg goals: String) = findExecutions(plugin).filter { it.goals.goals.any { it.rawText in goals } }
fun addExecution(plugin: MavenDomPlugin, executionId: String, phase: String, goals: List<String>): MavenDomPluginExecution {
require(goals.isNotEmpty()) { "Execution $executionId requires at least one goal but empty list has been provided" }
require(executionId.isNotEmpty()) { "executionId shouldn't be empty" }
require(phase.isNotEmpty()) { "phase shouldn't be empty" }
val execution = plugin.executions.executions.firstOrNull { it.id.stringValue == executionId } ?: plugin.executions.addExecution()
execution.id.stringValue = executionId
execution.phase.stringValue = phase
execution.goals.ensureTagExists()
val existingGoals = execution.goals.goals.mapNotNull { it.rawText }
for (goal in goals.filter { it !in existingGoals }) {
val goalTag = execution.goals.xmlTag.createChildTag("goal", goal)
execution.goals.xmlTag.add(goalTag)
}
return execution
}
fun addKotlinExecution(module: Module, plugin: MavenDomPlugin, executionId: String, phase: String, isTest: Boolean, goals: List<String>) {
val execution = addExecution(plugin, executionId, phase, goals)
val sourceDirs = ModuleRootManager.getInstance(module)
.contentEntries
.flatMap { it.sourceFolders.filter { it.isRelatedSourceRoot(isTest) } }
.mapNotNull { it.file }
.mapNotNull { VfsUtilCore.getRelativePath(it, xmlFile.virtualFile.parent, '/') }
executionSourceDirs(execution, sourceDirs)
}
fun executionSourceDirs(execution: MavenDomPluginExecution, sourceDirs: List<String>, forceSingleSource: Boolean = false) {
ensureBuild()
val isTest = execution.goals.goals.any { it.stringValue == KotlinGoals.TestCompile || it.stringValue == KotlinGoals.TestJs}
val defaultDir = if (isTest) "test" else "main"
val singleDirectoryElement = if (isTest) {
domModel.build.testSourceDirectory
}
else {
domModel.build.sourceDirectory
}
if (sourceDirs.isEmpty() || sourceDirs.singleOrNull() == "src/$defaultDir/java") {
execution.configuration.xmlTag?.findSubTags("sourceDirs")?.forEach { it.deleteCascade() }
singleDirectoryElement.undefine()
}
else if (sourceDirs.size == 1 && !forceSingleSource) {
singleDirectoryElement.stringValue = sourceDirs.single()
execution.configuration.xmlTag?.findSubTags("sourceDirs")?.forEach { it.deleteCascade() }
}
else {
val sourceDirsTag = executionConfiguration(execution, "sourceDirs")
val newSourceDirsTag = execution.configuration.createChildTag("sourceDirs")
for (dir in sourceDirs) {
newSourceDirsTag.add(newSourceDirsTag.createChildTag("source", dir))
}
sourceDirsTag.replace(newSourceDirsTag)
}
}
fun executionSourceDirs(execution: MavenDomPluginExecution): List<String> {
return execution.configuration.xmlTag
.getChildrenOfType<XmlTag>().firstOrNull { it.localName == "sourceDirs" }
?.getChildrenOfType<XmlTag>()
?.map { it.getChildrenOfType<XmlText>().joinToString("") { it.text } }
?: emptyList()
}
fun executionConfiguration(execution: MavenDomPluginExecution, name: String): XmlTag {
val configurationTag = execution.configuration.ensureTagExists()!!
val existingTag = configurationTag.findSubTags(name).firstOrNull()
if (existingTag != null) {
return existingTag
}
val newTag = configurationTag.createChildTag(name)
return configurationTag.add(newTag) as XmlTag
}
fun addPluginRepository(id: String, name: String, url: String, snapshots: Boolean = false, releases: Boolean = true): MavenDomRepository {
ensurePluginRepositories()
return addRepository(id, name, url, snapshots, releases, { domModel.pluginRepositories.pluginRepositories }, { domModel.pluginRepositories.addPluginRepository() })
}
fun addLibraryRepository(id: String, name: String, url: String, snapshots: Boolean = false, releases: Boolean = true): MavenDomRepository {
ensureRepositories()
return addRepository(id, name, url, snapshots, releases, { domModel.repositories.repositories }, { domModel.repositories.addRepository() })
}
private fun addRepository(id: String, name: String, url: String, snapshots: Boolean, releases: Boolean, existing: () -> List<MavenDomRepository>, create: () -> MavenDomRepository): MavenDomRepository {
val repository =
existing().firstOrNull { it.id.stringValue == id } ?:
existing().firstOrNull { it.url.stringValue == url } ?:
create()
if (repository.id.isEmpty()) {
repository.id.stringValue = id
}
if (repository.name.isEmpty()) {
repository.name.stringValue = name
}
if (repository.url.isEmpty()) {
repository.url.stringValue = url
}
repository.releases.enabled.value = repository.releases.enabled.value?.let { it || releases } ?: releases
repository.snapshots.enabled.value = repository.snapshots.enabled.value?.let { it || snapshots } ?: snapshots
repository.ensureTagExists()
return repository
}
fun hasPlugin(artifact: MavenId) = domModel.build.plugins.plugins.any { it.matches(artifact) }
fun hasDependency(artifact: MavenId, scope: MavenArtifactScope? = null) =
domModel.dependencies.dependencies.any { it.matches(artifact, scope) }
fun findDependencies(artifact: MavenId, scope: MavenArtifactScope? = null) =
domModel.dependencies.dependencies.filter { it.matches(artifact, scope) }
fun ensureBuild(): XmlTag = ensureElement(projectElement, "build")
fun ensureDependencies(): XmlTag = ensureElement(projectElement, "dependencies")
fun ensurePluginRepositories(): XmlTag = ensureElement(projectElement, "pluginRepositories")
fun ensureRepositories(): XmlTag = ensureElement(projectElement, "repositories")
private fun MavenDomPlugin.isKotlinMavenPlugin() = groupId.stringValue == KotlinMavenConfigurator.GROUP_ID
&& artifactId.stringValue == KotlinMavenConfigurator.MAVEN_PLUGIN_ID
private fun MavenDomDependency.matches(artifact: MavenId, scope: MavenArtifactScope?) =
this.matches(artifact) && (this.scope.stringValue == scope?.name?.toLowerCase() || scope == null && this.scope.stringValue == "compile")
private fun MavenDomArtifactCoordinates.matches(artifact: MavenId) =
(artifact.groupId == null || groupId.stringValue == artifact.groupId)
&& (artifact.artifactId == null || artifactId.stringValue == artifact.artifactId)
&& (artifact.version == null || version.stringValue == artifact.version)
private fun MavenId.withNoVersion() = MavenId(groupId, artifactId, null)
private fun MavenDomElement.createChildTag(name: String, value: String? = null) = xmlTag.createChildTag(name, value)
private fun XmlTag.createChildTag(name: String, value: String? = null) = createChildTag(name, namespace, value, false)!!
tailrec
private fun XmlTag.deleteCascade() {
val oldParent = this.parentTag
delete()
if (oldParent != null && oldParent.subTags.isEmpty()) {
oldParent.deleteCascade()
}
}
private fun ensureElement(projectElement: XmlTag, localName: String): XmlTag {
require(localName in recommendedElementsOrder) { "You can only ensure presence or the elements from the recommendation list" }
return nodesByName.getOrPut(localName) {
val tag = projectElement.createChildTag(localName, projectElement.namespace, null, false)!!
val newTag = insertTagImpl(projectElement, tag)
insertEmptyLines(newTag)
newTag
}
}
private fun insertTagImpl(projectElement: XmlTag, tag: XmlTag): XmlTag {
val middle = recommendedOrderAsList.indexOf(tag.localName)
require(middle != -1) { "You can only insert element from the recommendation list" }
for (idx in middle - 1 downTo 0) {
val reference = nodesByName[recommendedOrderAsList[idx]]
if (reference != null) {
return projectElement.addAfter(tag, reference) as XmlTag
}
}
for (idx in middle + 1..recommendedOrderAsList.lastIndex) {
val reference = nodesByName[recommendedOrderAsList[idx]]
if (reference != null) {
return projectElement.addBefore(tag, reference) as XmlTag
}
}
return projectElement.add(tag) as XmlTag
}
private fun insertEmptyLines(node: XmlTag) {
node.prevSibling?.let { before ->
if (!(before.hasEmptyLine() || before.lastChild?.hasEmptyLine() ?: false)) {
node.parent.addBefore(createEmptyLine(), node)
}
}
node.nextSibling?.let { after ->
if (!(after.hasEmptyLine() || after.firstChild?.hasEmptyLine() ?: false)) {
node.parent.addAfter(createEmptyLine(), node)
}
}
}
private fun PsiElement.hasEmptyLine() = this is PsiWhiteSpace && text.count { it == '\n' } > 1
private fun createEmptyLine(): XmlText {
return XmlElementFactory.getInstance(xmlFile.project).createTagFromText("<s>\n\n</s>").children.first { it is XmlText } as XmlText
}
private fun GenericDomValue<String>.isEmpty() = !exists() || stringValue.isNullOrEmpty()
private fun SourceFolder.isRelatedSourceRoot(isTest: Boolean): Boolean {
val relevantRootType = when {
isTest -> JavaSourceRootType.TEST_SOURCE
else -> JavaSourceRootType.SOURCE
}
return rootType === relevantRootType
}
@Suppress("Unused")
object DefaultPhases {
val Validate = "validate"
val Initialize = "initialize"
val GenerateSources = "generate-sources"
val ProcessSources = "process-sources"
val GenerateResources = "generate-resources"
val ProcessResources = "process-resources"
val Compile = "compile"
val ProcessClasses = "process-classes"
val GenerateTestSources = "generate-test-sources"
val ProcessTestSources = "process-test-sources"
val GenerateTestResources = "generate-test-resources"
val ProcessTestResources = "process-test-resources"
val TestCompile = "test-compile"
val ProcessTestClasses = "process-test-classes"
val Test = "test"
val PreparePackage = "prepare-package"
val Package = "package"
val PreIntegrationTest = "pre-integration-test"
val IntegrationTest = "integration-test"
val PostIntegrationTest = "post-integration-test"
val Verify = "verify"
val Install = "install"
val Deploy = "deploy"
}
object KotlinGoals {
val Compile = "compile"
val TestCompile = "test-compile"
val Js = "js"
val TestJs = "test-js"
}
companion object {
fun getPhase(hasJavaFiles: Boolean, isTest: Boolean) = when {
hasJavaFiles -> when {
isTest -> DefaultPhases.ProcessTestSources
else -> DefaultPhases.ProcessSources
}
else -> when {
isTest -> DefaultPhases.TestCompile
else -> DefaultPhases.Compile
}
}
// from maven code convention: https://maven.apache.org/developers/conventions/code.html
val recommendedElementsOrder = """
<modelVersion/>
<parent/>
<groupId/>
<artifactId/>
<version/>
<packaging/>
<name/>
<description/>
<url/>
<inceptionYear/>
<organization/>
<licenses/>
<developers/>
<contributors/>
<mailingLists/>
<prerequisites/>
<modules/>
<scm/>
<issueManagement/>
<ciManagement/>
<distributionManagement/>
<properties/>
<dependencyManagement/>
<dependencies/>
<repositories/>
<pluginRepositories/>
<build/>
<reporting/>
<profiles/>
""".lines()
.map { it.trim().removePrefix("<").removeSuffix("/>").trim() }
.filter { it.isNotEmpty() }
.toCollection(LinkedHashSet())
val recommendedOrderAsList = recommendedElementsOrder.toList()
}
}
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2016 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.module.Module
import com.intellij.psi.PsiFile
import org.jetbrains.idea.maven.model.MavenConstants
abstract class AbstractMavenConfigureProjectByChangingFileTest : AbstractConfigureProjectByChangingFileTest<KotlinMavenConfigurator>() {
fun doTestWithMaven(path: String) {
val pathWithFile = path + "/" + MavenConstants.POM_XML
doTest(pathWithFile, pathWithFile.replace("pom", "pom_after"), KotlinJavaMavenConfigurator())
}
fun doTestWithJSMaven(path: String) {
val pathWithFile = path + "/" + MavenConstants.POM_XML
doTest(pathWithFile, pathWithFile.replace("pom", "pom_after"), KotlinJavascriptMavenConfigurator())
}
override fun runConfigurator(module: Module, file: PsiFile, configurator: KotlinMavenConfigurator, version: String, collector: NotificationMessageCollector) {
configurator.changePomFile(module, file, version, collector)
}
}
@@ -0,0 +1,67 @@
/*
* Copyright 2010-2016 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.google.gson.JsonParser
import org.jetbrains.idea.maven.model.MavenArchetype
import org.junit.Test
import org.junit.Assert.*
import java.io.File
class KotlinMavenArchetypesProviderTest {
private val BASE_PATH = "idea/testData/configuration/"
@Test
fun extractVersions() {
val file = File(BASE_PATH, "extractVersions/maven-central-response.json")
assertTrue("Test data is missing", file.exists())
val json = file.bufferedReader().use {
JsonParser().parse(it)
}
val versions = KotlinMavenArchetypesProvider("1.0.0-Release-Something-1886").extractVersions(json)
assertEquals(
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.0.1-2", null, null),
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-js", "1.0.0", null, null)
).sortedBy { it.artifactId + "." + it.version },
versions.sortedBy { it.artifactId + "." + it.version }
)
}
@Test
fun extractVersionsNewPlugin() {
val file = File(BASE_PATH, "extractVersions/maven-central-response.json")
assertTrue("Test data is missing", file.exists())
val json = file.bufferedReader().use {
JsonParser().parse(it)
}
val versions = KotlinMavenArchetypesProvider("1.1.0-Next-Release-Something-9999").extractVersions(json)
assertEquals(
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.1.2", null, null)
).sortedBy { it.artifactId + "." + it.version },
versions.sortedBy { it.artifactId + "." + it.version }
)
}
}
@@ -0,0 +1,154 @@
/*
* Copyright 2010-2016 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.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@RunWith(JUnit3RunnerWithInners.class)
public class ConfigureProjectByChangingFileTestGenerated extends AbstractConfigureProjectByChangingFileTest {
@TestMetadata("idea/testData/configuration/gradle")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Gradle extends AbstractConfigureProjectByChangingFileTest {
public void testAllFilesPresentInGradle() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/configuration/gradle"), Pattern.compile("(\\w+)_before\\.gradle$"), true);
}
@TestMetadata("default_before.gradle")
public void testDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/gradle/default_before.gradle");
doTestGradle(fileName);
}
@TestMetadata("eapVersion_before.gradle")
public void testEapVersion() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/gradle/eapVersion_before.gradle");
doTestGradle(fileName);
}
@TestMetadata("missedLibrary_before.gradle")
public void testMissedLibrary() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/gradle/missedLibrary_before.gradle");
doTestGradle(fileName);
}
@TestMetadata("plugin_present_before.gradle")
public void testPlugin_present() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/gradle/plugin_present_before.gradle");
doTestGradle(fileName);
}
@TestMetadata("rcVersion_before.gradle")
public void testRcVersion() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/gradle/rcVersion_before.gradle");
doTestGradle(fileName);
}
}
@TestMetadata("idea/testData/configuration/maven")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Maven extends AbstractConfigureProjectByChangingFileTest {
public void testAllFilesPresentInMaven() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/configuration/maven"), Pattern.compile("^([^\\.]+)$"), false);
}
@TestMetadata("fixExisting")
public void testFixExisting() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/maven/fixExisting/");
doTestWithMaven(fileName);
}
@TestMetadata("libraryMissed")
public void testLibraryMissed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/maven/libraryMissed/");
doTestWithMaven(fileName);
}
@TestMetadata("pluginMissed")
public void testPluginMissed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/maven/pluginMissed/");
doTestWithMaven(fileName);
}
@TestMetadata("simpleProject")
public void testSimpleProject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/maven/simpleProject/");
doTestWithMaven(fileName);
}
@TestMetadata("simpleProjectEAP")
public void testSimpleProjectEAP() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/maven/simpleProjectEAP/");
doTestWithMaven(fileName);
}
@TestMetadata("simpleProjectRc")
public void testSimpleProjectRc() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/maven/simpleProjectRc/");
doTestWithMaven(fileName);
}
@TestMetadata("simpleProjectSnapshot")
public void testSimpleProjectSnapshot() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/maven/simpleProjectSnapshot/");
doTestWithMaven(fileName);
}
}
@TestMetadata("idea/testData/configuration/js-maven")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Js_maven extends AbstractConfigureProjectByChangingFileTest {
public void testAllFilesPresentInJs_maven() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/configuration/js-maven"), Pattern.compile("^([^\\.]+)$"), false);
}
@TestMetadata("libraryMissed")
public void testLibraryMissed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/js-maven/libraryMissed/");
doTestWithJSMaven(fileName);
}
@TestMetadata("pluginMissed")
public void testPluginMissed() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/js-maven/pluginMissed/");
doTestWithJSMaven(fileName);
}
@TestMetadata("simpleProject")
public void testSimpleProject() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/js-maven/simpleProject/");
doTestWithJSMaven(fileName);
}
@TestMetadata("simpleProjectSnapshot")
public void testSimpleProjectSnapshot() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/configuration/js-maven/simpleProjectSnapshot/");
doTestWithJSMaven(fileName);
}
}
}
@@ -0,0 +1,171 @@
/*
* Copyright 2010-2016 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.analysis.AnalysisScope
import com.intellij.codeInspection.*
import com.intellij.codeInspection.ex.InspectionManagerEx
import com.intellij.codeInspection.ex.LocalInspectionToolWrapper
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.Result
import com.intellij.openapi.application.WriteAction
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.fileEditor.FileDocumentManager
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiManager
import com.intellij.psi.search.FileTypeIndex
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.testFramework.InspectionTestUtil
import com.intellij.testFramework.fixtures.impl.CodeInsightTestFixtureImpl
import com.intellij.util.indexing.FileBasedIndex
import org.jetbrains.jps.model.java.JavaSourceRootType
import org.jetbrains.kotlin.idea.configuration.KotlinMavenPluginPhaseInspection
import org.jetbrains.kotlin.idea.refactoring.toPsiDirectory
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
import java.io.File
abstract class AbstractKotlinMavenInspectionTest : MavenImportingTestCase() {
override fun setUp() {
super.setUp()
repositoryPath = File(myDir, "repo").path
createStdProjectFolders()
}
fun doTest(fileName: String) {
val pomFile = File(fileName)
val pomText = pomFile.readText()
createPomFile(fileName)
importProject()
myProject.allModules().forEach {
setupJdkForModule(it.name)
}
if (pomText.contains("<!--\\s*mkjava\\s*-->".toRegex(RegexOption.MULTILINE))) {
mkJavaFile()
}
val inspectionClassName = "<!--\\s*inspection:\\s*([\\S]+)\\s-->".toRegex().find(pomText)?.groups?.get(1)?.value ?: KotlinMavenPluginPhaseInspection::class.qualifiedName !!
val inspectionClass = Class.forName(inspectionClassName)
val matcher = "<!--\\s*problem:\\s*on\\s*([^,]+),\\s*title\\s*(.+)\\s*-->".toRegex()
val expected = pomText.lines().mapNotNull { matcher.find(it) }.map { SimplifiedProblemDescription(it.groups[2]!!.value.trim(), it.groups[1]!!.value.trim()) }
val actual = runInspection(inspectionClass).sortedBy { it.first.text }
assertEquals(expected.sortedBy { it.text }, actual.map { it.first })
val suggestedFixes = actual.flatMap { p -> p.second.fixes?.sortedBy { it.familyName }?.map { p.second to it } ?: emptyList() }
val filenamePrefix = pomFile.nameWithoutExtension + ".fixed."
val fixFiles = pomFile.parentFile.listFiles { file, name -> name.startsWith(filenamePrefix) && name.endsWith(".xml") }.sortedBy { it.name }
if (fixFiles.size > suggestedFixes.size) {
fail("Not all fixes were suggested by the inspection: expected count: ${fixFiles.size}, actual fixes count: ${suggestedFixes.size}")
}
if (fixFiles.size < suggestedFixes.size) {
fail("Not all fixes covered by *.fixed.N.xml files")
}
val documentManager = PsiDocumentManager.getInstance(myProject)
val document = documentManager.getDocument(PsiManager.getInstance(myProject).findFile(myProjectPom)!!)!!
val originalText = document.text
fixFiles.forEachIndexed { index, file ->
val (problem, quickfix) = suggestedFixes[index]
quickfix.applyFix(problem)
assertEquals(file.readText().trim(), document.text.trim())
ApplicationManager.getApplication().runWriteAction {
document.setText(originalText)
documentManager.commitDocument(document)
}
}
}
private fun createPomFile(fileName: String) {
myProjectPom = myProjectRoot.findChild("pom.xml")
if (myProjectPom == null) {
myProjectPom = object : WriteAction<VirtualFile>() {
override fun run(result: Result<VirtualFile>) {
val res = myProjectRoot.createChildData(null, "pom.xml")
result.setResult(res)
}
}.execute().resultObject
}
myAllPoms.add(myProjectPom!!)
ApplicationManager.getApplication().runWriteAction {
myProjectPom!!.setBinaryContent(File(fileName).readBytes())
}
}
private fun QuickFix<CommonProblemDescriptor>.applyFix(desc: ProblemDescriptorBase) {
CommandProcessor.getInstance().executeCommand(myProject, {
ApplicationManager.getApplication().runWriteAction {
applyFix(myProject, desc)
val manager = PsiDocumentManager.getInstance(myProject)
val document = manager.getDocument(PsiManager.getInstance(myProject).findFile(myProjectPom)!!)!!
manager.doPostponedOperationsAndUnblockDocument(document)
manager.commitDocument(document)
FileDocumentManager.getInstance().saveDocument(document)
}
println(myProjectPom.contentsToByteArray().toString(Charsets.UTF_8))
}, "quick-fix-$name", "Kotlin")
}
private fun mkJavaFile() {
val sourceFolder = getContentRoots(myProject.allModules().single().name).single().getSourceFolders(JavaSourceRootType.SOURCE).single()
ApplicationManager.getApplication().runWriteAction {
val javaFile = sourceFolder.file?.toPsiDirectory(myProject)?.createFile("Test.java") ?: throw IllegalStateException()
javaFile.virtualFile.setBinaryContent("class Test {}\n".toByteArray())
FileBasedIndex.getInstance().ensureUpToDate(FileTypeIndex.NAME, myProject, GlobalSearchScope.projectScope(myProject))
myProject.allModules().forEach { module ->
FileBasedIndex.getInstance().ensureUpToDate(FileTypeIndex.NAME, myProject, module.moduleScope)
}
}
assertTrue(FileTypeIndex.containsFileOfType(JavaFileType.INSTANCE, myProject.allModules().single().moduleScope))
}
private fun runInspection(inspectionClass: Class<*>): List<Pair<SimplifiedProblemDescription, ProblemDescriptorBase>> {
val toolWrapper = LocalInspectionToolWrapper(inspectionClass.newInstance() as LocalInspectionTool)
val scope = AnalysisScope(myProject)
val inspectionManager = (InspectionManager.getInstance(myProject) as InspectionManagerEx)
val globalContext = CodeInsightTestFixtureImpl.createGlobalContextForTool(scope, myProject, inspectionManager, toolWrapper)
InspectionTestUtil.runTool(toolWrapper, scope, globalContext)
val presentation = globalContext.getPresentation(toolWrapper)
return presentation.problemElements.filter { it.key.name == "pom.xml" }
.values
.flatMap { it.toList() }
.mapNotNull { it as? ProblemDescriptorBase }
.map { SimplifiedProblemDescription(it.descriptionTemplate, it.psiElement.text.replace("\\s+".toRegex(), "")) to it }
}
private data class SimplifiedProblemDescription(val text: String, val elementText: String)
}
@@ -0,0 +1,391 @@
/*
* Copyright 2010-2016 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("""
<groupId>test</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>$kotlinVersion</version>
</dependency>
</dependencies>
""")
assertModules("project")
assertImporterStatePresent()
assertSources("project", "src/main/java")
}
fun testWithSpecifiedSourceRoot() {
createProjectSubDir("src/main/kotlin")
importProject("""
<groupId>test</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>$kotlinVersion</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
</build>
""")
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("""
<groupId>test</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>$kotlinVersion</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/main/kotlin</dir>
<dir>src/main/kotlin.jvm</dir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/test/kotlin</dir>
<dir>src/test/kotlin.jvm</dir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
""")
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("""
<groupId>test</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>$kotlinVersion</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/main/kotlin</dir>
<dir>src/main/kotlin.jvm</dir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/test/kotlin</dir>
<dir>src/test/kotlin.jvm</dir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
""")
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("""
<groupId>test</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>$kotlinVersion</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/main/kotlin</dir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/test/kotlin</dir>
<dir>src/test/kotlin.jvm</dir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
""")
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("""
<groupId>test</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>$kotlinVersion</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/main/kotlin</dir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/test/kotlin</dir>
<dir>src/test/kotlin.jvm</dir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
""")
assertModules("project")
assertImporterStatePresent()
assertSources("project", "src/main/kotlin")
assertTestSources("project", "src/test/java", "src/test/kotlin", "src/test/kotlin.jvm")
// reimport
importProject("""
<groupId>test</groupId>
<artifactId>project</artifactId>
<version>1.0.0</version>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>$kotlinVersion</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src/main/kotlin</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/main/kotlin</dir>
<dir>src/main/kotlin.jvm</dir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<dir>src/test/kotlin</dir>
<dir>src/test/kotlin.jvm</dir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
""")
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))
}
}
@@ -0,0 +1,73 @@
/*
* Copyright 2010-2016 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.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/idea-maven/testData/maven-inspections")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class KotlinMavenInspectionTestGenerated extends AbstractKotlinMavenInspectionTest {
public void testAllFilesPresentInMaven_inspections() throws Exception {
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/idea-maven/testData/maven-inspections"), Pattern.compile("^([\\w\\-]+).xml$"));
}
@TestMetadata("bothCompileAndTestCompileInTheSameExecution.xml")
public void testBothCompileAndTestCompileInTheSameExecution() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-maven/testData/maven-inspections/bothCompileAndTestCompileInTheSameExecution.xml");
doTest(fileName);
}
@TestMetadata("dependencyWithNoExecution.xml")
public void testDependencyWithNoExecution() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-maven/testData/maven-inspections/dependencyWithNoExecution.xml");
doTest(fileName);
}
@TestMetadata("missingDependencies.xml")
public void testMissingDependencies() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-maven/testData/maven-inspections/missingDependencies.xml");
doTest(fileName);
}
@TestMetadata("noExecutions.xml")
public void testNoExecutions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-maven/testData/maven-inspections/noExecutions.xml");
doTest(fileName);
}
@TestMetadata("wrongJsExecution.xml")
public void testWrongJsExecution() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-maven/testData/maven-inspections/wrongJsExecution.xml");
doTest(fileName);
}
@TestMetadata("wrongPhaseExecution.xml")
public void testWrongPhaseExecution() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/idea-maven/testData/maven-inspections/wrongPhaseExecution.xml");
doTest(fileName);
}
}
@@ -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<String> actualNames = new ArrayList<String>();
for (Module m : actual) {
actualNames.add(m.getName());
}
assertUnorderedElementsAreEqual(actualNames, expectedNames);
}
protected void assertContentRoots(String moduleName, String... expectedRoots) {
List<String> actual = new ArrayList<String>();
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<ContentFolder> folders = new ArrayList<ContentFolder>();
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<String> actual = new ArrayList<String>();
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<String> classesPaths,
List<String> sourcePaths,
List<String> 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<String> 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<String> actual = new ArrayList<String>();
getRootManager(moduleName).orderEntries().withoutSdk().withoutModuleSourceEntries().exportedOnly().process(new RootPolicy<Object>() {
@Override
public Object visitModuleOrderEntry(ModuleOrderEntry e, Object value) {
actual.add(e.getModuleName());
return null;
}
@Override
public Object visitLibraryOrderEntry(LibraryOrderEntry e, Object value) {
actual.add(e.getLibraryName());
return null;
}
}, null);
assertOrderedElementsAreEqual(actual, expectedDeps);
}
protected void assertModuleModuleDeps(String moduleName, String... expectedDeps) {
assertModuleDeps(moduleName, ModuleOrderEntry.class, expectedDeps);
}
private void assertModuleDeps(String moduleName, Class clazz, String... expectedDeps) {
assertOrderedElementsAreEqual(collectModuleDepsNames(moduleName, clazz), expectedDeps);
}
protected void assertModuleModuleDepScope(String moduleName, String depName, DependencyScope scope) {
ModuleOrderEntry dep = getModuleModuleDep(moduleName, depName);
assertEquals(scope, dep.getScope());
}
private ModuleOrderEntry getModuleModuleDep(String moduleName, String depName) {
return getModuleDep(moduleName, depName, ModuleOrderEntry.class);
}
private List<String> collectModuleDepsNames(String moduleName, Class clazz) {
List<String> actual = new ArrayList<String>();
for (OrderEntry e : getRootManager(moduleName).getOrderEntries()) {
if (clazz.isInstance(e)) {
actual.add(e.getPresentableName());
}
}
return actual;
}
private <T> T getModuleDep(String moduleName, String depName, Class<T> clazz) {
T dep = null;
for (OrderEntry e : getRootManager(moduleName).getOrderEntries()) {
if (clazz.isInstance(e) && e.getPresentableName().equals(depName)) {
dep = (T)e;
}
}
assertNotNull("Dependency not found: " + depName
+ "\namong: " + collectModuleDepsNames(moduleName, clazz),
dep);
return dep;
}
public void assertProjectLibraries(String... expectedNames) {
List<String> actualNames = new ArrayList<String>();
for (Library each : ProjectLibraryTable.getInstance(myProject).getLibraries()) {
String name = each.getName();
actualNames.add(name == null ? "<unnamed>" : name);
}
assertUnorderedElementsAreEqual(actualNames, expectedNames);
}
protected void assertModuleGroupPath(String moduleName, String... expected) {
String[] path = ModuleManager.getInstance(myProject).getModuleGroupPath(getModule(moduleName));
if (expected.length == 0) {
assertNull(path);
}
else {
assertNotNull(path);
assertOrderedElementsAreEqual(Arrays.asList(path), expected);
}
}
protected Module getModule(final String name) {
AccessToken accessToken = ApplicationManager.getApplication().acquireReadActionLock();
try {
Module m = ModuleManager.getInstance(myProject).findModuleByName(name);
assertNotNull("Module " + name + " not found", m);
return m;
}
finally {
accessToken.finish();
}
}
private ContentEntry getContentRoot(String moduleName) {
ContentEntry[] ee = getContentRoots(moduleName);
List<String> roots = new ArrayList<String>();
for (ContentEntry e : ee) {
roots.add(e.getUrl());
}
String message = "Several content roots found: [" + StringUtil.join(roots, ", ") + "]";
assertEquals(message, 1, ee.length);
return ee[0];
}
private ContentEntry getContentRoot(String moduleName, String path) {
for (ContentEntry e : getContentRoots(moduleName)) {
if (e.getUrl().equals(VfsUtil.pathToUrl(path))) return e;
}
throw new AssertionError("content root not found");
}
public ContentEntry[] getContentRoots(String moduleName) {
return getRootManager(moduleName).getContentEntries();
}
private ModuleRootManager getRootManager(String module) {
return ModuleRootManager.getInstance(getModule(module));
}
protected void importProject(@NonNls String xml) throws IOException {
createProjectPom(xml);
importProject();
}
protected void importProject() {
importProjectWithProfiles();
}
protected void importProjectWithProfiles(String... profiles) {
doImportProjects(true, Collections.singletonList(myProjectPom), profiles);
}
protected void importProject(VirtualFile file) {
importProjects(file);
}
protected void importProjects(VirtualFile... files) {
doImportProjects(true, Arrays.asList(files));
}
protected void importProjectWithMaven3(@NonNls String xml) throws IOException {
createProjectPom(xml);
importProjectWithMaven3();
}
protected void importProjectWithMaven3() {
importProjectWithMaven3WithProfiles();
}
protected void importProjectWithMaven3WithProfiles(String... profiles) {
doImportProjects(false, Collections.singletonList(myProjectPom), profiles);
}
private void doImportProjects(boolean useMaven2, final List<VirtualFile> files, String... profiles) {
MavenServerManager.getInstance().setUseMaven2(useMaven2);
initProjectsManager(false);
readProjects(files, profiles);
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myProjectsManager.waitForResolvingCompletion();
myProjectsManager.scheduleImportInTests(files);
myProjectsManager.importProjects();
}
});
for (MavenProject each : myProjectsTree.getProjects()) {
if (each.hasReadingProblems()) {
System.out.println(each + " has problems: " + each.getProblems());
}
}
}
protected void readProjects(List<VirtualFile> files, String... profiles) {
myProjectsManager.resetManagedFilesAndProfilesInTests(files, new MavenExplicitProfiles(Arrays.asList(profiles)));
waitForReadingCompletion();
}
protected void updateProjectsAndImport(VirtualFile... files) {
readProjects(files);
myProjectsManager.performScheduledImportInTests();
}
protected void initProjectsManager(boolean enableEventHandling) {
myProjectsManager.initForTests();
myProjectsTree = myProjectsManager.getProjectsTreeForTests();
if (enableEventHandling) myProjectsManager.listenForExternalChanges();
}
protected void scheduleResolveAll() {
myProjectsManager.scheduleResolveAllInTests();
}
protected void waitForReadingCompletion() {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
myProjectsManager.waitForReadingCompletion();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
}
protected void readProjects() {
readProjects(myProjectsManager.getProjectsFiles());
}
protected void readProjects(VirtualFile... files) {
List<MavenProject> projects = new ArrayList<MavenProject>();
for (VirtualFile each : files) {
projects.add(myProjectsManager.findProject(each));
}
myProjectsManager.forceUpdateProjects(projects);
waitForReadingCompletion();
}
protected void resolveDependenciesAndImport() {
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myProjectsManager.waitForResolvingCompletion();
myProjectsManager.performScheduledImportInTests();
}
});
}
protected void resolveFoldersAndImport() {
myProjectsManager.scheduleFoldersResolveForAllProjects();
myProjectsManager.waitForFoldersResolvingCompletion();
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
myProjectsManager.performScheduledImportInTests();
}
});
}
protected void resolvePlugins() {
myProjectsManager.waitForPluginsResolvingCompletion();
}
protected void downloadArtifacts() {
downloadArtifacts(myProjectsManager.getProjects(), null);
}
protected MavenArtifactDownloader.DownloadResult downloadArtifacts(Collection<MavenProject> projects,
List<MavenArtifact> artifacts) {
final MavenArtifactDownloader.DownloadResult[] unresolved = new MavenArtifactDownloader.DownloadResult[1];
AsyncResult<MavenArtifactDownloader.DownloadResult> result = new AsyncResult<MavenArtifactDownloader.DownloadResult>();
result.doWhenDone(new Consumer<MavenArtifactDownloader.DownloadResult>() {
@Override
public void consume(MavenArtifactDownloader.DownloadResult unresolvedArtifacts) {
unresolved[0] = unresolvedArtifacts;
}
});
myProjectsManager.scheduleArtifactsDownloading(projects, artifacts, true, true, result);
myProjectsManager.waitForArtifactsDownloadingCompletion();
return unresolved[0];
}
protected void performPostImportTasks() {
myProjectsManager.waitForPostImportTasksCompletion();
}
protected void executeGoal(String relativePath, String goal) {
VirtualFile dir = myProjectRoot.findFileByRelativePath(relativePath);
MavenRunnerParameters rp = new MavenRunnerParameters(true, dir.getPath(), Arrays.asList(goal), Collections.<String>emptyList());
MavenRunnerSettings rs = new MavenRunnerSettings();
MavenExecutor e = new MavenExternalExecutor(myProject, rp, getMavenGeneralSettings(), rs, new SoutMavenConsole());
e.execute(new EmptyProgressIndicator());
}
protected void removeFromLocalRepository(String relativePath) throws IOException {
FileUtil.delete(new File(getRepositoryPath(), relativePath));
}
protected void setupJdkForModules(String... moduleNames) {
for (String each : moduleNames) {
setupJdkForModule(each);
}
}
protected Sdk setupJdkForModule(final String moduleName) {
final Sdk sdk = JavaAwareProjectJdkTableImpl.getInstanceEx().getInternalJdk();
ModuleRootModificationUtil.setModuleSdk(getModule(moduleName), sdk);
return sdk;
}
protected static Sdk createJdk(String versionName) {
return IdeaTestUtil.getMockJdk17(versionName);
}
protected static AtomicInteger configConfirmationForYesAnswer() {
final AtomicInteger counter = new AtomicInteger();
Messages.setTestDialog(new TestDialog() {
@Override
public int show(String message) {
counter.set(counter.get() + 1);
return 0;
}
});
return counter;
}
protected static AtomicInteger configConfirmationForNoAnswer() {
final AtomicInteger counter = new AtomicInteger();
Messages.setTestDialog(new TestDialog() {
@Override
public int show(String message) {
counter.set(counter.get() + 1);
return 1;
}
});
return counter;
}
}
@@ -0,0 +1,621 @@
/*
* Copyright 2010-2016 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.openapi.application.ApplicationManager;
import com.intellij.openapi.application.Result;
import com.intellij.openapi.application.WriteAction;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.module.ModuleType;
import com.intellij.openapi.module.StdModuleTypes;
import com.intellij.openapi.progress.EmptyProgressIndicator;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.PsiTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.testFramework.fixtures.IdeaProjectTestFixture;
import com.intellij.testFramework.fixtures.IdeaTestFixtureFactory;
import com.intellij.util.ui.UIUtil;
import gnu.trove.THashSet;
import org.intellij.lang.annotations.Language;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.idea.maven.indices.MavenIndicesManager;
import org.jetbrains.idea.maven.project.*;
import org.jetbrains.idea.maven.server.MavenServerManager;
import org.jetbrains.idea.maven.utils.MavenProgressIndicator;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
public abstract class MavenTestCase extends UsefulTestCase {
protected static final MavenConsole NULL_MAVEN_CONSOLE = new NullMavenConsole();
// should not be static
protected static MavenProgressIndicator EMPTY_MAVEN_PROCESS = new MavenProgressIndicator(new EmptyProgressIndicator());
private File ourTempDir;
protected IdeaProjectTestFixture myTestFixture;
protected Project myProject;
protected File myDir;
protected VirtualFile myProjectRoot;
protected VirtualFile myProjectPom;
protected List<VirtualFile> myAllPoms = new ArrayList<VirtualFile>();
@Override
protected void setUp() throws Exception {
super.setUp();
ensureTempDirCreated();
myDir = new File(ourTempDir, getTestName(false));
FileUtil.ensureExists(myDir);
setUpFixtures();
myProject = myTestFixture.getProject();
MavenWorkspaceSettingsComponent.getInstance(myProject).loadState(new MavenWorkspaceSettings());
String home = getTestMavenHome();
if (home != null) {
getMavenGeneralSettings().setMavenHome(home);
}
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
restoreSettingsFile();
}
catch (IOException e) {
throw new RuntimeException(e);
}
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
try {
setUpInWriteAction();
}
catch (Throwable e) {
try {
tearDown();
}
catch (Exception e1) {
e1.printStackTrace();
}
throw new RuntimeException(e);
}
}
});
}
});
}
private void ensureTempDirCreated() throws IOException {
if (ourTempDir != null) return;
ourTempDir = new File(FileUtil.getTempDirectory(), "mavenTests");
FileUtil.delete(ourTempDir);
FileUtil.ensureExists(ourTempDir);
}
protected void setUpFixtures() throws Exception {
myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()).getFixture();
myTestFixture.setUp();
}
protected void setUpInWriteAction() throws Exception {
File projectDir = new File(myDir, "project");
projectDir.mkdirs();
myProjectRoot = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(projectDir);
}
@Override
protected void tearDown() throws Exception {
try {
MavenServerManager.getInstance().shutdown(true);
MavenArtifactDownloader.awaitQuiescence(100, TimeUnit.SECONDS);
myProject = null;
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
@Override
public void run() {
try {
tearDownFixtures();
}
catch (Exception e) {
throw new RuntimeException(e);
}
}
});
MavenIndicesManager.getInstance().clear();
}
finally {
super.tearDown();
FileUtil.delete(myDir);
// cannot use reliably the result of the com.intellij.openapi.util.io.FileUtil.delete() method
// because com.intellij.openapi.util.io.FileUtilRt.deleteRecursivelyNIO() does not honor this contract
if (myDir.exists()) {
System.err.println("Cannot delete " + myDir);
//printDirectoryContent(myDir);
myDir.deleteOnExit();
}
resetClassFields(getClass());
}
}
private static void printDirectoryContent(File dir) {
File[] files = dir.listFiles();
if (files == null) return;
for (File file : files) {
System.out.println(file.getAbsolutePath());
if (file.isDirectory()) {
printDirectoryContent(file);
}
}
}
protected void tearDownFixtures() throws Exception {
myTestFixture.tearDown();
myTestFixture = null;
}
private void resetClassFields(final Class<?> aClass) {
if (aClass == null) return;
final Field[] fields = aClass.getDeclaredFields();
for (Field field : fields) {
final int modifiers = field.getModifiers();
if ((modifiers & Modifier.FINAL) == 0
&& (modifiers & Modifier.STATIC) == 0
&& !field.getType().isPrimitive()) {
field.setAccessible(true);
try {
field.set(this, null);
}
catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
if (aClass == MavenTestCase.class) return;
resetClassFields(aClass.getSuperclass());
}
@Override
protected void runTest() throws Throwable {
try {
if (runInWriteAction()) {
new WriteAction() {
@Override
protected void run(@NotNull Result result) throws Throwable {
MavenTestCase.super.runTest();
}
}.executeSilently().throwException();
}
else {
MavenTestCase.super.runTest();
}
}
catch (Exception throwable) {
Throwable each = throwable;
do {
if (each instanceof HeadlessException) {
printIgnoredMessage("Doesn't work in Headless environment");
return;
}
}
while ((each = each.getCause()) != null);
throw throwable;
}
}
@Override
protected void invokeTestRunnable(@NotNull Runnable runnable) throws Exception {
runnable.run();
}
protected boolean runInWriteAction() {
return false;
}
protected static String getRoot() {
if (SystemInfo.isWindows) return "c:";
return "";
}
protected static String getEnvVar() {
if (SystemInfo.isWindows) return "TEMP";
else if (SystemInfo.isLinux) return "HOME";
return "TMPDIR";
}
protected MavenGeneralSettings getMavenGeneralSettings() {
return MavenProjectsManager.getInstance(myProject).getGeneralSettings();
}
protected MavenImportingSettings getMavenImporterSettings() {
return MavenProjectsManager.getInstance(myProject).getImportingSettings();
}
protected String getRepositoryPath() {
String path = getRepositoryFile().getPath();
return FileUtil.toSystemIndependentName(path);
}
protected File getRepositoryFile() {
return getMavenGeneralSettings().getEffectiveLocalRepository();
}
protected void setRepositoryPath(String path) {
getMavenGeneralSettings().setLocalRepository(path);
}
protected String getProjectPath() {
return myProjectRoot.getPath();
}
protected String getParentPath() {
return myProjectRoot.getParent().getPath();
}
protected String pathFromBasedir(String relPath) {
return pathFromBasedir(myProjectRoot, relPath);
}
protected static String pathFromBasedir(VirtualFile root, String relPath) {
return FileUtil.toSystemIndependentName(root.getPath() + "/" + relPath);
}
protected VirtualFile updateSettingsXml(String content) throws IOException {
return updateSettingsXmlFully(createSettingsXmlContent(content));
}
protected VirtualFile updateSettingsXmlFully(@NonNls @Language("XML") String content) throws IOException {
File ioFile = new File(myDir, "settings.xml");
ioFile.createNewFile();
VirtualFile f = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(ioFile);
setFileContent(f, content, true);
getMavenGeneralSettings().setUserSettingsFile(f.getPath());
return f;
}
protected void deleteSettingsXml() throws IOException {
new WriteCommandAction.Simple(myProject) {
@Override
protected void run() throws Throwable {
VirtualFile f = LocalFileSystem.getInstance().refreshAndFindFileByIoFile(new File(myDir, "settings.xml"));
if (f != null) f.delete(this);
}
}.execute().throwException();
}
private static String createSettingsXmlContent(String content) {
String mirror = System.getProperty("idea.maven.test.mirror",
// use JB maven proxy server for internal use by default, see details at
// https://confluence.jetbrains.com/display/JBINT/Maven+proxy+server
"http://maven.labs.intellij.net/repo1");
return "<settings>" +
content +
"<mirrors>" +
" <mirror>" +
" <id>jb-central-proxy</id>" +
" <url>" + mirror + "</url>" +
" <mirrorOf>external:*</mirrorOf>" +
" </mirror>" +
"</mirrors>" +
"</settings>";
}
protected void restoreSettingsFile() throws IOException {
updateSettingsXml("");
}
protected Module createModule(String name) throws IOException {
return createModule(name, StdModuleTypes.JAVA);
}
protected Module createModule(final String name, final ModuleType type) throws IOException {
return new WriteCommandAction<Module>(myProject) {
@Override
protected void run(@NotNull Result<Module> moduleResult) throws Throwable {
VirtualFile f = createProjectSubFile(name + "/" + name + ".iml");
Module module = ModuleManager.getInstance(myProject).newModule(f.getPath(), type.getId());
PsiTestUtil.addContentRoot(module, f.getParent());
moduleResult.setResult(module);
}
}.execute().getResultObject();
}
protected VirtualFile createProjectPom(@NonNls String xml) throws IOException {
return myProjectPom = createPomFile(myProjectRoot, xml);
}
protected VirtualFile createModulePom(String relativePath, String xml) throws IOException {
return createPomFile(createProjectSubDir(relativePath), xml);
}
protected VirtualFile createPomFile(final VirtualFile dir, String xml) throws IOException {
VirtualFile f = dir.findChild("pom.xml");
if (f == null) {
f = new WriteAction<VirtualFile>() {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
VirtualFile res = dir.createChildData(null, "pom.xml");
result.setResult(res);
}
}.execute().getResultObject();
myAllPoms.add(f);
}
setFileContent(f, createPomXml(xml), true);
return f;
}
@NonNls @Language(value="XML")
public static String createPomXml(@NonNls @Language(value="XML", prefix="<xml>", suffix="</xml>") String xml) {
return "<?xml version=\"1.0\"?>" +
"<project xmlns=\"http://maven.apache.org/POM/4.0.0\"" +
" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"" +
" xsi:schemaLocation=\"http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd\">" +
" <modelVersion>4.0.0</modelVersion>" +
xml +
"</project>";
}
protected VirtualFile createProfilesXmlOldStyle(String xml) throws IOException {
return createProfilesFile(myProjectRoot, xml, true);
}
protected VirtualFile createProfilesXmlOldStyle(String relativePath, String xml) throws IOException {
return createProfilesFile(createProjectSubDir(relativePath), xml, true);
}
protected VirtualFile createProfilesXml(String xml) throws IOException {
return createProfilesFile(myProjectRoot, xml, false);
}
protected VirtualFile createProfilesXml(String relativePath, String xml) throws IOException {
return createProfilesFile(createProjectSubDir(relativePath), xml, false);
}
private static VirtualFile createProfilesFile(VirtualFile dir, String xml, boolean oldStyle) throws IOException {
return createProfilesFile(dir, createValidProfiles(xml, oldStyle));
}
protected VirtualFile createFullProfilesXml(String content) throws IOException {
return createProfilesFile(myProjectRoot, content);
}
protected VirtualFile createFullProfilesXml(String relativePath, String content) throws IOException {
return createProfilesFile(createProjectSubDir(relativePath), content);
}
private static VirtualFile createProfilesFile(final VirtualFile dir, String content) throws IOException {
VirtualFile f = dir.findChild("profiles.xml");
if (f == null) {
f = new WriteAction<VirtualFile>() {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
VirtualFile res = dir.createChildData(null, "profiles.xml");
result.setResult(res);
}
}.execute().getResultObject();
}
setFileContent(f, content, true);
return f;
}
@Language("XML")
private static String createValidProfiles(String xml, boolean oldStyle) {
if (oldStyle) {
return "<?xml version=\"1.0\"?>" +
"<profiles>" +
xml +
"</profiles>";
}
return "<?xml version=\"1.0\"?>" +
"<profilesXml>" +
"<profiles>" +
xml +
"</profiles>" +
"</profilesXml>";
}
protected void deleteProfilesXml() throws IOException {
new WriteCommandAction.Simple(myProject) {
@Override
protected void run() throws Throwable {
VirtualFile f = myProjectRoot.findChild("profiles.xml");
if (f != null) f.delete(this);
}
}.execute().throwException();
}
protected void createStdProjectFolders() {
createProjectSubDirs("src/main/java",
"src/main/resources",
"src/test/java",
"src/test/resources");
}
protected void createProjectSubDirs(String... relativePaths) {
for (String path : relativePaths) {
createProjectSubDir(path);
}
}
protected VirtualFile createProjectSubDir(String relativePath) {
File f = new File(getProjectPath(), relativePath);
f.mkdirs();
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
}
protected VirtualFile createProjectSubFile(String relativePath) throws IOException {
File f = new File(getProjectPath(), relativePath);
f.getParentFile().mkdirs();
f.createNewFile();
return LocalFileSystem.getInstance().refreshAndFindFileByIoFile(f);
}
protected VirtualFile createProjectSubFile(String relativePath, String content) throws IOException {
VirtualFile file = createProjectSubFile(relativePath);
setFileContent(file, content, false);
return file;
}
private static void setFileContent(final VirtualFile file, final String content, final boolean advanceStamps) throws IOException {
new WriteAction<VirtualFile>() {
@Override
protected void run(@NotNull Result<VirtualFile> result) throws Throwable {
if (advanceStamps) {
file.setBinaryContent(content.getBytes(), -1, file.getTimeStamp() + 4000);
}
else {
file.setBinaryContent(content.getBytes(), file.getModificationStamp(), file.getTimeStamp());
}
}
}.execute().getResultObject();
}
protected static <T, U> void assertOrderedElementsAreEqual(Collection<U> actual, Collection<T> expected) {
assertOrderedElementsAreEqual(actual, expected.toArray());
}
protected static <T> void assertUnorderedElementsAreEqual(Collection<T> actual, Collection<T> expected) {
assertEquals(new HashSet<T>(expected), new HashSet<T>(actual));
}
protected static void assertUnorderedPathsAreEqual(Collection<String> actual, Collection<String> expected) {
assertEquals(new SetWithToString<String>(new THashSet<String>(expected, FileUtil.PATH_HASHING_STRATEGY)),
new SetWithToString<String>(new THashSet<String>(actual, FileUtil.PATH_HASHING_STRATEGY)));
}
protected static <T> void assertUnorderedElementsAreEqual(T[] actual, T... expected) {
assertUnorderedElementsAreEqual(Arrays.asList(actual), expected);
}
protected static <T> void assertUnorderedElementsAreEqual(Collection<T> actual, T... expected) {
assertUnorderedElementsAreEqual(actual, Arrays.asList(expected));
}
protected static <T, U> void assertOrderedElementsAreEqual(Collection<U> actual, T... expected) {
String s = "\nexpected: " + Arrays.asList(expected) + "\nactual: " + new ArrayList<U>(actual);
assertEquals(s, expected.length, actual.size());
List<U> actualList = new ArrayList<U>(actual);
for (int i = 0; i < expected.length; i++) {
T expectedElement = expected[i];
U actualElement = actualList.get(i);
assertEquals(s, expectedElement, actualElement);
}
}
protected static <T> void assertContain(List<? extends T> actual, T... expected) {
List<T> expectedList = Arrays.asList(expected);
assertTrue("expected: " + expectedList + "\n" + "actual: " + actual.toString(), actual.containsAll(expectedList));
}
protected static <T> void assertDoNotContain(List<T> actual, T... expected) {
List<T> actualCopy = new ArrayList<T>(actual);
actualCopy.removeAll(Arrays.asList(expected));
assertEquals(actual.toString(), actualCopy.size(), actual.size());
}
protected boolean ignore() {
printIgnoredMessage(null);
return true;
}
protected boolean hasMavenInstallation() {
boolean result = getTestMavenHome() != null;
if (!result) printIgnoredMessage("Maven installation not found");
return result;
}
private void printIgnoredMessage(String message) {
String toPrint = "Ignored";
if (message != null) {
toPrint += ", because " + message;
}
toPrint += ": " + getClass().getSimpleName() + "." + getName();
System.out.println(toPrint);
}
private static String getTestMavenHome() {
return System.getProperty("idea.maven.test.home");
}
private static class SetWithToString<T> extends AbstractSet<T> {
private final Set<T> myDelegate;
public SetWithToString(@NotNull Set<T> delegate) {
myDelegate = delegate;
}
@Override
public int size() {
return myDelegate.size();
}
@Override
public boolean contains(Object o) {
return myDelegate.contains(o);
}
@NotNull
@Override
public Iterator<T> iterator() {
return myDelegate.iterator();
}
@Override
public boolean containsAll(Collection<?> c) {
return myDelegate.containsAll(c);
}
@Override
public boolean equals(Object o) {
return myDelegate.equals(o);
}
@Override
public int hashCode() {
return myDelegate.hashCode();
}
}
}
@@ -0,0 +1,49 @@
/*
* 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.execution.process.ProcessHandler;
import org.jetbrains.idea.maven.execution.MavenExecutionOptions;
import org.jetbrains.idea.maven.project.MavenConsole;
public class NullMavenConsole extends MavenConsole {
public NullMavenConsole() {
super(MavenExecutionOptions.LoggingLevel.DISABLED, false);
}
@Override
public boolean canPause() {
return false;
}
@Override
public boolean isOutputPaused() {
return false;
}
@Override
public void setOutputPaused(boolean outputPaused) {
}
@Override
public void attachToProcess(ProcessHandler processHandler) {
}
@Override
protected void doPrint(String text, MavenConsole.OutputType type) {
}
}
@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>js</id>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
</project>
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>js</id>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
<execution>
<id>js-test</id>
<phase>test-compile</phase>
<goals>
<goal>test-js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>js</id>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
<execution>
<id>js-test</id>
<phase>test-compile</phase>
<goals>
<goal>test-js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>js</id>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
<execution>
<id>js-test</id>
<phase>test-compile</phase>
<goals>
<goal>test-js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
<!--
// VERSION: 0.1-SNAPSHOT
-->
@@ -0,0 +1,82 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<repositories>
<repository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonatype.oss.snapshots</id>
<name>Sonatype OSS Snapshot Repository</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonatype.oss.snapshots</id>
<name>Sonatype OSS Snapshot Repository</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</pluginRepository>
</pluginRepositories>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>js</id>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
<execution>
<id>js-test</id>
<phase>test-compile</phase>
<goals>
<goal>test-js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!--
// VERSION: $VERSION$
-->
@@ -0,0 +1,42 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>wrong-kotlin-version</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>wrong-version</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>wrong-source-dir</sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>wrong-plugin-version</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>wrong-goal</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>wrong-goal</goal>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,40 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
</project>
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</project>
@@ -0,0 +1,61 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
@@ -0,0 +1,63 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
<!--
// VERSION: 0.1-SNAPSHOT
-->
@@ -0,0 +1,94 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>maventest</groupId>
<artifactId>maventest</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>$VERSION$</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
</dependencies>
<repositories>
<repository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonatype.oss.snapshots</id>
<name>Sonatype OSS Snapshot Repository</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<releases>
<enabled>false</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
<id>sonatype.oss.snapshots</id>
<name>Sonatype OSS Snapshot Repository</name>
<url>http://oss.sonatype.org/content/repositories/snapshots</url>
</pluginRepository>
</pluginRepositories>
<build>
<sourceDirectory></sourceDirectory>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!--
// VERSION: $VERSION$
-->
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on <goals><goal>compile</goal><goal>test-compile</goal></goals>, title It is not recommended to have both test and compile goals in the same execution -->
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on kotlin-stdlib, title You have kotlin-stdlib configured but no corresponding plugin execution -->
<!-- problem: on kotlin-js-library, title You have kotlin-js-library configured but no corresponding plugin execution -->
@@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on kotlin-stdlib, title You have kotlin-stdlib configured but no corresponding plugin execution -->
<!-- problem: on kotlin-js-library, title You have kotlin-js-library configured but no corresponding plugin execution -->
@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</project>
<!-- problem: on kotlin-stdlib, title You have kotlin-stdlib configured but no corresponding plugin execution -->
<!-- problem: on kotlin-js-library, title You have kotlin-js-library configured but no corresponding plugin execution -->
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
<goal>js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on kotlin-maven-plugin, title Kotlin JVM compiler configured but no kotlin-stdlib dependency -->
<!-- problem: on kotlin-maven-plugin, title Kotlin JavaScript compiler configured but no kotlin-js-library dependency -->
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
<goal>js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on kotlin-maven-plugin, title Kotlin JVM compiler configured but no kotlin-stdlib dependency -->
<!-- problem: on kotlin-maven-plugin, title Kotlin JavaScript compiler configured but no kotlin-js-library dependency -->
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
<goal>js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on kotlin-maven-plugin, title Kotlin JVM compiler configured but no kotlin-stdlib dependency -->
<!-- problem: on kotlin-maven-plugin, title Kotlin JavaScript compiler configured but no kotlin-js-library dependency -->
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on kotlin-maven-plugin, title Kotlin plugin has no compile executions -->
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>js</id>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on kotlin-maven-plugin, title Kotlin plugin has no compile executions -->
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
</plugin>
</plugins>
</build>
</project>
<!-- problem: on kotlin-maven-plugin, title Kotlin plugin has no compile executions -->
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-library</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>js</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- mkjava -->
<!-- problem: on js, title JavaScript goal configured for module with Java files -->
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<phase>process-sources</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- mkjava -->
<!-- problem: on compile, title Kotlin plugin should run before javac so kotlin classes could be visible from Java -->
@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.test</groupId>
<artifactId>configure-maven-test</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<kotlin.version>1.0.1</kotlin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
<!-- mkjava -->
<!-- problem: on compile, title Kotlin plugin should run before javac so kotlin classes could be visible from Java -->