Parse compiler arguments and configure LV properly in Platform.kt
This commit is contained in:
+7
-6
@@ -38,31 +38,32 @@ import org.jetbrains.kotlin.idea.project.getLanguageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.project.languageVersionSettings
|
||||
import org.jetbrains.kotlin.idea.project.targetPlatform
|
||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||
import org.jetbrains.kotlin.utils.Jsr305State
|
||||
|
||||
object IDELanguageSettingsProvider : LanguageSettingsProvider {
|
||||
override fun getLanguageVersionSettings(moduleInfo: ModuleInfo, project: Project): LanguageVersionSettings =
|
||||
when (moduleInfo) {
|
||||
is ModuleSourceInfo -> moduleInfo.module.languageVersionSettings
|
||||
is LibraryInfo -> project.getLanguageVersionSettings(extraAnalysisFlags = getExtraAnalysisFlags(project))
|
||||
is LibraryInfo -> project.getLanguageVersionSettings(jsr305State = computeJsr305State(project))
|
||||
is ScriptModuleInfo -> getVersionLanguageSettingsForScripts(project, moduleInfo.scriptDefinition)
|
||||
is ScriptDependenciesInfo.ForFile -> getVersionLanguageSettingsForScripts(project, moduleInfo.scriptDefinition)
|
||||
is PlatformModuleInfo -> moduleInfo.platformModule.module.languageVersionSettings
|
||||
else -> project.getLanguageVersionSettings()
|
||||
}
|
||||
|
||||
private fun getExtraAnalysisFlags(project: Project): Map<AnalysisFlag<*>, Any?> {
|
||||
val map = mutableMapOf<AnalysisFlag<*>, Any>()
|
||||
private fun computeJsr305State(project: Project): Jsr305State? {
|
||||
var result: Jsr305State? = null
|
||||
for (module in ModuleManager.getInstance(project).modules) {
|
||||
val settings = KotlinFacetSettingsProvider.getInstance(project).getSettings(module) ?: continue
|
||||
val compilerArguments = settings.mergedCompilerArguments as? K2JVMCompilerArguments ?: continue
|
||||
|
||||
val jsr305State = Jsr305Parser(MessageCollector.NONE).parse(
|
||||
result = Jsr305Parser(MessageCollector.NONE).parse(
|
||||
compilerArguments.jsr305,
|
||||
compilerArguments.supportCompatqualCheckerFrameworkAnnotations
|
||||
)
|
||||
map.put(AnalysisFlag.jsr305, jsr305State)
|
||||
|
||||
}
|
||||
return map
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getTargetPlatform(moduleInfo: ModuleInfo): TargetPlatformVersion {
|
||||
|
||||
@@ -28,8 +28,7 @@ import com.intellij.psi.util.CachedValue
|
||||
import com.intellij.psi.util.CachedValueProvider
|
||||
import com.intellij.psi.util.CachedValuesManager
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.cli.common.arguments.Argument
|
||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||
import org.jetbrains.kotlin.config.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||
@@ -39,6 +38,7 @@ import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
|
||||
import org.jetbrains.kotlin.idea.facet.getLibraryLanguageLevel
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||
import org.jetbrains.kotlin.utils.Jsr305State
|
||||
|
||||
val KtElement.platform: TargetPlatform
|
||||
get() = TargetPlatformDetector.getPlatform(containingKtFile)
|
||||
@@ -46,22 +46,6 @@ val KtElement.platform: TargetPlatform
|
||||
val KtElement.builtIns: KotlinBuiltIns
|
||||
get() = getResolutionFacade().moduleDescriptor.builtIns
|
||||
|
||||
private val multiPlatformProjectsArg: String by lazy {
|
||||
CommonCompilerArguments::multiPlatform.annotations.filterIsInstance<Argument>().single().value
|
||||
}
|
||||
|
||||
private val effectSystemArg: String by lazy {
|
||||
CommonCompilerArguments::effectSystem.annotations.filterIsInstance<Argument>().single().value
|
||||
}
|
||||
|
||||
private val readDeserializedContractsArg: String by lazy {
|
||||
CommonCompilerArguments::readDeserializedContracts.annotations.filterIsInstance<Argument>().single().value
|
||||
}
|
||||
|
||||
private val newInferenceArg: String by lazy {
|
||||
CommonCompilerArguments::newInference.annotations.filterIsInstance<Argument>().single().value
|
||||
}
|
||||
|
||||
fun Module.getAndCacheLanguageLevelByDependencies(): LanguageVersion {
|
||||
val facetSettings = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(this)
|
||||
val languageLevel = getLibraryLanguageLevel(this, null, facetSettings.targetPlatformKind)
|
||||
@@ -93,7 +77,7 @@ fun Module.getAndCacheLanguageLevelByDependencies(): LanguageVersion {
|
||||
@JvmOverloads
|
||||
fun Project.getLanguageVersionSettings(
|
||||
contextModule: Module? = null,
|
||||
extraAnalysisFlags: Map<AnalysisFlag<*>, Any?> = emptyMap()
|
||||
jsr305State: Jsr305State? = null // this is a temporary hack until we'll have a sane way to configure libraries analysis
|
||||
): LanguageVersionSettings {
|
||||
val arguments = KotlinCommonCompilerArgumentsHolder.getInstance(this).settings
|
||||
val languageVersion =
|
||||
@@ -102,16 +86,24 @@ fun Project.getLanguageVersionSettings(
|
||||
?: LanguageVersion.LATEST_STABLE
|
||||
val apiVersion = ApiVersion.createByLanguageVersion(LanguageVersion.fromVersionString(arguments.apiVersion) ?: languageVersion)
|
||||
val compilerSettings = KotlinCompilerSettings.getInstance(this).settings
|
||||
val extraLanguageFeatures = getExtraLanguageFeatures(
|
||||
null,
|
||||
CoroutineSupport.byCompilerArguments(KotlinCommonCompilerArgumentsHolder.getInstance(this).settings),
|
||||
compilerSettings,
|
||||
null
|
||||
|
||||
val additionalArguments: CommonCompilerArguments = parseArguments(
|
||||
TargetPlatformKind.DEFAULT_PLATFORM,
|
||||
compilerSettings.additionalArgumentsAsList
|
||||
)
|
||||
|
||||
val extraLanguageFeatures = additionalArguments.configureLanguageFeatures(MessageCollector.NONE).apply {
|
||||
configureCoroutinesSupport(CoroutineSupport.byCompilerArguments(KotlinCommonCompilerArgumentsHolder.getInstance(this@getLanguageVersionSettings).settings))
|
||||
}
|
||||
|
||||
val extraAnalysisFlags = additionalArguments.configureAnalysisFlags(MessageCollector.NONE).apply {
|
||||
if (jsr305State != null) put(AnalysisFlag.jsr305, jsr305State)
|
||||
}
|
||||
|
||||
return LanguageVersionSettingsImpl(
|
||||
languageVersion, apiVersion,
|
||||
arguments.configureAnalysisFlags(MessageCollector.NONE) + extraAnalysisFlags,
|
||||
extraLanguageFeatures
|
||||
arguments.configureLanguageFeatures(MessageCollector.NONE) + extraLanguageFeatures
|
||||
)
|
||||
}
|
||||
|
||||
@@ -137,26 +129,30 @@ private fun Module.createCachedValueForLanguageVersionSettings(): CachedValue<La
|
||||
}, false)
|
||||
}
|
||||
|
||||
private fun Module.computeLanguageVersionSettings(): LanguageVersionSettings {
|
||||
private fun Module.shouldUseProjectLanguageVersionSettings(): Boolean {
|
||||
val facetSettingsProvider = KotlinFacetSettingsProvider.getInstance(project)
|
||||
if (facetSettingsProvider.getSettings(this) == null) return project.getLanguageVersionSettings(this)
|
||||
val facetSettings = facetSettingsProvider.getInitializedSettings(this)
|
||||
if (facetSettings.useProjectSettings) return project.getLanguageVersionSettings(this)
|
||||
return facetSettingsProvider.getSettings(this) == null || facetSettingsProvider.getInitializedSettings(this).useProjectSettings
|
||||
}
|
||||
|
||||
private fun Module.computeLanguageVersionSettings(): LanguageVersionSettings {
|
||||
if (shouldUseProjectLanguageVersionSettings()) return project.getLanguageVersionSettings()
|
||||
|
||||
val facetSettings = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(this)
|
||||
val languageVersion = facetSettings.languageLevel ?: getAndCacheLanguageLevelByDependencies()
|
||||
val apiVersion = facetSettings.apiLevel ?: languageVersion
|
||||
|
||||
val extraLanguageFeatures = getExtraLanguageFeatures(
|
||||
facetSettings.targetPlatformKind ?: TargetPlatformKind.Common,
|
||||
facetSettings.coroutineSupport,
|
||||
facetSettings.compilerSettings,
|
||||
this
|
||||
)
|
||||
val languageFeatures = facetSettings.mergedCompilerArguments?.configureLanguageFeatures(MessageCollector.NONE)?.apply {
|
||||
configureCoroutinesSupport(facetSettings.coroutineSupport)
|
||||
configureMultiplatformSupport(facetSettings.targetPlatformKind, this@computeLanguageVersionSettings)
|
||||
}.orEmpty()
|
||||
|
||||
val analysisFlags = facetSettings.mergedCompilerArguments?.configureAnalysisFlags(MessageCollector.NONE).orEmpty()
|
||||
|
||||
return LanguageVersionSettingsImpl(
|
||||
languageVersion,
|
||||
ApiVersion.createByLanguageVersion(apiVersion),
|
||||
facetSettings.mergedCompilerArguments?.configureAnalysisFlags(MessageCollector.NONE).orEmpty(),
|
||||
extraLanguageFeatures
|
||||
analysisFlags,
|
||||
languageFeatures
|
||||
)
|
||||
}
|
||||
|
||||
@@ -174,37 +170,35 @@ private val Module.implementsCommonModule: Boolean
|
||||
get() = targetPlatform != TargetPlatformKind.Common
|
||||
&& ModuleRootManager.getInstance(this).dependencies.any { it.targetPlatform == TargetPlatformKind.Common }
|
||||
|
||||
private fun getExtraLanguageFeatures(
|
||||
private fun parseArguments(
|
||||
targetPlatformKind: TargetPlatformKind<*>,
|
||||
additionalArguments: List<String>
|
||||
): CommonCompilerArguments {
|
||||
val arguments = when (targetPlatformKind) {
|
||||
is TargetPlatformKind.Jvm -> K2JVMCompilerArguments()
|
||||
TargetPlatformKind.JavaScript -> K2JSCompilerArguments()
|
||||
TargetPlatformKind.Common -> K2MetadataCompilerArguments()
|
||||
}
|
||||
|
||||
parseCommandLineArguments(additionalArguments, arguments)
|
||||
|
||||
return arguments
|
||||
}
|
||||
|
||||
fun MutableMap<LanguageFeature, LanguageFeature.State>.configureCoroutinesSupport(coroutineSupport: LanguageFeature.State) {
|
||||
put(LanguageFeature.Coroutines, coroutineSupport)
|
||||
}
|
||||
|
||||
fun MutableMap<LanguageFeature, LanguageFeature.State>.configureMultiplatformSupport(
|
||||
targetPlatformKind: TargetPlatformKind<*>?,
|
||||
coroutineSupport: LanguageFeature.State,
|
||||
compilerSettings: CompilerSettings?,
|
||||
module: Module?
|
||||
): Map<LanguageFeature, LanguageFeature.State> {
|
||||
return mutableMapOf<LanguageFeature, LanguageFeature.State>().apply {
|
||||
put(LanguageFeature.Coroutines, coroutineSupport)
|
||||
if (targetPlatformKind == TargetPlatformKind.Common ||
|
||||
// TODO: this is a dirty hack, parse arguments correctly here
|
||||
compilerSettings?.additionalArguments?.contains(multiPlatformProjectsArg) == true ||
|
||||
(module != null && module.implementsCommonModule)
|
||||
) {
|
||||
put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (compilerSettings?.additionalArguments?.contains(effectSystemArg) == true) {
|
||||
put(LanguageFeature.UseReturnsEffect, LanguageFeature.State.ENABLED)
|
||||
put(LanguageFeature.UseCallsInPlaceEffect, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (compilerSettings?.additionalArguments?.contains(readDeserializedContractsArg) == true) {
|
||||
put(LanguageFeature.ReadDeserializedContracts, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
|
||||
if (compilerSettings?.additionalArguments?.contains(newInferenceArg) == true) {
|
||||
put(LanguageFeature.NewInference, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
) {
|
||||
if (targetPlatformKind == TargetPlatformKind.Common || module?.implementsCommonModule == true) {
|
||||
put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val KtElement.languageVersionSettings: LanguageVersionSettings
|
||||
get() {
|
||||
if (ServiceManager.getService(project, ProjectFileIndex::class.java) == null) {
|
||||
|
||||
Reference in New Issue
Block a user