[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
@@ -33,7 +33,7 @@ import org.jetbrains.kotlin.idea.resolve.ResolutionFacade
import org.jetbrains.kotlin.load.java.JvmAnnotationNames
import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
import org.jetbrains.kotlin.resolve.scopes.MemberScope
import org.jetbrains.kotlin.resolve.scopes.getDescriptorsFiltered
@@ -68,7 +68,7 @@ class AllClassesCompletion(private val parameters: CompletionParameters,
.forEach { classifierDescriptorCollector(it) }
}
if (TargetPlatformDetector.getPlatform(parameters.originalFile as KtFile) == JvmPlatform) {
if (TargetPlatformDetector.getPlatform(parameters.originalFile as KtFile).isJvm()) {
addAdaptedJavaCompletion(javaClassCollector)
}
}
@@ -60,7 +60,7 @@ import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.renderer.render
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.descriptorUtil.*
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindExclude
import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter
@@ -270,7 +270,7 @@ class BasicCompletionSession(
val packageNames = PackageIndexUtil.getSubPackageFqNames(FqName.ROOT, searchScope, project, prefixMatcher.asNameFilter())
.toMutableSet()
if (TargetPlatformDetector.getPlatform(parameters.originalFile as KtFile) == JvmPlatform) {
if (TargetPlatformDetector.getPlatform(parameters.originalFile as KtFile).isJvm()) {
JavaPsiFacade.getInstance(project).findPackage("")?.getSubPackages(searchScope)?.forEach { psiPackage ->
val name = psiPackage.name
if (Name.isValidIdentifier(name!!)) {
@@ -28,7 +28,6 @@ import com.intellij.patterns.PatternCondition
import com.intellij.patterns.StandardPatterns
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.util.ProcessingContext
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.idea.caches.project.ModuleOrigin
import org.jetbrains.kotlin.idea.caches.project.OriginCapability
@@ -38,15 +37,13 @@ import org.jetbrains.kotlin.idea.codeInsight.ReferenceVariantsHelper
import org.jetbrains.kotlin.idea.core.*
import org.jetbrains.kotlin.idea.imports.importableFqName
import org.jetbrains.kotlin.idea.project.TargetPlatformDetector
import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.idea.util.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.MultiTargetPlatform
import org.jetbrains.kotlin.resolve.descriptorUtil.module
import org.jetbrains.kotlin.resolve.getMultiTargetPlatform
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.receivers.ExpressionReceiver
import org.jetbrains.kotlin.types.TypeUtils
@@ -88,7 +85,7 @@ abstract class CompletionSession(
protected val resolutionFacade = file.getResolutionFacade()
protected val moduleDescriptor = resolutionFacade.moduleDescriptor
protected val project = position.project
protected val isJvmModule = TargetPlatformDetector.getPlatform(parameters.originalFile as KtFile) == JvmPlatform
protected val isJvmModule = TargetPlatformDetector.getPlatform(parameters.originalFile as KtFile).isJvm()
protected val isDebuggerContext = file is KtCodeFragment
protected val nameExpression: KtSimpleNameExpression?
@@ -149,7 +146,7 @@ abstract class CompletionSession(
{ CompletionBenchmarkSink.instance.onFlush(this) },
prefixMatcher, parameters, resultSet,
createSorter(), (file as? KtCodeFragment)?.extraCompletionFilter,
moduleDescriptor.getMultiTargetPlatform() === MultiTargetPlatform.Common
moduleDescriptor.platform.isCommon()
)
}
@@ -7,10 +7,10 @@ package org.jetbrains.kotlin.idea.completion.test
import com.intellij.codeInsight.completion.CompletionType
import org.jetbrains.kotlin.idea.test.SdkAndMockLibraryProjectDescriptor
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
abstract class AbstractCompiledKotlinInJavaCompletionTest : KotlinFixtureCompletionBaseTestCase() {
override fun getPlatform() = JvmPlatform
override fun getPlatform() = JvmPlatforms.defaultJvmPlatform
override fun getProjectDescriptor() =
SdkAndMockLibraryProjectDescriptor(COMPLETION_TEST_DATA_BASE_PATH + "/injava/mockLib", false)
@@ -12,7 +12,7 @@ import org.jetbrains.kotlin.idea.completion.CompletionBindingContextProvider
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.io.File
@@ -82,7 +82,7 @@ abstract class AbstractCompletionIncrementalResolveTest : KotlinLightCodeInsight
}
testCompletion(FileUtil.loadFile(file, true),
JvmPlatform,
JvmPlatforms.defaultJvmPlatform,
{ completionType, count -> myFixture.complete(completionType, count) },
additionalValidDirectives = listOf(TYPE_DIRECTIVE_PREFIX, BACKSPACES_DIRECTIVE_PREFIX))
@@ -9,8 +9,8 @@ import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.test.KotlinStdJSProjectDescriptor;
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;
public abstract class AbstractJSBasicCompletionTest extends KotlinFixtureCompletionBaseTestCase {
@NotNull
@@ -22,7 +22,7 @@ public abstract class AbstractJSBasicCompletionTest extends KotlinFixtureComplet
@NotNull
@Override
public TargetPlatform getPlatform() {
return JsPlatform.INSTANCE;
return JsPlatforms.INSTANCE.getDefaultJsPlatform();
}
@NotNull
@@ -9,8 +9,8 @@ import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor;
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;
public abstract class AbstractJvmBasicCompletionTest extends KotlinFixtureCompletionBaseTestCase {
@NotNull
@@ -22,7 +22,7 @@ public abstract class AbstractJvmBasicCompletionTest extends KotlinFixtureComple
@NotNull
@Override
public TargetPlatform getPlatform() {
return JvmPlatform.INSTANCE;
return JvmPlatforms.INSTANCE.getDefaultJvmPlatform();
}
@NotNull
@@ -9,8 +9,8 @@ import com.intellij.codeInsight.completion.CompletionType;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor;
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;
public abstract class AbstractJvmSmartCompletionTest extends KotlinFixtureCompletionBaseTestCase {
@NotNull
@@ -22,7 +22,7 @@ public abstract class AbstractJvmSmartCompletionTest extends KotlinFixtureComple
@NotNull
@Override
public TargetPlatform getPlatform() {
return JvmPlatform.INSTANCE;
return JvmPlatforms.INSTANCE.getDefaultJvmPlatform();
}
@NotNull
@@ -9,7 +9,7 @@ import com.intellij.codeInsight.completion.CompletionType
import com.intellij.testFramework.LightProjectDescriptor
import org.jetbrains.kotlin.idea.test.SdkAndMockLibraryProjectDescriptor
import org.jetbrains.kotlin.idea.test.PluginTestCaseBase
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
abstract class AbstractJvmWithLibBasicCompletionTest : KotlinFixtureCompletionBaseTestCase() {
private val TEST_PATH = COMPLETION_TEST_DATA_BASE_PATH + "/basic/withLib"
@@ -21,6 +21,6 @@ abstract class AbstractJvmWithLibBasicCompletionTest : KotlinFixtureCompletionBa
return SdkAndMockLibraryProjectDescriptor(TEST_PATH + "/" + getTestName(false) + "Src", false)
}
override fun getPlatform() = JvmPlatform
override fun getPlatform() = JvmPlatforms.defaultJvmPlatform
override fun defaultCompletionType() = CompletionType.BASIC
}
@@ -10,10 +10,10 @@ import com.intellij.codeInsight.lookup.LookupElement
import org.jetbrains.kotlin.idea.completion.KeywordLookupObject
import org.jetbrains.kotlin.idea.test.KotlinLightProjectDescriptor
import org.jetbrains.kotlin.idea.test.KotlinProjectDescriptorWithFacet
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
abstract class AbstractKeywordCompletionTest : KotlinFixtureCompletionBaseTestCase() {
override fun getPlatform() = JvmPlatform
override fun getPlatform() = JvmPlatforms.defaultJvmPlatform
override fun defaultCompletionType() = CompletionType.BASIC
@@ -7,14 +7,12 @@ package org.jetbrains.kotlin.idea.completion.test
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.vfs.VirtualFile
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
import org.apache.commons.io.FileUtils
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import java.io.File
abstract class AbstractKotlinSourceInJavaCompletionTest : KotlinFixtureCompletionBaseTestCase() {
override fun getPlatform() = JvmPlatform
override fun getPlatform() = JvmPlatforms.defaultJvmPlatform
override fun doTest(testPath: String) {
val mockPath = RELATIVE_COMPLETION_TEST_DATA_BASE_PATH + "/injava/mockLib"
@@ -7,10 +7,10 @@ package org.jetbrains.kotlin.idea.completion.test
import com.intellij.codeInsight.completion.CompletionType
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
abstract class AbstractKotlinStdLibInJavaCompletionTest : KotlinFixtureCompletionBaseTestCase() {
override fun getPlatform() = JvmPlatform
override fun getPlatform() = JvmPlatforms.defaultJvmPlatform
override fun getProjectDescriptor() = KotlinWithJdkAndRuntimeLightProjectDescriptor.INSTANCE
override fun defaultCompletionType() = CompletionType.BASIC
}
@@ -7,14 +7,14 @@ package org.jetbrains.kotlin.idea.completion.test
import com.intellij.codeInsight.completion.CompletionType
import org.jetbrains.kotlin.idea.test.AstAccessControl
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
abstract class AbstractMultiFileJvmBasicCompletionTest : KotlinCompletionTestCase() {
protected fun doTest(testPath: String) {
configureByFile(getTestName(false) + ".kt", "")
val shouldFail = testPath.contains("NoSpecifiedType")
AstAccessControl.testWithControlledAccessToAst(shouldFail, getFile().getVirtualFile(), getProject(), getTestRootDisposable(), {
testCompletion(file.text, JvmPlatform, { completionType, invocationCount ->
testCompletion(file.text, JvmPlatforms.defaultJvmPlatform, { completionType, invocationCount ->
setType(completionType)
complete(invocationCount)
myItems
@@ -7,7 +7,7 @@ package org.jetbrains.kotlin.idea.completion.test
import com.intellij.codeInsight.completion.CompletionType
import org.jetbrains.kotlin.idea.test.AstAccessControl
import org.jetbrains.kotlin.resolve.jvm.platform.JvmPlatform
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
abstract class AbstractMultiFileSmartCompletionTest : KotlinCompletionTestCase() {
override fun setUp() {
@@ -18,7 +18,7 @@ abstract class AbstractMultiFileSmartCompletionTest : KotlinCompletionTestCase()
protected fun doTest(testPath: String) {
configureByFile(getTestName(false) + ".kt", "")
AstAccessControl.testWithControlledAccessToAst(false, getFile().getVirtualFile(), getProject(), getTestRootDisposable(), {
testCompletion(file.text, JvmPlatform, { completionType, invocationCount ->
testCompletion(file.text, JvmPlatforms.defaultJvmPlatform, { completionType, invocationCount ->
setType(completionType)
complete(invocationCount)
myItems
@@ -8,7 +8,7 @@ package org.jetbrains.kotlin.idea.completion.test
import com.intellij.codeInsight.CodeInsightSettings
import com.intellij.codeInsight.completion.CompletionType
import com.intellij.codeInsight.lookup.LookupElement
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.junit.Assert
@@ -17,12 +17,12 @@ val RELATIVE_COMPLETION_TEST_DATA_BASE_PATH = "idea/idea-completion/testData"
val COMPLETION_TEST_DATA_BASE_PATH = KotlinTestUtils.getHomeDirectory() + "/" + RELATIVE_COMPLETION_TEST_DATA_BASE_PATH
fun testCompletion(
fileText: String,
platform: TargetPlatform?,
complete: (CompletionType, Int) -> Array<LookupElement>?,
defaultCompletionType: CompletionType = CompletionType.BASIC,
defaultInvocationCount: Int = 0,
additionalValidDirectives: Collection<String> = emptyList()
fileText: String,
platform: TargetPlatform?,
complete: (CompletionType, Int) -> Array<LookupElement>?,
defaultCompletionType: CompletionType = CompletionType.BASIC,
defaultInvocationCount: Int = 0,
additionalValidDirectives: Collection<String> = emptyList()
) {
testWithAutoCompleteSetting(fileText) {
val completionType = ExpectedCompletionUtils.getCompletionType(fileText) ?: defaultCompletionType
@@ -19,9 +19,11 @@ import org.jetbrains.kotlin.idea.completion.LookupElementFactory
import org.jetbrains.kotlin.idea.core.completion.DeclarationLookupObject
import org.jetbrains.kotlin.idea.test.AstAccessControl
import org.jetbrains.kotlin.idea.util.module
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.jvm.JvmPlatforms
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.platform.js.isJs
import org.jetbrains.kotlin.platform.jvm.isJvm
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.junit.Assert
import java.util.*
@@ -87,7 +89,7 @@ object ExpectedCompletionUtils {
}
}
private val UNSUPPORTED_PLATFORM_MESSAGE = "Only $JvmPlatform and $JsPlatform platforms are supported"
private val UNSUPPORTED_PLATFORM_MESSAGE = "Only ${JvmPlatforms.defaultJvmPlatform} and ${JsPlatforms.defaultJsPlatform} platforms are supported"
private val EXIST_LINE_PREFIX = "EXIST:"
@@ -135,19 +137,19 @@ object ExpectedCompletionUtils {
AstAccessControl.ALLOW_AST_ACCESS_DIRECTIVE)
fun itemsShouldExist(fileText: String, platform: TargetPlatform?): Array<CompletionProposal> {
return when (platform) {
is JvmPlatform -> processProposalAssertions(fileText, EXIST_LINE_PREFIX, EXIST_JAVA_ONLY_LINE_PREFIX)
JsPlatform -> processProposalAssertions(fileText, EXIST_LINE_PREFIX, EXIST_JS_ONLY_LINE_PREFIX)
null -> processProposalAssertions(fileText, EXIST_LINE_PREFIX)
return when {
platform.isJvm() -> processProposalAssertions(fileText, EXIST_LINE_PREFIX, EXIST_JAVA_ONLY_LINE_PREFIX)
platform.isJs() -> processProposalAssertions(fileText, EXIST_LINE_PREFIX, EXIST_JS_ONLY_LINE_PREFIX)
platform == null -> processProposalAssertions(fileText, EXIST_LINE_PREFIX)
else -> throw IllegalArgumentException(UNSUPPORTED_PLATFORM_MESSAGE)
}
}
fun itemsShouldAbsent(fileText: String, platform: TargetPlatform?): Array<CompletionProposal> {
return when (platform) {
is JvmPlatform -> processProposalAssertions(fileText, ABSENT_LINE_PREFIX, ABSENT_JAVA_LINE_PREFIX, EXIST_JS_ONLY_LINE_PREFIX)
JsPlatform -> processProposalAssertions(fileText, ABSENT_LINE_PREFIX, ABSENT_JS_LINE_PREFIX, EXIST_JAVA_ONLY_LINE_PREFIX)
null -> processProposalAssertions(fileText, ABSENT_LINE_PREFIX)
return when {
platform.isJvm() -> processProposalAssertions(fileText, ABSENT_LINE_PREFIX, ABSENT_JAVA_LINE_PREFIX, EXIST_JS_ONLY_LINE_PREFIX)
platform.isJs() -> processProposalAssertions(fileText, ABSENT_LINE_PREFIX, ABSENT_JS_LINE_PREFIX, EXIST_JAVA_ONLY_LINE_PREFIX)
platform == null -> processProposalAssertions(fileText, ABSENT_LINE_PREFIX)
else -> throw IllegalArgumentException(UNSUPPORTED_PLATFORM_MESSAGE)
}
}
@@ -179,10 +181,10 @@ object ExpectedCompletionUtils {
}
fun getExpectedNumber(fileText: String, platform: TargetPlatform?): Int? {
return when (platform) {
null -> InTextDirectivesUtils.getPrefixedInt(fileText, NUMBER_LINE_PREFIX)
is JvmPlatform -> getPlatformExpectedNumber(fileText, NUMBER_JAVA_LINE_PREFIX)
JsPlatform -> getPlatformExpectedNumber(fileText, NUMBER_JS_LINE_PREFIX)
return when {
platform == null -> InTextDirectivesUtils.getPrefixedInt(fileText, NUMBER_LINE_PREFIX)
platform.isJvm() -> getPlatformExpectedNumber(fileText, NUMBER_JAVA_LINE_PREFIX)
platform.isJs() -> getPlatformExpectedNumber(fileText, NUMBER_JS_LINE_PREFIX)
else -> throw IllegalArgumentException(UNSUPPORTED_PLATFORM_MESSAGE)
}
}
@@ -13,7 +13,7 @@ import org.jetbrains.kotlin.idea.test.CompilerTestDirectives
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.test.configureCompilerOptions
import org.jetbrains.kotlin.idea.test.rollbackCompilerOptions
import org.jetbrains.kotlin.resolve.TargetPlatform
import org.jetbrains.kotlin.platform.TargetPlatform
import java.io.File
abstract class KotlinFixtureCompletionBaseTestCase : KotlinLightCodeInsightFixtureTestCase() {