diff --git a/plugins/fir-plugin-prototype/plugin-annotations/src/org/jetbrains/kotlin/fir/plugin/annotations.kt b/plugins/fir-plugin-prototype/plugin-annotations/src/org/jetbrains/kotlin/fir/plugin/annotations.kt index f1c117494b5..d7106fb2a31 100644 --- a/plugins/fir-plugin-prototype/plugin-annotations/src/org/jetbrains/kotlin/fir/plugin/annotations.kt +++ b/plugins/fir-plugin-prototype/plugin-annotations/src/org/jetbrains/kotlin/fir/plugin/annotations.kt @@ -33,3 +33,7 @@ enum class Visibility { annotation class SupertypeWithTypeArgument(val kClass: KClass<*>) annotation class MetaSupertype + +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.TYPE, AnnotationTarget.EXPRESSION) +@Retention(AnnotationRetention.SOURCE) +annotation class MyComposable diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirPluginPrototypeExtensionRegistrar.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirPluginPrototypeExtensionRegistrar.kt index 7ac71ce36be..e84c83644de 100644 --- a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirPluginPrototypeExtensionRegistrar.kt +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/FirPluginPrototypeExtensionRegistrar.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrar import org.jetbrains.kotlin.fir.extensions.FirExtensionRegistrarAdapter import org.jetbrains.kotlin.fir.plugin.generators.* import org.jetbrains.kotlin.fir.plugin.types.FirNumberSignAttributeExtension +import org.jetbrains.kotlin.fir.plugin.types.ComposableLikeFunctionalTypeKindExtension import org.jetbrains.kotlin.ir.plugin.GeneratedDeclarationsIrBodyFiller class FirPluginPrototypeExtensionRegistrar : FirExtensionRegistrar() { @@ -23,6 +24,7 @@ class FirPluginPrototypeExtensionRegistrar : FirExtensionRegistrar() { +::PluginAdditionalCheckers +::FirNumberSignAttributeExtension +::AlgebraReceiverInjector + +::ComposableLikeFunctionalTypeKindExtension // Declaration generators +::TopLevelDeclarationsGenerator diff --git a/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/types/ComposableLikeFunctionalTypeKindExtension.kt b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/types/ComposableLikeFunctionalTypeKindExtension.kt new file mode 100644 index 00000000000..6db97eac5e5 --- /dev/null +++ b/plugins/fir-plugin-prototype/src/org/jetbrains/kotlin/fir/plugin/types/ComposableLikeFunctionalTypeKindExtension.kt @@ -0,0 +1,44 @@ +/* + * 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.kotlin.fir.plugin.types + +import org.jetbrains.kotlin.builtins.functions.FunctionalTypeKind +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.extensions.FirFunctionalTypeKindExtension +import org.jetbrains.kotlin.fir.plugin.fqn +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.Name + +class ComposableLikeFunctionalTypeKindExtension(session: FirSession) : FirFunctionalTypeKindExtension(session) { + override fun FunctionalTypeKindRegistrar.registerKinds() { + registerKind(ComposableFunction, KComposableFunction) + } +} + +private val COMPOSABLE_PACKAGE_FQN = FqName.topLevel(Name.identifier("some")) +private val MY_COMPOSABLE_ANNOTATION_CLASS_ID = ClassId.topLevel("MyComposable".fqn()) + +object ComposableFunction : FunctionalTypeKind( + COMPOSABLE_PACKAGE_FQN, + "MyComposableFunction", + MY_COMPOSABLE_ANNOTATION_CLASS_ID, + isReflectType = false +) { + override val prefixForTypeRender: String + get() = "@MyComposable" + + override fun reflectKind(): FunctionalTypeKind = KComposableFunction +} + +object KComposableFunction : FunctionalTypeKind( + COMPOSABLE_PACKAGE_FQN, + "KMyComposableFunction", + MY_COMPOSABLE_ANNOTATION_CLASS_ID, + isReflectType = true +) { + override fun nonReflectKind(): FunctionalTypeKind = ComposableFunction +} diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/ambigousKinds.fir.txt b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/ambigousKinds.fir.txt new file mode 100644 index 00000000000..b51df49723e --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/ambigousKinds.fir.txt @@ -0,0 +1,3 @@ +FILE: ambigousKinds.kt + public final fun incorrect(block: ): R|kotlin/Unit| { + } diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/ambigousKinds.kt b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/ambigousKinds.kt new file mode 100644 index 00000000000..a24a1a87c8f --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/ambigousKinds.kt @@ -0,0 +1,3 @@ +import org.jetbrains.kotlin.fir.plugin.MyComposable + +fun incorrect(block: @MyComposable suspend () -> Unit) {} diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/simple.fir.txt b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/simple.fir.txt new file mode 100644 index 00000000000..055f6fbc3a3 --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/simple.fir.txt @@ -0,0 +1,55 @@ +FILE: simple.kt + public final fun runUsual(block: R|() -> kotlin/Unit|): R|kotlin/Unit| { + } + public final fun runComposable(block: R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0|): R|kotlin/Unit| { + } + public final fun test_1(): R|kotlin/Unit| { + lval l0: R|() -> kotlin/Unit| = fun (): R|kotlin/Unit| { + ^ Unit + } + + lval l1: R|some/MyComposableFunction0| = fun (): R|kotlin/Unit| { + ^ Unit + } + + lval l2: R|@R|org/jetbrains/kotlin/fir/plugin/MyComposable|() some/MyComposableFunction0| = fun (): R|kotlin/Unit| { + ^ Unit + } + + lval l3: R|some/MyComposableFunction0| = @R|org/jetbrains/kotlin/fir/plugin/MyComposable|() fun (): R|kotlin/Unit| { + ^ Unit + } + + R|/runUsual|(R|/l0|) + R|/runUsual#|(R|/l1|) + R|/runUsual#|(R|/l2|) + R|/runUsual#|(R|/l3|) + R|/runUsual|( = runUsual@fun (): R|kotlin/Unit| { + ^@runUsual Unit + } + ) + R|/runUsual#|( = @R|org/jetbrains/kotlin/fir/plugin/MyComposable|() runUsual@fun (): R|kotlin/Unit| { + ^@runUsual Unit + } + ) + R|/runComposable|(R|/l0|) + R|/runComposable|(R|/l1|) + R|/runComposable|(R|/l2|) + R|/runComposable|(R|/l3|) + R|/runComposable|( = runComposable@fun (): R|kotlin/Unit| { + ^@runComposable Unit + } + ) + R|/runComposable|( = @R|org/jetbrains/kotlin/fir/plugin/MyComposable|() runComposable@fun (): R|kotlin/Unit| { + ^@runComposable Unit + } + ) + } + public final fun runComposable2(block: R|some/MyComposableFunction1|): R|kotlin/Unit| { + } + public final fun test_2(): R|kotlin/Unit| { + R|/runComposable2|( = runComposable2@fun (it: R|kotlin/String|): R|kotlin/Int| { + ^ R|/it|.R|kotlin/String.length| + } + ) + } diff --git a/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/simple.kt b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/simple.kt new file mode 100644 index 00000000000..aa54d8501c4 --- /dev/null +++ b/plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/simple.kt @@ -0,0 +1,31 @@ +import org.jetbrains.kotlin.fir.plugin.MyComposable + +fun runUsual(block: () -> Unit) {} +fun runComposable(block: @MyComposable () -> Unit) {} + +fun test_1() { + val l0 = {} + val l1: some.MyComposableFunction0 = {} + val l2: @MyComposable (() -> Unit) = {} + val l3 = @MyComposable {} + + runUsual(l0) // ok + runUsual(l1) // error + runUsual(l2) // error + runUsual(l3) // error + runUsual {} // ok + runUsual @MyComposable {} // error + + runComposable(l0) // ok + runComposable(l1) // ok + runComposable(l2) // ok + runComposable(l3) // ok + runComposable {} // ok + runComposable @MyComposable {} // ok +} + +fun runComposable2(block: some.MyComposableFunction1) {} + +fun test_2() { + runComposable2 { it.length } +} diff --git a/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirPluginDiagnosticTestGenerated.java b/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirPluginDiagnosticTestGenerated.java index 31337e6f15e..96ed142b53b 100644 --- a/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirPluginDiagnosticTestGenerated.java +++ b/plugins/fir-plugin-prototype/tests-gen/org/jetbrains/kotlin/fir/plugin/runners/FirPluginDiagnosticTestGenerated.java @@ -46,6 +46,28 @@ public class FirPluginDiagnosticTestGenerated extends AbstractFirPluginDiagnosti } } + @Nested + @TestMetadata("plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes") + @TestDataPath("$PROJECT_ROOT") + public class FunctionalTypes { + @Test + public void testAllFilesPresentInFunctionalTypes() throws Exception { + KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes"), Pattern.compile("^(.+)\\.kt$"), null, true); + } + + @Test + @TestMetadata("ambigousKinds.kt") + public void testAmbigousKinds() throws Exception { + runTest("plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/ambigousKinds.kt"); + } + + @Test + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + runTest("plugins/fir-plugin-prototype/testData/diagnostics/functionalTypes/simple.kt"); + } + } + @Nested @TestMetadata("plugins/fir-plugin-prototype/testData/diagnostics/memberGen") @TestDataPath("$PROJECT_ROOT")