Skip to content

Commit 1890757

Browse files
authored
Merge pull request #109 from wpopielarski/KE-282
Rewrites maven project configurator to use project properties
2 parents 1187c7f + dff53f5 commit 1890757

File tree

9 files changed

+199
-72
lines changed

9 files changed

+199
-72
lines changed

kotlin-eclipse-core/plugin.xml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@
5656
<extension
5757
point="org.jetbrains.kotlin.core.predefinedKotlinCodeStyle">
5858
<codeStyle
59-
class="org.jetbrains.kotlin.idea.formatter.KotlinObsoleteCodeStyle">
59+
class="org.jetbrains.kotlin.idea.formatter.KotlinObsoleteCodeStyle"
60+
nameInBuildsystem="obsolete">
6061
</codeStyle>
6162
<codeStyle
62-
class="org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle">
63+
class="org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle"
64+
nameInBuildsystem="official">
6365
</codeStyle>
6466
</extension>
6567
</plugin>
Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,68 @@
11
package org.jetbrains.kotlin.core.formatting
22

33
import com.intellij.psi.codeStyle.CodeStyleSettings
4-
import org.eclipse.core.internal.registry.ExtensionRegistry
54
import org.eclipse.core.resources.IProject
65
import org.eclipse.core.resources.ProjectScope
6+
import org.jetbrains.kotlin.core.model.EPAttribute
7+
import org.jetbrains.kotlin.core.model.ExecutableExtensionPointDescriptor
78
import org.jetbrains.kotlin.core.model.loadExecutableEP
89
import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties
9-
import org.jetbrains.kotlin.idea.formatter.KotlinObsoleteCodeStyle
10+
import org.jetbrains.kotlin.core.utils.pairOfNotNulls
1011
import org.jetbrains.kotlin.idea.formatter.KotlinPredefinedCodeStyle
11-
import org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle
1212
import java.util.concurrent.ConcurrentHashMap
1313

1414
private const val CODESTYLE_EXTENSION_POINT = "org.jetbrains.kotlin.core.predefinedKotlinCodeStyle"
1515

1616
object KotlinCodeStyleManager {
17+
private val extensions by lazy {
18+
loadExecutableEP<KotlinPredefinedCodeStyle>(CODESTYLE_EXTENSION_POINT, isCaching = true)
19+
}
20+
1721
private val stylesCache = ConcurrentHashMap<String, CodeStyleSettings>()
1822

1923
private val predefinedStyles: Map<String, KotlinPredefinedCodeStyle> by lazy {
20-
loadPredefinedCodeStyles()
21-
.map { it.codeStyleId to it }
22-
.toMap()
24+
extensions
25+
.mapNotNull { it.createProvider() }
26+
.map { it.codeStyleId to it }
27+
.toMap()
28+
}
29+
30+
val buildsystemAliases by lazy {
31+
extensions.mapNotNull { pairOfNotNulls(it.nameInBuildsystem, it.createProvider()?.name) }
32+
.toMap()
2333
}
2434

2535
val styles: List<String>
2636
get() = (predefinedStyles.keys + stylesCache.keys).sorted()
2737

2838
// Can be used in the future to provide user defined code styles
2939
fun getOrCreate(id: String, settingsApplier: CodeStyleSettings.() -> Unit): CodeStyleSettings =
30-
stylesCache.getOrPut(id) { CodeStyleSettings().also { it.settingsApplier() } }
40+
stylesCache.getOrPut(id) { CodeStyleSettings().also { it.settingsApplier() } }
3141

3242
fun get(id: String): CodeStyleSettings? = stylesCache[id] ?: createStyleFromPredef(id)
33-
43+
3444
// Uses the same logic as ConcurrentHashMap.getOrPut() but due to possible nullability cannot be expressed by that method.
3545
private fun createStyleFromPredef(id: String): CodeStyleSettings? = predefinedStyles[id]
36-
?.let { CodeStyleSettings().also(it::apply) }
37-
?.let { stylesCache.putIfAbsent(id, it) ?: it }
46+
?.let { CodeStyleSettings().also(it::apply) }
47+
?.let { stylesCache.putIfAbsent(id, it) ?: it }
3848

3949
fun invalidate(id: String) {
4050
stylesCache -= id
4151
}
4252

4353
fun getStyleLabel(id: String?) =
44-
id?.let { predefinedStyles[it]?.name ?: it } ?: "unknown"
54+
id?.let { predefinedStyles[it]?.name ?: it } ?: "unknown"
4555
}
4656

