From dc91247e163c05381463c956d44ace73dc0610d1 Mon Sep 17 00:00:00 2001 From: Iaroslav Postovalov Date: Tue, 9 May 2023 17:33:15 +0400 Subject: [PATCH] Update Kotlin to 1.8.20, all necessary accompanying changes --- README.md | 4 +- build.gradle.kts | 77 ++++++++++---- buildSrc/build.gradle.kts | 16 +-- buildSrc/settings.gradle.kts | 5 +- detekt.yml | 2 + diktat-analysis.yml | 2 + examples/build.gradle.kts | 14 +-- examples/settings.gradle.kts | 2 +- gradle-plugin/build.gradle.kts | 27 +++-- .../reflekt/plugin/ReflektGradleExtension.kt | 31 +----- .../reflekt/plugin/ReflektSubPlugin.kt | 21 +++- .../reflekt/plugin/util/SerializationUtils.kt | 2 +- gradle/libs.versions.toml | 28 +++-- gradle/wrapper/gradle-wrapper.jar | Bin 59536 -> 59821 bytes gradle/wrapper/gradle-wrapper.properties | 2 +- reflekt-core/build.gradle.kts | 4 - .../kotlin/org/jetbrains/reflekt/util/Util.kt | 7 +- reflekt-dsl/build.gradle.kts | 4 - .../util/TypeStringRepresentationUtil.kt | 2 +- reflekt-plugin/build.gradle.kts | 8 +- .../plugin/ReflektCommandLineProcessor.kt | 1 + .../plugin/ReflektComponentRegistrar.kt | 35 ++----- .../collector/ir/InstancesCollector.kt | 39 +++---- .../plugin/analysis/common/ReflektNames.kt | 21 +++- .../plugin/analysis/ir/ArgumentCollectors.kt | 17 +-- .../reflekt/plugin/analysis/ir/Util.kt | 27 +++-- .../reflekt/plugin/analysis/models/Common.kt | 78 ++------------ .../analysis/models/ReflektQueryArguments.kt | 10 +- .../analysis/models/ir/IrFunctionInfo.kt | 8 +- .../plugin/analysis/models/ir/IrInstances.kt | 40 +++---- .../analysis/models/ir/LibraryArguments.kt | 23 ++-- .../reflekt/plugin/analysis/processor/Util.kt | 11 -- .../IrClassOrObjectArgumentProcessor.kt | 15 ++- .../IrReflektArgumentProcessor.kt | 18 ++-- .../serialization/ClassIdSerializer.kt | 98 +++++++++++++++++ .../serialization/SerializationUtils.kt | 32 +++--- .../generation/ReflektMetaFileGenerator.kt | 6 +- .../code/generator/ReflektImplGenerator.kt | 4 +- .../plugin/generation/code/generator/Util.kt | 7 +- .../models/ClassesOrObjectsGenerator.kt | 2 - .../generator/models/FunctionsGenerator.kt | 1 - .../generator/models/HelperClassGenerator.kt | 5 +- .../generation/ir/BaseReflektIrTransformer.kt | 20 ++-- .../plugin/generation/ir/GenerationSymbols.kt | 66 +++++++----- .../generation/ir/IrBuilderExtension.kt | 99 +++++++++++++++--- .../generation/ir/ReflektIrTransformer.kt | 2 +- .../ir/SmartReflektIrTransformer.kt | 31 +++--- .../generation/ir/StorageClassGenerator.kt | 20 ++-- .../plugin/scripting/KotlinScriptRunner.kt | 1 - .../reflekt/plugin/utils/PluginConfig.kt | 1 - .../jetbrains/reflekt/plugin/utils/Util.kt | 13 ++- .../reflekt/ReflektPluginProviders.kt | 10 +- .../compiler/runners/base/AbstractTest.kt | 4 +- .../compiler/runners/base/BaseTestRunner.kt | 4 +- .../plugin/compiler/util/CompilationUtil.kt | 8 +- .../plugin/compiler/util/TestICReporter.kt | 13 +-- .../scripting/KotlinScriptRunnerTest.kt | 11 -- settings.gradle.kts | 5 +- 58 files changed, 583 insertions(+), 481 deletions(-) create mode 100644 reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/serialization/ClassIdSerializer.kt diff --git a/README.md b/README.md index da6d5122..3fd06628 100644 --- a/README.md +++ b/README.md @@ -134,10 +134,10 @@ for Java and Kotlin in the `build.gradle.kts` file: ```kotlin import org.jetbrains.kotlin.gradle.tasks.KotlinCompile +kotlin.jvmToolchain(11) + tasks.withType { kotlinOptions { - useIR = true - jvmTarget = "11" // Current Reflekt version does not support incremental compilation process incremental = false } diff --git a/build.gradle.kts b/build.gradle.kts index 954072de..c6d15cf9 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -3,32 +3,37 @@ import io.gitlab.arturbosch.detekt.DetektPlugin import io.gitlab.arturbosch.detekt.extensions.DetektExtension import io.gitlab.arturbosch.detekt.report.ReportMergeTask import org.jetbrains.dokka.gradle.DokkaTaskPartial +import org.jetbrains.kotlin.gradle.dsl.KotlinCompile import org.jetbrains.reflekt.buildutils.* import java.net.URL @Suppress("DSL_SCOPE_VIOLATION") // https://youtrack.jetbrains.com/issue/KTIJ-19369 plugins { `maven-publish` - alias(libs.plugins.kosogor) alias(libs.plugins.buildconfig) apply false alias(libs.plugins.dokka) id(libs.plugins.kotlin.jvm.get().pluginId) } val detektReportMerge by tasks.registering(ReportMergeTask::class) { - output.set(rootProject.buildDir.resolve("reports/detekt/merge.sarif")) + output = rootProject.layout.buildDirectory.file("reports/detekt/merge.sarif") } group = "org.jetbrains.reflekt" -version = libs.versions.kotlin.asProvider().get() +version = libs.versions.kotlin.get() +description = "Reflekt is a compile-time reflection library that leverages the flows of the standard reflection approach and can find classes, objects " + + "(singleton classes) or functions by some conditions in compile-time." allprojects { - apply { - plugin("kotlin") + apply(plugin = "kotlin") - tasks.withType> { - kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" - } + tasks.withType> { + kotlinOptions.freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" + } + + java { + targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_11 } tasks.withType().all { @@ -39,34 +44,31 @@ allprojects { repositories { mavenCentral() - maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") // Uncomment it for using the last kotlin compiler version // The full list of the build can be found here: // https://teamcity.jetbrains.com/buildConfiguration/Kotlin_KotlinPublic_BuildNumber?mode=builds&tag=bootstrap // (see builds with tag) // Note: uncomment it also in the settings.gradle.kts - // maven { - // url = uri("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") - // } + // maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") } // We should publish the project in the local maven repository before the tests running tasks.withType { - dependsOn(tasks.withType {}, ":reflekt-plugin:jar", ":reflekt-dsl:jar") + dependsOn(tasks.withType(), ":reflekt-plugin:jar", ":reflekt-dsl:jar") } configureDiktat() apply() configure { - config = rootProject.files("detekt.yml") + config.setFrom(rootProject.files("detekt.yml")) buildUponDefaultConfig = true debug = true } tasks.withType { finalizedBy(detektReportMerge) - reports.sarif.required.set(true) + reports.sarif.required = true detektReportMerge.get().input.from(sarifReportFile) } } @@ -82,11 +84,42 @@ subprojects { tasks.withType { dokkaSourceSets.configureEach { sourceLink { - localDirectory.set(this@subprojects.file("src/main/kotlin")) + localDirectory = this@subprojects.file("src/main/kotlin") - remoteUrl.set( + remoteUrl = URL("https://github.com/JetBrains-Research/${rootProject.name}/tree/master/${this@subprojects.name}/src/main/kotlin/") - ) + } + } + } + } + + if (this@subprojects.name != "gradle-plugin") { + publishing { + publications { + @Suppress("unused") + val mavenJava by creating(MavenPublication::class) { + from(this@subprojects.components["java"]) + + pom { + description = rootProject.description + inceptionYear = "2020" + url = "https://github.com/JetBrains-Research/${rootProject.name}" + + licenses { + license { + comments = "Open-source license" + distribution = "repo" + name = "Apache License" + url = "https://github.com/JetBrains-Research/${rootProject.name}/blob/master/LICENSE" + } + } + + scm { + connection = "scm:git:git@github.com:JetBrains-Research/${rootProject.name}.git" + developerConnection = "scm:git:git@github.com:JetBrains-Research/${rootProject.name}.git" + url = "git@github.com:JetBrains-Research/${rootProject.name}.git" + } + } } } } @@ -94,12 +127,12 @@ subprojects { publishing { repositories { - maven { + maven("https://packages.jetbrains.team/maven/p/reflekt/reflekt") { name = "SpacePackages" - url = uri("https://packages.jetbrains.team/maven/p/reflekt/reflekt") + credentials { - username = System.getenv("JB_SPACE_CLIENT_ID")?.takeIf { it.isNotBlank() } ?: "" - password = System.getenv("JB_SPACE_CLIENT_SECRET")?.takeIf { it.isNotBlank() } ?: "" + username = System.getenv("JB_SPACE_CLIENT_ID").orEmpty() + password = System.getenv("JB_SPACE_CLIENT_SECRET").orEmpty() } } } diff --git a/buildSrc/build.gradle.kts b/buildSrc/build.gradle.kts index a04ddf5a..3948f8e9 100644 --- a/buildSrc/build.gradle.kts +++ b/buildSrc/build.gradle.kts @@ -5,15 +5,12 @@ plugins { repositories { mavenCentral() google() - maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") // Uncomment it for using the last kotlin compiler version // The full list of the build can be found here: // https://teamcity.jetbrains.com/buildConfiguration/Kotlin_KotlinPublic_BuildNumber?mode=builds&tag=bootstrap // (see builds with tag) // Note: uncomment it also in the settings.gradle.kts - // maven { - // url = uri("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") - // } + // maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") } dependencies { @@ -22,8 +19,11 @@ dependencies { implementation(libs.gradle.plugin.detekt) } -tasks.withType().all { - kotlinOptions { - jvmTarget = "11" - } +java { + targetCompatibility = JavaVersion.VERSION_11 + sourceCompatibility = JavaVersion.VERSION_11 +} + +tasks.withType { + kotlinOptions.jvmTarget = "11" } diff --git a/buildSrc/settings.gradle.kts b/buildSrc/settings.gradle.kts index b60c48be..ec22a169 100644 --- a/buildSrc/settings.gradle.kts +++ b/buildSrc/settings.gradle.kts @@ -10,14 +10,11 @@ pluginManagement { repositories { mavenCentral() gradlePluginPortal() - maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") // Uncomment it for using the last kotlin compiler version // The full list of the build can be found here: // https://teamcity.jetbrains.com/buildConfiguration/Kotlin_KotlinPublic_BuildNumber?mode=builds&tag=bootstrap // (see builds with tag) // Note: uncomment it also in the build.gradle.kts - // maven { - // url = uri("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") - // } + // maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") } } diff --git a/detekt.yml b/detekt.yml index 4a6aa4f2..97f37821 100644 --- a/detekt.yml +++ b/detekt.yml @@ -15,3 +15,5 @@ style: active: false ReturnCount: max: 3 + DestructuringDeclarationWithTooManyEntries: + active: false diff --git a/diktat-analysis.yml b/diktat-analysis.yml index 1a2920fc..2943a190 100644 --- a/diktat-analysis.yml +++ b/diktat-analysis.yml @@ -154,3 +154,5 @@ enabled: false - name: IDENTIFIER_LENGTH enabled: false +- name: KDOC_DUPLICATE_PROPERTY + enabled: false diff --git a/examples/build.gradle.kts b/examples/build.gradle.kts index f5854e18..bbf772b4 100644 --- a/examples/build.gradle.kts +++ b/examples/build.gradle.kts @@ -1,12 +1,11 @@ -import org.jetbrains.reflekt.plugin.reflekt import org.jetbrains.kotlin.gradle.tasks.KotlinCompile group = rootProject.group version = rootProject.version plugins { - id("org.jetbrains.reflekt") version "1.8.0-dev-6" - id("org.jetbrains.kotlin.jvm") version "1.8.0-dev-6" + id("org.jetbrains.reflekt") version "1.8.21" + id("org.jetbrains.kotlin.jvm") version "1.8.21" } allprojects { @@ -24,7 +23,7 @@ allprojects { } dependencies { - implementation("org.jetbrains.reflekt", "reflekt-dsl", "1.8.0-dev-6") + implementation("org.jetbrains.reflekt", "reflekt-dsl", "1.8.21") } repositories { @@ -32,11 +31,8 @@ allprojects { mavenLocal() maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") // Uncomment to use a released version -// maven(url = uri("https://packages.jetbrains.team/maven/p/reflekt/reflekt")) - } - - reflekt { - enabled = true + // maven("https://packages.jetbrains.team/maven/p/reflekt/reflekt") } + reflekt.enabled = true } diff --git a/examples/settings.gradle.kts b/examples/settings.gradle.kts index 036446e2..a483f42c 100644 --- a/examples/settings.gradle.kts +++ b/examples/settings.gradle.kts @@ -9,7 +9,7 @@ pluginManagement { maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") // add the dependency to Reflekt Maven repository // Uncomment to use a released version - // maven(url = uri("https://packages.jetbrains.team/maven/p/reflekt/reflekt")) + // maven("https://packages.jetbrains.team/maven/p/reflekt/reflekt") gradlePluginPortal() } } diff --git a/gradle-plugin/build.gradle.kts b/gradle-plugin/build.gradle.kts index 3765f751..2e06aa0a 100644 --- a/gradle-plugin/build.gradle.kts +++ b/gradle-plugin/build.gradle.kts @@ -1,31 +1,30 @@ -import tanvd.kosogor.proxy.publishPlugin - @Suppress("DSL_SCOPE_VIOLATION") // https://youtrack.jetbrains.com/issue/KTIJ-19369 plugins { `kotlin-dsl` alias(libs.plugins.kotlin.plugin.serialization) + alias(libs.plugins.plugin.publish) } group = rootProject.group version = rootProject.version dependencies { - implementation(kotlin("gradle-plugin-api")) + implementation(embeddedKotlin("gradle-plugin-api")) implementation(projects.reflektCore) api(projects.reflektDsl) implementation(libs.kotlinx.serialization.protobuf) } -publishPlugin { - id = "org.jetbrains.reflekt" - displayName = "Reflekt" - implementationClass = "org.jetbrains.reflekt.plugin.ReflektSubPlugin" - version = project.version.toString() - - info { - description = "Compile-time reflection library" - website = "https://github.com/JetBrains-Research/reflekt" - vcsUrl = "https://github.com/JetBrains-Research/reflekt" - tags.addAll(listOf("kotlin", "reflection", "reflekt")) +gradlePlugin { + website = "https://github.com/JetBrains-Research/reflekt" + vcsUrl = "https://github.com/JetBrains-Research/reflekt" + plugins { + val reflekt by creating { + id = "org.jetbrains.reflekt" + displayName = "Gradle Reflekt plugin" + description = rootProject.description + implementationClass = "org.jetbrains.reflekt.plugin.ReflektSubPlugin" + tags.addAll(listOf("kotlin", "reflection", "reflekt")) + } } } diff --git a/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektGradleExtension.kt b/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektGradleExtension.kt index 9be60f19..34169c0c 100644 --- a/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektGradleExtension.kt +++ b/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektGradleExtension.kt @@ -1,32 +1,16 @@ package org.jetbrains.reflekt.plugin -import org.gradle.api.Project - -/** - * Users can configure this extension in their build.gradle like this: - * reflekt { - * enabled = false - * // ... set other members on the ReflektGradleExtension class - * } - */ -@PublishedApi -internal val Project.reflekt: ReflektGradleExtension - get() = project.extensions.findByType(ReflektGradleExtension::class.java) ?: run { - extensions.create("reflekt", ReflektGradleExtension::class.java) - } - /** - * Gradle extension class containing the configuration information for the plugin + * Gradle extension class containing the configuration information for the plugin. */ open class ReflektGradleExtension { - /** If `false`, this plugin won't actually be applied */ + /** If `false`, this plugin won't actually be applied. */ var enabled: Boolean = true /** * Path to which code should be generated. * - * It would be automatically added to source set and marked - * as generated in IntelliJ IDEA + * It would be automatically added to the source set and marked as generated in IntelliJ IDEA. */ var generationPath: String = "build/src/main/kotlin-gen" @@ -35,12 +19,3 @@ open class ReflektGradleExtension { * as a library for ReflektImpl file generation. */ var toSaveMetadata: Boolean = false } - -/** - * Reflekt Generator configuration extension. - * - * @param configure - */ -inline fun Project.reflekt(configure: ReflektGradleExtension.() -> Unit) { - reflekt.apply(configure) -} diff --git a/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektSubPlugin.kt b/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektSubPlugin.kt index 5734f2be..c4bb7f99 100644 --- a/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektSubPlugin.kt +++ b/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektSubPlugin.kt @@ -22,12 +22,20 @@ typealias ReflektMetaFilesFromLibrariesMap = HashMap> @Suppress("TooManyFunctions") class ReflektSubPlugin : KotlinCompilerPluginSupportPlugin { private lateinit var reflektMetaFilesFromLibrariesMap: ReflektMetaFilesFromLibrariesMap + private lateinit var extension: ReflektGradleExtension + + override fun apply(target: Project) { + extension = target.extensions.create("reflekt", ReflektGradleExtension::class.java) + } override fun applyToCompilation(kotlinCompilation: KotlinCompilation<*>): Provider> { - println("ReflektSubPlugin loaded") val project = kotlinCompilation.target.project - val extension = project.reflekt - val buildDir = project.buildDir.absolutePath + val buildDir = project + .layout + .buildDirectory + .asFile + .get() + .absolutePath reflektMetaFilesFromLibrariesMap = SerializationUtils.deserializeReflektMetaFilesFromLibrariesMap(buildDir) val reflektMetaFilesFromLibraries = if (extension.toSaveMetadata) emptyList() else project.getReflektMetaFilesFromLibraries() @@ -97,7 +105,12 @@ class ReflektSubPlugin : KotlinCompilerPluginSupportPlugin { private fun getLibJarWithoutSources(jarFile: File): File? { val jarName = "${jarFile.name.substringBeforeLast('.', "")}.jar" // TODO: make sure each jar has the same file structure and it's safe to call jarFile.parentFile.parentFile.listFiles() - return jarFile.parentFile.parentFile.listFiles()?.firstOrNull { it.isDirectory }?.listFiles() + return jarFile + .parentFile + .parentFile + .listFiles() + ?.firstOrNull { it.isDirectory } + ?.listFiles() ?.find { it.name == jarName } } diff --git a/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/util/SerializationUtils.kt b/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/util/SerializationUtils.kt index c28ddac5..292145d3 100644 --- a/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/util/SerializationUtils.kt +++ b/gradle-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/util/SerializationUtils.kt @@ -11,7 +11,7 @@ internal typealias SerializableReflektMetaFilesFromLibrariesMap = HashMap`VW15{5nuy;_V&a5O#0S&!a4dSkUMz_VHu3S zGA@p9Q$T|Sj}tYGWdjH;Mpp8m&yu&YURcrt{K;R|kM~(*{v%QwrBJIUF+K1kX5ZmF zty3i{d`y0;DgE+de>vN@yYqFPe1Ud{!&G*Q?iUc^V=|H%4~2|N zW+DM)W!`b&V2mQ0Y4u_)uB=P@-2`v|Wm{>CxER1P^ z>c}ZPZ)xxdOCDu59{X^~2id7+6l6x)U}C4Em?H~F`uOxS1?}xMxTV|5@}PlN%Cg$( zwY6c}r60=z5ZA1L zTMe;84rLtYvcm?M(H~ZqU;6F7Evo{P7!LGcdwO|qf1w+)MsnvK5^c@Uzj<{ zUoej1>95tuSvDJ|5K6k%&UF*uE6kBn47QJw^yE&#G;u^Z9oYWrK(+oL97hBsUMc_^ z;-lmxebwlB`Er_kXp2$`&o+rPJAN<`WX3ws2K{q@qUp}XTfV{t%KrsZ5vM!Q#4{V& zq>iO$MCiLq#%wXj%`W$_%FRg_WR*quv65TdHhdpV&jlq<=K^K`&!Kl5mA6p4n~p3u zWE{20^hYpn1M}}VmSHBXl1*-)2MP=0_k)EPr#>EoZukiXFDz?Di1I>2@Z^P$pvaF+ zN+qUy63jek2m59;YG)`r^F3-O)0RDIXPhf)XOOdkmu`3SMMSW(g+`Ajt{=h1dt~ks ztrhhP|L4G%5x79N#kwAHh5N){@{fzE7n&%dnisCm65Za<8r_hKvfx4Bg*`%-*-Mvn zFvn~)VP@}1sAyD+B{{8l{EjD10Av&Mz9^Xff*t`lU=q=S#(|>ls520;n3<}X#pyh& z*{CJf7$*&~!9jMnw_D~ikUKJ2+UnXmN6qak{xx%W;BKuXt7@ky!LPI1qk?gDwG@@o zkY+BkIie>{{q==5)kXw(*t#I?__Kwi>`=+s?Gq6X+vtSsaAO&Tf+Bl$vKnzc&%BHM z=loWOQq~n}>l=EL(5&6((ESsQC3^@4jlO5Od{qN#sWV)vqXw}aA>*uvwZopNN(|-T zRTF%5Y_k1R$;(d-)n;hWex{;7b6KgdAVE@&0pd(*qDzBO#YZV%kh%pYt1`hnQ(Fa& zYiDrOTDqk5M7hzp9kI2h!PxNnuJ&xl*zF8sx6!67bA49R1bmUF5bpK&&{eI0U~cH}PM z3aW1$lRb|ItkG5~_eBNu$|I|vYIdAA9a!pVq<+UTx*M}fG`23zxXp&E=FfnY- zEzKj;Cu_s4v>leO7M2-mE(UzKHL4c$c`3dS*19OpLV^4NI*hWWnJQ9lvzP4c;c?do zqrcsKT*i~eIHl0D3r4N{)+RsB6XhrC^;sp2cf_Eq#6*CV;t8v=V!ISe>>9kPgh}NI z=1UZutslxcT$Ad;_P^;Oouoa(cs!Ctpvi>%aQ+Zp=1d|h{W9Wmf7JWxa(~<#tSZ?C%wu4_5F!fc!<@PIBeJ)Nr^$bB6!_Gic_7}c3J{QI~Gg5g5jTp9}V6KYgrgaX>pJt}7$!wOht&KO|+z{Iw@YL|@~D zMww}+lG}rm2^peNx>58ME||ZQxFQeVSX8iogHLq_vXb`>RnoEKaTWBF-$JD#Q4BMv zt2(2Qb*x-?ur1Y(NsW8AdtX0#rDB?O(Vs4_xA(u-o!-tBG03OI!pQD+2UytbL5>lG z*(F)KacHqMa4?dxa(Vcrw>IIAeB$3cx#;;5r2X;HE8|}eYdAgCw#tpXNy7C3w1q`9 zGxZ6;@1G%8shz9e+!K2MO*{_RjO}Jo6eL3{TSZ>nY7)Qs`Dhi5><@oh0r)gT7H-?3 zLDsd^@m%JvrS8sta5`QiZNs^*GT}Hiy^zjK2^Ni%`Z|ma)D2 zuyumbvw$M8$haCTI~6M%d4+P)uX%u{Sfg4Al+F7c6;O-*)DKI7E8izSOKB#FcV{M+ zEvY0FBkq!$J0EW$Cxl}3{JwV^ki-T?q6C30Y5e&p@8Rd?$ST-Ghn*-`tB{k54W<>F z5I)TFpUC!E9298=sk>m#FI4sUDy_!8?51FqqW!9LN1(zuDnB3$!pEUjL>N>RNgAG~-9Xm|1lqHseW(%v&6K(DZ3Pano(1-Qe?3%J&>0`~w^Q-p&@ zg@HjvhJk?*hpF7$9P|gkzz`zBz_5Z!C4_-%fCcAgiSilzFQef!@amHDrW!YZS@?7C zs2Y9~>yqO+rkih?kXztzvnB^6W=f52*iyuZPv$c42$WK7>PHb z6%MYIr5D32KPdwL1hJf{_#jn?`k(taW?mwmZVvrr=y~fNcV$`}v(8};o9AjOJumS4 z`889O91^pkF+|@$d9wVoZ3;^j;^sUs&Ubo_qD&MTL%O z&*SE0ujG~zm;?x)8TLC&ft))nyI zcg44@*Q{cYT+qGrA=In_X{NNCD+B0w#;@g)jvBU;_8od6U>;7HIo@F*=g8CQUo(u^ z3r4FJ7#<@)MXO&5+DgKE&^>^`r!loe7CWE*1k0*0wLFzSOV8jvlX~WOQ?$1v zk$Or}!;ix0g78^6W;+<=J>z@CBs!<<)HvF(Ls-&`matpesJ5kkjC)6nGB@b{ii6-Uoho$BT%iJgugTOeZ$5Xo4D7Pd< zC*LJh5V@2#5%aBZCgzlQi3@<_!VfiL07ywc)ZbwKPfcR|ElQoS(8x|a7#IR}7#Io= zwg4$8S{egr-NffD)Fg&X9bJSoM25pF&%hf>(T&9bI}=#dPQyNYz;ZZ7EZ=u1n701SWKkZ9n(-qU ztN`sdWL1uxQ1mKS@x11;O|@^AD9!NeoPx}?EKIr!2>1Qq4gjfGU)tr6?Z5l7JAS3j zZeq{vG{rb%DFE4%$szK}d2UzB{4>L?Tv+NAlE*&Nq6g+XauaSI+N2Y8PJLw+aNg1p zbxr|hI8wcMP&&+(Cu|%+Jq|r>+BHk@{AvfBXKiVldN)@}TBS0LdIpnANCVE26WL-} zV}HJ^?m&$Rkq;Zf*i-hoasnpJVyTH__dbGWrB_R55d*>pTyl6(?$EO@>RCmTX1Hzr zT2)rOng?D4FfZ_C49hjMV*UonG2DlG$^+k=Y%|?Dqae4}JOU=8=fgY4Uh!pa9eEqf zFX&WLPu!jArN*^(>|H>dj~g`ONZhaaD%h_HHrHkk%d~TR_RrX{&eM#P@3x=S^%_6h zh=A)A{id16$zEFq@-D7La;kTuE!oopx^9{uA3y<}9 z^bQ@U<&pJV6kq7LRF47&!UAvgkBx=)KS_X!NY28^gQr27P=gKh0+E>$aCx&^vj2uc}ycsfSEP zedhTgUwPx%?;+dESs!g1z}5q9EC+fol}tAH9#fhZQ?q1GjyIaR@}lGCSpM-014T~l zEwriqt~ftwz=@2tn$xP&-rJt?nn5sy8sJ5Roy;pavj@O+tm}d_qmAlvhG(&k>(arz z;e|SiTr+0<&6(-An0*4{7akwUk~Yf4M!!YKj^swp9WOa%al`%R>V7mi z+5+UodFAaPdi4(8_FO&O!Ymb#@yxkuVMrog(7gkj$G@FLA#ENMxG)4f<}S%Fn?Up$+C%{02AgMKa^ z4SFGWp6U>{Q6VRJV}yjxXT*e`1XaX}(dW1F&RNhpTzvCtzuu;LMhMfJ2LBEy?{^GHG!OF!! zDvs64TG)?MX&9NCE#H3(M0K>O>`ca0WT2YR>PTe&tn?~0FV!MRtdb@v?MAUG&Ef7v zW%7>H(;Mm)RJkt18GXv!&np z?RUxOrCfs;m{fBz5MVlq59idhov21di5>WXWD-594L-X5;|@kyWi@N+(jLuh=o+5l zGGTi~)nflP_G}Yg5Pi%pl88U4+^*ihDoMP&zA*^xJE_X*Ah!jODrijCqQ^{=&hD7& z^)qv3;cu?olaT3pc{)Kcy9jA2E8I)#Kn8qO>70SQ5P8YSCN=_+_&)qg)OYBg|-k^d3*@jRAeB?;yd-O1A0wJ z?K*RDm|wE<(PBz~+C%2CTtzCTUohxP2*1kE8Of~{KRAvMrO_}NN&@P7SUO{;zx0iK z@or9R8ydYOFZf(cHASCAatL%;62IL27~SmASr(7F&NMr+#gNw@z1VM z_ALFwo3)SoANEwRerBdRV`>y`t72#aF2ConmWQp(Xy|msN9$yxhZ1jAQ67lq{vbC5 zujj|MlGo`6Bfn0TfKgi(k=gq0`K~W+X(@GzYlPI4g0M;owH3yG14rhK>lG8lS{`!K z+Nc@glT-DGz?Ym?v#Hq|_mEdPAlHH5jZuh*6glq!+>Lk$S%ED2@+ea6CE@&1-9a?s znglt|fmIK}fg<9@XgHe4*q!aO<-;Xj$T?IzB-{&2`#eA6rdtCi80mpP&vw(Uytxu$#YzNI_cB>LS zmim>ys;ir;*Dzbr22ZDxO2s;671&J0U<9(n1yj)J zHFNz=ufPcQVEG+ePjB<5C;=H0{>Mi*xD>hQq8`Vi7TjJ$V04$`h3EZGL|}a07oQdR z?{cR(z+d>arn^AUug&voOzzi$ZqaS)blz-z3zr;10x;oP2)|Cyb^WtN2*wNn`YX!Y z+$Pji<7|!XyMCEw4so}xXLU)p)BA~2fl>y2Tt}o9*BPm?AXA8UE8a;>rOgyCwZBFa zyl42y`bc3}+hiZL_|L_LY29vVerM+BVE@YxK>TGm@dHi@Uw*7AIq?QA9?THL603J% zIBJ4y3n8OFzsOI;NH%DZ!MDwMl<#$)d9eVVeqVl(5ZX$PPbt*p_(_9VSXhaUPa9Qu z7)q4vqYKX7ieVSjOmVEbLj4VYtnDpe*0Y&+>0dS^bJ<8s*eHq3tjRAw^+Mu4W^-E= z4;&namG4G;3pVDyPkUw#0kWEO1;HI6M51(1<0|*pa(I!sj}F^)avrE`ShVMKBz}nE zzKgOPMSEp6M>hJzyTHHcjV%W*;Tdb}1xJjCP#=iQuBk_Eho6yCRVp&e!}4IBJ&?ksVc&u#g3+G$oNlJ?mWfADjeBS-Ph3`DKk-~Z70XugH8sq2eba@4 zIC1H_J$`9b$K`J)sGX3d!&>OmC@@rx1TL~NinQOYy72Q_+^&Mg>Ku(fTgaXdr$p_V z#gav1o{k~c>#)u3r@~6v^o)Lf=C{rAlL@!s457pq)pO;Cojx7U{urO4cvXP|E>+dV zmr2?!-5)tk-&*ap^D^2x7NG6nOop2zNFQ9v8-EZ{WCz-h36C)<^|f{V#R_WE^@(T0+d-at5hXX{U?zak*ac-XnyINo+yBD~~3O1I=a z99|CI>502&s-Qi5bv>^2#cQ%ut<4d7KgQ^kE|=%6#VlGiY8$rdJUH{sra;P~cyb_i zeX(kS%w0C?mjhJl9TZp8RS;N~y3(EXEz13oPhOSE4WaTljGkVXWd~|#)vsG6_76I)Kb z8ro?;{j^lxNsaxE-cfP;g(e;mhh3)&ba}li?woV2#7ByioiD>s%L_D;?#;C#z;a(N z-_WY<=SH42m9bFQ>Nb z@4K$@4l8pD7AKxCR>t0%`Qoy9=hA?<<^Vcj8;-E+oBe3ReW1`el8np8E$k{LgFQ}2 z2t8a`wOXFdJ9!5$&mEfD1CnJ)TB+RJih88-Zos9@HZ# zL#{qfbF0ARTXkR@G{lwlOH~nnL)1jcyu!qv2`57S&%oKz0}r{~l9U_UHaJ5!8#nrs z?2FrL`mxnzu&{bweD&62)ilz*?pYIvt`T!XFVVA78})p1YEy7 z8fK#s?b~Yo$n7&_a?EBdXH-_W)Z44?!;DFx6pZ?~RArtBI*Qm4~6nX6Z_T*i$bQPE;Qz?DAPstpGSqr-AJ zo%m9cA`oDDm?&dTaoh_>@F>a?!y4qt_;NGN9Z<%SS;fX-cSu|>+Pba22`CRb#|HZa z;{)yHE>M-pc1C0mrnT~80!u&dvVTYFV8xTQ#g;6{c<9d!FDqU%TK5T6h*w*p980D~ zUyCb`y3{-?(mJFP)0*-Nt;mI$-gc4VQumh|rs&j_^R{sgTPF`1Xja2YWstsKFuQ(d zmZMxV$p$|qQUXchu&8%J(9|)B?`~rIx&)LqDS>ob5%gTeTP#Sbny#y*rnJ&?(l=!( zoV~}LJ1DPLnF8oyM(2ScrQ0{Q4m4-BWnS4wilgCW-~~;}pw=&<+HggRD_3c@3RQIr z9+-%!%}u_{`YS=&>h%kPO3ce}>y!d-zqiniNR-b5r97u;+K6HA2tS>Z#cV{+eFI`* zd8RMGAUtX1KWfPV;q<-5JAykS+2sY$2~UX+4461a(%{P#{rwFPu0xpIuYlbgD{C7C z=U{FUarVTYX6ZUq3wE@G^QT4H2Re;n$Fz9cJ>hABl)9T8pozqbA1)H-%1=WKm^QMu zjnUZ&Pu>q+X&6Co*y#@pxc-4waKMInEPGmE_>3@Ym3S*dedSradmc5mlJn`i0vMW6 zhBnGQD^Z;&S0lnS0curqDO@({J7kTtRE+Ra?nl^HP9<)W&C>~`!258f$XDbyQOQXG zP8hhySnarOpgu8xv8@WlXnm(Uk~)_3$Sg0vTbU3 z{W!5B(L3{Yy3K5PN<@jEarAtja`}@KYva&zFRF*s+_%jIXh$T(S=an8?=Ry3H*NRqWgsM`&!#|@kf1>=4q%bFw7^Rhz!z5I zyI^zU8_R1WN9`88Z=n>pIZQ`Ixr~_9G%Q}@A7rd#*%y7G zXl^Id=^ZL?Rx}}gWXCqzj9C6;x(~mAH|$JteXa1MH<6UQig@!Hf~t}B%tP0I|H&;y zO6N0}svOa1a^PyP9N5?4W6VF%=Bj{qHUgc8@siw4bafT=UPFSoQqKgyUX>sXTBZ=x zOh^Ad!{kOM9v{%5y}`-8u*T&C7Vq6mD%GR}UeU(*epO&qgC-CkD;%=l)ZuinSzHM` z{@`j&_vC6dDe{Yb9k@1zeV_K6!l(@=6ucoI=R^cH=6{i71%4W3$J-?<8Qn#$-DMtA z6Qqi)t?4ifrt%3jSA#6ji#{f(($KBL-iQh-xrC||3U3lq`9>r)>X%oLvtimuHW-)} zy}>9~|M>w4eES`g7;iBM%Se5-OP%1U6gNWp3AZqT8C6OlFFfQ$|7LL;tBV)(qlp4K zruar^K8FnJN3@_}B;G`a~H`t|3+6d>q3#`ctTkE-D^1#d9NalQ04lH*qUW2!V zhk7#z8OwHhSl8w14;KctfO8ubZJ4$dEdpXE78wABz=n5*=q9ex3S}`e7x~~V-jmHOhtX2*n+pBslo3uosdE7xABK=V#-t{1Hd~?i z{i~%Bw6NYF+F$aK$M`r#xe=NxhA5=p%i7!$);sd>Q}#`G?Q~fygrMXmZw?0#5#17W}6Tj+&kFexG{!mYl5FoA99}3G9l;3lVQ^ z48^~gsVppE*x91WheqI(A%F0Z#$#1UJP1R12Mj9r)y(A?a+iquX+d8WD4WAQJ_!oq z9rTISr7bPd(GTP57xm$}C}&kjMivi;zi^Y9g3&X0A;ovdJ?{%_wHgt%%9P&N4H z^XzV(uNA4 zAP`hgP6BEN5`YXh|DF~6Pud?~gWfhUKoPX4>z|}0aocC&K+AoV%|SX*N!wGq3|y< zg4lP(04XIPmt6}$N!dTk+pZv>u;MTB{L4hp9uXk7>aS!6jqM2lVr%{)H3$O127TSZ z0x9hi0k-P?nWFdQ0K`pykqUIT&jD~B0tHP{ffS(}fZ(aW$oBWTSfHO!A^><6vA?qar%tzN-5NQO zL&|F{nGiQyzNJ+bM$Y`n=Lx^3wTG^o2bGB@cwr1eb+6c-1tN=U+Db;bc~eJ!hwM{SbI=#g?$!PjDB+) zPgU_2EIxocr*EOJG52-~!gml&|D|C2OQ3Y(zAhL}iae4-Ut0F*!z!VEdfw8#`LAi# zhJ_EM*~;S|FMV6y%-SduHjPOI3cFM(GpH|HES<}*=vqY+64%dJYc|k?n6Br7)D#~# zEqO(xepfaf2F{>{E2`xb=AO%A<7RtUq6kU_Iu0m?@0K(+<}u3gVw5fy=Y4CC*{IE3 zLP3YBJ7x+U(os5=&NT%gKi23bbaZ`@;%ln)wp4GpDUT$J8NtFDHJzIe_-t}{!HAsh zJ4<^WovY};)9IKAskSebdQiXv$y5}THuJZ}ouoElIZRui=6lrupV|_Jz=9^&;@HwL;J#@23k?A;k`0Bgf;ioO>W`IQ+4? z7A)eKoY4%+g%=w;=Vm8}H>@U*=*AWNtPqgWRqib#5RTGA@Q=43FrQn3J`GkTUV5yp0U`EOTqjfp+-9;0F8!dMEwwcK%(6`8sDD^aR04 zd6O5vh|Xk?&3dy4f|1QK&Ulf{h6Iq;d-&*ti#Ck>wZFG;GHwc?b;X~eBITx49>2d8 z4HcK&1&DvEGT6kXdzAm4oO8%c}8OBt~8H956_;YP-ss*uMf==a+%w~F>Qkm7r)IAuxuoX}h92$gHqbFUun#8m zWHdy`Zrm#=Pa98x8cO0vd@Tgkr*lm0{dky+Gocr0P8y%HGEI#c3qLqIRc`Oq_C%*; zG+QTr(#Q|yHKv6R@!DmLlwJQ3FAB)Yor-I4zyDyqM4yp5n2TrQH>gRt*Zw0+WI-Sj`EgmYHh=t9! zF6lz^xpqGGpo6!5`sc0a^FVhy_Uxq|@~(1@IIzV)nTpY9sY`CV!?8e&bB8=M&sYEb z2i}fvKdhp9Hs68Y-!QJ<=wE(iQ5+49tqt;Rh|jhYrI5VW-mIz|UY{h8E=rC5sh#DU z?wGgk-Tn!I?+Zer7pHlF_Z^!Kd1qkS3&lv#%s6-<5Y%jQL${cge5=G5Ab?D&|9$Y~ zf%rJC2+=2vg;y0-SJb3<@3%}BO$T$C66q$L_H33a`VUbgW~N(4B=v5(<=My|#|J7q z*Ox4wL4kbJd_~EjLTABSu4U7Jk#`y(6O*U6(k6XxM}CtGZB(H@3~kh*zaGRXM}Iwp zQ%xFk2>@wiZrVCV_G4G~v;NebCQ%T7{SDyPpSv&dT@Cn)Mx@IK*IdNrj{*4pkV4wv z)y0J538h>cpB7iPSzA~x24T`{dzNkpvGIqvt1Dvdq@o-`B=$hkczX8$yFMhsWNK-X zxr$kR$tMD0@W)Vxe1^t9qVmsg&K^F@u84)(n2dttIEAZFN6VD$&tskpG%SI7whGL3 z)DeRiwe&?8m7U{G`oW8!SCi*dM>oYL%UKQnKxV_0RXAEBQg1kStExGEUVwLJ0orGGwb7uv+kPDl7_E2*iD|J*=8A@;XCvwq0aw5oJYN*Yh&o=l} z2z8YKb-fIAH5spql4eXqp*)o2*b>#1@DSt?zZi{GPj0gH&Nm+EI<3^z0w%YTEV4xw zI6$+=Faa|Y4o5i0zm5lOg|&tmnJ806DBovU@Ll6XsA;NRrTK~t*AAJIAS=v-UZ%Pr z$oddI@NRir&erzCwq|)ciJemr-E061j{0Vc@Ys7K(mW|JYj*$+i1Q8XlIK8T?TYS(AXu$`2U zQ@fHxc=AVHl_}cRZQ)w0anMEoqRKKIvS^`<-aMf*FM`NsG&Uowneo+Ji$7DUDYc7*Hjg;-&aHM%3 zXO6cz$$G};Uqh+iY7Wpme>PHG4cu(q;xyskNLs$^uRRMfEg?8Cj~aE-ajM%CXkx0F z>C?g3tIA#9sBQOpe`J+04{q7^TqhFk^F1jFtk4JDRO*`d-fx`GYHb=&(JiaM1b?Y^ zO3Kj3sj76ieol|N$;>j@t#tKj=@*gP+mv}KwlTcPYgR$+)2(gk)2JNE=jSauPq!$< z<|?Sb%W)wS)b>b6i{8!x!^!xIdU3{CJFVnTcw0j{M%DUCF=_>eYYEUWnA-|B(+KYL z_W_`JI&&u^@t0})@DH^1LDuT0s3dMpCHIbYBgOT4Zh_4yHbSqRbtIKndeT4Q*Jg91 z@>rO!^t-G~*AIW;FQ$3J=b;oGg8?CTa~qNCb>&cgp@e;?0AqA&paz~(%PYO+QBo4( zp?}ZdSMWx0iJm7HVNk9A#^9Osa#GPJ!_pYEW}($8>&2}fbr@&ygZ?${A7_9?X$(&5 z#~-hxdPQwCNEpf=^+WH-3`2LxrrBMTa}~qJC9S;VzhG!On^JLyW6WkF{8aAE$sM+( zxr8xLW(KIjI`Rm(24r3OJBk<3GF=G!uSP0-G&AY32mLm8q=#Xom&Pqv=1C{d3>1^ zAjsmV@XZ%BKq^eUfBpa8KvO8ob|F3hAjJv*yo2Bhl0)KUus{qA9m8jf)KnOGGTa6~4>3@J_VzkL|vYPl*uL+Ot*Q7W!f5rJw5+AsjP_IfL+-S*2p| zB7!FhjvkUTxQkGWGSg{X;h~dK>gAJivW?88Nu!3o>ySDaABn$rAYt086#27fbjPQS zhq>55ASvm*60qRdVOY9=bU^+{Pi#!OaZwENN;zy5?EztOHK-Q5;rCuiFl}BSc1YaQ zC-S{=KsGDz@Ji9O5W;XxE0xI|@3o6(2~i4b8Ii9VT;^G$*dRw(V?=br)D&q^XkeBX z+gl~+R@rVD-Hwv@7RHV?Bip5KMI)aV^&snt?H<$Nt=OPx#VxF&BGi?2A2+lNOYywNUGMeGL;|(=UjGDtLG0sN&LpGx;|U;xa13s z;W_|SPk^G}!M9_^pO zA3bt3-tca%^42sHeDtfcC0S3w3H1ny!Bxpa=*k?XRPpx9Bb-gx1J9Yvx)4J(8cG+q z(iCPZ9dsf3#QVyZgD_MW#G#qgV)olu$59&3(PzQfw@%4uZ~<5J=ABvdY43(Qnp{;G zHg3>@T#>DbTuhFl3)fb3TFqdh)V2aq7!;&JOHseTWukvA7}(iGUq;v-{2J0iHSNHq z;+)h!p6Ok^+Sp8-jgL($n6Qu47xyE`cFO5SdZR6;R!FET`tm#0D37z339Suxjpv+s z*=%2-N$N?X&0?x_uut3erF@aBGj;9$k9?3FlbDO{RQa1_qtxrh4!4#fjp4x~akvdTp@ zos?^Q&XE;3N93s4rHQGPrV7+au1$$aB6$hLy*Yz_kN$~dweb9PcB!eYVQTGjFuJP> zZCEwBtb>TIgIO^qAzq@Bv-qud_ZD-2W<_at&ml-gv`tPt$@DF5`HlA zM>DmmMkpv&Zm-8)Y#0bLQf4MpD4_-7M8eu6rh(tL8dq8onHs#R9J~dGd2IaXXMC~h z91pKhnQa%Fsn29nAA1;x(%oC zhca~qQDJaMf?wFrl-Pj;e$bZMYmMF!Y3Lv&Sb?Sjn#!NVx&NDyc^$b4uYyo2OmERa zRz;yDGd@JTykzFLe|Wk-y7#3x`6$wt$zR8r48mdUvfbeL+4D|Z``~7$PrE@qc7rZe zVsIoIbCwzjLZ@_M1*bD{HaYn();Z1-q*-I{tEnTZ(}Zmk&%MXSNBX>o| z-u*RNkAyKC-Srp7c-=@5f)xMWg>o2WWl}j6j9=8+D8;T z>0*0q#;qw8%U8i;6s0fu#I*%(g*@@a2Er@@nyI}{=@W{Z-;`=wN4N~>6Xrh&z#g}l zN1g5}0-#(nHUTv_rl2{yUZ;h#t&Fd?tY!7L%ClY)>uH-Ny2ET$lW$S)IQiN79H)D^ zb&0AXYkupy0~w8)*>Sj_p9}4L?lGTq%VG|2p`nWGhnM^!g|j-|O{%9Q%swOq63|*W zw$(N_laI}`ilB+o!a-wl?er~;;3+)$_akSQ!8YO_&-e*SI7n^(QQ;X0ZE`{4f!gAl z5$d+9CKVNonM!NO_frREICIAxOv)wm>}-k?iRisM`R7;=lyo|E_YR~FpS&PS`Lg0f zl-ON<0S%Uix8J%#yZdkCz4YNhcec<|7*P(JsM#>-L>+tYg_71q9~70FAc^6KW5jql zw!crdgVLH1G_eET=|SEc977;)ezVC|{PJZfra|}@rD;0s&@61mTEBJtILllg{%{vN zfhb&lq0yChaLhnJ-Qb62MB7`>M;|_ceHKZAeeh@#8tbrK!ArP6oXIhMK;dhEJTY`@ z0Tq>MIe0`7tGv)N*F0IGYSJv0vN?Az8g+4K9S!pW2~9F4W(_U_T=jCZrzuZ3*|__T zONp_UWmyePv8C~rckc?Xji;Z5OEqg zC*Um)i;Wh4TEwqReQdVVbUKT^2>Tpi6z_^-uF*adUFug4i@JhzpWT^Sk&E>CyP2?H zWf6x}ehuTs6wvzCnTU&gYzT029Nz19(In1WC z`(1IGmi!O%2AR|BjQa4Q0~u)kM%}?xQyjWuQ16^Gp++;`vr7!k--UZWM*~7Zl|ceO@I3`OpaRhD;YoCuo5IC0uHx>9 z478hu@H|e0Zlo)Zj@01#;8BDs@991xe~^9uG2}UXLM(m7fa}AMwX*tjioBeV&Q8Gx zSq$6wZFkRBK`cMI>R(@W@+lo2t)L+4q-negWRLWZBz*|%=W4v62JrmzNuOtA*x)QE z5L%=OH#@KMdB%Jp^r?0tE}5-*6oP`-lO7Sf)0)n*e<{HA=&qhLR)oD8-+V}Z4=md) z+k9lKf64DB2hAT)UaCP~di?-V3~JBH7itYyk~L6hrnxM%?RKntqd`=!b|e7eFnAcu z3*V;g{xr7TSTm$}DY%~SMpl>m{Sj!We+WfxSEor?YeiAxYUy25pn(?T()E>ByP^c@ zipwvWrhIK((R((VU+;@LmOnDu)ZXB3YArzzin!Z^0;PyJWnlfflo|q8(QY;o1*5CO z##hnkO{uynTMdk`~DOC#1 zdiYxQoy}=@7(ke#A8$YZZVtk4wo$8x28&I;cY3Ro-|kW=*yiiHgCLZeAr)UtVx>Tu z|LvL0hq|1-jC0I4x#>&QZCfrVB=zT!nR|~Uz`9%~2 znl{uZ{VEszW`Fad^q_HB!K9*|U-stK%?~;g?&&+12A}Rq$z($Bzuk^2X(Y=hF?-dQ ztc3DsQKI;qhWIV`99Q#R3xnU0AvY!i*BECj-z9l74|%O=V@nlv|qqC^r^-~C?E zGW%c|uYgnfJ(gjsTm_cIqcv*mYM{+i+&@F@+69ZQOK&u#v4oxUSQJ=tvqQ3W=*m;| z>SkBi8LYb-qRY7Sthh*0%3XAC%$z1rhOJzuX=PkTOa=DlocZUpE#KxVNH5)_4n=T( zGi3YrH7e~sPNYVBd~Grcq#CF~rN{p9Zza-Ntnwfma@TB)=3g36*0lSZg#ixEjFe%+ zX=&LDZ5zqculZ`=RYc^ln(~;nN|Qh6gN=!6f9-N2h+3NWbIxYud&;4SX*tWf5slk4 z{q@@l71UAZgj~*6edXb57fBUxvAS7s(RI=X868JM0+^DCn2yC>;v%S;qPOjB>YVsz(Zx9a>>BK&M zIQK>7_n)4ud0X5YM}^i*keH{ehLsiy9@NvOpsFeQjdI6anLGvVbBw_*fU1TzdVS$i z*4j7z!I5RF#rSz|8ibi$;qE{4`aqWYik7QB5U&F5C*;TO_x+gtzPGpzNt!7~nsBT7)Ckc(K~%uv&{{6A`mmBJVAk-{s~52Vu|HbCH7_W1~ZCX^RflOakGg=jo2Z z<*s;5-J+2@^LRDZ-7EV&Pq+FTErw@pfFqvx^i%E7Fx#^n(E`m2(c>K-O5`M`Yek9el zzTGs5qD6*G;y#~xu3>qWuO?-amKYtvRA}I9z#UspEeM;wOERYeot_n_EUMJf$4_u?E!6X~?q)tPoZb^_;8Y_Ox2h1m<+Le-fsRd|T8db<8#$bqez zua^Z|>h%zdnuU^ww$#-dZ9NTM`FN+!IlLkz*FqWb!x^Z|C{KyGjZ+>G;;7Mb@LY|H zc+Gp`L((Dw7pnDlHNm&;SfHedhx*kad$I^uGz{`0BYelq0yEUHpNKSkvj$|dpvY3{7*YGyhXA^LP0&wOw9oNoC=QoVx1<2Dne8qqZL zm>nFh5DX(-RnQwvHCZQwn^#Z=E!SPVlaRJ78Bo@}!!9dRt^qZy?-*`Pt4WSmgucJv zV1yFkcjlEM^uz-;b#Q7ZCP@Lk)m}uPX={R4B=56k7WNh11BN~0T*vr@!!ow^B0hOR zQ)4)&(e%>bNNL%bm<&8H{*l_L7s0$2GUgX2Vd;=4d9Dm2v3TaL+;L>{K7h7 zV#k?xDPm(NDE31$ z<}|X)pEY6myjK+^gaIMk&Yj2~F0rSKemNqlsVm4c|N7mp_C*L01s;GNx#D-*&gk!qQr}^?_r@q!8fuXw!)fA7xkd} zb>vHvdx~H$5qqAWrow7}+8zBM65-JOt5z za=T6f7MK`XJuQog8kIEboPdhcaVJeHy)5z7EBLK5NRr()E|#K0L0N^JD@pUA^Czb` zbUZ_558y+vqAGeyHCbrvOvLD67Ph}06959VzQ_|>RrXQAqE+AQ(-AaKdxoWaF8hdt z{O3W@b^*o#-f1VuU>YMV03ELF7zkCN4Q&b#prz%3Nne0lSbRo@@ z^ihv%oIl~Qyl6Q;a#$*jOC%x0_;eis*)J7=f@Ct*)xF5 zo}u~@-I}2|$b%5L7>@+Z?4o+1r&v6ceIy+vroK&jCQ<4q&45HP2wCol4hVm3pZtjf zHz1D7oyaSKJ~T{Gx}7ONLA)D5k(%%`WswrDyzX*rn}i}}TB4^y#@mAwPzoC)`?rYv zHgx|trUN#mu*VzUV~8TnJM2Qh*ZM5B{x&y>5An`(M7=Z*Q>TdiH@j*2=moNuOtvpz z+G`@~-`%~+AgPKgke@XiRPgndh@bp*-HRsh;HTtz@-y_uhb%7ylVOTqG0#u?Vn5c5 zEp*XRo|8hcgG^$#{$O9CJ&NE;TrfRpSnLmes&MO{m=N%zc`}gb!eQ7odl$oy1%PI} z#AIxx%oRVy&{O~9xnK4$EY>(eQj}!HKIV$Fz*H=-=Kn)N0D6u`(;iO|VraI4fu_W` z;b5{7;Lyx4za}DU#+U7}=H0dAS#YJJ&g2!P@Htu-AL&w=-)*%P9h2{wR|@?Ff9~)b z^+e_3Hetq7W%ls{!?<6&Y$Z;NNB41pvrv)|MET6AZXFXJeFqbFW5@i5WGzl?bP+~? z*&_puH;wKv2)9T_d+P`bLvJFqX#j&xa*-;0nGBbQf0DC>o~=J_Wmtf*2SZQr?{i~X z9-IbRH8{iy?<0v9Ir1?$66+igy|yDQ5J~A9sFX@Pe<*kCY8+MwH?I z`P}zfQ6l^AO8ehZ=l^ZR;R%uu4;BK*=?W9t|0{+-at(MQZ(CtG=EJFNaFMlKCMXu30(gJUqj5+ z`GM|!keqcj;FKTa_qq;{*dHRXAq157hlB@kL#8%yAm2AgfU|*rDKX@FLlp=HL8ddv zAWLCHe@DcDeB2}fl7#=0+#<05c3=VqM*O3bkr@9X4nO|)q0hU;Gye{L8ZN*NH8Id@mP-u;Fmb8YuorjLrW&ndip8CN%_qp982r w1WEnz9^$&s1hkp_3#lPJQ~!HI7WYYjA7>z!`?f%npAh2%rB@vD|Lau$2O)#1n*aa+ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 92f06b50..b93c46a5 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/reflekt-core/build.gradle.kts b/reflekt-core/build.gradle.kts index 19ba903a..f8f7e433 100644 --- a/reflekt-core/build.gradle.kts +++ b/reflekt-core/build.gradle.kts @@ -1,5 +1,3 @@ -import tanvd.kosogor.proxy.publishJar - group = rootProject.group version = rootProject.version @@ -7,8 +5,6 @@ dependencies { implementation(libs.tomlj) } -publishJar {} - tasks.processResources.configure { duplicatesStrategy = DuplicatesStrategy.INCLUDE from(rootProject.file("gradle/libs.versions.toml")) diff --git a/reflekt-core/src/main/kotlin/org/jetbrains/reflekt/util/Util.kt b/reflekt-core/src/main/kotlin/org/jetbrains/reflekt/util/Util.kt index 4c916fbd..387c1f15 100644 --- a/reflekt-core/src/main/kotlin/org/jetbrains/reflekt/util/Util.kt +++ b/reflekt-core/src/main/kotlin/org/jetbrains/reflekt/util/Util.kt @@ -3,10 +3,6 @@ package org.jetbrains.reflekt.util import org.tomlj.Toml object Util { - private val versionCatalog by lazy { - Toml.parse(javaClass.getResource("/libs.versions.toml")!!.readText()) - } - /** Global constant with plugin identifier */ const val PLUGIN_ID = "org.jetbrains.reflekt" const val GRADLE_GROUP_ID = "org.jetbrains.reflekt" @@ -15,6 +11,9 @@ object Util { * Just needs to be consistent with the artifactId in reflekt-plugin build.gradle.kts#publishJar */ const val GRADLE_ARTIFACT_ID = "reflekt-plugin" + private val versionCatalog by lazy { + Toml.parse(javaClass.getResource("/libs.versions.toml")!!.readText()) + } val VERSION = versionCatalog.getString("versions.kotlin")!! val ENABLED_OPTION_INFO = MyCliOption( name = "enabled", diff --git a/reflekt-dsl/build.gradle.kts b/reflekt-dsl/build.gradle.kts index 3e62f9fc..fa067ceb 100644 --- a/reflekt-dsl/build.gradle.kts +++ b/reflekt-dsl/build.gradle.kts @@ -1,10 +1,6 @@ -import tanvd.kosogor.proxy.publishJar - group = rootProject.group version = rootProject.version dependencies { api(kotlin("compiler")) } - -publishJar {} diff --git a/reflekt-dsl/src/main/kotlin/org/jetbrains/reflekt/util/TypeStringRepresentationUtil.kt b/reflekt-dsl/src/main/kotlin/org/jetbrains/reflekt/util/TypeStringRepresentationUtil.kt index 1b2ba7c1..fed735ca 100644 --- a/reflekt-dsl/src/main/kotlin/org/jetbrains/reflekt/util/TypeStringRepresentationUtil.kt +++ b/reflekt-dsl/src/main/kotlin/org/jetbrains/reflekt/util/TypeStringRepresentationUtil.kt @@ -34,7 +34,7 @@ object TypeStringRepresentationUtil { */ fun KType.stringRepresentation(): String { // Get simple classifier name, e.g. kotlin.Function1 - val classifierName = (classifier as? KClass<*>)?.qualifiedName ?: (classifier as? KTypeParameter)?.name ?: "" + val classifierName = (classifier as? KClass<*>)?.qualifiedName ?: (classifier as? KTypeParameter)?.name.orEmpty() // If type is null it means we have star projection return TypeStringRepresentationUtil.getStringRepresentation( classifierName, diff --git a/reflekt-plugin/build.gradle.kts b/reflekt-plugin/build.gradle.kts index c67e74f3..ced5a117 100644 --- a/reflekt-plugin/build.gradle.kts +++ b/reflekt-plugin/build.gradle.kts @@ -1,4 +1,3 @@ -import tanvd.kosogor.proxy.publishJar @Suppress("DSL_SCOPE_VIOLATION") // https://youtrack.jetbrains.com/issue/KTIJ-19369 plugins { @@ -9,8 +8,6 @@ group = rootProject.group version = rootProject.version dependencies { - implementation(kotlin("scripting-common")) - implementation(kotlin("scripting-jvm")) implementation(kotlin("scripting-jvm-host-unshaded")) implementation(projects.reflektCore) @@ -35,7 +32,6 @@ dependencies { testImplementation(libs.kotlin.reflect) testImplementation(libs.kotlin.compiler.internal.test.framework) - testImplementation(platform(libs.junit.bom)) testImplementation(libs.junit.jupiter) testImplementation(libs.junit.platform.commons) testImplementation(libs.junit.platform.launcher) @@ -65,8 +61,6 @@ tasks.processTestResources.configure { from(rootProject.file("gradle/libs.versions.toml")) } -publishJar {} - fun Test.setLibraryProperty(propName: String, jarName: String) { val path = project.configurations.testRuntimeClasspath @@ -80,7 +74,7 @@ fun Test.setLibraryProperty(propName: String, jarName: String) { tasks.create("generateTests") { classpath = sourceSets.test.get().runtimeClasspath - mainClass.set("org.jetbrains.reflekt.plugin.compiler.GenerateTestsKt") + mainClass = "org.jetbrains.reflekt.plugin.compiler.GenerateTestsKt" } sourceSets { diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektCommandLineProcessor.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektCommandLineProcessor.kt index 8dcbc258..42e2d9fa 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektCommandLineProcessor.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektCommandLineProcessor.kt @@ -22,6 +22,7 @@ import java.io.File * Should match up with the options returned from the ReflektSubPlugin.applyToCompilation in the gradle-plugin module. * Should also have matching 'when'-branches for each option in the [processOption] function */ +@OptIn(ExperimentalCompilerApi::class) class ReflektCommandLineProcessor : CommandLineProcessor { override val pluginId: String = PLUGIN_ID override val pluginOptions: Collection = diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektComponentRegistrar.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektComponentRegistrar.kt index 8b1be126..d90d1084 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektComponentRegistrar.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/ReflektComponentRegistrar.kt @@ -2,9 +2,8 @@ package org.jetbrains.reflekt.plugin -import com.intellij.mock.MockProject import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension -import org.jetbrains.kotlin.compiler.plugin.ComponentRegistrar +import org.jetbrains.kotlin.compiler.plugin.* import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.reflekt.plugin.analysis.analyzer.IrInstancesAnalyzer import org.jetbrains.reflekt.plugin.analysis.collector.ir.* @@ -15,8 +14,6 @@ import org.jetbrains.reflekt.plugin.generation.code.generator.ReflektImplGenerat import org.jetbrains.reflekt.plugin.generation.ir.ReflektIrGenerationExtension import org.jetbrains.reflekt.plugin.generation.ir.SmartReflektIrGenerationExtension import org.jetbrains.reflekt.plugin.utils.PluginConfig -import org.jetbrains.reflekt.plugin.utils.Util.log -import org.jetbrains.reflekt.plugin.utils.Util.messageCollector import java.io.File /** @@ -36,8 +33,9 @@ import java.io.File * * @property isTestConfiguration indicates if the plugin is used in tests */ +@OptIn(ExperimentalCompilerApi::class) @Suppress("TOO_LONG_FUNCTION") -class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false) : ComponentRegistrar { +class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false) : CompilerPluginRegistrar() { override val supportsK2: Boolean = false /** @@ -45,21 +43,17 @@ class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false * All extensions will be called multiple times (for each project module), * since compilation process runs module by module * - * @param project current project - * @param configuration current compiler configuration, also stores all parsed options form the [ReflektCommandLineProcessor] + * @param configuration current compiler configuration, also stores all parsed options from the [ReflektCommandLineProcessor] */ - override fun registerProjectComponents( - project: MockProject, + override fun ExtensionStorage.registerExtensions( configuration: CompilerConfiguration, ) { val config = PluginConfig(configuration, isTestConfiguration = isTestConfiguration) - configuration.messageCollector.log("PROJECT FILE PATH: ${project.projectFilePath}") val instancesAnalyzer = IrInstancesAnalyzer() val libraryArgumentsWithInstances = LibraryArgumentsWithInstances() // Collect IR instances for classes, objects, and functions IrGenerationExtension.registerExtension( - project, InstancesCollectorExtension( irInstancesAnalyzer = instancesAnalyzer, reflektMetaFilesFromLibraries = config.reflektMetaFilesFromLibraries, @@ -86,20 +80,19 @@ class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false // file installed of IR replacement for these queries. if (config.toSaveMetadata) { // Handle II.a) case - project.collectAndStoreReflektArguments(config, instancesAnalyzer) + collectAndStoreReflektArguments(config, instancesAnalyzer) } else { // Handle I case - project.replaceReflektQueries(config, instancesAnalyzer, libraryArgumentsWithInstances) + replaceReflektQueries(config, instancesAnalyzer, libraryArgumentsWithInstances) } } - private fun MockProject.collectAndStoreReflektArguments( + private fun ExtensionStorage.collectAndStoreReflektArguments( config: PluginConfig, instancesAnalyzer: IrInstancesAnalyzer, ) { val reflektQueriesArguments = LibraryArguments() IrGenerationExtension.registerExtension( - this, ReflektArgumentsCollectorExtension( irInstancesAnalyzer = instancesAnalyzer, reflektQueriesArguments = reflektQueriesArguments, @@ -108,7 +101,6 @@ class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false ) val reflektMetaFile = config.reflektMetaFileRelativePath?.let { File(it) } ?: error("reflektMetaFileRelativePath is null for the project") IrGenerationExtension.registerExtension( - this, ReflektMetaFileGenerator( instancesAnalyzer, reflektQueriesArguments, @@ -118,22 +110,20 @@ class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false ) } - private fun MockProject.replaceReflektQueries( + private fun ExtensionStorage.replaceReflektQueries( config: PluginConfig, instancesAnalyzer: IrInstancesAnalyzer, libraryArgumentsWithInstances: LibraryArgumentsWithInstances, ) { // Extract reflekt arguments from external libraries IrGenerationExtension.registerExtension( - this, ExternalLibraryInstancesCollectorExtension( irInstancesAnalyzer = instancesAnalyzer, - irInstancesFqNames = libraryArgumentsWithInstances.instances, + irInstancesIds = libraryArgumentsWithInstances.instances, ), ) this.generateReflektImpl(config, instancesAnalyzer, libraryArgumentsWithInstances.libraryArguments) IrGenerationExtension.registerExtension( - this, ReflektIrGenerationExtension( irInstancesAnalyzer = instancesAnalyzer, libraryArguments = libraryArgumentsWithInstances.libraryArguments, @@ -142,7 +132,6 @@ class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false ) IrGenerationExtension.registerExtension( - this, SmartReflektIrGenerationExtension( irInstancesAnalyzer = instancesAnalyzer, classpath = config.dependencyJars, @@ -151,7 +140,7 @@ class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false ) } - private fun MockProject.generateReflektImpl( + private fun ExtensionStorage.generateReflektImpl( config: PluginConfig, instancesAnalyzer: IrInstancesAnalyzer, libraryArguments: LibraryArguments, @@ -161,7 +150,6 @@ class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false } val libraryQueriesResults = LibraryQueriesResults.fromLibraryArguments(libraryArguments) IrGenerationExtension.registerExtension( - this, LibraryQueriesResultsCollector( irInstancesAnalyzer = instancesAnalyzer, libraryQueriesResults = libraryQueriesResults, @@ -169,7 +157,6 @@ class ReflektComponentRegistrar(private val isTestConfiguration: Boolean = false ), ) IrGenerationExtension.registerExtension( - this, ReflektImplGeneratorExtension( libraryQueriesResults = libraryQueriesResults, generationPath = config.outputDir!!, diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/collector/ir/InstancesCollector.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/collector/ir/InstancesCollector.kt index 70e096f2..b8a3925f 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/collector/ir/InstancesCollector.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/collector/ir/InstancesCollector.kt @@ -9,19 +9,16 @@ import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.symbols.* import org.jetbrains.kotlin.ir.util.file -import org.jetbrains.kotlin.ir.util.nameForIrSerialization import org.jetbrains.kotlin.ir.visitors.acceptChildrenVoid -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.* import java.io.File /** * A collector for searching and collecting all classes, objects, and functions in the project. * - * @param irInstancesAnalyzer analyzer that check if the current IR element satisfy a condition, - * e.g. is a top level function + * @param irInstancesAnalyzer the analyzer that checks if the current IR element satisfies to a condition like being a top level function. * @param messageCollector */ class InstancesCollector( @@ -29,15 +26,15 @@ class InstancesCollector( messageCollector: MessageCollector? = null, ) : BaseCollector(irInstancesAnalyzer, messageCollector) { override fun visitDeclaration(declaration: IrDeclarationBase) { - messageCollector?.log("Start checking declaration: ${declaration.nameForIrSerialization}") + messageCollector?.log("Start checking declaration: ${(declaration as? IrDeclarationWithName)?.name}") irInstancesAnalyzer.process(declaration, declaration.file) - messageCollector?.log("Finish checking declaration: ${declaration.nameForIrSerialization}") + messageCollector?.log("Finish checking declaration: ${(declaration as? IrDeclarationWithName)?.name}") super.visitDeclaration(declaration) } } /** - * A compiler plugin extension for searching and collection all classes, objects, and functions. + * A compiler plugin extension for searching and collecting all classes, objects, and functions. */ class InstancesCollectorExtension( private val irInstancesAnalyzer: IrInstancesAnalyzer, @@ -47,7 +44,7 @@ class InstancesCollectorExtension( ) : IrGenerationExtension { // TODO: can we avoid making a copy here? (using var and make a copy later, e.g. 60-61 code rows) private var libraryArguments = LibraryArguments() - private var irInstancesFqNames = IrInstancesFqNames() + private var irInstancesIds = IrInstancesIds() override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { extractInstancesFromLibraries(pluginContext) @@ -58,32 +55,28 @@ class InstancesCollectorExtension( for (metaFile in reflektMetaFilesFromLibraries) { val currentLibraryArgumentsWithInstances = SerializationUtils.decodeArguments(metaFile.readBytes(), pluginContext) libraryArguments = libraryArguments.merge(currentLibraryArgumentsWithInstances.libraryArguments) - irInstancesFqNames = irInstancesFqNames.merge(currentLibraryArgumentsWithInstances.instances) + irInstancesIds = irInstancesIds.merge(currentLibraryArgumentsWithInstances.instances) } - libraryArgumentsWithInstances.replace(libraryArguments, irInstancesFqNames) + libraryArgumentsWithInstances.replace(libraryArguments, irInstancesIds) } } class ExternalLibraryInstancesCollectorExtension( private val irInstancesAnalyzer: IrInstancesAnalyzer, - private val irInstancesFqNames: IrInstancesFqNames, + private val irInstancesIds: IrInstancesIds, ) : IrGenerationExtension { private val externalLibraryId = "EXTERNAL_LIBRARY" override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { - val classes = findIrClasses(irInstancesFqNames.classes, pluginContext::referenceClass) - val objects = findIrClasses(irInstancesFqNames.objects, pluginContext::referenceClass) - val functions = findIrFunctions(irInstancesFqNames.functions, pluginContext::referenceFunctions) + val classes = findIrClasses(irInstancesIds.classes, pluginContext) + val objects = findIrClasses(irInstancesIds.objects, pluginContext) + val functions = findIrFunctions(irInstancesIds.functions, pluginContext) irInstancesAnalyzer.addDeclarations(externalLibraryId, classes, objects, functions) } - private fun findIrClasses( - fqNamesStr: List, - referenceDeclaration: (FqName) -> IrClassSymbol?, - ) = fqNamesStr.mapNotNull { referenceDeclaration(FqName(it))?.owner } + private fun findIrClasses(fqNamesStr: List, pluginContext: IrPluginContext) = + fqNamesStr.mapNotNull { pluginContext.referenceClass(it)?.owner } - private fun findIrFunctions( - fqNamesStr: List, - referenceDeclaration: (FqName) -> Collection?, - ) = fqNamesStr.mapNotNull { referenceDeclaration(FqName(it)) }.flatten().map { it.owner } + private fun findIrFunctions(fqNamesStr: List, pluginContext: IrPluginContext) = + fqNamesStr.map { pluginContext.referenceFunctions(it) }.flatten().map { it.owner } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/common/ReflektNames.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/common/ReflektNames.kt index 712e9a68..739ea349 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/common/ReflektNames.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/common/ReflektNames.kt @@ -1,7 +1,6 @@ package org.jetbrains.reflekt.plugin.analysis.common -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.name.* import org.jetbrains.reflekt.Reflekt import org.jetbrains.reflekt.SmartReflekt @@ -71,12 +70,28 @@ enum class SmartReflektTerminalFunction(val functionName: String) { ; } -object ReflektPackage { +object ReflektNames { const val PACKAGE_NAME = "org.jetbrains.reflekt" + const val REFLEKT_CLASS = "ReflektClass" + const val REFLEKT_CLASS_IMPL = "ReflektClassImpl" + const val REFLEKT_OBJECT = "ReflektObject" + const val REFLEKT_VISIBILITY = "ReflektVisibility" val PACKAGE_FQ_NAME = FqName(PACKAGE_NAME) + val REFLEKT_CLASS_NAME = Name.identifier(REFLEKT_CLASS) + val REFLEKT_CLASS_CLASS_ID = ClassId(PACKAGE_FQ_NAME, REFLEKT_CLASS_NAME) + val REFLEKT_CLASS_IMPL_NAME = Name.identifier(REFLEKT_CLASS_IMPL) + val REFLEKT_CLASS_IMPL_CLASS_ID = ClassId(PACKAGE_FQ_NAME, REFLEKT_CLASS_IMPL_NAME) + val REFLEKT_OBJECT_NAME = Name.identifier(REFLEKT_OBJECT) + val REFLEKT_OBJECT_CLASS_ID = ClassId(PACKAGE_FQ_NAME, REFLEKT_OBJECT_NAME) + val REFLEKT_VISIBILITY_NAME = Name.identifier(REFLEKT_VISIBILITY) + val REFLEKT_VISIBILITY_CLASS_ID = ClassId(PACKAGE_FQ_NAME, REFLEKT_VISIBILITY_NAME) } object StorageClassNames { const val REFLEKT_CLASSES = "reflektClasses" val REFLEKT_CLASSES_NAME = Name.identifier(REFLEKT_CLASSES) + + fun getStorageClass(idx: Int): String = "Storage_$idx" + fun getStorageClassName(idx: Int): Name = Name.identifier(getStorageClass(idx)) + fun getStorageClassId(idx: Int): ClassId = ClassId(ReflektNames.PACKAGE_FQ_NAME, getStorageClassName(idx)) } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/ir/ArgumentCollectors.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/ir/ArgumentCollectors.kt index 33bec41a..efa9a8a8 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/ir/ArgumentCollectors.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/ir/ArgumentCollectors.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.visitors.IrElementVisitor +import org.jetbrains.kotlin.name.ClassId open class IrRecursiveVisitor : IrElementVisitor { override fun visitElement(element: IrElement, data: Nothing?) { @@ -23,18 +24,18 @@ open class IrRecursiveVisitor : IrElementVisitor { * Traverses subtree of expression and collects arguments of withSupertype, withSupertypes and withAnnotations calls to construct [SupertypesToAnnotations]. */ class ReflektInvokeArgumentsCollector : IrRecursiveVisitor() { - private val supertypes = HashSet() - private val annotations = HashSet() + private val supertypes = HashSet() + private val annotations = HashSet() override fun visitCall(expression: IrCall, data: Nothing?) { super.visitCall(expression, data) val function = expression.symbol.owner when (function.name.asString()) { - ReflektFunction.WITH_SUPERTYPE.functionName -> supertypes.addAll(expression.getFqNamesOfTypeArguments()) - ReflektFunction.WITH_SUPERTYPES.functionName -> supertypes.addAll(expression.getFqNamesOfClassReferenceValueArguments()) + ReflektFunction.WITH_SUPERTYPE.functionName -> supertypes.addAll(expression.getClassIdsOfTypeArguments()) + ReflektFunction.WITH_SUPERTYPES.functionName -> supertypes.addAll(expression.getClassIdsOfClassReferenceValueArguments()) ReflektFunction.WITH_ANNOTATIONS.functionName -> { - annotations.addAll(expression.getFqNamesOfClassReferenceValueArguments()) - supertypes.addAll(expression.getFqNamesOfTypeArguments()) + annotations.addAll(expression.getClassIdsOfClassReferenceValueArguments()) + supertypes.addAll(expression.getClassIdsOfTypeArguments()) } } } @@ -56,7 +57,7 @@ class ReflektInvokeArgumentsCollector : IrRecursiveVisitor() { * Traverses subtree of expression and collects arguments of withSupertype, withSupertypes and withAnnotations calls to construct [SignatureToAnnotations]. */ class ReflektFunctionInvokeArgumentsCollector : IrRecursiveVisitor() { - private val annotations = HashSet() + private val annotations = HashSet() private var irSignature: IrType? = null override fun visitCall(expression: IrCall, data: Nothing?) { @@ -64,7 +65,7 @@ class ReflektFunctionInvokeArgumentsCollector : IrRecursiveVisitor() { val function = expression.symbol.owner when (function.name.asString()) { ReflektFunction.WITH_ANNOTATIONS.functionName -> { - annotations.addAll(expression.getFqNamesOfClassReferenceValueArguments()) + annotations.addAll(expression.getClassIdsOfClassReferenceValueArguments()) irSignature = expression.getTypeArgument(0) } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/ir/Util.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/ir/Util.kt index b3b44d27..9614ce5d 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/ir/Util.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/ir/Util.kt @@ -10,22 +10,25 @@ import org.jetbrains.kotlin.ir.expressions.* import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.* +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.types.Variance import org.jetbrains.reflekt.plugin.analysis.models.ir.IrFunctionInfo +import org.jetbrains.reflekt.plugin.utils.callableId -fun IrCall.getFqNamesOfTypeArguments(): List { - val result = ArrayList() +fun IrCall.getClassIdsOfTypeArguments(): List { + val result = ArrayList() for (i in 0 until typeArgumentsCount) { val type = getTypeArgument(i) require(type is IrSimpleType) { "Type argument is not IrSimpleType" } - result += type.classFqName.toString() + result += type.classOrNull?.owner?.classId ?: continue } return result } -fun IrCall.getFqNamesOfClassReferenceValueArguments(): List = - (getValueArgument(0) as? IrVararg)?.elements?.map { - (it as IrClassReference).classType.classFqName.toString() +fun IrCall.getClassIdsOfClassReferenceValueArguments(): List = + (getValueArgument(0) as? IrVararg)?.elements?.mapNotNull { + (it as IrClassReference).classType.classOrNull?.owner + ?.classId } ?: emptyList() @OptIn(ObsoleteDescriptorBasedAPI::class) @@ -35,13 +38,9 @@ fun IrClass.isSubtypeOf(type: IrType, pluginContext: IrPluginContext) = this.def fun IrType.makeTypeProjection() = makeTypeProjection(this, if (this is IrTypeProjection) this.variance else Variance.INVARIANT) -fun IrFunction.toFunctionInfo(): IrFunctionInfo { - fqNameWhenAvailable ?: error("Can not get FqName for function $this") - return IrFunctionInfo( - fqNameWhenAvailable.toString(), - receiverFqName = receiverType()?.classFqName?.asString(), - isObjectReceiver = receiverType()?.getClass()?.isObject ?: false, - ) -} +fun IrFunction.toFunctionInfo(): IrFunctionInfo = IrFunctionInfo( + callableId, + isObjectReceiver = receiverType()?.getClass()?.isObject ?: false, +) fun IrFunction.receiverType(): IrType? = extensionReceiverParameter?.type ?: dispatchReceiverParameter?.type diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/Common.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/Common.kt index b4e9cdf9..46f9f392 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/Common.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/Common.kt @@ -4,30 +4,8 @@ import org.jetbrains.reflekt.plugin.analysis.processor.FileId import org.jetbrains.kotlin.types.Variance import kotlinx.serialization.Serializable import org.jetbrains.kotlin.ir.types.SimpleTypeNullability - -/** - * @property value - */ -enum class ElementType(val value: String) { - BLOCK("BLOCK"), - CALL_EXPRESSION("CALL_EXPRESSION"), - DOT_QUALIFIED_EXPRESSION("DOT_QUALIFIED_EXPRESSION"), - FILE("kotlin.FILE"), - FUNCTION_LITERAL("FUNCTION_LITERAL"), - FUNCTION_TYPE("FUNCTION_TYPE"), - LAMBDA_ARGUMENT("LAMBDA_ARGUMENT"), - LAMBDA_EXPRESSION("LAMBDA_EXPRESSION"), - NULLABLE_TYPE("NULLABLE_TYPE"), - REFERENCE_EXPRESSION("REFERENCE_EXPRESSION"), - TYPE_ARGUMENT_LIST("TYPE_ARGUMENT_LIST"), - TYPE_PROJECTION("TYPE_PROJECTION"), - TYPE_REFERENCE("TYPE_REFERENCE"), - USER_TYPE("USER_TYPE"), - VALUE_ARGUMENT_LIST("VALUE_ARGUMENT_LIST"), - VALUE_PARAMETER("VALUE_PARAMETER"), - VALUE_PARAMETER_LIST("VALUE_PARAMETER_LIST"), - ; -} +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.reflekt.plugin.analysis.serialization.ClassIdSerializer /** * Interface of classes for which empty instances may exist. @@ -40,23 +18,9 @@ interface Emptiable { } /** - * @property fqName - * @property arguments - * @property returnType - * @property receiverType - * @property contextReceiverTypes - */ -@Serializable -data class SerializableKotlinType( - val fqName: String, - val arguments: List = emptyList(), - val returnType: String, - val receiverType: SerializableKotlinType?, - val contextReceiverTypes: List = emptyList(), -) - -/** - * @property classifierFqName + * + * + * @property classifierClassId * @property nullability * @property arguments * @property annotations @@ -65,7 +29,7 @@ data class SerializableKotlinType( */ @Serializable data class SerializableIrType( - val classifierFqName: String, + val classifierClassId: @Serializable(with = ClassIdSerializer::class) ClassId, val nullability: SimpleTypeNullability, val arguments: List, val annotations: List, @@ -74,29 +38,19 @@ data class SerializableIrType( ) /** - * @property fqName + * + * + * @property classId The class ID of the serialized IrType * @property isStarProjection * @property variance */ @Serializable data class SerializableIrTypeArgument( - val fqName: String? = null, + val classId: @Serializable(with = ClassIdSerializer::class) ClassId? = null, val isStarProjection: Boolean, val variance: Variance, ) -/** - * @property fqName - * @property isStarProjection - * @property projectionKind - */ -@Serializable -data class SerializableTypeProjection( - val fqName: String, - val isStarProjection: Boolean, - val projectionKind: Variance, -) - /** * @property objects * @property classes @@ -141,14 +95,4 @@ fun Emptiable.isNotEmpty() = !isEmpty() @Suppress("IDENTIFIER_LENGTH") inline fun , M : MutableMap> M.merge(second: Map, defaultValue: () -> T): M = - this.also { second.forEach { (k, v) -> this.getOrPut(k) { defaultValue() }.addAll(v) } } - -inline fun merge( - first: T, - second: T, - mergeFunction: (T, T) -> T, -): T = when { - first.isEmpty() -> second - second.isEmpty() -> first - else -> mergeFunction(first, second) -} + this.apply { second.forEach { (k, v) -> getOrPut(k) { defaultValue() }.addAll(v) } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ReflektQueryArguments.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ReflektQueryArguments.kt index 84bffa44..5867070d 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ReflektQueryArguments.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ReflektQueryArguments.kt @@ -2,7 +2,9 @@ package org.jetbrains.reflekt.plugin.analysis.models import kotlinx.serialization.Serializable import org.jetbrains.kotlin.ir.types.IrType +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.reflekt.plugin.analysis.processor.FileId +import org.jetbrains.reflekt.plugin.analysis.serialization.ClassIdSerializer typealias ClassOrObjectQueryArguments = MutableSet typealias FunctionQueryArguments = MutableSet @@ -19,8 +21,8 @@ interface ReflektQueryArguments */ @Serializable data class SupertypesToAnnotations( - val supertypes: Set = emptySet(), - val annotations: Set = emptySet(), + val supertypes: Set<@Serializable(with = ClassIdSerializer::class) ClassId> = emptySet(), + val annotations: Set<@Serializable(with = ClassIdSerializer::class) ClassId> = emptySet(), ) : ReflektQueryArguments /** @@ -29,7 +31,7 @@ data class SupertypesToAnnotations( */ data class SignatureToAnnotations( val irSignature: IrType?, - val annotations: Set = emptySet(), + val annotations: Set = emptySet(), ) : ReflektQueryArguments /** @@ -39,7 +41,7 @@ data class SignatureToAnnotations( @Serializable data class SerializableSignatureToAnnotations( val irSignature: SerializableIrType?, - val annotations: Set = emptySet(), + val annotations: Set<@Serializable(with = ClassIdSerializer::class) ClassId> = emptySet(), ) /** diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/IrFunctionInfo.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/IrFunctionInfo.kt index ff52f1b2..8aa566af 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/IrFunctionInfo.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/IrFunctionInfo.kt @@ -1,14 +1,14 @@ package org.jetbrains.reflekt.plugin.analysis.models.ir +import org.jetbrains.kotlin.name.CallableId + /** * Stores enough information to generate function reference IR * - * @property fqName - * @property receiverFqName + * @property callableId The callable ID of function. * @property isObjectReceiver */ data class IrFunctionInfo( - val fqName: String, - val receiverFqName: String?, + val callableId: CallableId, val isObjectReceiver: Boolean, ) diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/IrInstances.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/IrInstances.kt index 89b4849f..e5433235 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/IrInstances.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/IrInstances.kt @@ -1,11 +1,15 @@ package org.jetbrains.reflekt.plugin.analysis.models.ir -import org.jetbrains.reflekt.plugin.analysis.models.BaseCollectionReflektData - -import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable - import kotlinx.serialization.Serializable +import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.IrFunction +import org.jetbrains.kotlin.ir.util.classId +import org.jetbrains.kotlin.name.CallableId +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.reflekt.plugin.analysis.models.BaseCollectionReflektData +import org.jetbrains.reflekt.plugin.analysis.serialization.CallableIdSerializer +import org.jetbrains.reflekt.plugin.analysis.serialization.ClassIdSerializer +import org.jetbrains.reflekt.plugin.utils.callableId /** * Stores all [classes], [objects], and [functions] from the project. @@ -33,12 +37,12 @@ data class IrInstances( // TODO: We can not inherit from BaseCollectionReflektData since this issue: // https://github.com/Kotlin/kotlinx.serialization/issues/1264 @Serializable -data class IrInstancesFqNames( - val objects: List = ArrayList(), - val classes: List = ArrayList(), - val functions: List = ArrayList(), +data class IrInstancesIds( + val objects: List<@Serializable(with = ClassIdSerializer::class) ClassId> = ArrayList(), + val classes: List<@Serializable(with = ClassIdSerializer::class) ClassId> = ArrayList(), + val functions: List<@Serializable(with = CallableIdSerializer::class) CallableId> = ArrayList(), ) { - fun merge(second: IrInstancesFqNames) = IrInstancesFqNames( + fun merge(second: IrInstancesIds) = IrInstancesIds( classes = classes.plus(second.classes), objects = objects.plus(second.objects), functions = functions.plus(second.functions), @@ -46,18 +50,16 @@ data class IrInstancesFqNames( companion object { /** - * Converts [IrInstances] into [IrInstancesFqNames]. - * For each IrElement, e.g. IrClass or IrFunction, collects its fqName if it is possible. + * Converts [IrInstances] into [IrInstancesIds]. + * For each IrElement, e.g., IrClass or IrFunction, collects its fqName if it is possible. * * @param irInstances - * @return [IrInstancesFqNames] + * @return [IrInstancesIds] */ - fun fromIrInstances(irInstances: IrInstances) = IrInstancesFqNames( - classes = irInstances.classes.fqNameWhenAvailable(), - objects = irInstances.objects.fqNameWhenAvailable(), - functions = irInstances.functions.fqNameWhenAvailable(), + fun fromIrInstances(irInstances: IrInstances) = IrInstancesIds( + classes = irInstances.classes.mapNotNull { it.classId }, + objects = irInstances.objects.mapNotNull { it.classId }, + functions = irInstances.functions.map { it.callableId }, ) - - private fun List.fqNameWhenAvailable() = this.mapNotNull { it.fqNameWhenAvailable?.asString() } } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/LibraryArguments.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/LibraryArguments.kt index a1748996..a0a48c0f 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/LibraryArguments.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/models/ir/LibraryArguments.kt @@ -55,28 +55,28 @@ data class LibraryArguments( /** * Stores all Reflekt queries arguments from the library with all instances of classes, objects, and functions. - * @property libraryArguments_ - * @property instances_ + * @property _libraryArguments + * @property _instances */ @Suppress("ConstructorParameterNaming") data class LibraryArgumentsWithInstances( - private var libraryArguments_: LibraryArguments = LibraryArguments(), - private var instances_: IrInstancesFqNames = IrInstancesFqNames(), + private var _libraryArguments: LibraryArguments = LibraryArguments(), + private var _instances: IrInstancesIds = IrInstancesIds(), ) { val libraryArguments: LibraryArguments - get() = libraryArguments_ + get() = _libraryArguments - val instances: IrInstancesFqNames - get() = instances_ + val instances: IrInstancesIds + get() = _instances fun toSerializableLibraryArgumentsWithInstances() = SerializableLibraryArgumentsWithInstances( libraryArguments = libraryArguments.toSerializableLibraryArguments(), instances = instances, ) - fun replace(newLibraryArguments: LibraryArguments, newInstances: IrInstancesFqNames) { - libraryArguments_ = newLibraryArguments - instances_ = newInstances + fun replace(newLibraryArguments: LibraryArguments, newInstances: IrInstancesIds) { + _libraryArguments = newLibraryArguments + _instances = newInstances } } @@ -89,7 +89,7 @@ data class LibraryArgumentsWithInstances( @Serializable data class SerializableLibraryArgumentsWithInstances( val libraryArguments: SerializableReflektQueryArguments, - val instances: IrInstancesFqNames, + val instances: IrInstancesIds, ) { fun toLibraryArgumentsWithInstances(pluginContext: IrPluginContext) = LibraryArgumentsWithInstances( @@ -138,7 +138,6 @@ data class LibraryQueriesResults( functions = libraryArguments.functions.flatten(), ) - @Suppress("IDENTIFIER_LENGTH", "TYPE_ALIAS") private fun LibraryArgumentsMap.flatten(): TypeLibraryQueriesResults { val queriesResults: TypeLibraryQueriesResults = HashMap() for ((_, arguments) in this) { diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/Util.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/Util.kt index 528217e8..ca9c11eb 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/Util.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/Util.kt @@ -3,14 +3,8 @@ package org.jetbrains.reflekt.plugin.analysis.processor import org.jetbrains.kotlin.descriptors.DescriptorVisibilities import org.jetbrains.kotlin.descriptors.DescriptorVisibility import org.jetbrains.kotlin.ir.declarations.IrFile -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.reflekt.ReflektVisibility -// TODO: is it enough to identify a file? -internal val KtFile.fullName: FileId - get() = getNameWithPackage(this.packageFqName, this.name) - // TODO: Use this function instead KtFile.fullName in the future internal val IrFile.fullName: FileId get() = this.fileEntry.getSourceRangeInfo(0, this.fileEntry.maxOffset).filePath @@ -28,11 +22,6 @@ internal fun DescriptorVisibility.toReflektVisibility() = when (this) { internal fun > getInvokesGroupedByFiles(fileToInvokes: Map): MutableSet = groupFilesByInvokes(fileToInvokes).keys.flatten().toHashSet() -internal fun getNameWithPackage(packageFqName: FqName, name: String? = null): FileId { - val postfix = name?.let { ".$name" } ?: "" - return "${packageFqName.asString()}$postfix" -} - // To avoid repeated checks for belonging invokes in different files, // we will group files by invokes and process each of them once // MutableSet<*> here is ClassOrObjectInvokes = MutableSet diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/ir/reflektArguments/IrClassOrObjectArgumentProcessor.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/ir/reflektArguments/IrClassOrObjectArgumentProcessor.kt index 4cb0ff46..58cf7503 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/ir/reflektArguments/IrClassOrObjectArgumentProcessor.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/ir/reflektArguments/IrClassOrObjectArgumentProcessor.kt @@ -2,16 +2,15 @@ package org.jetbrains.reflekt.plugin.analysis.processor.ir.reflektArguments -import org.jetbrains.reflekt.plugin.analysis.common.ReflektEntity -import org.jetbrains.reflekt.plugin.analysis.ir.ReflektInvokeArgumentsCollector -import org.jetbrains.reflekt.plugin.analysis.ir.isSubtypeOf -import org.jetbrains.reflekt.plugin.analysis.models.SupertypesToAnnotations - import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.types.defaultType -import org.jetbrains.kotlin.name.FqName +import org.jetbrains.kotlin.name.ClassId +import org.jetbrains.reflekt.plugin.analysis.common.ReflektEntity +import org.jetbrains.reflekt.plugin.analysis.ir.ReflektInvokeArgumentsCollector +import org.jetbrains.reflekt.plugin.analysis.ir.isSubtypeOf +import org.jetbrains.reflekt.plugin.analysis.models.SupertypesToAnnotations /** * A base class to process objects and classes Reflekt queries and extract the arguments. @@ -28,9 +27,9 @@ abstract class IrClassOrObjectArgumentProcessor(private val irInstances: List): Boolean { + private fun IrClass.isSubtypeOfAny(superTypes: Set): Boolean { require(superTypes.isNotEmpty()) { "The set of super types is empty" } - return superTypes.mapNotNull { context.referenceClass(FqName(it)) }.any { this.isSubtypeOf(it.defaultType, context) } + return superTypes.mapNotNull { context.referenceClass(it) }.any { this.isSubtypeOf(it.defaultType, context) } } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/ir/reflektArguments/IrReflektArgumentProcessor.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/ir/reflektArguments/IrReflektArgumentProcessor.kt index 2cfc5061..a82dcb15 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/ir/reflektArguments/IrReflektArgumentProcessor.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/processor/ir/reflektArguments/IrReflektArgumentProcessor.kt @@ -12,7 +12,9 @@ import org.jetbrains.kotlin.backend.jvm.codegen.AnnotationCodegen.Companion.anno import org.jetbrains.kotlin.ir.IrElement import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall +import org.jetbrains.kotlin.ir.util.classId import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable +import org.jetbrains.kotlin.name.ClassId import java.util.* import kotlin.collections.HashMap @@ -92,20 +94,22 @@ abstract class IrReflektArgumentProcessor): Boolean { - if (annotationsFqNames.isEmpty()) { + protected fun T.hasAnnotationFrom(annotationsClassIds: Set): Boolean { + if (annotationsClassIds.isEmpty()) { return true } - if (this.annotations.isEmpty()) { + if (annotations.isEmpty()) { return false } - return annotationsFqNames.any { name -> name in this.annotations.mapNotNull { it.annotationClass.fqNameWhenAvailable?.toString() } } + return annotationsClassIds.any { name -> + name in annotations.mapNotNull { it.annotationClass.classId } + } } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/serialization/ClassIdSerializer.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/serialization/ClassIdSerializer.kt new file mode 100644 index 00000000..0146cb9c --- /dev/null +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/serialization/ClassIdSerializer.kt @@ -0,0 +1,98 @@ +package org.jetbrains.reflekt.plugin.analysis.serialization + +import kotlinx.serialization.* +import kotlinx.serialization.builtins.serializer +import kotlinx.serialization.descriptors.SerialDescriptor +import kotlinx.serialization.encoding.Decoder +import kotlinx.serialization.encoding.Encoder +import org.jetbrains.kotlin.name.* + +@OptIn(ExperimentalSerializationApi::class) +@Serializer(forClass = FqName::class) +object FqNameSerializer : KSerializer { + override val descriptor: SerialDescriptor = String.serializer().descriptor + override fun deserialize(decoder: Decoder): FqName = FqName(decoder.decodeString()) + override fun serialize(encoder: Encoder, value: FqName) = encoder.encodeString(value.asString()) +} + +@OptIn(ExperimentalSerializationApi::class) +@Serializer(forClass = Name::class) +object NameSerializer : KSerializer { + override val descriptor: SerialDescriptor = NameSurrogate.serializer().descriptor + override fun deserialize(decoder: Decoder): Name { + val surrogate = decoder.decodeSerializableValue(NameSurrogate.serializer()) + return if (surrogate.isSpecial) { + Name.special(surrogate.name) + } else { + Name.identifier(surrogate.name) + } + } + + override fun serialize(encoder: Encoder, value: Name) = + encoder.encodeSerializableValue(NameSurrogate.serializer(), NameSurrogate(value.asString(), value.isSpecial)) +} + +@OptIn(ExperimentalSerializationApi::class) +@Serializer(forClass = ClassId::class) +object ClassIdSerializer : KSerializer { + override val descriptor: SerialDescriptor = ClassIdSurrogate.serializer().descriptor + + override fun deserialize(decoder: Decoder): ClassId { + val surrogate = decoder.decodeSerializableValue(ClassIdSurrogate.serializer()) + return ClassId(surrogate.packageFqName, surrogate.relativeClassName, surrogate.isLocal) + } + + override fun serialize(encoder: Encoder, value: ClassId) { + val surrogate = ClassIdSurrogate(value.packageFqName, value.relativeClassName, value.isLocal) + encoder.encodeSerializableValue(ClassIdSurrogate.serializer(), surrogate) + } +} + +@OptIn(ExperimentalSerializationApi::class) +object CallableIdSerializer : KSerializer { + override val descriptor: SerialDescriptor = CallableIdSurrogate.serializer().descriptor + + override fun deserialize(decoder: Decoder): CallableId { + val surrogate = decoder.decodeSerializableValue(CallableIdSurrogate.serializer()) + return CallableId(surrogate.packageName, surrogate.className, surrogate.callableName) + } + + override fun serialize(encoder: Encoder, value: CallableId) { + val surrogate = CallableIdSurrogate(value.packageName, value.className, value.callableName) + encoder.encodeSerializableValue(CallableIdSurrogate.serializer(), surrogate) + } +} + +/** + * @property name + * @property isSpecial + */ +@Serializable +private data class NameSurrogate( + val name: String, + val isSpecial: Boolean, +) + +/** + * @property packageFqName + * @property relativeClassName + * @property isLocal + */ +@Serializable +private data class ClassIdSurrogate( + val packageFqName: @Serializable(with = FqNameSerializer::class) FqName, + val relativeClassName: @Serializable(with = FqNameSerializer::class) FqName, + val isLocal: Boolean, +) + +/** + * @property packageName + * @property className + * @property callableName + */ +@Serializable +private data class CallableIdSurrogate( + val packageName: @Serializable(with = FqNameSerializer::class) FqName, + val className: @Serializable(with = FqNameSerializer::class) FqName?, + val callableName: @Serializable(with = NameSerializer::class) Name, +) diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/serialization/SerializationUtils.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/serialization/SerializationUtils.kt index cfdc764d..96a25005 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/serialization/SerializationUtils.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/analysis/serialization/SerializationUtils.kt @@ -1,20 +1,17 @@ package org.jetbrains.reflekt.plugin.analysis.serialization -import org.jetbrains.reflekt.plugin.analysis.models.SerializableIrType -import org.jetbrains.reflekt.plugin.analysis.models.SerializableIrTypeArgument -import org.jetbrains.reflekt.plugin.analysis.models.ir.LibraryArgumentsWithInstances -import org.jetbrains.reflekt.plugin.analysis.models.ir.SerializableLibraryArgumentsWithInstances - +import kotlinx.serialization.* +import kotlinx.serialization.protobuf.ProtoBuf import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.* -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull +import org.jetbrains.kotlin.ir.util.classId import org.jetbrains.kotlin.types.Variance - -import kotlinx.serialization.* -import kotlinx.serialization.protobuf.ProtoBuf +import org.jetbrains.reflekt.plugin.analysis.models.SerializableIrType +import org.jetbrains.reflekt.plugin.analysis.models.SerializableIrTypeArgument +import org.jetbrains.reflekt.plugin.analysis.models.ir.LibraryArgumentsWithInstances +import org.jetbrains.reflekt.plugin.analysis.models.ir.SerializableLibraryArgumentsWithInstances @Suppress("UnnecessaryOptInAnnotation") @OptIn(ExperimentalSerializationApi::class) @@ -36,9 +33,9 @@ object SerializationUtils { variance = Variance.INVARIANT, ) } - val fqName = typeOrNull?.classFqName?.asString() ?: error("Can not get class fq name for IrTypeProjection") + val classId = typeOrNull?.classOrNull?.owner?.classId ?: error("Can not get class fq name for IrTypeProjection") return SerializableIrTypeArgument( - fqName = fqName, + classId = classId, isStarProjection = false, variance = (this as IrTypeProjection).variance, ) @@ -51,12 +48,12 @@ object SerializationUtils { @OptIn(ObsoleteDescriptorBasedAPI::class) fun IrSimpleType.toSerializableIrType(): SerializableIrType { - val classifierFqName = this.classifier.descriptor.fqNameOrNull()?.asString() ?: error("Can not get class fq name for ClassifierDescriptor") - val arguments = this.arguments.map { it.toSerializableIrTypeArgument() } + val classifierClassId = this.classOrNull?.owner?.classId ?: error("Can not get class ID for type") + val arguments = arguments.map { it.toSerializableIrTypeArgument() } // TODO: should we serialize it? val abbreviation = null return SerializableIrType( - classifierFqName = classifierFqName, + classifierClassId = classifierClassId, nullability = nullability, arguments = arguments, // We use serialization only for functions signatures, they don't have annotations @@ -67,7 +64,7 @@ object SerializationUtils { } fun SerializableIrType.toIrType(pluginContext: IrPluginContext) = IrSimpleTypeBuilder().also { - it.classifier = pluginContext.referenceClass(FqName(classifierFqName)) + it.classifier = pluginContext.referenceClass(classifierClassId) it.nullability = this.nullability it.arguments = this.arguments.map { argument -> argument.toIrTypeArgument(pluginContext) } // TODO: should we deserialize it? @@ -80,9 +77,8 @@ object SerializationUtils { if (this.isStarProjection) { return IrStarProjectionImpl } - requireNotNull(this.fqName) { "Empty fqName for IrTypeProjection" } return IrSimpleTypeBuilder().also { - it.classifier = pluginContext.referenceClass(FqName(this.fqName)) + it.classifier = pluginContext.referenceClass(requireNotNull(this.classId) { "Empty classId for IrTypeProjection" }) }.buildTypeProjection() } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ReflektMetaFileGenerator.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ReflektMetaFileGenerator.kt index 16b4307d..29eff792 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ReflektMetaFileGenerator.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ReflektMetaFileGenerator.kt @@ -23,11 +23,11 @@ class ReflektMetaFileGenerator( private val messageCollector: MessageCollector? = null, ) : IrGenerationExtension { override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) { - val instancesFqNames = instancesAnalyzer.getInstancesFqNames() + val instancesFqNames = instancesAnalyzer.getInstancesIds() saveMetaData(reflektQueriesArguments, instancesFqNames) } - private fun saveMetaData(libraryArguments: LibraryArguments, instancesFqNames: IrInstancesFqNames) { + private fun saveMetaData(libraryArguments: LibraryArguments, instancesFqNames: IrInstancesIds) { messageCollector?.log("Save Reflekt meta data: ${reflektMetaFile.path}") reflektMetaFile.createNewFile() reflektMetaFile.writeBytes( @@ -37,5 +37,5 @@ class ReflektMetaFileGenerator( ) } - private fun IrInstancesAnalyzer.getInstancesFqNames() = IrInstancesFqNames.fromIrInstances(this.getIrInstances()) + private fun IrInstancesAnalyzer.getInstancesIds() = IrInstancesIds.fromIrInstances(this.getIrInstances()) } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/ReflektImplGenerator.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/ReflektImplGenerator.kt index ec9efd93..ba397ebf 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/ReflektImplGenerator.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/ReflektImplGenerator.kt @@ -12,7 +12,7 @@ import org.jetbrains.kotlin.ir.types.classFqName import org.jetbrains.kotlin.ir.types.isPrimitiveType import org.jetbrains.kotlin.ir.util.* import org.jetbrains.reflekt.ReflektClass -import org.jetbrains.reflekt.plugin.analysis.common.ReflektPackage +import org.jetbrains.reflekt.plugin.analysis.common.ReflektNames import org.jetbrains.reflekt.plugin.analysis.common.StorageClassNames import org.jetbrains.reflekt.plugin.analysis.models.ir.LibraryQueriesResults import org.jetbrains.reflekt.plugin.analysis.processor.toReflektVisibility @@ -32,7 +32,7 @@ import java.util.* * */ @Suppress("KDOC_NO_CLASS_BODY_PROPERTIES_IN_HEADER", "KDOC_EXTRA_PROPERTY") class ReflektImplGenerator(private val libraryQueriesResults: LibraryQueriesResults) : FileGenerator() { - override val packageName = ReflektPackage.PACKAGE_NAME + override val packageName = ReflektNames.PACKAGE_NAME override val fileName = "ReflektImpl" /** diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/Util.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/Util.kt index 605ea32d..9d6c7047 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/Util.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/Util.kt @@ -52,8 +52,11 @@ fun controlFlow( code: CodeBlock, template: String, vararg args: Any?): CodeBlock = - CodeBlock.builder().beginControlFlow(template, *args).add(code) - .endControlFlow().build() + CodeBlock.builder() + .beginControlFlow(template, *args) + .add(code) + .endControlFlow() + .build() /** * Wraps a [CodeBlock] in brackets. diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/ClassesOrObjectsGenerator.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/ClassesOrObjectsGenerator.kt index 44f928b3..6b69a1c7 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/ClassesOrObjectsGenerator.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/ClassesOrObjectsGenerator.kt @@ -54,7 +54,6 @@ abstract class ClassesOrObjectsGenerator(protected val uses: ClassOrObjectLibrar * * @param enclosingClassName * @param libraryQueriesResults stores entities that satisfy all Reflekt queries arguments (invokes) - * * @property typeName a fully-qualified class name * @property typeVariable a generic variable to parametrize functions in the generated class * @property returnParameter a type for casting the results (all found entities) to @@ -69,7 +68,6 @@ class ClassesGenerator(enclosingClassName: ClassName, libraryQueriesResults: Cla * * @param enclosingClassName * @param libraryQueriesResults stores entities that satisfy all Reflekt queries arguments (invokes) - * * @property typeName a fully-qualified class name * @property typeVariable a generic variable to parametrize functions in the generated class * @property returnParameter a type for casting the results (all found entities) to diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/FunctionsGenerator.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/FunctionsGenerator.kt index 999b904a..edf3f126 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/FunctionsGenerator.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/FunctionsGenerator.kt @@ -18,7 +18,6 @@ import kotlin.reflect.KFunction * @param enclosingClassName * @param libraryQueriesResults stores entities that satisfy all Reflekt queries arguments (invokes) * @param fileGenerator a generator that can generate new unique aliased imports for functions - * * @property typeName a fully-qualified class name * @property typeVariable a generic variable to parametrize functions in the generated class * @property returnParameter a type for casting the results (all found entities) to diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/HelperClassGenerator.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/HelperClassGenerator.kt index a77842c8..f5d33556 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/HelperClassGenerator.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/code/generator/models/HelperClassGenerator.kt @@ -6,6 +6,7 @@ import com.squareup.kotlinpoet.* import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import org.jetbrains.kotlin.ir.declarations.IrFunction import org.jetbrains.kotlin.ir.util.fqNameWhenAvailable +import org.jetbrains.kotlin.name.ClassId import org.jetbrains.reflekt.plugin.analysis.models.SignatureToAnnotations import org.jetbrains.reflekt.plugin.analysis.models.SupertypesToAnnotations import org.jetbrains.reflekt.plugin.analysis.models.ir.ClassOrObjectLibraryQueriesResults @@ -112,11 +113,11 @@ abstract class HelperClassGenerator : ClassGenerator() { * setOf("invokes[0]", "invokes[1]" ...) -> listOf({uses[0] with typeSuffix} as %T, {uses[1] with typeSuffix} as %T) * the right part of this option should be generated earlier and passed into this function as [rightPart] */ - fun getWhenOptionForSet(invokes: Set, rightPart: CodeBlock): CodeBlock { + fun getWhenOptionForSet(invokes: Set, rightPart: CodeBlock): CodeBlock { val setOfBlock = if (invokes.isEmpty()) { "emptySet()" } else { - "setOf(${invokes.joinToString(separator = ", ") { "\"$it\"" }})" + "setOf(${invokes.joinToString(separator = ", ") { "\"${it.asFqNameString()}\"" }})" } return getWhenOption(setOfBlock, rightPart) } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/BaseReflektIrTransformer.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/BaseReflektIrTransformer.kt index bb98e631..8fae5e6d 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/BaseReflektIrTransformer.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/BaseReflektIrTransformer.kt @@ -10,9 +10,7 @@ import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.util.fields -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.utils.addToStdlib.safeAs +import org.jetbrains.kotlin.name.* import org.jetbrains.reflekt.plugin.analysis.common.ReflektEntity import org.jetbrains.reflekt.plugin.analysis.common.StorageClassNames import org.jetbrains.reflekt.plugin.analysis.ir.isSubtypeOf @@ -61,7 +59,7 @@ abstract class BaseReflektIrTransformer( protected fun resultIrCall( moduleFragment: IrModuleFragment, invokeParts: BaseReflektInvokeParts, - resultValues: List, + resultValues: List, resultType: IrType, ): IrExpression = IrBuilderWithCurrentScope().run { require(resultType is IrSimpleType) { "resultType is not IrSimpleType" } @@ -70,7 +68,7 @@ abstract class BaseReflektIrTransformer( ?: throw ReflektGenerationException("Return type must have one type argument (e. g. List, Set)") val items = resultValues - .map { pluginContext.referenceClass(FqName(it)) ?: throw ReflektGenerationException("Failed to find class $it") } + .map { pluginContext.referenceClass(it) ?: throw ReflektGenerationException("Failed to find class $it") } .map { classSymbol -> when (invokeParts.entityType) { ReflektEntity.OBJECTS, ReflektEntity.CLASSES -> { @@ -95,7 +93,7 @@ abstract class BaseReflektIrTransformer( irCall( generationSymbols.reflektObjectConstructor, typeArguments = listOf( - itemType.safeAs() + (itemType as? IrSimpleType) ?.arguments ?.get(0) ?.typeOrNull, @@ -144,19 +142,19 @@ abstract class BaseReflektIrTransformer( messageCollector?.log("RES ARGS: ${itemType.arguments.map { (it as IrSimpleType).classFqName }}") messageCollector?.log("size of result values ${resultValues.size}") val items = resultValues.map { irFunctionInfo -> - val functionSymbol = pluginContext.referenceFunctions(FqName(irFunctionInfo.fqName)).firstOrNull { symbol -> + val functionSymbol = pluginContext.referenceFunctions(irFunctionInfo.callableId).firstOrNull { symbol -> symbol.owner.isSubtypeOf(itemType, pluginContext).also { messageCollector?.log("${symbol.owner.isSubtypeOf(itemType, pluginContext)}") } } messageCollector?.log("function symbol is $functionSymbol") functionSymbol ?: run { messageCollector?.log("function symbol is null") - throw ReflektGenerationException("Failed to find function ${irFunctionInfo.fqName} with signature ${itemType.toParameterizedType()}") + throw ReflektGenerationException("Failed to find function ${irFunctionInfo.callableId} with signature ${itemType.toParameterizedType()}") } irKFunction(itemType, functionSymbol).also { call -> - irFunctionInfo.receiverFqName?.let { + irFunctionInfo.callableId.classId?.let { if (irFunctionInfo.isObjectReceiver) { - val dispatchSymbol = pluginContext.referenceClass(FqName(irFunctionInfo.receiverFqName)) - ?: throw ReflektGenerationException("Failed to find receiver class ${irFunctionInfo.receiverFqName}") + val dispatchSymbol = pluginContext.referenceClass(it) + ?: throw ReflektGenerationException("Failed to find receiver class ${irFunctionInfo.callableId.classId}") call.dispatchReceiver = irGetObject(dispatchSymbol) } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/GenerationSymbols.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/GenerationSymbols.kt index f0715cfc..be1576bb 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/GenerationSymbols.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/GenerationSymbols.kt @@ -4,8 +4,7 @@ import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.jvm.functionByName import org.jetbrains.kotlin.ir.types.classOrNull import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.name.JvmNames +import org.jetbrains.kotlin.name.* import org.jetbrains.reflekt.plugin.analysis.common.* import org.jetbrains.reflekt.plugin.generation.common.* @@ -15,37 +14,46 @@ import org.jetbrains.reflekt.plugin.generation.common.* class GenerationSymbols(private val pluginContext: IrPluginContext) { private val irBuiltIns = pluginContext.irBuiltIns val anyConstructor = irBuiltIns.anyClass.constructors.single() - val jvmSyntheticConstructor = referenceConstructorsOrFail(JvmNames.JVM_SYNTHETIC_ANNOTATION_FQ_NAME).first() - val jvmFieldConstructor = referenceConstructorsOrFail(FqName("kotlin.jvm.JvmField")).first() - val listOf = referenceVarargCollectionFunction("kotlin.collections.listOf") - val mapGet = irBuiltIns.mapClass.owner.functions.first { it.name.asString() == "get" && it.valueParameters.size == 1 }.symbol - val setOf = referenceVarargCollectionFunction("kotlin.collections.setOf") - val hashMapClass = referenceTypeAliasOrFail("kotlin.collections.HashMap").owner.expandedType.classOrNull!! - val hashMapOf = referenceVarargCollectionFunction("kotlin.collections.hashMapOf") - val hashSetOf = referenceVarargCollectionFunction("kotlin.collections.hashSetOf") - private val hashSetClass = referenceTypeAliasOrFail("kotlin.collections.HashSet").owner.expandedType.classOrNull!! + val jvmSyntheticConstructor = referenceConstructorsOrFail(ClassId(StandardClassIds.BASE_JVM_PACKAGE, Name.identifier("JvmSynthetic"))).first() + val jvmFieldConstructor = referenceConstructorsOrFail(ClassId(StandardClassIds.BASE_JVM_PACKAGE, Name.identifier("JvmField"))).first() + val listOf = referenceVarargCollectionFunction("listOf") + val mapGet = irBuiltIns + .mapClass + .owner + .functions + .first { it.name.asString() == "get" && it.valueParameters.size == 1 } + .symbol + val setOf = referenceVarargCollectionFunction("setOf") + val hashMapClass = referenceTypeAliasOrFail(ClassId(StandardClassIds.BASE_COLLECTIONS_PACKAGE, Name.identifier("HashMap"))).owner.expandedType.classOrNull!! + val hashMapOf = referenceVarargCollectionFunction("hashMapOf") + val hashSetOf = referenceVarargCollectionFunction("hashSetOf") + private val hashSetClass = + referenceTypeAliasOrFail(ClassId(StandardClassIds.BASE_COLLECTIONS_PACKAGE, Name.identifier("HashSet"))).owner.expandedType.classOrNull!! val mutableSetAdd = irBuiltIns.mutableSetClass.functionByName("add") val hashSetConstructor = hashSetClass.constructors.first { it.owner.valueParameters.isEmpty() } - val pairClass = referenceClassOrFail("kotlin.Pair") - val to = checkNotNull(pluginContext.referenceFunctions(FqName("kotlin.to")).takeIf { it.isNotEmpty() }) { + val pairClass = referenceClassOrFail(ClassId(StandardClassIds.BASE_KOTLIN_PACKAGE, Name.identifier("Pair"))) + val to = checkNotNull( + pluginContext.referenceFunctions(CallableId(StandardClassIds.BASE_KOTLIN_PACKAGE, Name.identifier("to"))).takeIf { it.isNotEmpty() }, + ) { "Can't reference functions named ${"kotlin.to"}, Kotlin standard library or Reflekt DSL aren't available" }.first() - val reflektClassClass = referenceClassOrFail("${ReflektPackage.PACKAGE_NAME}.ReflektClass") - val reflektClassImplClass = referenceClassOrFail("${ReflektPackage.PACKAGE_NAME}.ReflektClassImpl") + val reflektClassClass = referenceClassOrFail(ReflektNames.REFLEKT_CLASS_CLASS_ID) + val reflektClassImplClass = referenceClassOrFail(ReflektNames.REFLEKT_CLASS_IMPL_CLASS_ID) val reflektClassImplConstructor = reflektClassImplClass.constructors.first() val reflektClassImplGetSealedSubclasses = reflektClassImplClass.getPropertyGetter("sealedSubclasses")!! val reflektClassImplGetSuperclasses = reflektClassImplClass.getPropertyGetter("superclasses")!! - val reflektObjectClass = referenceClassOrFail("${ReflektPackage.PACKAGE_NAME}.ReflektObject") + val reflektObjectClass = referenceClassOrFail(ReflektNames.REFLEKT_OBJECT_CLASS_ID) val reflektObjectConstructor = reflektObjectClass.constructors.first() - val reflektVisibilityClass = referenceClassOrFail("${ReflektPackage.PACKAGE_NAME}.ReflektVisibility") + val reflektVisibilityClass = referenceClassOrFail(ReflektNames.REFLEKT_VISIBILITY_CLASS_ID) - private fun referenceVarargCollectionFunction(fqName: String) = pluginContext.referenceFunctions(FqName(fqName)).firstOrNull { - val parameters = it.owner.valueParameters - parameters.size == 1 && parameters[0].isVararg - } ?: error("Can't reference function $fqName, Kotlin standard library or Reflekt DSL aren't available") + private fun referenceVarargCollectionFunction(shortName: String) = + pluginContext.referenceFunctions(CallableId(StandardClassIds.BASE_COLLECTIONS_PACKAGE, Name.identifier(shortName))).firstOrNull { + val parameters = it.owner.valueParameters + parameters.size == 1 && parameters[0].isVararg + } ?: error("Can't reference function $shortName, Kotlin standard library or Reflekt DSL aren't available") /** - * Generates IR for the Reflekt terminal function (toList/toSet/etc). + * Generates IR for the Reflekt terminal function ([toList]/[toSet]/etc). * * @param parts */ @@ -60,16 +68,16 @@ class GenerationSymbols(private val pluginContext: IrPluginContext) { } } - private fun referenceClassOrFail(fqNameString: String) = checkNotNull(pluginContext.referenceClass(FqName(fqNameString))) { - "Can't reference class $fqNameString, Kotlin standard library or Reflekt DSL aren't available" + private fun referenceClassOrFail(classID: ClassId) = checkNotNull(pluginContext.referenceClass(classID)) { + "Can't reference class $classID, Kotlin standard library or Reflekt DSL aren't available" } - private fun referenceTypeAliasOrFail(fqNameString: String) = checkNotNull(pluginContext.referenceTypeAlias(FqName(fqNameString))) { - "Can't reference class $fqNameString, Kotlin standard library or Reflekt DSL aren't available" + private fun referenceTypeAliasOrFail(classID: ClassId) = checkNotNull(pluginContext.referenceTypeAlias(classID)) { + "Can't reference class $classID, Kotlin standard library or Reflekt DSL aren't available" } - private fun referenceConstructorsOrFail(fqName: FqName) = - checkNotNull(pluginContext.referenceConstructors(fqName).takeIf { it.isNotEmpty() }) { - "Can't reference constructors of $fqName, Kotlin standard library or Reflekt DSL aren't available" + private fun referenceConstructorsOrFail(classID: ClassId) = + checkNotNull(pluginContext.referenceConstructors(classID).takeIf { it.isNotEmpty() }) { + "Can't reference constructors of $classID, Kotlin standard library or Reflekt DSL aren't available" } } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/IrBuilderExtension.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/IrBuilderExtension.kt index 504e732b..0cc9cb87 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/IrBuilderExtension.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/IrBuilderExtension.kt @@ -3,18 +3,16 @@ package org.jetbrains.reflekt.plugin.generation.ir import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.descriptors.Modality -import org.jetbrains.kotlin.ir.IrBuiltIns -import org.jetbrains.kotlin.ir.ObsoleteDescriptorBasedAPI +import org.jetbrains.kotlin.ir.* import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.declarations.IrClass import org.jetbrains.kotlin.ir.declarations.IrEnumEntry -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrFunctionAccessExpression +import org.jetbrains.kotlin.ir.expressions.* +import org.jetbrains.kotlin.ir.expressions.impl.* import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.symbols.impl.IrAnonymousInitializerSymbolImpl import org.jetbrains.kotlin.ir.types.* -import org.jetbrains.kotlin.ir.util.isObject -import org.jetbrains.kotlin.ir.util.kotlinFqName +import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.name.Name import org.jetbrains.reflekt.plugin.analysis.ir.makeTypeProjection import org.jetbrains.reflekt.plugin.analysis.processor.toReflektVisibility @@ -33,11 +31,16 @@ interface IrBuilderExtension { @OptIn(ObsoleteDescriptorBasedAPI::class) fun IrClass.contributeAnonymousInitializer(body: IrBlockBodyBuilder.() -> Unit) { - factory.createAnonymousInitializer(startOffset, endOffset, origin, IrAnonymousInitializerSymbolImpl(descriptor)).also { - it.parent = this - declarations += it - it.body = DeclarationIrBuilder(pluginContext, it.symbol, startOffset, endOffset).irBlockBody(startOffset, endOffset, body) - } + factory.createAnonymousInitializer(startOffset, endOffset, origin, IrAnonymousInitializerSymbolImpl(descriptor)) + .also { + it.parent = this + declarations += it + it.body = DeclarationIrBuilder(pluginContext, it.symbol, startOffset, endOffset).irBlockBody( + startOffset, + endOffset, + body + ) + } } fun IrBuilderWithScope.irCheckNotNull(value: IrExpression) = irCall( @@ -50,7 +53,12 @@ interface IrBuilderExtension { irCall(generationSymbols.mapGet, dispatchReceiver = map, valueArguments = listOf(key)) fun IrBuilderWithScope.irTo(left: IrExpression, right: IrExpression) = - irCall(generationSymbols.to, typeArguments = listOf(left.type, right.type), extensionReceiver = left, valueArguments = listOf(right)) + irCall( + generationSymbols.to, + typeArguments = listOf(left.type, right.type), + extensionReceiver = left, + valueArguments = listOf(right) + ) fun IrBuilderWithScope.irHashMapOf(keyType: IrType, valueType: IrType, pairs: List) = irCall( generationSymbols.hashMapOf, @@ -81,7 +89,11 @@ interface IrBuilderExtension { typeArguments = listOf(irBuiltIns.annotationType), valueArguments = listOf( irVarargOut(irBuiltIns.annotationType, - irClass.annotations.map { irCall(it.symbol, valueArguments = it.getValueArguments()) }), + irClass.annotations.map { + irCall( + it.symbol, + valueArguments = it.getValueArguments().map { arg -> arg?.shallowCopyUndefinedOffset() }) + }), ), ), irBoolean(irClass.modality == Modality.ABSTRACT), @@ -115,3 +127,64 @@ interface IrBuilderExtension { ) } } + +private fun IrExpression.shallowCopyUndefinedOffset(): IrExpression = + shallowCopyOrNullUndefinedOffset() + ?: error("Not a copyable expression: ${render()}") + +private fun IrConst.shallowCopyUndefinedOffset() = IrConstImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + type, + kind, + value +) + +private fun IrExpression.shallowCopyOrNullUndefinedOffset(): IrExpression? = + when (this) { + is IrConst<*> -> shallowCopyUndefinedOffset() + is IrGetEnumValue -> IrGetEnumValueImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + type, + symbol + ) + + is IrGetObjectValue -> IrGetObjectValueImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + type, + symbol + ) + + is IrGetValueImpl -> IrGetValueImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + type, + symbol, + origin + ) + + is IrErrorExpressionImpl -> IrErrorExpressionImpl( + UNDEFINED_OFFSET, + UNDEFINED_OFFSET, + type, + description + ) + + is IrConstructorCall -> IrConstructorCallImpl( + startOffset, + endOffset, + type, + symbol, + typeArgumentsCount, + constructorTypeArgumentsCount, + valueArgumentsCount, + origin, + source, + ).also { + it.copyTypeAndValueArgumentsFrom(this) + } + + else -> null + } diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/ReflektIrTransformer.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/ReflektIrTransformer.kt index b5f54367..0537631a 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/ReflektIrTransformer.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/ReflektIrTransformer.kt @@ -51,7 +51,7 @@ class ReflektIrTransformer( ReflektEntity.OBJECTS, ReflektEntity.CLASSES -> resultIrCall( currentFile.module, invokeParts, - filteredInstances.mapNotNull { (it as? IrClass)?.fqNameWhenAvailable?.asString() }, + filteredInstances.mapNotNull { (it as? IrClass)?.classId }, expression.type, ) ReflektEntity.FUNCTIONS -> functionResultIrCall( diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/SmartReflektIrTransformer.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/SmartReflektIrTransformer.kt index 75088fd3..b65ca30a 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/SmartReflektIrTransformer.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/SmartReflektIrTransformer.kt @@ -1,29 +1,26 @@ package org.jetbrains.reflekt.plugin.generation.ir -import org.jetbrains.reflekt.plugin.analysis.common.ReflektEntity -import org.jetbrains.reflekt.plugin.analysis.ir.* -import org.jetbrains.reflekt.plugin.analysis.models.* -import org.jetbrains.reflekt.plugin.analysis.models.ir.* -import org.jetbrains.reflekt.plugin.generation.common.SmartReflektInvokeParts -import org.jetbrains.reflekt.plugin.scripting.ImportChecker -import org.jetbrains.reflekt.plugin.scripting.KotlinScriptRunner -import org.jetbrains.reflekt.plugin.utils.Util.log -import org.jetbrains.reflekt.plugin.utils.Util.getJarBySystemPropertyName - import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.cli.common.messages.MessageCollector import org.jetbrains.kotlin.ir.IrElement +import org.jetbrains.kotlin.ir.PsiIrFileEntry import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrCall import org.jetbrains.kotlin.ir.expressions.IrExpression import org.jetbrains.kotlin.ir.types.IrType import org.jetbrains.kotlin.ir.util.* import org.jetbrains.kotlin.util.removeSuffixIfPresent -import org.jetbrains.kotlin.ir.PsiIrFileEntry +import org.jetbrains.reflekt.plugin.analysis.common.ReflektEntity +import org.jetbrains.reflekt.plugin.analysis.ir.* +import org.jetbrains.reflekt.plugin.analysis.models.* +import org.jetbrains.reflekt.plugin.analysis.models.ir.IrInstances +import org.jetbrains.reflekt.plugin.generation.common.SmartReflektInvokeParts +import org.jetbrains.reflekt.plugin.scripting.ImportChecker +import org.jetbrains.reflekt.plugin.scripting.KotlinScriptRunner import org.jetbrains.reflekt.plugin.utils.Util.KOTLIN_COMPILER_PROP - +import org.jetbrains.reflekt.plugin.utils.Util.getJarBySystemPropertyName +import org.jetbrains.reflekt.plugin.utils.Util.log import java.io.File - import kotlin.reflect.KClass /** @@ -73,7 +70,7 @@ class SmartReflektIrTransformer( resultIrCall( currentFile.module, invokeParts, - filteredInstances.mapNotNull { (it as? IrClass)?.fqNameWhenAvailable?.asString() }, + filteredInstances.mapNotNull { (it as? IrClass)?.classId }, expression.type, ) } @@ -119,11 +116,11 @@ class SmartReflektIrTransformer( } /** - * Check if instance [T] satisfies list of [filters] + * Check if instance [T] satisfies to a list of [filters] * * @param imports for KotlinScript running * @param filters - * @return {@code true} if instance [T] satisfies list of [filters] + * @return {@code true} if instance [T] satisfies to a list of [filters] */ // TODO: union filters and run KotlinScript one time private fun T.isEvaluatedFilterBody( @@ -158,7 +155,7 @@ class SmartReflektIrTransformer( } } - private fun IrFile.readText() = (this.fileEntry as PsiIrFileEntry).psiFile.text + private fun IrFile.readText(): String = (fileEntry as PsiIrFileEntry).psiFile.text!! /** * Construct [SourceFile] manually from [String] (extract imports and its content) diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/StorageClassGenerator.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/StorageClassGenerator.kt index 6aeaa8c5..6bbc5779 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/StorageClassGenerator.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/generation/ir/StorageClassGenerator.kt @@ -5,6 +5,7 @@ import org.jetbrains.kotlin.backend.common.lower.DeclarationIrBuilder import org.jetbrains.kotlin.backend.jvm.fieldByName import org.jetbrains.kotlin.descriptors.* import org.jetbrains.kotlin.descriptors.impl.EmptyPackageFragmentDescriptor +import org.jetbrains.kotlin.ir.UNDEFINED_OFFSET import org.jetbrains.kotlin.ir.builders.* import org.jetbrains.kotlin.ir.builders.declarations.* import org.jetbrains.kotlin.ir.declarations.* @@ -15,10 +16,9 @@ import org.jetbrains.kotlin.ir.symbols.IrFunctionSymbol import org.jetbrains.kotlin.ir.types.* import org.jetbrains.kotlin.ir.types.impl.makeTypeProjection import org.jetbrains.kotlin.ir.util.* -import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.types.Variance -import org.jetbrains.reflekt.plugin.analysis.common.ReflektPackage +import org.jetbrains.reflekt.plugin.analysis.common.ReflektNames import org.jetbrains.reflekt.plugin.analysis.common.StorageClassNames import org.jetbrains.reflekt.plugin.generation.ir.util.* import org.jetbrains.reflekt.plugin.utils.getImmediateSuperclasses @@ -36,12 +36,18 @@ class StorageClassGenerator(override val pluginContext: IrPluginContext) : IrBui private val mVariableName = Name.identifier("m") private fun syntheticFile(packageFragmentDescriptor: PackageFragmentDescriptor, name: String, module: IrModuleFragment): IrFile = - IrFileImpl(NaiveSourceBasedFileEntryImpl(name), packageFragmentDescriptor, module).also { module.files += it } + IrFileImpl(NaiveSourceBasedFileEntryImpl(name, maxOffset = UNDEFINED_OFFSET), packageFragmentDescriptor, module).also { + module.files += it + } fun createStorageClass(moduleFragment: IrModuleFragment): IrClassSymbol { // Names of storage class are chosen to avoid duplication. - val idx = generateSequence(0) { it + 1 }.first { pluginContext.referenceClass(FqName("${ReflektPackage.PACKAGE_NAME}.Storage_$it")) == null } - val file = syntheticFile(EmptyPackageFragmentDescriptor(moduleFragment.descriptor, ReflektPackage.PACKAGE_FQ_NAME), "Storage_$idx", moduleFragment) + val idx = generateSequence(0) { it + 1 }.first { pluginContext.referenceClass(StorageClassNames.getStorageClassId(it)) == null } + val file = syntheticFile( + EmptyPackageFragmentDescriptor(moduleFragment.descriptor, ReflektNames.PACKAGE_FQ_NAME), + StorageClassNames.getStorageClass(idx), + moduleFragment, + ) // Initially, storage class contains: // 1. thisReceiver and typical constructor @@ -49,7 +55,7 @@ class StorageClassGenerator(override val pluginContext: IrPluginContext) : IrBui return irFactory.buildClass { visibility = DescriptorVisibilities.INTERNAL kind = ClassKind.OBJECT - name = Name.identifier("Storage_$idx") + name = StorageClassNames.getStorageClassName(idx) }.also { irClass -> file.addChild(irClass) @@ -166,7 +172,7 @@ class StorageClassGenerator(override val pluginContext: IrPluginContext) : IrBui ) } - // Created HashMap is stored to the data field. + // Created HashMap is stored in the data field. +irSetField( irGet(storageClass.thisReceiver!!), storageClass.symbol.fieldByName(StorageClassNames.REFLEKT_CLASSES).owner, diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/scripting/KotlinScriptRunner.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/scripting/KotlinScriptRunner.kt index 53fc50dc..e8c6dd4a 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/scripting/KotlinScriptRunner.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/scripting/KotlinScriptRunner.kt @@ -23,7 +23,6 @@ typealias KotlinScriptProperties = List>> * e.g. for code properties can be listOf("a" to Array::class, "b" to String::class) * It means the KotlinScript expects Array for the variable and String for the variable * @param classpath the list of files that should be added into the KotlinScript classpath - * * @property argumentNames the list of names from the properties list * @property source the full Kotlin source file that should be run (imports + code fragment) * @property compilationConfiguration configuration that works with extended classpath and KotlinScript properties diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/utils/PluginConfig.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/utils/PluginConfig.kt index d48d14ad..e035abaf 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/utils/PluginConfig.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/utils/PluginConfig.kt @@ -13,7 +13,6 @@ import java.io.File * @param configuration the current Kotlin compiler configuration or null * @param logFilePath path to the file with logs. By default, it is pathToKotlin/daemon/reflekt-log.log * @param isTestConfiguration indicates if the plugin is used in tests - * * @property enabled indicates if the plugin is enabled * @property reflektMetaFilesFromLibraries stores the absolute file's path from the library with Reflekt meta information * @property outputDir stores a relative path for generated files (e.g. ReflektImpl.kt) diff --git a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/utils/Util.kt b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/utils/Util.kt index 43e4caba..0b69b0a8 100644 --- a/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/utils/Util.kt +++ b/reflekt-plugin/src/main/kotlin/org/jetbrains/reflekt/plugin/utils/Util.kt @@ -2,19 +2,30 @@ package org.jetbrains.reflekt.plugin.utils +import org.jetbrains.kotlin.backend.jvm.ir.parentClassId import org.jetbrains.kotlin.cli.common.CLIConfigurationKeys import org.jetbrains.kotlin.cli.common.messages.* import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.descriptors.DescriptorVisibilities -import org.jetbrains.kotlin.ir.declarations.IrClass +import org.jetbrains.kotlin.ir.declarations.* import org.jetbrains.kotlin.ir.expressions.IrMemberAccessExpression import org.jetbrains.kotlin.ir.symbols.IrClassSymbol import org.jetbrains.kotlin.ir.types.* +import org.jetbrains.kotlin.ir.util.getPackageFragment +import org.jetbrains.kotlin.name.CallableId import org.jetbrains.kotlin.types.checker.SimpleClassicTypeSystemContext.isStarProjection import org.jetbrains.reflekt.util.TypeStringRepresentationUtil import java.io.File import java.io.PrintStream +val IrMemberWithContainerSource.callableId: CallableId + get() { + val parentClassId = parentClassId + return parentClassId?.let { + CallableId(parentClassId, name) + } ?: CallableId(getPackageFragment().fqName, name) + } + /** * Common functions and constants for the plugin. * diff --git a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/providers/reflekt/ReflektPluginProviders.kt b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/providers/reflekt/ReflektPluginProviders.kt index 7971f519..60401034 100644 --- a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/providers/reflekt/ReflektPluginProviders.kt +++ b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/providers/reflekt/ReflektPluginProviders.kt @@ -3,6 +3,7 @@ package org.jetbrains.reflekt.plugin.compiler.providers.reflekt import com.intellij.mock.MockProject import com.intellij.openapi.project.Project import org.jetbrains.kotlin.backend.common.extensions.IrGenerationExtension +import org.jetbrains.kotlin.compiler.plugin.* import org.jetbrains.kotlin.config.CompilerConfiguration import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDumpHandler import org.jetbrains.kotlin.test.model.TestModule @@ -15,15 +16,18 @@ import org.jetbrains.reflekt.plugin.generation.code.generator.ReflektImplGenerat import org.jetbrains.reflekt.plugin.util.CodeGenTestPaths import java.io.File +@OptIn(ExperimentalCompilerApi::class) class ReflektPluginWithStandaloneProjectProvider(testServices: TestServices) : ReflektPluginProviderBase(testServices) { - override fun registerCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) { - ReflektComponentRegistrar(true).registerProjectComponents(project as MockProject, configuration) + override fun CompilerPluginRegistrar.ExtensionStorage.registerCompilerExtensions(module: TestModule, configuration: CompilerConfiguration) { + with(ReflektComponentRegistrar(true)) { + this@registerCompilerExtensions.registerExtensions(configuration) + } } } // Provider only for tests to generate ReflektImpl file (without parsing ReflektMeta file) class ReflektPluginWithLibraryProvider(testServices: TestServices) : ReflektPluginProviderBase(testServices) { - override fun registerCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) { + override fun legacyRegisterCompilerExtensions(project: Project, module: TestModule, configuration: CompilerConfiguration) { val instancesAnalyzer = IrInstancesAnalyzer() val libraryArgumentsWithInstances = LibraryArgumentsWithInstances() diff --git a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/runners/base/AbstractTest.kt b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/runners/base/AbstractTest.kt index f34e9506..d81d75d5 100644 --- a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/runners/base/AbstractTest.kt +++ b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/runners/base/AbstractTest.kt @@ -19,7 +19,7 @@ import org.jetbrains.kotlin.test.frontend.classic.handlers.DiagnosticMessagesTex import org.jetbrains.kotlin.test.model.DependencyKind import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.runners.RunnerWithTargetBackendForTestGeneratorMarker -import org.jetbrains.kotlin.test.runners.codegen.commonConfigurationForCodegenTest +import org.jetbrains.kotlin.test.runners.codegen.commonConfigurationForTest abstract class AbstractTest : BaseTestRunner(), RunnerWithTargetBackendForTestGeneratorMarker { override val targetBackend: TargetBackend @@ -32,7 +32,7 @@ abstract class AbstractTest : BaseTestRunner(), RunnerWithTargetBackendForTestGe } fun TestConfigurationBuilder.baseOldFrontEndIrBackEndBoxConfiguration() { - commonConfigurationForCodegenTest( + commonConfigurationForTest( FrontendKinds.ClassicFrontend, ::ClassicFrontendFacade, ::ClassicFrontend2IrConverter, diff --git a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/runners/base/BaseTestRunner.kt b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/runners/base/BaseTestRunner.kt index dc03c188..67863fa1 100644 --- a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/runners/base/BaseTestRunner.kt +++ b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/runners/base/BaseTestRunner.kt @@ -15,7 +15,5 @@ abstract class BaseTestRunner : AbstractKotlinCompilerTest() { } } - override fun createKotlinStandardLibrariesPathProvider(): KotlinStandardLibrariesPathProvider { - return EnvironmentBasedStandardLibrariesPathProvider - } + override fun createKotlinStandardLibrariesPathProvider(): KotlinStandardLibrariesPathProvider = EnvironmentBasedStandardLibrariesPathProvider } diff --git a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/util/CompilationUtil.kt b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/util/CompilationUtil.kt index e8c30e25..cf360c5c 100644 --- a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/util/CompilationUtil.kt +++ b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/util/CompilationUtil.kt @@ -5,13 +5,12 @@ import org.jetbrains.kotlin.incremental.makeIncrementally import org.jetbrains.reflekt.plugin.utils.Util import java.io.File -internal fun createCompilerArguments(destinationDir: File, testDir: File, compilerClasspath: List = emptyList()): K2JVMCompilerArguments { - return K2JVMCompilerArguments().apply { +internal fun createCompilerArguments(destinationDir: File, testDir: File, compilerClasspath: List = emptyList()): K2JVMCompilerArguments = + K2JVMCompilerArguments().apply { moduleName = testDir.name destination = destinationDir.path classpath = compilerClasspath.joinToString(File.pathSeparator) { it.absolutePath } } -} // This function does not take into account java sources internal fun compile(cacheDir: File, sourceRoots: Iterable, args: K2JVMCompilerArguments): TestCompilationResult { @@ -23,6 +22,5 @@ internal fun compile(cacheDir: File, sourceRoots: Iterable, args: K2JVMCom internal fun compileSources(cacheDir: File, sources: List, compilerArgs: K2JVMCompilerArguments, errorMessagePrefix: String) { val (_, errors) = compile(cacheDir, sources, compilerArgs) - check(errors.isEmpty()) { "$errorMessagePrefix build failed: \n${errors.joinToString("\n")}" } + check(errors.isEmpty()) { "$errorMessagePrefix build failed:\n${errors.joinToString("\n")}" } } - diff --git a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/util/TestICReporter.kt b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/util/TestICReporter.kt index f723615a..848468b3 100644 --- a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/util/TestICReporter.kt +++ b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/compiler/util/TestICReporter.kt @@ -1,5 +1,6 @@ package org.jetbrains.reflekt.plugin.compiler.util +import org.jetbrains.kotlin.build.report.ICReporter import org.jetbrains.kotlin.build.report.ICReporterBase import org.jetbrains.kotlin.cli.common.ExitCode import java.io.File @@ -8,15 +9,11 @@ class TestICReporter(private val isVerbose: Boolean = false) : ICReporterBase() var exitCode: ExitCode = ExitCode.OK private set - val icLogLines = arrayListOf() + val icLogLines = ArrayList() - override fun report(message: () -> String) { - icLogLines.add(message()) - } - - override fun reportVerbose(message: () -> String) { - if (isVerbose) { - report(message) + override fun report(message: () -> String, severity: ICReporter.ReportSeverity) { + if (isVerbose || severity.level >= ICReporter.ReportSeverity.INFO.level) { + icLogLines.add(message()) } } diff --git a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/scripting/KotlinScriptRunnerTest.kt b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/scripting/KotlinScriptRunnerTest.kt index 191fd7aa..ce0593ad 100644 --- a/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/scripting/KotlinScriptRunnerTest.kt +++ b/reflekt-plugin/src/test/kotlin/org/jetbrains/reflekt/plugin/scripting/KotlinScriptRunnerTest.kt @@ -55,15 +55,4 @@ class KotlinScriptRunnerTest { ).eval(listOf("hello")), ) } - - companion object { - // Equals private val with same name from org.jetbrains.kotlin.scripting.compiler.plugin.impl - private const val SCRIPT_COMPILATION_DISABLE_PLUGINS_PROPERTY = "script.compilation.disable.plugins" - - @BeforeAll - @JvmStatic - fun disableCompilerTestingPlugin() { - System.setProperty(SCRIPT_COMPILATION_DISABLE_PLUGINS_PROPERTY, "com.tschuchort.compiletesting.MainComponentRegistrar") - } - } } diff --git a/settings.gradle.kts b/settings.gradle.kts index c3e8438d..58a85963 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -13,14 +13,11 @@ pluginManagement { repositories { mavenCentral() gradlePluginPortal() - maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") // Uncomment it for using the last kotlin compiler version // The full list of the build can be found here: // https://teamcity.jetbrains.com/buildConfiguration/Kotlin_KotlinPublic_BuildNumber?mode=builds&tag=bootstrap // (see builds with tag) // Note: uncomment it also in the build.gradle.kts - // maven { - // url = uri("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") - // } + // maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/bootstrap") } }