[K/JS] Prepare JS Plain Objects plugin to publication

This commit is contained in:
Artem Kobzar
2024-01-17 10:52:58 +00:00
committed by Space Team
parent 561be747c1
commit dfe2d8651e
53 changed files with 479 additions and 393 deletions
+2 -2
View File
@@ -376,8 +376,8 @@
/plugins/kapt3/kapt3-compiler/tests-gen/ "Kotlin Compiler Core" "Kotlin JVM" /plugins/kapt3/kapt3-compiler/tests-gen/ "Kotlin Compiler Core" "Kotlin JVM"
/plugins/kapt4/ "Kotlin JVM" /plugins/kapt4/ "Kotlin JVM"
/plugins/kotlinx-serialization/ Sergey.Shanshin Leonid.Startsev /plugins/kotlinx-serialization/ Sergey.Shanshin Leonid.Startsev
/plugins/jso/ "Kotlin JS" /plugins/js-plain-objects/ "Kotlin JS"
/libraries/tools/jso "Kotlin JS" /libraries/tools/js-plain-objects "Kotlin JS"
/plugins/lombok/ "Kotlin Compiler Core" /plugins/lombok/ "Kotlin Compiler Core"
/plugins/noarg/ "Kotlin Compiler Core" /plugins/noarg/ "Kotlin Compiler Core"
/plugins/parcelize/ "Kotlin Compiler Core" /plugins/parcelize/ "Kotlin Compiler Core"
+1 -1
View File
@@ -874,7 +874,7 @@ tasks {
dependsOn(":plugins:fir-plugin-prototype:fir-plugin-ic-test:test") dependsOn(":plugins:fir-plugin-prototype:fir-plugin-ic-test:test")
dependsOn(":kotlin-imports-dumper-compiler-plugin:test") dependsOn(":kotlin-imports-dumper-compiler-plugin:test")
dependsOn(":plugins:jvm-abi-gen:test") dependsOn(":plugins:jvm-abi-gen:test")
dependsOn(":plugins:jso:compiler-plugin:test") dependsOn(":plugins:js-plain-objects:compiler-plugin:test")
dependsOn(":kotlinx-serialization-compiler-plugin:test") dependsOn(":kotlinx-serialization-compiler-plugin:test")
dependsOn(":kotlin-lombok-compiler-plugin:test") dependsOn(":kotlin-lombok-compiler-plugin:test")
dependsOn(":kotlin-noarg-compiler-plugin:test") dependsOn(":kotlin-noarg-compiler-plugin:test")
@@ -0,0 +1,18 @@
plugins {
id("gradle-plugin-common-configuration")
}
dependencies {
commonApi(platform(project(":kotlin-gradle-plugins-bom")))
}
gradlePlugin {
plugins {
create("js-plain-objects") {
id = "org.jetbrains.kotlin.plugin.js-plain-objects"
displayName = "Kotlin compiler plugin for typed JS-objects library"
description = displayName
implementationClass = "org.jetbrains.kotlinx.jspo.gradle.JsPlainObjectsKotlinGradleSubplugin"
}
}
}
@@ -14,14 +14,14 @@
* limitations under the License. * limitations under the License.
*/ */
package org.jetbrains.kotlinx.jso.gradle package org.jetbrains.kotlinx.jspo.gradle
import org.gradle.api.provider.Provider import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.plugin.* import org.jetbrains.kotlin.gradle.plugin.*
class JsoKotlinGradleSubplugin : KotlinCompilerPluginSupportPlugin { class JsPlainObjectsKotlinGradleSubplugin : KotlinCompilerPluginSupportPlugin {
companion object { companion object {
const val JSO_ARTIFACT_NAME = "kotlinx-jso-compiler-plugin-embeddable" const val JS_PLAIN_OBJECTS_ARTIFACT_NAME = "kotlinx-js-plain-objects-compiler-plugin-embeddable"
} }
override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean =
@@ -33,9 +33,9 @@ class JsoKotlinGradleSubplugin : KotlinCompilerPluginSupportPlugin {
kotlinCompilation.target.project.provider { emptyList() } kotlinCompilation.target.project.provider { emptyList() }
override fun getPluginArtifact(): SubpluginArtifact = override fun getPluginArtifact(): SubpluginArtifact =
JetBrainsSubpluginArtifact(JSO_ARTIFACT_NAME) JetBrainsSubpluginArtifact(JS_PLAIN_OBJECTS_ARTIFACT_NAME)
override fun getCompilerPluginId() = "org.jetbrains.kotlinx.jso" override fun getCompilerPluginId() = "org.jetbrains.kotlinx.js-plain-objects"
private fun KotlinTarget.isJs() = platformType == KotlinPlatformType.js private fun KotlinTarget.isJs() = platformType == KotlinPlatformType.js
@@ -0,0 +1 @@
implementation-class=org.jetbrains.kotlinx.jspo.gradle.JsPlainObjectsKotlinGradleSubplugin
-18
View File
@@ -1,18 +0,0 @@
plugins {
id("gradle-plugin-common-configuration")
}
dependencies {
commonApi(platform(project(":kotlin-gradle-plugins-bom")))
}
gradlePlugin {
plugins {
create("jso") {
id = "org.jetbrains.kotlin.plugin.jso"
displayName = "Kotlin compiler plugin for kotlinx.jso library"
description = displayName
implementationClass = "org.jetbrains.kotlinx.jso.gradle.JsoKotlinGradleSubplugin"
}
}
}
@@ -1 +0,0 @@
implementation-class=org.jetbrains.kotlinx.jso.gradle.JsoKotlinGradleSubplugin
@@ -0,0 +1,19 @@
plugins {
id("org.jetbrains.kotlin.jvm")
}
dependencies {
embedded(project(":plugins:js-plain-objects:compiler-plugin")) { isTransitive = false }
}
publish {
artifactId = "kotlinx-js-plain-objects-compiler-plugin-embeddable"
}
runtimeJar(rewriteDefaultJarDepsToShadedCompiler())
sourcesJarWithSourcesFromEmbedded(
project(":plugins:js-plain-objects:compiler-plugin").tasks.named<Jar>("sourcesJar")
)
javadocJarWithJavadocFromEmbedded(
project(":plugins:js-plain-objects:compiler-plugin").tasks.named<Jar>("javadocJar")
)
@@ -2,7 +2,7 @@ import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute
description = "JavaScript Object Compiler Plugin" description = "JavaScript Plain Objects Compiler Plugin"
plugins { plugins {
kotlin("jvm") kotlin("jvm")
@@ -18,14 +18,14 @@ val jsoIrRuntimeForTests by configurations.creating {
} }
dependencies { dependencies {
embedded(project(":plugins:jso:compiler-plugin:jso.common")) { isTransitive = false } embedded(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.common")) { isTransitive = false }
embedded(project(":plugins:jso:compiler-plugin:jso.k2")) { isTransitive = false } embedded(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.k2")) { isTransitive = false }
embedded(project(":plugins:jso:compiler-plugin:jso.backend")) { isTransitive = false } embedded(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.backend")) { isTransitive = false }
embedded(project(":plugins:jso:compiler-plugin:jso.cli")) { isTransitive = false } embedded(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.cli")) { isTransitive = false }
testApi(project(":compiler:backend")) testApi(project(":compiler:backend"))
testApi(project(":compiler:cli")) testApi(project(":compiler:cli"))
testApi(project(":plugins:jso:compiler-plugin:jso.cli")) testApi(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.cli"))
testApi(projectTests(":compiler:test-infrastructure")) testApi(projectTests(":compiler:test-infrastructure"))
testApi(projectTests(":compiler:test-infrastructure-utils")) testApi(projectTests(":compiler:test-infrastructure-utils"))
@@ -40,9 +40,9 @@ dependencies {
testRuntimeOnly(libs.junit.jupiter.engine) testRuntimeOnly(libs.junit.jupiter.engine)
if (!project.kotlinBuildProperties.isInJpsBuildIdeaSync) { if (!project.kotlinBuildProperties.isInJpsBuildIdeaSync) {
jsoIrRuntimeForTests(project(":plugins:jso:runtime")) { isTransitive = false } jsoIrRuntimeForTests(project(":plugins:js-plain-objects:runtime")) { isTransitive = false }
embedded(project(":plugins:jso:runtime")) { embedded(project(":plugins:js-plain-objects:runtime")) {
attributes { attributes {
attribute(KotlinPlatformType.attribute, KotlinPlatformType.js) attribute(KotlinPlatformType.attribute, KotlinPlatformType.js)
attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, KotlinJsCompilerAttribute.ir) attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, KotlinJsCompilerAttribute.ir)
@@ -65,7 +65,9 @@ sourceSets {
} }
} }
publish() publish {
artifactId = "kotlinx-js-plain-objects-compiler-plugin"
}
runtimeJar() runtimeJar()
sourcesJar() sourcesJar()
@@ -80,11 +82,11 @@ projectTest(parallel = true, jUnitMode = JUnitMode.JUnit5) {
dependsOn(jsoIrRuntimeForTests) dependsOn(jsoIrRuntimeForTests)
val localJsoIrRuntimePath: FileCollection = jsoIrRuntimeForTests val localJsPlainObjectsIrRuntimePath: FileCollection = jsoIrRuntimeForTests
doFirst { doFirst {
systemProperty("jso.runtime.path", localJsoIrRuntimePath.asPath) systemProperty("jso.runtime.path", localJsPlainObjectsIrRuntimePath.asPath)
} }
} }
val generateTests by generator("org.jetbrains.kotlinx.jso.TestGeneratorKt") val generateTests by generator("org.jetbrains.kotlinx.jspo.TestGeneratorKt")
@@ -1,4 +1,4 @@
description = "Kotlin JavaScript Object Compiler Plugin (Backend)" description = "Kotlin JavaScript Plain Objects Compiler Plugin (Backend)"
plugins { plugins {
kotlin("jvm") kotlin("jvm")
@@ -10,7 +10,7 @@ dependencies {
compileOnly(project(":compiler:ir.backend.common")) compileOnly(project(":compiler:ir.backend.common"))
compileOnly(project(":compiler:ir.tree")) compileOnly(project(":compiler:ir.tree"))
implementation(project(":plugins:jso:compiler-plugin:jso.common")) implementation(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.common"))
compileOnly(intellijCore()) compileOnly(intellijCore())
} }
@@ -2,7 +2,7 @@
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.backend package org.jetbrains.kotlinx.jspo.compiler.backend
import org.jetbrains.kotlin.backend.common.DeclarationTransformer import org.jetbrains.kotlin.backend.common.DeclarationTransformer
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
@@ -15,12 +15,12 @@ import org.jetbrains.kotlin.ir.expressions.impl.*
import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI
import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.ir.util.*
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlinx.jso.compiler.resolve.JsSimpleObjectPluginKey import org.jetbrains.kotlinx.jspo.compiler.resolve.JsPlainObjectsPluginKey
import org.jetbrains.kotlinx.jso.compiler.resolve.StandardIds import org.jetbrains.kotlinx.jspo.compiler.resolve.StandardIds
private class MoveExternalInlineFunctionsWithBodiesOutsideLowering(private val context: IrPluginContext) : DeclarationTransformer { private class MoveExternalInlineFunctionsWithBodiesOutsideLowering(private val context: IrPluginContext) : DeclarationTransformer {
private val jsFunction = context.referenceFunctions(StandardIds.JS_FUNCTION_ID).single() private val jsFunction = context.referenceFunctions(StandardIds.JS_FUNCTION_ID).single()
private val EXPECTED_ORIGIN = IrDeclarationOrigin.GeneratedByPlugin(JsSimpleObjectPluginKey) private val EXPECTED_ORIGIN = IrDeclarationOrigin.GeneratedByPlugin(JsPlainObjectsPluginKey)
@OptIn(UnsafeDuringIrConstructionAPI::class) @OptIn(UnsafeDuringIrConstructionAPI::class)
override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? { override fun transformFlat(declaration: IrDeclaration): List<IrDeclaration>? {
@@ -66,7 +66,7 @@ private class MoveExternalInlineFunctionsWithBodiesOutsideLowering(private val c
} }
} }
open class JsObjectLoweringExtension : IrGenerationExtension { open class JsPlainObjectsLoweringExtension : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
MoveExternalInlineFunctionsWithBodiesOutsideLowering(pluginContext).lower(moduleFragment) MoveExternalInlineFunctionsWithBodiesOutsideLowering(pluginContext).lower(moduleFragment)
} }
@@ -1,4 +1,4 @@
description = "Kotlin JavaScript Object Compiler Plugin (CLI)" description = "Kotlin JavaScript Plain Objects Compiler Plugin (CLI)"
plugins { plugins {
kotlin("jvm") kotlin("jvm")
@@ -12,9 +12,9 @@ dependencies {
compileOnly(project(":compiler:fir:entrypoint")) compileOnly(project(":compiler:fir:entrypoint"))
compileOnly(project(":compiler:ir.backend.common")) compileOnly(project(":compiler:ir.backend.common"))
implementation(project(":plugins:jso:compiler-plugin:jso.common")) implementation(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.common"))
implementation(project(":plugins:jso:compiler-plugin:jso.backend")) implementation(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.backend"))
implementation(project(":plugins:jso:compiler-plugin:jso.k2")) implementation(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.k2"))
compileOnly(intellijCore()) compileOnly(intellijCore())
} }
@@ -14,4 +14,4 @@
# limitations under the License. # limitations under the License.
# #
org.jetbrains.kotlinx.jso.compiler.cli.JsObjectComponentRegistrar org.jetbrains.kotlinx.jspo.compiler.cli.JsPlainObjectsComponentRegistrar
@@ -3,16 +3,16 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.cli package org.jetbrains.kotlinx.jspo.compiler.cli
import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter
import org.jetbrains.kotlinx.jso.compiler.backend.JsObjectLoweringExtension import org.jetbrains.kotlinx.jspo.compiler.backend.JsPlainObjectsLoweringExtension
import org.jetbrains.kotlinx.jso.compiler.fir.JsObjectExtensionRegistrar import org.jetbrains.kotlinx.jspo.compiler.fir.JsPlainObjectsExtensionRegistrar
class JsObjectComponentRegistrar : CompilerPluginRegistrar() { class JsPlainObjectsComponentRegistrar : CompilerPluginRegistrar() {
override val supportsK2: Boolean get() = true override val supportsK2: Boolean get() = true
override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) { override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) {
@@ -21,8 +21,8 @@ class JsObjectComponentRegistrar : CompilerPluginRegistrar() {
companion object { companion object {
fun registerExtensions(extensionStorage: ExtensionStorage) = with(extensionStorage) { fun registerExtensions(extensionStorage: ExtensionStorage) = with(extensionStorage) {
FirExtensionRegistrarAdapter.registerExtension(JsObjectExtensionRegistrar()) FirExtensionRegistrarAdapter.registerExtension(JsPlainObjectsExtensionRegistrar())
IrGenerationExtension.registerExtension(JsObjectLoweringExtension()) IrGenerationExtension.registerExtension(JsPlainObjectsLoweringExtension())
} }
} }
} }
@@ -1,4 +1,4 @@
description = "Kotlin JavaScript Object Compiler Plugin (Common)" description = "Kotlin JavaScript Plain Objects Compiler Plugin (Common)"
plugins { plugins {
kotlin("jvm") kotlin("jvm")
@@ -3,12 +3,12 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.resolve package org.jetbrains.kotlinx.jspo.compiler.resolve
import org.jetbrains.kotlin.GeneratedDeclarationKey import org.jetbrains.kotlin.GeneratedDeclarationKey
object JsSimpleObjectPluginKey : GeneratedDeclarationKey() { object JsPlainObjectsPluginKey : GeneratedDeclarationKey() {
override fun toString(): String { override fun toString(): String {
return "KotlinxJsSimpleObjectPlugin" return "KotlinxJsPlainObjectsPlugin"
} }
} }
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.resolve; package org.jetbrains.kotlinx.jspo.compiler.resolve;
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.ClassId
@@ -15,7 +15,7 @@ object StandardIds {
val JS_FUNCTION_ID = CallableId(KOTLIN_JS_FQN, Name.identifier("js")) val JS_FUNCTION_ID = CallableId(KOTLIN_JS_FQN, Name.identifier("js"))
} }
object JsObjectAnnotations { object JsPlainObjectsAnnotations {
val jsSimpleObjectAnnotationClassId = ClassId(FqName("kotlinx.jso"), Name.identifier("JsSimpleObject")) val jsPlainObjectAnnotationClassId = ClassId(FqName("kotlinx.js"), Name.identifier("JsPlainObject"))
val jsSimpleObjectAnnotationFqName = jsSimpleObjectAnnotationClassId.asSingleFqName() val jsPlainObjectAnnotationFqName = jsPlainObjectAnnotationClassId.asSingleFqName()
} }
@@ -1,4 +1,4 @@
description = "Kotlin JavaScript Object Compiler Plugin (K2)" description = "Kotlin JavaScript Plain Objects Compiler Plugin (K2)"
plugins { plugins {
kotlin("jvm") kotlin("jvm")
@@ -13,7 +13,7 @@ dependencies {
compileOnly(project(":compiler:fir:entrypoint")) compileOnly(project(":compiler:fir:entrypoint"))
compileOnly(project(":compiler:cli-common")) compileOnly(project(":compiler:cli-common"))
implementation(project(":plugins:jso:compiler-plugin:jso.common")) implementation(project(":plugins:js-plain-objects:compiler-plugin:js-plain-objects.common"))
compileOnly(intellijCore()) compileOnly(intellijCore())
@@ -0,0 +1,19 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.kotlinx.jspo.compiler.fir
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlinx.jspo.compiler.fir.checkers.FirJsPlainObjectsCheckersComponent
import org.jetbrains.kotlinx.jspo.compiler.fir.services.JsPlainObjectsPropertiesProvider
class JsPlainObjectsExtensionRegistrar : FirExtensionRegistrar() {
override fun ExtensionRegistrarContext.configurePlugin() {
+::FirJsPlainObjectsCheckersComponent
+::JsPlainObjectsFunctionsGenerator
// services
+::JsPlainObjectsPropertiesProvider
}
}
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.fir package org.jetbrains.kotlinx.jspo.compiler.fir
import org.jetbrains.kotlin.builtins.StandardNames import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
@@ -12,10 +12,8 @@ import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirFunctionTarget import org.jetbrains.kotlin.fir.FirFunctionTarget
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol import org.jetbrains.kotlin.fir.analysis.checkers.getContainingClassSymbol
import org.jetbrains.kotlin.fir.builder.createDataClassCopyFunction
import org.jetbrains.kotlin.fir.declarations.FirResolvePhase import org.jetbrains.kotlin.fir.declarations.FirResolvePhase
import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder
import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass
import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
@@ -37,27 +35,25 @@ import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider
import org.jetbrains.kotlin.fir.symbols.SymbolInternals import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.toEffectiveVisibility import org.jetbrains.kotlin.fir.toEffectiveVisibility
import org.jetbrains.kotlin.fir.types.coneTypeOrNull
import org.jetbrains.kotlin.fir.types.isNullable import org.jetbrains.kotlin.fir.types.isNullable
import org.jetbrains.kotlin.fir.types.toFirResolvedTypeRef import org.jetbrains.kotlin.fir.types.toFirResolvedTypeRef
import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.name.StandardClassIds
import org.jetbrains.kotlin.types.ConstantValueKind import org.jetbrains.kotlin.types.ConstantValueKind
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlinx.jso.compiler.fir.services.jsObjectPropertiesProvider import org.jetbrains.kotlinx.jspo.compiler.fir.services.jsPlainObjectPropertiesProvider
import org.jetbrains.kotlinx.jso.compiler.resolve.JsSimpleObjectPluginKey import org.jetbrains.kotlinx.jspo.compiler.resolve.JsPlainObjectsPluginKey
/** /**
* The extension generate a synthetic factory and copy-method for an `external interface` annotated with @JsSimpleObject * The extension generate a synthetic factory and copy-method for an `external interface` annotated with @JsPlainObjects
* Imagine the next interfaces: * Imagine the next interfaces:
* ``` * ```
* external interface User { * external interface User {
* val name: String * val name: String
* } * }
* @JsSimpleObject * @JsPlainObjects
* external interface Admin { * external interface Admin {
* val chat: Chat * val chat: Chat
* } * }
@@ -78,24 +74,24 @@ import org.jetbrains.kotlinx.jso.compiler.resolve.JsSimpleObjectPluginKey
* } * }
* ``` * ```
*/ */
class JsObjectFunctionsGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { class JsPlainObjectsFunctionsGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) {
private val predicateBasedProvider = session.predicateBasedProvider private val predicateBasedProvider = session.predicateBasedProvider
private val matchedInterfaces by lazy { private val matchedInterfaces by lazy {
predicateBasedProvider.getSymbolsByPredicate(JsObjectPredicates.AnnotatedWithJsSimpleObject.LOOKUP) predicateBasedProvider.getSymbolsByPredicate(JsPlainObjectsPredicates.AnnotatedWithJsPlainObject.LOOKUP)
.filterIsInstance<FirRegularClassSymbol>() .filterIsInstance<FirRegularClassSymbol>()
.toSet() .toSet()
} }
private val factoryFqNamesToJsObjectInterface by lazy { private val factoryFqNamesToJsPlainObjectsInterface by lazy {
matchedInterfaces.associateBy { it.classId.asSingleFqName() } matchedInterfaces.associateBy { it.classId.asSingleFqName() }
} }
private val FirClassLikeSymbol<*>.isJsObject: Boolean private val FirClassLikeSymbol<*>.isJsPlainObject: Boolean
get() = this is FirRegularClassSymbol && this in matchedInterfaces get() = this is FirRegularClassSymbol && this in matchedInterfaces
override fun getNestedClassifiersNames(classSymbol: FirClassSymbol<*>, context: NestedClassGenerationContext): Set<Name> { override fun getNestedClassifiersNames(classSymbol: FirClassSymbol<*>, context: NestedClassGenerationContext): Set<Name> {
return if (classSymbol.isJsObject) setOf(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT) else emptySet() return if (classSymbol.isJsPlainObject) setOf(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT) else emptySet()
} }
override fun generateNestedClassLikeDeclaration( override fun generateNestedClassLikeDeclaration(
@@ -105,7 +101,7 @@ class JsObjectFunctionsGenerator(session: FirSession) : FirDeclarationGeneration
): FirClassLikeSymbol<*>? { ): FirClassLikeSymbol<*>? {
return if ( return if (
owner is FirRegularClassSymbol && owner is FirRegularClassSymbol &&
owner.isJsObject && owner.isJsPlainObject &&
name == org.jetbrains.kotlin.name.SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT name == org.jetbrains.kotlin.name.SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT
) generateCompanionDeclaration(owner) ) generateCompanionDeclaration(owner)
else null else null
@@ -117,7 +113,7 @@ class JsObjectFunctionsGenerator(session: FirSession) : FirDeclarationGeneration
return buildRegularClass { return buildRegularClass {
resolvePhase = FirResolvePhase.BODY_RESOLVE resolvePhase = FirResolvePhase.BODY_RESOLVE
moduleData = session.moduleData moduleData = session.moduleData
origin = JsSimpleObjectPluginKey.origin origin = JsPlainObjectsPluginKey.origin
classKind = ClassKind.OBJECT classKind = ClassKind.OBJECT
scopeProvider = session.kotlinScopeProvider scopeProvider = session.kotlinScopeProvider
status = FirResolvedDeclarationStatusImpl( status = FirResolvedDeclarationStatusImpl(
@@ -136,8 +132,8 @@ class JsObjectFunctionsGenerator(session: FirSession) : FirDeclarationGeneration
override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>, context: MemberGenerationContext): Set<Name> { override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>, context: MemberGenerationContext): Set<Name> {
val outerClass = classSymbol.getContainingClassSymbol(session) val outerClass = classSymbol.getContainingClassSymbol(session)
return when { return when {
classSymbol.isCompanion && outerClass?.isJsObject == true -> setOf(OperatorNameConventions.INVOKE) classSymbol.isCompanion && outerClass?.isJsPlainObject == true -> setOf(OperatorNameConventions.INVOKE)
classSymbol.isJsObject -> setOf(StandardNames.DATA_CLASS_COPY) classSymbol.isJsPlainObject -> setOf(StandardNames.DATA_CLASS_COPY)
else -> emptySet() else -> emptySet()
} }
} }
@@ -151,25 +147,25 @@ class JsObjectFunctionsGenerator(session: FirSession) : FirDeclarationGeneration
return when (callableId.callableName) { return when (callableId.callableName) {
StandardNames.DATA_CLASS_COPY -> { StandardNames.DATA_CLASS_COPY -> {
containingClass containingClass
?.let { factoryFqNamesToJsObjectInterface[it.asSingleFqName()] } ?.let { factoryFqNamesToJsPlainObjectsInterface[it.asSingleFqName()] }
?.let { listOf(createJsObjectCopyFunction(callableId, context.owner, it).symbol) } ?: emptyList() ?.let { listOf(createJsPlainObjectCopyFunction(callableId, context.owner, it).symbol) } ?: emptyList()
} }
OperatorNameConventions.INVOKE -> { OperatorNameConventions.INVOKE -> {
possibleInterface possibleInterface
?.takeIf { context.owner.isCompanion } ?.takeIf { context.owner.isCompanion }
?.let { factoryFqNamesToJsObjectInterface[it.asSingleFqName()] } ?.let { factoryFqNamesToJsPlainObjectsInterface[it.asSingleFqName()] }
?.let { listOf(createJsObjectFactoryFunction(callableId, context.owner, it).symbol) } ?: emptyList() ?.let { listOf(createJsPlainObjectFactoryFunction(callableId, context.owner, it).symbol) } ?: emptyList()
} }
else -> emptyList() else -> emptyList()
} }
} }
private fun createJsObjectFactoryFunction( private fun createJsPlainObjectFactoryFunction(
callableId: CallableId, callableId: CallableId,
parent: FirClassSymbol<*>, parent: FirClassSymbol<*>,
jsSimpleObjectInterface: FirRegularClassSymbol, jsPlainObjectInterface: FirRegularClassSymbol,
): FirSimpleFunction { ): FirSimpleFunction {
return createJsObjectFunction(callableId, parent, jsSimpleObjectInterface) { return createJsPlainObjectsFunction(callableId, parent, jsPlainObjectInterface) {
runIf(resolvedReturnTypeRef.type.isNullable) { runIf(resolvedReturnTypeRef.type.isNullable) {
buildConstExpression( buildConstExpression(
source = null, source = null,
@@ -181,21 +177,21 @@ class JsObjectFunctionsGenerator(session: FirSession) : FirDeclarationGeneration
} }
} }
private fun createJsObjectCopyFunction( private fun createJsPlainObjectCopyFunction(
callableId: CallableId, callableId: CallableId,
parent: FirClassSymbol<*>, parent: FirClassSymbol<*>,
jsSimpleObjectInterface: FirRegularClassSymbol, jsPlainObjectInterface: FirRegularClassSymbol,
): FirSimpleFunction { ): FirSimpleFunction {
val interfaceType = jsSimpleObjectInterface.defaultType() val interfaceType = jsPlainObjectInterface.defaultType()
return createJsObjectFunction(callableId, parent, jsSimpleObjectInterface) { return createJsPlainObjectsFunction(callableId, parent, jsPlainObjectInterface) {
buildPropertyAccessExpression { buildPropertyAccessExpression {
dispatchReceiver = buildThisReceiverExpression { dispatchReceiver = buildThisReceiverExpression {
calleeReference = buildImplicitThisReference { boundSymbol = jsSimpleObjectInterface } calleeReference = buildImplicitThisReference { boundSymbol = jsPlainObjectInterface }
coneTypeOrNull = interfaceType coneTypeOrNull = interfaceType
} }
calleeReference = buildResolvedNamedReference { calleeReference = buildResolvedNamedReference {
name = this@createJsObjectFunction.name name = this@createJsPlainObjectsFunction.name
resolvedSymbol = this@createJsObjectFunction resolvedSymbol = this@createJsPlainObjectsFunction
} }
coneTypeOrNull = resolvedReturnType coneTypeOrNull = resolvedReturnType
} }
@@ -203,40 +199,40 @@ class JsObjectFunctionsGenerator(session: FirSession) : FirDeclarationGeneration
} }
@OptIn(SymbolInternals::class) @OptIn(SymbolInternals::class)
private fun createJsObjectFunction( private fun createJsPlainObjectsFunction(
callableId: CallableId, callableId: CallableId,
parent: FirClassSymbol<*>, parent: FirClassSymbol<*>,
jsSimpleObjectInterface: FirRegularClassSymbol, jsPlainObjectInterface: FirRegularClassSymbol,
getParameterDefaultValueFromProperty: FirPropertySymbol.() -> FirExpression? getParameterDefaultValueFromProperty: FirPropertySymbol.() -> FirExpression?
): FirSimpleFunction { ): FirSimpleFunction {
val jsSimpleObjectProperties = session.jsObjectPropertiesProvider.getJsObjectPropertiesForClass(jsSimpleObjectInterface) val jsPlainObjectProperties = session.jsPlainObjectPropertiesProvider.getJsPlainObjectsPropertiesForClass(jsPlainObjectInterface)
val functionTarget = FirFunctionTarget(null, isLambda = false) val functionTarget = FirFunctionTarget(null, isLambda = false)
val jsSimpleObjectInterfaceDefaultType = jsSimpleObjectInterface.defaultType() val jsPlainObjectInterfaceDefaultType = jsPlainObjectInterface.defaultType()
return buildSimpleFunction { return buildSimpleFunction {
moduleData = jsSimpleObjectInterface.moduleData moduleData = jsPlainObjectInterface.moduleData
resolvePhase = FirResolvePhase.BODY_RESOLVE resolvePhase = FirResolvePhase.BODY_RESOLVE
origin = JsSimpleObjectPluginKey.origin origin = JsPlainObjectsPluginKey.origin
symbol = FirNamedFunctionSymbol(callableId) symbol = FirNamedFunctionSymbol(callableId)
name = callableId.callableName name = callableId.callableName
returnTypeRef = jsSimpleObjectInterfaceDefaultType.toFirResolvedTypeRef() returnTypeRef = jsPlainObjectInterfaceDefaultType.toFirResolvedTypeRef()
status = FirResolvedDeclarationStatusImpl( status = FirResolvedDeclarationStatusImpl(
jsSimpleObjectInterface.visibility, jsPlainObjectInterface.visibility,
Modality.FINAL, Modality.FINAL,
jsSimpleObjectInterface.visibility.toEffectiveVisibility(parent, forClass = true) jsPlainObjectInterface.visibility.toEffectiveVisibility(parent, forClass = true)
).apply { ).apply {
isInline = true isInline = true
isOperator = true isOperator = true
} }
dispatchReceiverType = parent.defaultType() dispatchReceiverType = parent.defaultType()
jsSimpleObjectInterface.typeParameterSymbols.mapTo(typeParameters) { it.fir } jsPlainObjectInterface.typeParameterSymbols.mapTo(typeParameters) { it.fir }
jsSimpleObjectProperties.mapTo(valueParameters) { jsPlainObjectProperties.mapTo(valueParameters) {
val typeRef = it.resolvedReturnTypeRef val typeRef = it.resolvedReturnTypeRef
buildValueParameter { buildValueParameter {
moduleData = session.moduleData moduleData = session.moduleData
origin = JsSimpleObjectPluginKey.origin origin = JsPlainObjectsPluginKey.origin
returnTypeRef = typeRef returnTypeRef = typeRef
name = it.name name = it.name
symbol = FirValueParameterSymbol(it.name) symbol = FirValueParameterSymbol(it.name)
@@ -2,16 +2,16 @@
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.fir package org.jetbrains.kotlinx.jspo.compiler.fir
import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate import org.jetbrains.kotlin.fir.extensions.predicate.DeclarationPredicate
import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate
import org.jetbrains.kotlinx.jso.compiler.resolve.JsObjectAnnotations import org.jetbrains.kotlinx.jspo.compiler.resolve.JsPlainObjectsAnnotations
object JsObjectPredicates { object JsPlainObjectsPredicates {
internal object AnnotatedWithJsSimpleObject { internal object AnnotatedWithJsPlainObject {
private val jsSimpleObjectAnnotation = setOf(JsObjectAnnotations.jsSimpleObjectAnnotationFqName) private val jsPlainObjectAnnotation = setOf(JsPlainObjectsAnnotations.jsPlainObjectAnnotationFqName)
internal val LOOKUP = LookupPredicate.create { annotated(jsSimpleObjectAnnotation) } internal val LOOKUP = LookupPredicate.create { annotated(jsPlainObjectAnnotation) }
internal val DECLARATION = DeclarationPredicate.create { annotated(jsSimpleObjectAnnotation) } internal val DECLARATION = DeclarationPredicate.create { annotated(jsPlainObjectAnnotation) }
} }
} }
@@ -3,15 +3,15 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.fir.checkers package org.jetbrains.kotlinx.jspo.compiler.fir.checkers
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension
class FirJsoCheckersComponent(session: FirSession) : FirAdditionalCheckersExtension(session) { class FirJsPlainObjectsCheckersComponent(session: FirSession) : FirAdditionalCheckersExtension(session) {
override val declarationCheckers: DeclarationCheckers = object : DeclarationCheckers() { override val declarationCheckers: DeclarationCheckers = object : DeclarationCheckers() {
override val classCheckers: Set<FirClassChecker> = setOf(FirJsoPluginClassChecker) override val classCheckers: Set<FirClassChecker> = setOf(FirJsPlainObjectsPluginClassChecker)
} }
} }
@@ -3,22 +3,20 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.fir.checkers package org.jetbrains.kotlinx.jspo.compiler.fir.checkers
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.diagnostics.* import org.jetbrains.kotlin.diagnostics.*
import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory import org.jetbrains.kotlin.diagnostics.rendering.RootDiagnosticRendererFactory
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.psi.KtAnnotationEntry
object FirJsoErrors { object FirJsPlainObjectsErrors {
val NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED by error1<PsiElement, String>() val NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED by error1<PsiElement, String>()
val ONLY_INTERFACES_ARE_SUPPORTED by error1<PsiElement, String>() val ONLY_INTERFACES_ARE_SUPPORTED by error1<PsiElement, String>()
val IMPLEMENTING_OF_JSO_IS_NOT_SUPPORTED by error1<PsiElement, String>() val IMPLEMENTING_OF_JS_PLAIN_OBJECT_IS_NOT_SUPPORTED by error1<PsiElement, String>()
val METHODS_ARE_NOT_ALLOWED_INSIDE_JS_PLAIN_OBJECT by error0<PsiElement>()
val JS_PLAIN_OBJECT_CAN_EXTEND_ONLY_OTHER_JS_PLAIN_OBJECTS by error1<PsiElement, String>()
init { init {
RootDiagnosticRendererFactory.registerFactory(KtDefaultErrorMessagesJso) RootDiagnosticRendererFactory.registerFactory(KtDefaultErrorMessagesJsPlainObjects)
} }
} }
@@ -0,0 +1,105 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.kotlinx.jspo.compiler.fir.checkers
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal
import org.jetbrains.kotlin.fir.declarations.utils.isInline
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.declarations.utils.isMethodOfAny
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope
import org.jetbrains.kotlin.fir.scopes.processAllFunctions
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.isAny
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlinx.jspo.compiler.resolve.JsPlainObjectsAnnotations
object FirJsPlainObjectsPluginClassChecker : FirClassChecker() {
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
with(context) {
val classSymbol = declaration.symbol as? FirRegularClassSymbol ?: return
if (classSymbol.hasAnnotation(JsPlainObjectsAnnotations.jsPlainObjectAnnotationClassId, session)) {
checkJsPlainObjectAnnotationTargets(classSymbol, reporter)
checkJsPlainObjectSuperTypes(classSymbol, reporter)
checkJsPlainObjectMembers(classSymbol, reporter)
} else {
checkJsPlainObjectAsSuperInterface(classSymbol, reporter)
}
}
}
context(CheckerContext)
private fun checkJsPlainObjectAnnotationTargets(classSymbol: FirClassSymbol<out FirClass>, reporter: DiagnosticReporter) {
val classKind = classSymbol.classKind.codeRepresentation ?: error("Unexpected enum entry")
if (!classSymbol.isEffectivelyExternal(session)) {
reporter.reportOn(classSymbol.source, FirJsPlainObjectsErrors.NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED, classKind)
return
}
if (!classSymbol.isInterface) {
reporter.reportOn(classSymbol.source, FirJsPlainObjectsErrors.ONLY_INTERFACES_ARE_SUPPORTED, classKind)
return
}
}
context(CheckerContext)
private fun checkJsPlainObjectMembers(classSymbol: FirClassSymbol<out FirClass>, reporter: DiagnosticReporter) {
if (!classSymbol.isEffectivelyExternal(session) || !classSymbol.isInterface) return
classSymbol
.declaredMemberScope(session, null)
.processAllFunctions {
if (!it.isMethodOfAny && !it.isInline) {
reporter.reportOn(it.source, FirJsPlainObjectsErrors.METHODS_ARE_NOT_ALLOWED_INSIDE_JS_PLAIN_OBJECT)
}
}
}
context(CheckerContext)
private fun checkJsPlainObjectSuperTypes(classSymbol: FirClassSymbol<out FirClass>, reporter: DiagnosticReporter) {
if (!classSymbol.isEffectivelyExternal(session) || !classSymbol.isInterface) return
classSymbol.resolvedSuperTypeRefs.forEach { superType ->
val superInterface = superType.coneType
.takeIf { !it.isAny }
?.fullyExpandedType(session)
?.toRegularClassSymbol(session) ?: return@forEach
if (!superInterface.hasAnnotation(JsPlainObjectsAnnotations.jsPlainObjectAnnotationClassId, session)) {
reporter.reportOn(
superType.source,
FirJsPlainObjectsErrors.JS_PLAIN_OBJECT_CAN_EXTEND_ONLY_OTHER_JS_PLAIN_OBJECTS,
classSymbol.classId.asFqNameString()
)
}
}
}
context(CheckerContext)
private fun checkJsPlainObjectAsSuperInterface(classSymbol: FirClassSymbol<out FirClass>, reporter: DiagnosticReporter) {
classSymbol.resolvedSuperTypeRefs.forEach {
val superInterface = it.coneType.fullyExpandedType(session)
.toRegularClassSymbol(session)
?.takeIf { it.classKind == ClassKind.INTERFACE } ?: return@forEach
if (superInterface.hasAnnotation(JsPlainObjectsAnnotations.jsPlainObjectAnnotationClassId, session)) {
reporter.reportOn(
it.source,
FirJsPlainObjectsErrors.IMPLEMENTING_OF_JS_PLAIN_OBJECT_IS_NOT_SUPPORTED,
classSymbol.classId.asFqNameString()
)
}
}
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.kotlinx.jspo.compiler.fir.checkers
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers
object KtDefaultErrorMessagesJsPlainObjects : BaseDiagnosticRendererFactory() {
override val MAP = KtDiagnosticFactoryToRendererMap("JsPlainObjects").apply {
put(
FirJsPlainObjectsErrors.NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED,
"Non-external {0} can not be annotated with JsPlainObjects. Only external interfaces are supported.",
CommonRenderers.STRING
)
put(
FirJsPlainObjectsErrors.ONLY_INTERFACES_ARE_SUPPORTED,
"External {0} can not be annotated with JsPlainObjects. Only external interfaces are supported.",
CommonRenderers.STRING
)
put(
FirJsPlainObjectsErrors.IMPLEMENTING_OF_JS_PLAIN_OBJECT_IS_NOT_SUPPORTED,
"[{0}] is marked as JsPlainObjects, so, it can not be used as a super-type for non-JsPlainObjects declarations",
CommonRenderers.STRING
)
}
}
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.compiler.fir.services package org.jetbrains.kotlinx.jspo.compiler.fir.services
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
@@ -23,23 +23,23 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlinx.jso.compiler.fir.JsObjectPredicates import org.jetbrains.kotlinx.jspo.compiler.fir.JsPlainObjectsPredicates
import org.jetbrains.kotlinx.jso.compiler.resolve.JsObjectAnnotations import org.jetbrains.kotlinx.jspo.compiler.resolve.JsPlainObjectsAnnotations
class JsSimpleObjectPropertiesProvider(session: FirSession) : FirExtensionSessionComponent(session) { class JsPlainObjectsPropertiesProvider(session: FirSession) : FirExtensionSessionComponent(session) {
private val cache: FirCache<FirClassSymbol<*>, List<FirPropertySymbol>, Nothing?> = private val cache: FirCache<FirClassSymbol<*>, List<FirPropertySymbol>, Nothing?> =
session.firCachesFactory.createCache(this::createJsSimpleObjectProperties) session.firCachesFactory.createCache(this::createJsPlainObjectProperties)
override fun FirDeclarationPredicateRegistrar.registerPredicates() { override fun FirDeclarationPredicateRegistrar.registerPredicates() {
register(JsObjectPredicates.AnnotatedWithJsSimpleObject.DECLARATION) register(JsPlainObjectsPredicates.AnnotatedWithJsPlainObject.DECLARATION)
} }
fun getJsObjectPropertiesForClass(classSymbol: FirClassSymbol<*>): List<FirPropertySymbol> { fun getJsPlainObjectsPropertiesForClass(classSymbol: FirClassSymbol<*>): List<FirPropertySymbol> {
return cache.getValue(classSymbol) return cache.getValue(classSymbol)
} }
private fun createJsSimpleObjectProperties(classSymbol: FirClassSymbol<*>): List<FirPropertySymbol> = private fun createJsPlainObjectProperties(classSymbol: FirClassSymbol<*>): List<FirPropertySymbol> =
if (!classSymbol.hasAnnotation(JsObjectAnnotations.jsSimpleObjectAnnotationClassId, session)) { if (!classSymbol.hasAnnotation(JsPlainObjectsAnnotations.jsPlainObjectAnnotationClassId, session)) {
emptyList() emptyList()
} else { } else {
buildList { buildList {
@@ -48,7 +48,7 @@ class JsSimpleObjectPropertiesProvider(session: FirSession) : FirExtensionSessio
.toRegularClassSymbol(session) .toRegularClassSymbol(session)
?.takeIf { it.classKind == ClassKind.INTERFACE } ?: return@forEach ?.takeIf { it.classKind == ClassKind.INTERFACE } ?: return@forEach
val superInterfaceSimpleObjectProperties = createJsSimpleObjectProperties(superInterface) val superInterfaceSimpleObjectProperties = createJsPlainObjectProperties(superInterface)
superInterfaceSimpleObjectProperties.forEach(::addIfNotNull) superInterfaceSimpleObjectProperties.forEach(::addIfNotNull)
} }
@@ -61,4 +61,4 @@ class JsSimpleObjectPropertiesProvider(session: FirSession) : FirExtensionSessio
} }
} }
val FirSession.jsObjectPropertiesProvider: JsSimpleObjectPropertiesProvider by FirSession.sessionComponentAccessor() val FirSession.jsPlainObjectPropertiesProvider: JsPlainObjectsPropertiesProvider by FirSession.sessionComponentAccessor()
@@ -1,8 +1,8 @@
package foo package foo
import kotlinx.jso.JsSimpleObject import kotlinx.js.JsPlainObject
@JsSimpleObject @JsPlainObject
external interface User { external interface User {
var name: String var name: String
val age: Int val age: Int
@@ -1,8 +1,8 @@
package foo package foo
import kotlinx.jso.JsSimpleObject import kotlinx.js.JsPlainObject
@JsSimpleObject @JsPlainObject
external interface User { external interface User {
var name: String var name: String
val age: Int val age: Int
@@ -1,8 +1,8 @@
package foo package foo
import kotlinx.jso.JsSimpleObject import kotlinx.js.JsPlainObject
@JsSimpleObject @JsPlainObject
external interface User { external interface User {
var name: String var name: String
val age: Int val age: Int
@@ -1,14 +1,14 @@
package foo package foo
import kotlinx.jso.JsSimpleObject import kotlinx.js.JsPlainObject
@JsSimpleObject @JsPlainObject
external interface User { external interface User {
var name: String var name: String
val age: Int val age: Int
} }
@JsSimpleObject @JsPlainObject
external interface ExtendedUser : User { external interface ExtendedUser : User {
val email: String val email: String
} }
@@ -1,19 +1,19 @@
package foo package foo
import kotlinx.jso.JsSimpleObject import kotlinx.js.JsPlainObject
@JsSimpleObject @JsPlainObject
external interface User { external interface User {
var name: String var name: String
val age: Int val age: Int
} }
@JsSimpleObject @JsPlainObject
external interface Role { external interface Role {
val role: String val role: String
} }
@JsSimpleObject @JsPlainObject
external interface ExtendedUser : User, Role { external interface ExtendedUser : User, Role {
val email: String val email: String
} }
@@ -0,0 +1,27 @@
// FIR_IDENTICAL
// SKIP_TXT
// FILE: test.kt
import kotlinx.js.JsPlainObject
external interface A
external interface B
external interface C
@JsPlainObject
external interface D : <!JS_PLAIN_OBJECT_CAN_EXTEND_ONLY_OTHER_JS_PLAIN_OBJECTS!>A<!>, <!JS_PLAIN_OBJECT_CAN_EXTEND_ONLY_OTHER_JS_PLAIN_OBJECTS!>B<!>, <!JS_PLAIN_OBJECT_CAN_EXTEND_ONLY_OTHER_JS_PLAIN_OBJECTS!>C<!>
@JsPlainObject
external interface E
@JsPlainObject
external interface F
@JsPlainObject
external interface DEF: D, E, F
external interface G: A, C, <!IMPLEMENTING_OF_JS_PLAIN_OBJECT_IS_NOT_SUPPORTED!>E<!>
class Foo : A, <!IMPLEMENTING_OF_JS_PLAIN_OBJECT_IS_NOT_SUPPORTED!>D<!>, B
@@ -0,0 +1,15 @@
// FIR_IDENTICAL
// SKIP_TXT
// FILE: test.kt
import kotlinx.js.JsPlainObject
@JsPlainObject
external interface Foo {
val foo: String
val bar: Int?
val fn: () -> String
val fnOptional: (() -> String)?
<!METHODS_ARE_NOT_ALLOWED_INSIDE_JS_PLAIN_OBJECT!>fun test(): String<!>
}
@@ -2,27 +2,27 @@
// SKIP_TXT // SKIP_TXT
// FILE: test.kt // FILE: test.kt
import kotlinx.jso.JsSimpleObject import kotlinx.js.JsPlainObject
<!NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED("class")!>@JsSimpleObject <!NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED("class")!>@JsPlainObject
class Regular1<!> class Regular1<!>
@JsSimpleObject @JsPlainObject
<!NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED("object")!>object Regular2<!> <!NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED("object")!>object Regular2<!>
<!NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED("enum class")!>@JsSimpleObject <!NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED("enum class")!>@JsPlainObject
enum class Regular3<!> enum class Regular3<!>
<!ONLY_INTERFACES_ARE_SUPPORTED("class")!>@JsSimpleObject <!ONLY_INTERFACES_ARE_SUPPORTED("class")!>@JsPlainObject
external class External1<!> external class External1<!>
@JsSimpleObject @JsPlainObject
external <!ONLY_INTERFACES_ARE_SUPPORTED("object")!>object External2<!> external <!ONLY_INTERFACES_ARE_SUPPORTED("object")!>object External2<!>
@JsSimpleObject @JsPlainObject
external interface External3 external interface External3
external class Nested { external class Nested {
@JsSimpleObject @JsPlainObject
interface Inner interface Inner
} }
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.runners; package org.jetbrains.kotlinx.jspo.runners;
import com.intellij.testFramework.TestDataPath; import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil; import org.jetbrains.kotlin.test.util.KtTestUtil;
@@ -15,43 +15,43 @@ import org.junit.jupiter.api.Test;
import java.io.File; import java.io.File;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlinx.jso.TestGeneratorKt}. DO NOT MODIFY MANUALLY */ /** This class is generated by {@link org.jetbrains.kotlinx.jspo.TestGeneratorKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all") @SuppressWarnings("all")
@TestMetadata("plugins/jso/compiler-plugin/testData/box") @TestMetadata("plugins/js-plain-objects/compiler-plugin/testData/box")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
public class FirJsObjectIrJsBoxTestGenerated extends AbstractFirJsObjectIrJsBoxTest { public class FirJsPlainObjectsIrJsBoxTestGenerated extends AbstractFirJsPlainObjectsIrJsBoxTest {
@Test @Test
public void testAllFilesPresentInBox() throws Exception { public void testAllFilesPresentInBox() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/jso/compiler-plugin/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/js-plain-objects/compiler-plugin/testData/box"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
} }
@Test @Test
@TestMetadata("copy.kt") @TestMetadata("copy.kt")
public void testCopy() throws Exception { public void testCopy() throws Exception {
runTest("plugins/jso/compiler-plugin/testData/box/copy.kt"); runTest("plugins/js-plain-objects/compiler-plugin/testData/box/copy.kt");
} }
@Test @Test
@TestMetadata("optional.kt") @TestMetadata("optional.kt")
public void testOptional() throws Exception { public void testOptional() throws Exception {
runTest("plugins/jso/compiler-plugin/testData/box/optional.kt"); runTest("plugins/js-plain-objects/compiler-plugin/testData/box/optional.kt");
} }
@Test @Test
@TestMetadata("simple.kt") @TestMetadata("simple.kt")
public void testSimple() throws Exception { public void testSimple() throws Exception {
runTest("plugins/jso/compiler-plugin/testData/box/simple.kt"); runTest("plugins/js-plain-objects/compiler-plugin/testData/box/simple.kt");
} }
@Test @Test
@TestMetadata("with-inheritance.kt") @TestMetadata("with-inheritance.kt")
public void testWith_inheritance() throws Exception { public void testWith_inheritance() throws Exception {
runTest("plugins/jso/compiler-plugin/testData/box/with-inheritance.kt"); runTest("plugins/js-plain-objects/compiler-plugin/testData/box/with-inheritance.kt");
} }
@Test @Test
@TestMetadata("with-multiple-inheritance.kt") @TestMetadata("with-multiple-inheritance.kt")
public void testWith_multiple_inheritance() throws Exception { public void testWith_multiple_inheritance() throws Exception {
runTest("plugins/jso/compiler-plugin/testData/box/with-multiple-inheritance.kt"); runTest("plugins/js-plain-objects/compiler-plugin/testData/box/with-multiple-inheritance.kt");
} }
} }
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.runners; package org.jetbrains.kotlinx.jspo.runners;
import com.intellij.testFramework.TestDataPath; import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.util.KtTestUtil; import org.jetbrains.kotlin.test.util.KtTestUtil;
@@ -14,25 +14,31 @@ import org.junit.jupiter.api.Test;
import java.io.File; import java.io.File;
import java.util.regex.Pattern; import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlinx.jso.TestGeneratorKt}. DO NOT MODIFY MANUALLY */ /** This class is generated by {@link org.jetbrains.kotlinx.jspo.TestGeneratorKt}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all") @SuppressWarnings("all")
@TestMetadata("plugins/jso/compiler-plugin/testData/diagnostics") @TestMetadata("plugins/js-plain-objects/compiler-plugin/testData/diagnostics")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
public class JsObjectPluginDiagnosticTestGenerated extends AbstractJsObjectPluginDiagnosticTest { public class FirJsPlainObjectsPluginDiagnosticTestGenerated extends AbstractFirJsPlainObjectsPluginDiagnosticTest {
@Test @Test
public void testAllFilesPresentInDiagnostics() throws Exception { public void testAllFilesPresentInDiagnostics() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/jso/compiler-plugin/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true); KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/js-plain-objects/compiler-plugin/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true);
} }
@Test @Test
@TestMetadata("inheritance.kt") @TestMetadata("inheritance.kt")
public void testInheritance() throws Exception { public void testInheritance() throws Exception {
runTest("plugins/jso/compiler-plugin/testData/diagnostics/inheritance.kt"); runTest("plugins/js-plain-objects/compiler-plugin/testData/diagnostics/inheritance.kt");
}
@Test
@TestMetadata("only-properties.kt")
public void testOnly_properties() throws Exception {
runTest("plugins/js-plain-objects/compiler-plugin/testData/diagnostics/only-properties.kt");
} }
@Test @Test
@TestMetadata("wrongAnnotationTarget.kt") @TestMetadata("wrongAnnotationTarget.kt")
public void testWrongAnnotationTarget() throws Exception { public void testWrongAnnotationTarget() throws Exception {
runTest("plugins/jso/compiler-plugin/testData/diagnostics/wrongAnnotationTarget.kt"); runTest("plugins/js-plain-objects/compiler-plugin/testData/diagnostics/wrongAnnotationTarget.kt");
} }
} }
@@ -3,26 +3,26 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso package org.jetbrains.kotlinx.jspo
import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5 import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5
import org.jetbrains.kotlinx.jso.runners.AbstractFirJsObjectIrJsBoxTest import org.jetbrains.kotlinx.jspo.runners.AbstractFirJsPlainObjectsIrJsBoxTest
import org.jetbrains.kotlinx.jso.runners.AbstractJsObjectPluginDiagnosticTest import org.jetbrains.kotlinx.jspo.runners.AbstractFirJsPlainObjectsPluginDiagnosticTest
fun main(args: Array<String>) { fun main(args: Array<String>) {
generateTestGroupSuiteWithJUnit5(args) { generateTestGroupSuiteWithJUnit5(args) {
testGroup( testGroup(
"plugins/jso/compiler-plugin/tests-gen", "plugins/js-plain-objects/compiler-plugin/tests-gen",
"plugins/jso/compiler-plugin/testData" "plugins/js-plain-objects/compiler-plugin/testData"
) { ) {
// ------------------------------- diagnostics ------------------------------- // ------------------------------- diagnostics -------------------------------
testClass<AbstractJsObjectPluginDiagnosticTest>() { testClass<AbstractFirJsPlainObjectsPluginDiagnosticTest>() {
model("diagnostics") model("diagnostics")
} }
// ------------------------------- box ------------------------------- // ------------------------------- box -------------------------------
testClass<AbstractFirJsObjectIrJsBoxTest> { testClass<AbstractFirJsPlainObjectsIrJsBoxTest> {
model("box") model("box")
} }
} }
@@ -3,7 +3,7 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.runners package org.jetbrains.kotlinx.jspo.runners
import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar
import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.config.CompilerConfiguration
@@ -12,25 +12,25 @@ import org.jetbrains.kotlin.test.model.TestModule
import org.jetbrains.kotlin.test.services.EnvironmentConfigurator import org.jetbrains.kotlin.test.services.EnvironmentConfigurator
import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider
import org.jetbrains.kotlin.test.services.TestServices import org.jetbrains.kotlin.test.services.TestServices
import org.jetbrains.kotlinx.jso.compiler.cli.JsObjectComponentRegistrar import org.jetbrains.kotlinx.jspo.compiler.cli.JsPlainObjectsComponentRegistrar
import java.io.File import java.io.File
class JsObjectEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) { class JsPlainObjectsEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) {
override fun CompilerPluginRegistrar.ExtensionStorage.registerCompilerExtensions( override fun CompilerPluginRegistrar.ExtensionStorage.registerCompilerExtensions(
module: TestModule, module: TestModule,
configuration: CompilerConfiguration configuration: CompilerConfiguration
) { ) {
JsObjectComponentRegistrar.registerExtensions(this) JsPlainObjectsComponentRegistrar.registerExtensions(this)
} }
} }
class JsObjectRuntimeClasspathProvider(testServices: TestServices) : RuntimeClasspathProvider(testServices) { class JsPlainObjectsRuntimeClasspathProvider(testServices: TestServices) : RuntimeClasspathProvider(testServices) {
override fun runtimeClassPaths(module: TestModule): List<File> { override fun runtimeClassPaths(module: TestModule): List<File> {
return listOf(File(System.getProperty("jso.runtime.path"))) return listOf(File(System.getProperty("jso.runtime.path")))
} }
} }
fun TestConfigurationBuilder.configureForKotlinxJsObject() { fun TestConfigurationBuilder.configureForKotlinxJsPlainObjects() {
useConfigurators(::JsObjectEnvironmentConfigurator) useConfigurators(::JsPlainObjectsEnvironmentConfigurator)
useCustomRuntimeClasspathProviders(::JsObjectRuntimeClasspathProvider) useCustomRuntimeClasspathProviders(::JsPlainObjectsRuntimeClasspathProvider)
} }
@@ -3,18 +3,17 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.runners package org.jetbrains.kotlinx.jspo.runners
import org.jetbrains.kotlin.js.test.fir.AbstractFirJsTest import org.jetbrains.kotlin.js.test.fir.AbstractFirJsTest
import org.jetbrains.kotlin.js.test.ir.AbstractJsIrTest
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
open class AbstractFirJsObjectIrJsBoxTest : AbstractFirJsTest( open class AbstractFirJsPlainObjectsIrJsBoxTest : AbstractFirJsTest(
pathToTestDir = "plugins/kotlinx-serialization/testData/boxIr/", pathToTestDir = "plugins/kotlinx-serialization/testData/boxIr/",
testGroupOutputDirPrefix = "codegen/serializationBoxIr/" testGroupOutputDirPrefix = "codegen/serializationBoxIr/"
) { ) {
override fun configure(builder: TestConfigurationBuilder) { override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder) super.configure(builder)
builder.configureForKotlinxJsObject() builder.configureForKotlinxJsPlainObjects()
} }
} }
@@ -3,18 +3,16 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * 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.kotlinx.jso.runners package org.jetbrains.kotlinx.jspo.runners
import org.jetbrains.kotlin.platform.TargetPlatform
import org.jetbrains.kotlin.platform.js.JsPlatforms import org.jetbrains.kotlin.platform.js.JsPlatforms
import org.jetbrains.kotlin.test.TargetBackend import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives.DIAGNOSTICS import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives.DIAGNOSTICS
import org.jetbrains.kotlin.test.model.DependencyKind import org.jetbrains.kotlin.test.model.DependencyKind
import org.jetbrains.kotlin.test.runners.AbstractFirPsiDiagnosticTest import org.jetbrains.kotlin.test.runners.AbstractFirPsiDiagnosticTest
import org.jetbrains.kotlin.test.runners.configurationForClassicAndFirTestsAlongside
abstract class AbstractJsObjectPluginDiagnosticTest : AbstractFirPsiDiagnosticTest() { abstract class AbstractFirJsPlainObjectsPluginDiagnosticTest : AbstractFirPsiDiagnosticTest() {
override fun configure(builder: TestConfigurationBuilder) { override fun configure(builder: TestConfigurationBuilder) {
super.configure(builder) super.configure(builder)
with(builder) { with(builder) {
@@ -24,7 +22,7 @@ abstract class AbstractJsObjectPluginDiagnosticTest : AbstractFirPsiDiagnosticTe
dependencyKind = DependencyKind.Source dependencyKind = DependencyKind.Source
} }
configureForKotlinxJsObject() configureForKotlinxJsPlainObjects()
disableOptInErrors() disableOptInErrors()
} }
} }
@@ -1,14 +1,14 @@
import plugins.configureDefaultPublishing import plugins.configureDefaultPublishing
import plugins.configureKotlinPomAttributes import plugins.configureKotlinPomAttributes
description = "Runtime library for the JSO compiler plugin" description = "Runtime library for the JS Plain Objects compiler plugin"
plugins { plugins {
kotlin("js") kotlin("js")
`maven-publish` `maven-publish`
} }
group = "org.jetbrains.kotlinx" group = "org.jetbrains.kotlin"
kotlin { kotlin {
js { js {
@@ -26,17 +26,17 @@ val emptyJavadocJar by tasks.registering(Jar::class) {
archiveClassifier.set("javadoc") archiveClassifier.set("javadoc")
} }
configureDefaultPublishing()
publishing { publishing {
publications { publications {
create<MavenPublication>("maven") { create<MavenPublication>("maven") {
artifactId = "jso" artifactId = "kotlin-js-plain-objects"
from(components["kotlin"]) from(components["kotlin"])
configureKotlinPomAttributes(project, "Runtime library for the JSO compiler plugin", packaging = "klib") configureKotlinPomAttributes(project, "Annotations library for the JS Plain Objects compiler plugin", packaging = "klib")
} }
withType<MavenPublication> { withType<MavenPublication> {
artifact(emptyJavadocJar) artifact(emptyJavadocJar)
} }
} }
} }
configureDefaultPublishing()
@@ -3,9 +3,9 @@
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/ */
package kotlinx.jso package kotlinx.js
@Target(AnnotationTarget.CLASS) @Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.BINARY) @Retention(AnnotationRetention.BINARY)
public annotation class JsSimpleObject public annotation class JsPlainObject
@@ -1,19 +0,0 @@
plugins {
id("org.jetbrains.kotlin.jvm")
}
dependencies {
embedded(project(":plugins:jso:compiler-plugin")) { isTransitive = false }
}
publish {
artifactId = "kotlinx-jso-compiler-plugin-embeddable"
}
runtimeJar(rewriteDefaultJarDepsToShadedCompiler())
sourcesJarWithSourcesFromEmbedded(
project(":plugins:jso:compiler-plugin").tasks.named<Jar>("sourcesJar")
)
javadocJarWithJavadocFromEmbedded(
project(":plugins:jso:compiler-plugin").tasks.named<Jar>("javadocJar")
)
@@ -1,19 +0,0 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.kotlinx.jso.compiler.fir
import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar
import org.jetbrains.kotlinx.jso.compiler.fir.checkers.FirJsoCheckersComponent
import org.jetbrains.kotlinx.jso.compiler.fir.services.JsSimpleObjectPropertiesProvider
class JsObjectExtensionRegistrar : FirExtensionRegistrar() {
override fun ExtensionRegistrarContext.configurePlugin() {
+::FirJsoCheckersComponent
+::JsObjectFunctionsGenerator
// services
+::JsSimpleObjectPropertiesProvider
}
}
@@ -1,68 +0,0 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.kotlinx.jso.compiler.fir.checkers
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker
import org.jetbrains.kotlin.fir.declarations.FirClass
import org.jetbrains.kotlin.fir.declarations.hasAnnotation
import org.jetbrains.kotlin.fir.declarations.utils.isEffectivelyExternal
import org.jetbrains.kotlin.fir.declarations.utils.isExternal
import org.jetbrains.kotlin.fir.declarations.utils.isInterface
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
import org.jetbrains.kotlinx.jso.compiler.resolve.JsObjectAnnotations
object FirJsoPluginClassChecker : FirClassChecker() {
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
with(context) {
val classSymbol = declaration.symbol as? FirRegularClassSymbol ?: return
if (classSymbol.hasAnnotation(JsObjectAnnotations.jsSimpleObjectAnnotationClassId, session)) {
checkJsoAnnotationTargets(classSymbol, reporter)
} else {
checkJsoSuperInterfaces(classSymbol, reporter)
}
}
}
context(CheckerContext)
private fun checkJsoAnnotationTargets(classSymbol: FirClassSymbol<out FirClass>, reporter: DiagnosticReporter) {
val classKind = classSymbol.classKind.codeRepresentation ?: error("Unexpected enum entry")
if (!classSymbol.isEffectivelyExternal(session)) {
reporter.reportOn(classSymbol.source, FirJsoErrors.NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED, classKind)
return
}
if (!classSymbol.isInterface) {
reporter.reportOn(classSymbol.source, FirJsoErrors.ONLY_INTERFACES_ARE_SUPPORTED, classKind)
return
}
}
context(CheckerContext)
private fun checkJsoSuperInterfaces(classSymbol: FirClassSymbol<out FirClass>, reporter: DiagnosticReporter) {
classSymbol.resolvedSuperTypeRefs.forEach {
val superInterface = it.coneType.fullyExpandedType(session)
.toRegularClassSymbol(session)
?.takeIf { it.classKind == ClassKind.INTERFACE } ?: return@forEach
if (superInterface.hasAnnotation(JsObjectAnnotations.jsSimpleObjectAnnotationClassId, session)) {
reporter.reportOn(
it.source,
FirJsoErrors.IMPLEMENTING_OF_JSO_IS_NOT_SUPPORTED,
classSymbol.classId.asFqNameString()
)
}
}
}
}
@@ -1,30 +0,0 @@
/*
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
* 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.kotlinx.jso.compiler.fir.checkers
import org.jetbrains.kotlin.diagnostics.KtDiagnosticFactoryToRendererMap
import org.jetbrains.kotlin.diagnostics.rendering.BaseDiagnosticRendererFactory
import org.jetbrains.kotlin.diagnostics.rendering.CommonRenderers
object KtDefaultErrorMessagesJso : BaseDiagnosticRendererFactory() {
override val MAP = KtDiagnosticFactoryToRendererMap("JsSimpleObject").apply {
put(
FirJsoErrors.NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED,
"Non-external {0} can not be annotated with JsSimpleObject. Only external interfaces are supported.",
CommonRenderers.STRING
)
put(
FirJsoErrors.ONLY_INTERFACES_ARE_SUPPORTED,
"External {0} can not be annotated with JsSimpleObject. Only external interfaces are supported.",
CommonRenderers.STRING
)
put(
FirJsoErrors.IMPLEMENTING_OF_JSO_IS_NOT_SUPPORTED,
"[{0}] is marked as JsSimpleObject, so, it can not be used as a super-type for non-JsSimpleObject declarations",
CommonRenderers.STRING
)
}
}
@@ -1,27 +0,0 @@
// FIR_IDENTICAL
// SKIP_TXT
// FILE: test.kt
import kotlinx.jso.JsSimpleObject
external interface A
external interface B
external interface C
@JsSimpleObject
external interface D : A, B, C
@JsSimpleObject
external interface E
@JsSimpleObject
external interface F
@JsSimpleObject
external interface DEF: D, E, F
external interface G: A, C, <!IMPLEMENTING_OF_JSO_IS_NOT_SUPPORTED!>E<!>
class Foo : A, <!IMPLEMENTING_OF_JSO_IS_NOT_SUPPORTED!>D<!>, B
@@ -7,10 +7,10 @@
<!-- do_not_remove: published-with-gradle-metadata --> <!-- do_not_remove: published-with-gradle-metadata -->
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>jso</artifactId> <artifactId>js-plain-objects</artifactId>
<version>ArtifactsTest.version</version> <version>ArtifactsTest.version</version>
<name>Jso</name> <name>Js Plain Objects</name>
<description>Jso</description> <description>Js Plain Objects</description>
<url>https://kotlinlang.org/</url> <url>https://kotlinlang.org/</url>
<licenses> <licenses>
<license> <license>
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<!-- This module was also published with a richer model, Gradle metadata, -->
<!-- which should be used instead. Do not delete the following line which -->
<!-- is to indicate to Gradle or any Gradle module metadata file consumer -->
<!-- that they should prefer consuming it instead. -->
<!-- do_not_remove: published-with-gradle-metadata -->
<modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-js-plain-objects</artifactId>
<version>ArtifactsTest.version</version>
<packaging>klib</packaging>
<name>Kotlin Js Plain Objects</name>
<description>Annotations library for the JS Plain Objects compiler plugin</description>
<url>https://kotlinlang.org/</url>
<licenses>
<license>
<name>The Apache License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
</license>
</licenses>
<developers>
<developer>
<name>Kotlin Team</name>
<organization>JetBrains</organization>
<organizationUrl>https://www.jetbrains.com</organizationUrl>
</developer>
</developers>
<scm>
<connection>scm:git:https://github.com/JetBrains/kotlin.git</connection>
<developerConnection>scm:git:https://github.com/JetBrains/kotlin.git</developerConnection>
<url>https://github.com/JetBrains/kotlin</url>
</scm>
</project>
@@ -2,7 +2,7 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlinx-jso-compiler-plugin-embeddable</artifactId> <artifactId>kotlinx-js-plain-objects-compiler-plugin-embeddable</artifactId>
<version>ArtifactsTest.version</version> <version>ArtifactsTest.version</version>
<name>Compiler Plugin Embeddable</name> <name>Compiler Plugin Embeddable</name>
<description>Compiler Plugin Embeddable</description> <description>Compiler Plugin Embeddable</description>
@@ -2,10 +2,10 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>compiler-plugin</artifactId> <artifactId>kotlinx-js-plain-objects-compiler-plugin</artifactId>
<version>ArtifactsTest.version</version> <version>ArtifactsTest.version</version>
<name>Compiler Plugin</name> <name>Compiler Plugin</name>
<description>JavaScript Object Compiler Plugin</description> <description>JavaScript Plain Objects Compiler Plugin</description>
<url>https://kotlinlang.org/</url> <url>https://kotlinlang.org/</url>
<licenses> <licenses>
<license> <license>
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion> <modelVersion>4.0.0</modelVersion>
<groupId>org.jetbrains.kotlin.plugin.jso</groupId> <groupId>org.jetbrains.kotlin.plugin.js-plain-objects</groupId>
<artifactId>org.jetbrains.kotlin.plugin.jso.gradle.plugin</artifactId> <artifactId>org.jetbrains.kotlin.plugin.js-plain-objects.gradle.plugin</artifactId>
<version>ArtifactsTest.version</version> <version>ArtifactsTest.version</version>
<packaging>pom</packaging> <packaging>pom</packaging>
<name>Kotlin compiler plugin for kotlinx.jso library</name> <name>Kotlin compiler plugin for typed JS-objects library</name>
<description>Kotlin compiler plugin for kotlinx.jso library</description> <description>Kotlin compiler plugin for typed JS-objects library</description>
<url>https://kotlinlang.org/</url> <url>https://kotlinlang.org/</url>
<licenses> <licenses>
<license> <license>
@@ -29,7 +29,7 @@
<dependencies> <dependencies>
<dependency> <dependency>
<groupId>org.jetbrains.kotlin</groupId> <groupId>org.jetbrains.kotlin</groupId>
<artifactId>jso</artifactId> <artifactId>js-plain-objects</artifactId>
<version>ArtifactsTest.version</version> <version>ArtifactsTest.version</version>
</dependency> </dependency>
</dependencies> </dependencies>
+8 -8
View File
@@ -283,16 +283,16 @@ include ":kotlin-atomicfu-compiler-plugin",
":kotlinx-atomicfu-runtime", ":kotlinx-atomicfu-runtime",
":atomicfu" ":atomicfu"
include ":plugins:jso:compiler-plugin", include ":plugins:js-plain-objects:compiler-plugin",
":plugins:jso:compiler-plugin-embeddable", ":plugins:js-plain-objects:compiler-plugin-embeddable",
":plugins:jso:compiler-plugin:jso.common", ":plugins:js-plain-objects:compiler-plugin:js-plain-objects.common",
":plugins:jso:compiler-plugin:jso.k2", ":plugins:js-plain-objects:compiler-plugin:js-plain-objects.k2",
":plugins:jso:compiler-plugin:jso.backend", ":plugins:js-plain-objects:compiler-plugin:js-plain-objects.backend",
":plugins:jso:compiler-plugin:jso.cli" ":plugins:js-plain-objects:compiler-plugin:js-plain-objects.cli"
if (!buildProperties.inJpsBuildIdeaSync) { if (!buildProperties.inJpsBuildIdeaSync) {
include ":plugins:jso:runtime", include ":plugins:js-plain-objects:runtime",
":libraries:tools:jso" ":libraries:tools:js-plain-objects"
} }
include ":compiler:fir", include ":compiler:fir",