diff --git a/.space/CODEOWNERS b/.space/CODEOWNERS index 3fbc0476cf2..f00b1a38fc6 100644 --- a/.space/CODEOWNERS +++ b/.space/CODEOWNERS @@ -376,6 +376,8 @@ /plugins/kapt3/kapt3-compiler/tests-gen/ "Kotlin Compiler Core" "Kotlin JVM" /plugins/kapt4/ "Kotlin JVM" /plugins/kotlinx-serialization/ Sergey.Shanshin Leonid.Startsev +/plugins/jso/ "Kotlin JS" +/libraries/tools/jso "Kotlin JS" /plugins/lombok/ "Kotlin Compiler Core" /plugins/noarg/ "Kotlin Compiler Core" /plugins/parcelize/ "Kotlin Compiler Core" diff --git a/build.gradle.kts b/build.gradle.kts index 89816859c26..88c95fba589 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -874,6 +874,7 @@ tasks { dependsOn(":plugins:fir-plugin-prototype:fir-plugin-ic-test:test") dependsOn(":kotlin-imports-dumper-compiler-plugin:test") dependsOn(":plugins:jvm-abi-gen:test") + dependsOn(":plugins:jso:compiler-plugin:test") dependsOn(":kotlinx-serialization-compiler-plugin:test") dependsOn(":kotlin-lombok-compiler-plugin:test") dependsOn(":kotlin-noarg-compiler-plugin:test") diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt index 209b6a42873..cf0b35f3eb0 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/JsLoweringPhases.kt @@ -14,6 +14,7 @@ import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineFunc import org.jetbrains.kotlin.backend.common.lower.inline.LocalClassesInInlineLambdasLowering import org.jetbrains.kotlin.backend.common.lower.loops.ForLoopsLowering import org.jetbrains.kotlin.backend.common.phaser.* +import org.jetbrains.kotlin.config.CommonConfigurationKeys import org.jetbrains.kotlin.ir.backend.js.lower.* import org.jetbrains.kotlin.ir.backend.js.lower.calls.CallsLowering import org.jetbrains.kotlin.ir.backend.js.lower.cleanup.CleanupLowering diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt index 74cf3cd313c..7282d1d1fda 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/IrElementToJsExpressionTransformer.kt @@ -148,7 +148,10 @@ class IrElementToJsExpressionTransformer : BaseIrElementToJsNodeTransformer JsNullLiteral() + else -> context.getRefForExternalClass(obj).withSource(expression, context) + } } override fun visitSetField(expression: IrSetField, context: JsGenerationContext): JsExpression { diff --git a/libraries/tools/jso/build.gradle.kts b/libraries/tools/jso/build.gradle.kts new file mode 100644 index 00000000000..73e3739890d --- /dev/null +++ b/libraries/tools/jso/build.gradle.kts @@ -0,0 +1,18 @@ +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" + } + } +} \ No newline at end of file diff --git a/libraries/tools/jso/src/common/kotlin/org/jetbrains/kotlinx/jso/gradle/JsoKotlinGradleSubplugin.kt b/libraries/tools/jso/src/common/kotlin/org/jetbrains/kotlinx/jso/gradle/JsoKotlinGradleSubplugin.kt new file mode 100644 index 00000000000..011e012d778 --- /dev/null +++ b/libraries/tools/jso/src/common/kotlin/org/jetbrains/kotlinx/jso/gradle/JsoKotlinGradleSubplugin.kt @@ -0,0 +1,43 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlinx.jso.gradle + +import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.plugin.* + +class JsoKotlinGradleSubplugin : KotlinCompilerPluginSupportPlugin { + companion object { + const val JSO_ARTIFACT_NAME = "kotlinx-jso-compiler-plugin-embeddable" + } + + override fun isApplicable(kotlinCompilation: KotlinCompilation<*>): Boolean = + kotlinCompilation.target.isJs() || kotlinCompilation.target.isWasm() + + override fun applyToCompilation( + kotlinCompilation: KotlinCompilation<*> + ): Provider> = + kotlinCompilation.target.project.provider { emptyList() } + + override fun getPluginArtifact(): SubpluginArtifact = + JetBrainsSubpluginArtifact(JSO_ARTIFACT_NAME) + + override fun getCompilerPluginId() = "org.jetbrains.kotlinx.jso" + + private fun KotlinTarget.isJs() = platformType == KotlinPlatformType.js + + private fun KotlinTarget.isWasm() = platformType == KotlinPlatformType.wasm +} diff --git a/libraries/tools/jso/src/common/resources/META-INF/gradle-plugins/kotlinx-jso.properties b/libraries/tools/jso/src/common/resources/META-INF/gradle-plugins/kotlinx-jso.properties new file mode 100644 index 00000000000..39526c33a9a --- /dev/null +++ b/libraries/tools/jso/src/common/resources/META-INF/gradle-plugins/kotlinx-jso.properties @@ -0,0 +1 @@ +implementation-class=org.jetbrains.kotlinx.jso.gradle.JsoKotlinGradleSubplugin \ No newline at end of file diff --git a/plugins/jso/compiler-plugin-embeddable/build.gradle.kts b/plugins/jso/compiler-plugin-embeddable/build.gradle.kts new file mode 100644 index 00000000000..95875d08434 --- /dev/null +++ b/plugins/jso/compiler-plugin-embeddable/build.gradle.kts @@ -0,0 +1,19 @@ +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("sourcesJar") +) +javadocJarWithJavadocFromEmbedded( + project(":plugins:jso:compiler-plugin").tasks.named("javadocJar") +) diff --git a/plugins/jso/compiler-plugin/build.gradle.kts b/plugins/jso/compiler-plugin/build.gradle.kts new file mode 100644 index 00000000000..319aa0d6317 --- /dev/null +++ b/plugins/jso/compiler-plugin/build.gradle.kts @@ -0,0 +1,88 @@ +import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages +import org.jetbrains.kotlin.gradle.targets.js.KotlinJsCompilerAttribute + +description = "JavaScript Object Compiler Plugin" + +plugins { + kotlin("jvm") + id("jps-compatible") +} + +val jsoIrRuntimeForTests by configurations.creating { + attributes { + attribute(KotlinPlatformType.attribute, KotlinPlatformType.js) + attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, KotlinJsCompilerAttribute.ir) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_RUNTIME)) + } +} + +dependencies { + embedded(project(":plugins:jso:compiler-plugin:jso.common")) { isTransitive = false } + embedded(project(":plugins:jso:compiler-plugin:jso.k2")) { isTransitive = false } + embedded(project(":plugins:jso:compiler-plugin:jso.backend")) { isTransitive = false } + embedded(project(":plugins:jso:compiler-plugin:jso.cli")) { isTransitive = false } + + testApi(project(":compiler:backend")) + testApi(project(":compiler:cli")) + testApi(project(":plugins:jso:compiler-plugin:jso.cli")) + + testApi(projectTests(":compiler:test-infrastructure")) + testApi(projectTests(":compiler:test-infrastructure-utils")) + testApi(projectTests(":compiler:tests-compiler-utils")) + testApi(projectTests(":compiler:tests-common-new")) + + testImplementation(projectTests(":js:js.tests")) + testImplementation(projectTests(":generators:test-generator")) + + testApi(platform(libs.junit.bom)) + testImplementation(libs.junit.jupiter.api) + testRuntimeOnly(libs.junit.jupiter.engine) + + jsoIrRuntimeForTests(project(":plugins:jso:runtime")) { isTransitive = false } + + embedded(project(":plugins:jso:runtime")) { + attributes { + attribute(KotlinPlatformType.attribute, KotlinPlatformType.js) + attribute(KotlinJsCompilerAttribute.jsCompilerAttribute, KotlinJsCompilerAttribute.ir) + attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_RUNTIME)) + } + isTransitive = false + } + + testRuntimeOnly(project(":core:descriptors.runtime")) +} + +optInToExperimentalCompilerApi() + +sourceSets { + "main" { none() } + "test" { + projectDefault() + generatedTestDir() + } +} + +publish() + +runtimeJar() +sourcesJar() +javadocJar() +testsJar() + +projectTest(parallel = true, jUnitMode = JUnitMode.JUnit5) { + useJUnitPlatform() + useJsIrBoxTests(version = version, buildDir = layout.buildDirectory) + + workingDir = rootDir + + dependsOn(jsoIrRuntimeForTests) + + val localJsoIrRuntimePath: FileCollection = jsoIrRuntimeForTests + + doFirst { + systemProperty("jso.runtime.path", localJsoIrRuntimePath.asPath) + } +} + +val generateTests by generator("org.jetbrains.kotlinx.jso.TestGeneratorKt") \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/jso.backend/build.gradle.kts b/plugins/jso/compiler-plugin/jso.backend/build.gradle.kts new file mode 100644 index 00000000000..c8a9e8bcfc3 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.backend/build.gradle.kts @@ -0,0 +1,25 @@ +description = "Kotlin JavaScript Object Compiler Plugin (Backend)" + +plugins { + kotlin("jvm") + id("jps-compatible") +} + +dependencies { + compileOnly(project(":compiler:backend")) + compileOnly(project(":compiler:ir.backend.common")) + compileOnly(project(":compiler:ir.tree")) + + implementation(project(":plugins:jso:compiler-plugin:jso.common")) + + compileOnly(intellijCore()) +} + +sourceSets { + "main" { projectDefault() } + "test" { none() } +} + +runtimeJar() +sourcesJar() +javadocJar() diff --git a/plugins/jso/compiler-plugin/jso.backend/src/org/jetbrains/kotlinx/jso/compiler/backend/JsObjectLoweringExtension.kt b/plugins/jso/compiler-plugin/jso.backend/src/org/jetbrains/kotlinx/jso/compiler/backend/JsObjectLoweringExtension.kt new file mode 100644 index 00000000000..d28a2ced868 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.backend/src/org/jetbrains/kotlinx/jso/compiler/backend/JsObjectLoweringExtension.kt @@ -0,0 +1,73 @@ +/* + * 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.backend + +import org.jetbrains.kotlin.backend.common.DeclarationTransformer +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext +import org.jetbrains.kotlin.backend.common.lower +import org.jetbrains.kotlin.builtins.StandardNames +import org.jetbrains.kotlin.ir.declarations.* +import org.jetbrains.kotlin.ir.expressions.IrBlockBody +import org.jetbrains.kotlin.ir.expressions.impl.* +import org.jetbrains.kotlin.ir.symbols.UnsafeDuringIrConstructionAPI +import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlinx.jso.compiler.resolve.JsSimpleObjectPluginKey +import org.jetbrains.kotlinx.jso.compiler.resolve.StandardIds + +private class MoveExternalInlineFunctionsWithBodiesOutsideLowering(private val context: IrPluginContext) : DeclarationTransformer { + private val jsFunction = context.referenceFunctions(StandardIds.JS_FUNCTION_ID).single() + private val EXPECTED_ORIGIN = IrDeclarationOrigin.GeneratedByPlugin(JsSimpleObjectPluginKey) + + @OptIn(UnsafeDuringIrConstructionAPI::class) + override fun transformFlat(declaration: IrDeclaration): List? { + val file = declaration.file + val parent = declaration.parentClassOrNull + + if (parent == null || declaration !is IrSimpleFunction || declaration.origin != EXPECTED_ORIGIN) return null + + file.declarations.add(declaration) + + declaration.body = when (declaration.name) { + StandardNames.DATA_CLASS_COPY, OperatorNameConventions.INVOKE -> declaration.generateBodyForFactoryAndCopyFunction() + else -> error("Unexpected function with name `${declaration.name.identifier}`") + } + + declaration.parent = file + declaration.isExternal = false + + return emptyList() + } + + private fun IrSimpleFunction.generateBodyForFactoryAndCopyFunction(): IrBlockBody { + val declaration = this + return context.irFactory.createBlockBody(startOffset, declaration.endOffset).apply { + statements += IrReturnImpl( + declaration.startOffset, + declaration.endOffset, + declaration.returnType, + declaration.symbol, + IrCallImpl( + declaration.startOffset, + declaration.endOffset, + declaration.returnType, + jsFunction, + 0, + 1, + ).apply { + val jsObject = "{ ${declaration.valueParameters.joinToString(", ") { "${it.name.identifier}:${it.name.identifier}" }} }" + putValueArgument(0, jsObject.toIrConst(context.irBuiltIns.stringType)) + } + ) + } + } +} + +open class JsObjectLoweringExtension : IrGenerationExtension { + override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { + MoveExternalInlineFunctionsWithBodiesOutsideLowering(pluginContext).lower(moduleFragment) + } +} diff --git a/plugins/jso/compiler-plugin/jso.cli/build.gradle.kts b/plugins/jso/compiler-plugin/jso.cli/build.gradle.kts new file mode 100644 index 00000000000..0449833fdfa --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.cli/build.gradle.kts @@ -0,0 +1,31 @@ +description = "Kotlin JavaScript Object Compiler Plugin (CLI)" + +plugins { + kotlin("jvm") + id("jps-compatible") +} + +dependencies { + compileOnly(project(":compiler:util")) + compileOnly(project(":compiler:cli")) + compileOnly(project(":compiler:plugin-api")) + compileOnly(project(":compiler:fir:entrypoint")) + compileOnly(project(":compiler:ir.backend.common")) + + implementation(project(":plugins:jso:compiler-plugin:jso.common")) + implementation(project(":plugins:jso:compiler-plugin:jso.backend")) + implementation(project(":plugins:jso:compiler-plugin:jso.k2")) + + compileOnly(intellijCore()) +} + +optInToExperimentalCompilerApi() + +sourceSets { + "main" { projectDefault() } + "test" { none() } +} + +runtimeJar() +sourcesJar() +javadocJar() diff --git a/plugins/jso/compiler-plugin/jso.cli/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar b/plugins/jso/compiler-plugin/jso.cli/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar new file mode 100644 index 00000000000..c28bd958547 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.cli/resources/META-INF/services/org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar @@ -0,0 +1,17 @@ +# +# Copyright 2010-2023 JetBrains s.r.o. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +org.jetbrains.kotlinx.jso.compiler.cli.JsObjectComponentRegistrar \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/jso.cli/src/org/jetbrains/kotlinx/jso/compiler/cli/JsObjectComponentRegistrar.kt b/plugins/jso/compiler-plugin/jso.cli/src/org/jetbrains/kotlinx/jso/compiler/cli/JsObjectComponentRegistrar.kt new file mode 100644 index 00000000000..c7e48cb7596 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.cli/src/org/jetbrains/kotlinx/jso/compiler/cli/JsObjectComponentRegistrar.kt @@ -0,0 +1,28 @@ +/* + * 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.cli + +import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter +import org.jetbrains.kotlinx.jso.compiler.backend.JsObjectLoweringExtension +import org.jetbrains.kotlinx.jso.compiler.fir.JsObjectExtensionRegistrar + +class JsObjectComponentRegistrar : CompilerPluginRegistrar() { + override val supportsK2: Boolean get() = true + + override fun ExtensionStorage.registerExtensions(configuration: CompilerConfiguration) { + Companion.registerExtensions(this) + } + + companion object { + fun registerExtensions(extensionStorage: ExtensionStorage) = with(extensionStorage) { + FirExtensionRegistrarAdapter.registerExtension(JsObjectExtensionRegistrar()) + IrGenerationExtension.registerExtension(JsObjectLoweringExtension()) + } + } +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/jso.common/build.gradle.kts b/plugins/jso/compiler-plugin/jso.common/build.gradle.kts new file mode 100644 index 00000000000..fba05fc08cc --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.common/build.gradle.kts @@ -0,0 +1,21 @@ +description = "Kotlin JavaScript Object Compiler Plugin (Common)" + +plugins { + kotlin("jvm") + id("jps-compatible") +} + +dependencies { + compileOnly(project(":compiler:util")) + compileOnly(project(":core:compiler.common")) + compileOnly(intellijCore()) +} + +sourceSets { + "main" { projectDefault() } + "test" { none() } +} + +runtimeJar() +sourcesJar() +javadocJar() diff --git a/plugins/jso/compiler-plugin/jso.common/src/org/jetbrains/kotlinx/jso/compiler/resolve/JsSimpleObjectPluginKey.kt b/plugins/jso/compiler-plugin/jso.common/src/org/jetbrains/kotlinx/jso/compiler/resolve/JsSimpleObjectPluginKey.kt new file mode 100644 index 00000000000..aa077ceb768 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.common/src/org/jetbrains/kotlinx/jso/compiler/resolve/JsSimpleObjectPluginKey.kt @@ -0,0 +1,14 @@ +/* + * 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.resolve + +import org.jetbrains.kotlin.GeneratedDeclarationKey + +object JsSimpleObjectPluginKey : GeneratedDeclarationKey() { + override fun toString(): String { + return "KotlinxJsSimpleObjectPlugin" + } +} diff --git a/plugins/jso/compiler-plugin/jso.common/src/org/jetbrains/kotlinx/jso/compiler/resolve/NamingConventions.kt b/plugins/jso/compiler-plugin/jso.common/src/org/jetbrains/kotlinx/jso/compiler/resolve/NamingConventions.kt new file mode 100644 index 00000000000..0274a3a3661 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.common/src/org/jetbrains/kotlinx/jso/compiler/resolve/NamingConventions.kt @@ -0,0 +1,21 @@ +/* + * 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.resolve; + +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +object StandardIds { + val KOTLIN_JS_FQN = FqName("kotlin.js") + val JS_FUNCTION_ID = CallableId(KOTLIN_JS_FQN, Name.identifier("js")) +} + +object JsObjectAnnotations { + val jsSimpleObjectAnnotationClassId = ClassId(FqName("kotlinx.jso"), Name.identifier("JsSimpleObject")) + val jsSimpleObjectAnnotationFqName = jsSimpleObjectAnnotationClassId.asSingleFqName() +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/jso.k2/build.gradle.kts b/plugins/jso/compiler-plugin/jso.k2/build.gradle.kts new file mode 100644 index 00000000000..61a364a7c5e --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/build.gradle.kts @@ -0,0 +1,34 @@ +description = "Kotlin JavaScript Object Compiler Plugin (K2)" + +plugins { + kotlin("jvm") + id("jps-compatible") +} + +dependencies { + compileOnly(project(":compiler:fir:cones")) + compileOnly(project(":compiler:fir:tree")) + compileOnly(project(":compiler:fir:resolve")) + compileOnly(project(":compiler:fir:plugin-utils")) + compileOnly(project(":compiler:fir:entrypoint")) + compileOnly(project(":compiler:cli-common")) + + implementation(project(":plugins:jso:compiler-plugin:jso.common")) + + compileOnly(intellijCore()) + + testApi(project(":compiler:fir:plugin-utils")) +} + +sourceSets { + "main" { projectDefault() } + "test" { none() } +} + +runtimeJar() +sourcesJar() +javadocJar() + +tasks.withType().configureEach { + compilerOptions.freeCompilerArgs.add("-Xcontext-receivers") +} diff --git a/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectExtensionRegistrar.kt b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectExtensionRegistrar.kt new file mode 100644 index 00000000000..b80cac4d20b --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectExtensionRegistrar.kt @@ -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.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 + } +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectFunctionsGenerator.kt b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectFunctionsGenerator.kt new file mode 100644 index 00000000000..8b42012f9a0 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectFunctionsGenerator.kt @@ -0,0 +1,253 @@ +/* + * 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.builtins.StandardNames +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Modality +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirFunctionTarget +import org.jetbrains.kotlin.fir.FirSession +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.FirSimpleFunction +import org.jetbrains.kotlin.fir.declarations.builder.FirSimpleFunctionBuilder +import org.jetbrains.kotlin.fir.declarations.builder.buildRegularClass +import org.jetbrains.kotlin.fir.declarations.builder.buildSimpleFunction +import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter +import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedDeclarationStatusImpl +import org.jetbrains.kotlin.fir.declarations.origin +import org.jetbrains.kotlin.fir.declarations.utils.isCompanion +import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.expressions.FirExpression +import org.jetbrains.kotlin.fir.expressions.builder.* +import org.jetbrains.kotlin.fir.extensions.FirDeclarationGenerationExtension +import org.jetbrains.kotlin.fir.extensions.MemberGenerationContext +import org.jetbrains.kotlin.fir.extensions.NestedClassGenerationContext +import org.jetbrains.kotlin.fir.extensions.predicateBasedProvider +import org.jetbrains.kotlin.fir.moduleData +import org.jetbrains.kotlin.fir.references.builder.buildImplicitThisReference +import org.jetbrains.kotlin.fir.references.builder.buildResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.defaultType +import org.jetbrains.kotlin.fir.scopes.kotlinScopeProvider +import org.jetbrains.kotlin.fir.symbols.SymbolInternals +import org.jetbrains.kotlin.fir.symbols.impl.* +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.toFirResolvedTypeRef +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.SpecialNames +import org.jetbrains.kotlin.name.StandardClassIds +import org.jetbrains.kotlin.types.ConstantValueKind +import org.jetbrains.kotlin.util.OperatorNameConventions +import org.jetbrains.kotlin.utils.addToStdlib.runIf +import org.jetbrains.kotlinx.jso.compiler.fir.services.jsObjectPropertiesProvider +import org.jetbrains.kotlinx.jso.compiler.resolve.JsSimpleObjectPluginKey + +/** + * The extension generate a synthetic factory and copy-method for an `external interface` annotated with @JsSimpleObject + * Imagine the next interfaces: + * ``` + * external interface User { + * val name: String + * } + * @JsSimpleObject + * external interface Admin { + * val chat: Chat + * } + * ``` + * + * For the interface `Admin` this function should generate the companion inline function: + * ``` + * external interface Admin { + * val chat: Chat + * + * inline fun copy(chat: Chat = this.chat, name: String = this.name): Admin = + * Admin.Companion.invoke(chat, name) + * + * companion object { + * inline operator fun invoke(chat: Chat, name: String): Admin = + * js("{ chat: chat, name: name }") + * } + * } + * ``` + */ +class JsObjectFunctionsGenerator(session: FirSession) : FirDeclarationGenerationExtension(session) { + private val predicateBasedProvider = session.predicateBasedProvider + + private val matchedInterfaces by lazy { + predicateBasedProvider.getSymbolsByPredicate(JsObjectPredicates.AnnotatedWithJsSimpleObject.LOOKUP) + .filterIsInstance() + .toSet() + } + + private val factoryFqNamesToJsObjectInterface by lazy { + matchedInterfaces.associateBy { it.classId.asSingleFqName() } + } + + private val FirClassLikeSymbol<*>.isJsObject: Boolean + get() = this is FirRegularClassSymbol && this in matchedInterfaces + + override fun getNestedClassifiersNames(classSymbol: FirClassSymbol<*>, context: NestedClassGenerationContext): Set { + return if (classSymbol.isJsObject) setOf(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT) else emptySet() + } + + override fun generateNestedClassLikeDeclaration( + owner: FirClassSymbol<*>, + name: Name, + context: NestedClassGenerationContext + ): FirClassLikeSymbol<*>? { + return if ( + owner is FirRegularClassSymbol && + owner.isJsObject && + name == org.jetbrains.kotlin.name.SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT + ) generateCompanionDeclaration(owner) + else null + } + + private fun generateCompanionDeclaration(owner: FirRegularClassSymbol): FirRegularClassSymbol? { + if (owner.companionObjectSymbol != null) return null + val classId = owner.classId.createNestedClassId(SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT) + return buildRegularClass { + resolvePhase = FirResolvePhase.BODY_RESOLVE + moduleData = session.moduleData + origin = JsSimpleObjectPluginKey.origin + classKind = ClassKind.OBJECT + scopeProvider = session.kotlinScopeProvider + status = FirResolvedDeclarationStatusImpl( + Visibilities.Public, + Modality.FINAL, + Visibilities.Public.toEffectiveVisibility(owner, forClass = true) + ).apply { + isExternal = true + isCompanion = true + } + name = classId.shortClassName + symbol = FirRegularClassSymbol(classId) + }.symbol + } + + override fun getCallableNamesForClass(classSymbol: FirClassSymbol<*>, context: MemberGenerationContext): Set { + val outerClass = classSymbol.getContainingClassSymbol(session) + return when { + classSymbol.isCompanion && outerClass?.isJsObject == true -> setOf(OperatorNameConventions.INVOKE) + classSymbol.isJsObject -> setOf(StandardNames.DATA_CLASS_COPY) + else -> emptySet() + } + } + + override fun generateFunctions(callableId: CallableId, context: MemberGenerationContext?): List { + if (context == null) return emptyList() + + val containingClass = callableId.classId + val possibleInterface = containingClass?.outerClassId + + return when (callableId.callableName) { + StandardNames.DATA_CLASS_COPY -> { + containingClass + ?.let { factoryFqNamesToJsObjectInterface[it.asSingleFqName()] } + ?.let { listOf(createJsObjectCopyFunction(callableId, context.owner, it).symbol) } ?: emptyList() + } + OperatorNameConventions.INVOKE -> { + possibleInterface + ?.takeIf { context.owner.isCompanion } + ?.let { factoryFqNamesToJsObjectInterface[it.asSingleFqName()] } + ?.let { listOf(createJsObjectFactoryFunction(callableId, context.owner, it).symbol) } ?: emptyList() + } + else -> emptyList() + } + } + + private fun createJsObjectFactoryFunction( + callableId: CallableId, + parent: FirClassSymbol<*>, + jsSimpleObjectInterface: FirRegularClassSymbol, + ): FirSimpleFunction { + return createJsObjectFunction(callableId, parent, jsSimpleObjectInterface) { + runIf(resolvedReturnTypeRef.type.isNullable) { + buildConstExpression( + source = null, + value = null, + kind = ConstantValueKind.Null, + setType = true + ) + } + } + } + + private fun createJsObjectCopyFunction( + callableId: CallableId, + parent: FirClassSymbol<*>, + jsSimpleObjectInterface: FirRegularClassSymbol, + ): FirSimpleFunction { + val interfaceType = jsSimpleObjectInterface.defaultType() + return createJsObjectFunction(callableId, parent, jsSimpleObjectInterface) { + buildPropertyAccessExpression { + dispatchReceiver = buildThisReceiverExpression { + calleeReference = buildImplicitThisReference { boundSymbol = jsSimpleObjectInterface } + coneTypeOrNull = interfaceType + } + calleeReference = buildResolvedNamedReference { + name = this@createJsObjectFunction.name + resolvedSymbol = this@createJsObjectFunction + } + coneTypeOrNull = resolvedReturnType + } + } + } + + @OptIn(SymbolInternals::class) + private fun createJsObjectFunction( + callableId: CallableId, + parent: FirClassSymbol<*>, + jsSimpleObjectInterface: FirRegularClassSymbol, + getParameterDefaultValueFromProperty: FirPropertySymbol.() -> FirExpression? + ): FirSimpleFunction { + val jsSimpleObjectProperties = session.jsObjectPropertiesProvider.getJsObjectPropertiesForClass(jsSimpleObjectInterface) + val functionTarget = FirFunctionTarget(null, isLambda = false) + val jsSimpleObjectInterfaceDefaultType = jsSimpleObjectInterface.defaultType() + + return buildSimpleFunction { + moduleData = jsSimpleObjectInterface.moduleData + resolvePhase = FirResolvePhase.BODY_RESOLVE + origin = JsSimpleObjectPluginKey.origin + symbol = FirNamedFunctionSymbol(callableId) + name = callableId.callableName + returnTypeRef = jsSimpleObjectInterfaceDefaultType.toFirResolvedTypeRef() + + status = FirResolvedDeclarationStatusImpl( + jsSimpleObjectInterface.visibility, + Modality.FINAL, + jsSimpleObjectInterface.visibility.toEffectiveVisibility(parent, forClass = true) + ).apply { + isInline = true + isOperator = true + } + + dispatchReceiverType = parent.defaultType() + jsSimpleObjectInterface.typeParameterSymbols.mapTo(typeParameters) { it.fir } + jsSimpleObjectProperties.mapTo(valueParameters) { + val typeRef = it.resolvedReturnTypeRef + buildValueParameter { + moduleData = session.moduleData + origin = JsSimpleObjectPluginKey.origin + returnTypeRef = typeRef + name = it.name + symbol = FirValueParameterSymbol(it.name) + isCrossinline = false + isNoinline = true + isVararg = false + resolvePhase = FirResolvePhase.BODY_RESOLVE + containingFunctionSymbol = this@buildSimpleFunction.symbol + defaultValue = it.getParameterDefaultValueFromProperty() + } + } + }.also(functionTarget::bind) + } +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectPredicates.kt b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectPredicates.kt new file mode 100644 index 00000000000..f349d1519ba --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/JsObjectPredicates.kt @@ -0,0 +1,17 @@ +/* + * 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.predicate.DeclarationPredicate +import org.jetbrains.kotlin.fir.extensions.predicate.LookupPredicate +import org.jetbrains.kotlinx.jso.compiler.resolve.JsObjectAnnotations + +object JsObjectPredicates { + internal object AnnotatedWithJsSimpleObject { + private val jsSimpleObjectAnnotation = setOf(JsObjectAnnotations.jsSimpleObjectAnnotationFqName) + internal val LOOKUP = LookupPredicate.create { annotated(jsSimpleObjectAnnotation) } + internal val DECLARATION = DeclarationPredicate.create { annotated(jsSimpleObjectAnnotation) } + } +} diff --git a/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoCheckersComponent.kt b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoCheckersComponent.kt new file mode 100644 index 00000000000..7d57d0698ab --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoCheckersComponent.kt @@ -0,0 +1,17 @@ +/* + * 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.fir.FirSession +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.DeclarationCheckers +import org.jetbrains.kotlin.fir.analysis.checkers.declaration.FirClassChecker +import org.jetbrains.kotlin.fir.analysis.extensions.FirAdditionalCheckersExtension + +class FirJsoCheckersComponent(session: FirSession) : FirAdditionalCheckersExtension(session) { + override val declarationCheckers: DeclarationCheckers = object : DeclarationCheckers() { + override val classCheckers: Set = setOf(FirJsoPluginClassChecker) + } +} diff --git a/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoErrors.kt b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoErrors.kt new file mode 100644 index 00000000000..7c4db90d5f2 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoErrors.kt @@ -0,0 +1,24 @@ +/* + * 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 com.intellij.psi.PsiElement +import org.jetbrains.kotlin.diagnostics.* +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 { + val NON_EXTERNAL_DECLARATIONS_NOT_SUPPORTED by error1() + val ONLY_INTERFACES_ARE_SUPPORTED by error1() + val IMPLEMENTING_OF_JSO_IS_NOT_SUPPORTED by error1() + + init { + RootDiagnosticRendererFactory.registerFactory(KtDefaultErrorMessagesJso) + } +} diff --git a/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoPluginClassChecker.kt b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoPluginClassChecker.kt new file mode 100644 index 00000000000..72230e080f0 --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/FirJsoPluginClassChecker.kt @@ -0,0 +1,68 @@ +/* + * 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, 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, 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() + ) + } + } + } +} diff --git a/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/KtDefaultErrorMessagesJso.kt b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/KtDefaultErrorMessagesJso.kt new file mode 100644 index 00000000000..f625581d13f --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/checkers/KtDefaultErrorMessagesJso.kt @@ -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.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 + ) + } +} diff --git a/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/services/JsSimpleObjectPropertiesProvider.kt b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/services/JsSimpleObjectPropertiesProvider.kt new file mode 100644 index 00000000000..df5cb35492a --- /dev/null +++ b/plugins/jso/compiler-plugin/jso.k2/src/org/jetbrains/kotlinx/jso/compiler/fir/services/JsSimpleObjectPropertiesProvider.kt @@ -0,0 +1,64 @@ +/* + * 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.services + +import org.jetbrains.kotlin.descriptors.ClassKind +import org.jetbrains.kotlin.descriptors.Visibilities +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.caches.FirCache +import org.jetbrains.kotlin.fir.caches.createCache +import org.jetbrains.kotlin.fir.caches.firCachesFactory +import org.jetbrains.kotlin.fir.caches.getValue +import org.jetbrains.kotlin.fir.declarations.hasAnnotation +import org.jetbrains.kotlin.fir.declarations.utils.visibility +import org.jetbrains.kotlin.fir.extensions.FirDeclarationPredicateRegistrar +import org.jetbrains.kotlin.fir.extensions.FirExtensionSessionComponent +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.scopes.impl.declaredMemberScope +import org.jetbrains.kotlin.fir.scopes.processAllProperties +import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol +import org.jetbrains.kotlin.fir.types.toRegularClassSymbol +import org.jetbrains.kotlin.utils.addIfNotNull +import org.jetbrains.kotlinx.jso.compiler.fir.JsObjectPredicates +import org.jetbrains.kotlinx.jso.compiler.resolve.JsObjectAnnotations + +class JsSimpleObjectPropertiesProvider(session: FirSession) : FirExtensionSessionComponent(session) { + private val cache: FirCache, List, Nothing?> = + session.firCachesFactory.createCache(this::createJsSimpleObjectProperties) + + override fun FirDeclarationPredicateRegistrar.registerPredicates() { + register(JsObjectPredicates.AnnotatedWithJsSimpleObject.DECLARATION) + } + + fun getJsObjectPropertiesForClass(classSymbol: FirClassSymbol<*>): List { + return cache.getValue(classSymbol) + } + + private fun createJsSimpleObjectProperties(classSymbol: FirClassSymbol<*>): List = + if (!classSymbol.hasAnnotation(JsObjectAnnotations.jsSimpleObjectAnnotationClassId, session)) { + emptyList() + } else { + buildList { + classSymbol.resolvedSuperTypes.forEach { + val superInterface = it.fullyExpandedType(session) + .toRegularClassSymbol(session) + ?.takeIf { it.classKind == ClassKind.INTERFACE } ?: return@forEach + + val superInterfaceSimpleObjectProperties = createJsSimpleObjectProperties(superInterface) + superInterfaceSimpleObjectProperties.forEach(::addIfNotNull) + } + + classSymbol + .declaredMemberScope(session, null) + .processAllProperties { + addIfNotNull(it.takeIf { it.visibility == Visibilities.Public } as? FirPropertySymbol) + } + } + } +} + +val FirSession.jsObjectPropertiesProvider: JsSimpleObjectPropertiesProvider by FirSession.sessionComponentAccessor() \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/testData/box/copy.kt b/plugins/jso/compiler-plugin/testData/box/copy.kt new file mode 100644 index 00000000000..29586b8233d --- /dev/null +++ b/plugins/jso/compiler-plugin/testData/box/copy.kt @@ -0,0 +1,25 @@ +package foo + +import kotlinx.jso.JsSimpleObject + +@JsSimpleObject +external interface User { + var name: String + val age: Int +} + +fun box(): String { + val user = User(name = "Name", age = 10) + val copy = user.copy(age = 11) + + if (copy === user) return "Fail: mutation instead of immutable copy" + + val json = js("JSON.stringify(copy)") + + if (copy.name != "Name") return "Fail: problem with copied `name` property" + if (copy.age != 11) return "Fail: problem with copied `age` property" + + if (json != "{\"age\":11,\"name\":\"Name\"}") return "Fail: got the next json for the copy: $json" + + return "OK" +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/testData/box/optional.kt b/plugins/jso/compiler-plugin/testData/box/optional.kt new file mode 100644 index 00000000000..4d8f8c09ca0 --- /dev/null +++ b/plugins/jso/compiler-plugin/testData/box/optional.kt @@ -0,0 +1,31 @@ +package foo + +import kotlinx.jso.JsSimpleObject + +@JsSimpleObject +external interface User { + var name: String + val age: Int + val email: String? +} + +fun box(): String { + val user = User(name = "Name", age = 10) + + if (user.name != "Name") return "Fail: problem with `name` property" + if (user.age != 10) return "Fail: problem with `age` property" + + val json = js("JSON.stringify(user)") + if (json != "{\"email\":null,\"age\":10,\"name\":\"Name\"}") return "Fail: got the next json: $json" + + val withEmail = User(name = "Name", age = 10, email = "test@test") + + if (withEmail.name != "Name") return "Fail: problem with emailed `name` property" + if (withEmail.age != 10) return "Fail: problem with emailed `age` property" + if (withEmail.email != "test@test") return "Fail: problem with emailed `email` property" + + val jsonWithEmail = js("JSON.stringify(withEmail)") + if (jsonWithEmail != "{\"email\":\"test@test\",\"age\":10,\"name\":\"Name\"}") return "Fail: got the next emailed json: $jsonWithEmail" + + return "OK" +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/testData/box/simple.kt b/plugins/jso/compiler-plugin/testData/box/simple.kt new file mode 100644 index 00000000000..ac86451cf41 --- /dev/null +++ b/plugins/jso/compiler-plugin/testData/box/simple.kt @@ -0,0 +1,21 @@ +package foo + +import kotlinx.jso.JsSimpleObject + +@JsSimpleObject +external interface User { + var name: String + val age: Int +} + +fun box(): String { + val user = User(name = "Name", age = 10) + + if (user.name != "Name") return "Fail: problem with `name` property" + if (user.age != 10) return "Fail: problem with `age` property" + + val json = js("JSON.stringify(user)") + if (json != "{\"age\":10,\"name\":\"Name\"}") return "Fail: got the next json: $json" + + return "OK" +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/testData/box/with-inheritance.kt b/plugins/jso/compiler-plugin/testData/box/with-inheritance.kt new file mode 100644 index 00000000000..8da2dca6b31 --- /dev/null +++ b/plugins/jso/compiler-plugin/testData/box/with-inheritance.kt @@ -0,0 +1,28 @@ +package foo + +import kotlinx.jso.JsSimpleObject + +@JsSimpleObject +external interface User { + var name: String + val age: Int +} + +@JsSimpleObject +external interface ExtendedUser : User { + val email: String +} + + +fun box(): String { + val user = ExtendedUser(name = "Name", age = 10, email = "test@test") + + if (user.name != "Name") return "Fail: problem with `name` property" + if (user.age != 10) return "Fail: problem with `age` property" + if (user.email != "test@test") return "Fail: problem with `email` property" + + val json = js("JSON.stringify(user)") + if (json != "{\"age\":10,\"name\":\"Name\",\"email\":\"test@test\"}") return "Fail: got the next json: $json" + + return "OK" +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/testData/box/with-multiple-inheritance.kt b/plugins/jso/compiler-plugin/testData/box/with-multiple-inheritance.kt new file mode 100644 index 00000000000..b873ec9bbee --- /dev/null +++ b/plugins/jso/compiler-plugin/testData/box/with-multiple-inheritance.kt @@ -0,0 +1,33 @@ +package foo + +import kotlinx.jso.JsSimpleObject + +@JsSimpleObject +external interface User { + var name: String + val age: Int +} + +@JsSimpleObject +external interface Role { + val role: String +} + +@JsSimpleObject +external interface ExtendedUser : User, Role { + val email: String +} + +fun box(): String { + val user = ExtendedUser(name = "Name", age = 10, email = "test@test", role = "Admin") + + if (user.name != "Name") return "Fail: problem with `name` property" + if (user.age != 10) return "Fail: problem with `age` property" + if (user.email != "test@test") return "Fail: problem with `email` property" + if (user.role != "Admin") return "Fail: problem with `role` property" + + val json = js("JSON.stringify(user)") + if (json != "{\"age\":10,\"name\":\"Name\",\"role\":\"Admin\",\"email\":\"test@test\"}") return "Fail: got the next json: $json" + + return "OK" +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/testData/diagnostics/inheritance.kt b/plugins/jso/compiler-plugin/testData/diagnostics/inheritance.kt new file mode 100644 index 00000000000..2680ffac8d6 --- /dev/null +++ b/plugins/jso/compiler-plugin/testData/diagnostics/inheritance.kt @@ -0,0 +1,27 @@ +// 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, E + +class Foo : A, D, B diff --git a/plugins/jso/compiler-plugin/testData/diagnostics/wrongAnnotationTarget.kt b/plugins/jso/compiler-plugin/testData/diagnostics/wrongAnnotationTarget.kt new file mode 100644 index 00000000000..0ea4ac96ec6 --- /dev/null +++ b/plugins/jso/compiler-plugin/testData/diagnostics/wrongAnnotationTarget.kt @@ -0,0 +1,28 @@ +// FIR_IDENTICAL +// SKIP_TXT + +// FILE: test.kt +import kotlinx.jso.JsSimpleObject + +@JsSimpleObject +class Regular1 + +@JsSimpleObject +object Regular2 + +@JsSimpleObject +enum class Regular3 + +@JsSimpleObject +external class External1 + +@JsSimpleObject +external object External2 + +@JsSimpleObject +external interface External3 + +external class Nested { + @JsSimpleObject + interface Inner +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/tests-gen/org/jetbrains/kotlinx/jso/runners/FirJsObjectIrJsBoxTestGenerated.java b/plugins/jso/compiler-plugin/tests-gen/org/jetbrains/kotlinx/jso/runners/FirJsObjectIrJsBoxTestGenerated.java new file mode 100644 index 00000000000..6750d791daa --- /dev/null +++ b/plugins/jso/compiler-plugin/tests-gen/org/jetbrains/kotlinx/jso/runners/FirJsObjectIrJsBoxTestGenerated.java @@ -0,0 +1,57 @@ +/* + * Copyright 2010-2024 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.runners; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TargetBackend; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlinx.jso.TestGeneratorKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("plugins/jso/compiler-plugin/testData/box") +@TestDataPath("$PROJECT_ROOT") +public class FirJsObjectIrJsBoxTestGenerated extends AbstractFirJsObjectIrJsBoxTest { + @Test + 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); + } + + @Test + @TestMetadata("copy.kt") + public void testCopy() throws Exception { + runTest("plugins/jso/compiler-plugin/testData/box/copy.kt"); + } + + @Test + @TestMetadata("optional.kt") + public void testOptional() throws Exception { + runTest("plugins/jso/compiler-plugin/testData/box/optional.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("plugins/jso/compiler-plugin/testData/box/simple.kt"); + } + + @Test + @TestMetadata("with-inheritance.kt") + public void testWith_inheritance() throws Exception { + runTest("plugins/jso/compiler-plugin/testData/box/with-inheritance.kt"); + } + + @Test + @TestMetadata("with-multiple-inheritance.kt") + public void testWith_multiple_inheritance() throws Exception { + runTest("plugins/jso/compiler-plugin/testData/box/with-multiple-inheritance.kt"); + } +} diff --git a/plugins/jso/compiler-plugin/tests-gen/org/jetbrains/kotlinx/jso/runners/JsObjectPluginDiagnosticTestGenerated.java b/plugins/jso/compiler-plugin/tests-gen/org/jetbrains/kotlinx/jso/runners/JsObjectPluginDiagnosticTestGenerated.java new file mode 100644 index 00000000000..ded2014e823 --- /dev/null +++ b/plugins/jso/compiler-plugin/tests-gen/org/jetbrains/kotlinx/jso/runners/JsObjectPluginDiagnosticTestGenerated.java @@ -0,0 +1,38 @@ +/* + * Copyright 2010-2024 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.runners; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.util.KtTestUtil; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlinx.jso.TestGeneratorKt}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("plugins/jso/compiler-plugin/testData/diagnostics") +@TestDataPath("$PROJECT_ROOT") +public class JsObjectPluginDiagnosticTestGenerated extends AbstractJsObjectPluginDiagnosticTest { + @Test + public void testAllFilesPresentInDiagnostics() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/jso/compiler-plugin/testData/diagnostics"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("inheritance.kt") + public void testInheritance() throws Exception { + runTest("plugins/jso/compiler-plugin/testData/diagnostics/inheritance.kt"); + } + + @Test + @TestMetadata("wrongAnnotationTarget.kt") + public void testWrongAnnotationTarget() throws Exception { + runTest("plugins/jso/compiler-plugin/testData/diagnostics/wrongAnnotationTarget.kt"); + } +} diff --git a/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/TestGenerator.kt b/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/TestGenerator.kt new file mode 100644 index 00000000000..bf6a8ba9585 --- /dev/null +++ b/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/TestGenerator.kt @@ -0,0 +1,30 @@ +/* + * Copyright 2010-2021 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 + +import org.jetbrains.kotlin.generators.generateTestGroupSuiteWithJUnit5 +import org.jetbrains.kotlinx.jso.runners.AbstractFirJsObjectIrJsBoxTest +import org.jetbrains.kotlinx.jso.runners.AbstractJsObjectPluginDiagnosticTest + +fun main(args: Array) { + generateTestGroupSuiteWithJUnit5(args) { + testGroup( + "plugins/jso/compiler-plugin/tests-gen", + "plugins/jso/compiler-plugin/testData" + ) { + // ------------------------------- diagnostics ------------------------------- + testClass() { + model("diagnostics") + } + + // ------------------------------- box ------------------------------- + + testClass { + model("box") + } + } + } +} diff --git a/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/jsObjectConfiguration.kt b/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/jsObjectConfiguration.kt new file mode 100644 index 00000000000..7e50f96f99e --- /dev/null +++ b/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/jsObjectConfiguration.kt @@ -0,0 +1,36 @@ +/* + * Copyright 2010-2022 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.runners + +import org.jetbrains.kotlin.compiler.plugin.CompilerPluginRegistrar +import org.jetbrains.kotlin.config.CompilerConfiguration +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.model.TestModule +import org.jetbrains.kotlin.test.services.EnvironmentConfigurator +import org.jetbrains.kotlin.test.services.RuntimeClasspathProvider +import org.jetbrains.kotlin.test.services.TestServices +import org.jetbrains.kotlinx.jso.compiler.cli.JsObjectComponentRegistrar +import java.io.File + +class JsObjectEnvironmentConfigurator(testServices: TestServices) : EnvironmentConfigurator(testServices) { + override fun CompilerPluginRegistrar.ExtensionStorage.registerCompilerExtensions( + module: TestModule, + configuration: CompilerConfiguration + ) { + JsObjectComponentRegistrar.registerExtensions(this) + } +} + +class JsObjectRuntimeClasspathProvider(testServices: TestServices) : RuntimeClasspathProvider(testServices) { + override fun runtimeClassPaths(module: TestModule): List { + return listOf(File(System.getProperty("jso.runtime.path"))) + } +} + +fun TestConfigurationBuilder.configureForKotlinxJsObject() { + useConfigurators(::JsObjectEnvironmentConfigurator) + useCustomRuntimeClasspathProviders(::JsObjectRuntimeClasspathProvider) +} diff --git a/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/runners/BoxTests.kt b/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/runners/BoxTests.kt new file mode 100644 index 00000000000..002651e018f --- /dev/null +++ b/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/runners/BoxTests.kt @@ -0,0 +1,20 @@ +/* + * Copyright 2010-2022 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.runners + +import org.jetbrains.kotlin.js.test.fir.AbstractFirJsTest +import org.jetbrains.kotlin.js.test.ir.AbstractJsIrTest +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder + +open class AbstractFirJsObjectIrJsBoxTest : AbstractFirJsTest( + pathToTestDir = "plugins/kotlinx-serialization/testData/boxIr/", + testGroupOutputDirPrefix = "codegen/serializationBoxIr/" +) { + override fun configure(builder: TestConfigurationBuilder) { + super.configure(builder) + builder.configureForKotlinxJsObject() + } +} \ No newline at end of file diff --git a/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/runners/DiagnosticTests.kt b/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/runners/DiagnosticTests.kt new file mode 100644 index 00000000000..a71955e94cf --- /dev/null +++ b/plugins/jso/compiler-plugin/tests/org/jetbrains/kotlinx/jso/runners/DiagnosticTests.kt @@ -0,0 +1,37 @@ +/* + * Copyright 2010-2022 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.runners + +import org.jetbrains.kotlin.platform.TargetPlatform +import org.jetbrains.kotlin.platform.js.JsPlatforms +import org.jetbrains.kotlin.test.TargetBackend +import org.jetbrains.kotlin.test.builders.TestConfigurationBuilder +import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives.DIAGNOSTICS +import org.jetbrains.kotlin.test.model.DependencyKind +import org.jetbrains.kotlin.test.runners.AbstractFirPsiDiagnosticTest +import org.jetbrains.kotlin.test.runners.configurationForClassicAndFirTestsAlongside + +abstract class AbstractJsObjectPluginDiagnosticTest : AbstractFirPsiDiagnosticTest() { + override fun configure(builder: TestConfigurationBuilder) { + super.configure(builder) + with(builder) { + globalDefaults { + targetPlatform = JsPlatforms.defaultJsPlatform + targetBackend = TargetBackend.JS_IR + dependencyKind = DependencyKind.Source + } + + configureForKotlinxJsObject() + disableOptInErrors() + } + } +} + +private fun TestConfigurationBuilder.disableOptInErrors() { + defaultDirectives { + DIAGNOSTICS with listOf("-OPT_IN_USAGE", "-OPT_IN_USAGE_ERROR") + } +} diff --git a/plugins/jso/runtime/build.gradle.kts b/plugins/jso/runtime/build.gradle.kts new file mode 100644 index 00000000000..61ba76084cb --- /dev/null +++ b/plugins/jso/runtime/build.gradle.kts @@ -0,0 +1,42 @@ +import plugins.configureDefaultPublishing +import plugins.configureKotlinPomAttributes + +description = "Runtime library for the JSO compiler plugin" + +plugins { + kotlin("js") + `maven-publish` +} + +group = "org.jetbrains.kotlinx" + +kotlin { + js { + browser() + nodejs() + compilations["main"].defaultSourceSet { + dependencies { + compileOnly(kotlin("stdlib-js")) + } + } + } +} + +val emptyJavadocJar by tasks.registering(Jar::class) { + archiveClassifier.set("javadoc") +} + +publishing { + publications { + create("maven") { + artifactId = "jso" + from(components["kotlin"]) + configureKotlinPomAttributes(project, "Runtime library for the JSO compiler plugin", packaging = "klib") + } + withType { + artifact(emptyJavadocJar) + } + } +} + +configureDefaultPublishing() \ No newline at end of file diff --git a/plugins/jso/runtime/src/main/kotlin/jso.kt b/plugins/jso/runtime/src/main/kotlin/jso.kt new file mode 100644 index 00000000000..430774cca55 --- /dev/null +++ b/plugins/jso/runtime/src/main/kotlin/jso.kt @@ -0,0 +1,11 @@ +/* + * 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 kotlinx.jso + + +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +public annotation class JsSimpleObject \ No newline at end of file diff --git a/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/compiler-plugin/compiler-plugin.pom b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/compiler-plugin/compiler-plugin.pom new file mode 100644 index 00000000000..76435ea73cd --- /dev/null +++ b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/compiler-plugin/compiler-plugin.pom @@ -0,0 +1,28 @@ + + + 4.0.0 + org.jetbrains.kotlin + compiler-plugin + ArtifactsTest.version + Compiler Plugin + JavaScript Object Compiler Plugin + https://kotlinlang.org/ + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + Kotlin Team + JetBrains + https://www.jetbrains.com + + + + scm:git:https://github.com/JetBrains/kotlin.git + scm:git:https://github.com/JetBrains/kotlin.git + https://github.com/JetBrains/kotlin + + diff --git a/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/jso/jso.pom b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/jso/jso.pom new file mode 100644 index 00000000000..6c9a5615f09 --- /dev/null +++ b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/jso/jso.pom @@ -0,0 +1,342 @@ + + + + + + + + 4.0.0 + org.jetbrains.kotlin + jso + ArtifactsTest.version + Jso + Jso + https://kotlinlang.org/ + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + Kotlin Team + JetBrains + https://www.jetbrains.com + + + + scm:git:https://github.com/JetBrains/kotlin.git + scm:git:https://github.com/JetBrains/kotlin.git + https://github.com/JetBrains/kotlin + + + + + org.jetbrains.kotlin + kotlin-gradle-plugins-bom + ArtifactsTest.version + pom + import + + + + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + true + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + true + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + true + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + true + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + true + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + true + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + true + + + org.jetbrains.kotlin + kotlin-gradle-plugin-api + ArtifactsTest.version + compile + + + org.jetbrains.kotlin + kotlin-reflect + + + org.jetbrains.kotlin + kotlin-stdlib-jdk8 + + + org.jetbrains.kotlin + kotlin-stdlib-jdk7 + + + org.jetbrains.kotlin + kotlin-stdlib + + + org.jetbrains.kotlin + kotlin-script-runtime + + + org.jetbrains.kotlin + kotlin-stdlib-common + + + true + + + diff --git a/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlinx-jso-compiler-plugin-embeddable/kotlinx-jso-compiler-plugin-embeddable.pom b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlinx-jso-compiler-plugin-embeddable/kotlinx-jso-compiler-plugin-embeddable.pom new file mode 100644 index 00000000000..2b24903ff97 --- /dev/null +++ b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/kotlinx-jso-compiler-plugin-embeddable/kotlinx-jso-compiler-plugin-embeddable.pom @@ -0,0 +1,28 @@ + + + 4.0.0 + org.jetbrains.kotlin + kotlinx-jso-compiler-plugin-embeddable + ArtifactsTest.version + Compiler Plugin Embeddable + Compiler Plugin Embeddable + https://kotlinlang.org/ + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + Kotlin Team + JetBrains + https://www.jetbrains.com + + + + scm:git:https://github.com/JetBrains/kotlin.git + scm:git:https://github.com/JetBrains/kotlin.git + https://github.com/JetBrains/kotlin + + diff --git a/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/plugin/jso/org.jetbrains.kotlin.plugin.jso.gradle.plugin/org.jetbrains.kotlin.plugin.jso.gradle.plugin.pom b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/plugin/jso/org.jetbrains.kotlin.plugin.jso.gradle.plugin/org.jetbrains.kotlin.plugin.jso.gradle.plugin.pom new file mode 100644 index 00000000000..5f648962a80 --- /dev/null +++ b/repo/artifacts-tests/src/test/resources/org/jetbrains/kotlin/plugin/jso/org.jetbrains.kotlin.plugin.jso.gradle.plugin/org.jetbrains.kotlin.plugin.jso.gradle.plugin.pom @@ -0,0 +1,36 @@ + + + 4.0.0 + org.jetbrains.kotlin.plugin.jso + org.jetbrains.kotlin.plugin.jso.gradle.plugin + ArtifactsTest.version + pom + Kotlin compiler plugin for kotlinx.jso library + Kotlin compiler plugin for kotlinx.jso library + https://kotlinlang.org/ + + + The Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + + Kotlin Team + JetBrains + https://www.jetbrains.com + + + + scm:git:https://github.com/JetBrains/kotlin.git + scm:git:https://github.com/JetBrains/kotlin.git + https://github.com/JetBrains/kotlin + + + + org.jetbrains.kotlin + jso + ArtifactsTest.version + + + diff --git a/settings.gradle b/settings.gradle index e8ddc070d35..773c8b50990 100644 --- a/settings.gradle +++ b/settings.gradle @@ -283,6 +283,15 @@ include ":kotlin-atomicfu-compiler-plugin", ":kotlinx-atomicfu-runtime", ":atomicfu" +include ":plugins:jso:compiler-plugin", + ":plugins:jso:compiler-plugin-embeddable", + ":plugins:jso:compiler-plugin:jso.common", + ":plugins:jso:compiler-plugin:jso.k2", + ":plugins:jso:compiler-plugin:jso.backend", + ":plugins:jso:compiler-plugin:jso.cli", + ":plugins:jso:runtime", + ":libraries:tools:jso" + include ":compiler:fir", ":compiler:fir:cones", ":compiler:fir:tree", @@ -866,4 +875,4 @@ if (buildProperties.isKotlinNativeEnabled) { include ':kotlin-native:libclangext' include ':kotlin-native:backend.native:tests' include ":kotlin-native:prepare:kotlin-native-compiler-embeddable" -} +} \ No newline at end of file