Skip to content

Commit 4325632

Browse files
committed
Kotlin Facet: Always parse argument string to proper compiler arguments bean
#KT-16137 Fixed #KT-16157 Fixed #KT-16206 Fixed
1 parent 9d6f4d7 commit 4325632

File tree

9 files changed

+315
-36
lines changed

9 files changed

+315
-36
lines changed

.idea/artifacts/KotlinPlugin.xml

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

compiler/cli/cli-common/src/org/jetbrains/kotlin/cli/common/arguments/argumentUtils.kt

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,16 +37,22 @@ import java.util.*
3737
}
3838
}
3939

40-
fun <T : Any> copyBean(bean: T) = copyFields(bean, bean.javaClass.newInstance(), true)
40+
fun <T : Any> copyBean(bean: T) = copyFields(bean, bean.javaClass.newInstance(), true, collectFieldsToCopy(bean.javaClass, false))
4141

4242
fun <From : Any, To : From> mergeBeans(from: From, to: To): To {
4343
// TODO: rewrite when updated version of com.intellij.util.xmlb is available on TeamCity
44-
return copyFields(from, XmlSerializerUtil.createCopy(to), false)
44+
return copyFields(from, XmlSerializerUtil.createCopy(to), false, collectFieldsToCopy(from.javaClass, false))
4545
}
4646