4757
private val IProject.codeStyleSettings
4858
get() = KotlinCodeStyleProperties(ProjectScope(this))
49-
.takeIf { it.globalsOverridden }
50-
?: KotlinCodeStyleProperties.workspaceInstance
59+
.takeIf { it.globalsOverridden }
60+
?: KotlinCodeStyleProperties.workspaceInstance
5161

5262
val IProject.codeStyle: CodeStyleSettings
5363
get() = codeStyleSettings
54-
.codeStyleId
55-
?.let { KotlinCodeStyleManager.get(it) }
56-
?: CodeStyleSettings()
64+
.codeStyleId
65+
?.let { KotlinCodeStyleManager.get(it) }
66+
?: CodeStyleSettings()
5767

58-
private fun loadPredefinedCodeStyles() =
59-
loadExecutableEP<KotlinPredefinedCodeStyle>(CODESTYLE_EXTENSION_POINT)
60-
.mapNotNull { it.createProvider() }
68+
private val ExecutableExtensionPointDescriptor<KotlinPredefinedCodeStyle>.nameInBuildsystem: String? by EPAttribute

kotlin-eclipse-core/src/org/jetbrains/kotlin/core/model/executableEP.kt

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,26 +20,47 @@ import org.eclipse.core.runtime.CoreException
2020
import org.eclipse.core.runtime.IConfigurationElement
2121
import org.eclipse.core.runtime.Platform
2222
import org.jetbrains.kotlin.core.log.KotlinLogger
23+
import kotlin.reflect.KProperty
2324

