Reformat and cleanup idea-maven_main module

This commit is contained in:
Nikolay Krasko
2018-01-17 18:39:29 +03:00
parent 7f1cc81d39
commit 4a2440ea0f
23 changed files with 2059 additions and 1788 deletions
+1
View File
@@ -2,6 +2,7 @@
<dictionary name="Nikolay.Krasko">
<words>
<w>accessors</w>
<w>coroutines</w>
<w>crossinline</w>
<w>fqname</w>
<w>goto</w>
@@ -29,10 +29,36 @@ import java.net.HttpURLConnection
import java.net.URLEncoder
import java.util.concurrent.TimeUnit
class KotlinMavenArchetypesProvider(val kotlinPluginVersion: String, val predefinedInternalMode: Boolean?) : MavenArchetypesProvider {
class KotlinMavenArchetypesProvider(private val kotlinPluginVersion: String, private val predefinedInternalMode: Boolean?) :
MavenArchetypesProvider {
@Suppress("unused")
constructor() : this(KotlinPluginUtil.getPluginVersion(), null)
val VERSIONS_LIST_URL = mavenSearchUrl("org.jetbrains.kotlin", packaging = "maven-archetype", rowsLimit = 1000)
companion object {
private val VERSIONS_LIST_URL = mavenSearchUrl("org.jetbrains.kotlin", packaging = "maven-archetype", rowsLimit = 1000)
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 }.joinToString(separator = " AND ") { "${it.first}:\"${it.second}\"" }
return "http://search.maven.org/solrsearch/select?q=${q.encodeURL()}&core=gav&rows=$rowsLimit&wt=json"
}
private fun String.encodeURL() = URLEncoder.encode(this, "UTF-8")
}
private val versionPrefix by lazy { versionPrefix(kotlinPluginVersion) }
private val fallbackVersion = "1.0.3"
private val internalMode: Boolean
@@ -41,8 +67,7 @@ class KotlinMavenArchetypesProvider(val kotlinPluginVersion: String, val predefi
private val archetypesBlocking by lazy {
try {
loadVersions().ifEmpty { fallbackArchetypes() }
}
catch (t: Throwable) {
} catch (t: Throwable) {
fallbackArchetypes()
}
}
@@ -50,8 +75,8 @@ class KotlinMavenArchetypesProvider(val kotlinPluginVersion: String, val predefi
override fun getArchetypes() = archetypesBlocking.toMutableList()
private fun fallbackArchetypes() =
listOf("kotlin-archetype-jvm", "kotlin-archetype-js")
.map { MavenArchetype("org.jetbrains.kotlin", it, fallbackVersion, null, null) }
listOf("kotlin-archetype-jvm", "kotlin-archetype-js")
.map { MavenArchetype("org.jetbrains.kotlin", it, fallbackVersion, null, null) }
private fun loadVersions(): List<MavenArchetype> {
return connectAndApply(VERSIONS_LIST_URL) { urlConnection ->
@@ -62,39 +87,27 @@ class KotlinMavenArchetypesProvider(val kotlinPluginVersion: String, val predefi
}
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) }
.let { versions ->
val prefix = versionPrefix
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) }
.let { versions ->
val prefix = versionPrefix
when {
internalMode || prefix == null -> versions
else -> versions.filter { it.version?.startsWith(prefix) ?: false }.ifEmpty { versions }
}
.groupBy { it.groupId + ":" + it.artifactId + ":" + versionPrefix(it.version) }
.mapValues { chooseVersion(it.value) }
.mapNotNull { it.value }
}
when {
internalMode || prefix == null -> versions
else -> versions.filter { it.version?.startsWith(prefix) ?: false }.ifEmpty { versions }
}
.groupBy { it.groupId + ":" + it.artifactId + ":" + versionPrefix(it.version) }
.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 }.joinToString(separator = " AND ") { "${it.first}:\"${it.second}\"" }
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()
@@ -107,14 +120,11 @@ class KotlinMavenArchetypesProvider(val kotlinPluginVersion: String, val predefi
}
private fun <R> HttpURLConnection.use(block: (HttpURLConnection) -> R): R =
try {
block(this)
}
finally {
disconnect()
}
private fun String.encodeURL() = URLEncoder.encode(this, "UTF-8")
try {
block(this)
} finally {
disconnect()
}
private fun versionPrefix(version: String) = """^\d+\.\d+\.""".toRegex().find(version)?.value
}
@@ -53,8 +53,8 @@ import java.util.*
interface MavenProjectImportHandler {
companion object : ProjectExtensionDescriptor<MavenProjectImportHandler>(
"org.jetbrains.kotlin.mavenProjectImportHandler",
MavenProjectImportHandler::class.java
"org.jetbrains.kotlin.mavenProjectImportHandler",
MavenProjectImportHandler::class.java
)
operator fun invoke(facet: KotlinFacet, mavenProject: MavenProject)
@@ -62,30 +62,42 @@ interface MavenProjectImportHandler {
class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ARTIFACT_ID) {
companion object {
val KOTLIN_PLUGIN_GROUP_ID = "org.jetbrains.kotlin"
val KOTLIN_PLUGIN_ARTIFACT_ID = "kotlin-maven-plugin"
const val KOTLIN_PLUGIN_GROUP_ID = "org.jetbrains.kotlin"
const val KOTLIN_PLUGIN_ARTIFACT_ID = "kotlin-maven-plugin"
val KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG = "sourceDirs"
const val KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG = "sourceDirs"
}
override fun preProcess(module: Module, mavenProject: MavenProject, changes: MavenProjectChanges, modifiableModelsProvider: IdeModifiableModelsProvider) {
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>) {
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)
}
}
override fun postProcess(module: Module, mavenProject: MavenProject, changes: MavenProjectChanges, modifiableModelsProvider: IdeModifiableModelsProvider) {
override fun postProcess(
module: Module,
mavenProject: MavenProject,
changes: MavenProjectChanges,
modifiableModelsProvider: IdeModifiableModelsProvider
) {
super.postProcess(module, mavenProject, changes, modifiableModelsProvider)
if (changes.dependencies) {
@@ -108,7 +120,8 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
private fun scheduleDownloadStdlibSources(mavenProject: MavenProject, module: Module) {
// TODO: here we have to process all kotlin libraries but for now we only handle standard libraries
val artifacts = mavenProject.dependencyArtifactIndex.data[KOTLIN_PLUGIN_GROUP_ID]?.values?.flatMap { it.filter { it.isResolved } } ?: emptyList()
val artifacts = mavenProject.dependencyArtifactIndex.data[KOTLIN_PLUGIN_GROUP_ID]?.values?.flatMap { it.filter { it.isResolved } }
?: emptyList()
val librariesWithNoSources = ArrayList<Library>()
OrderEnumerator.orderEntries(module).forEachLibrary { library ->
@@ -121,21 +134,26 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
val toBeDownloaded = artifacts.filter { it.libraryName in libraryNames }
if (toBeDownloaded.isNotEmpty()) {
MavenProjectsManager.getInstance(module.project).scheduleArtifactsDownloading(listOf(mavenProject), toBeDownloaded, true, false, AsyncResult())
MavenProjectsManager.getInstance(module.project)
.scheduleArtifactsDownloading(listOf(mavenProject), toBeDownloaded, true, false, AsyncResult())
}
}
private fun getCompilerArgumentsByConfigurationElement(mavenProject: MavenProject,
configuration: Element?,
platform: TargetPlatformKind<*>): List<String> {
private fun getCompilerArgumentsByConfigurationElement(
mavenProject: MavenProject,
configuration: Element?,
platform: TargetPlatformKind<*>
): List<String> {
val arguments = when (platform) {
is TargetPlatformKind.Jvm -> K2JVMCompilerArguments()
is TargetPlatformKind.JavaScript -> K2JSCompilerArguments()
is TargetPlatformKind.Common -> K2MetadataCompilerArguments()
TargetPlatformKind.JavaScript -> K2JSCompilerArguments()
TargetPlatformKind.Common -> K2MetadataCompilerArguments()
}
arguments.apiVersion = configuration?.getChild("apiVersion")?.text ?: mavenProject.properties["kotlin.compiler.apiVersion"]?.toString()
arguments.languageVersion = configuration?.getChild("languageVersion")?.text ?: mavenProject.properties["kotlin.compiler.languageVersion"]?.toString()
arguments.apiVersion = configuration?.getChild("apiVersion")?.text ?:
mavenProject.properties["kotlin.compiler.apiVersion"]?.toString()
arguments.languageVersion = configuration?.getChild("languageVersion")?.text ?:
mavenProject.properties["kotlin.compiler.languageVersion"]?.toString()
arguments.multiPlatform = configuration?.getChild("multiPlatform")?.text?.trim()?.toBoolean() ?: false
arguments.suppressWarnings = configuration?.getChild("nowarn")?.text?.trim()?.toBoolean() ?: false
@@ -147,7 +165,8 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
is K2JVMCompilerArguments -> {
arguments.classpath = configuration?.getChild("classpath")?.text
arguments.jdkHome = configuration?.getChild("jdkHome")?.text
arguments.jvmTarget = configuration?.getChild("jvmTarget")?.text ?: mavenProject.properties["kotlin.compiler.jvmTarget"]?.toString()
arguments.jvmTarget = configuration?.getChild("jvmTarget")?.text ?:
mavenProject.properties["kotlin.compiler.jvmTarget"]?.toString()
}
is K2JSCompilerArguments -> {
arguments.sourceMap = configuration?.getChild("sourceMap")?.text?.trim()?.toBoolean() ?: false
@@ -181,11 +200,13 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
return ArgumentUtils.convertArgumentsToStringList(arguments)
}
private val compilationGoals = listOf(PomFile.KotlinGoals.Compile,
PomFile.KotlinGoals.TestCompile,
PomFile.KotlinGoals.Js,
PomFile.KotlinGoals.TestJs,
PomFile.KotlinGoals.MetaData)
private val compilationGoals = listOf(
PomFile.KotlinGoals.Compile,
PomFile.KotlinGoals.TestCompile,
PomFile.KotlinGoals.Js,
PomFile.KotlinGoals.TestJs,
PomFile.KotlinGoals.MetaData
)
private fun configureFacet(mavenProject: MavenProject, modifiableModelsProvider: IdeModifiableModelsProvider, module: Module) {
val mavenPlugin = mavenProject.findPlugin(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID) ?: return
@@ -197,9 +218,9 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
val configuredPlatform = kotlinFacet.configuration.settings.targetPlatformKind!!
val configuration = mavenPlugin.configurationElement
val sharedArguments = getCompilerArgumentsByConfigurationElement(mavenProject, configuration, configuredPlatform)
val executionArguments = mavenPlugin.executions?.filter { it.goals.any { it in compilationGoals } }
?.firstOrNull()
?.configurationElement?.let { getCompilerArgumentsByConfigurationElement(mavenProject, it, configuredPlatform) }
val executionArguments = mavenPlugin.executions
?.firstOrNull { it.goals.any { it in compilationGoals } }
?.configurationElement?.let { getCompilerArgumentsByConfigurationElement(mavenProject, it, configuredPlatform) }
parseCompilerArgumentsToFacet(sharedArguments, emptyList(), kotlinFacet, modifiableModelsProvider)
if (executionArguments != null) {
parseCompilerArgumentsToFacet(executionArguments, emptyList(), kotlinFacet, modifiableModelsProvider)
@@ -209,18 +230,19 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
kotlinFacet.noVersionAutoAdvance()
}
private fun detectPlatform(mavenProject: MavenProject) = detectPlatformByExecutions(mavenProject) ?:
detectPlatformByLibraries(mavenProject)
private fun detectPlatform(mavenProject: MavenProject) =
detectPlatformByExecutions(mavenProject) ?: detectPlatformByLibraries(mavenProject)
private fun detectPlatformByExecutions(mavenProject: MavenProject): TargetPlatformKind<*>? {
return mavenProject.findPlugin(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ARTIFACT_ID)?.executions?.flatMap { it.goals }?.mapNotNull { goal ->
when (goal) {
PomFile.KotlinGoals.Compile, PomFile.KotlinGoals.TestCompile -> TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]
PomFile.KotlinGoals.Js, PomFile.KotlinGoals.TestJs -> TargetPlatformKind.JavaScript
PomFile.KotlinGoals.MetaData -> TargetPlatformKind.Common
else -> null
}
}?.distinct()?.singleOrNull()
return mavenProject.findPlugin(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_ARTIFACT_ID)?.executions?.flatMap { it.goals }
?.mapNotNull { goal ->
when (goal) {
PomFile.KotlinGoals.Compile, PomFile.KotlinGoals.TestCompile -> TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]
PomFile.KotlinGoals.Js, PomFile.KotlinGoals.TestJs -> TargetPlatformKind.JavaScript
PomFile.KotlinGoals.MetaData -> TargetPlatformKind.Common
else -> null
}
}?.distinct()?.singleOrNull()
}
private fun detectPlatformByLibraries(mavenProject: MavenProject): TargetPlatformKind<*>? {
@@ -270,10 +292,12 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
}
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()
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 setImplementedModuleName(kotlinFacet: KotlinFacet, mavenProject: MavenProject, module: Module) {
if (kotlinFacet.configuration.settings.targetPlatformKind == TargetPlatformKind.Common) {
@@ -288,12 +312,17 @@ class KotlinMavenImporter : MavenImporter(KOTLIN_PLUGIN_GROUP_ID, KOTLIN_PLUGIN_
}
}
private fun MavenPlugin.isKotlinPlugin() = groupId == KotlinMavenImporter.KOTLIN_PLUGIN_GROUP_ID && artifactId == KotlinMavenImporter.KOTLIN_PLUGIN_ARTIFACT_ID
private fun Element?.sourceDirectories(): List<String> = this?.getChildren(KotlinMavenImporter.KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG)?.flatMap { it.children ?: emptyList() }?.map { it.textTrim } ?: emptyList()
private fun MavenPlugin.isKotlinPlugin() =
groupId == KotlinMavenImporter.KOTLIN_PLUGIN_GROUP_ID && artifactId == KotlinMavenImporter.KOTLIN_PLUGIN_ARTIFACT_ID
private fun Element?.sourceDirectories(): List<String> =
this?.getChildren(KotlinMavenImporter.KOTLIN_PLUGIN_SOURCE_DIRS_CONFIG)?.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
goals.map { if (isTestGoalName(it)) SourceType.TEST else SourceType.PROD }
.distinct()
.singleOrNull() ?: SourceType.PROD
private fun isTestGoalName(goalName: String) = goalName.startsWith("test-")
@@ -301,14 +330,14 @@ private enum class SourceType {
PROD, TEST
}
@State(name = "AutoImportedSourceRoots",
storages = arrayOf(
Storage(id = "other", file = StoragePathMacros.MODULE_FILE)
))
@State(
name = "AutoImportedSourceRoots",
storages = [(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>())
val addedSources: MutableSet<String> = Collections.synchronizedSet(HashSet<String>())
override fun loadState(state: State?) {
addedSources.clear()
@@ -24,21 +24,21 @@ import org.jetbrains.kotlin.config.LanguageVersion
import org.jetbrains.kotlin.idea.actions.internal.KotlinInternalMode
class MavenLanguageVersionsCompletionProvider : MavenFixedValueReferenceProvider(
LanguageVersion.values().filter { it.isStable || KotlinInternalMode.enabled }.map { it.versionString }.toTypedArray()
LanguageVersion.values().filter { it.isStable || KotlinInternalMode.enabled }.map { it.versionString }.toTypedArray()
)
class MavenApiVersionsCompletionProvider : MavenFixedValueReferenceProvider(
LanguageVersion.values().filter { it.isStable || KotlinInternalMode.enabled }.map { it.versionString }.toTypedArray()
LanguageVersion.values().filter { it.isStable || KotlinInternalMode.enabled }.map { it.versionString }.toTypedArray()
)
class MavenJvmTargetsCompletionProvider : MavenFixedValueReferenceProvider(
JvmTarget.values().map(JvmTarget::description).toTypedArray()
JvmTarget.values().map(JvmTarget::description).toTypedArray()
)
class MavenJsModuleKindsCompletionProvider : MavenFixedValueReferenceProvider(
DefaultValues.JsModuleKinds.possibleValues!!.map(StringUtil::unquoteString).toTypedArray()
DefaultValues.JsModuleKinds.possibleValues!!.map(StringUtil::unquoteString).toTypedArray()
)
class MavenJsMainCallCompletionProvider : MavenFixedValueReferenceProvider(
DefaultValues.JsMain.possibleValues!!.map(StringUtil::unquoteString).toTypedArray()
DefaultValues.JsMain.possibleValues!!.map(StringUtil::unquoteString).toTypedArray()
)
@@ -47,8 +47,12 @@ import java.util.*
fun kotlinPluginId(version: String?) = MavenId(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID, version)
class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomProjectModel) {
constructor(xmlFile: XmlFile) : this(xmlFile, MavenDomUtil.getMavenDomProjectModel(xmlFile.project, xmlFile.virtualFile) ?: throw IllegalStateException("No DOM model found for pom ${xmlFile.name}"))
class PomFile private constructor(private val xmlFile: XmlFile, val domModel: MavenDomProjectModel) {
constructor(xmlFile: XmlFile) : this(
xmlFile,
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
@@ -62,12 +66,10 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
if (element is XmlTag && element.localName in recommendedElementsOrder && element.parent === projectElement) {
nodesByName[element.localName] = element
}
else if (element is XmlTag && element.localName == "project") {
} else if (element is XmlTag && element.localName == "project") {
projectElement = element
element.acceptChildren(this)
}
else {
} else {
element.acceptChildren(this)
}
}
@@ -86,13 +88,11 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
val textNode = tag.children.filterIsInstance<XmlText>().firstOrNull()
if (textNode != null) {
textNode.value = value
}
else {
} else {
tag.replace(projectElement.createChildTag(name, value))
}
}
}
else {
} else {
properties.add(projectElement.createChildTag(name, value))
}
}
@@ -102,7 +102,13 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
return propertiesNode.findFirstSubTag(name)
}
fun addDependency(artifact: MavenId, scope: MavenArtifactScope? = null, classifier: String? = null, optional: Boolean = false, systemPath: String? = null): MavenDomDependency {
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" }
@@ -163,7 +169,7 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
return true
}
fun ensurePluginAfter(plugin: MavenDomPlugin, referencePlugin: MavenDomPlugin): MavenDomPlugin {
private fun ensurePluginAfter(plugin: MavenDomPlugin, referencePlugin: MavenDomPlugin): MavenDomPlugin {
if (!isPluginAfter(plugin, referencePlugin)) {
// rearrange
val referenceElement = referencePlugin.xmlElement!!
@@ -180,8 +186,9 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
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 } }
private 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(executionId.isNotEmpty()) { "executionId shouldn't be empty" }
@@ -200,32 +207,39 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
return execution
}
fun addKotlinExecution(module: Module, plugin: MavenDomPlugin, executionId: String, phase: String, isTest: Boolean, goals: List<String>) {
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, '/') }
.contentEntries
.flatMap { it.sourceFolders.filter { it.isRelatedSourceRoot(isTest) } }
.mapNotNull { it.file }
.mapNotNull { VfsUtilCore.getRelativePath(it, xmlFile.virtualFile.parent, '/') }
executionSourceDirs(execution, sourceDirs)
}
fun isPluginExecutionMissing(plugin: MavenPlugin?, excludedExecutionId: String, goal: String) = plugin == null || plugin.executions.none { it.executionId != excludedExecutionId && goal in it.goals }
fun isPluginExecutionMissing(plugin: MavenPlugin?, excludedExecutionId: String, goal: String) =
plugin == null || plugin.executions.none { it.executionId != excludedExecutionId && goal in it.goals }
fun addJavacExecutions(module: Module, kotlinPlugin: MavenDomPlugin) {
val javacPlugin = ensurePluginAfter(addPlugin(MavenId("org.apache.maven.plugins", "maven-compiler-plugin", null)), kotlinPlugin)
val project: MavenProject =
MavenProjectsManager.getInstance(module.project).findProject(module) ?:
run {
if (ApplicationManager.getApplication().isUnitTestMode) {
LOG.warn("WARNING: Bad project configuration in tests. Javac execution configuration was skipped.")
return
}
error("Can't find maven project for $module")
MavenProjectsManager.getInstance(module.project).findProject(module) ?: run {
if (ApplicationManager.getApplication().isUnitTestMode) {
LOG.warn("WARNING: Bad project configuration in tests. Javac execution configuration was skipped.")
return
}
error("Can't find maven project for $module")
}
val plugin = project.findPlugin("org.apache.maven.plugins", "maven-compiler-plugin")
@@ -252,16 +266,17 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
}
if (domModel.build.plugins.plugins.any {
it.groupId.stringValue == "org.apache.maven.plugins"
&& it.artifactId.stringValue == "maven-compiler-plugin"
&& it.executions.executions.any { it.id.stringValue == executionId && it.phase.stringValue == DefaultPhases.None }
}) {
it.groupId.stringValue == "org.apache.maven.plugins"
&& it.artifactId.stringValue == "maven-compiler-plugin"
&& it.executions.executions.any { it.id.stringValue == executionId && it.phase.stringValue == DefaultPhases.None }
}) {
return false
}
// TODO: getPhase has been added as per https://youtrack.jetbrains.com/issue/IDEA-153582 and available only in latest IDEAs
return plugin.executions.filter { it.executionId == executionId }.all { execution ->
execution::class.java.methods.filter { it.name == "getPhase" && it.parameterTypes.isEmpty() }.all { it.invoke(execution) == DefaultPhases.None }
execution::class.java.methods.filter { it.name == "getPhase" && it.parameterTypes.isEmpty() }
.all { it.invoke(execution) == DefaultPhases.None }
}
}
@@ -272,20 +287,17 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
val defaultDir = if (isTest) "test" else "main"
val singleDirectoryElement = if (isTest) {
domModel.build.testSourceDirectory
}
else {
} 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) {
} else if (sourceDirs.size == 1 && !forceSingleSource) {
singleDirectoryElement.stringValue = sourceDirs.single()
execution.configuration.xmlTag?.findSubTags("sourceDirs")?.forEach { it.deleteCascade() }
}
else {
} else {
val sourceDirsTag = executionConfiguration(execution, "sourceDirs")
val newSourceDirsTag = execution.configuration.createChildTag("sourceDirs")
for (dir in sourceDirs) {
@@ -297,13 +309,13 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
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()
.getChildrenOfType<XmlTag>().firstOrNull { it.localName == "sourceDirs" }
?.getChildrenOfType<XmlTag>()
?.map { it.getChildrenOfType<XmlText>().joinToString("") { it.text } }
?: emptyList()
}
fun executionConfiguration(execution: MavenDomPluginExecution, name: String): XmlTag {
private fun executionConfiguration(execution: MavenDomPluginExecution, name: String): XmlTag {
val configurationTag = execution.configuration.ensureTagExists()!!
val existingTag = configurationTag.findSubTags(name).firstOrNull()
@@ -320,39 +332,70 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
val existingTag = configurationTag.findFirstSubTag(optionName)
if (existingTag != null) {
existingTag.value.text = optionValue
}
else {
} else {
configurationTag.add(configurationTag.createChildTag(optionName, optionValue))
}
return configurationTag
}
fun addPluginRepository(id: String, name: String, url: String, snapshots: Boolean = false, releases: Boolean = true): MavenDomRepository {
private 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() })
return addRepository(
id,
name,
url,
snapshots,
releases,
{ domModel.pluginRepositories.pluginRepositories },
{ domModel.pluginRepositories.addPluginRepository() })
}
fun addPluginRepository(description: RepositoryDescription) {
addPluginRepository(description.id, description.name, description.url, description.isSnapshot, true)
}
fun addLibraryRepository(id: String, name: String, url: String, snapshots: Boolean = false, releases: Boolean = true): MavenDomRepository {
private 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() })
return addRepository(
id,
name,
url,
snapshots,
releases,
{ domModel.repositories.repositories },
{ domModel.repositories.addRepository() })
}
fun addLibraryRepository(description: RepositoryDescription) {
addLibraryRepository(description.id, description.name, description.url, description.isSnapshot, true)
}
private fun addRepository(id: String, name: String, url: String, snapshots: Boolean, releases: Boolean, existing: () -> List<MavenDomRepository>, create: () -> MavenDomRepository): MavenDomRepository {
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()
existing().firstOrNull { it.id.stringValue == id } ?: existing().firstOrNull { it.url.stringValue == url } ?: create()
if (repository.id.isEmpty()) {
repository.id.stringValue = id
@@ -371,42 +414,37 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
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) }
domModel.dependencies.dependencies.filter { it.matches(artifact, scope) }
fun ensureBuild(): XmlTag = ensureElement(projectElement, "build")
private 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 ensureDependencies(): XmlTag = ensureElement(projectElement, "dependencies")
private fun ensurePluginRepositories(): XmlTag = ensureElement(projectElement, "pluginRepositories")
private fun ensureRepositories(): XmlTag = ensureElement(projectElement, "repositories")
private fun MavenDomPlugin.isKotlinMavenPlugin() = groupId.stringValue == KotlinMavenConfigurator.GROUP_ID
&& artifactId.stringValue == KotlinMavenConfigurator.MAVEN_PLUGIN_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")
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)
(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 MavenId.withoutJDKSpecificSuffix() = MavenId(
groupId,
artifactId?.substringBeforeLast("-jre")?.substringBeforeLast("-jdk"),
null)
groupId,
artifactId?.substringBeforeLast("-jre")?.substringBeforeLast("-jdk"),
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() {
private tailrec fun XmlTag.deleteCascade() {
val oldParent = this.parentTag
delete()
@@ -451,12 +489,12 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
private fun insertEmptyLines(node: XmlTag) {
node.prevSibling?.let { before ->
if (!(before.hasEmptyLine() || before.lastChild?.hasEmptyLine() ?: false)) {
if (!(before.hasEmptyLine() || before.lastChild?.hasEmptyLine() == true)) {
node.parent.addBefore(createEmptyLine(), node)
}
}
node.nextSibling?.let { after ->
if (!(after.hasEmptyLine() || after.firstChild?.hasEmptyLine() ?: false)) {
if (!(after.hasEmptyLine() || after.firstChild?.hasEmptyLine() == true)) {
node.parent.addAfter(createEmptyLine(), node)
}
}
@@ -481,45 +519,47 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
@Suppress("Unused")
object DefaultPhases {
val None = "none"
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"
const val None = "none"
const val Validate = "validate"
const val Initialize = "initialize"
const val GenerateSources = "generate-sources"
const val ProcessSources = "process-sources"
const val GenerateResources = "generate-resources"
const val ProcessResources = "process-resources"
const val Compile = "compile"
const val ProcessClasses = "process-classes"
const val GenerateTestSources = "generate-test-sources"
const val ProcessTestSources = "process-test-sources"
const val GenerateTestResources = "generate-test-resources"
const val ProcessTestResources = "process-test-resources"
const val TestCompile = "test-compile"
const val ProcessTestClasses = "process-test-classes"
const val Test = "test"
const val PreparePackage = "prepare-package"
const val Package = "package"
const val PreIntegrationTest = "pre-integration-test"
const val IntegrationTest = "integration-test"
const val PostIntegrationTest = "post-integration-test"
const val Verify = "verify"
const val Install = "install"
const val Deploy = "deploy"
}
object KotlinGoals {
val Compile = "compile"
val TestCompile = "test-compile"
val Js = "js"
val TestJs = "test-js"
val MetaData = "metadata"
const val Compile = "compile"
const val TestCompile = "test-compile"
const val Js = "js"
const val TestJs = "test-js"
const val MetaData = "metadata"
}
companion object {
private val LOG = Logger.getInstance(PomFile::class.java)
fun forFileOrNull(xmlFile: XmlFile): PomFile? = MavenDomUtil.getMavenDomProjectModel(xmlFile.project, xmlFile.virtualFile)?.let { PomFile(xmlFile, it) }
fun forFileOrNull(xmlFile: XmlFile): PomFile? =
MavenDomUtil.getMavenDomProjectModel(xmlFile.project, xmlFile.virtualFile)?.let { PomFile(xmlFile, it) }
@Suppress("DeprecatedCallableAddReplaceWith")
@Deprecated("We shouldn't use phase but additional compiler configuration in most cases")
fun getPhase(hasJavaFiles: Boolean, isTest: Boolean) = when {
hasJavaFiles -> when {
@@ -577,18 +617,22 @@ class PomFile private constructor(val xmlFile: XmlFile, val domModel: MavenDomPr
<profiles/>
""".lines()
.map { it.trim().removePrefix("<").removeSuffix("/>").trim() }
.filter(String::isNotEmpty)
.toCollection(LinkedHashSet())
.map { it.trim().removePrefix("<").removeSuffix("/>").trim() }
.filter(String::isNotEmpty)
.toCollection(LinkedHashSet())
val recommendedOrderAsList = recommendedElementsOrder.toList()
}
}
fun PomFile.changeLanguageVersion(languageVersion: String?, apiVersion: String?): PsiElement? {
val kotlinPlugin = findPlugin(MavenId(KotlinMavenConfigurator.GROUP_ID,
KotlinMavenConfigurator.MAVEN_PLUGIN_ID,
null)) ?: return null
val kotlinPlugin = findPlugin(
MavenId(
KotlinMavenConfigurator.GROUP_ID,
KotlinMavenConfigurator.MAVEN_PLUGIN_ID,
null
)
) ?: return null
val languageElement = languageVersion?.let {
changeConfigurationOrProperty(kotlinPlugin, "languageVersion", "kotlin.compiler.languageVersion", it)
}
@@ -598,9 +642,11 @@ fun PomFile.changeLanguageVersion(languageVersion: String?, apiVersion: String?)
return languageElement ?: apiElement
}
private fun PomFile.changeConfigurationOrProperty(kotlinPlugin: MavenDomPlugin,
configurationTagName: String,
propertyName: String, value: String): XmlTag? {
private fun PomFile.changeConfigurationOrProperty(
kotlinPlugin: MavenDomPlugin,
configurationTagName: String,
propertyName: String, value: String
): XmlTag? {
val configuration = kotlinPlugin.configuration
if (configuration.exists()) {
val subTag = configuration.xmlTag.findFirstSubTag(configurationTagName)
@@ -623,8 +669,12 @@ private fun PomFile.changeConfigurationOrProperty(kotlinPlugin: MavenDomPlugin,
}
fun PomFile.changeCoroutineConfiguration(value: String): PsiElement? {
val kotlinPlugin = findPlugin(MavenId(KotlinMavenConfigurator.GROUP_ID,
KotlinMavenConfigurator.MAVEN_PLUGIN_ID,
null)) ?: return null
val kotlinPlugin = findPlugin(
MavenId(
KotlinMavenConfigurator.GROUP_ID,
KotlinMavenConfigurator.MAVEN_PLUGIN_ID,
null
)
) ?: return null
return changeConfigurationOrProperty(kotlinPlugin, "experimentalCoroutines", "kotlin.compiler.experimental.coroutines", value)
}
@@ -110,7 +110,11 @@ class MavenPluginSourcesMoveToBuild : PsiElementBaseIntentionAction() {
}
}
private fun tryInvoke(project: Project, element: PsiElement, block: (pom: PomFile, dir: String, execution: MavenDomPluginExecution, build: MavenDomBuild) -> Unit = { _, _, _, _ -> }): Boolean {
private fun tryInvoke(
project: Project,
element: PsiElement,
block: (pom: PomFile, dir: String, execution: MavenDomPluginExecution, build: MavenDomBuild) -> Unit = { _, _, _, _ -> }
): Boolean {
val file = element.containingFile
if (file == null || !MavenDomUtil.isMavenFile(file) || (element !is XmlElement && element.parent !is XmlElement)) {
@@ -122,9 +126,9 @@ class MavenPluginSourcesMoveToBuild : PsiElementBaseIntentionAction() {
val execution = domElement.getParentOfType(MavenDomPluginExecution::class.java, false) ?: return false
tag.parentsWithSelf
.takeWhile { it != execution.xmlElement }
.filterIsInstance<XmlTag>()
.firstOrNull { it.localName == "sourceDirs" } ?: return false
.takeWhile { it != execution.xmlElement }
.filterIsInstance<XmlTag>()
.firstOrNull { it.localName == "sourceDirs" } ?: return false
val pom = PomFile.forFileOrNull(element.containingFile as XmlFile) ?: return false
val sourceDirsToMove = pom.executionSourceDirs(execution)
@@ -137,12 +141,12 @@ class MavenPluginSourcesMoveToBuild : PsiElementBaseIntentionAction() {
var couldMove = 0
if (shouldMoveCompileSourceRoot(execution)) {
if (!build.sourceDirectory.exists() || build.sourceDirectory.stringValue == sourceDirsToMove.single()) {
couldMove ++
couldMove++
}
}
if (shouldMoveTestSourceRoot(execution)) {
if (!build.testSourceDirectory.exists() || build.testSourceDirectory.stringValue == sourceDirsToMove.single()) {
couldMove ++
couldMove++
}
}
@@ -158,5 +162,5 @@ class MavenPluginSourcesMoveToBuild : PsiElementBaseIntentionAction() {
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 }
execution.goals.goals.any { it.stringValue == PomFile.KotlinGoals.TestCompile || it.stringValue == PomFile.KotlinGoals.TestJs }
}
@@ -33,11 +33,15 @@ import org.jetbrains.kotlin.idea.maven.configuration.KotlinMavenConfigurator
import org.jetbrains.kotlin.idea.versions.MAVEN_STDLIB_ID
import org.jetbrains.kotlin.psi.psiUtil.endOffset
class GenerateMavenCompileExecutionAction : PomFileActionBase(KotlinMavenExecutionProvider(PomFile.KotlinGoals.Compile, PomFile.DefaultPhases.Compile))
class GenerateMavenTestCompileExecutionAction : PomFileActionBase(KotlinMavenExecutionProvider(PomFile.KotlinGoals.TestCompile, PomFile.DefaultPhases.TestCompile))
class GenerateMavenCompileExecutionAction :
PomFileActionBase(KotlinMavenExecutionProvider(PomFile.KotlinGoals.Compile, PomFile.DefaultPhases.Compile))
class GenerateMavenTestCompileExecutionAction :
PomFileActionBase(KotlinMavenExecutionProvider(PomFile.KotlinGoals.TestCompile, PomFile.DefaultPhases.TestCompile))
class GenerateMavenPluginAction : PomFileActionBase(KotlinMavenPluginProvider())
private val DefaultKotlinVersion = "\${kotlin.version}"
private const val DefaultKotlinVersion = "\${kotlin.version}"
open class PomFileActionBase(generateProvider: AbstractDomGenerateProvider<*>) : GenerateDomElementAction(generateProvider) {
override fun isValidForFile(project: Project, editor: Editor, file: PsiFile): Boolean {
@@ -47,7 +51,8 @@ open class PomFileActionBase(generateProvider: AbstractDomGenerateProvider<*>) :
override fun startInWriteAction() = true
}
private class KotlinMavenPluginProvider : AbstractDomGenerateProvider<MavenDomPlugin>("kotlin-maven-plugin-provider", MavenDomPlugin::class.java) {
private class KotlinMavenPluginProvider :
AbstractDomGenerateProvider<MavenDomPlugin>("kotlin-maven-plugin-provider", MavenDomPlugin::class.java) {
override fun generate(parent: DomElement?, editor: Editor?): MavenDomPlugin? {
if (parent !is MavenDomProjectModel) {
@@ -82,7 +87,8 @@ private class KotlinMavenPluginProvider : AbstractDomGenerateProvider<MavenDomPl
}
}
private class KotlinMavenExecutionProvider(val goal: String, val phase: String) : AbstractDomGenerateProvider<MavenDomPlugin>("kotlin-maven-execution-provider", MavenDomPlugin::class.java) {
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) {
@@ -99,7 +105,7 @@ private class KotlinMavenExecutionProvider(val goal: String, val phase: String)
return parent
}
override fun getElementToNavigate(t: MavenDomPlugin?) = null
override fun getElementToNavigate(t: MavenDomPlugin?): DomElement? = null
override fun getParentDomElement(project: Project?, editor: Editor?, file: PsiFile?): DomElement? {
if (project == null || editor == null || file == null) {
@@ -112,8 +118,8 @@ private class KotlinMavenExecutionProvider(val goal: String, val phase: String)
override fun isAvailableForElement(contextElement: DomElement): Boolean {
val plugin = contextElement.findPlugin()
return plugin != null
&& plugin.isKotlinMavenPlugin()
&& plugin.executions.executions.none { it.goals.goals.any { it.value == goal } }
&& plugin.isKotlinMavenPlugin()
&& plugin.executions.executions.none { it.goals.goals.any { it.value == goal } }
}
}
@@ -129,11 +135,14 @@ 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 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
&& artifactId.stringValue == KotlinMavenConfigurator.MAVEN_PLUGIN_ID
private fun MavenDomDependency.isKotlinStdlib() = groupId.stringValue == KotlinMavenConfigurator.GROUP_ID
&& artifactId.stringValue == MAVEN_STDLIB_ID
&& artifactId.stringValue == MAVEN_STDLIB_ID
@@ -29,16 +29,21 @@ import org.jetbrains.kotlin.idea.versions.getStdlibArtifactId
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
class KotlinJavaMavenConfigurator : KotlinMavenConfigurator(KotlinJavaMavenConfigurator.TEST_LIB_ID, false, KotlinJavaMavenConfigurator.NAME, KotlinJavaMavenConfigurator.PRESENTABLE_TEXT) {
class KotlinJavaMavenConfigurator : KotlinMavenConfigurator(
KotlinJavaMavenConfigurator.TEST_LIB_ID,
false,
KotlinJavaMavenConfigurator.NAME,
KotlinJavaMavenConfigurator.PRESENTABLE_TEXT
) {
override fun isKotlinModule(module: Module) =
hasKotlinJvmRuntimeInScope(module)
hasKotlinJvmRuntimeInScope(module)
override fun isRelevantGoal(goalName: String) =
goalName == PomFile.KotlinGoals.Compile
goalName == PomFile.KotlinGoals.Compile
override fun getStdlibArtifactId(module: Module, version: String): String =
getStdlibArtifactId(ModuleRootManager.getInstance(module).sdk, version)
getStdlibArtifactId(ModuleRootManager.getInstance(module).sdk, version)
override fun createExecutions(pomFile: PomFile, kotlinPlugin: MavenDomPlugin, module: Module) {
createExecution(pomFile, kotlinPlugin, PomFile.DefaultPhases.Compile, PomFile.KotlinGoals.Compile, module, false)
@@ -66,8 +71,8 @@ class KotlinJavaMavenConfigurator : KotlinMavenConfigurator(KotlinJavaMavenConfi
get() = JvmPlatform
companion object {
private val NAME = "maven"
val TEST_LIB_ID = "kotlin-test"
private val PRESENTABLE_TEXT = "Maven"
private const val NAME = "maven"
const val TEST_LIB_ID = "kotlin-test"
private const val PRESENTABLE_TEXT = "Maven"
}
}
@@ -24,7 +24,8 @@ import org.jetbrains.kotlin.idea.versions.MAVEN_JS_STDLIB_ID
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform
class KotlinJavascriptMavenConfigurator : KotlinMavenConfigurator(null, false, KotlinJavascriptMavenConfigurator.NAME, KotlinJavascriptMavenConfigurator.PRESENTABLE_TEXT) {
class KotlinJavascriptMavenConfigurator :
KotlinMavenConfigurator(null, false, KotlinJavascriptMavenConfigurator.NAME, KotlinJavascriptMavenConfigurator.PRESENTABLE_TEXT) {
override fun getStdlibArtifactId(module: Module, version: String) = MAVEN_JS_STDLIB_ID
@@ -47,7 +48,7 @@ class KotlinJavascriptMavenConfigurator : KotlinMavenConfigurator(null, false, K
override fun getMinimumSupportedVersion() = "1.1.0"
companion object {
private val NAME = "js maven"
private val PRESENTABLE_TEXT = "Maven (JavaScript)"
private const val NAME = "js maven"
private const val PRESENTABLE_TEXT = "Maven (JavaScript)"
}
}
@@ -41,10 +41,12 @@ import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
abstract class KotlinMavenConfigurator
protected constructor(private val testArtifactId: String?,
private val addJunit: Boolean,
override val name: String,
override val presentableText: String) : KotlinProjectConfigurator {
protected constructor(
private val testArtifactId: String?,
private val addJunit: Boolean,
override val name: String,
override val presentableText: String
) : KotlinProjectConfigurator {
override fun getStatus(moduleSourceRootGroup: ModuleSourceRootGroup): ConfigureKotlinStatus {
val module = moduleSourceRootGroup.baseModule
@@ -77,8 +79,8 @@ abstract class KotlinMavenConfigurator
val mavenProject = mavenProjectsManager.findProject(module) ?: return ConfigureKotlinStatus.BROKEN
val kotlinPluginId = kotlinPluginId(null)
val kotlinPlugin = mavenProject.plugins.find { it.mavenId.equals(kotlinPluginId.groupId, kotlinPluginId.artifactId)}
?: return ConfigureKotlinStatus.CAN_BE_CONFIGURED
val kotlinPlugin = mavenProject.plugins.find { it.mavenId.equals(kotlinPluginId.groupId, kotlinPluginId.artifactId) }
?: return ConfigureKotlinStatus.CAN_BE_CONFIGURED
if (kotlinPlugin.executions.any { it.goals.any(this::isRelevantGoal) }) {
return ConfigureKotlinStatus.CONFIGURED
@@ -108,8 +110,7 @@ abstract class KotlinMavenConfigurator
if (file != null && canConfigureFile(file)) {
configureModule(module, file, dialog.kotlinVersion, collector)
OpenFileAction.openFile(file.virtualFile, project)
}
else {
} else {
showErrorMessage(project, "Cannot find pom.xml for module " + module.name)
}
}
@@ -126,13 +127,13 @@ abstract class KotlinMavenConfigurator
protected abstract fun getStdlibArtifactId(module: Module, version: String): String
open fun configureModule(module: Module, file: PsiFile, version: String, collector: NotificationMessageCollector): Boolean =
changePomFile(module, file, version, collector)
changePomFile(module, file, version, collector)
private fun changePomFile(
module: Module,
file: PsiFile,
version: String,
collector: NotificationMessageCollector
module: Module,
file: PsiFile,
version: String,
collector: NotificationMessageCollector
): Boolean {
val virtualFile = file.virtualFile ?: error("Virtual file should exists for psi file " + file.name)
val domModel = MavenDomUtil.getMavenDomProjectModel(module.project, virtualFile)
@@ -144,7 +145,13 @@ abstract class KotlinMavenConfigurator
val pom = PomFile.forFileOrNull(file as XmlFile) ?: return false
pom.addProperty(KOTLIN_VERSION_PROPERTY, version)
pom.addDependency(MavenId(GROUP_ID, getStdlibArtifactId(module, version), "\${$KOTLIN_VERSION_PROPERTY}"), MavenArtifactScope.COMPILE, null, false, null)
pom.addDependency(
MavenId(GROUP_ID, getStdlibArtifactId(module, version), "\${$KOTLIN_VERSION_PROPERTY}"),
MavenArtifactScope.COMPILE,
null,
false,
null
)
if (testArtifactId != null) {
pom.addDependency(MavenId(GROUP_ID, testArtifactId, "\${$KOTLIN_VERSION_PROPERTY}"), MavenArtifactScope.TEST, null, false, null)
}
@@ -174,13 +181,13 @@ abstract class KotlinMavenConfigurator
}
protected fun createExecution(
pomFile: PomFile,
kotlinPlugin: MavenDomPlugin,
executionId: String,
goalName: String,
module: Module,
isTest: Boolean) {
pomFile: PomFile,
kotlinPlugin: MavenDomPlugin,
executionId: String,
goalName: String,
module: Module,
isTest: Boolean
) {
pomFile.addKotlinExecution(module, kotlinPlugin, executionId, PomFile.getPhase(false, isTest), isTest, listOf(goalName))
if (hasJavaFiles(module)) {
@@ -189,18 +196,19 @@ abstract class KotlinMavenConfigurator
}
override fun updateLanguageVersion(
module: Module,
languageVersion: String?,
apiVersion: String?,
requiredStdlibVersion: ApiVersion,
forTests: Boolean
module: Module,
languageVersion: String?,
apiVersion: String?,
requiredStdlibVersion: ApiVersion,
forTests: Boolean
) {
fun doUpdateMavenLanguageVersion(): PsiElement? {
val psi = KotlinMavenConfigurator.findModulePomFile(module) as? XmlFile ?: return null
val pom = PomFile.forFileOrNull(psi) ?: return null
return pom.changeLanguageVersion(
languageVersion,
apiVersion)
languageVersion,
apiVersion
)
}
val runtimeUpdateRequired = getRuntimeLibraryVersion(module)?.let { ApiVersion.parse(it) }?.let { runtimeVersion ->
@@ -208,39 +216,49 @@ abstract class KotlinMavenConfigurator
} ?: false
if (runtimeUpdateRequired) {
Messages.showErrorDialog(module.project,
"This language feature requires version $requiredStdlibVersion or later of the Kotlin runtime library. " +
"Please update the version in your build script.",
"Update Language Version")
Messages.showErrorDialog(
module.project,
"This language feature requires version $requiredStdlibVersion or later of the Kotlin runtime library. " +
"Please update the version in your build script.",
"Update Language Version"
)
return
}
val element = doUpdateMavenLanguageVersion()
if (element == null) {
Messages.showErrorDialog(module.project,
"Failed to update.pom.xml. Please update the file manually.",
"Update Language Version")
}
else {
Messages.showErrorDialog(
module.project,
"Failed to update.pom.xml. Please update the file manually.",
"Update Language Version"
)
} else {
OpenFileDescriptor(module.project, element.containingFile.virtualFile, element.textRange.startOffset).navigate(true)
}
}
override fun addLibraryDependency(module: Module, element: PsiElement, library: ExternalLibraryDescriptor, libraryJarDescriptors: List<LibraryJarDescriptor>) {
override fun addLibraryDependency(
module: Module,
element: PsiElement,
library: ExternalLibraryDescriptor,
libraryJarDescriptors: List<LibraryJarDescriptor>
) {
val scope = OrderEntryFix.suggestScopeByLocation(module, element)
JavaProjectModelModificationService.getInstance(module.project).addDependency(module, library, scope)
}
override fun changeCoroutineConfiguration(module: Module, state: LanguageFeature.State) {
val runtimeUpdateRequired = state != LanguageFeature.State.DISABLED &&
(getRuntimeLibraryVersion(module)?.startsWith("1.0") ?: false)
(getRuntimeLibraryVersion(module)?.startsWith("1.0") ?: false)
val messageTitle = ChangeCoroutineSupportFix.getFixText(state)
if (runtimeUpdateRequired) {
Messages.showErrorDialog(module.project,
"Coroutines support requires version 1.1 or later of the Kotlin runtime library. " +
"Please update the version in your build script.",
messageTitle)
Messages.showErrorDialog(
module.project,
"Coroutines support requires version 1.1 or later of the Kotlin runtime library. " +
"Please update the version in your build script.",
messageTitle
)
return
}
@@ -261,19 +279,19 @@ abstract class KotlinMavenConfigurator
val element = doChangeMavenCoroutineConfiguration()
if (element == null) {
Messages.showErrorDialog(module.project,
"Failed to update.pom.xml. Please update the file manually.",
messageTitle)
Messages.showErrorDialog(
module.project,
"Failed to update.pom.xml. Please update the file manually.",
messageTitle
)
}
return element
}
companion object {
val NAME = "maven"
val GROUP_ID = "org.jetbrains.kotlin"
val MAVEN_PLUGIN_ID = "kotlin-maven-plugin"
private val KOTLIN_VERSION_PROPERTY = "kotlin.version"
const val GROUP_ID = "org.jetbrains.kotlin"
const val MAVEN_PLUGIN_ID = "kotlin-maven-plugin"
private const val KOTLIN_VERSION_PROPERTY = "kotlin.version"
private fun hasJavaFiles(module: Module): Boolean {
return !FileTypeIndex.getFiles(JavaFileType.INSTANCE, GlobalSearchScope.moduleScope(module)).isEmpty()
@@ -296,11 +314,13 @@ abstract class KotlinMavenConfigurator
}
private fun showErrorMessage(project: Project, message: String?) {
Messages.showErrorDialog(project,
"<html>Couldn't configure kotlin-maven plugin automatically.<br/>" +
(if (message != null) "$message</br>" else "") +
"See manual installation instructions <a href=\"http://confluence.jetbrains.com/display/Kotlin/Kotlin+Build+Tools#KotlinBuildTools-Maven\">here</a>.</html>",
"Configure Kotlin-Maven Plugin")
Messages.showErrorDialog(
project,
"<html>Couldn't configure kotlin-maven plugin automatically.<br/>" +
(if (message != null) "$message</br>" else "") +
"See manual installation instructions <a href=\"http://confluence.jetbrains.com/display/Kotlin/Kotlin+Build+Tools#KotlinBuildTools-Maven\">here</a>.</html>",
"Configure Kotlin-Maven Plugin"
)
}
}
}
@@ -41,23 +41,26 @@ class DeprecatedMavenDependencyInspection : DomElementsInspection<MavenDomProjec
for (libInfo in DEPRECATED_LIBRARIES_INFORMATION) {
pomFile.findDependencies(MavenId(libInfo.old.groupId, libInfo.old.name, null))
.filter { it.version?.stringValue != null }
.filter {
val libVersion = project.findDependencies(libInfo.old.groupId, libInfo.old.name).map { it.version }.distinct().singleOrNull()
libVersion != null && VersionComparatorUtil.COMPARATOR.compare(libVersion, libInfo.outdatedAfterVersion) >= 0
}
.forEach { dependency ->
val xmlElement = dependency.artifactId.xmlElement
if (xmlElement != null) {
val fix = ReplaceStringInDocumentFix(xmlElement, libInfo.old.name, libInfo.new.name)
.filter { it.version?.stringValue != null }
.filter {
val libVersion =
project.findDependencies(libInfo.old.groupId, libInfo.old.name).map { it.version }.distinct().singleOrNull()
libVersion != null && VersionComparatorUtil.COMPARATOR.compare(libVersion, libInfo.outdatedAfterVersion) >= 0
}
.forEach { dependency ->
val xmlElement = dependency.artifactId.xmlElement
if (xmlElement != null) {
val fix = ReplaceStringInDocumentFix(xmlElement, libInfo.old.name, libInfo.new.name)
holder.createProblem(dependency.artifactId,
ProblemHighlightType.LIKE_DEPRECATED,
libInfo.message,
null,
fix)
}
holder.createProblem(
dependency.artifactId,
ProblemHighlightType.LIKE_DEPRECATED,
libInfo.message,
null,
fix
)
}
}
}
}
}
@@ -28,7 +28,8 @@ import org.jetbrains.kotlin.idea.inspections.PluginVersionDependentInspection
import org.jetbrains.kotlin.idea.maven.PomFile
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
class DifferentKotlinMavenVersionInspection : DomElementsInspection<MavenDomProjectModel>(MavenDomProjectModel::class.java), PluginVersionDependentInspection {
class DifferentKotlinMavenVersionInspection : DomElementsInspection<MavenDomProjectModel>(MavenDomProjectModel::class.java),
PluginVersionDependentInspection {
private val idePluginVersion by lazy { bundledRuntimeVersion() }
override var testVersionMessage: String? = null
@@ -53,8 +54,11 @@ class DifferentKotlinMavenVersionInspection : DomElementsInspection<MavenDomProj
}
private fun createProblem(holder: DomElementAnnotationHolder, plugin: MavenDomPlugin) {
holder.createProblem(plugin.version,
HighlightSeverity.WARNING,
"Kotlin version that is used for building with Maven (${plugin.version.stringValue}) differs from the one bundled into the IDE plugin (${testVersionMessage ?: idePluginVersion})")
holder.createProblem(
plugin.version,
HighlightSeverity.WARNING,
"Kotlin version that is used for building with Maven (${plugin.version.stringValue}) differs from the one bundled into the IDE plugin (${testVersionMessage
?: idePluginVersion})"
)
}
}
@@ -57,11 +57,12 @@ class DifferentMavenStdlibVersionInspection : DomElementsInspection<MavenDomProj
createFixes(project, plugin.version, stdlibVersion + version)
} ?: emptyList()
holder.createProblem(plugin.version,
HighlightSeverity.WARNING,
"Plugin version (${plugin.version}) is not the same as library version (${stdlibVersion.joinToString(",", "", "")})",
*fixes.toTypedArray()
)
holder.createProblem(
plugin.version,
HighlightSeverity.WARNING,
"Plugin version (${plugin.version}) is not the same as library version (${stdlibVersion.joinToString(",", "", "")})",
*fixes.toTypedArray()
)
}
pomFile.findDependencies(MavenId(KotlinMavenConfigurator.GROUP_ID, MAVEN_STDLIB_ID, null))
@@ -71,10 +72,12 @@ class DifferentMavenStdlibVersionInspection : DomElementsInspection<MavenDomProj
createFixes(project, dependency.version, listOf(version, pluginVersion))
} ?: emptyList()
holder.createProblem(dependency.version,
HighlightSeverity.WARNING,
"Plugin version ($pluginVersion) is not the same as library version (${dependency.version})",
*fixes.toTypedArray())
holder.createProblem(
dependency.version,
HighlightSeverity.WARNING,
"Plugin version ($pluginVersion) is not the same as library version (${dependency.version})",
*fixes.toTypedArray()
)
}
}
@@ -87,11 +90,14 @@ class DifferentMavenStdlibVersionInspection : DomElementsInspection<MavenDomProj
val properties = project.properties.entries.filter { it.value == bestVersion }.map { "\${${it.key}}" }
return properties.map { SetVersionQuickFix(versionElement, it, bestVersion) } +
SetVersionQuickFix(versionElement, bestVersion, null)
SetVersionQuickFix(versionElement, bestVersion, null)
}
private class SetVersionQuickFix(val versionElement: GenericDomValue<*>, val newVersion: String, val versionResolved: String?) : LocalQuickFix {
override fun getName() = if (versionResolved == null) "Change version to $newVersion" else "Change version to $newVersion ($versionResolved)"
private class SetVersionQuickFix(val versionElement: GenericDomValue<*>, val newVersion: String, val versionResolved: String?) :
LocalQuickFix {
override fun getName() =
if (versionResolved == null) "Change version to $newVersion" else "Change version to $newVersion ($versionResolved)"
override fun getFamilyName() = "Change version"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
@@ -59,8 +59,8 @@ class KotlinMavenPluginPhaseInspection : DomElementsInspection<MavenDomProjectMo
// all executions including inherited
val executions = mavenProject.plugins
.filter { it.isKotlinMavenPlugin() }
.flatMap { it.executions }
.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
@@ -71,45 +71,52 @@ class KotlinMavenPluginPhaseInspection : DomElementsInspection<MavenDomProjectMo
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))
} 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 {
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 ->
val javacPlugin = mavenProject.findPlugin("org.apache.maven.plugins", "maven-compiler-plugin")
val existingJavac = pom.domModel.build.plugins.plugins.firstOrNull {
it.groupId.stringValue == "org.apache.maven.plugins" &&
it.artifactId.stringValue == "maven-compiler-plugin"
}
pom.findExecutions(kotlinPlugin, PomFile.KotlinGoals.Compile).notAtPhase(PomFile.DefaultPhases.ProcessSources)
.forEach { badExecution ->
val javacPlugin = mavenProject.findPlugin("org.apache.maven.plugins", "maven-compiler-plugin")
val existingJavac = pom.domModel.build.plugins.plugins.firstOrNull {
it.groupId.stringValue == "org.apache.maven.plugins" &&
it.artifactId.stringValue == "maven-compiler-plugin"
}
if (existingJavac == null
|| !pom.isPluginAfter(existingJavac, kotlinPlugin)
|| pom.isExecutionEnabled(javacPlugin, "default-compile")
|| pom.isExecutionEnabled(javacPlugin, "default-testCompile")
|| pom.isPluginExecutionMissing(javacPlugin, "default-compile", "compile")
|| pom.isPluginExecutionMissing(javacPlugin, "default-testCompile", "testCompile")) {
if (existingJavac == null
|| !pom.isPluginAfter(existingJavac, kotlinPlugin)
|| pom.isExecutionEnabled(javacPlugin, "default-compile")
|| pom.isExecutionEnabled(javacPlugin, "default-testCompile")
|| pom.isPluginExecutionMissing(javacPlugin, "default-compile", "compile")
|| pom.isPluginExecutionMissing(javacPlugin, "default-testCompile", "testCompile")) {
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),
AddJavaExecutionsLocalFix(module, domFileElement.file, kotlinPlugin))
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),
AddJavaExecutionsLocalFix(module, domFileElement.file, kotlinPlugin)
)
}
}
}
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")
holder.createProblem(
badExecution.goals.goals.first { it.isJsGoal() }.createStableCopy(),
HighlightSeverity.WARNING,
"JavaScript goal configured for module with Java files"
)
}
}
@@ -117,16 +124,20 @@ class KotlinMavenPluginPhaseInspection : DomElementsInspection<MavenDomProjectMo
val jsDependencies = mavenProject.findDependencies(KotlinMavenConfigurator.GROUP_ID, MAVEN_JS_STDLIB_ID)
if (hasJvmExecution && stdlibDependencies.isEmpty()) {
holder.createProblem(kotlinPlugin.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"Kotlin JVM compiler configured but no $MAVEN_STDLIB_ID dependency",
FixAddStdlibLocalFix(domFileElement.file, MAVEN_STDLIB_ID, kotlinPlugin.version.rawText))
holder.createProblem(
kotlinPlugin.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"Kotlin JVM compiler configured but no $MAVEN_STDLIB_ID dependency",
FixAddStdlibLocalFix(domFileElement.file, MAVEN_STDLIB_ID, kotlinPlugin.version.rawText)
)
}
if (hasJsExecution && jsDependencies.isEmpty()) {
holder.createProblem(kotlinPlugin.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"Kotlin JavaScript compiler configured but no $MAVEN_JS_STDLIB_ID dependency",
FixAddStdlibLocalFix(domFileElement.file, MAVEN_JS_STDLIB_ID, kotlinPlugin.version.rawText))
holder.createProblem(
kotlinPlugin.artifactId.createStableCopy(),
HighlightSeverity.WARNING,
"Kotlin JavaScript compiler configured but no $MAVEN_JS_STDLIB_ID dependency",
FixAddStdlibLocalFix(domFileElement.file, MAVEN_JS_STDLIB_ID, kotlinPlugin.version.rawText)
)
}
}
}
@@ -134,40 +145,48 @@ class KotlinMavenPluginPhaseInspection : DomElementsInspection<MavenDomProjectMo
val stdlibDependencies = pom.findDependencies(MavenId(KotlinMavenConfigurator.GROUP_ID, MAVEN_STDLIB_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))
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(KotlinMavenConfigurator.GROUP_ID, MAVEN_JS_STDLIB_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))
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 }
&& 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")
}
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 {
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() = "Create kotlin execution"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
PomFile.forFileOrNull(file)?.addKotlinExecution(module, kotlinPlugin, goal, PomFile.getPhase(module.hasJavaFiles(), false), false, listOf(goal))
PomFile.forFileOrNull(file)
?.addKotlinExecution(module, kotlinPlugin, goal, PomFile.getPhase(module.hasJavaFiles(), false), false, listOf(goal))
}
}
@@ -195,11 +214,13 @@ class KotlinMavenPluginPhaseInspection : DomElementsInspection<MavenDomProjectMo
override fun getFamilyName() = "Add dependency"
override fun applyFix(project: Project, descriptor: ProblemDescriptor) {
PomFile.forFileOrNull(pomFile)?.addDependency(MavenId(KotlinMavenConfigurator.GROUP_ID, id, version), MavenArtifactScope.COMPILE)
PomFile.forFileOrNull(pomFile)
?.addDependency(MavenId(KotlinMavenConfigurator.GROUP_ID, id, version), MavenArtifactScope.COMPILE)
}
}
private class ConfigurePluginExecutionLocalFix(val module: Module, val xmlFile: XmlFile, val goal: String, val version: String?) : LocalQuickFix {
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() = "Create kotlin execution"
@@ -217,7 +238,7 @@ fun Module.hasJavaFiles(): Boolean {
}
private fun MavenPlugin.isKotlinMavenPlugin() = groupId == KotlinMavenConfigurator.GROUP_ID
&& artifactId == KotlinMavenConfigurator.MAVEN_PLUGIN_ID
&& artifactId == KotlinMavenConfigurator.MAVEN_PLUGIN_ID
private fun MavenDomGoal.isJsGoal() = rawText == PomFile.KotlinGoals.Js || rawText == PomFile.KotlinGoals.TestJs
@@ -42,7 +42,7 @@ import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
class KotlinMavenUnresolvedReferenceQuickFixProvider : UnresolvedReferenceQuickFixProvider<KtSimpleNameReference>() {
override fun getReferenceClass(): Class<KtSimpleNameReference> = KtSimpleNameReference::class.java
override fun getReferenceClass(): Class<KtSimpleNameReference> = KtSimpleNameReference::class.java
override fun registerFixes(ref: KtSimpleNameReference, registrar: QuickFixActionRegistrar) {
val module = ModuleUtilCore.findModuleForPsiElement(ref.expression) ?: return
@@ -59,15 +59,14 @@ class KotlinMavenUnresolvedReferenceQuickFixProvider : UnresolvedReferenceQuickF
} else {
importDirective.importedFqName?.asString()
}
}
else {
} else {
val typeReference = expression.getParentOfType<KtTypeReference>(true)
val referenced = typeReference?.text ?: expression.getReferencedName()
expression.containingKtFile
.importDirectives
.firstOrNull { !it.isAllUnder && it.aliasName == referenced || it.importedFqName?.shortName()?.asString() == referenced }
?.let { it.importedFqName?.asString() }
.importDirectives
.firstOrNull { !it.isAllUnder && it.aliasName == referenced || it.importedFqName?.shortName()?.asString() == referenced }
?.let { it.importedFqName?.asString() }
?: referenced
}
@@ -77,12 +76,16 @@ class KotlinMavenUnresolvedReferenceQuickFixProvider : UnresolvedReferenceQuickF
}
}
class AddMavenDependencyQuickFix(val className: String, val smartPsiElementPointer: SmartPsiElementPointer<KtSimpleNameExpression>) : IntentionAction, LowPriorityAction {
class AddMavenDependencyQuickFix(
val className: String,
private val smartPsiElementPointer: SmartPsiElementPointer<KtSimpleNameExpression>
) :
IntentionAction, LowPriorityAction {
override fun getText() = "Add Maven dependency..."
override fun getFamilyName() = text
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
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) {
@@ -45,14 +45,15 @@ class KotlinTestJUnitInspection : DomElementsInspection<MavenDomProjectModel>(Ma
}
val kotlinTestDependencies = domFileElement.rootElement.dependencies
.dependencies.filter { it.groupId.rawText == KotlinMavenConfigurator.GROUP_ID && it.artifactId.rawText == KotlinJavaMavenConfigurator.TEST_LIB_ID }
.dependencies.filter { it.groupId.rawText == KotlinMavenConfigurator.GROUP_ID && it.artifactId.rawText == KotlinJavaMavenConfigurator.TEST_LIB_ID }
kotlinTestDependencies.forEach {
holder.createProblem(it.artifactId,
HighlightSeverity.WEAK_WARNING,
"kotlin-test-junit is better with junit",
ReplaceToKotlinTest(it)
)
holder.createProblem(
it.artifactId,
HighlightSeverity.WEAK_WARNING,
"kotlin-test-junit is better with junit",
ReplaceToKotlinTest(it)
)
}
}
@@ -19,7 +19,6 @@ package org.jetbrains.kotlin.idea.maven
import com.intellij.codeInspection.CommonProblemDescriptor
import com.intellij.codeInspection.ProblemDescriptorBase
import com.intellij.codeInspection.QuickFix
import com.intellij.codeInspection.reference.RefEntity
import com.intellij.ide.highlighter.JavaFileType
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.Result
@@ -60,29 +59,32 @@ abstract class AbstractKotlinMavenInspectionTest : MavenImportingTestCase() {
mkJavaFile()
}
val inspectionClassName = "<!--\\s*inspection:\\s*([\\S]+)\\s-->".toRegex().find(pomText)?.groups?.get(1)?.value ?: KotlinMavenPluginPhaseInspection::class.qualifiedName !!
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 expected = pomText.lines().mapNotNull { matcher.find(it) }
.map { SimplifiedProblemDescription(it.groups[2]!!.value.trim(), it.groups[1]!!.value.trim()) }
val problemElements = runInspection(inspectionClass, myProject).problemElements
val actualProblems = problemElements
.keys()
.filter { it.name == "pom.xml" }
.map { problemElements.get(it) }
.flatMap { it.toList() }
.mapNotNull { it as? ProblemDescriptorBase }
.keys()
.filter { it.name == "pom.xml" }
.map { problemElements.get(it) }
.flatMap { it.toList() }
.mapNotNull { it as? ProblemDescriptorBase }
val actual = actualProblems
.map { SimplifiedProblemDescription(it.descriptionTemplate, it.psiElement.text.replace("\\s+".toRegex(), "")) to it }
.sortedBy { it.first.text }
.map { SimplifiedProblemDescription(it.descriptionTemplate, it.psiElement.text.replace("\\s+".toRegex(), "")) to it }
.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 { _, name -> name.startsWith(filenamePrefix) && name.endsWith(".xml") }.sortedBy { it.name }
val fixFiles =
pomFile.parentFile.listFiles { _, 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}")
@@ -144,7 +146,8 @@ abstract class AbstractKotlinMavenInspectionTest : MavenImportingTestCase() {
}
private fun mkJavaFile() {
val sourceFolder = getContentRoots(myProject.allModules().single().name).single().getSourceFolders(JavaSourceRootType.SOURCE).single()
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.viewProvider.document!!.setText("class Test {}\n")
@@ -24,7 +24,9 @@ import org.junit.Test
import java.io.File
class KotlinMavenArchetypesProviderTest {
private val BASE_PATH = "idea/testData/configuration/"
companion object {
private const val BASE_PATH = "idea/testData/configuration/"
}
@Test
fun extractVersions() {
@@ -38,11 +40,11 @@ class KotlinMavenArchetypesProviderTest {
val versions = KotlinMavenArchetypesProvider("1.0.0-Release-Something-1886", false).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 }
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 }
)
}
@@ -58,10 +60,10 @@ class KotlinMavenArchetypesProviderTest {
val versions = KotlinMavenArchetypesProvider("1.1.0-Next-Release-Something-9999", false).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 }
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.1.2", null, null)
).sortedBy { it.artifactId + "." + it.version },
versions.sortedBy { it.artifactId + "." + it.version }
)
}
@@ -77,12 +79,12 @@ class KotlinMavenArchetypesProviderTest {
val versions = KotlinMavenArchetypesProvider("1.0.0-Release-Something-1886", true).extractVersions(json)
assertEquals(
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.0.1-2", null, null),
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.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 }
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.0.1-2", null, null),
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.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 }
)
}
@@ -98,12 +100,12 @@ class KotlinMavenArchetypesProviderTest {
val versions = KotlinMavenArchetypesProvider("1.9.0-Missing-Release-Something-1886", false).extractVersions(json)
assertEquals(
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.0.1-2", null, null),
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.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 }
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.0.1-2", null, null),
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.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 }
)
}
@@ -119,12 +121,12 @@ class KotlinMavenArchetypesProviderTest {
val versions = KotlinMavenArchetypesProvider("@snapshot@", false).extractVersions(json)
assertEquals(
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.0.1-2", null, null),
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.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 }
listOf(
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.0.1-2", null, null),
MavenArchetype("org.jetbrains.kotlin", "kotlin-archetype-jvm", "1.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 }
)
}
}
File diff suppressed because it is too large Load Diff
@@ -217,14 +217,17 @@ public abstract class MavenImportingTestCase extends MavenTestCase {
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));
assertModuleLibDepPath(lib, JavadocOrderRootType.getInstance(),
javadocPath == null ? null : Collections.singletonList(javadocPath));
}
protected void assertModuleLibDep(String moduleName,
protected void assertModuleLibDep(
String moduleName,
String depName,
List<String> classesPaths,
List<String> sourcePaths,
List<String> javadocPaths) {
List<String> javadocPaths
) {
LibraryOrderEntry lib = getModuleLibDep(moduleName, depName);
assertModuleLibDepPath(lib, OrderRootType.CLASSES, classesPaths);
@@ -255,19 +258,20 @@ public abstract class MavenImportingTestCase extends MavenTestCase {
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;
}
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);
@Override
public Object visitLibraryOrderEntry(LibraryOrderEntry e, Object value) {
actual.add(e.getLibraryName());
return null;
}
}, null);
assertOrderedElementsAreEqual(actual, expectedDeps);
}
@@ -305,7 +309,7 @@ public abstract class MavenImportingTestCase extends MavenTestCase {
for (OrderEntry e : getRootManager(moduleName).getOrderEntries()) {
if (clazz.isInstance(e) && e.getPresentableName().equals(depName)) {
dep = (T)e;
dep = (T) e;
}
}
assertNotNull("Dependency not found: " + depName
@@ -507,8 +511,10 @@ public abstract class MavenImportingTestCase extends MavenTestCase {
downloadArtifacts(myProjectsManager.getProjects(), null);
}
protected MavenArtifactDownloader.DownloadResult downloadArtifacts(Collection<MavenProject> projects,
List<MavenArtifact> artifacts) {
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>();
@@ -67,7 +67,7 @@ public abstract class MavenTestCase extends UsefulTestCase {
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setConnectTimeout(1000);
int responseCode = urlConnection.getResponseCode();
if(responseCode < 400) {
if (responseCode < 400) {
mirrorDiscoverable = true;
}
}
@@ -137,7 +137,6 @@ public abstract class MavenTestCase extends UsefulTestCase {
});
}
});
}
private void ensureTempDirCreated() throws IOException {
@@ -277,7 +276,9 @@ public abstract class MavenTestCase extends UsefulTestCase {
}
protected static String getEnvVar() {
if (SystemInfo.isWindows) return "TEMP";
if (SystemInfo.isWindows) {
return "TEMP";
}
else if (SystemInfo.isLinux) return "HOME";
return "TMPDIR";
}
@@ -409,8 +410,9 @@ public abstract class MavenTestCase extends UsefulTestCase {
return f;
}
@NonNls @Language(value="XML")
public static String createPomXml(@NonNls @Language(value="XML", prefix="<xml>", suffix="</xml>") String xml) {
@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\"" +
@@ -542,6 +544,7 @@ public abstract class MavenTestCase extends UsefulTestCase {
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)));
@@ -641,5 +644,4 @@ public abstract class MavenTestCase extends UsefulTestCase {
return myDelegate.hashCode();
}
}
}
@@ -33,7 +33,8 @@ import kotlin.reflect.KMutableProperty0
class MavenUpdateConfigurationQuickFixTest : MavenImportingTestCase() {
private lateinit var codeInsightTestFixture: CodeInsightTestFixture
fun getTestDataPath() = KotlinTestUtils.getHomeDirectory() + "/idea/idea-maven/testData/languageFeature/" + getTestName(true).substringBefore('_')
private fun getTestDataPath() =
KotlinTestUtils.getHomeDirectory() + "/idea/idea-maven/testData/languageFeature/" + getTestName(true).substringBefore('_')
override fun setUpFixtures() {
myTestFixture = IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(getName()).fixture
@@ -43,31 +44,38 @@ class MavenUpdateConfigurationQuickFixTest : MavenImportingTestCase() {
override fun tearDownFixtures() {
codeInsightTestFixture.tearDown()
@Suppress("UNCHECKED_CAST")
(this::codeInsightTestFixture as KMutableProperty0<CodeInsightTestFixture?>).set(null)
myTestFixture = null
}
@Test fun testUpdateLanguageVersion() {
@Test
fun testUpdateLanguageVersion() {
doTest("Set module language version to 1.1")
}
@Test fun testUpdateLanguageVersionProperty() {
@Test
fun testUpdateLanguageVersionProperty() {
doTest("Set module language version to 1.1")
}
@Test fun testUpdateApiVersion() {
@Test
fun testUpdateApiVersion() {
doTest("Set module API version to 1.1")
}
@Test fun testUpdateLanguageAndApiVersion() {
@Test
fun testUpdateLanguageAndApiVersion() {
doTest("Set module language version to 1.1")
}
@Test fun testEnableCoroutines() {
@Test
fun testEnableCoroutines() {
doTest("Enable coroutine support in the current module")
}
@Test fun testAddKotlinReflect() {
@Test
fun testAddKotlinReflect() {
doTest("Add kotlin-reflect.jar to the classpath")
}
@@ -39,7 +39,13 @@ abstract class AbstractMavenConfigureProjectByChangingFileTest : AbstractConfigu
doTest(pathWithFile, pathWithFile.replace("pom", "pom_after"), KotlinJavascriptMavenConfigurator())
}
override fun runConfigurator(module: Module, file: PsiFile, configurator: KotlinMavenConfigurator, version: String, collector: NotificationMessageCollector) {
override fun runConfigurator(
module: Module,
file: PsiFile,
configurator: KotlinMavenConfigurator,
version: String,
collector: NotificationMessageCollector
) {
WriteCommandAction.runWriteCommandAction(module.project) {
configurator.configureModule(module, file, version, collector)
}