47-
private fun <From : Any, To : From> copyFields(from: From, to: To, deepCopyWhenNeeded: Boolean = false): To {
48-
val fromFields = collectFieldsToCopy(from.javaClass)
49-
for (fromField in fromFields) {
47+
fun <From : Any, To : Any> copyInheritedFields(from: From, to: To) = copyFields(from, to, true, collectFieldsToCopy(from.javaClass, true))
48+
49+
fun <From : Any, To : Any> copyFieldsSatisfying(from: From, to: To, predicate: (Field) -> Boolean) =
50+
copyFields(from, to, true, collectFieldsToCopy(from.javaClass, false).filter(predicate))
51+
52+
private fun <From : Any, To : Any> copyFields(from: From, to: To, deepCopyWhenNeeded: Boolean, fieldsToCopy: List<Field>): To {
53+
if (from == to) return to
54+
55+
for (fromField in fieldsToCopy) {
5056
val toField = to.javaClass.getField(fromField.name)
5157
val fromValue = fromField.get(from)
5258
toField.set(to, if (deepCopyWhenNeeded) fromValue?.copyValueIfNeeded() else fromValue)
@@ -83,10 +89,10 @@ private fun Any.copyValueIfNeeded(): Any {
8389
}
8490
}
8591

86-
private fun collectFieldsToCopy(clazz: Class<*>): List<Field> {
92+
private fun collectFieldsToCopy(clazz: Class<*>, inheritedOnly: Boolean): List<Field> {
8793
val fromFields = ArrayList<Field>()
8894

89-
var currentClass: Class<*>? = clazz
95+
var currentClass: Class<*>? = if (inheritedOnly) clazz.superclass else clazz
9096
while (currentClass != null) {
9197
for (field in currentClass.declaredFields) {
9298
val modifiers = field.modifiers

idea/idea-jps-common/src/org/jetbrains/kotlin/config/CompilerSettings.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class CompilerSettings {
2424
@JvmField var outputDirectoryForJsLibraryFiles: String = DEFAULT_OUTPUT_DIRECTORY
2525

2626
companion object {
27-
private val DEFAULT_ADDITIONAL_ARGUMENTS = "-version"
27+
val DEFAULT_ADDITIONAL_ARGUMENTS = "-version"
2828
private val DEFAULT_OUTPUT_DIRECTORY = "lib"
2929
}
3030
}

idea/idea-jps-common/src/org/jetbrains/kotlin/config/KotlinFacetSettings.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import com.intellij.util.xmlb.annotations.Property
2323
import com.intellij.util.xmlb.annotations.Transient
2424
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
2525
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
26+
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
2627
import org.jetbrains.kotlin.utils.DescriptionAware
2728

2829
sealed class TargetPlatformKind<out Version : DescriptionAware>(
@@ -96,6 +97,7 @@ class KotlinCompilerInfo {
9697
_commonCompilerArguments = value as? CommonCompilerArguments.DummyImpl
9798
}
9899
var k2jsCompilerArguments: K2JSCompilerArguments? = null
100+
var k2jvmCompilerArguments: K2JVMCompilerArguments? = null
99101
var compilerSettings: CompilerSettings? = null
100102

101103
@get:Transient var coroutineSupport: CoroutineSupport

idea/idea.iml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,5 +61,6 @@
6161
<orderEntry type="module" module-name="sam-with-receiver-ide" scope="TEST" />
6262
<orderEntry type="module" module-name="descriptors" />
6363
<orderEntry type="module" module-name="kotlin-gradle-tooling" />
64+
<orderEntry type="module" module-name="build-common" />
6465
</component>
6566
</module>

idea/src/org/jetbrains/kotlin/idea/facet/KotlinFacetEditorGeneralTab.kt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import com.intellij.util.ui.ThreeStateCheckBox
2525
import com.intellij.util.ui.UIUtil
2626
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
2727
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
28+
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
2829
import org.jetbrains.kotlin.config.CompilerSettings
2930
import org.jetbrains.kotlin.config.KotlinCompilerInfo
3031
import org.jetbrains.kotlin.config.LanguageVersion
@@ -49,6 +50,7 @@ class KotlinFacetEditorGeneralTab(
4950
.apply {
5051
commonCompilerArguments = object : CommonCompilerArguments() {}
5152
k2jsCompilerArguments = K2JSCompilerArguments()
53+
k2jvmCompilerArguments = K2JVMCompilerArguments()
5254
compilerSettings = CompilerSettings()
5355
}
5456
val compilerConfigurable = with(compilerInfo) {
@@ -58,7 +60,7 @@ class KotlinFacetEditorGeneralTab(
5860
k2jsCompilerArguments,
5961
compilerSettings,
6062
null,
61-
null,
63+
k2jvmCompilerArguments,
6264
false,
6365
isMultiEditor
6466
)

idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ import com.intellij.openapi.roots.ModuleRootManager
2525
import com.intellij.openapi.roots.ModuleRootModel
2626
import com.intellij.openapi.roots.OrderRootType
2727
import com.intellij.util.text.VersionComparatorUtil
28-
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
29-
import org.jetbrains.kotlin.cli.common.arguments.copyBean
30-
import org.jetbrains.kotlin.cli.common.arguments.parseArguments
28+
import org.jetbrains.kotlin.cli.common.arguments.*
29+
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
3130
import org.jetbrains.kotlin.config.*
3231
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JsCompilerArgumentsHolder
32+
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder
3333
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder
3434
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
3535
import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider
@@ -139,6 +139,10 @@ fun KotlinFacetSettings.initializeIfNeeded(module: Module, rootModel: ModuleRoot
139139
if (k2jsCompilerArguments == null) {
140140
k2jsCompilerArguments = copyBean(Kotlin2JsCompilerArgumentsHolder.getInstance(project).settings)
141141
}
142+
143+
if (k2jvmCompilerArguments == null) {
144+
k2jvmCompilerArguments = copyBean(Kotlin2JvmCompilerArgumentsHolder.getInstance(project).settings)
145+
}
142146
}
143147
}
144148

@@ -181,38 +185,80 @@ fun KotlinFacet.configureFacet(
181185
}
182186
}
183187

188+
// Update these lists when facet/project settings UI changes
189+
private val commonExposedFields = listOf("languageVersion",
190+
"apiVersion",
191+
"suppressWarnings",
192+
"coroutinesEnable",
193+
"coroutinesWarn",
194+
"coroutinesError")
195+
private val jvmExposedFields = commonExposedFields +
196+
listOf("jvmTarget")
197+
private val jsExposedFields = commonExposedFields +
198+
listOf("sourceMap",
199+
"outputPrefix",
200+
"outputPostfix",
201+
"moduleKind")
202+
203+
private val CommonCompilerArguments.exposedFields: List<String>
204+
get() = when (this) {
205+
is K2JVMCompilerArguments -> jvmExposedFields
206+
is K2JSCompilerArguments -> jsExposedFields
207+
else -> commonExposedFields
208+
}
209+
184210
fun parseCompilerArgumentsToFacet(arguments: List<String>, kotlinFacet: KotlinFacet) {
185211
val argumentArray = arguments.toTypedArray()
212+
186213
with(kotlinFacet.configuration.settings) {
187214
// todo: merge common arguments with platform-specific ones in facet settings
188-
compilerInfo.commonCompilerArguments!!.let { commonCompilerArguments ->
189-
val oldCoroutineSupport = CoroutineSupport.byCompilerArguments(commonCompilerArguments)
190-
commonCompilerArguments.coroutinesEnable = false
191-
commonCompilerArguments.coroutinesWarn = false
192-
commonCompilerArguments.coroutinesError = false
193-
194-
parseArguments(argumentArray, commonCompilerArguments, ignoreInvalidArguments = true)
195-
if (!commonCompilerArguments.coroutinesEnable && !commonCompilerArguments.coroutinesWarn && !commonCompilerArguments.coroutinesError) {
196-
compilerInfo.coroutineSupport = oldCoroutineSupport
197-
}
198215

199-
versionInfo.apiLevel = LanguageVersion.fromVersionString(commonCompilerArguments.apiVersion)
200-
versionInfo.languageLevel = LanguageVersion.fromVersionString(commonCompilerArguments.languageVersion)
216+
val commonCompilerArguments = compilerInfo.commonCompilerArguments!!
217+
val compilerArguments = when (versionInfo.targetPlatformKind) {
218+
is TargetPlatformKind.Jvm -> compilerInfo.k2jvmCompilerArguments
219+
is TargetPlatformKind.JavaScript -> compilerInfo.k2jsCompilerArguments
220+
else -> commonCompilerArguments
221+
}!!
222+
223+
val oldCoroutineSupport = CoroutineSupport.byCompilerArguments(commonCompilerArguments)
224+
commonCompilerArguments.coroutinesEnable = false
225+
commonCompilerArguments.coroutinesWarn = false
226+
commonCompilerArguments.coroutinesError = false
227+
228+
parseArguments(argumentArray, compilerArguments, true)
229+
230+
if (!compilerArguments.coroutinesEnable && !compilerArguments.coroutinesWarn && !compilerArguments.coroutinesError) {
231+
compilerInfo.coroutineSupport = oldCoroutineSupport
201232
}
202233

203-
when (versionInfo.targetPlatformKind) {
204-
is TargetPlatformKind.Jvm -> {
205-
val jvmTarget = K2JVMCompilerArguments().apply { parseArguments(argumentArray, this, ignoreInvalidArguments = true) }.jvmTarget
206-
if (jvmTarget != null) {
207-
versionInfo.targetPlatformKind = TargetPlatformKind.Jvm.JVM_PLATFORMS.firstOrNull {
208-
VersionComparatorUtil.compare(it.version.description, jvmTarget) >= 0
209-
} ?: TargetPlatformKind.Jvm.JVM_PLATFORMS.last()
210-
}
234+
versionInfo.apiLevel = LanguageVersion.fromVersionString(compilerArguments.apiVersion)
235+
versionInfo.languageLevel = LanguageVersion.fromVersionString(compilerArguments.languageVersion)
236+
237+
if (versionInfo.targetPlatformKind is TargetPlatformKind.Jvm) {
238+
val jvmTarget = compilerInfo.k2jvmCompilerArguments!!.jvmTarget
239+
if (jvmTarget != null) {
240+
versionInfo.targetPlatformKind = TargetPlatformKind.Jvm.JVM_PLATFORMS.firstOrNull {
241+
VersionComparatorUtil.compare(it.version.description, jvmTarget) >= 0
242+
} ?: TargetPlatformKind.Jvm.JVM_PLATFORMS.last()
211243
}
212-
is TargetPlatformKind.JavaScript -> parseArguments(argumentArray, compilerInfo.k2jsCompilerArguments!!, ignoreInvalidArguments = true)
213-
else -> {}
214244
}
215245

216-
compilerInfo.compilerSettings!!.additionalArguments = compilerInfo.commonCompilerArguments!!.freeArgs.joinToString(separator = " ")
246+
// Retain only fields exposed in facet configuration editor.
247+
// The rest is combined into string and stored in CompilerSettings.additionalArguments
248+
249+
val exposedFields = compilerArguments.exposedFields
250+
251+
val additionalArgumentsString = with(compilerArguments.javaClass.newInstance()) {
252+
copyFieldsSatisfying(compilerArguments, this) { it.name !in exposedFields }
253+
ArgumentUtils.convertArgumentsToStringList(this).joinToString(separator = " ")
254+
}
255+
compilerInfo.compilerSettings!!.additionalArguments =
256+
if (additionalArgumentsString.isNotEmpty()) additionalArgumentsString else CompilerSettings.DEFAULT_ADDITIONAL_ARGUMENTS
257+
258+
with(compilerArguments.javaClass.newInstance()) {
259+
copyFieldsSatisfying(this, compilerArguments) { it.name !in exposedFields }
260+
}
261+
262+
copyInheritedFields(compilerArguments, commonCompilerArguments)
217263
}
218264
}

0 commit comments

Comments
 (0)