MPP: Refactoring, extract IDE platform kinds, allow to add custom platforms

This commit is contained in:
Yan Zhulanow
2018-08-30 18:46:59 +05:00
parent cf1b2bedf4
commit d00f5b335a
81 changed files with 1327 additions and 844 deletions
+10 -5
View File
@@ -15,8 +15,8 @@
interface="org.jetbrains.kotlin.android.model.AndroidModuleInfoProvider"
area="IDEA_MODULE"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.idePlatformSupport"
interface="org.jetbrains.kotlin.caches.resolve.IdePlatformSupport"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.idePlatformKindResolution"
interface="org.jetbrains.kotlin.caches.resolve.IdePlatformKindResolution"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.highlighterExtension"
interface="org.jetbrains.kotlin.idea.highlighter.HighlighterExtension"/>
@@ -37,6 +37,11 @@
interface="org.jetbrains.kotlin.idea.completion.KotlinCompletionExtension"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.buildSystemTypeDetector"
interface="org.jetbrains.kotlin.idea.configuration.BuildSystemTypeDetector"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.idePlatformKind"
interface="org.jetbrains.kotlin.platform.IdePlatformKind"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.idePlatformKindTooling"
interface="org.jetbrains.kotlin.idea.platform.IdePlatformKindTooling"/>
</extensionPoints>
<extensions defaultExtensionNs="org.jetbrains.kotlin">
@@ -58,9 +63,9 @@
<scriptDefinitionContributor id="ConsoleScriptDefinitionContributor"
implementation="org.jetbrains.kotlin.console.ConsoleScriptDefinitionContributor"/>
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JvmPlatformSupport"/>
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JsPlatformSupport"/>
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.CommonPlatformSupport"/>
<idePlatformKindResolution implementation="org.jetbrains.kotlin.caches.resolve.JvmPlatformKindResolution"/>
<idePlatformKindResolution implementation="org.jetbrains.kotlin.caches.resolve.JsPlatformKindResolution"/>
<idePlatformKindResolution implementation="org.jetbrains.kotlin.caches.resolve.CommonPlatformKindResolution"/>
<scratchFileLanguageProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.scratch.KtScratchFileLanguageProvider"/>
</extensions>
+5 -5
View File
@@ -7,8 +7,8 @@
interface="org.jetbrains.kotlin.extensions.DeclarationAttributeAltererExtension"
area="IDEA_PROJECT"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.idePlatformSupport"
interface="org.jetbrains.kotlin.caches.resolve.IdePlatformSupport"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.idePlatformKindResolution"
interface="org.jetbrains.kotlin.caches.resolve.IdePlatformKindResolution"/>
<extensionPoint qualifiedName="org.jetbrains.kotlin.highlighterExtension"
interface="org.jetbrains.kotlin.idea.highlighter.HighlighterExtension"/>
@@ -50,9 +50,9 @@
<scriptDefinitionContributor id="ConsoleScriptDefinitionContributor"
implementation="org.jetbrains.kotlin.console.ConsoleScriptDefinitionContributor"/>
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JvmPlatformSupport"/>
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.JsPlatformSupport"/>
<idePlatformSupport implementation="org.jetbrains.kotlin.caches.resolve.CommonPlatformSupport"/>
<idePlatformKindResolution implementation="org.jetbrains.kotlin.caches.resolve.JvmPlatformKindResolution"/>
<idePlatformKindResolution implementation="org.jetbrains.kotlin.caches.resolve.JsPlatformKindResolution"/>
<idePlatformKindResolution implementation="org.jetbrains.kotlin.caches.resolve.CommonPlatformKindResolution"/>
<scratchFileLanguageProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.scratch.KtScratchFileLanguageProvider"/>
</extensions>
+10
View File
@@ -131,6 +131,10 @@
<projectService serviceInterface="org.jetbrains.uast.kotlin.KotlinUastResolveProviderService"
serviceImplementation="org.jetbrains.uast.kotlin.internal.IdeaKotlinUastResolveProviderService"/>
<applicationService
serviceInterface="org.jetbrains.kotlin.platform.DefaultIdeTargetPlatformKindProvider"
serviceImplementation="org.jetbrains.kotlin.platform.impl.IdeaDefaultIdeTargetPlatformKindProvider"/>
</extensions>
<extensions defaultExtensionNs="org.jetbrains.uast">
@@ -158,5 +162,11 @@
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJavaFrameworkSupportProvider" />
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleKotlinDSLKotlinJSFrameworkSupportProvider" />
<gradleFrameworkSupport implementation="org.jetbrains.kotlin.gradle.kdsl.frameworkSupport.GradleGroovyFrameworkSupportProvider" />
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.JsIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JvmIdePlatformKindTooling"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.JsIdePlatformKindTooling"/>
</extensions>
</idea-plugin>
+4
View File
@@ -3106,6 +3106,10 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<binaryExtension implementation="org.jetbrains.kotlin.idea.util.KotlinJsMetaBinary"/>
<highlighterExtension implementation="org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.CommonIdePlatformKindTooling"/>
</extensions>
<extensions defaultExtensionNs="com.intellij.jvm">
+4
View File
@@ -3104,6 +3104,10 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<binaryExtension implementation="org.jetbrains.kotlin.idea.util.KotlinJsMetaBinary"/>
<highlighterExtension implementation="org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.CommonIdePlatformKindTooling"/>
</extensions>
</idea-plugin>
+4
View File
@@ -3105,6 +3105,10 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<binaryExtension implementation="org.jetbrains.kotlin.idea.util.KotlinJsMetaBinary"/>
<highlighterExtension implementation="org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.CommonIdePlatformKindTooling"/>
</extensions>
</idea-plugin>
+4
View File
@@ -3106,6 +3106,10 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<binaryExtension implementation="org.jetbrains.kotlin.idea.util.KotlinJsMetaBinary"/>
<highlighterExtension implementation="org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.CommonIdePlatformKindTooling"/>
</extensions>
<extensions defaultExtensionNs="com.intellij.jvm">
+4
View File
@@ -3104,6 +3104,10 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<binaryExtension implementation="org.jetbrains.kotlin.idea.util.KotlinJsMetaBinary"/>
<highlighterExtension implementation="org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.CommonIdePlatformKindTooling"/>
</extensions>
</idea-plugin>
+4
View File
@@ -3106,6 +3106,10 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<highlighterExtension implementation="org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension"/>
<pluginUpdateVerifier implementation="org.jetbrains.kotlin.idea.update.GooglePluginUpdateVerifier"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.CommonIdePlatformKindTooling"/>
</extensions>
</idea-plugin>
+4
View File
@@ -3108,6 +3108,10 @@ The Kotlin plugin provides language support in IntelliJ IDEA and Android Studio.
<highlighterExtension implementation="org.jetbrains.kotlin.idea.highlighter.dsl.DslHighlighterExtension"/>
<pluginUpdateVerifier implementation="org.jetbrains.kotlin.idea.update.GooglePluginUpdateVerifier"/>
<idePlatformKind implementation="org.jetbrains.kotlin.platform.impl.CommonIdePlatformKind"/>
<idePlatformKindTooling implementation="org.jetbrains.kotlin.idea.core.platform.impl.CommonIdePlatformKindTooling"/>
</extensions>
<extensions defaultExtensionNs="com.intellij.jvm">
@@ -14,18 +14,17 @@ import com.intellij.openapi.vfs.VirtualFile
import com.intellij.psi.ResolveScopeEnlarger
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.SearchScope
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.caches.project.implementingModules
import org.jetbrains.kotlin.idea.project.targetPlatform
import org.jetbrains.kotlin.idea.project.platform
import org.jetbrains.kotlin.platform.impl.isCommon
import org.jetbrains.kotlin.platform.impl.isJvm
class CommonModuleResolveScopeEnlarger : ResolveScopeEnlarger() {
override fun getAdditionalResolveScope(file: VirtualFile, project: Project): SearchScope? {
val module = ProjectFileIndex.getInstance(project).getModuleForFile(file)
if (module?.targetPlatform != TargetPlatformKind.Common) return null
val module = ProjectFileIndex.getInstance(project).getModuleForFile(file) ?: return null
if (!module.platform.isCommon) return null
val implementingModule = module.implementingModules.find {
it.targetPlatform is TargetPlatformKind.Jvm
} ?: return null
val implementingModule = module.implementingModules.find { it.platform.isJvm } ?: return null
var result = GlobalSearchScope.EMPTY_SCOPE
for (entry in ModuleRootManager.getInstance(implementingModule).orderEntries) {
@@ -15,10 +15,8 @@ import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.options.SearchableConfigurable;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ex.ProjectRootManagerEx;
import com.intellij.openapi.ui.TextComponentAccessor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.EmptyRunnable;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.RawCommandLineEditor;
@@ -44,6 +42,11 @@ import org.jetbrains.kotlin.idea.facet.DescriptionListCellRenderer;
import org.jetbrains.kotlin.idea.facet.KotlinFacet;
import org.jetbrains.kotlin.idea.roots.ProjectRootUtilsKt;
import org.jetbrains.kotlin.idea.util.application.ApplicationUtilsKt;
import org.jetbrains.kotlin.platform.IdePlatform;
import org.jetbrains.kotlin.platform.IdePlatformKind;
import org.jetbrains.kotlin.platform.impl.JsIdePlatformUtil;
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformUtil;
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind;
import javax.swing.*;
import java.awt.event.ActionEvent;
@@ -353,7 +356,7 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
@SuppressWarnings("unchecked")
private void fillJvmVersionList() {
for (TargetPlatformKind.Jvm jvm : TargetPlatformKind.Jvm.Companion.getJVM_PLATFORMS()) {
for (IdePlatform<JvmIdePlatformKind, ?> jvm : JvmIdePlatformKind.INSTANCE.getPlatforms()) {
jvmVersionComboBox.addItem(jvm.getVersion().getDescription());
}
}
@@ -384,9 +387,9 @@ public class KotlinCompilerConfigurableTab implements SearchableConfigurable, Co
coroutineSupportComboBox.setRenderer(new DescriptionListCellRenderer());
}
public void setTargetPlatform(@Nullable TargetPlatformKind<?> targetPlatform) {
k2jsPanel.setVisible(TargetPlatformKind.JavaScript.INSTANCE.equals(targetPlatform));
scriptPanel.setVisible(targetPlatform instanceof TargetPlatformKind.Jvm);
public void setTargetPlatform(@Nullable IdePlatformKind<?> targetPlatform) {
k2jsPanel.setVisible(JsIdePlatformUtil.isJavaScript(targetPlatform));
scriptPanel.setVisible(JvmIdePlatformUtil.isJvm(targetPlatform));
}
@SuppressWarnings("unchecked")
@@ -23,12 +23,13 @@ import com.intellij.ui.HoverHyperlinkLabel
import com.intellij.util.ui.FormBuilder
import com.intellij.util.ui.ThreeStateCheckBox
import org.jetbrains.kotlin.cli.common.arguments.*
import org.jetbrains.kotlin.config.CompilerSettings
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.config.createCompilerArguments
import org.jetbrains.kotlin.config.splitArgumentString
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.idea.compiler.configuration.*
import org.jetbrains.kotlin.idea.util.onTextChange
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.platform.impl.isCommon
import org.jetbrains.kotlin.platform.impl.isJavaScript
import org.jetbrains.kotlin.platform.impl.isJvm
import java.awt.BorderLayout
import javax.swing.*
import javax.swing.border.EmptyBorder
@@ -85,7 +86,7 @@ class KotlinFacetEditorGeneralTab(
val useProjectSettingsCheckBox = ThreeStateCheckBox("Use project settings").apply { isThirdStateEnabled = isMultiEditor }
val targetPlatformComboBox =
JComboBox<TargetPlatformKind<*>>(TargetPlatformKind.ALL_PLATFORMS.toTypedArray()).apply {
JComboBox<IdePlatformKind<*>>(IdePlatformKind.ALL_KINDS.toTypedArray()).apply {
setRenderer(DescriptionListCellRenderer())
}
@@ -143,14 +144,14 @@ class KotlinFacetEditorGeneralTab(
compilerConfigurable.reset()
}
private val chosenPlatform: TargetPlatformKind<*>?
get() = targetPlatformComboBox.selectedItem as TargetPlatformKind<*>?
private val chosenPlatform: IdePlatformKind<*>?
get() = targetPlatformComboBox.selectedItem as IdePlatformKind<*>?
}
inner class ArgumentConsistencyValidator : FacetEditorValidator() {
override fun check(): ValidationResult {
val platform = editor.targetPlatformComboBox.selectedItem as TargetPlatformKind<*>? ?: return ValidationResult.OK
val primaryArguments = platform.createCompilerArguments().apply {
val platformKind = editor.targetPlatformComboBox.selectedItem as IdePlatformKind<*>? ?: return ValidationResult.OK
val primaryArguments = platformKind.defaultPlatform.createArguments().apply {
editor.compilerConfigurable.applyTo(
this,
this as? K2JVMCompilerArguments ?: K2JVMCompilerArguments(),
@@ -164,10 +165,10 @@ class KotlinFacetEditorGeneralTab(
validateArguments(errors)?.let { message -> return ValidationResult(message) }
}
val emptyArguments = argumentClass.newInstance()
val fieldNamesToCheck = when (platform) {
is TargetPlatformKind.Jvm -> jvmUIExposedFields
is TargetPlatformKind.JavaScript -> jsUIExposedFields
is TargetPlatformKind.Common-> metadataUIExposedFields
val fieldNamesToCheck = when {
platformKind.isJvm -> jvmUIExposedFields
platformKind.isJavaScript -> jsUIExposedFields
platformKind.isCommon -> metadataUIExposedFields
else -> commonUIExposedFields
}
@@ -266,14 +267,14 @@ class KotlinFacetEditorGeneralTab(
override fun isModified(): Boolean {
if (editor.useProjectSettingsCheckBox.isSelected != configuration.settings.useProjectSettings) return true
if (editor.targetPlatformComboBox.selectedItem != configuration.settings.targetPlatformKind) return true
if (editor.targetPlatformComboBox.selectedItem != configuration.settings.platform) return true
return !editor.useProjectSettingsCheckBox.isSelected && editor.compilerConfigurable.isModified
}
override fun reset() {
validateOnce {
editor.useProjectSettingsCheckBox.isSelected = configuration.settings.useProjectSettings
editor.targetPlatformComboBox.selectedItem = configuration.settings.targetPlatformKind
editor.targetPlatformComboBox.selectedItem = configuration.settings.platform
editor.compilerConfigurable.reset()
editor.updateCompilerConfigurable()
}
@@ -284,14 +285,14 @@ class KotlinFacetEditorGeneralTab(
editor.compilerConfigurable.apply()
with(configuration.settings) {
useProjectSettings = editor.useProjectSettingsCheckBox.isSelected
(editor.targetPlatformComboBox.selectedItem as TargetPlatformKind<*>?)?.let {
if (it != targetPlatformKind) {
val platformArguments = when (it) {
is TargetPlatformKind.Jvm -> editor.compilerConfigurable.k2jvmCompilerArguments
is TargetPlatformKind.JavaScript -> editor.compilerConfigurable.k2jsCompilerArguments
(editor.targetPlatformComboBox.selectedItem as IdePlatformKind<*>?)?.let {
if (it != platform) {
val platformArguments = when {
it.isJvm -> editor.compilerConfigurable.k2jvmCompilerArguments
it.isJavaScript -> editor.compilerConfigurable.k2jsCompilerArguments
else -> null
}
compilerArguments = it.createCompilerArguments {
compilerArguments = it.defaultPlatform.createArguments {
if (platformArguments != null) {
mergeBeans(platformArguments, this)
}
@@ -20,27 +20,24 @@ import com.intellij.openapi.module.Module
import com.intellij.openapi.roots.LibraryOrderEntry
import com.intellij.openapi.roots.ModuleRootManager
import com.intellij.openapi.roots.ModuleRootModel
import com.intellij.openapi.roots.libraries.Library
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.framework.JavaRuntimeDetectionUtil
import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil
import org.jetbrains.kotlin.idea.framework.getCommonRuntimeLibraryVersion
import org.jetbrains.kotlin.idea.platform.tooling
import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion
import org.jetbrains.kotlin.platform.IdePlatformKind
class KotlinVersionInfoProviderByModuleDependencies : KotlinVersionInfoProvider {
override fun getCompilerVersion(module: Module) = bundledRuntimeVersion()
override fun getLibraryVersions(module: Module, targetPlatform: TargetPlatformKind<*>, rootModel: ModuleRootModel?): Collection<String> {
val versionProvider: (Library) -> String? = when (targetPlatform) {
is TargetPlatformKind.JavaScript -> fun(library: Library) = JsLibraryStdDetectionUtil.getJsLibraryStdVersion(library, module.project)
is TargetPlatformKind.Jvm -> JavaRuntimeDetectionUtil::getJavaRuntimeVersion
is TargetPlatformKind.Common -> ::getCommonRuntimeLibraryVersion
}
override fun getLibraryVersions(
module: Module,
platformKind: IdePlatformKind<*>,
rootModel: ModuleRootModel?
): Collection<String> {
val versionProvider = platformKind.tooling.getLibraryVersionProvider(module.project)
return (rootModel ?: ModuleRootManager.getInstance(module))
.orderEntries
.asSequence()
.filterIsInstance<LibraryOrderEntry>()
.mapNotNull { it.library?.let { versionProvider(it) } }
.mapNotNull { libraryEntry -> libraryEntry.library?.let { versionProvider(it) } }
.toList()
}
}
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.facet
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.openapi.projectRoots.JavaSdk
import com.intellij.openapi.projectRoots.JavaSdkVersion
import com.intellij.openapi.projectRoots.ProjectJdkTable
@@ -30,35 +29,37 @@ import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.cli.common.arguments.*
import org.jetbrains.kotlin.compilerRunner.ArgumentUtils
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JsCompilerArgumentsHolder
import org.jetbrains.kotlin.idea.compiler.configuration.Kotlin2JvmCompilerArgumentsHolder
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCommonCompilerArgumentsHolder
import org.jetbrains.kotlin.idea.compiler.configuration.KotlinCompilerSettings
import org.jetbrains.kotlin.idea.configuration.externalCompilerVersion
import org.jetbrains.kotlin.idea.framework.KotlinSdkType
import org.jetbrains.kotlin.idea.platform.tooling
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.versions.*
import org.jetbrains.kotlin.platform.IdePlatform
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind
import kotlin.reflect.KProperty1
private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel?): TargetPlatformKind<*> {
for (platform in TargetPlatformKind.ALL_PLATFORMS) {
private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel?): IdePlatform<*, *> {
for (platform in IdePlatformKind.ALL_KINDS) {
if (getRuntimeLibraryVersions(module, rootModel, platform).isNotEmpty()) {
return platform
//TODO investigate, looks strange
return platform.defaultPlatform
}
}
val sdk = ((rootModel ?: ModuleRootManager.getInstance(module))).sdk
val sdkVersion = (sdk?.sdkType as? JavaSdk)?.getVersion(sdk!!)
val sdkVersion = (sdk?.sdkType as? JavaSdk)?.getVersion(sdk)
return when {
sdkVersion == null || sdkVersion >= JavaSdkVersion.JDK_1_8 -> TargetPlatformKind.Jvm[JvmTarget.JVM_1_8]
else -> TargetPlatformKind.Jvm[JvmTarget.JVM_1_6]
sdkVersion == null || sdkVersion >= JavaSdkVersion.JDK_1_8 -> JvmIdePlatformKind.Platform(JvmTarget.JVM_1_8)
else -> JvmIdePlatformKind.defaultPlatform
}
}
fun KotlinFacetSettings.initializeIfNeeded(
module: Module,
rootModel: ModuleRootModel?,
platformKind: TargetPlatformKind<*>? = null, // if null, detect by module dependencies
platform: IdePlatform<*, *>? = null, // if null, detect by module dependencies
compilerVersion: String? = null
) {
val project = module.project
@@ -73,9 +74,9 @@ fun KotlinFacetSettings.initializeIfNeeded(
val commonArguments = KotlinCommonCompilerArgumentsHolder.getInstance(module.project).settings
if (compilerArguments == null) {
val targetPlatformKind = platformKind ?: getDefaultTargetPlatform(module, rootModel)
compilerArguments = targetPlatformKind.createCompilerArguments {
targetPlatformKind.getPlatformCompilerArgumentsByProject(module.project)?.let { mergeBeans(it, this) }
val targetPlatform = platform ?: getDefaultTargetPlatform(module, rootModel)
compilerArguments = targetPlatform.createArguments {
targetPlatform.kind.tooling.compilerArgumentsForProject(module.project)?.let { mergeBeans(it, this) }
mergeBeans(commonArguments, this)
}
}
@@ -93,7 +94,7 @@ fun KotlinFacetSettings.initializeIfNeeded(
getLibraryLanguageLevel(
module,
rootModel,
targetPlatformKind,
this.platform?.kind,
coerceRuntimeLibraryVersionToReleased = compilerVersion == null
)
)
@@ -101,30 +102,9 @@ fun KotlinFacetSettings.initializeIfNeeded(
}
}
fun TargetPlatformKind<*>.getPlatformCompilerArgumentsByProject(project: Project): CommonCompilerArguments? {
return when (this) {
is TargetPlatformKind.Jvm -> Kotlin2JvmCompilerArgumentsHolder.getInstance(project).settings
is TargetPlatformKind.JavaScript -> Kotlin2JsCompilerArgumentsHolder.getInstance(project).settings
else -> null
}
}
val TargetPlatformKind<*>.mavenLibraryIds: List<String>
get() = when (this) {
is TargetPlatformKind.Jvm -> listOf(
MAVEN_STDLIB_ID,
MAVEN_STDLIB_ID_JRE7,
MAVEN_STDLIB_ID_JDK7,
MAVEN_STDLIB_ID_JRE8,
MAVEN_STDLIB_ID_JDK8
)
is TargetPlatformKind.JavaScript -> listOf(MAVEN_JS_STDLIB_ID, MAVEN_OLD_JS_STDLIB_ID)
is TargetPlatformKind.Common -> listOf(MAVEN_COMMON_STDLIB_ID)
}
val mavenLibraryIdToPlatform: Map<String, TargetPlatformKind<*>> by lazy {
TargetPlatformKind.ALL_PLATFORMS
.flatMap { platform -> platform.mavenLibraryIds.map { it to platform } }
val mavenLibraryIdToPlatform: Map<String, IdePlatformKind<*>> by lazy {
IdePlatformKind.ALL_KINDS
.flatMap { platform -> platform.tooling.mavenLibraryIds.map { it to platform } }
.sortedByDescending { it.first.length }
.toMap()
}
@@ -155,7 +135,7 @@ fun Module.getOrCreateFacet(
fun KotlinFacet.configureFacet(
compilerVersion: String,
coroutineSupport: LanguageFeature.State,
platformKind: TargetPlatformKind<*>?, // if null, detect by module dependencies
platform: IdePlatform<*, *>?, // if null, detect by module dependencies
modelsProvider: IdeModifiableModelsProvider
) {
val module = module
@@ -165,7 +145,7 @@ fun KotlinFacet.configureFacet(
initializeIfNeeded(
module,
modelsProvider.getModifiableRootModel(module),
platformKind,
platform,
compilerVersion
)
val apiLevel = apiLevel
@@ -28,14 +28,14 @@ import com.intellij.psi.*
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.caches.lightClasses.KtFakeLightClass
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.project.targetPlatform
import org.jetbrains.kotlin.idea.project.platform
import org.jetbrains.kotlin.idea.search.allScope
import org.jetbrains.kotlin.idea.stubindex.KotlinClassShortNameIndex
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.platform.impl.isJvm
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtConstructor
import org.jetbrains.kotlin.psi.KtNamedFunction
@@ -46,7 +46,7 @@ import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class KotlinTypeHierarchyProvider : JavaTypeHierarchyProvider() {
private fun getOriginalPsiClassOrCreateLightClass(classOrObject: KtClassOrObject, module: Module?): PsiClass? {
val fqName = classOrObject.fqName
if (fqName != null && module?.targetPlatform is TargetPlatformKind.Jvm) {
if (fqName != null && module?.platform.isJvm) {
val javaClassId = JavaToKotlinClassMap.mapKotlinToJava(fqName.toUnsafe())
if (javaClassId != null) {
return JavaPsiFacade.getInstance(classOrObject.project).findClass(
@@ -16,23 +16,16 @@
package org.jetbrains.kotlin.idea.highlighter
import com.intellij.execution.actions.RunConfigurationProducer
import com.intellij.execution.lineMarker.ExecutorAction
import com.intellij.execution.lineMarker.RunLineMarkerContributor
import com.intellij.icons.AllIcons
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.idea.MainFunctionDetector
import org.jetbrains.kotlin.idea.caches.project.implementingModules
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.project.targetPlatform
import org.jetbrains.kotlin.idea.platform.tooling
import org.jetbrains.kotlin.idea.project.platform
import org.jetbrains.kotlin.idea.util.module
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
class KotlinRunLineMarkerContributor : RunLineMarkerContributor() {
override fun getInfo(element: PsiElement): Info? {
@@ -45,34 +38,12 @@ class KotlinRunLineMarkerContributor : RunLineMarkerContributor() {
}
if (detector.isMain(function)) {
val platform = function.containingKtFile.module?.targetPlatform ?: return null
if (!platform.acceptsAsEntryPoint(function)) return null
val platform = function.containingKtFile.module?.platform ?: return null
if (!platform.kind.tooling.acceptsAsEntryPoint(function)) return null
return RunLineMarkerContributor.Info(AllIcons.RunConfigurations.TestState.Run, null, ExecutorAction.getActions(0))
}
return null
}
private fun TargetPlatformKind<*>.acceptsAsEntryPoint(function: KtNamedFunction): Boolean {
return when (this) {
is TargetPlatformKind.Common -> {
val module = function.containingKtFile.module ?: return false
return module.implementingModules.any { implementingModule ->
implementingModule.targetPlatform?.takeIf { it !is TargetPlatformKind.Common }?.acceptsAsEntryPoint(function) ?: false
}
}
is TargetPlatformKind.Jvm -> true
is TargetPlatformKind.JavaScript -> {
RunConfigurationProducer
.getProducers(function.project)
.asSequence()
.filterIsInstance<KotlinJSRunConfigurationDataProvider<*>>()
.filter { !it.isForTests }
.mapNotNull { it.getConfigurationData(function) }
.firstOrNull() != null
}
}
}
}
@@ -16,127 +16,39 @@
package org.jetbrains.kotlin.idea.highlighter
import com.intellij.codeInsight.TestFrameworks
import com.intellij.execution.TestStateStorage
import com.intellij.execution.actions.RunConfigurationProducer
import com.intellij.execution.lineMarker.ExecutorAction
import com.intellij.execution.lineMarker.RunLineMarkerContributor
import com.intellij.execution.testframework.TestIconMapper
import com.intellij.execution.testframework.sm.runner.states.TestStateInfo
import com.intellij.icons.AllIcons
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.asJava.toLightMethods
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.js.KotlinJSRunConfigurationDataProvider
import org.jetbrains.kotlin.idea.project.targetPlatform
import org.jetbrains.kotlin.idea.platform.tooling
import org.jetbrains.kotlin.idea.project.platform
import org.jetbrains.kotlin.idea.util.projectStructure.module
import org.jetbrains.kotlin.idea.util.string.joinWithEscape
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
import javax.swing.Icon
class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() {
companion object {
private val TEST_FQ_NAME = FqName("kotlin.test.Test")
private val IGNORE_FQ_NAME = FqName("kotlin.test.Ignore")
}
private fun getTestStateIcon(url: String, project: Project): Icon? {
val defaultIcon = AllIcons.RunConfigurations.TestState.Run
val state = TestStateStorage.getInstance(project).getState(url) ?: return defaultIcon
val magnitude = TestIconMapper.getMagnitude(state.magnitude)
return when (magnitude) {
TestStateInfo.Magnitude.ERROR_INDEX,
TestStateInfo.Magnitude.FAILED_INDEX -> AllIcons.RunConfigurations.TestState.Red2
TestStateInfo.Magnitude.PASSED_INDEX,
TestStateInfo.Magnitude.COMPLETE_INDEX -> AllIcons.RunConfigurations.TestState.Green2
else -> defaultIcon
}
}
private fun getJavaTestIcon(declaration: KtNamedDeclaration): Icon? {
val (url, framework) = when (declaration) {
is KtClassOrObject -> {
val lightClass = declaration.toLightClass() ?: return null
val framework = TestFrameworks.detectFramework(lightClass) ?: return null
if (!framework.isTestClass(lightClass)) return null
val qualifiedName = lightClass.qualifiedName ?: return null
"java:suite://$qualifiedName" to framework
fun getTestStateIcon(url: String, project: Project): Icon? {
val defaultIcon = AllIcons.RunConfigurations.TestState.Run
val state = TestStateStorage.getInstance(project).getState(url) ?: return defaultIcon
val magnitude = TestIconMapper.getMagnitude(state.magnitude)
return when (magnitude) {
TestStateInfo.Magnitude.ERROR_INDEX,
TestStateInfo.Magnitude.FAILED_INDEX -> AllIcons.RunConfigurations.TestState.Red2
TestStateInfo.Magnitude.PASSED_INDEX,
TestStateInfo.Magnitude.COMPLETE_INDEX -> AllIcons.RunConfigurations.TestState.Green2
else -> defaultIcon
}
is KtNamedFunction -> {
val lightMethod = declaration.toLightMethods().firstOrNull() ?: return null
val lightClass = lightMethod.containingClass as? KtLightClass ?: return null
val framework = TestFrameworks.detectFramework(lightClass) ?: return null
if (!framework.isTestMethod(lightMethod)) return null
"java:test://${lightClass.qualifiedName}.${lightMethod.name}" to framework
}
else -> return null
}
return getTestStateIcon(url, declaration.project) ?: framework.icon
}
private fun DeclarationDescriptor.isIgnored(): Boolean =
annotations.any { it.fqName == IGNORE_FQ_NAME } || ((containingDeclaration as? ClassDescriptor)?.isIgnored() ?: false)
private fun DeclarationDescriptor.isTest(): Boolean {
if (isIgnored()) return false
if (annotations.any { it.fqName == TEST_FQ_NAME }) return true
if (this is ClassDescriptorWithResolutionScopes) {
return declaredCallableMembers.any { it.isTest() }
}
return false
}
private fun getJavaScriptTestIcon(declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor): Icon? {
if (!descriptor.isTest()) return null
val runConfigData = RunConfigurationProducer
.getProducers(declaration.project)
.asSequence()
.filterIsInstance<KotlinJSRunConfigurationDataProvider<*>>()
.filter { it.isForTests }
.mapNotNull { it.getConfigurationData(declaration) }
.firstOrNull() ?: return null
val locations = ArrayList<String>()
locations += FileUtil.toSystemDependentName(runConfigData.jsOutputFilePath)
val klass = when (declaration) {
is KtClassOrObject -> declaration
is KtNamedFunction -> declaration.containingClassOrObject ?: return null
else -> return null
}
locations += klass.parentsWithSelf.filterIsInstance<KtNamedDeclaration>().mapNotNull { it.name }.toList().asReversed()
val testName = (declaration as? KtNamedFunction)?.name
if (testName != null) {
locations += "$testName"
}
val prefix = if (testName != null) "test://" else "suite://"
val url = prefix + locations.joinWithEscape('.')
return getTestStateIcon(url, declaration.project)
}
override fun getInfo(element: PsiElement): RunLineMarkerContributor.Info? {
@@ -150,23 +62,8 @@ class KotlinTestRunLineMarkerContributor : RunLineMarkerContributor() {
// To prevent IDEA failing on red code
val descriptor = declaration.resolveToDescriptorIfAny() ?: return null
val icon = getTestIcon(declaration, descriptor) ?: return null
val targetPlatform = declaration.module?.platform ?: return null
val icon = targetPlatform.kind.tooling.getTestIcon(declaration, descriptor) ?: return null
return RunLineMarkerContributor.Info(icon, { "Run Test" }, ExecutorAction.getActions())
}
private fun getTestIcon(declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor): Icon? {
val module = declaration.module ?: return null
val targetPlatformKind = module.targetPlatform ?: return null
return when (targetPlatformKind) {
is TargetPlatformKind.JavaScript -> getJavaScriptTestIcon(declaration, descriptor)
is TargetPlatformKind.Jvm -> getJavaTestIcon(declaration)
is TargetPlatformKind.Common -> {
val icons = listOfNotNull(getJavaScriptTestIcon(declaration, descriptor), getJavaTestIcon(declaration))
when (icons.size) {
0 -> null
else -> icons.distinct().singleOrNull() ?: AllIcons.RunConfigurations.TestState.Run
}
}
}
}
}
@@ -0,0 +1,68 @@
/*
* Copyright 2010-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license
* that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.idea.platform
import com.intellij.openapi.project.Project
import com.intellij.openapi.roots.libraries.Library
import com.intellij.openapi.roots.libraries.PersistentLibraryKind
import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription
import org.jetbrains.kotlin.extensions.ApplicationExtensionDescriptor
import org.jetbrains.kotlin.analyzer.ResolverForModuleFactory
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.platform.IdePlatformKind
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.psi.KtNamedDeclaration
import javax.swing.Icon
abstract class IdePlatformKindTooling {
abstract val kind: IdePlatformKind<*>
abstract fun compilerArgumentsForProject(project: Project): CommonCompilerArguments?
abstract val resolverForModuleFactory: ResolverForModuleFactory
abstract val mavenLibraryIds: List<String>
abstract val gradlePluginId: String
abstract val libraryKind: PersistentLibraryKind<*>?
abstract fun getLibraryDescription(project: Project): CustomLibraryDescription
abstract fun getLibraryVersionProvider(project: Project): (Library) -> String?
abstract fun getTestIcon(declaration: KtNamedDeclaration, descriptor: DeclarationDescriptor): Icon?
abstract fun acceptsAsEntryPoint(function: KtFunction): Boolean
override fun equals(other: Any?): Boolean = javaClass == other?.javaClass
override fun hashCode(): Int = javaClass.hashCode()
companion object : ApplicationExtensionDescriptor<IdePlatformKindTooling>(
"org.jetbrains.kotlin.idePlatformKindTooling", IdePlatformKindTooling::class.java
) {
private val CACHED_TOOLING_SUPPORT by lazy {
val allPlatformKinds = IdePlatformKind.ALL_KINDS
val groupedTooling = IdePlatformKindTooling.getInstances().groupBy { it.kind }.mapValues { it.value.single() }
for (kind in allPlatformKinds) {
if (kind !in groupedTooling) {
throw IllegalStateException(
"Tooling support for the platform '$kind' is missing. " +
"Implement 'IdePlatformKindTooling' for it."
)
}
}
groupedTooling
}
fun getTooling(kind: IdePlatformKind<*>): IdePlatformKindTooling {
return CACHED_TOOLING_SUPPORT[kind] ?: error("Unknown platform $this")
}
}
}
val IdePlatformKind<*>.tooling: IdePlatformKindTooling
get() = IdePlatformKindTooling.getTooling(this)
@@ -137,7 +137,7 @@ class KotlinNonJvmSourceRootConverterProvider : ConverterProvider("kotlin-non-jv
getFacetElement(KotlinFacetType.ID)
?.getChild(JpsFacetSerializer.CONFIGURATION_TAG)
?.getFacetPlatformByConfigurationElement()
?.asTargetPlatform()
?.kind?.compilerPlatform
private fun ModuleSettings.detectPlatformByDependencies(): TargetPlatform? {
var hasCommonStdlib = false
@@ -17,10 +17,6 @@ import org.jetbrains.jps.model.module.JpsModuleSourceRoot
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
import org.jetbrains.kotlin.config.KotlinResourceRootType
import org.jetbrains.kotlin.config.KotlinSourceRootType
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
private fun JpsModuleSourceRoot.getOrCreateProperties() =
getProperties(rootType)?.also { (it as? JpsElementBase<*>)?.setParent(null) } ?: rootType.createDefaultProperties()
@@ -49,12 +45,6 @@ fun migrateNonJvmSourceFolders(modifiableRootModel: ModifiableRootModel) {
}
}
fun TargetPlatformKind<*>.asTargetPlatform() = when (this) {
is TargetPlatformKind.Jvm -> JvmPlatform
is TargetPlatformKind.JavaScript -> JsPlatform
is TargetPlatformKind.Common -> TargetPlatform.Common
}
fun Project.invalidateProjectRoots() {
ProjectRootManagerEx.getInstanceEx(this).makeRootsChange(EmptyRunnable.INSTANCE, false, true)
}
@@ -269,8 +269,7 @@ const val MAVEN_STDLIB_ID_JDK8 = PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME
const val MAVEN_JS_STDLIB_ID = PathUtil.JS_LIB_NAME
const val MAVEN_JS_TEST_ID = PathUtil.KOTLIN_TEST_JS_NAME
const val MAVEN_OLD_JS_STDLIB_ID = "kotlin-js-library"
const val MAVEN_COMMON_STDLIB_ID = "kotlin-stdlib-common" // TODO: KotlinCommonMavenConfigurator
const val MAVEN_TEST_ID = PathUtil.KOTLIN_TEST_NAME
const val MAVEN_TEST_JUNIT_ID = "kotlin-test-junit"
const val MAVEN_COMMON_TEST_ID = "kotlin-test-common"