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.languageVersionSettings
|
||||||
import org.jetbrains.kotlin.idea.project.targetPlatform
|
import org.jetbrains.kotlin.idea.project.targetPlatform
|
||||||
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
import org.jetbrains.kotlin.script.KotlinScriptDefinition
|
||||||
|
import org.jetbrains.kotlin.utils.Jsr305State
|
||||||
|
|
||||||
object IDELanguageSettingsProvider : LanguageSettingsProvider {
|
object IDELanguageSettingsProvider : LanguageSettingsProvider {
|
||||||
override fun getLanguageVersionSettings(moduleInfo: ModuleInfo, project: Project): LanguageVersionSettings =
|
override fun getLanguageVersionSettings(moduleInfo: ModuleInfo, project: Project): LanguageVersionSettings =
|
||||||
when (moduleInfo) {
|
when (moduleInfo) {
|
||||||
is ModuleSourceInfo -> moduleInfo.module.languageVersionSettings
|
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 ScriptModuleInfo -> getVersionLanguageSettingsForScripts(project, moduleInfo.scriptDefinition)
|
||||||
is ScriptDependenciesInfo.ForFile -> getVersionLanguageSettingsForScripts(project, moduleInfo.scriptDefinition)
|
is ScriptDependenciesInfo.ForFile -> getVersionLanguageSettingsForScripts(project, moduleInfo.scriptDefinition)
|
||||||
is PlatformModuleInfo -> moduleInfo.platformModule.module.languageVersionSettings
|
is PlatformModuleInfo -> moduleInfo.platformModule.module.languageVersionSettings
|
||||||
else -> project.getLanguageVersionSettings()
|
else -> project.getLanguageVersionSettings()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getExtraAnalysisFlags(project: Project): Map<AnalysisFlag<*>, Any?> {
|
private fun computeJsr305State(project: Project): Jsr305State? {
|
||||||
val map = mutableMapOf<AnalysisFlag<*>, Any>()
|
var result: Jsr305State? = null
|
||||||
for (module in ModuleManager.getInstance(project).modules) {
|
for (module in ModuleManager.getInstance(project).modules) {
|
||||||
val settings = KotlinFacetSettingsProvider.getInstance(project).getSettings(module) ?: continue
|
val settings = KotlinFacetSettingsProvider.getInstance(project).getSettings(module) ?: continue
|
||||||
val compilerArguments = settings.mergedCompilerArguments as? K2JVMCompilerArguments ?: continue
|
val compilerArguments = settings.mergedCompilerArguments as? K2JVMCompilerArguments ?: continue
|
||||||
|
|
||||||
val jsr305State = Jsr305Parser(MessageCollector.NONE).parse(
|
result = Jsr305Parser(MessageCollector.NONE).parse(
|
||||||
compilerArguments.jsr305,
|
compilerArguments.jsr305,
|
||||||
compilerArguments.supportCompatqualCheckerFrameworkAnnotations
|
compilerArguments.supportCompatqualCheckerFrameworkAnnotations
|
||||||
)
|
)
|
||||||
map.put(AnalysisFlag.jsr305, jsr305State)
|
|
||||||
}
|
}
|
||||||
return map
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getTargetPlatform(moduleInfo: ModuleInfo): TargetPlatformVersion {
|
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.CachedValueProvider
|
||||||
import com.intellij.psi.util.CachedValuesManager
|
import com.intellij.psi.util.CachedValuesManager
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.Argument
|
import org.jetbrains.kotlin.cli.common.arguments.*
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.config.*
|
import org.jetbrains.kotlin.config.*
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
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.idea.facet.getLibraryLanguageLevel
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.TargetPlatform
|
import org.jetbrains.kotlin.resolve.TargetPlatform
|
||||||
|
import org.jetbrains.kotlin.utils.Jsr305State
|
||||||
|
|
||||||
val KtElement.platform: TargetPlatform
|
val KtElement.platform: TargetPlatform
|
||||||
get() = TargetPlatformDetector.getPlatform(containingKtFile)
|
get() = TargetPlatformDetector.getPlatform(containingKtFile)
|
||||||
@@ -46,22 +46,6 @@ val KtElement.platform: TargetPlatform
|
|||||||
val KtElement.builtIns: KotlinBuiltIns
|
val KtElement.builtIns: KotlinBuiltIns
|
||||||
get() = getResolutionFacade().moduleDescriptor.builtIns
|
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 {
|
fun Module.getAndCacheLanguageLevelByDependencies(): LanguageVersion {
|
||||||
val facetSettings = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(this)
|
val facetSettings = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(this)
|
||||||
val languageLevel = getLibraryLanguageLevel(this, null, facetSettings.targetPlatformKind)
|
val languageLevel = getLibraryLanguageLevel(this, null, facetSettings.targetPlatformKind)
|
||||||
@@ -93,7 +77,7 @@ fun Module.getAndCacheLanguageLevelByDependencies(): LanguageVersion {
|
|||||||
@JvmOverloads
|
@JvmOverloads
|
||||||
fun Project.getLanguageVersionSettings(
|
fun Project.getLanguageVersionSettings(
|
||||||
contextModule: Module? = null,
|
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 {
|
): LanguageVersionSettings {
|
||||||
val arguments = KotlinCommonCompilerArgumentsHolder.getInstance(this).settings
|
val arguments = KotlinCommonCompilerArgumentsHolder.getInstance(this).settings
|
||||||
val languageVersion =
|
val languageVersion =
|
||||||
@@ -102,16 +86,24 @@ fun Project.getLanguageVersionSettings(
|
|||||||
?: LanguageVersion.LATEST_STABLE
|
?: LanguageVersion.LATEST_STABLE
|
||||||
val apiVersion = ApiVersion.createByLanguageVersion(LanguageVersion.fromVersionString(arguments.apiVersion) ?: languageVersion)
|
val apiVersion = ApiVersion.createByLanguageVersion(LanguageVersion.fromVersionString(arguments.apiVersion) ?: languageVersion)
|
||||||
val compilerSettings = KotlinCompilerSettings.getInstance(this).settings
|
val compilerSettings = KotlinCompilerSettings.getInstance(this).settings
|
||||||
val extraLanguageFeatures = getExtraLanguageFeatures(
|
|
||||||
null,
|
val additionalArguments: CommonCompilerArguments = parseArguments(
|
||||||
CoroutineSupport.byCompilerArguments(KotlinCommonCompilerArgumentsHolder.getInstance(this).settings),
|
TargetPlatformKind.DEFAULT_PLATFORM,
|
||||||
compilerSettings,
|
compilerSettings.additionalArgumentsAsList
|
||||||
null
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
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(
|
return LanguageVersionSettingsImpl(
|
||||||
languageVersion, apiVersion,
|
languageVersion, apiVersion,
|
||||||
arguments.configureAnalysisFlags(MessageCollector.NONE) + extraAnalysisFlags,
|
arguments.configureAnalysisFlags(MessageCollector.NONE) + extraAnalysisFlags,
|
||||||
extraLanguageFeatures
|
arguments.configureLanguageFeatures(MessageCollector.NONE) + extraLanguageFeatures
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -137,26 +129,30 @@ private fun Module.createCachedValueForLanguageVersionSettings(): CachedValue<La
|
|||||||
}, false)
|
}, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Module.computeLanguageVersionSettings(): LanguageVersionSettings {
|
private fun Module.shouldUseProjectLanguageVersionSettings(): Boolean {
|
||||||
val facetSettingsProvider = KotlinFacetSettingsProvider.getInstance(project)
|
val facetSettingsProvider = KotlinFacetSettingsProvider.getInstance(project)
|
||||||
if (facetSettingsProvider.getSettings(this) == null) return project.getLanguageVersionSettings(this)
|
return facetSettingsProvider.getSettings(this) == null || facetSettingsProvider.getInitializedSettings(this).useProjectSettings
|
||||||
val facetSettings = facetSettingsProvider.getInitializedSettings(this)
|
}
|
||||||
if (facetSettings.useProjectSettings) return project.getLanguageVersionSettings(this)
|
|
||||||
|
private fun Module.computeLanguageVersionSettings(): LanguageVersionSettings {
|
||||||
|
if (shouldUseProjectLanguageVersionSettings()) return project.getLanguageVersionSettings()
|
||||||
|
|
||||||
|
val facetSettings = KotlinFacetSettingsProvider.getInstance(project).getInitializedSettings(this)
|
||||||
val languageVersion = facetSettings.languageLevel ?: getAndCacheLanguageLevelByDependencies()
|
val languageVersion = facetSettings.languageLevel ?: getAndCacheLanguageLevelByDependencies()
|
||||||
val apiVersion = facetSettings.apiLevel ?: languageVersion
|
val apiVersion = facetSettings.apiLevel ?: languageVersion
|
||||||
|
|
||||||
val extraLanguageFeatures = getExtraLanguageFeatures(
|
val languageFeatures = facetSettings.mergedCompilerArguments?.configureLanguageFeatures(MessageCollector.NONE)?.apply {
|
||||||
facetSettings.targetPlatformKind ?: TargetPlatformKind.Common,
|
configureCoroutinesSupport(facetSettings.coroutineSupport)
|
||||||
facetSettings.coroutineSupport,
|
configureMultiplatformSupport(facetSettings.targetPlatformKind, this@computeLanguageVersionSettings)
|
||||||
facetSettings.compilerSettings,
|
}.orEmpty()
|
||||||
this
|
|
||||||
)
|
val analysisFlags = facetSettings.mergedCompilerArguments?.configureAnalysisFlags(MessageCollector.NONE).orEmpty()
|
||||||
|
|
||||||
return LanguageVersionSettingsImpl(
|
return LanguageVersionSettingsImpl(
|
||||||
languageVersion,
|
languageVersion,
|
||||||
ApiVersion.createByLanguageVersion(apiVersion),
|
ApiVersion.createByLanguageVersion(apiVersion),
|
||||||
facetSettings.mergedCompilerArguments?.configureAnalysisFlags(MessageCollector.NONE).orEmpty(),
|
analysisFlags,
|
||||||
extraLanguageFeatures
|
languageFeatures
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,37 +170,35 @@ private val Module.implementsCommonModule: Boolean
|
|||||||
get() = targetPlatform != TargetPlatformKind.Common
|
get() = targetPlatform != TargetPlatformKind.Common
|
||||||
&& ModuleRootManager.getInstance(this).dependencies.any { it.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<*>?,
|
targetPlatformKind: TargetPlatformKind<*>?,
|
||||||
coroutineSupport: LanguageFeature.State,
|
|
||||||
compilerSettings: CompilerSettings?,
|
|
||||||
module: Module?
|
module: Module?
|
||||||
): Map<LanguageFeature, LanguageFeature.State> {
|
) {
|
||||||
return mutableMapOf<LanguageFeature, LanguageFeature.State>().apply {
|
if (targetPlatformKind == TargetPlatformKind.Common || module?.implementsCommonModule == true) {
|
||||||
put(LanguageFeature.Coroutines, coroutineSupport)
|
put(LanguageFeature.MultiPlatformProjects, LanguageFeature.State.ENABLED)
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
val KtElement.languageVersionSettings: LanguageVersionSettings
|
val KtElement.languageVersionSettings: LanguageVersionSettings
|
||||||
get() {
|
get() {
|
||||||
if (ServiceManager.getService(project, ProjectFileIndex::class.java) == null) {
|
if (ServiceManager.getService(project, ProjectFileIndex::class.java) == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user