24-
fun <T> loadExecutableEP(extensionPointId: String): List<ExecutableExtensionPointDescriptor<T>> {
25+
fun <T> loadExecutableEP(extensionPointId: String, isCaching: Boolean = false): List<ExecutableExtensionPointDescriptor<T>> {
2526
return Platform
2627
.getExtensionRegistry()
2728
.getConfigurationElementsFor(extensionPointId)
28-
.map { ExecutableExtensionPointDescriptor<T>(it) }
29+
.map { ExecutableExtensionPointDescriptor<T>(it, isCaching) }
2930
}
3031

31-
class ExecutableExtensionPointDescriptor<T>(val configurationElement: IConfigurationElement) {
32+
class ExecutableExtensionPointDescriptor<T>(
33+
private val configurationElement: IConfigurationElement,
34+
private val isCaching: Boolean = false
35+
) {
3236
companion object {
3337
private const val CLASS = "class"
3438
}
3539

40+
private var cachedProvider: T? = null
41+
42+
val attributes: Map<String, String> = configurationElement.run {
43+
attributeNames
44+
.map { it to getAttribute(it) }
45+
.toMap()
46+
}
47+
3648
@Suppress("UNCHECKED_CAST")
3749
fun createProvider(): T? {
38-
try {
39-
return configurationElement.createExecutableExtension(CLASS) as T?
50+
return cachedProvider ?: try {
51+
val provider = (configurationElement.createExecutableExtension(CLASS) as T?)
52+
if (isCaching) {
53+
cachedProvider = provider
54+
}
55+
provider
4056
} catch(e: CoreException) {
4157
KotlinLogger.logError(e)
42-
return null
58+
null
4359
}
4460
}
61+
}
62+
63+
object EPAttribute {
64+
operator fun getValue(thisRef: ExecutableExtensionPointDescriptor<*>, property: KProperty<*>): String? =
65+
thisRef.attributes[property.name]
4566
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
package org.jetbrains.kotlin.core.utils
2+
3+
fun <T, S> pairOfNotNulls(first: T?, second: S?): Pair<T, S>? = second?.let { first?.to(it) }

kotlin-eclipse-maven/.classpath

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,6 @@
33
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
44
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
55
<classpathentry kind="src" path="src"/>
6+
<classpathentry kind="con" path="org.jetbrains.kotlin.core.KOTLIN_CONTAINER"/>
67
<classpathentry kind="output" path="bin"/>
78
</classpath>

kotlin-eclipse-maven/.project

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
<projects>
66
</projects>
77
<buildSpec>
8+
<buildCommand>
9+
<name>org.jetbrains.kotlin.ui.kotlinBuilder</name>
10+
<arguments>
11+
</arguments>
12+
</buildCommand>
813
<buildCommand>
914
<name>org.eclipse.jdt.core.javabuilder</name>
1015
<arguments>
@@ -24,5 +29,13 @@
2429
<natures>
2530
<nature>org.eclipse.pde.PluginNature</nature>
2631
<nature>org.eclipse.jdt.core.javanature</nature>
32+
<nature>org.jetbrains.kotlin.core.kotlinNature</nature>
2733
</natures>
34+
<linkedResources>
35+
<link>
36+
<name>kotlin_bin</name>
37+
<type>2</type>
38+
<locationURI>org.jetbrains.kotlin.core.filesystem:/kotlin-eclipse-maven/kotlin_bin</locationURI>
39+
</link>
40+
</linkedResources>
2841
</projectDescription>

kotlin-eclipse-maven/src/org/jetbrains/kotlin/maven/configuration/KotlinMavenProjectConfigurator.java

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package org.jetbrains.kotlin.maven.configuration
2+
3+
import org.apache.maven.model.Plugin
4+
import org.apache.maven.project.MavenProject
5+
import org.codehaus.plexus.util.xml.Xpp3Dom
6+
import org.eclipse.core.resources.ProjectScope
7+
import org.eclipse.core.runtime.IProgressMonitor
8+
import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator
9+
import org.eclipse.m2e.core.project.configurator.ProjectConfigurationRequest
10+
import org.eclipse.m2e.jdt.AbstractSourcesGenerationProjectConfigurator
11+
import org.eclipse.m2e.jdt.IClasspathDescriptor
12+
import org.jetbrains.kotlin.config.ApiVersion
13+
import org.jetbrains.kotlin.config.JvmTarget
14+
import org.jetbrains.kotlin.config.LanguageVersion
15+
import org.jetbrains.kotlin.core.KotlinClasspathContainer
16+
import org.jetbrains.kotlin.core.formatting.KotlinCodeStyleManager
17+
import org.jetbrains.kotlin.core.model.KotlinEnvironment
18+
import org.jetbrains.kotlin.core.model.KotlinNature
19+
import org.jetbrains.kotlin.core.preferences.KotlinCodeStyleProperties
20+
21+
private const val GROUP_ID = "org.jetbrains.kotlin"
22+
private const val MAVEN_PLUGIN_ID = "kotlin-maven-plugin"
23+
24+
class KotlinMavenProjectConfigurator : AbstractSourcesGenerationProjectConfigurator() {
25+
26+
override fun configure(request: ProjectConfigurationRequest, monitor: IProgressMonitor) {
27+
val mavenProject = request.mavenProject
28+
val plugin: Plugin = mavenProject.buildPlugins
29+
.find { checkCoordinates(it, GROUP_ID, MAVEN_PLUGIN_ID) } ?: return
30+
31+
val compilerProperties = KotlinEnvironment.getEnvironment(request.project).projectCompilerProperties
32+
var configurationChanged = false
33+
34+
fun configureProperty(
35+
attributeName: String? = null,
36+
propertyPath: String? = null,
37+
isChangingConfiguration: Boolean = true,
38+
callback: (String) -> Unit
39+
) {
40+
MavenAttributeAccessor(attributeName, propertyPath)
41+
.getFrom(mavenProject, plugin)
42+
?.also(callback)
43+
?.also { configurationChanged = configurationChanged || isChangingConfiguration }
44+
}
45+
46+
47+
configureProperty("languageVersion", "kotlin.compiler.languageVersion") {
48+
compilerProperties.languageVersion = LanguageVersion.fromVersionString(it) ?: LanguageVersion.LATEST_STABLE
49+
}
50+
51+
configureProperty("apiVersion", "kotlin.compiler.apiVersion") {
52+
compilerProperties.apiVersion = ApiVersion.parse(it)
53+
?: ApiVersion.createByLanguageVersion(compilerProperties.languageVersion)
54+
}
55+
56+
configureProperty("jvmTarget", "kotlin.compiler.jvmTarget") {
57+
compilerProperties.jvmTarget = JvmTarget.fromString(it) ?: JvmTarget.DEFAULT
58+
}
59+
60+
getCompilerFlags(plugin.configuration)?.also {
61+
compilerProperties.compilerFlags = it
62+
configurationChanged = true
63+
}
64+
65+
configureProperty(propertyPath = "kotlin.code.style", isChangingConfiguration = false) { alias ->
66+
KotlinCodeStyleManager.buildsystemAliases[alias]?.let {
67+
with(KotlinCodeStyleProperties(ProjectScope(request.project))) {
68+
codeStyleId = it
69+
globalsOverridden = true
70+
saveChanges()
71+
}
72+
}
73+
}
74+
75+
if (configurationChanged) {
76+
compilerProperties.globalsOverridden = true
77+
compilerProperties.saveChanges()
78+
}
79+
}
80+
81+
override fun configureRawClasspath(
82+
request: ProjectConfigurationRequest, classpath: IClasspathDescriptor,
83+
monitor: IProgressMonitor
84+
) {
85+
if (hasKotlinMavenPlugin(request.mavenProject)) {
86+
classpath.addEntry(KotlinClasspathContainer.CONTAINER_ENTRY)
87+
AbstractProjectConfigurator.addNature(request.project, KotlinNature.KOTLIN_NATURE, monitor)
88+
}
89+
}
90+
91+
private fun getCompilerFlags(configuration: Any): String? =
92+
(configuration as? Xpp3Dom)
93+
?.getChild("args")
94+
?.children
95+
?.filter { it.name == "arg" }
96+
?.map { it.value }
97+
?.takeIf { it.isNotEmpty() }
98+
?.joinToString(separator = " ")
99+
100+
private fun hasKotlinMavenPlugin(mavenProject: MavenProject): Boolean =
101+
mavenProject.buildPlugins.any { checkCoordinates(it, GROUP_ID, MAVEN_PLUGIN_ID) }
102+
103+
private fun checkCoordinates(buildPlugin: Plugin, groupId: String, artifactId: String): Boolean =
104+
groupId == buildPlugin.groupId && artifactId == buildPlugin.artifactId
105+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package org.jetbrains.kotlin.maven.configuration
2+
3+
import org.apache.maven.model.Plugin
4+
import org.apache.maven.project.MavenProject
5+
import org.codehaus.plexus.util.xml.Xpp3Dom
6+
import java.util.*
7+
8+
class MavenAttributeAccessor(private val attributeName: String? = null, private val propertyPath: String? = null) {
9+
fun getFrom(project: MavenProject, plugin: Plugin): String? =
10+
getFromConfiguration(plugin.configuration) ?: getFromProperties(project.properties)
11+
12+
private fun getFromConfiguration(configuration: Any?): String? =
13+
(configuration as? Xpp3Dom)
14+
?.getChild(attributeName)
15+
?.value
16+
17+
private fun getFromProperties(properties: Properties): String? =
18+
propertyPath?.let { properties[it] as? String }
19+
}

0 commit comments

Comments
 (0)