[Platform API] Introduce fundamental abstraction of Platform

This is a large commit, which introduces general API for working with
abstraction of Platform.

- Add new abstraction to 'core' - SimplePlatform - which represents
exactly one platform
  - Clients are strongly prohibited to create instances of SimplePlatform
  by hand, instead, corresponding *Platforms abstraction should be used
  (e.g. JvmPlatforms, JsPlatforms, KonanPlatforms)

- Move TargetPlatform to 'core', it represents now a collection of
SimplePlatforms
  - Clients are strongly encouraged to use TargetPlatform
    (not SimplePlatform) in API, to enforce checks for multiplatform

- Provide a helper-extensions to work with TargetPlatform
(in particular, for getting a specific component platform)

- Remove MultiTargetPlatform in favour of TargetPlatform
  - Notably, this commit leaves another widely used duplicated abstraction,
    namely, IdePlatform. For the sake sanity, removal of IdePlatform is
    extracted in the separate commit.
This commit is contained in:
Dmitry Savvinov
2019-04-24 11:59:07 +03:00
parent 451d14e504
commit d5fbe59a3e
162 changed files with 832 additions and 711 deletions
@@ -12,8 +12,8 @@ import com.intellij.openapi.ui.Messages
import com.intellij.util.PlatformUtils
import org.jetbrains.kotlin.idea.configuration.*
import org.jetbrains.kotlin.idea.util.projectStructure.allModules
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.js.isJs
import org.jetbrains.kotlin.platform.jvm.isJvm
abstract class ConfigureKotlinInProjectAction : AnAction() {
@@ -44,7 +44,7 @@ abstract class ConfigureKotlinInProjectAction : AnAction() {
class ConfigureKotlinJsInProjectAction: ConfigureKotlinInProjectAction() {
override fun getApplicableConfigurators(project: Project) = getAbleToRunConfigurators(project).filter {
it.targetPlatform == JsPlatform
it.targetPlatform.isJs()
}
override fun update(e: AnActionEvent) {
@@ -57,6 +57,6 @@ class ConfigureKotlinJsInProjectAction: ConfigureKotlinInProjectAction() {
class ConfigureKotlinJavaInProjectAction: ConfigureKotlinInProjectAction() {
override fun getApplicableConfigurators(project: Project) = getAbleToRunConfigurators(project).filter {
it.targetPlatform is JvmPlatform
it.targetPlatform.isJvm()
}
}
@@ -40,8 +40,8 @@ import org.jetbrains.kotlin.idea.util.projectStructure.sdk
import org.jetbrains.kotlin.idea.util.projectStructure.version
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
import org.jetbrains.kotlin.platform.impl.JvmIdePlatformKind
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
open class KotlinJavaModuleConfigurator protected constructor() : KotlinWithLibraryConfigurator() {
override fun isApplicable(module: Module): Boolean {
@@ -71,7 +71,7 @@ open class KotlinJavaModuleConfigurator protected constructor() : KotlinWithLibr
get() = NAME
override val targetPlatform: TargetPlatform
get() = JvmPlatform
get() = JvmPlatforms.defaultJvmPlatform
override fun getLibraryJarDescriptors(sdk: Sdk?): List<LibraryJarDescriptor> {
var result = listOf(
@@ -32,15 +32,15 @@ import org.jetbrains.kotlin.idea.framework.JsLibraryStdDetectionUtil
import org.jetbrains.kotlin.idea.util.application.runWriteAction
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
import org.jetbrains.kotlin.js.JavaScript
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms
open class KotlinJsModuleConfigurator : KotlinWithLibraryConfigurator() {
override val name: String
get() = NAME
override val targetPlatform: TargetPlatform
get() = JsPlatform
get() = JsPlatforms.defaultJsPlatform
override val presentableText: String
get() = JavaScript.FULL_NAME
@@ -24,7 +24,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.config.ApiVersion
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.idea.versions.LibraryJarDescriptor
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.platform.TargetPlatform
enum class ConfigureKotlinStatus {
/** Kotlin is correctly configured using this configurator. */
@@ -35,7 +35,7 @@ import org.jetbrains.kotlin.idea.versions.SuppressNotificationState
import org.jetbrains.kotlin.idea.versions.UnsupportedAbiVersionNotificationPanelProvider
import org.jetbrains.kotlin.idea.versions.createComponentActionLabel
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.isJvm
// Code is partially copied from com.intellij.codeInsight.daemon.impl.SetupSDKNotificationProvider
class KotlinSetupEnvironmentNotificationProvider(
@@ -68,7 +68,8 @@ class KotlinSetupEnvironmentNotificationProvider(
}
if (ModuleRootManager.getInstance(module).sdk == null &&
TargetPlatformDetector.getPlatform(psiFile) == JvmPlatform) {
TargetPlatformDetector.getPlatform(psiFile).isJvm()
) {
return createSetupSdkPanel(myProject, psiFile)
}
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.idea.debugger.evaluate
import org.jetbrains.kotlin.analyzer.common.CommonPlatform
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -27,7 +26,8 @@ import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.DescriptorFactory
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.SyntheticScope
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
@@ -78,7 +78,7 @@ class DebuggerFieldSyntheticScope(val javaSyntheticPropertiesScope: JavaSyntheti
val containingFile = element.containingFile?.takeIf { it.isValid } as? KtFile ?: return false
val platform = containingFile.platform
if (platform !is JvmPlatform && platform !is CommonPlatform) {
if (!platform.isJvm() && !platform.isCommon()) {
return false
}
@@ -28,6 +28,8 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.externalDescriptors
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.Variance
@@ -176,6 +178,9 @@ private object DebugLabelModuleDescriptor
}
}
override val platform: TargetPlatform?
get() = JvmPlatforms.defaultJvmPlatform
override fun getSubPackagesOf(fqName: FqName, nameFilter: (Name) -> Boolean): Collection<FqName> {
return emptyList()
}
@@ -24,14 +24,14 @@ import com.intellij.openapi.projectRoots.SdkTypeId
import com.intellij.openapi.roots.ModifiableRootModel
import com.intellij.openapi.roots.ui.configuration.ModulesProvider
import org.jetbrains.kotlin.idea.roots.migrateNonJvmSourceFolders
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.idea.statistics.FUSEventGroups
import org.jetbrains.kotlin.idea.statistics.KotlinFUSLogger
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import javax.swing.Icon
class KotlinModuleBuilder(
val targetPlatform: TargetPlatform, val builderName: String, val builderDescription: String, val icon: Icon
val targetPlatform: TargetPlatform, val builderName: String, val builderDescription: String, val icon: Icon
) : JavaModuleBuilder() {
private var wizardContext: WizardContext? = null
@@ -51,15 +51,15 @@ class KotlinModuleBuilder(
return KotlinModuleSettingStep(targetPlatform, this, settingsStep, wizardContext)
}
override fun isSuitableSdkType(sdkType: SdkTypeId?) = when (targetPlatform) {
is JvmPlatform -> super.isSuitableSdkType(sdkType)
override fun isSuitableSdkType(sdkType: SdkTypeId?) = when {
targetPlatform.isJvm() -> super.isSuitableSdkType(sdkType)
else -> sdkType is KotlinSdkType
}
override fun setupRootModel(rootModel: ModifiableRootModel) {
KotlinFUSLogger.log(FUSEventGroups.NPWizards, this.javaClass.simpleName + ": ${this.targetPlatform}")
super.setupRootModel(rootModel)
if (targetPlatform !is JvmPlatform) {
if (!targetPlatform.isJvm()) {
migrateNonJvmSourceFolders(rootModel)
}
}
@@ -46,9 +46,10 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.idea.formatter.KotlinStyleGuideCodeStyle;
import org.jetbrains.kotlin.idea.formatter.ProjectCodeStyleImporter;
import org.jetbrains.kotlin.js.resolve.JsPlatform;
import org.jetbrains.kotlin.resolve.TargetPlatform;
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
import org.jetbrains.kotlin.platform.TargetPlatform;
import org.jetbrains.kotlin.platform.TargetPlatformKt;
import org.jetbrains.kotlin.platform.js.JsPlatformKt;
import org.jetbrains.kotlin.platform.jvm.JvmPlatformKt;
import javax.swing.*;
import java.lang.reflect.Field;
@@ -83,7 +84,7 @@ public class KotlinModuleSettingStep extends ModuleWizardStep {
) {
isNewProject = wizardContext != null && wizardContext.isCreatingNewProject();
if (!(targetPlatform instanceof JvmPlatform)) {
if (!(JvmPlatformKt.isJvm(targetPlatform))) {
KotlinSdkType.Companion.setUpIfNeeded();
}
@@ -139,15 +140,15 @@ public class KotlinModuleSettingStep extends ModuleWizardStep {
@NotNull
protected String getLibraryLabelText() {
if (targetPlatform == JvmPlatform.INSTANCE) return "Kotlin runtime";
if (targetPlatform == JsPlatform.INSTANCE) return "Kotlin JS library";
if (JvmPlatformKt.isJvm(targetPlatform)) return "Kotlin runtime";
if (JsPlatformKt.isJs(targetPlatform)) return "Kotlin JS library";
throw new IllegalStateException("Only JS and JVM target are supported");
}
@NotNull
protected CustomLibraryDescription getCustomLibraryDescription(@Nullable Project project) {
if (targetPlatform == JvmPlatform.INSTANCE) return new JavaRuntimeLibraryDescription(project);
if (targetPlatform == JsPlatform.INSTANCE) return new JSLibraryStdDescription(project);
if (JvmPlatformKt.isJvm(targetPlatform)) return new JavaRuntimeLibraryDescription(project);
if (JsPlatformKt.isJs(targetPlatform)) return new JSLibraryStdDescription(project);
throw new IllegalStateException("Only JS and JVM target are supported");
}
@@ -24,8 +24,8 @@ import com.intellij.platform.ProjectTemplate
import com.intellij.platform.ProjectTemplatesFactory
import com.intellij.platform.templates.BuilderBasedTemplate
import org.jetbrains.kotlin.idea.KotlinIcons
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
class KotlinTemplatesFactory : ProjectTemplatesFactory() {
companion object {
@@ -39,15 +39,22 @@ class KotlinTemplatesFactory : ProjectTemplatesFactory() {
override fun createTemplates(group: String?, context: WizardContext?): Array<out ProjectTemplate> {
val result = mutableListOf<ProjectTemplate>(
BuilderBasedTemplate(KotlinModuleBuilder(JvmPlatform,
"JVM | IDEA",
"Kotlin project with a JVM target based on the IntelliJ IDEA build system",
KotlinIcons.SMALL_LOGO)),
BuilderBasedTemplate(KotlinModuleBuilder(JsPlatform, "JS | IDEA",
"Kotlin project with a JavaScript target based on the IntelliJ IDEA build system",
KotlinIcons.JS)
BuilderBasedTemplate(
KotlinModuleBuilder(
JvmPlatforms.defaultJvmPlatform,
"JVM | IDEA",
"Kotlin project with a JVM target based on the IntelliJ IDEA build system",
KotlinIcons.SMALL_LOGO
)
),
BuilderBasedTemplate(
KotlinModuleBuilder(
JsPlatforms.defaultJsPlatform, "JS | IDEA",
"Kotlin project with a JavaScript target based on the IntelliJ IDEA build system",
KotlinIcons.JS
)
)
)
result.addAll(Extensions.getExtensions(EP_NAME).map { BuilderBasedTemplate(it) })
return result.toTypedArray()
@@ -21,7 +21,6 @@ import com.intellij.openapi.util.Pair
import com.intellij.openapi.util.text.StringUtil
import com.intellij.openapi.wm.ToolWindow
import com.intellij.util.Alarm
import org.jetbrains.kotlin.analyzer.common.CommonPlatform
import org.jetbrains.kotlin.backend.common.phaser.PhaseConfig
import org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory
import org.jetbrains.kotlin.backend.jvm.jvmPhases
@@ -43,7 +42,10 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtCodeFragment
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.psi.KtScript
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.platform.isCommon
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.utils.join
import java.awt.BorderLayout
import java.awt.FlowLayout
@@ -281,10 +283,10 @@ class KotlinBytecodeToolWindow(private val myProject: Project, private val toolW
configuration: CompilerConfiguration
): GenerationState? {
val platform = ktFile.platform
if (platform !is CommonPlatform && platform !is JvmPlatform) return null
if (!platform.isCommon() && !platform.isJvm()) return null
val resolutionFacade = KotlinCacheService.getInstance(ktFile.project)
.getResolutionFacadeByFile(ktFile, JvmPlatform)
.getResolutionFacadeByFile(ktFile, JvmPlatforms.defaultJvmPlatform)
?: return null
val bindingContextForFile = resolutionFacade.analyzeWithAllCompilerChecks(listOf(ktFile)).bindingContext
@@ -41,7 +41,7 @@ import org.jetbrains.kotlin.asJava.LightClassUtilsKt;
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector;
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform;
import org.jetbrains.kotlin.platform.jvm.JvmPlatformKt;
import java.util.List;
@@ -116,7 +116,7 @@ public class KotlinTestNgConfigurationProducer extends TestNGConfigurationProduc
KtFile ktFile = (KtFile) leaf.getContainingFile();
if (TargetPlatformDetector.getPlatform(ktFile) != JvmPlatform.INSTANCE) {
if (!JvmPlatformKt.isJvm(TargetPlatformDetector.getPlatform(ktFile))) {
return false;
}
@@ -37,9 +37,9 @@ import org.jetbrains.kotlin.idea.KotlinPluginUpdater
import org.jetbrains.kotlin.idea.KotlinPluginUtil
import org.jetbrains.kotlin.idea.PluginUpdateStatus
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.js.resolve.JsPlatform
import org.jetbrains.kotlin.metadata.deserialization.BinaryVersion
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.js.isJs
import org.jetbrains.kotlin.platform.jvm.isJvm
import java.awt.event.ComponentAdapter
import java.awt.event.ComponentEvent
import java.text.MessageFormat
@@ -325,9 +325,10 @@ class UnsupportedAbiVersionNotificationPanelProvider(private val project: Projec
}
fun collectBadRoots(module: Module): Collection<BinaryVersionedFile<BinaryVersion>> {
val badRoots = when (TargetPlatformDetector.getPlatform(module)) {
JvmPlatform -> getLibraryRootsWithAbiIncompatibleKotlinClasses(module)
JsPlatform -> getLibraryRootsWithAbiIncompatibleForKotlinJs(module)
val platform = TargetPlatformDetector.getPlatform(module)
val badRoots = when {
platform.isJvm() -> getLibraryRootsWithAbiIncompatibleKotlinClasses(module)
platform.isJs() -> getLibraryRootsWithAbiIncompatibleForKotlinJs(module)
else -> return emptyList()
}