diff options
author | Colin Cross <ccross@android.com> | 2023-08-09 18:32:29 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-08-09 18:32:29 +0000 |
commit | 7adc4f925ee5c07558a8aba474f67af73bf0f817 (patch) | |
tree | 688d00f78a787b2ae907434df2d1c182f03bbe47 | |
parent | b0b113ceee6c177a45db702a34e421ed39e7ff96 (diff) | |
parent | 66d56503510e5538acf26becafa56d9c6f941768 (diff) | |
download | kotlinpoet-7adc4f925ee5c07558a8aba474f67af73bf0f817.tar.gz |
Upgrade kotlinpoet to 7ba293ecb6af9f66de19c689c4b69d8a3e20745e am: 72666fe64b am: a9a0ac38f4 am: 5b07fe9b7f am: 66d5650351
Original change: https://android-review.googlesource.com/c/platform/external/kotlinpoet/+/2677958
Change-Id: I04d171f5e36f1e49c902be115f1a8ca97cfd5943
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
95 files changed, 2857 insertions, 1766 deletions
diff --git a/.editorconfig b/.editorconfig index 3ac56613..f69b685d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -10,3 +10,4 @@ insert_final_newline = true ij_kotlin_imports_layout = * ij_kotlin_allow_trailing_comma = true ij_kotlin_allow_trailing_comma_on_call_site = true +ij_kotlin_name_count_to_use_star_import = 99999
\ No newline at end of file diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 46c31895..b9ff4be9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,6 +1,12 @@ name: Build -on: [push, pull_request] +on: + push: + branches-ignore: + - main + tags-ignore: + - '**' + pull_request: env: GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false -Dkotlin.incremental=false" @@ -20,14 +26,14 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 18 + java-version: 19 - name: Test run: ./gradlew build build-docs: runs-on: ubuntu-latest - if: github.repository == 'square/kotlinpoet' && github.ref != 'refs/heads/master' + if: github.repository == 'square/kotlinpoet' steps: - name: Checkout @@ -37,7 +43,7 @@ jobs: uses: actions/setup-java@v3 with: distribution: 'zulu' - java-version: 18 + java-version: 19 - name: Prep docs run: ./gradlew dokkaHtml @@ -51,47 +57,3 @@ jobs: run: | pip3 install -r .github/workflows/mkdocs-requirements.txt mkdocs build - - publish: - runs-on: ubuntu-latest - if: github.repository == 'square/kotlinpoet' && github.ref == 'refs/heads/master' - needs: - - jvm - - steps: - - name: Checkout - uses: actions/checkout@v3 - - - name: Configure JDK - uses: actions/setup-java@v3 - with: - distribution: 'zulu' - java-version: 18 - - - name: Upload Artifacts - run: ./gradlew publish - env: - ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_NEXUS_USERNAME }} - ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} - - - name: Prep docs - run: ./gradlew dokkaHtml - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: 3.8 - - - name: Build mkdocs - run: | - pip3 install -r .github/workflows/mkdocs-requirements.txt - mkdocs build - - - name: Deploy 🚀 - if: success() && github.ref == 'refs/heads/master' - uses: JamesIves/github-pages-deploy-action@releases/v3 - with: - GITHUB_TOKEN: ${{ secrets.PERSONAL_TOKEN }} - BRANCH: gh-pages # The branch the action should deploy to. - FOLDER: site # The folder the action should deploy. - SINGLE_COMMIT: true diff --git a/.github/workflows/mkdocs-requirements.txt b/.github/workflows/mkdocs-requirements.txt index 67c640f2..cb9f0930 100644 --- a/.github/workflows/mkdocs-requirements.txt +++ b/.github/workflows/mkdocs-requirements.txt @@ -1,19 +1,19 @@ -click==8.1.3 +click==8.1.6 future==0.18.3 Jinja2==3.1.2 livereload==2.6.3 lunr==0.6.2 Markdown==3.3.7 # See https://github.com/mkdocs/mkdocs/issues/2892. -MarkupSafe==2.1.2 -mkdocs==1.4.2 -mkdocs-macros-plugin==0.7.0 -mkdocs-material==9.0.9 +MarkupSafe==2.1.3 +mkdocs==1.4.3 +mkdocs-macros-plugin==1.0.2 +mkdocs-material==9.1.19 mkdocs-material-extensions==1.1.1 -Pygments==2.14.0 -pymdown-extensions==9.9.2 +Pygments==2.15.1 +pymdown-extensions==10.1 python-dateutil==2.8.2 -PyYAML==6.0 +PyYAML==6.0.1 repackage==0.7.3 six==1.16.0 -termcolor==2.2.0 -tornado==6.2 +termcolor==2.3.0 +tornado==6.3.2 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..fe264dea --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,55 @@ +name: Release + +on: + push: + branches: + - main + tags: + - '**' + +env: + GRADLE_OPTS: "-Dorg.gradle.jvmargs=-Xmx4g -Dorg.gradle.daemon=false -Dkotlin.incremental=false" + +jobs: + publish: + runs-on: ubuntu-latest + if: github.repository == 'square/kotlinpoet' + + steps: + - name: Checkout + uses: actions/checkout@v3 + + - name: Configure JDK + uses: actions/setup-java@v3 + with: + distribution: 'zulu' + java-version: 19 + + - name: Upload Artifacts + run: ./gradlew publish + env: + ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.SONATYPE_NEXUS_USERNAME }} + ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.SONATYPE_NEXUS_PASSWORD }} + ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.ARTIFACT_SIGNING_PRIVATE_KEY }} + + - name: Prep docs + run: ./gradlew dokkaHtml + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + + - name: Build mkdocs + run: | + pip3 install -r .github/workflows/mkdocs-requirements.txt + mkdocs build + + - name: Deploy 🚀 + if: success() + uses: JamesIves/github-pages-deploy-action@releases/v3 + with: + GITHUB_TOKEN: ${{ secrets.PERSONAL_TOKEN }} + BRANCH: gh-pages # The branch the action should deploy to. + FOLDER: site # The folder the action should deploy. + SINGLE_COMMIT: true @@ -16,6 +16,7 @@ license { java_library_host { name: "kotlinpoet", srcs: ["kotlinpoet/src/main/**/*.kt"], + kotlincflags: ["-Xjvm-default=all"], static_libs: [ "kotlin-stdlib-jdk8", "kotlin-reflect", @@ -25,6 +26,7 @@ java_library_host { java_library_host { name: "kotlinpoet-javapoet", srcs: ["interop/javapoet/src/main/**/*.kt"], + kotlincflags: ["-Xjvm-default=all"], static_libs: [ "javapoet", "kotlin-stdlib-jdk8", @@ -1,7 +1,9 @@ -name: "kotlinpoet" -description: - "A Kotlin API for generating .kt source files" +# This project was upgraded with external_updater. +# Usage: tools/external_updater/updater.sh update kotlinpoet +# For more info, check https://cs.android.com/android/platform/superproject/+/master:tools/external_updater/README.md +name: "kotlinpoet" +description: "A Kotlin API for generating .kt source files" third_party { url { type: HOMEPAGE @@ -11,7 +13,11 @@ third_party { type: GIT value: "https://github.com/square/kotlinpoet.git" } - version: "c99ed244c6e4c7f8594f75566bb19ec62fa9c80d" - last_upgrade_date { year: 2023 month: 1 day: 31 } + version: "7ba293ecb6af9f66de19c689c4b69d8a3e20745e" license_type: NOTICE + last_upgrade_date { + year: 2023 + month: 7 + day: 26 + } } diff --git a/RELEASING.md b/RELEASING.md index f987b6eb..418d9523 100644 --- a/RELEASING.md +++ b/RELEASING.md @@ -4,23 +4,10 @@ Releasing 1. Change the version in `gradle.properties` to a non-SNAPSHOT version. 2. Update `docs/changelog.md` for the impending release. 3. `git commit -am "Prepare for release X.Y.Z."` (where X.Y.Z is the new version) - 4. `./gradlew clean publish --no-daemon --no-parallel`. - 5. Visit [Sonatype Nexus][sonatype] and ensure there's only one staging repository. - 6. `./gradlew closeAndReleaseRepository`. - 7. `git tag -a X.Y.Z -m "Version X.Y.Z"` (where X.Y.Z is the new version). - 8. Update `gradle.properties` to the next SNAPSHOT version. - 9. `git commit -am "Prepare next development version."`. - 10. `git push && git push --tags`. + 4. `git tag -a X.Y.Z -m "Version X.Y.Z"` (where X.Y.Z is the new version). + 5. Update `gradle.properties` to the next SNAPSHOT version. + 6. `git commit -am "Prepare next development version."`. + 7. `git push && git push --tags`. -If steps 5-6 fail, drop the Sonatype repo, fix the problem, commit, and start again at step 4. - - -Prerequisites -------------- - -In `~/.gradle/gradle.properties`, set the following: - - * `ORG_GRADLE_PROJECT_mavenCentralUsername` - Sonatype username for releasing to `com.squareup`. - * `ORG_GRADLE_PROJECT_mavenCentralPassword` - Sonatype password for releasing to `com.squareup`. - - [sonatype]: https://s01.oss.sonatype.org/ +This will trigger a GitHub Action workflow which will create a GitHub release and upload the +release artifacts to Maven Central. diff --git a/build.gradle.kts b/build.gradle.kts index 421de38b..35223751 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -14,7 +14,9 @@ * limitations under the License. */ import com.diffplug.gradle.spotless.SpotlessExtension +import org.gradle.api.tasks.testing.logging.TestExceptionFormat import org.jetbrains.dokka.gradle.DokkaTask +import org.jetbrains.kotlin.gradle.dsl.JvmTarget import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension import org.jetbrains.kotlin.gradle.tasks.KotlinCompile @@ -28,7 +30,10 @@ plugins { } allprojects { - group = property("GROUP") as String + // Note that the group name for publishing is "com.squareup" and is declared in gradle.properties. It's set to a + // different value here to disambiguate the Maven coordinates of the :interop:javapoet submodule and the JavaPoet + // dependency. + group = "com.squareup.kotlinpoet" version = property("VERSION_NAME") as String repositories { @@ -38,14 +43,14 @@ allprojects { subprojects { tasks.withType<KotlinCompile> { - kotlinOptions { - freeCompilerArgs += listOf("-opt-in=kotlin.RequiresOptIn") + compilerOptions { + jvmTarget.set(JvmTarget.JVM_1_8) + freeCompilerArgs.add("-Xjvm-default=all") } } // Ensure "org.gradle.jvm.version" is set to "8" in Gradle metadata. tasks.withType<JavaCompile> { - sourceCompatibility = JavaVersion.VERSION_1_8.toString() - targetCompatibility = JavaVersion.VERSION_1_8.toString() + options.release.set(8) } apply(plugin = "org.jetbrains.kotlin.jvm") @@ -98,31 +103,35 @@ subprojects { } } - // Copied from https://github.com/square/retrofit/blob/master/retrofit/build.gradle#L28. - // Create a test task for each supported JDK. - for (majorVersion in 8..18) { - // Adoptium JDK 9 cannot extract on Linux or Mac OS. - if (majorVersion == 9) continue - // Started causing build failures in late 2022, e.g.: - // https://github.com/square/kotlinpoet/actions/runs/3816320722/jobs/6531532305. - if (majorVersion == 10) continue + // Only enable the extra toolchain tests on CI. Otherwise local development is broken on Apple Silicon macs + // because there are no matching toolchains for several older JDK versions. + if ("CI" in System.getenv()) { + // Copied from https://github.com/square/retrofit/blob/master/retrofit/build.gradle#L28. + // Create a test task for each supported JDK. We check every "LTS" + current version. + val versionsToTest = listOf(8, 11, 17, 19) + for (majorVersion in versionsToTest) { + val jdkTest = tasks.register<Test>("testJdk$majorVersion") { + val javaToolchains = project.extensions.getByType(JavaToolchainService::class) + javaLauncher.set(javaToolchains.launcherFor { + languageVersion.set(JavaLanguageVersion.of(majorVersion)) + vendor.set(JvmVendorSpec.AZUL) + }) - val jdkTest = tasks.register<Test>("testJdk$majorVersion") { - val javaToolchains = project.extensions.getByType(JavaToolchainService::class) - javaLauncher.set(javaToolchains.launcherFor { - languageVersion.set(JavaLanguageVersion.of(majorVersion)) - }) + description = "Runs the test suite on JDK $majorVersion" + group = LifecycleBasePlugin.VERIFICATION_GROUP - description = "Runs the test suite on JDK $majorVersion" - group = LifecycleBasePlugin.VERIFICATION_GROUP + // Copy inputs from normal Test task. + val testTask = tasks.getByName<Test>("test") + classpath = testTask.classpath + testClassesDirs = testTask.testClassesDirs - // Copy inputs from normal Test task. - val testTask = tasks.getByName<Test>("test") - classpath = testTask.classpath - testClassesDirs = testTask.testClassesDirs - } - tasks.named("check").configure { - dependsOn(jdkTest) + testLogging { + exceptionFormat = TestExceptionFormat.FULL + } + } + tasks.named("check").configure { + dependsOn(jdkTest) + } } } } diff --git a/docs/changelog.md b/docs/changelog.md index 05680e65..108d8e0b 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,6 +1,124 @@ Change Log ========== +## Unreleased + +## Version 1.14.2 + +_2023-05-30_ + + * Fix: Fix one more missing API in binary compatibility override in `Annotatable.Builder` (#1581). + +## Version 1.14.1 + +_2023-05-29_ + + * Fix: Restore ABI stability for annotatable and documentable builders (#1580). + +## Version 1.14.0 + +_2023-05-29_ + +Thanks to [@Omico][Omico], [@drawers][drawers], [@RBusarow][RBusarow] for contributing to this release. + + * New: Kotlin 1.8.21. + * New: KSP 1.8.21-1.0.11. + * New: Enable default methods in Java bytecode (#1561). + * New: Group Kotlin and Renovate updates together in Renovate (#1562). + * New: Extract trait interface for annotatable constructs and their builders (#1564). + * New: Extract trait interface for documentable constructs and their builders (#1571). + * New: Document the usage of `STAR` (#1572). + * New: Add builder for `FunSpec` which accepts a `MemberName` (#1574). + * Fix: Omit public modifier on override function or constructor parameters (#1550). + * Fix: Correct handling of members in various types (#1558). + * Fix: Function return types now default to `Unit` unless explicitly set (#1559). + + Previously, when `FunSpec` didn't have a return type specified and an expression body was produced, no return + type would be emitted. However, starting from `1.14.0`, KotlinPoet will not add `Unit` as a return type in such + cases. In order to correct the generated output, you are to specify the actual return type of the `FunSpec`. + + Before `1.14.0`, if omitted, no return type is produced: + ```kotlin + val funSpec = FunSpec.builder("foo") + .addStatement("return 1") + .build() + ``` + ```kotlin + public fun foo() = 1 + ``` + + From `1.14.0`, the return type defaults to `Unit` if not otherwise set: + ```kotlin + val funSpec = FunSpec.builder("foo") + .addStatement("return 1") + .build() + ``` + ```kotlin + public fun foo(): Unit = 1 // ❌ + ``` + + To fix it, explicitly define the return type: + ```diff + val funSpec = FunSpec.builder("foo") + + .returns(INT) + .addStatement("return 1") + .build() + ``` + ```kotlin + public fun foo(): Int = 1 // ✅ + ``` + + Additionally, as part of this change, `FunSpec.returnType` has changed to be non-nullable. This is a source- and + binary-compatible change, although if you were performing null-checks then new warnings may appear after upgrade. + + * Fix: Append nested class names to alias during name lookup (#1568). + * Fix: Allow PropertySpec with context receivers and without getter or setter (#1575). + +## Version 1.13.2 + +_2023-05-05_ + +Thanks to [@Squiry][Squiry] for contributing to this release. + +* Fix: `KSType.toTypeName` fixed to work with aliased types (#1534). + +## Version 1.13.1 + +_2023-04-28_ + +Thanks to [@rickclephas][rickclephas] for contributing to this release. + + * Fix: Look at canonical names instead of just package names when generating import aliases (#1519). + * Fix: Ignore KSP annotation arguments without a value (#1523). + * Fix: Fix arguments handling in `KSType.toTypeName()` (#1529). + +## Version 1.13.0 + +_2023-04-06_ + +Thanks to [@popematt][popematt], [@bitPogo][bitPogo], [@mars885][mars885], [@sjudd][sjudd], [@Sironheart][Sironheart], +[@polarene][polarene], [@DeoTimeTheGithubUser][DeoTimeTheGithubUser], [@drawers][drawers] for contributing to this release. + + * New: Kotlin 1.8.0. + * New: KSP 1.8.0-1.0.9. + * New: Support context receivers on TypeSpecs + extract ContextReceivable API (#1269). + * New: Optimize `OriginatingElements` and `TagMap` implementations (#1270). + * New: Auto-generate import aliases for types and members (#1355). + * New: Insert underscores into large decimal literals (#1384). + * New: New factory function `FileSpec.builder(ClassName)` (#1397). + * Fix: Fix StackOverflowError when calling `KSTypeArgument.toTypeName()` for a wildcard in a recursive type bound (#1272). + * Fix: Fix transitive aliases (#1306). + * Fix: Fix Aliases as TypeArgument (#1321). + * Fix: Don't escape special characters inside raw strings (#1331). + * Fix: Fix KSP interop's output of the annotation parameter value of type Char (#1338). + * Fix: Fix KSP interop's output for primitive arrays (#1340). + * Fix: Avoid emitting public if `shouldEmitPublicModifier` returns false (#1342). + * Fix: Fix context receivers being rendered in an incorrect position when on a nullable/suspending `LambdaTypeName` (#1454). + * Fix: Do not use `bestGuess` for `KClass.asClassName` (#1469). + * Fix: Handle fake nested types with platform mapped parents (#1472). + * Fix: Fix `TypeName` equals (#1477). + * Fix: Make equals consistent with compareTo for `ClassName` (#1506). + ## Version 1.12.0 _2022-06-13_ @@ -586,3 +704,15 @@ _2017-05-16_ [aksh1618]: https://github.com/aksh1618 [zsqw123]: https://github.com/zsqw123 [roihershberg]: https://github.com/roihershberg + [popematt]: https://github.com/popematt + [bitPogo]: https://github.com/bitPogo + [mars885]: https://github.com/mars885 + [sjudd]: https://github.com/sjudd + [Sironheart]: https://github.com/Sironheart + [polarene]: https://github.com/polarene + [DeoTimeTheGithubUser]: https://github.com/DeoTimeTheGithubUser + [drawers]: https://github.com/drawers + [rickclephas]: https://github.com/rickclephas + [Squiry]: https://github.com/Squiry + [Omico]: https://github.com/Omico + [RBusarow]: https://github.com/RBusarow diff --git a/docs/index.md b/docs/index.md index 4b8ec1a1..683f40e6 100644 --- a/docs/index.md +++ b/docs/index.md @@ -81,7 +81,7 @@ take advantage of Kotlin's multiline strings to make this look nice: val main = FunSpec.builder("main") .addCode(""" |var total = 0 - |for (i in 0 until 10) { + |for (i in 0..<10) { | total += i |} |""".trimMargin()) @@ -93,7 +93,7 @@ Which generates this: ```kotlin fun main() { var total = 0 - for (i in 0 until 10) { + for (i in 0..<10) { total += i } } @@ -104,7 +104,7 @@ There are additional APIs to assist with newlines, braces and indentation: ```kotlin val main = FunSpec.builder("main") .addStatement("var total = 0") - .beginControlFlow("for (i in 0 until 10)") + .beginControlFlow("for (i in 0..<10)") .addStatement("total += i") .endControlFlow() .build() @@ -118,7 +118,7 @@ private fun computeRange(name: String, from: Int, to: Int, op: String): FunSpec return FunSpec.builder(name) .returns(Int::class) .addStatement("var result = 1") - .beginControlFlow("for (i in $from until $to)") + .beginControlFlow("for (i in $from..<$to)") .addStatement("result = result $op i") .endControlFlow() .addStatement("return result") @@ -131,7 +131,7 @@ And here's what we get when we call `computeRange("multiply10to20", 10, 20, "*") ```kotlin fun multiply10to20(): kotlin.Int { var result = 1 - for (i in 10 until 20) { + for (i in 10..<20) { result = result * i } return result @@ -315,6 +315,7 @@ KotlinPoet has classes for building each of these: ```kotlin import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy +import com.squareup.kotlinpoet.STAR val hoverboard = ClassName("com.mattel", "Hoverboard") val list = ClassName("kotlin.collections", "List") @@ -339,8 +340,15 @@ val printThings = FunSpec.builder("printThings") .addParameter("things", producerArrayOfThings) .addStatement("println(things)") .build() + +val printKClass = FunSpec.builder("printKClass") + .addParameter("kClass", KClass::class.asClassName().parameterizedBy(STAR)) + .addStatement("println(kClass)") + .build() ``` +The `STAR` is represented as `*` in KotlinPoet. You can find more in the [KDoc][kdoc]. + KotlinPoet will decompose each type and import its components where possible. ```kotlin @@ -351,6 +359,7 @@ import com.misc.Thing import kotlin.Array import kotlin.collections.ArrayList import kotlin.collections.List +import kotlin.reflect.KClass class HelloWorld { fun beyond(): List<Hoverboard> { @@ -364,6 +373,10 @@ class HelloWorld { fun printThings(things: Array<out Thing>) { println(things) } + + fun printKClass(kClass: KClass<*>) { + println(kClass) + } } ``` @@ -599,7 +612,7 @@ private fun computeRange(name: String, from: Int, to: Int, op: String): FunSpec return FunSpec.builder(name) .returns(Int::class) .addStatement("var result = 0") - .beginControlFlow("for (i in %L until %L)", from, to) + .beginControlFlow("for (i in %L..<%L)", from, to) .addStatement("result = result %L i", op) .endControlFlow() .addStatement("return result") @@ -782,6 +795,29 @@ fun foo() = (100..10000).map { number -> number * number }.map { number -> The code is now correct and will compile properly. It still doesn't look perfect - you can play with replacing other spaces in the code block with `·` symbols to achieve better formatting. +Another common use case where you'd want to ensure spaces don't wrap is when emitting string literals: + +```kotlin +CodeBlock.of("""println("Class: $className")""") +``` + +If `$className` is long, KotlinPoet may wrap the space that precedes it, resulting in broken output: + +```kotlin +println("Class: +very.long.class.name.Here") +``` + +KotlinPoet doesn't know that `"Class: $className"` is, in fact, a string literal, and that the space inside of it +should never be wrapped. To make sure this case is handled correctly, use the `%S` modifier (as described in +[%S for Strings](#s-for-strings)): + +```kotlin +CodeBlock.of("""println(%S)""", "Class: $className") +``` + +Now the library knows it's dealing with a string literal and can use appropriate line-wrapping rules. + ### Constructors `FunSpec` is a slight misnomer; it can also be used for constructors: diff --git a/gradle.properties b/gradle.properties index f0543f01..dc6f7256 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ org.gradle.jvmargs='-Dfile.encoding=UTF-8' GROUP=com.squareup -VERSION_NAME=1.13.0-SNAPSHOT +VERSION_NAME=1.15.0-SNAPSHOT POM_URL=https://github.com/square/kotlinpoet POM_SCM_URL=https://github.com/square/kotlinpoet @@ -17,3 +17,4 @@ POM_DEVELOPER_NAME=Square, Inc. SONATYPE_HOST=S01 RELEASE_SIGNING_ENABLED=true +SONATYPE_AUTOMATIC_RELEASE=true diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 523b9bc0..7e65f1f1 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,39 +13,39 @@ # limitations under the License. [versions] -kotlin = "1.7.22" -kct = "1.4.9" -ksp = "1.7.22-1.0.8" +kotlin = "1.9.0" +kct = "0.3.1" +ksp = "1.9.0-1.0.12" ktlint = "0.48.2" [plugins] kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" } -dokka = { id = "org.jetbrains.dokka", version = "1.7.20" } +dokka = { id = "org.jetbrains.dokka", version = "1.8.20" } ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" } -spotless = { id = "com.diffplug.spotless", version = "6.14.0" } -mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.24.0" } -kotlinBinaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.12.1" } +spotless = { id = "com.diffplug.spotless", version = "6.20.0" } +mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.25.3" } +kotlinBinaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.13.2" } [libraries] -autoCommon = { module = "com.google.auto:auto-common", version = "1.2.1" } -guava = { module = "com.google.guava:guava", version = "31.1-jre" } +autoCommon = { module = "com.google.auto:auto-common", version = "1.2.2" } +guava = { module = "com.google.guava:guava", version = "32.1.1-jre" } javapoet = "com.squareup:javapoet:1.13.0" -autoService = "com.google.auto.service:auto-service-annotations:1.0.1" -autoService-ksp = "dev.zacsweers.autoservice:auto-service-ksp:1.0.0" +autoService = "com.google.auto.service:auto-service-annotations:1.1.1" +autoService-ksp = "dev.zacsweers.autoservice:auto-service-ksp:1.1.0" kotlin-compilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-embeddable", version.ref = "kotlin" } kotlin-annotationProcessingEmbeddable = { module = "org.jetbrains.kotlin:kotlin-annotation-processing-embeddable", version.ref = "kotlin" } kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin" } kotlin-junit = { module = "org.jetbrains.kotlin:kotlin-test-junit", version.ref = "kotlin" } -kotlin-metadata = { module = "org.jetbrains.kotlinx:kotlinx-metadata-jvm", version = "0.5.0" } +kotlin-metadata = { module = "org.jetbrains.kotlinx:kotlinx-metadata-jvm", version = "0.7.0" } ksp = { module = "com.google.devtools.ksp:symbol-processing", version.ref = "ksp" } ksp-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "ksp" } -truth = { module = "com.google.truth:truth", version = "1.1.3" } +truth = { module = "com.google.truth:truth", version = "1.1.5" } compileTesting = { module = "com.google.testing.compile:compile-testing", version = "0.21.0" } -jimfs = { module = "com.google.jimfs:jimfs", version = "1.2" } +jimfs = { module = "com.google.jimfs:jimfs", version = "1.3.0" } ecj = { module = "org.eclipse.jdt.core.compiler:ecj", version = "4.6.1" } -kotlinCompileTesting = { module = "com.github.tschuchortdev:kotlin-compile-testing", version.ref = "kct" } -kotlinCompileTesting-ksp = { module = "com.github.tschuchortdev:kotlin-compile-testing-ksp", version.ref = "kct" } +kotlinCompileTesting = { module = "dev.zacsweers.kctfork:core", version.ref = "kct" } +kotlinCompileTesting-ksp = { module = "dev.zacsweers.kctfork:ksp", version.ref = "kct" } diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar Binary files differindex 249e5832..033e24c4 100644 --- a/gradle/wrapper/gradle-wrapper.jar +++ b/gradle/wrapper/gradle-wrapper.jar diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8fad3f5a..c747538f 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-all.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +130,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,6 +197,10 @@ if "$cygwin" || "$msys" ; then done fi + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + # Collect all arguments for the java command; # * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of # shell script including quotes and variable substitutions, so put them in diff --git a/gradlew.bat b/gradlew.bat index f127cfd4..93e3f59f 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% diff --git a/interop/javapoet/build.gradle.kts b/interop/javapoet/build.gradle.kts index 9899d9cc..734d934f 100644 --- a/interop/javapoet/build.gradle.kts +++ b/interop/javapoet/build.gradle.kts @@ -21,7 +21,7 @@ tasks.jar { } dependencies { - api(project(":kotlinpoet")) + api(projects.kotlinpoet) api(libs.javapoet) testImplementation(libs.kotlin.junit) testImplementation(libs.truth) diff --git a/interop/javapoet/src/test/kotlin/com/squareup/kotlinpoet/javapoet/PoetInteropTest.kt b/interop/javapoet/src/test/kotlin/com/squareup/kotlinpoet/javapoet/PoetInteropTest.kt index b622e6b4..9700bde4 100644 --- a/interop/javapoet/src/test/kotlin/com/squareup/kotlinpoet/javapoet/PoetInteropTest.kt +++ b/interop/javapoet/src/test/kotlin/com/squareup/kotlinpoet/javapoet/PoetInteropTest.kt @@ -139,7 +139,7 @@ class PoetInteropTest { JWildcardTypeName.supertypeOf(String::class.java), ) assertThat(inKType.toJTypeName()).isEqualTo(superJType) - assertThat(superJType.toKTypeName()).isEqualTo(inKType) + assertThat(superJType.toKTypeName().toString()).isEqualTo(inKType.toString()) val outKType = typeNameOf<GenericType<out String>>() val extendsJType = JParameterizedTypeName.get( @@ -147,7 +147,7 @@ class PoetInteropTest { JWildcardTypeName.subtypeOf(String::class.java), ) assertThat(outKType.toJTypeName()).isEqualTo(extendsJType) - assertThat(extendsJType.toKTypeName()).isEqualTo(outKType) + assertThat(extendsJType.toKTypeName().toString()).isEqualTo(outKType.toString()) val star = typeNameOf<GenericType<*>>() val extendsObjectJType = JParameterizedTypeName.get( @@ -155,7 +155,7 @@ class PoetInteropTest { JWildcardTypeName.subtypeOf(JTypeName.OBJECT), ) assertThat(star.toJTypeName()).isEqualTo(extendsObjectJType) - assertThat(extendsObjectJType.toKTypeName()).isEqualTo(star) + assertThat(extendsObjectJType.toKTypeName().toString()).isEqualTo(star.toString()) assertThat(STAR.toJTypeName()).isEqualTo(JWildcardTypeName.subtypeOf(JTypeName.OBJECT)) assertThat(JWildcardTypeName.subtypeOf(JTypeName.OBJECT).toKTypeName()).isEqualTo(STAR) } diff --git a/interop/kotlinx-metadata/api/kotlinx-metadata.api b/interop/kotlinx-metadata/api/kotlinx-metadata.api index 96f47c0c..f780eae0 100644 --- a/interop/kotlinx-metadata/api/kotlinx-metadata.api +++ b/interop/kotlinx-metadata/api/kotlinx-metadata.api @@ -1,97 +1,3 @@ -public final class com/squareup/kotlinpoet/metadata/FlagsKt { - public static final fun getDeclaresDefaultValue (Lkotlinx/metadata/KmValueParameter;)Z - public static final fun getGetterPropertyAccessorFlags (Lkotlinx/metadata/KmProperty;)Ljava/util/Set; - public static final fun getHasAnnotations (I)Z - public static final fun getHasConstant (Lkotlinx/metadata/KmProperty;)Z - public static final fun getHasGetter (Lkotlinx/metadata/KmProperty;)Z - public static final fun getHasSetter (Lkotlinx/metadata/KmProperty;)Z - public static final fun getPropertyAccessorFlags (I)Ljava/util/Set; - public static final fun getSetterPropertyAccessorFlags (Lkotlinx/metadata/KmProperty;)Ljava/util/Set; - public static final fun isAbstract (I)Z - public static final fun isAnnotation (Lkotlinx/metadata/KmClass;)Z - public static final fun isAnnotationClass (I)Z - public static final fun isClass (I)Z - public static final fun isClass (Lkotlinx/metadata/KmClass;)Z - public static final fun isCompanionObject (Lkotlinx/metadata/KmClass;)Z - public static final fun isCompanionObjectClass (I)Z - public static final fun isConst (Lkotlinx/metadata/KmProperty;)Z - public static final fun isCrossInline (Lkotlinx/metadata/KmValueParameter;)Z - public static final fun isData (Lkotlinx/metadata/KmClass;)Z - public static final fun isDataClass (I)Z - public static final fun isDeclaration (Lkotlinx/metadata/KmFunction;)Z - public static final fun isDeclaration (Lkotlinx/metadata/KmProperty;)Z - public static final fun isDeclarationFunction (I)Z - public static final fun isDelegated (Lkotlinx/metadata/KmProperty;)Z - public static final fun isDelegation (Lkotlinx/metadata/KmFunction;)Z - public static final fun isDelegation (Lkotlinx/metadata/KmProperty;)Z - public static final fun isDelegationFunction (I)Z - public static final fun isEnum (Lkotlinx/metadata/KmClass;)Z - public static final fun isEnumClass (I)Z - public static final fun isEnumEntry (Lkotlinx/metadata/KmClass;)Z - public static final fun isEnumEntryClass (I)Z - public static final fun isExpect (Lkotlinx/metadata/KmClass;)Z - public static final fun isExpect (Lkotlinx/metadata/KmFunction;)Z - public static final fun isExpect (Lkotlinx/metadata/KmProperty;)Z - public static final fun isExpectClass (I)Z - public static final fun isExpectFunction (I)Z - public static final fun isExternal (Lkotlinx/metadata/KmClass;)Z - public static final fun isExternal (Lkotlinx/metadata/KmFunction;)Z - public static final fun isExternal (Lkotlinx/metadata/KmProperty;)Z - public static final fun isExternalClass (I)Z - public static final fun isExternalFunction (I)Z - public static final fun isFakeOverride (Lkotlinx/metadata/KmFunction;)Z - public static final fun isFakeOverride (Lkotlinx/metadata/KmProperty;)Z - public static final fun isFakeOverrideFunction (I)Z - public static final fun isFakeOverrideProperty (I)Z - public static final fun isFinal (I)Z - public static final fun isFun (I)Z - public static final fun isFun (Lkotlinx/metadata/KmClass;)Z - public static final fun isInfix (Lkotlinx/metadata/KmFunction;)Z - public static final fun isInfixFunction (I)Z - public static final fun isInline (Lkotlinx/metadata/KmFunction;)Z - public static final fun isInlineFunction (I)Z - public static final fun isInner (Lkotlinx/metadata/KmClass;)Z - public static final fun isInnerClass (I)Z - public static final fun isInterface (I)Z - public static final fun isInterface (Lkotlinx/metadata/KmClass;)Z - public static final fun isInternal (I)Z - public static final fun isLateinit (Lkotlinx/metadata/KmProperty;)Z - public static final fun isLocal (I)Z - public static final fun isNoInline (Lkotlinx/metadata/KmValueParameter;)Z - public static final fun isNullable (Lkotlinx/metadata/KmType;)Z - public static final fun isNullableType (I)Z - public static final fun isObject (Lkotlinx/metadata/KmClass;)Z - public static final fun isObjectClass (I)Z - public static final fun isOpen (I)Z - public static final fun isOperator (Lkotlinx/metadata/KmFunction;)Z - public static final fun isOperatorFunction (I)Z - public static final fun isPrimary (Lkotlinx/metadata/KmConstructor;)Z - public static final fun isPrimaryConstructor (I)Z - public static final fun isPrivate (I)Z - public static final fun isPrivate_to_this (I)Z - public static final fun isPropertyAccessorExternal (I)Z - public static final fun isPropertyAccessorInline (I)Z - public static final fun isPropertyAccessorNotDefault (I)Z - public static final fun isProtected (I)Z - public static final fun isPublic (I)Z - public static final fun isReified (Lkotlinx/metadata/KmTypeParameter;)Z - public static final fun isSealed (I)Z - public static final fun isSecondary (Lkotlinx/metadata/KmConstructor;)Z - public static final fun isSuspend (Lkotlinx/metadata/KmFunction;)Z - public static final fun isSuspend (Lkotlinx/metadata/KmType;)Z - public static final fun isSuspendFunction (I)Z - public static final fun isSuspendType (I)Z - public static final fun isSynthesized (Lkotlinx/metadata/KmFunction;)Z - public static final fun isSynthesized (Lkotlinx/metadata/KmProperty;)Z - public static final fun isSynthesizedFunction (I)Z - public static final fun isTailRec (Lkotlinx/metadata/KmFunction;)Z - public static final fun isTailRecFunction (I)Z - public static final fun isVal (Lkotlinx/metadata/KmProperty;)Z - public static final fun isValue (Lkotlinx/metadata/KmClass;)Z - public static final fun isValueClass (I)Z - public static final fun isVar (Lkotlinx/metadata/KmProperty;)Z -} - public final class com/squareup/kotlinpoet/metadata/KotlinPoetMetadata { public static final fun readKotlinClassMetadata (Lkotlin/Metadata;)Lkotlinx/metadata/jvm/KotlinClassMetadata; public static final fun toKmClass (Ljava/lang/Class;)Lkotlinx/metadata/KmClass; @@ -103,14 +9,6 @@ public final class com/squareup/kotlinpoet/metadata/KotlinPoetMetadata { public abstract interface annotation class com/squareup/kotlinpoet/metadata/KotlinPoetMetadataPreview : java/lang/annotation/Annotation { } -public final class com/squareup/kotlinpoet/metadata/PropertyAccessorFlag : java/lang/Enum { - public static final field IS_EXTERNAL Lcom/squareup/kotlinpoet/metadata/PropertyAccessorFlag; - public static final field IS_INLINE Lcom/squareup/kotlinpoet/metadata/PropertyAccessorFlag; - public static final field IS_NOT_DEFAULT Lcom/squareup/kotlinpoet/metadata/PropertyAccessorFlag; - public static fun valueOf (Ljava/lang/String;)Lcom/squareup/kotlinpoet/metadata/PropertyAccessorFlag; - public static fun values ()[Lcom/squareup/kotlinpoet/metadata/PropertyAccessorFlag; -} - public final class com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector : com/squareup/kotlinpoet/metadata/specs/ClassInspector { public static final field Companion Lcom/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector$Companion; public synthetic fun <init> (Ljavax/lang/model/util/Elements;Ljavax/lang/model/util/Types;Lkotlin/jvm/internal/DefaultConstructorMarker;)V @@ -273,7 +171,7 @@ public class com/squareup/kotlinpoet/metadata/specs/JvmFieldModifier : java/lang public static final field TRANSIENT Lcom/squareup/kotlinpoet/metadata/specs/JvmFieldModifier; public static final field VOLATILE Lcom/squareup/kotlinpoet/metadata/specs/JvmFieldModifier; public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun annotationSpec ()Lcom/squareup/kotlinpoet/AnnotationSpec; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/squareup/kotlinpoet/metadata/specs/JvmFieldModifier; public static fun values ()[Lcom/squareup/kotlinpoet/metadata/specs/JvmFieldModifier; } @@ -283,13 +181,13 @@ public class com/squareup/kotlinpoet/metadata/specs/JvmMethodModifier : java/lan public static final field STATIC Lcom/squareup/kotlinpoet/metadata/specs/JvmMethodModifier; public static final field SYNCHRONIZED Lcom/squareup/kotlinpoet/metadata/specs/JvmMethodModifier; public synthetic fun <init> (Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V - public fun annotationSpec ()Lcom/squareup/kotlinpoet/AnnotationSpec; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/squareup/kotlinpoet/metadata/specs/JvmMethodModifier; public static fun values ()[Lcom/squareup/kotlinpoet/metadata/specs/JvmMethodModifier; } public abstract interface class com/squareup/kotlinpoet/metadata/specs/JvmModifier { - public abstract fun annotationSpec ()Lcom/squareup/kotlinpoet/AnnotationSpec; + public fun annotationSpec ()Lcom/squareup/kotlinpoet/AnnotationSpec; } public final class com/squareup/kotlinpoet/metadata/specs/JvmModifier$DefaultImpls { diff --git a/interop/kotlinx-metadata/build.gradle.kts b/interop/kotlinx-metadata/build.gradle.kts index df75e1ad..a828789d 100644 --- a/interop/kotlinx-metadata/build.gradle.kts +++ b/interop/kotlinx-metadata/build.gradle.kts @@ -21,10 +21,11 @@ tasks.jar { } tasks.compileTestKotlin { - kotlinOptions { - freeCompilerArgs = listOf( + compilerOptions { + freeCompilerArgs.addAll( "-Xjvm-default=all", "-opt-in=com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview", + "-opt-in=org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi", ) } } @@ -33,7 +34,7 @@ dependencies { implementation(libs.autoCommon) implementation(libs.guava) api(libs.kotlin.metadata) - api(project(":kotlinpoet")) + api(projects.kotlinpoet) testImplementation(libs.kotlin.junit) testImplementation(libs.truth) diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/Flags.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/Flags.kt deleted file mode 100644 index 4745dda0..00000000 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/Flags.kt +++ /dev/null @@ -1,338 +0,0 @@ -/* - * Copyright (C) 2019 Square, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -@file:Suppress("unused") - -package com.squareup.kotlinpoet.metadata - -import kotlinx.metadata.Flag -import kotlinx.metadata.Flags -import kotlinx.metadata.KmClass -import kotlinx.metadata.KmConstructor -import kotlinx.metadata.KmFunction -import kotlinx.metadata.KmProperty -import kotlinx.metadata.KmType -import kotlinx.metadata.KmTypeParameter -import kotlinx.metadata.KmValueParameter - -// Common flags for any element with flags. -@KotlinPoetMetadataPreview -public val Flags.hasAnnotations: Boolean get() = Flag.HAS_ANNOTATIONS(this) - -@KotlinPoetMetadataPreview -public val Flags.isAbstract: Boolean get() = Flag.IS_ABSTRACT(this) - -@KotlinPoetMetadataPreview -public val Flags.isFinal: Boolean get() = Flag.IS_FINAL(this) - -@KotlinPoetMetadataPreview -public val Flags.isInternal: Boolean get() = Flag.IS_INTERNAL(this) - -@KotlinPoetMetadataPreview -public val Flags.isLocal: Boolean get() = Flag.IS_LOCAL(this) - -@KotlinPoetMetadataPreview -public val Flags.isOpen: Boolean get() = Flag.IS_OPEN(this) - -@KotlinPoetMetadataPreview -public val Flags.isPrivate: Boolean get() = Flag.IS_PRIVATE(this) - -@KotlinPoetMetadataPreview -public val Flags.isPrivate_to_this: Boolean get() = Flag.IS_PRIVATE_TO_THIS(this) - -@KotlinPoetMetadataPreview -public val Flags.isProtected: Boolean get() = Flag.IS_PROTECTED(this) - -@KotlinPoetMetadataPreview -public val Flags.isPublic: Boolean get() = Flag.IS_PUBLIC(this) - -@KotlinPoetMetadataPreview -public val Flags.isSealed: Boolean get() = Flag.IS_SEALED(this) - -// Type flags. -@KotlinPoetMetadataPreview -public val Flags.isNullableType: Boolean get() = Flag.Type.IS_NULLABLE(this) - -@KotlinPoetMetadataPreview -public val Flags.isSuspendType: Boolean get() = Flag.Type.IS_SUSPEND(this) - -// Class flags. -@KotlinPoetMetadataPreview -public val Flags.isAnnotationClass: Boolean get() = Flag.Class.IS_ANNOTATION_CLASS(this) - -@KotlinPoetMetadataPreview -public val Flags.isClass: Boolean get() = Flag.Class.IS_CLASS(this) - -@KotlinPoetMetadataPreview -public val Flags.isCompanionObjectClass: Boolean get() = Flag.Class.IS_COMPANION_OBJECT(this) - -@KotlinPoetMetadataPreview -public val Flags.isDataClass: Boolean get() = Flag.Class.IS_DATA(this) - -@KotlinPoetMetadataPreview -public val Flags.isEnumClass: Boolean get() = Flag.Class.IS_ENUM_CLASS(this) - -@KotlinPoetMetadataPreview -public val Flags.isEnumEntryClass: Boolean get() = Flag.Class.IS_ENUM_ENTRY(this) - -@KotlinPoetMetadataPreview -public val Flags.isExpectClass: Boolean get() = Flag.Class.IS_EXPECT(this) - -@KotlinPoetMetadataPreview -public val Flags.isExternalClass: Boolean get() = Flag.Class.IS_EXTERNAL(this) - -@KotlinPoetMetadataPreview -public val Flags.isValueClass: Boolean get() = Flag.Class.IS_VALUE(this) - -@KotlinPoetMetadataPreview -public val Flags.isInnerClass: Boolean get() = Flag.Class.IS_INNER(this) - -@KotlinPoetMetadataPreview -public val Flags.isObjectClass: Boolean get() = Flag.Class.IS_OBJECT(this) - -@KotlinPoetMetadataPreview -public val Flags.isInterface: Boolean get() = Flag.Class.IS_INTERFACE(this) - -@KotlinPoetMetadataPreview -public val Flags.isFun: Boolean get() = Flag.Class.IS_FUN(this) - -@KotlinPoetMetadataPreview -public val KmClass.isAnnotation: Boolean get() = flags.isAnnotationClass - -@KotlinPoetMetadataPreview -public val KmClass.isClass: Boolean get() = flags.isClass - -@KotlinPoetMetadataPreview -public val KmClass.isCompanionObject: Boolean get() = flags.isCompanionObjectClass - -@KotlinPoetMetadataPreview -public val KmClass.isData: Boolean get() = flags.isDataClass - -@KotlinPoetMetadataPreview -public val KmClass.isEnum: Boolean get() = flags.isEnumClass - -@KotlinPoetMetadataPreview -public val KmClass.isEnumEntry: Boolean get() = flags.isEnumEntryClass - -@KotlinPoetMetadataPreview -public val KmClass.isExpect: Boolean get() = flags.isExpectClass - -@KotlinPoetMetadataPreview -public val KmClass.isExternal: Boolean get() = flags.isExternalClass - -@KotlinPoetMetadataPreview -public val KmClass.isValue: Boolean get() = flags.isValueClass - -@KotlinPoetMetadataPreview -public val KmClass.isInner: Boolean get() = flags.isInnerClass - -@KotlinPoetMetadataPreview -public val KmClass.isObject: Boolean get() = flags.isObjectClass - -@KotlinPoetMetadataPreview -public val KmClass.isInterface: Boolean get() = flags.isInterface - -@KotlinPoetMetadataPreview -public val KmClass.isFun: Boolean get() = flags.isFun - -@KotlinPoetMetadataPreview -public val KmType.isSuspend: Boolean get() = flags.isSuspendType - -@KotlinPoetMetadataPreview -public val KmType.isNullable: Boolean get() = flags.isNullableType - -// Constructor flags. -@KotlinPoetMetadataPreview -public val Flags.isPrimaryConstructor: Boolean get() = !Flag.Constructor.IS_SECONDARY(this) - -@KotlinPoetMetadataPreview -public val KmConstructor.isPrimary: Boolean get() = flags.isPrimaryConstructor - -@KotlinPoetMetadataPreview -public val KmConstructor.isSecondary: Boolean get() = !isPrimary - -// Function flags. -@KotlinPoetMetadataPreview -public val Flags.isDeclarationFunction: Boolean get() = Flag.Function.IS_DECLARATION(this) - -@KotlinPoetMetadataPreview -public val Flags.isFakeOverrideFunction: Boolean get() = Flag.Function.IS_FAKE_OVERRIDE(this) - -@KotlinPoetMetadataPreview -public val Flags.isDelegationFunction: Boolean get() = Flag.Function.IS_DELEGATION(this) - -@KotlinPoetMetadataPreview -public val Flags.isSynthesizedFunction: Boolean get() = Flag.Function.IS_SYNTHESIZED(this) - -@KotlinPoetMetadataPreview -public val Flags.isOperatorFunction: Boolean get() = Flag.Function.IS_OPERATOR(this) - -@KotlinPoetMetadataPreview -public val Flags.isInfixFunction: Boolean get() = Flag.Function.IS_INFIX(this) - -@KotlinPoetMetadataPreview -public val Flags.isInlineFunction: Boolean get() = Flag.Function.IS_INLINE(this) - -@KotlinPoetMetadataPreview -public val Flags.isTailRecFunction: Boolean get() = Flag.Function.IS_TAILREC(this) - -@KotlinPoetMetadataPreview -public val Flags.isExternalFunction: Boolean get() = Flag.Function.IS_EXTERNAL(this) - -@KotlinPoetMetadataPreview -public val Flags.isSuspendFunction: Boolean get() = Flag.Function.IS_SUSPEND(this) - -@KotlinPoetMetadataPreview -public val Flags.isExpectFunction: Boolean get() = Flag.Function.IS_EXPECT(this) - -@KotlinPoetMetadataPreview -public val KmFunction.isDeclaration: Boolean get() = flags.isDeclarationFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isFakeOverride: Boolean get() = flags.isFakeOverrideFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isDelegation: Boolean get() = flags.isDelegationFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isSynthesized: Boolean get() = flags.isSynthesizedFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isOperator: Boolean get() = flags.isOperatorFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isInfix: Boolean get() = flags.isInfixFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isInline: Boolean get() = flags.isInlineFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isTailRec: Boolean get() = flags.isTailRecFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isExternal: Boolean get() = flags.isExternalFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isSuspend: Boolean get() = flags.isSuspendFunction - -@KotlinPoetMetadataPreview -public val KmFunction.isExpect: Boolean get() = flags.isExpectFunction - -// Parameter flags. -@KotlinPoetMetadataPreview -public val KmValueParameter.declaresDefaultValue: Boolean get() = - Flag.ValueParameter.DECLARES_DEFAULT_VALUE(flags) - -@KotlinPoetMetadataPreview -public val KmValueParameter.isCrossInline: Boolean get() = Flag.ValueParameter.IS_CROSSINLINE(flags) - -@KotlinPoetMetadataPreview -public val KmValueParameter.isNoInline: Boolean get() = Flag.ValueParameter.IS_NOINLINE(flags) - -// Property flags. -@KotlinPoetMetadataPreview -public val Flags.isFakeOverrideProperty: Boolean get() = Flag.Property.IS_FAKE_OVERRIDE(this) - -@KotlinPoetMetadataPreview -public val KmProperty.hasConstant: Boolean get() = Flag.Property.HAS_CONSTANT(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.hasGetter: Boolean get() = Flag.Property.HAS_GETTER(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.hasSetter: Boolean get() = Flag.Property.HAS_SETTER(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isConst: Boolean get() = Flag.Property.IS_CONST(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isDeclaration: Boolean get() = Flag.Property.IS_DECLARATION(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isDelegated: Boolean get() = Flag.Property.IS_DELEGATED(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isDelegation: Boolean get() = Flag.Property.IS_DELEGATION(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isExpect: Boolean get() = Flag.Property.IS_EXPECT(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isExternal: Boolean get() = Flag.Property.IS_EXTERNAL(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isFakeOverride: Boolean get() = flags.isFakeOverrideProperty - -@KotlinPoetMetadataPreview -public val KmProperty.isLateinit: Boolean get() = Flag.Property.IS_LATEINIT(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isSynthesized: Boolean get() = Flag.Property.IS_SYNTHESIZED(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isVar: Boolean get() = Flag.Property.IS_VAR(flags) - -@KotlinPoetMetadataPreview -public val KmProperty.isVal: Boolean get() = !isVar - -// Property Accessor Flags -@KotlinPoetMetadataPreview -public val Flags.isPropertyAccessorExternal: Boolean - get() = Flag.PropertyAccessor.IS_EXTERNAL(this) - -@KotlinPoetMetadataPreview -public val Flags.isPropertyAccessorInline: Boolean - get() = Flag.PropertyAccessor.IS_INLINE(this) - -@KotlinPoetMetadataPreview -public val Flags.isPropertyAccessorNotDefault: Boolean - get() = Flag.PropertyAccessor.IS_NOT_DEFAULT(this) - -// TypeParameter flags. -@KotlinPoetMetadataPreview -public val KmTypeParameter.isReified: Boolean get() = Flag.TypeParameter.IS_REIFIED(flags) - -// Property Accessor Flags -public enum class PropertyAccessorFlag { - IS_EXTERNAL, - IS_INLINE, - IS_NOT_DEFAULT, -} - -@KotlinPoetMetadataPreview -public val KmProperty.setterPropertyAccessorFlags: Set<PropertyAccessorFlag> - get() = setterFlags.propertyAccessorFlags - -@KotlinPoetMetadataPreview -public val KmProperty.getterPropertyAccessorFlags: Set<PropertyAccessorFlag> - get() = getterFlags.propertyAccessorFlags - -@KotlinPoetMetadataPreview -public val Flags.propertyAccessorFlags: Set<PropertyAccessorFlag> - get() = setOf { - if (Flag.PropertyAccessor.IS_EXTERNAL(this@propertyAccessorFlags)) { - add(PropertyAccessorFlag.IS_EXTERNAL) - } - if (Flag.PropertyAccessor.IS_INLINE(this@propertyAccessorFlags)) { - add(PropertyAccessorFlag.IS_INLINE) - } - if (Flag.PropertyAccessor.IS_NOT_DEFAULT(this@propertyAccessorFlags)) { - add(PropertyAccessorFlag.IS_NOT_DEFAULT) - } - } - -internal inline fun <E> setOf(body: MutableSet<E>.() -> Unit): Set<E> { - return mutableSetOf<E>().apply(body).toSet() -} diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/KotlinPoetMetadata.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/KotlinPoetMetadata.kt index 6cb3c91d..bae24747 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/KotlinPoetMetadata.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/KotlinPoetMetadata.kt @@ -14,7 +14,6 @@ * limitations under the License. */ @file:JvmName("KotlinPoetMetadata") -@file:Suppress("unused") package com.squareup.kotlinpoet.metadata @@ -24,8 +23,8 @@ import kotlin.annotation.AnnotationTarget.FUNCTION import kotlin.annotation.AnnotationTarget.PROPERTY import kotlin.reflect.KClass import kotlinx.metadata.KmClass -import kotlinx.metadata.jvm.KotlinClassHeader import kotlinx.metadata.jvm.KotlinClassMetadata +import kotlinx.metadata.jvm.Metadata /** * Indicates that a given API is part of the experimental KotlinPoet metadata support. This exists @@ -51,7 +50,7 @@ public fun TypeElement.toKmClass(): KmClass = readMetadata(::getAnnotation).toKm @KotlinPoetMetadataPreview public fun Metadata.toKmClass(): KmClass { return toKotlinClassMetadata<KotlinClassMetadata.Class>() - .toKmClass() + .kmClass } @KotlinPoetMetadataPreview @@ -99,8 +98,8 @@ private inline fun readMetadata(lookup: ((Class<Metadata>) -> Metadata?)): Metad } } -private fun Metadata.asClassHeader(): KotlinClassHeader { - return KotlinClassHeader( +private fun Metadata.asClassHeader(): Metadata { + return Metadata( kind = kind, metadataVersion = metadataVersion, data1 = data1, diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ClassInspectorUtil.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ClassInspectorUtil.kt index d9caa834..1bbf6945 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ClassInspectorUtil.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ClassInspectorUtil.kt @@ -38,12 +38,12 @@ import com.squareup.kotlinpoet.TypeName import com.squareup.kotlinpoet.asClassName import com.squareup.kotlinpoet.joinToCode import com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview -import com.squareup.kotlinpoet.metadata.isConst import com.squareup.kotlinpoet.metadata.specs.ClassInspector import java.util.Collections import java.util.TreeSet import kotlinx.metadata.KmProperty -import kotlinx.metadata.isLocal +import kotlinx.metadata.isConst +import kotlinx.metadata.isLocalClassName import org.jetbrains.annotations.NotNull import org.jetbrains.annotations.Nullable @@ -195,7 +195,7 @@ internal object ClassInspectorUtil { * with those. */ fun createClassName(kotlinMetadataName: String): ClassName { - require(!kotlinMetadataName.isLocal) { + require(!kotlinMetadataName.isLocalClassName()) { "Local/anonymous classes are not supported!" } // Top-level: package/of/class/MyClass diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector.kt index d4f77860..0282913c 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ElementsClassInspector.kt @@ -24,6 +24,7 @@ import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.AnnotationSpec.UseSiteTarget.FILE import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.DelicateKotlinPoetApi import com.squareup.kotlinpoet.TypeName import com.squareup.kotlinpoet.asClassName import com.squareup.kotlinpoet.asTypeName @@ -31,14 +32,7 @@ import com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.JAVA_DEPRECATED import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.JVM_NAME import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.filterOutNullabilityAnnotations -import com.squareup.kotlinpoet.metadata.hasAnnotations -import com.squareup.kotlinpoet.metadata.hasConstant -import com.squareup.kotlinpoet.metadata.isAnnotation -import com.squareup.kotlinpoet.metadata.isCompanionObject -import com.squareup.kotlinpoet.metadata.isConst import com.squareup.kotlinpoet.metadata.isDeclaration -import com.squareup.kotlinpoet.metadata.isSynthesized -import com.squareup.kotlinpoet.metadata.isValue import com.squareup.kotlinpoet.metadata.readKotlinClassMetadata import com.squareup.kotlinpoet.metadata.specs.ClassData import com.squareup.kotlinpoet.metadata.specs.ClassInspector @@ -73,9 +67,14 @@ import javax.lang.model.util.ElementFilter import javax.lang.model.util.Elements import javax.lang.model.util.Types import kotlin.LazyThreadSafetyMode.NONE +import kotlinx.metadata.ClassKind import kotlinx.metadata.KmClass import kotlinx.metadata.KmDeclarationContainer import kotlinx.metadata.KmPackage +import kotlinx.metadata.hasAnnotations +import kotlinx.metadata.hasConstant +import kotlinx.metadata.isConst +import kotlinx.metadata.isValue import kotlinx.metadata.jvm.JvmFieldSignature import kotlinx.metadata.jvm.JvmMethodSignature import kotlinx.metadata.jvm.KotlinClassMetadata @@ -84,6 +83,7 @@ import kotlinx.metadata.jvm.getterSignature import kotlinx.metadata.jvm.setterSignature import kotlinx.metadata.jvm.signature import kotlinx.metadata.jvm.syntheticMethodForAnnotations +import kotlinx.metadata.kind private typealias ElementsModifier = javax.lang.model.element.Modifier @@ -116,8 +116,8 @@ public class ElementsClassInspector private constructor( val metadata = typeElement.getAnnotation(Metadata::class.java) return when (val kotlinClassMetadata = metadata.readKotlinClassMetadata()) { - is KotlinClassMetadata.Class -> kotlinClassMetadata.toKmClass() - is KotlinClassMetadata.FileFacade -> kotlinClassMetadata.toKmPackage() + is KotlinClassMetadata.Class -> kotlinClassMetadata.kmClass + is KotlinClassMetadata.FileFacade -> kotlinClassMetadata.kmPackage else -> TODO("Not implemented yet: ${kotlinClassMetadata.javaClass.simpleName}") } } @@ -130,7 +130,7 @@ public class ElementsClassInspector private constructor( } private fun TypeElement.lookupField(fieldSignature: JvmFieldSignature): VariableElement? { - val signatureString = fieldSignature.asString() + val signatureString = fieldSignature.toString() return variableElementCache.getOrPut(this to signatureString) { ElementFilter.fieldsIn(enclosedElements) .find { signatureString == it.jvmFieldSignature(types) }.toOptional() @@ -149,7 +149,7 @@ public class ElementsClassInspector private constructor( methodSignature: JvmMethodSignature, elementFilter: (Iterable<Element>) -> List<ExecutableElement>, ): ExecutableElement? { - val signatureString = methodSignature.asString() + val signatureString = methodSignature.toString() return methodCache.getOrPut(this to signatureString) { elementFilter(enclosedElements) .find { signatureString == it.jvmMethodSignature(types) }.toOptional() @@ -167,8 +167,8 @@ public class ElementsClassInspector private constructor( } } + @OptIn(DelicateKotlinPoetApi::class) private fun VariableElement.annotationSpecs(): List<AnnotationSpec> { - @Suppress("DEPRECATION") return filterOutNullabilityAnnotations( annotationMirrors.map { AnnotationSpec.get(it) }, ) @@ -185,15 +185,15 @@ public class ElementsClassInspector private constructor( } } + @OptIn(DelicateKotlinPoetApi::class) private fun ExecutableElement.annotationSpecs(): List<AnnotationSpec> { - @Suppress("DEPRECATION") return filterOutNullabilityAnnotations( annotationMirrors.map { AnnotationSpec.get(it) }, ) } + @OptIn(DelicateKotlinPoetApi::class) private fun ExecutableElement.exceptionTypeNames(): List<TypeName> { - @Suppress("DEPRECATION") return thrownTypes.map { it.asTypeName() } } @@ -303,6 +303,7 @@ public class ElementsClassInspector private constructor( } } + @OptIn(DelicateKotlinPoetApi::class) override fun containerData( declarationContainer: KmDeclarationContainer, className: ClassName, @@ -311,7 +312,7 @@ public class ElementsClassInspector private constructor( val typeElement: TypeElement = lookupTypeElement(className) ?: error("No class found for: $className.") val isCompanionObject = when (declarationContainer) { is KmClass -> { - declarationContainer.isCompanionObject + declarationContainer.kind == ClassKind.COMPANION_OBJECT } is KmPackage -> { false @@ -331,8 +332,7 @@ public class ElementsClassInspector private constructor( val propertyData = declarationContainer.properties .asSequence() - .filter { it.isDeclaration } - .filterNot { it.isSynthesized } + .filter { it.kind.isDeclaration } .associateWithTo(TreeMap(KM_PROPERTY_COMPARATOR)) { property -> val isJvmField = ClassInspectorUtil.computeIsJvmField( property = property, @@ -395,7 +395,7 @@ public class ElementsClassInspector private constructor( val method = classIfCompanion.lookupMethod(getterSignature, ElementFilter::methodsIn) method?.methodData( typeElement = typeElement, - hasAnnotations = property.getterFlags.hasAnnotations, + hasAnnotations = property.getter.hasAnnotations, jvmInformationMethod = classIfCompanion.takeIf { it != typeElement } ?.lookupMethod(getterSignature, ElementFilter::methodsIn) ?: method, @@ -407,7 +407,7 @@ public class ElementsClassInspector private constructor( val method = classIfCompanion.lookupMethod(setterSignature, ElementFilter::methodsIn) method?.methodData( typeElement = typeElement, - hasAnnotations = property.setterFlags.hasAnnotations, + hasAnnotations = property.setter?.hasAnnotations ?: false, jvmInformationMethod = classIfCompanion.takeIf { it != typeElement } ?.lookupMethod(setterSignature, ElementFilter::methodsIn) ?: method, @@ -417,7 +417,7 @@ public class ElementsClassInspector private constructor( } val annotations = mutableListOf<AnnotationSpec>() - if (property.flags.hasAnnotations) { + if (property.hasAnnotations) { property.syntheticMethodForAnnotations?.let { annotationsHolderSignature -> val method = typeElement.lookupMethod(annotationsHolderSignature, ElementFilter::methodsIn) ?: return@let MethodData.SYNTHETIC @@ -459,7 +459,7 @@ public class ElementsClassInspector private constructor( val method = typeElement.lookupMethod(signature, ElementFilter::methodsIn) method?.methodData( typeElement = typeElement, - hasAnnotations = kmFunction.flags.hasAnnotations, + hasAnnotations = kmFunction.hasAnnotations, jvmInformationMethod = classIfCompanion.takeIf { it != typeElement } ?.lookupMethod(signature, ElementFilter::methodsIn) ?: method, @@ -474,7 +474,7 @@ public class ElementsClassInspector private constructor( is KmClass -> { val constructorData = declarationContainer.constructors .associateWithTo(TreeMap(KM_CONSTRUCTOR_COMPARATOR)) { kmConstructor -> - if (declarationContainer.isAnnotation || declarationContainer.isValue) { + if (declarationContainer.kind == ClassKind.ANNOTATION_CLASS || declarationContainer.isValue) { // // Annotations are interfaces in bytecode, but kotlin metadata will still report a // constructor signature @@ -488,7 +488,7 @@ public class ElementsClassInspector private constructor( val constructor = typeElement.lookupMethod(signature, ElementFilter::constructorsIn) ?: return@associateWithTo ConstructorData.EMPTY ConstructorData( - annotations = if (kmConstructor.flags.hasAnnotations) { + annotations = if (kmConstructor.hasAnnotations) { constructor.annotationSpecs() } else { emptyList() @@ -505,9 +505,8 @@ public class ElementsClassInspector private constructor( return ClassData( declarationContainer = declarationContainer, className = className, - annotations = if (declarationContainer.flags.hasAnnotations) { + annotations = if (declarationContainer.hasAnnotations) { ClassInspectorUtil.createAnnotations { - @Suppress("DEPRECATION") addAll(typeElement.annotationMirrors.map { AnnotationSpec.get(it) }) } } else { @@ -532,7 +531,6 @@ public class ElementsClassInspector private constructor( } jvmName = nameValue.value as String } - @Suppress("DEPRECATION") AnnotationSpec.get(it) }, ) diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/JvmDescriptorUtils.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/JvmDescriptorUtils.kt index 235e5e87..aea3213b 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/JvmDescriptorUtils.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/JvmDescriptorUtils.kt @@ -25,6 +25,7 @@ import javax.lang.model.type.ArrayType import javax.lang.model.type.DeclaredType import javax.lang.model.type.ErrorType import javax.lang.model.type.ExecutableType +import javax.lang.model.type.IntersectionType import javax.lang.model.type.NoType import javax.lang.model.type.NullType import javax.lang.model.type.PrimitiveType @@ -38,8 +39,9 @@ import javax.lang.model.type.TypeKind.LONG import javax.lang.model.type.TypeKind.SHORT import javax.lang.model.type.TypeMirror import javax.lang.model.type.TypeVariable +import javax.lang.model.type.UnionType import javax.lang.model.type.WildcardType -import javax.lang.model.util.AbstractTypeVisitor6 +import javax.lang.model.util.AbstractTypeVisitor8 import javax.lang.model.util.Types import kotlinx.metadata.jvm.JvmFieldSignature import kotlinx.metadata.jvm.JvmMethodSignature @@ -55,6 +57,7 @@ import kotlinx.metadata.jvm.JvmMethodSignature * * @return the name of this [Element] in its "internal form". */ +@Suppress("RecursivePropertyAccessor") internal val Element.internalName: String get() = when (this) { is TypeElement -> { @@ -171,7 +174,7 @@ internal fun VariableElement.jvmFieldSignature(types: Types): String { * * For reference, see the [JVM specification, section 4.3](https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3). */ -internal object JvmDescriptorTypeVisitor : AbstractTypeVisitor6<String, Types>() { +internal object JvmDescriptorTypeVisitor : AbstractTypeVisitor8<String, Types>() { override fun visitNoType(t: NoType, types: Types): String = t.descriptor override fun visitDeclared(t: DeclaredType, types: Types): String = t.descriptor override fun visitPrimitive(t: PrimitiveType, types: Types): String = t.descriptor @@ -181,14 +184,13 @@ internal object JvmDescriptorTypeVisitor : AbstractTypeVisitor6<String, Types>() override fun visitExecutable(t: ExecutableType, types: Types): String = t.descriptor(types) override fun visitTypeVariable(t: TypeVariable, types: Types): String = t.descriptor(types) - override fun visitNull(t: NullType, types: Types): String = visitUnknown( - t, - types, - ) - override fun visitError(t: ErrorType, types: Types): String = visitUnknown( - t, - types, - ) + override fun visitNull(t: NullType, types: Types): String = visitUnknown(t, types) + + override fun visitError(t: ErrorType, types: Types): String = visitUnknown(t, types) + + override fun visitUnion(t: UnionType, types: Types): String = visitUnknown(t, types) + + override fun visitIntersection(t: IntersectionType, types: Types): String = visitUnknown(t, types) override fun visitUnknown(t: TypeMirror, types: Types): String = error("Unsupported type $t") } diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector.kt index fc31ba09..d4c74eb3 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/classinspectors/ReflectiveClassInspector.kt @@ -19,19 +19,13 @@ import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.AnnotationSpec.UseSiteTarget.FILE import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.DelicateKotlinPoetApi import com.squareup.kotlinpoet.TypeName import com.squareup.kotlinpoet.asTypeName import com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.JAVA_DEPRECATED import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.filterOutNullabilityAnnotations -import com.squareup.kotlinpoet.metadata.hasAnnotations -import com.squareup.kotlinpoet.metadata.hasConstant -import com.squareup.kotlinpoet.metadata.isAnnotation -import com.squareup.kotlinpoet.metadata.isCompanionObject -import com.squareup.kotlinpoet.metadata.isConst import com.squareup.kotlinpoet.metadata.isDeclaration -import com.squareup.kotlinpoet.metadata.isSynthesized -import com.squareup.kotlinpoet.metadata.isValue import com.squareup.kotlinpoet.metadata.readKotlinClassMetadata import com.squareup.kotlinpoet.metadata.specs.ClassData import com.squareup.kotlinpoet.metadata.specs.ClassInspector @@ -61,9 +55,14 @@ import java.lang.reflect.Parameter import java.util.TreeMap import java.util.concurrent.ConcurrentHashMap import kotlin.LazyThreadSafetyMode.NONE +import kotlinx.metadata.ClassKind import kotlinx.metadata.KmClass import kotlinx.metadata.KmDeclarationContainer import kotlinx.metadata.KmPackage +import kotlinx.metadata.hasAnnotations +import kotlinx.metadata.hasConstant +import kotlinx.metadata.isConst +import kotlinx.metadata.isValue import kotlinx.metadata.jvm.JvmFieldSignature import kotlinx.metadata.jvm.JvmMethodSignature import kotlinx.metadata.jvm.KotlinClassMetadata @@ -72,6 +71,7 @@ import kotlinx.metadata.jvm.getterSignature import kotlinx.metadata.jvm.setterSignature import kotlinx.metadata.jvm.signature import kotlinx.metadata.jvm.syntheticMethodForAnnotations +import kotlinx.metadata.kind @KotlinPoetMetadataPreview public class ReflectiveClassInspector private constructor( @@ -106,8 +106,8 @@ public class ReflectiveClassInspector private constructor( val metadata = clazz.getAnnotation(Metadata::class.java) return when (val kotlinClassMetadata = metadata.readKotlinClassMetadata()) { - is KotlinClassMetadata.Class -> kotlinClassMetadata.toKmClass() - is KotlinClassMetadata.FileFacade -> kotlinClassMetadata.toKmPackage() + is KotlinClassMetadata.Class -> kotlinClassMetadata.kmClass + is KotlinClassMetadata.FileFacade -> kotlinClassMetadata.kmPackage else -> TODO("Not implemented yet: ${kotlinClassMetadata.javaClass.simpleName}") } } @@ -121,7 +121,7 @@ public class ReflectiveClassInspector private constructor( private fun Class<*>.lookupField(fieldSignature: JvmFieldSignature): Field? { return try { - val signatureString = fieldSignature.asString() + val signatureString = fieldSignature.toString() fieldCache.getOrPut(this to signatureString) { declaredFields .asSequence() @@ -136,7 +136,7 @@ public class ReflectiveClassInspector private constructor( private fun Class<*>.lookupMethod( methodSignature: JvmMethodSignature, ): Method? { - val signatureString = methodSignature.asString() + val signatureString = methodSignature.toString() return methodCache.getOrPut(this to signatureString) { declaredMethods .asSequence() @@ -148,7 +148,7 @@ public class ReflectiveClassInspector private constructor( private fun Class<*>.lookupConstructor( constructorSignature: JvmMethodSignature, ): Constructor<*>? { - val signatureString = constructorSignature.asString() + val signatureString = constructorSignature.toString() return constructorCache.getOrPut(this to signatureString) { declaredConstructors .asSequence() @@ -171,12 +171,14 @@ public class ReflectiveClassInspector private constructor( } } + @OptIn(DelicateKotlinPoetApi::class) private fun Field.annotationSpecs(): List<AnnotationSpec> { return filterOutNullabilityAnnotations( declaredAnnotations.orEmpty().map { AnnotationSpec.get(it, includeDefaultValues = true) }, ) } + @OptIn(DelicateKotlinPoetApi::class) private fun Constructor<*>.annotationSpecs(): List<AnnotationSpec> { return filterOutNullabilityAnnotations( declaredAnnotations.orEmpty().map { AnnotationSpec.get(it, true) }, @@ -205,12 +207,14 @@ public class ReflectiveClassInspector private constructor( return jvmMethodModifiers } + @OptIn(DelicateKotlinPoetApi::class) private fun Method.annotationSpecs(): List<AnnotationSpec> { return filterOutNullabilityAnnotations( declaredAnnotations.orEmpty().map { AnnotationSpec.get(it, includeDefaultValues = true) }, ) } + @OptIn(DelicateKotlinPoetApi::class) private fun Parameter.annotationSpecs(): List<AnnotationSpec> { return filterOutNullabilityAnnotations( declaredAnnotations.map { AnnotationSpec.get(it, includeDefaultValues = true) }, @@ -262,7 +266,7 @@ public class ReflectiveClassInspector private constructor( } private fun JvmMethodSignature.isOverriddenIn(clazz: Class<*>): Boolean { - val signatureString = asString() + val signatureString = toString() val classPackage = clazz.`package`.name val interfaceMethods = clazz.interfaces.asSequence() .flatMap { it.methods.asSequence() } @@ -285,6 +289,7 @@ public class ReflectiveClassInspector private constructor( return lookupClass(className)?.lookupMethod(methodSignature) != null } + @OptIn(DelicateKotlinPoetApi::class) override fun containerData( declarationContainer: KmDeclarationContainer, className: ClassName, @@ -293,7 +298,7 @@ public class ReflectiveClassInspector private constructor( val targetClass = lookupClass(className) ?: error("No class found for: $className.") val isCompanionObject: Boolean = when (declarationContainer) { is KmClass -> { - declarationContainer.isCompanionObject + declarationContainer.kind == ClassKind.COMPANION_OBJECT } is KmPackage -> { false @@ -313,8 +318,7 @@ public class ReflectiveClassInspector private constructor( val propertyData = declarationContainer.properties .asSequence() - .filter { it.isDeclaration } - .filterNot { it.isSynthesized } + .filter { it.kind.isDeclaration } .associateWithTo(TreeMap(KM_PROPERTY_COMPARATOR)) { property -> val isJvmField = ClassInspectorUtil.computeIsJvmField( property = property, @@ -387,7 +391,7 @@ public class ReflectiveClassInspector private constructor( method?.methodData( clazz = targetClass, signature = getterSignature, - hasAnnotations = property.getterFlags.hasAnnotations, + hasAnnotations = property.getter.hasAnnotations, jvmInformationMethod = classIfCompanion.takeIf { it != targetClass } ?.lookupMethod(getterSignature) ?: method, ) @@ -399,7 +403,7 @@ public class ReflectiveClassInspector private constructor( method?.methodData( clazz = targetClass, signature = setterSignature, - hasAnnotations = property.setterFlags.hasAnnotations, + hasAnnotations = property.setter?.hasAnnotations ?: false, jvmInformationMethod = classIfCompanion.takeIf { it != targetClass } ?.lookupMethod(setterSignature) ?: method, knownIsOverride = getterData?.isOverride, @@ -408,7 +412,7 @@ public class ReflectiveClassInspector private constructor( } val annotations = mutableListOf<AnnotationSpec>() - if (property.flags.hasAnnotations) { + if (property.hasAnnotations) { property.syntheticMethodForAnnotations?.let { annotationsHolderSignature -> targetClass.lookupMethod(annotationsHolderSignature)?.let { method -> annotations += method.annotationSpecs() @@ -435,7 +439,7 @@ public class ReflectiveClassInspector private constructor( method?.methodData( clazz = targetClass, signature = signature, - hasAnnotations = kmFunction.flags.hasAnnotations, + hasAnnotations = kmFunction.hasAnnotations, jvmInformationMethod = classIfCompanion.takeIf { it != targetClass }?.lookupMethod(signature) ?: method, ) @@ -447,7 +451,7 @@ public class ReflectiveClassInspector private constructor( when (declarationContainer) { is KmClass -> { - val classAnnotations = if (declarationContainer.flags.hasAnnotations) { + val classAnnotations = if (declarationContainer.hasAnnotations) { ClassInspectorUtil.createAnnotations { addAll(targetClass.annotations.map { AnnotationSpec.get(it, includeDefaultValues = true) }) } @@ -456,7 +460,7 @@ public class ReflectiveClassInspector private constructor( } val constructorData = declarationContainer.constructors .associateWithTo(TreeMap(KM_CONSTRUCTOR_COMPARATOR)) { kmConstructor -> - if (declarationContainer.isAnnotation || declarationContainer.isValue) { + if (declarationContainer.kind == ClassKind.ANNOTATION_CLASS || declarationContainer.isValue) { // // Annotations are interfaces in reflection, but kotlin metadata will still report a // constructor signature @@ -470,7 +474,7 @@ public class ReflectiveClassInspector private constructor( val constructor = targetClass.lookupConstructor(signature) ?: error("No constructor $signature found in $targetClass.") ConstructorData( - annotations = if (kmConstructor.flags.hasAnnotations) { + annotations = if (kmConstructor.hasAnnotations) { constructor.annotationSpecs() } else { emptyList() diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/JvmModifier.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/JvmModifier.kt index f09e6add..079a0e9a 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/JvmModifier.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/JvmModifier.kt @@ -26,6 +26,7 @@ import com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview * This API is considered read-only and should not be implemented outside of KotlinPoet. */ @KotlinPoetMetadataPreview +@JvmDefaultWithCompatibility public interface JvmModifier { public fun annotationSpec(): AnnotationSpec? { return null diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KmTypes.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KmTypes.kt index cd12479c..23e793d0 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KmTypes.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KmTypes.kt @@ -26,10 +26,7 @@ import com.squareup.kotlinpoet.TypeVariableName import com.squareup.kotlinpoet.WildcardTypeName import com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil -import com.squareup.kotlinpoet.metadata.isNullable import com.squareup.kotlinpoet.metadata.isPrimary -import com.squareup.kotlinpoet.metadata.isReified -import com.squareup.kotlinpoet.metadata.isSuspend import com.squareup.kotlinpoet.tags.TypeAliasTag import kotlinx.metadata.KmClass import kotlinx.metadata.KmClassifier @@ -47,6 +44,9 @@ import kotlinx.metadata.KmVariance import kotlinx.metadata.KmVariance.IN import kotlinx.metadata.KmVariance.INVARIANT import kotlinx.metadata.KmVariance.OUT +import kotlinx.metadata.isNullable +import kotlinx.metadata.isReified +import kotlinx.metadata.isSuspend import kotlinx.metadata.jvm.annotations import kotlinx.metadata.jvm.signature @@ -251,7 +251,7 @@ internal val KM_FUNCTION_COMPARATOR = Comparator<KmFunction> { o1, o2 -> val signature1 = o1.signature val signature2 = o2.signature if (signature1 != null && signature2 != null) { - result = signature1.asString().compareTo(signature2.asString()) + result = signature1.toString().compareTo(signature2.toString()) if (result != 0) return@Comparator result } @@ -265,7 +265,7 @@ internal val KM_CONSTRUCTOR_COMPARATOR = Comparator<KmConstructor> { o1, o2 -> val signature1 = o1.signature val signature2 = o2.signature if (signature1 != null && signature2 != null) { - val result = signature1.asString().compareTo(signature2.asString()) + val result = signature1.toString().compareTo(signature2.toString()) if (result != 0) return@Comparator result } diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs.kt index 6c0730a6..88c7b25b 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecs.kt @@ -22,6 +22,7 @@ import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.AnnotationSpec.UseSiteTarget import com.squareup.kotlinpoet.AnnotationSpec.UseSiteTarget.FILE import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.DelicateKotlinPoetApi import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.FunSpec.Builder @@ -36,15 +37,12 @@ import com.squareup.kotlinpoet.KModifier.FINAL import com.squareup.kotlinpoet.KModifier.INFIX import com.squareup.kotlinpoet.KModifier.INLINE import com.squareup.kotlinpoet.KModifier.INNER -import com.squareup.kotlinpoet.KModifier.INTERNAL import com.squareup.kotlinpoet.KModifier.LATEINIT import com.squareup.kotlinpoet.KModifier.NOINLINE import com.squareup.kotlinpoet.KModifier.OPEN import com.squareup.kotlinpoet.KModifier.OPERATOR import com.squareup.kotlinpoet.KModifier.PRIVATE -import com.squareup.kotlinpoet.KModifier.PROTECTED import com.squareup.kotlinpoet.KModifier.PUBLIC -import com.squareup.kotlinpoet.KModifier.SEALED import com.squareup.kotlinpoet.KModifier.SUSPEND import com.squareup.kotlinpoet.KModifier.TAILREC import com.squareup.kotlinpoet.KModifier.VALUE @@ -57,58 +55,21 @@ import com.squareup.kotlinpoet.TypeSpec import com.squareup.kotlinpoet.UNIT import com.squareup.kotlinpoet.asClassName import com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview -import com.squareup.kotlinpoet.metadata.PropertyAccessorFlag -import com.squareup.kotlinpoet.metadata.PropertyAccessorFlag.IS_EXTERNAL -import com.squareup.kotlinpoet.metadata.PropertyAccessorFlag.IS_INLINE -import com.squareup.kotlinpoet.metadata.PropertyAccessorFlag.IS_NOT_DEFAULT import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.createAnnotations import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.createClassName import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.toTreeSet -import com.squareup.kotlinpoet.metadata.declaresDefaultValue -import com.squareup.kotlinpoet.metadata.hasAnnotations -import com.squareup.kotlinpoet.metadata.hasGetter -import com.squareup.kotlinpoet.metadata.hasSetter -import com.squareup.kotlinpoet.metadata.isAbstract import com.squareup.kotlinpoet.metadata.isAnnotation import com.squareup.kotlinpoet.metadata.isClass import com.squareup.kotlinpoet.metadata.isCompanionObject -import com.squareup.kotlinpoet.metadata.isConst -import com.squareup.kotlinpoet.metadata.isCrossInline -import com.squareup.kotlinpoet.metadata.isData import com.squareup.kotlinpoet.metadata.isDeclaration -import com.squareup.kotlinpoet.metadata.isDelegated -import com.squareup.kotlinpoet.metadata.isDelegation import com.squareup.kotlinpoet.metadata.isEnum -import com.squareup.kotlinpoet.metadata.isEnumEntry -import com.squareup.kotlinpoet.metadata.isExpect -import com.squareup.kotlinpoet.metadata.isExternal -import com.squareup.kotlinpoet.metadata.isFinal -import com.squareup.kotlinpoet.metadata.isFun -import com.squareup.kotlinpoet.metadata.isInfix -import com.squareup.kotlinpoet.metadata.isInline -import com.squareup.kotlinpoet.metadata.isInner import com.squareup.kotlinpoet.metadata.isInterface -import com.squareup.kotlinpoet.metadata.isInternal -import com.squareup.kotlinpoet.metadata.isLateinit -import com.squareup.kotlinpoet.metadata.isNoInline import com.squareup.kotlinpoet.metadata.isObject -import com.squareup.kotlinpoet.metadata.isOpen -import com.squareup.kotlinpoet.metadata.isOperator import com.squareup.kotlinpoet.metadata.isPrimary -import com.squareup.kotlinpoet.metadata.isPrivate -import com.squareup.kotlinpoet.metadata.isProtected -import com.squareup.kotlinpoet.metadata.isPublic -import com.squareup.kotlinpoet.metadata.isReified -import com.squareup.kotlinpoet.metadata.isSealed -import com.squareup.kotlinpoet.metadata.isSuspend -import com.squareup.kotlinpoet.metadata.isSynthesized -import com.squareup.kotlinpoet.metadata.isTailRec import com.squareup.kotlinpoet.metadata.isVal -import com.squareup.kotlinpoet.metadata.isValue -import com.squareup.kotlinpoet.metadata.isVar -import com.squareup.kotlinpoet.metadata.propertyAccessorFlags import com.squareup.kotlinpoet.metadata.specs.JvmMethodModifier.DEFAULT +import com.squareup.kotlinpoet.metadata.toKModifier import com.squareup.kotlinpoet.metadata.toKmClass import com.squareup.kotlinpoet.tag import java.util.Locale @@ -117,21 +78,49 @@ import javax.lang.model.element.ElementKind import javax.lang.model.element.PackageElement import javax.lang.model.element.TypeElement import kotlin.reflect.KClass -import kotlinx.metadata.Flags +import kotlinx.metadata.ClassKind import kotlinx.metadata.KmClass import kotlinx.metadata.KmClassifier import kotlinx.metadata.KmConstructor import kotlinx.metadata.KmFunction import kotlinx.metadata.KmPackage import kotlinx.metadata.KmProperty +import kotlinx.metadata.KmPropertyAccessorAttributes import kotlinx.metadata.KmType import kotlinx.metadata.KmTypeAlias import kotlinx.metadata.KmValueParameter +import kotlinx.metadata.Modality +import kotlinx.metadata.Visibility +import kotlinx.metadata.declaresDefaultValue +import kotlinx.metadata.hasAnnotations +import kotlinx.metadata.hasGetter +import kotlinx.metadata.hasSetter +import kotlinx.metadata.isConst +import kotlinx.metadata.isCrossinline +import kotlinx.metadata.isData +import kotlinx.metadata.isDelegated +import kotlinx.metadata.isExpect +import kotlinx.metadata.isExternal +import kotlinx.metadata.isFunInterface +import kotlinx.metadata.isInfix +import kotlinx.metadata.isInline +import kotlinx.metadata.isInner +import kotlinx.metadata.isLateinit +import kotlinx.metadata.isNoinline +import kotlinx.metadata.isOperator +import kotlinx.metadata.isReified +import kotlinx.metadata.isSuspend +import kotlinx.metadata.isTailrec +import kotlinx.metadata.isValue +import kotlinx.metadata.isVar import kotlinx.metadata.jvm.JvmMethodSignature import kotlinx.metadata.jvm.getterSignature -import kotlinx.metadata.jvm.jvmInternalName import kotlinx.metadata.jvm.setterSignature import kotlinx.metadata.jvm.signature +import kotlinx.metadata.jvm.toJvmInternalName +import kotlinx.metadata.kind +import kotlinx.metadata.modality +import kotlinx.metadata.visibility /** @return a [TypeSpec] ABI representation of this [KClass]. */ @KotlinPoetMetadataPreview @@ -140,13 +129,14 @@ public fun KClass<*>.toTypeSpec( ): TypeSpec = java.toTypeSpec(classInspector) /** @return a [TypeSpec] ABI representation of this [KClass]. */ +@OptIn(DelicateKotlinPoetApi::class) @KotlinPoetMetadataPreview public fun Class<*>.toTypeSpec( classInspector: ClassInspector? = null, ): TypeSpec = toKmClass().toTypeSpec(classInspector, asClassName()) /** @return a [TypeSpec] ABI representation of this [TypeElement]. */ -@Suppress("DEPRECATION") +@OptIn(DelicateKotlinPoetApi::class) @KotlinPoetMetadataPreview public fun TypeElement.toTypeSpec( classInspector: ClassInspector? = null, @@ -260,7 +250,7 @@ private fun KmClass.toTypeSpec( parentClassName: ClassName?, ): TypeSpec { val classTypeParamsResolver = typeParameters.toTypeParameterResolver() - val jvmInternalName = name.jvmInternalName + val jvmInternalName = name.toJvmInternalName() val simpleName = className.simpleName val classData = classInspector?.containerData(className, parentClassName) check(classData is ClassData?) { @@ -271,16 +261,17 @@ private fun KmClass.toTypeSpec( isAnnotation -> TypeSpec.annotationBuilder(simpleName) isCompanionObject -> TypeSpec.companionObjectBuilder(companionObjectName(simpleName)) isEnum -> TypeSpec.enumBuilder(simpleName) - isExpect -> TypeSpec.expectClassBuilder(simpleName) + isExpect -> TypeSpec.classBuilder(simpleName).addModifiers(EXPECT) isObject -> TypeSpec.objectBuilder(simpleName) isInterface -> { - if (classData?.declarationContainer?.isFun == true) { + if (classData?.declarationContainer?.isFunInterface == true) { TypeSpec.funInterfaceBuilder(simpleName) } else { TypeSpec.interfaceBuilder(simpleName) } } - isEnumEntry -> TypeSpec.anonymousClassBuilder() + + kind == ClassKind.ENUM_ENTRY -> TypeSpec.anonymousClassBuilder() else -> TypeSpec.classBuilder(simpleName) } @@ -290,7 +281,7 @@ private fun KmClass.toTypeSpec( } ?.let(builder::addAnnotations) - if (isEnum) { + if (kind == ClassKind.ENUM_CLASS) { enumEntries.forEach { entryName -> val typeSpec = if (classInspector != null) { val entry = classInspector.enumEntry(className, entryName) @@ -313,14 +304,13 @@ private fun KmClass.toTypeSpec( } } - if (!isEnumEntry) { - visibilityFrom(flags) { builder.addModifiers(it) } - builder.addModifiers( - *flags.modalities - .filterNot { it == FINAL } // Default - .filterNot { isInterface && it == ABSTRACT } // Abstract is a default on interfaces - .toTypedArray(), - ) + if (kind != ClassKind.ENUM_ENTRY) { + visibilityFrom(visibility) { builder.addModifiers(it) } + modality + .takeUnless { it == Modality.FINAL } // Default + ?.takeUnless { kind == ClassKind.INTERFACE && it == Modality.ABSTRACT } // Abstract is a default on interfaces + ?.let(Modality::toKModifier) + ?.let { builder.addModifiers(it) } if (isData) { builder.addModifiers(DATA) } @@ -387,8 +377,7 @@ private fun KmClass.toTypeSpec( builder.addProperties( properties .asSequence() - .filter { it.isDeclaration } - .filterNot { it.isSynthesized } + .filter { it.kind.isDeclaration } .map { it to classData?.properties?.get(it) } .map { (property, propertyData) -> property.toPropertySpec( @@ -419,9 +408,7 @@ private fun KmClass.toTypeSpec( builder.addFunctions( functions .asSequence() - .filter { it.isDeclaration } - .filterNot { it.isDelegation } - .filterNot { it.isSynthesized } + .filter { it.kind.isDeclaration } .map { it to classData?.methods?.get(it) } .map { (func, methodData) -> func.toFunSpec(classTypeParamsResolver, classInspector, classData, methodData) @@ -431,11 +418,11 @@ private fun KmClass.toTypeSpec( fun isKotlinDefaultInterfaceMethod(): Boolean { classInspector?.let { handler -> func.signature?.let { signature -> - val suffix = signature.desc.removePrefix("(") + val suffix = signature.descriptor.removePrefix("(") return handler.methodExists( className.nestedClass("DefaultImpls"), signature.copy( - desc = "(L$jvmInternalName;$suffix", + descriptor = "(L$jvmInternalName;$suffix", ), ) } @@ -504,7 +491,7 @@ private fun KmConstructor.toFunSpec( return FunSpec.constructorBuilder() .apply { addAnnotations(constructorData?.allAnnotations.orEmpty()) - visibilityFrom(flags) { addModifiers(it) } + visibilityFrom(visibility) { addModifiers(it) } addParameters( this@toFunSpec.valueParameters.mapIndexed { index, param -> param.toParameterSpec( @@ -516,7 +503,7 @@ private fun KmConstructor.toFunSpec( ) }, ) - if (!isPrimary) { + if (!this@toFunSpec.isPrimary) { // TODO How do we know when to add callSuperConstructor()? } } @@ -563,14 +550,14 @@ private fun KmFunction.toFunSpec( return FunSpec.builder(name) .apply { addAnnotations(annotations) - visibilityFrom(flags) { addModifiers(it) } + visibilityFrom(visibility) { addModifiers(it) } val isOverride = methodData?.isOverride == true - addModifiers( - flags.modalities - .filterNot { it == FINAL && !isOverride } // Final is the default - .filterNot { it == OPEN && isOverride } // Overrides are implicitly open - .filterNot { it == OPEN && isInInterface }, // interface methods are implicitly open - ) + modality + .takeUnless { it == Modality.FINAL && !isOverride } // Final is the default + ?.takeUnless { it == Modality.OPEN && isOverride } // Overrides are implicitly open + ?.takeUnless { it == Modality.OPEN && isInInterface } // interface methods are implicitly open + ?.let(Modality::toKModifier) + ?.let { addModifiers(it) } if (valueParameters.isNotEmpty()) { addParameters( valueParameters.mapIndexed { index, param -> @@ -597,7 +584,7 @@ private fun KmFunction.toFunSpec( if (isInline) { addModifiers(INLINE) } - if (isTailRec) { + if (isTailrec) { addModifiers(TAILREC) } if (isExternal) { @@ -612,7 +599,7 @@ private fun KmFunction.toFunSpec( val returnTypeName = this@toFunSpec.returnType.toTypeName(typeParamsResolver) if (returnTypeName != UNIT) { returns(returnTypeName) - if (!flags.isAbstract) { + if (modality != Modality.ABSTRACT) { addStatement(NOT_IMPLEMENTED) } } @@ -627,17 +614,17 @@ private fun KmValueParameter.toParameterSpec( typeParamResolver: TypeParameterResolver, annotations: Collection<AnnotationSpec>, ): ParameterSpec { - val paramType = varargElementType ?: type ?: throw IllegalStateException("No argument type!") + val paramType = varargElementType ?: type return ParameterSpec.builder(name, paramType.toTypeName(typeParamResolver)) .apply { addAnnotations(annotations) if (varargElementType != null) { addModifiers(VARARG) } - if (isCrossInline) { + if (isCrossinline) { addModifiers(CROSSINLINE) } - if (isNoInline) { + if (isNoinline) { addModifiers(NOINLINE) } if (declaresDefaultValue) { @@ -664,8 +651,7 @@ private fun KmProperty.toPropertySpec( if (hasGetter) { getterSignature?.let { getterSignature -> if (!containerData.isInterface && - !flags.isOpen && - !flags.isAbstract + modality != Modality.OPEN && modality != Modality.ABSTRACT ) { // Infer if JvmName was used // We skip interface types or open/abstract properties because they can't have @JvmName. @@ -694,8 +680,7 @@ private fun KmProperty.toPropertySpec( !containerData.declarationContainer.isAnnotation && !containerData.declarationContainer.isInterface && classInspector?.supportsNonRuntimeRetainedAnnotations == false && - !flags.isOpen && - !flags.isAbstract + modality != Modality.OPEN && modality != Modality.ABSTRACT ) { // Infer if JvmName was used // We skip annotation types for this because they can't have vars. @@ -732,14 +717,14 @@ private fun KmProperty.toPropertySpec( } .toTreeSet() addAnnotations(finalAnnotations) - visibilityFrom(flags) { addModifiers(it) } - addModifiers( - flags.modalities - .filterNot { it == FINAL && !isOverride } // Final is the default - .filterNot { it == OPEN && isOverride } // Overrides are implicitly open - .filterNot { it == OPEN && isInInterface } // Interface properties implicitly open - .filterNot { it == ABSTRACT && isInInterface }, // Interface properties implicitly abstract - ) + visibilityFrom(visibility) { addModifiers(it) } + modality + .takeUnless { it == Modality.FINAL && !isOverride } // Final is the default + ?.takeUnless { it == Modality.OPEN && isOverride } // Overrides are implicitly open + ?.takeUnless { it == Modality.OPEN && isInInterface } // Interface properties implicitly open + ?.takeUnless { it == Modality.ABSTRACT && isInInterface } // Interface properties implicitly abstract + ?.let(Modality::toKModifier) + ?.let { addModifiers(it) } if (isOverride) { addModifiers(KModifier.OVERRIDE) } @@ -782,7 +767,7 @@ private fun KmProperty.toPropertySpec( constant != null -> initializer(constant) isConstructorParam -> initializer(name) returnTypeName.isNullable -> initializer("null") - flags.isAbstract || isInInterface -> { + modality == Modality.ABSTRACT || isInInterface -> { // No-op, don't emit an initializer for abstract or interface properties } else -> initializer(NOT_IMPLEMENTED) @@ -792,16 +777,16 @@ private fun KmProperty.toPropertySpec( // since the delegate handles it // vals with initialized constants have a getter in bytecode but not a body in kotlin source val modifierSet = modifiers.toSet() - if (hasGetter && !isDelegated && !flags.isAbstract) { + if (hasGetter && !isDelegated && modality != Modality.ABSTRACT) { propertyAccessor( modifierSet, - getterFlags, + getter, FunSpec.getterBuilder().addStatement(NOT_IMPLEMENTED), isOverride, )?.let(::getter) } - if (hasSetter && !isDelegated && !flags.isAbstract) { - propertyAccessor(modifierSet, setterFlags, FunSpec.setterBuilder(), isOverride)?.let(::setter) + if (hasSetter && !isDelegated && modality != Modality.ABSTRACT) { + propertyAccessor(modifierSet, setter!!, FunSpec.setterBuilder(), isOverride)?.let(::setter) } } .tag(this) @@ -811,26 +796,34 @@ private fun KmProperty.toPropertySpec( @KotlinPoetMetadataPreview private fun propertyAccessor( propertyModifiers: Set<KModifier>, - flags: Flags, + attrs: KmPropertyAccessorAttributes, functionBuilder: Builder, isOverride: Boolean, ): FunSpec? { - val visibility = flags.visibility + val visibility = attrs.visibility.toKModifier() if (visibility == PUBLIC || visibility !in propertyModifiers) { // This is redundant and just a stub // For annotations on this accessor, we declare them on the property with site target instead return null } - val modalities = flags.modalities - .filterNot { it == FINAL && !isOverride } - .filterNot { it == OPEN && isOverride } - val propertyAccessorFlags = flags.propertyAccessorFlags - return if (visibility != PUBLIC || modalities.isNotEmpty() || propertyAccessorFlags.isNotEmpty()) { + val modality = attrs.modality + .takeUnless { it == Modality.FINAL && !isOverride } + .takeUnless { it == Modality.OPEN && isOverride } + + val localModifiers = buildList { + if (attrs.isExternal) { + add(EXTERNAL) + } + if (attrs.isInline) { + add(INLINE) + } + } + return if (modality != null || localModifiers.isNotEmpty()) { functionBuilder .apply { addModifiers(visibility) - addModifiers(modalities) - addModifiers(*propertyAccessorFlags.toKModifiersArray()) + modality?.let { addModifiers(it.toKModifier()) } + addModifiers(localModifiers) } .build() } else { @@ -838,25 +831,15 @@ private fun propertyAccessor( } } -private fun Set<PropertyAccessorFlag>.toKModifiersArray(): Array<KModifier> { - return mapNotNull { - when (it) { - IS_EXTERNAL -> EXTERNAL - IS_INLINE -> INLINE - IS_NOT_DEFAULT -> null // Gracefully skip over these - } - }.toTypedArray() -} - @KotlinPoetMetadataPreview private fun KmTypeAlias.toTypeAliasSpec(): TypeAliasSpec { val typeParamResolver = typeParameters.toTypeParameterResolver() return TypeAliasSpec.builder(name, underlyingType.toTypeName(typeParamResolver)) .apply { - visibilityFrom(flags) { + visibilityFrom(visibility) { addModifiers(it) } - if (flags.hasAnnotations) { + if (hasAnnotations) { val annotationSpecs = this@toTypeAliasSpec.annotations .map { it.toAnnotationSpec() } addAnnotations(annotationSpecs) @@ -886,21 +869,8 @@ private val JAVA_ANNOTATION_ANNOTATIONS = setOf( ) @KotlinPoetMetadataPreview -private val Flags.visibility: KModifier - get() = when { - isInternal -> INTERNAL - isPrivate -> PRIVATE - isProtected -> PROTECTED - isPublic -> PUBLIC - else -> { - // IS_PRIVATE_TO_THIS or IS_LOCAL, so just default to public - PUBLIC - } - } - -@KotlinPoetMetadataPreview -private fun visibilityFrom(flags: Flags, body: (KModifier) -> Unit) { - val modifierVisibility = flags.visibility +private fun visibilityFrom(visibility: Visibility, body: (KModifier) -> Unit) { + val modifierVisibility = visibility.toKModifier() if (modifierVisibility != PUBLIC) { body(modifierVisibility) } @@ -910,23 +880,6 @@ private fun String.safeCapitalize(locale: Locale): String { return replaceFirstChar { if (it.isLowerCase()) it.titlecase(locale) else it.toString() } } -@KotlinPoetMetadataPreview -private val Flags.modalities: Set<KModifier> - get() = setOf { - if (isFinal) { - add(FINAL) - } - if (isOpen) { - add(OPEN) - } - if (isAbstract) { - add(ABSTRACT) - } - if (isSealed) { - add(SEALED) - } - } - private inline fun <E> setOf(body: MutableSet<E>.() -> Unit): Set<E> { return mutableSetOf<E>().apply(body).toSet() } @@ -934,7 +887,7 @@ private inline fun <E> setOf(body: MutableSet<E>.() -> Unit): Set<E> { private val METADATA = Metadata::class.asClassName() @Suppress("DEPRECATION") -private val JVM_DEFAULT = JvmDefault::class.asClassName() +private val JVM_DEFAULT = ClassName("kotlin.jvm", "JvmDefault") private val JVM_STATIC = JvmStatic::class.asClassName() @PublishedApi diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/kmAnnotations.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/kmAnnotations.kt index f6b44670..671147f7 100644 --- a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/kmAnnotations.kt +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/kmAnnotations.kt @@ -15,8 +15,10 @@ */ package com.squareup.kotlinpoet.metadata.specs +import com.squareup.kotlinpoet.ARRAY import com.squareup.kotlinpoet.AnnotationSpec import com.squareup.kotlinpoet.CodeBlock +import com.squareup.kotlinpoet.buildCodeBlock import com.squareup.kotlinpoet.joinToCode import com.squareup.kotlinpoet.metadata.KotlinPoetMetadataPreview import com.squareup.kotlinpoet.metadata.classinspectors.ClassInspectorUtil.createClassName @@ -75,5 +77,10 @@ internal fun KmAnnotationArgument.toCodeBlock(): CodeBlock { is EnumValue -> CodeBlock.of("%T.%L", createClassName(enumClassName), enumEntryName) is AnnotationValue -> CodeBlock.of("%L", annotation.toAnnotationSpec()) is ArrayValue -> elements.map { it.toCodeBlock() }.joinToCode(", ", "[", "]") + is KmAnnotationArgument.ArrayKClassValue -> buildCodeBlock { + repeat(arrayDimensionCount) { add("%T<", ARRAY) } + add("%T::class", createClassName(className)) + repeat(arrayDimensionCount) { add(">") } + } } } diff --git a/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/util.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/util.kt new file mode 100644 index 00000000..ab30c8ee --- /dev/null +++ b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/util.kt @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2019 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.kotlinpoet.metadata + +import com.squareup.kotlinpoet.KModifier +import kotlinx.metadata.ClassKind +import kotlinx.metadata.KmClass +import kotlinx.metadata.KmConstructor +import kotlinx.metadata.KmProperty +import kotlinx.metadata.MemberKind +import kotlinx.metadata.Modality +import kotlinx.metadata.Visibility +import kotlinx.metadata.isSecondary +import kotlinx.metadata.isVar +import kotlinx.metadata.kind + +internal val KmClass.isObject: Boolean + get() = kind == ClassKind.OBJECT + +internal val KmClass.isCompanionObject: Boolean + get() = kind == ClassKind.COMPANION_OBJECT + +internal val KmClass.isClass: Boolean + get() = kind == ClassKind.CLASS + +internal val KmClass.isAnnotation: Boolean + get() = kind == ClassKind.ANNOTATION_CLASS + +internal val KmClass.isEnum: Boolean + get() = kind == ClassKind.ENUM_CLASS + +internal val KmClass.isInterface: Boolean + get() = kind == ClassKind.INTERFACE + +internal val KmConstructor.isPrimary: Boolean + get() = !isSecondary + +internal val KmProperty.isVal: Boolean + get() = !isVar + +internal fun Modality.toKModifier(): KModifier = when (this) { + Modality.FINAL -> KModifier.FINAL + Modality.OPEN -> KModifier.OPEN + Modality.ABSTRACT -> KModifier.ABSTRACT + Modality.SEALED -> KModifier.SEALED +} + +internal fun Visibility.toKModifier(): KModifier = when (this) { + Visibility.INTERNAL -> KModifier.INTERNAL + Visibility.PRIVATE -> KModifier.PRIVATE + Visibility.PROTECTED -> KModifier.PROTECTED + Visibility.PUBLIC -> KModifier.PUBLIC + Visibility.PRIVATE_TO_THIS, + Visibility.LOCAL, + -> { + // Default to public + KModifier.PUBLIC + } +} + +internal val MemberKind.isDeclaration: Boolean get() = this == MemberKind.DECLARATION diff --git a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/FacadeFileTest.kt b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/FacadeFileTest.kt index adea853f..e31c0cc6 100644 --- a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/FacadeFileTest.kt +++ b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/FacadeFileTest.kt @@ -50,7 +50,6 @@ class FacadeFileTest : MultiClassInspectorTest() { import kotlin.Int import kotlin.Long import kotlin.String - import kotlin.Unit import kotlin.collections.List import kotlin.jvm.JvmField import kotlin.jvm.JvmName @@ -58,21 +57,21 @@ class FacadeFileTest : MultiClassInspectorTest() { import kotlin.jvm.Synchronized @JvmName(name = "jvmStaticFunction") - public fun jvmNameFunction(): Unit { + public fun jvmNameFunction() { } public fun jvmOverloads( param1: String, optionalParam2: String = throw NotImplementedError("Stub!"), nullableParam3: String? = throw NotImplementedError("Stub!"), - ): Unit { + ) { } - public fun regularFun(): Unit { + public fun regularFun() { } @Synchronized - public fun synchronizedFun(): Unit { + public fun synchronizedFun() { } public val BINARY_PROP: Int = 11 @@ -186,7 +185,6 @@ class FacadeFileTest : MultiClassInspectorTest() { import kotlin.Int import kotlin.Long import kotlin.String - import kotlin.Unit import kotlin.collections.List import kotlin.jvm.JvmName import kotlin.jvm.JvmOverloads @@ -194,7 +192,7 @@ class FacadeFileTest : MultiClassInspectorTest() { import kotlin.jvm.Synchronized @JvmName(name = "jvmStaticFunction") - public fun jvmNameFunction(): Unit { + public fun jvmNameFunction() { } @JvmOverloads @@ -202,14 +200,14 @@ class FacadeFileTest : MultiClassInspectorTest() { param1: String, optionalParam2: String = throw NotImplementedError("Stub!"), nullableParam3: String? = throw NotImplementedError("Stub!"), - ): Unit { + ) { } - public fun regularFun(): Unit { + public fun regularFun() { } @Synchronized - public fun synchronizedFun(): Unit { + public fun synchronizedFun() { } public val BINARY_PROP: Int = throw NotImplementedError("Stub!") diff --git a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/KmAnnotationsTest.kt b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/KmAnnotationsTest.kt index c7928b4e..a2ad9d18 100644 --- a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/KmAnnotationsTest.kt +++ b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/KmAnnotationsTest.kt @@ -209,7 +209,7 @@ class KmAnnotationsTest { @Test fun kClassValue() { val annotation = KmAnnotation( "test/KClassValueAnnotation", - mapOf("value" to KClassValue("test/OtherClass", 0)), + mapOf("value" to KClassValue("test/OtherClass")), ) assertThat(annotation.toAnnotationSpec().toString()).isEqualTo( """ diff --git a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecsTest.kt b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecsTest.kt index 9198dbcb..2dd54bbf 100644 --- a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecsTest.kt +++ b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/KotlinPoetMetadataSpecsTest.kt @@ -15,7 +15,6 @@ */ @file:OptIn(KotlinPoetMetadataPreview::class) @file:Suppress( - "DEPRECATION", "NOTHING_TO_INLINE", "RedundantSuspendModifier", "RedundantUnitReturnType", @@ -264,13 +263,13 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public class SuspendTypes() { public val testProp: suspend (kotlin.Int, kotlin.Long) -> kotlin.String = throw NotImplementedError("Stub!") - public suspend fun testComplexSuspendFun(body: suspend (kotlin.Int, suspend (kotlin.Long) -> kotlin.String) -> kotlin.String): kotlin.Unit { + public suspend fun testComplexSuspendFun(body: suspend (kotlin.Int, suspend (kotlin.Long) -> kotlin.String) -> kotlin.String) { } - public fun testFun(body: suspend (kotlin.Int, kotlin.Long) -> kotlin.String): kotlin.Unit { + public fun testFun(body: suspend (kotlin.Int, kotlin.Long) -> kotlin.String) { } - public suspend fun testSuspendFun(param1: kotlin.String): kotlin.Unit { + public suspend fun testSuspendFun(param1: kotlin.String) { } } """.trimIndent(), @@ -297,10 +296,10 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(typeSpec.trimmedToString()).isEqualTo( """ public class Parameters() { - public inline fun hasDefault(param1: kotlin.String = throw NotImplementedError("Stub!")): kotlin.Unit { + public inline fun hasDefault(param1: kotlin.String = throw NotImplementedError("Stub!")) { } - public inline fun `inline`(crossinline param1: () -> kotlin.String): kotlin.Unit { + public inline fun `inline`(crossinline param1: () -> kotlin.String) { } public inline fun `noinline`(noinline param1: () -> kotlin.String): kotlin.String = throw NotImplementedError("Stub!") @@ -328,13 +327,13 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(typeSpec.trimmedToString()).isEqualTo( """ public class LambdaReceiver() { - public fun lambdaReceiver(block: kotlin.String.() -> kotlin.Unit): kotlin.Unit { + public fun lambdaReceiver(block: kotlin.String.() -> kotlin.Unit) { } - public fun lambdaReceiver2(block: kotlin.String.(kotlin.Int) -> kotlin.Unit): kotlin.Unit { + public fun lambdaReceiver2(block: kotlin.String.(kotlin.Int) -> kotlin.Unit) { } - public fun lambdaReceiver3(block: kotlin.String.(kotlin.Int, kotlin.String) -> kotlin.Unit): kotlin.Unit { + public fun lambdaReceiver3(block: kotlin.String.(kotlin.Int, kotlin.String) -> kotlin.Unit) { } } """.trimIndent(), @@ -369,21 +368,6 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { } @Test - fun inlineClass() { - val typeSpec = InlineClass::class.toTypeSpecWithTestHandler() - - //language=kotlin - assertThat(typeSpec.trimmedToString()).isEqualTo( - """ - @kotlin.jvm.JvmInline - public value class InlineClass( - public val `value`: kotlin.String, - ) - """.trimIndent(), - ) - } - - @Test fun valueClass() { val typeSpec = ValueClass::class.toTypeSpecWithTestHandler() @@ -406,7 +390,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(typeSpec.trimmedToString()).isEqualTo( """ public class FunctionsReferencingTypeParameters<T>() { - public fun test(`param`: T): kotlin.Unit { + public fun test(`param`: T) { } } """.trimIndent(), @@ -426,14 +410,14 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(typeSpec.trimmedToString()).isEqualTo( """ public abstract class OverriddenThings() : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.OverriddenThingsBase(), com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.OverriddenThingsInterface { - public override var openProp: kotlin.String = throw NotImplementedError("Stub!") + override var openProp: kotlin.String = throw NotImplementedError("Stub!") - public override var openPropInterface: kotlin.String = throw NotImplementedError("Stub!") + override var openPropInterface: kotlin.String = throw NotImplementedError("Stub!") - public override fun openFunction(): kotlin.Unit { + override fun openFunction() { } - public override fun openFunctionInterface(): kotlin.Unit { + override fun openFunctionInterface() { } } """.trimIndent(), @@ -551,13 +535,13 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public val `value`: kotlin.String, ) { FOO { - public override fun toString(): kotlin.String = throw NotImplementedError("Stub!") + override fun toString(): kotlin.String = throw NotImplementedError("Stub!") }, BAR { - public override fun toString(): kotlin.String = throw NotImplementedError("Stub!") + override fun toString(): kotlin.String = throw NotImplementedError("Stub!") }, BAZ { - public override fun toString(): kotlin.String = throw NotImplementedError("Stub!") + override fun toString(): kotlin.String = throw NotImplementedError("Stub!") }, ; } @@ -616,14 +600,14 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public val `value`: kotlin.String, ) { FOO { - public override fun toString(): kotlin.String = throw NotImplementedError("Stub!") + override fun toString(): kotlin.String = throw NotImplementedError("Stub!") }, @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.FieldAnnotation BAR { - public override fun toString(): kotlin.String = throw NotImplementedError("Stub!") + override fun toString(): kotlin.String = throw NotImplementedError("Stub!") }, BAZ { - public override fun toString(): kotlin.String = throw NotImplementedError("Stub!") + override fun toString(): kotlin.String = throw NotImplementedError("Stub!") }, ; } @@ -661,22 +645,18 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public interface TestInterface { public fun complex(input: kotlin.String, input2: kotlin.String = throw NotImplementedError("Stub!")): kotlin.String = throw NotImplementedError("Stub!") - public fun hasDefault(): kotlin.Unit { + public fun hasDefault() { } public fun hasDefaultMultiParam(input: kotlin.String, input2: kotlin.String): kotlin.String = throw NotImplementedError("Stub!") public fun hasDefaultSingleParam(input: kotlin.String): kotlin.String = throw NotImplementedError("Stub!") - @kotlin.jvm.JvmDefault - public fun hasJvmDefault(): kotlin.Unit { - } - - public fun noDefault(): kotlin.Unit + public fun noDefault() - public fun noDefaultWithInput(input: kotlin.String): kotlin.Unit + public fun noDefaultWithInput(input: kotlin.String) - public fun noDefaultWithInputDefault(input: kotlin.String = throw NotImplementedError("Stub!")): kotlin.Unit + public fun noDefaultWithInputDefault(input: kotlin.String = throw NotImplementedError("Stub!")) } """.trimIndent(), ) @@ -687,14 +667,10 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(subInterfaceSpec.trimmedToString()).isEqualTo( """ public interface SubInterface : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TestInterface { - public override fun hasDefault(): kotlin.Unit { - } - - @kotlin.jvm.JvmDefault - public override fun hasJvmDefault(): kotlin.Unit { + override fun hasDefault() { } - public fun subInterfaceFunction(): kotlin.Unit { + public fun subInterfaceFunction() { } } """.trimIndent(), @@ -706,13 +682,13 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(implSpec.trimmedToString()).isEqualTo( """ public class TestSubInterfaceImpl() : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.SubInterface { - public override fun noDefault(): kotlin.Unit { + override fun noDefault() { } - public override fun noDefaultWithInput(input: kotlin.String): kotlin.Unit { + override fun noDefaultWithInput(input: kotlin.String) { } - public override fun noDefaultWithInputDefault(input: kotlin.String): kotlin.Unit { + override fun noDefaultWithInputDefault(input: kotlin.String) { } } """.trimIndent(), @@ -727,10 +703,6 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { fun noDefaultWithInputDefault(input: String = "") - @JvmDefault - fun hasJvmDefault() { - } - fun hasDefault() { } @@ -751,11 +723,6 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { fun subInterfaceFunction() { } - @JvmDefault - override fun hasJvmDefault() { - super.hasJvmDefault() - } - override fun hasDefault() { super.hasDefault() } @@ -838,19 +805,19 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(typeSpec.trimmedToString()).isEqualTo( """ public class GenericClass<T>() { - public fun <T> functionAlsoWithT(`param`: T): kotlin.Unit { + public fun <T> functionAlsoWithT(`param`: T) { } - public fun <R> functionWithADifferentType(`param`: R): kotlin.Unit { + public fun <R> functionWithADifferentType(`param`: R) { } - public fun functionWithT(`param`: T): kotlin.Unit { + public fun functionWithT(`param`: T) { } /** * Note: Since this is a synthetic function, some JVM information (annotations, modifiers) may be missing. */ - public inline fun <reified T> `reified`(`param`: T): kotlin.Unit { + public inline fun <reified T> `reified`(`param`: T) { } } """.trimIndent(), @@ -925,7 +892,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public constructor(`value`: kotlin.String) @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.FunctionAnnotation - public fun function(): kotlin.Unit { + public fun function() { } } """.trimIndent(), @@ -1226,7 +1193,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public var volatileProp: kotlin.String? = null @kotlin.jvm.Synchronized - public fun synchronizedFun(): kotlin.Unit { + public fun synchronizedFun() { } } """.trimIndent(), @@ -1238,11 +1205,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(interfaceSpec.trimmedToString()).isEqualTo( """ public interface JvmAnnotationsInterface { - @kotlin.jvm.JvmDefault - public fun defaultMethod(): kotlin.Unit { - } - - public fun notDefaultMethod(): kotlin.Unit + public fun notDefaultMethod() } """.trimIndent(), ) @@ -1263,9 +1226,6 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { } interface JvmAnnotationsInterface { - @JvmDefault - fun defaultMethod() { - } fun notDefaultMethod() } @@ -1317,7 +1277,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public var propertySet: kotlin.String? = null @kotlin.jvm.JvmName(name = "jvmFunction") - public fun function(): kotlin.Unit { + public fun function() { } public interface InterfaceWithJvmName { @@ -1328,7 +1288,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { @kotlin.jvm.JvmName(name = "jvmStaticFunction") @kotlin.jvm.JvmStatic - public fun staticFunction(): kotlin.Unit { + public fun staticFunction() { } } } @@ -1364,7 +1324,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public var propertySet: kotlin.String? = null @kotlin.jvm.JvmName(name = "jvmFunction") - public fun function(): kotlin.Unit { + public fun function() { } public interface InterfaceWithJvmName { @@ -1375,7 +1335,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { @kotlin.jvm.JvmName(name = "jvmStaticFunction") @kotlin.jvm.JvmStatic - public fun staticFunction(): kotlin.Unit { + public fun staticFunction() { } } } @@ -1439,7 +1399,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { param1: kotlin.String, optionalParam2: kotlin.String = throw NotImplementedError("Stub!"), nullableParam3: kotlin.String? = throw NotImplementedError("Stub!"), - ): kotlin.Unit { + ) { } } """.trimIndent(), @@ -1573,7 +1533,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { * Note: Since this is a synthetic function, some JVM information (annotations, modifiers) may be missing. */ @kotlin.jvm.JvmSynthetic - public fun function(): kotlin.Unit { + public fun function() { } public interface InterfaceWithJvmName { @@ -1581,7 +1541,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { * Note: Since this is a synthetic function, some JVM information (annotations, modifiers) may be missing. */ @kotlin.jvm.JvmSynthetic - public fun interfaceFunction(): kotlin.Unit + public fun interfaceFunction() public companion object { @get:kotlin.jvm.JvmSynthetic @@ -1593,7 +1553,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { */ @kotlin.jvm.JvmStatic @kotlin.jvm.JvmSynthetic - public fun staticFunction(): kotlin.Unit { + public fun staticFunction() { } } } @@ -1638,7 +1598,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { * Note: Since this is a synthetic function, some JVM information (annotations, modifiers) may be missing. */ @kotlin.jvm.JvmSynthetic - public fun function(): kotlin.Unit { + public fun function() { } public interface InterfaceWithJvmName { @@ -1646,7 +1606,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { * Note: Since this is a synthetic function, some JVM information (annotations, modifiers) may be missing. */ @kotlin.jvm.JvmSynthetic - public fun interfaceFunction(): kotlin.Unit + public fun interfaceFunction() public companion object { @get:kotlin.jvm.JvmSynthetic @@ -1657,7 +1617,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { * Note: Since this is a synthetic function, some JVM information (annotations, modifiers) may be missing. */ @kotlin.jvm.JvmSynthetic - public fun staticFunction(): kotlin.Unit { + public fun staticFunction() { } } } @@ -1728,7 +1688,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public var setterThrows: kotlin.String? = null @kotlin.jvm.Throws(exceptionClasses = [java.lang.IllegalStateException::class]) - public fun testFunction(): kotlin.Unit { + public fun testFunction() { } } """.trimIndent(), @@ -1884,7 +1844,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.CustomAnnotation(name = "2") param2: kotlin.String, ) { - public fun function(@com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.CustomAnnotation(name = "woo") param1: kotlin.String): kotlin.Unit { + public fun function(@com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.CustomAnnotation(name = "woo") param1: kotlin.String) { } } """.trimIndent(), @@ -1908,7 +1868,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.CustomAnnotation(name = "2") param2: kotlin.String, ) { - public fun function(@com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.CustomAnnotation(name = "woo") param1: kotlin.String): kotlin.Unit { + public fun function(@com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.CustomAnnotation(name = "woo") param1: kotlin.String) { } } """.trimIndent(), @@ -1983,7 +1943,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public class TypeAnnotations() { public val foo: kotlin.collections.List<@com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation kotlin.String> = throw NotImplementedError("Stub!") - public fun <T> bar(input: @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation kotlin.String, input2: @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation (@com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation kotlin.Int) -> @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation kotlin.String): kotlin.Unit { + public fun <T> bar(input: @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation kotlin.String, input2: @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation (@com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation kotlin.Int) -> @com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TypeAnnotation kotlin.String) { } } """.trimIndent(), @@ -2011,7 +1971,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(typeSpec.trimmedToString()).isEqualTo( """ public class Asset<A : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.Asset<A>>() { - public fun <D : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.Asset<D>, C : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.Asset<A>> function(): kotlin.Unit { + public fun <D : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.Asset<D>, C : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.Asset<A>> function() { } public class AssetIn<in C : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.Asset.AssetIn<C>>() @@ -2043,11 +2003,11 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public abstract val foo: kotlin.String - public abstract fun bar(): kotlin.Unit + public abstract fun bar() public abstract fun barWithReturn(): kotlin.String - public fun fuz(): kotlin.Unit { + public fun fuz() { } public fun fuzWithReturn(): kotlin.String = throw NotImplementedError("Stub!") @@ -2100,17 +2060,17 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { public abstract class AbstractModalities() : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.ModalitiesInterface { public val implicitFinalProp: kotlin.String? = null - public override val interfaceProp: kotlin.String? = null + override val interfaceProp: kotlin.String? = null public open val openProp: kotlin.String? = null - public fun implicitFinalFun(): kotlin.Unit { + public fun implicitFinalFun() { } - public override fun interfaceFun(): kotlin.Unit { + override fun interfaceFun() { } - public open fun openFun(): kotlin.Unit { + public open fun openFun() { } } """.trimIndent(), @@ -2122,9 +2082,9 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(finalAbstractModalities.trimmedToString()).isEqualTo( """ public abstract class FinalAbstractModalities() : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.ModalitiesInterface { - public final override val interfaceProp: kotlin.String? = null + final override val interfaceProp: kotlin.String? = null - public final override fun interfaceFun(): kotlin.Unit { + final override fun interfaceFun() { } } """.trimIndent(), @@ -2136,14 +2096,14 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(modalities.trimmedToString()).isEqualTo( """ public class Modalities() : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.AbstractModalities() { - public override val interfaceProp: kotlin.String? = null + override val interfaceProp: kotlin.String? = null - public override val openProp: kotlin.String? = null + override val openProp: kotlin.String? = null - public override fun interfaceFun(): kotlin.Unit { + override fun interfaceFun() { } - public override fun openFun(): kotlin.Unit { + override fun openFun() { } } """.trimIndent(), @@ -2188,7 +2148,7 @@ class KotlinPoetMetadataSpecsTest : MultiClassInspectorTest() { assertThat(funInterface.trimmedToString()).isEqualTo( """ public fun interface FunInterface { - public fun example(): kotlin.Unit + public fun example() } """.trimIndent(), ) @@ -2240,8 +2200,6 @@ private fun TypeSpec.trimmedToString(): String { return toString().trim() } -inline class InlineClass(val value: String) - @JvmInline value class ValueClass(val value: String) diff --git a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/MultiClassInspectorTest.kt b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/MultiClassInspectorTest.kt index cb7c21d6..6bb9192a 100644 --- a/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/MultiClassInspectorTest.kt +++ b/interop/kotlinx-metadata/src/test/kotlin/com/squareup/kotlinpoet/metadata/specs/MultiClassInspectorTest.kt @@ -113,7 +113,7 @@ abstract class MultiClassInspectorTest { protected fun KClass<*>.toFileSpecWithTestHandler(): FileSpec { val classInspector = classInspectorType.create(this@MultiClassInspectorTest) return java.annotations.filterIsInstance<Metadata>().first().toKotlinClassMetadata<FileFacade>() - .toKmPackage() + .kmPackage .toFileSpec(classInspector, asClassName()) } } diff --git a/interop/ksp/api/ksp.api b/interop/ksp/api/ksp.api index cc8cb2b8..edc736d4 100644 --- a/interop/ksp/api/ksp.api +++ b/interop/ksp/api/ksp.api @@ -1,5 +1,7 @@ public final class com/squareup/kotlinpoet/ksp/AnnotationsKt { public static final fun toAnnotationSpec (Lcom/google/devtools/ksp/symbol/KSAnnotation;)Lcom/squareup/kotlinpoet/AnnotationSpec; + public static final fun toAnnotationSpec (Lcom/google/devtools/ksp/symbol/KSAnnotation;Z)Lcom/squareup/kotlinpoet/AnnotationSpec; + public static synthetic fun toAnnotationSpec$default (Lcom/google/devtools/ksp/symbol/KSAnnotation;ZILjava/lang/Object;)Lcom/squareup/kotlinpoet/AnnotationSpec; } public final class com/squareup/kotlinpoet/ksp/KsClassDeclarationsKt { diff --git a/interop/ksp/build.gradle.kts b/interop/ksp/build.gradle.kts index c18fa7c9..3d615a39 100644 --- a/interop/ksp/build.gradle.kts +++ b/interop/ksp/build.gradle.kts @@ -21,7 +21,7 @@ tasks.jar { } dependencies { - api(project(":kotlinpoet")) + api(projects.kotlinpoet) compileOnly(libs.ksp.api) testImplementation(libs.kotlin.junit) testImplementation(libs.truth) diff --git a/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/Annotations.kt b/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/Annotations.kt index 7964de2e..b5dd38c1 100644 --- a/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/Annotations.kt +++ b/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/Annotations.kt @@ -28,8 +28,12 @@ import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.CodeBlock import com.squareup.kotlinpoet.ParameterizedTypeName -/** Returns an [AnnotationSpec] representation of this [KSAnnotation] instance. */ -public fun KSAnnotation.toAnnotationSpec(): AnnotationSpec { +/** + * Returns an [AnnotationSpec] representation of this [KSAnnotation] instance. + * @param omitDefaultValues omit defining default values when `true` + */ +@JvmOverloads +public fun KSAnnotation.toAnnotationSpec(omitDefaultValues: Boolean = false): AnnotationSpec { val builder = when (val type = annotationType.resolve().unwrapTypeAlias().toTypeName()) { is ClassName -> AnnotationSpec.builder(type) is ParameterizedTypeName -> AnnotationSpec.builder(type) @@ -38,15 +42,35 @@ public fun KSAnnotation.toAnnotationSpec(): AnnotationSpec { useSiteTarget?.let { builder.useSiteTarget(it.kpAnalog) } // TODO support type params once they're exposed https://github.com/google/ksp/issues/753 for (argument in arguments) { - val member = CodeBlock.builder() + val value = argument.value ?: continue val name = argument.name!!.getShortName() + if (omitDefaultValues) { + val defaultValue = this.defaultArguments.firstOrNull { it.name?.asString() == name }?.value + if (isDefaultValue(value, defaultValue)) { continue } + } + val member = CodeBlock.builder() member.add("%N = ", name) - addValueToBlock(argument.value!!, member) + addValueToBlock(value, member, omitDefaultValues) builder.addMember(member.build()) } return builder.build() } +private fun isDefaultValue(value: Any?, defaultValue: Any?): Boolean { + if (defaultValue == null) return false + if (value is KSAnnotation && defaultValue is KSAnnotation) { + return defaultValue.defaultArguments.all { defaultValueArg -> + isDefaultValue(value.arguments.firstOrNull { it.name == defaultValueArg.name }?.value, defaultValueArg.value) + } + } + if (value is List<*> && defaultValue is List<*>) { + return value.size == defaultValue.size && defaultValue.indices.all { index -> + isDefaultValue(value[index], defaultValue[index]) + } + } + return value == defaultValue +} + private val AnnotationUseSiteTarget.kpAnalog: UseSiteTarget get() = when (this) { AnnotationUseSiteTarget.FILE -> UseSiteTarget.FILE AnnotationUseSiteTarget.PROPERTY -> UseSiteTarget.PROPERTY @@ -67,7 +91,7 @@ internal fun KSType.unwrapTypeAlias(): KSType { } } -private fun addValueToBlock(value: Any, member: CodeBlock.Builder) { +private fun addValueToBlock(value: Any, member: CodeBlock.Builder, omitDefaultValues: Boolean) { when (value) { is List<*> -> { // Array type @@ -85,7 +109,7 @@ private fun addValueToBlock(value: Any, member: CodeBlock.Builder) { member.add("$arrayType(⇥⇥") value.forEachIndexed { index, innerValue -> if (index > 0) member.add(", ") - addValueToBlock(innerValue!!, member) + addValueToBlock(innerValue!!, member, omitDefaultValues) } member.add("⇤⇤)") } @@ -106,7 +130,7 @@ private fun addValueToBlock(value: Any, member: CodeBlock.Builder) { ClassName.bestGuess(value.getQualifier()), value.getShortName(), ) - is KSAnnotation -> member.add("%L", value.toAnnotationSpec()) + is KSAnnotation -> member.add("%L", value.toAnnotationSpec(omitDefaultValues)) else -> member.add(memberForValue(value)) } } diff --git a/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt b/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt index 0572b739..8d072201 100644 --- a/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt +++ b/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt @@ -15,7 +15,6 @@ */ package com.squareup.kotlinpoet.ksp -import com.google.devtools.ksp.symbol.ClassKind import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSType import com.google.devtools.ksp.symbol.KSTypeAlias @@ -53,7 +52,7 @@ public fun KSType.toClassName(): ClassName { */ public fun KSType.toTypeName( typeParamResolver: TypeParameterResolver = TypeParameterResolver.EMPTY, -): TypeName = toTypeName(typeParamResolver, emptyList()) +): TypeName = toTypeName(typeParamResolver, arguments) internal fun KSType.toTypeName( typeParamResolver: TypeParameterResolver, @@ -64,12 +63,6 @@ internal fun KSType.toTypeName( } val type = when (val decl = declaration) { is KSClassDeclaration -> { - val arguments = if (decl.classKind == ClassKind.ANNOTATION_CLASS) { - arguments - } else { - typeArguments - } - decl.toClassName().withTypeArguments(arguments.map { it.toTypeName(typeParamResolver) }) } is KSTypeParameter -> typeParamResolver[decl.name.getShortName()] diff --git a/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/OriginatingKSFiles.kt b/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/OriginatingKSFiles.kt index f7c40b3d..c8373e24 100644 --- a/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/OriginatingKSFiles.kt +++ b/interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/OriginatingKSFiles.kt @@ -32,7 +32,7 @@ import java.nio.charset.StandardCharsets * A simple holder class for containing originating [KSFiles][KSFile], which are used by KSP to * inform its incremental processing. * - * See [the docs](https://github.com/google/ksp/blob/main/docs/incremental.md) for more information. + * See [the docs](https://kotlinlang.org/docs/ksp-incremental.html) for more information. */ public interface OriginatingKSFiles { public val files: List<KSFile> diff --git a/interop/ksp/test-processor/build.gradle.kts b/interop/ksp/test-processor/build.gradle.kts index 9fc212e7..f0a4d71d 100644 --- a/interop/ksp/test-processor/build.gradle.kts +++ b/interop/ksp/test-processor/build.gradle.kts @@ -13,14 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - plugins { id("com.google.devtools.ksp") } +tasks.compileTestKotlin { + compilerOptions { + freeCompilerArgs.add("-opt-in=org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi") + } +} + dependencies { - implementation(project(":kotlinpoet")) - implementation(project(":interop:ksp")) + implementation(projects.kotlinpoet) + implementation(projects.interop.ksp) implementation(libs.autoService) compileOnly(libs.ksp.api) ksp(libs.autoService.ksp) diff --git a/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt b/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt index b1d41d40..82064c85 100644 --- a/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt +++ b/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt @@ -22,13 +22,18 @@ import com.google.devtools.ksp.isConstructor import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.processing.SymbolProcessor import com.google.devtools.ksp.processing.SymbolProcessorEnvironment +import com.google.devtools.ksp.symbol.ClassKind import com.google.devtools.ksp.symbol.KSAnnotated import com.google.devtools.ksp.symbol.KSClassDeclaration +import com.google.devtools.ksp.symbol.KSTypeReference +import com.squareup.kotlinpoet.ANY import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.PropertySpec +import com.squareup.kotlinpoet.TypeName import com.squareup.kotlinpoet.TypeSpec +import com.squareup.kotlinpoet.ksp.TypeParameterResolver import com.squareup.kotlinpoet.ksp.addOriginatingKSFile import com.squareup.kotlinpoet.ksp.kspDependencies import com.squareup.kotlinpoet.ksp.originatingKSFiles @@ -53,6 +58,15 @@ class TestProcessor(private val env: SymbolProcessorEnvironment) : SymbolProcess return emptyList() } + private fun KSTypeReference.toValidatedTypeName(resolver: TypeParameterResolver): TypeName { + // Validates that both toTypeName() and resolve() return the same TypeName. + // Regression for https://github.com/square/kotlinpoet/issues/1513. + val typeName = toTypeName(resolver) + val resolvedTypeName = resolve().toTypeName(resolver) + check(typeName == resolvedTypeName) + return typeName + } + private fun process(decl: KSAnnotated) { check(decl is KSClassDeclaration) @@ -64,7 +78,34 @@ class TestProcessor(private val env: SymbolProcessorEnvironment) : SymbolProcess addAnnotations( decl.annotations .filterNot { it.shortName.getShortName() == "ExampleAnnotation" } - .map { it.toAnnotationSpec() }.asIterable(), + .map { it.toAnnotationSpec(it.shortName.getShortName() == "ExampleAnnotationWithDefaults") } + .asIterable(), + ) + val allSupertypes = decl.superTypes.toList() + val (superclassReference, superInterfaces) = if (allSupertypes.isNotEmpty()) { + val superClass = allSupertypes.firstOrNull { + val resolved = it.resolve() + resolved is KSClassDeclaration && resolved.classKind == ClassKind.CLASS + } + if (superClass != null) { + superClass to allSupertypes.filterNot { it == superClass } + } else { + null to allSupertypes + } + } else { + null to allSupertypes + } + + superclassReference?.let { + val typeName = it.toValidatedTypeName(decl.typeParameters.toTypeParameterResolver()) + if (typeName != ANY) { + superclass(typeName) + } + } + addSuperinterfaces( + superInterfaces.map { it.toValidatedTypeName(decl.typeParameters.toTypeParameterResolver()) } + .filterNot { it == ANY } + .toList(), ) } val classTypeParams = decl.typeParameters.toTypeParameterResolver() @@ -85,7 +126,7 @@ class TestProcessor(private val env: SymbolProcessorEnvironment) : SymbolProcess classBuilder.addProperty( PropertySpec.builder( property.simpleName.getShortName(), - property.type.toTypeName(classTypeParams).let { + property.type.toValidatedTypeName(classTypeParams).let { if (unwrapTypeAliases) { it.unwrapTypeAlias() } else { @@ -130,7 +171,7 @@ class TestProcessor(private val env: SymbolProcessorEnvironment) : SymbolProcess ) .addParameters( function.parameters.map { parameter -> - val parameterType = parameter.type.toTypeName(functionTypeParams).let { + val parameterType = parameter.type.toValidatedTypeName(functionTypeParams).let { if (unwrapTypeAliases) { it.unwrapTypeAlias() } else { @@ -143,7 +184,7 @@ class TestProcessor(private val env: SymbolProcessorEnvironment) : SymbolProcess }, ) .returns( - function.returnType!!.toTypeName(functionTypeParams).let { + function.returnType!!.toValidatedTypeName(functionTypeParams).let { if (unwrapTypeAliases) { it.unwrapTypeAlias() } else { diff --git a/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/exampleAnnotations.kt b/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/exampleAnnotations.kt index 993222e2..1d763464 100644 --- a/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/exampleAnnotations.kt +++ b/interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/exampleAnnotations.kt @@ -18,6 +18,32 @@ package com.squareup.kotlinpoet.ksp.test.processor import kotlin.reflect.KClass annotation class ExampleAnnotation +annotation class ExampleAnnotationWithDefaults( + val boolean: Boolean = true, + val booleanArray: BooleanArray = [true], + val byte: Byte = 1, + val byteArray: ByteArray = [1], + val char: Char = 'C', + val charArray: CharArray = ['C'], + val short: Short = 1, + val shortArray: ShortArray = [1], + val int: Int = 1, + val intArray: IntArray = [1], + val long: Long = 1, + val longArray: LongArray = [1], + val float: Float = 1.0f, + val floatArray: FloatArray = [1.0f], + val double: Double = 1.0, + val doubleArray: DoubleArray = [1.0], + val string: String = "", + val stringArray: Array<String> = [""], + val someClass: KClass<*> = String::class, + val someClasses: Array<KClass<*>> = [String::class], + val enumValue: AnnotationEnumValue = AnnotationEnumValue.ONE, + val enumValueArray: Array<AnnotationEnumValue> = [AnnotationEnumValue.ONE], + val anotherAnnotation: AnotherAnnotation = AnotherAnnotation(""), + val anotherAnnotationArray: Array<AnotherAnnotation> = [AnotherAnnotation("")], +) annotation class ComprehensiveAnnotation<T : CharSequence>( val boolean: Boolean, diff --git a/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/KsTypesTest.kt b/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/KsTypesTest.kt index b392f374..8da749db 100644 --- a/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/KsTypesTest.kt +++ b/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/KsTypesTest.kt @@ -36,7 +36,7 @@ class KsTypesTest { override val annotations: Sequence<KSAnnotation> get() = throw NotImplementedError() override val arguments: List<KSTypeArgument> - get() = throw NotImplementedError() + get() = emptyList() override val declaration: KSDeclaration get() = throw NotImplementedError() override val isFunctionType: Boolean diff --git a/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt b/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt index 06518eff..1aaa1edb 100644 --- a/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt +++ b/interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt @@ -46,6 +46,7 @@ class TestProcessorTest { import com.squareup.kotlinpoet.ksp.test.processor.AnotherAnnotation import com.squareup.kotlinpoet.ksp.test.processor.ComprehensiveAnnotation import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotationWithDefaults typealias TypeAliasName = String typealias GenericTypeAlias = List<String> @@ -77,6 +78,32 @@ class TestProcessorTest { anotherAnnotation = AnotherAnnotation("Hello"), anotherAnnotationArray = [AnotherAnnotation("Hello")] ) + @ExampleAnnotationWithDefaults( + true, // Omit the name intentionally here to test names are still picked up + booleanArray = [false], + byte = 0.toByte(), + byteArray = [1.toByte()], + char = 'C', + charArray = ['C'], + short = 0.toShort(), + shortArray = [1.toShort()], + int = 0, + intArray = [1], + long = 0L, + longArray = [1L], + float = 0f, + floatArray = [1f], + double = 1.0, + doubleArray = [0.0], + string = "Hello", + stringArray = [""], + someClass = String::class, + someClasses = [Int::class], + enumValue = AnnotationEnumValue.ONE, + enumValueArray = [AnnotationEnumValue.ONE, AnnotationEnumValue.TWO], + anotherAnnotation = AnotherAnnotation(""), + anotherAnnotationArray = [AnotherAnnotation("Hello")] + ) @ExampleAnnotation class SmokeTestClass<T, R : Any, E : Enum<E>> { @field:AnotherAnnotation("siteTargeting") @@ -150,6 +177,7 @@ class TestProcessorTest { import com.squareup.kotlinpoet.ksp.test.processor.AnnotationEnumValue import com.squareup.kotlinpoet.ksp.test.processor.AnotherAnnotation import com.squareup.kotlinpoet.ksp.test.processor.ComprehensiveAnnotation + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotationWithDefaults import kotlin.Any import kotlin.Array import kotlin.Boolean @@ -160,7 +188,6 @@ class TestProcessorTest { import kotlin.Int import kotlin.IntArray import kotlin.String - import kotlin.Unit import kotlin.collections.List import kotlin.collections.Map import kotlin.collections.MutableList @@ -193,6 +220,18 @@ class TestProcessorTest { anotherAnnotationArray = arrayOf(AnotherAnnotation(input = "Hello")), defaultingString = "defaultValue", ) + @ExampleAnnotationWithDefaults( + booleanArray = booleanArrayOf(false), + byte = 0.toByte(), + short = 0.toShort(), + int = 0, + long = 0, + float = 0.0f, + doubleArray = doubleArrayOf(0.0), + string = "Hello", + someClasses = arrayOf(Int::class), + enumValueArray = arrayOf(AnnotationEnumValue.ONE, AnnotationEnumValue.TWO), + ) public class SmokeTestClass<T, R : Any, E : Enum<E>> { @field:AnotherAnnotation(input = "siteTargeting") private val propA: String @@ -225,7 +264,7 @@ class TestProcessorTest { param1: Function0<String>, param2: Function1<String, String>, param3: Function1<String, String>, - ): Unit { + ) { } public fun wildTypes( @@ -252,7 +291,7 @@ class TestProcessorTest { genericAlias: GenericTypeAlias, parameterizedTypeAlias: ParameterizedTypeAlias<String>, nestedArray: Array<Map<String, Any>>?, - ): Unit { + ) { } } @@ -302,7 +341,6 @@ class TestProcessorTest { import kotlin.Int import kotlin.String - import kotlin.Unit import kotlin.collections.List import kotlin.collections.Map @@ -313,7 +351,7 @@ class TestProcessorTest { genericMapAlias: Map<Int, String>, t1Unused: Map<Int, String>, a1: Map<String, Int>, - ): Unit { + ) { } } @@ -322,6 +360,75 @@ class TestProcessorTest { } @Test + fun removeDefaultValues() { + val compilation = prepareCompilation( + kotlin( + "Example.kt", + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotationWithDefaults + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + import com.squareup.kotlinpoet.ksp.test.processor.AnotherAnnotation + import com.squareup.kotlinpoet.ksp.test.processor.AnnotationEnumValue + + @ExampleAnnotation + @ExampleAnnotationWithDefaults( + true, // Omit the name intentionally here to test names are still picked up + booleanArray = [true], + byte = 1.toByte(), + byteArray = [1.toByte()], + char = 'C', + charArray = ['C'], + short = 1.toShort(), + shortArray = [1.toShort()], + int = 1, + intArray = [1], + long = 1L, + longArray = [1L], + float = 1f, + floatArray = [1f], + double = 1.0, + doubleArray = [1.0], + string = "", + stringArray = [""], + someClass = String::class, + someClasses = [String::class], + enumValue = AnnotationEnumValue.ONE, + enumValueArray = [AnnotationEnumValue.ONE], + anotherAnnotation = AnotherAnnotation(""), + anotherAnnotationArray = [AnotherAnnotation("")] + ) + open class Node<T : Node<T, R>, R : Node<R, T>> { + var t: T? = null + var r: R? = null + } + """, + ), + ) + + val result = compilation.compile() + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val generatedFileText = File(compilation.kspSourcesDir, "kotlin/test/TestNode.kt") + .readText() + assertThat(generatedFileText).isEqualTo( + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotationWithDefaults + + @ExampleAnnotationWithDefaults + public open class Node<T : Node<T, R>, R : Node<R, T>> { + public var t: T? + + public var r: R? + } + + """.trimIndent(), + ) + } + + @Test fun complexSelfReferencingTypeArgs() { val compilation = prepareCompilation( kotlin( @@ -431,10 +538,9 @@ class TestProcessorTest { package test import kotlin.Int - import kotlin.Unit public class TransitiveAliases { - public fun <T : Alias41<Alias23, out Alias77<Alias73<Int>>>> bar(arg1: T): Unit { + public fun <T : Alias41<Alias23, out Alias77<Alias73<Int>>>> bar(arg1: T) { } } @@ -471,11 +577,10 @@ class TestProcessorTest { """ package test - import kotlin.Unit import kotlin.collections.List public class AliasAsTypeArgument { - public fun bar(arg1: List<Alias997>): Unit { + public fun bar(arg1: List<Alias997>) { } } @@ -483,6 +588,158 @@ class TestProcessorTest { ) } + @Test + fun regression_1513() { + val compilation = prepareCompilation( + kotlin( + "Example.kt", + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + + interface Repository<T> + @ExampleAnnotation + class RealRepository @Inject constructor() : Repository<String> + """, + ), + ) + + val result = compilation.compile() + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val generatedFileText = File(compilation.kspSourcesDir, "kotlin/test/TestRealRepository.kt") + .readText() + + assertThat(generatedFileText).isEqualTo( + """ + package test + + import kotlin.String + + public class RealRepository : Repository<String> + + """.trimIndent(), + ) + } + + @Test + fun regression_1513_annotation() { + val compilation = prepareCompilation( + kotlin( + "Example.kt", + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + + annotation class GenericAnnotation<T> + + @ExampleAnnotation + @GenericAnnotation<String> + class RealRepository + """, + ), + ) + + val result = compilation.compile() + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val generatedFileText = File(compilation.kspSourcesDir, "kotlin/test/TestRealRepository.kt") + .readText() + + assertThat(generatedFileText).isEqualTo( + """ + package test + + import kotlin.String + + @GenericAnnotation<String> + public class RealRepository + + """.trimIndent(), + ) + } + + @Test + fun regression_1304() { + val compilation = prepareCompilation( + kotlin( + "Example.kt", + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + + interface Flow<T> + typealias LeAlias = Map<Int, String> + + @ExampleAnnotation + class RealRepository { + lateinit var prop: LeAlias + lateinit var complicated: Flow<LeAlias> + } + """, + ), + ) + + val result = compilation.compile() + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val generatedFileText = File(compilation.kspSourcesDir, "kotlin/test/TestRealRepository.kt") + .readText() + + assertThat(generatedFileText).isEqualTo( + """ + package test + + public class RealRepository { + public lateinit var prop: LeAlias + + public lateinit var complicated: Flow<LeAlias> + } + + """.trimIndent(), + ) + } + + @Test + fun regression_1304_with_type_parameters() { + val compilation = prepareCompilation( + kotlin( + "Example.kt", + """ + package test + + import com.squareup.kotlinpoet.ksp.test.processor.ExampleAnnotation + + interface Flow<T> + typealias LeAlias<T> = Flow<T> + + @ExampleAnnotation + class RealRepository { + lateinit var prop: LeAlias<String> + } + """, + ), + ) + + val result = compilation.compile() + assertThat(result.exitCode).isEqualTo(KotlinCompilation.ExitCode.OK) + val generatedFileText = File(compilation.kspSourcesDir, "kotlin/test/TestRealRepository.kt") + .readText() + + assertThat(generatedFileText).isEqualTo( + """ + package test + + import kotlin.String + + public class RealRepository { + public lateinit var prop: LeAlias<String> + } + + """.trimIndent(), + ) + } + private fun prepareCompilation(vararg sourceFiles: SourceFile): KotlinCompilation { return KotlinCompilation() .apply { diff --git a/kotlinpoet/api/kotlinpoet.api b/kotlinpoet/api/kotlinpoet.api index 59f04dca..c9547c1f 100644 --- a/kotlinpoet/api/kotlinpoet.api +++ b/kotlinpoet/api/kotlinpoet.api @@ -1,3 +1,16 @@ +public abstract interface class com/squareup/kotlinpoet/Annotatable { + public abstract fun getAnnotations ()Ljava/util/List; +} + +public abstract interface class com/squareup/kotlinpoet/Annotatable$Builder { + public fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public abstract fun getAnnotations ()Ljava/util/List; +} + public final class com/squareup/kotlinpoet/AnnotationSpec : com/squareup/kotlinpoet/Taggable { public static final field Companion Lcom/squareup/kotlinpoet/AnnotationSpec$Companion; public static final fun builder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/AnnotationSpec$Builder; @@ -27,10 +40,6 @@ public final class com/squareup/kotlinpoet/AnnotationSpec$Builder : com/squareup public final fun build ()Lcom/squareup/kotlinpoet/AnnotationSpec; public final fun getMembers ()Ljava/util/List; public fun getTags ()Ljava/util/Map; - public fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/AnnotationSpec$Builder; - public synthetic fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/AnnotationSpec$Builder; - public synthetic fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; public final fun useSiteTarget (Lcom/squareup/kotlinpoet/AnnotationSpec$UseSiteTarget;)Lcom/squareup/kotlinpoet/AnnotationSpec$Builder; } @@ -58,6 +67,7 @@ public final class com/squareup/kotlinpoet/AnnotationSpec$UseSiteTarget : java/l public static final field RECEIVER Lcom/squareup/kotlinpoet/AnnotationSpec$UseSiteTarget; public static final field SET Lcom/squareup/kotlinpoet/AnnotationSpec$UseSiteTarget; public static final field SETPARAM Lcom/squareup/kotlinpoet/AnnotationSpec$UseSiteTarget; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/squareup/kotlinpoet/AnnotationSpec$UseSiteTarget; public static fun values ()[Lcom/squareup/kotlinpoet/AnnotationSpec$UseSiteTarget; } @@ -75,10 +85,12 @@ public final class com/squareup/kotlinpoet/ClassName : com/squareup/kotlinpoet/T public fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/ClassName; public synthetic fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/TypeName; public final fun enclosingClassName ()Lcom/squareup/kotlinpoet/ClassName; + public fun equals (Ljava/lang/Object;)Z public final fun getCanonicalName ()Ljava/lang/String; public final fun getPackageName ()Ljava/lang/String; public final fun getSimpleName ()Ljava/lang/String; public final fun getSimpleNames ()Ljava/util/List; + public fun hashCode ()I public final fun nestedClass (Ljava/lang/String;)Lcom/squareup/kotlinpoet/ClassName; public final fun peerClass (Ljava/lang/String;)Lcom/squareup/kotlinpoet/ClassName; public final fun reflectionName ()Ljava/lang/String; @@ -141,7 +153,6 @@ public final class com/squareup/kotlinpoet/CodeBlocks { } public abstract interface class com/squareup/kotlinpoet/ContextReceivable { - public abstract fun getContextReceiverTypes ()Ljava/util/List; } public abstract interface class com/squareup/kotlinpoet/ContextReceivable$Builder { @@ -155,6 +166,16 @@ public abstract interface annotation class com/squareup/kotlinpoet/DelicateKotli public abstract fun message ()Ljava/lang/String; } +public abstract interface class com/squareup/kotlinpoet/Documentable { + public abstract fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; +} + +public abstract interface class com/squareup/kotlinpoet/Documentable$Builder { + public fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public abstract fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock$Builder; +} + public final class com/squareup/kotlinpoet/Dynamic : com/squareup/kotlinpoet/TypeName { public static final field INSTANCE Lcom/squareup/kotlinpoet/Dynamic; public synthetic fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/TypeName; @@ -164,13 +185,14 @@ public final class com/squareup/kotlinpoet/Dynamic : com/squareup/kotlinpoet/Typ public abstract interface annotation class com/squareup/kotlinpoet/ExperimentalKotlinPoetApi : java/lang/annotation/Annotation { } -public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/Taggable { +public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/Taggable { public static final field Companion Lcom/squareup/kotlinpoet/FileSpec$Companion; public static final fun builder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public static final fun builder (Lcom/squareup/kotlinpoet/MemberName;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public static final fun builder (Ljava/lang/String;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public fun equals (Ljava/lang/Object;)Z public static final fun get (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/FileSpec; - public final fun getAnnotations ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; public final fun getBody ()Lcom/squareup/kotlinpoet/CodeBlock; public final fun getComment ()Lcom/squareup/kotlinpoet/CodeBlock; public final fun getDefaultImports ()Ljava/util/Set; @@ -195,16 +217,22 @@ public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/Ta public final fun writeTo (Ljavax/annotation/processing/Filer;)V } -public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotlinpoet/Taggable$Builder { +public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/Taggable$Builder { public final fun addAliasedImport (Lcom/squareup/kotlinpoet/ClassName;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addAliasedImport (Lcom/squareup/kotlinpoet/ClassName;Ljava/lang/String;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addAliasedImport (Lcom/squareup/kotlinpoet/MemberName;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addAliasedImport (Ljava/lang/Class;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addAliasedImport (Lkotlin/reflect/KClass;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; - public final fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder; - public final fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FileSpec$Builder; - public final fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/FileSpec$Builder; - public final fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public synthetic fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public synthetic fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public synthetic fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addBodyComment (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addCode (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun addCode (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder; @@ -235,7 +263,7 @@ public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotli public final fun clearComment ()Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun clearImports ()Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun endControlFlow ()Lcom/squareup/kotlinpoet/FileSpec$Builder; - public final fun getAnnotations ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; public final fun getDefaultImports ()Ljava/util/Set; public final fun getImports ()Ljava/util/List; public final fun getMembers ()Ljava/util/List; @@ -245,31 +273,29 @@ public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotli public final fun indent (Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun isScript ()Z public final fun nextControlFlow (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder; - public fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder; - public synthetic fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder; - public synthetic fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; } public final class com/squareup/kotlinpoet/FileSpec$Companion { public final fun builder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FileSpec$Builder; + public final fun builder (Lcom/squareup/kotlinpoet/MemberName;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun builder (Ljava/lang/String;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public final fun get (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/FileSpec; public final fun scriptBuilder (Ljava/lang/String;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder; public static synthetic fun scriptBuilder$default (Lcom/squareup/kotlinpoet/FileSpec$Companion;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder; } -public final class com/squareup/kotlinpoet/FunSpec : com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/OriginatingElementsHolder, com/squareup/kotlinpoet/Taggable { +public final class com/squareup/kotlinpoet/FunSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/Documentable, com/squareup/kotlinpoet/OriginatingElementsHolder, com/squareup/kotlinpoet/Taggable { public static final field Companion Lcom/squareup/kotlinpoet/FunSpec$Companion; + public static final fun builder (Lcom/squareup/kotlinpoet/MemberName;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public static final fun builder (Ljava/lang/String;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public static final fun constructorBuilder ()Lcom/squareup/kotlinpoet/FunSpec$Builder; public fun equals (Ljava/lang/Object;)Z - public final fun getAnnotations ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; public final fun getBody ()Lcom/squareup/kotlinpoet/CodeBlock; public fun getContextReceiverTypes ()Ljava/util/List; public final fun getDelegateConstructor ()Ljava/lang/String; public final fun getDelegateConstructorArguments ()Ljava/util/List; - public final fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; public final fun getModifiers ()Ljava/util/Set; public final fun getName ()Ljava/lang/String; public fun getOriginatingElements ()Ljava/util/List; @@ -295,22 +321,27 @@ public final class com/squareup/kotlinpoet/FunSpec : com/squareup/kotlinpoet/Con public fun toString ()Ljava/lang/String; } -public final class com/squareup/kotlinpoet/FunSpec$Builder : com/squareup/kotlinpoet/ContextReceivable$Builder, com/squareup/kotlinpoet/OriginatingElementsHolder$Builder, com/squareup/kotlinpoet/Taggable$Builder { - public final fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public final fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public final fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public final fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public final fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/FunSpec$Builder; +public final class com/squareup/kotlinpoet/FunSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/ContextReceivable$Builder, com/squareup/kotlinpoet/Documentable$Builder, com/squareup/kotlinpoet/OriginatingElementsHolder$Builder, com/squareup/kotlinpoet/Taggable$Builder { + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/FunSpec$Builder; + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/FunSpec$Builder; + public synthetic fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/FunSpec$Builder; + public synthetic fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/FunSpec$Builder; + public synthetic fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun addCode (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun addCode (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun addComment (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public final fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public final fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; + public synthetic fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/FunSpec$Builder; + public synthetic fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun addModifiers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun addModifiers ([Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun addNamedCode (Ljava/lang/String;Ljava/util/Map;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public fun addOriginatingElement (Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public synthetic fun addOriginatingElement (Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/OriginatingElementsHolder$Builder; public final fun addParameter (Lcom/squareup/kotlinpoet/ParameterSpec;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun addParameter (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeName;Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun addParameter (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeName;[Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/FunSpec$Builder; @@ -336,10 +367,9 @@ public final class com/squareup/kotlinpoet/FunSpec$Builder : com/squareup/kotlin public static synthetic fun callThisConstructor$default (Lcom/squareup/kotlinpoet/FunSpec$Builder;[Lcom/squareup/kotlinpoet/CodeBlock;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun clearBody ()Lcom/squareup/kotlinpoet/FunSpec$Builder; public synthetic fun contextReceivers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ContextReceivable$Builder; - public synthetic fun contextReceivers ([Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/ContextReceivable$Builder; public final fun endControlFlow ()Lcom/squareup/kotlinpoet/FunSpec$Builder; - public final fun getAnnotations ()Ljava/util/List; - public fun getContextReceiverTypes ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock$Builder; public final fun getModifiers ()Ljava/util/List; public fun getOriginatingElements ()Ljava/util/List; public final fun getParameters ()Ljava/util/List; @@ -369,13 +399,10 @@ public final class com/squareup/kotlinpoet/FunSpec$Builder : com/squareup/kotlin public static synthetic fun returns$default (Lcom/squareup/kotlinpoet/FunSpec$Builder;Lcom/squareup/kotlinpoet/TypeName;Lcom/squareup/kotlinpoet/CodeBlock;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public static synthetic fun returns$default (Lcom/squareup/kotlinpoet/FunSpec$Builder;Ljava/lang/reflect/Type;Lcom/squareup/kotlinpoet/CodeBlock;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public static synthetic fun returns$default (Lcom/squareup/kotlinpoet/FunSpec$Builder;Lkotlin/reflect/KClass;Lcom/squareup/kotlinpoet/CodeBlock;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public synthetic fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FunSpec$Builder; - public synthetic fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; } public final class com/squareup/kotlinpoet/FunSpec$Companion { + public final fun builder (Lcom/squareup/kotlinpoet/MemberName;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun builder (Ljava/lang/String;)Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun constructorBuilder ()Lcom/squareup/kotlinpoet/FunSpec$Builder; public final fun getterBuilder ()Lcom/squareup/kotlinpoet/FunSpec$Builder; @@ -431,6 +458,7 @@ public final class com/squareup/kotlinpoet/KModifier : java/lang/Enum { public static final field TAILREC Lcom/squareup/kotlinpoet/KModifier; public static final field VALUE Lcom/squareup/kotlinpoet/KModifier; public static final field VARARG Lcom/squareup/kotlinpoet/KModifier; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/squareup/kotlinpoet/KModifier; public static fun values ()[Lcom/squareup/kotlinpoet/KModifier; } @@ -461,6 +489,7 @@ public final class com/squareup/kotlinpoet/KOperator : java/lang/Enum { public static final field TIMES_ASSIGN Lcom/squareup/kotlinpoet/KOperator; public static final field UNARY_MINUS Lcom/squareup/kotlinpoet/KOperator; public static final field UNARY_PLUS Lcom/squareup/kotlinpoet/KOperator; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/squareup/kotlinpoet/KOperator; public static fun values ()[Lcom/squareup/kotlinpoet/KOperator; } @@ -471,12 +500,14 @@ public final class com/squareup/kotlinpoet/LambdaTypeName : com/squareup/kotlinp public synthetic fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/TypeName; public final fun copy (ZLjava/util/List;ZLjava/util/Map;)Lcom/squareup/kotlinpoet/LambdaTypeName; public static synthetic fun copy$default (Lcom/squareup/kotlinpoet/LambdaTypeName;ZLjava/util/List;ZLjava/util/Map;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/LambdaTypeName; + public fun equals (Ljava/lang/Object;)Z public static final fun get (Lcom/squareup/kotlinpoet/TypeName;Ljava/util/List;Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/LambdaTypeName; public static final fun get (Lcom/squareup/kotlinpoet/TypeName;[Lcom/squareup/kotlinpoet/ParameterSpec;Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/LambdaTypeName; public static final fun get (Lcom/squareup/kotlinpoet/TypeName;[Lcom/squareup/kotlinpoet/TypeName;Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/LambdaTypeName; public final fun getParameters ()Ljava/util/List; public final fun getReceiver ()Lcom/squareup/kotlinpoet/TypeName; public final fun getReturnType ()Lcom/squareup/kotlinpoet/TypeName; + public fun hashCode ()I public final fun isSuspending ()Z } @@ -539,7 +570,7 @@ public abstract interface class com/squareup/kotlinpoet/OriginatingElementsHolde } public abstract interface class com/squareup/kotlinpoet/OriginatingElementsHolder$Builder { - public abstract fun addOriginatingElement (Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/OriginatingElementsHolder$Builder; + public fun addOriginatingElement (Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/OriginatingElementsHolder$Builder; public abstract fun getOriginatingElements ()Ljava/util/List; } @@ -547,7 +578,7 @@ public final class com/squareup/kotlinpoet/OriginatingElementsHolder$Builder$Def public static fun addOriginatingElement (Lcom/squareup/kotlinpoet/OriginatingElementsHolder$Builder;Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/OriginatingElementsHolder$Builder; } -public final class com/squareup/kotlinpoet/ParameterSpec : com/squareup/kotlinpoet/Taggable { +public final class com/squareup/kotlinpoet/ParameterSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/Documentable, com/squareup/kotlinpoet/Taggable { public static final field Companion Lcom/squareup/kotlinpoet/ParameterSpec$Companion; public fun <init> (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeName;Ljava/lang/Iterable;)V public fun <init> (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeName;[Lcom/squareup/kotlinpoet/KModifier;)V @@ -559,9 +590,9 @@ public final class com/squareup/kotlinpoet/ParameterSpec : com/squareup/kotlinpo public static final fun builder (Ljava/lang/String;Lkotlin/reflect/KClass;[Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; public fun equals (Ljava/lang/Object;)Z public static final fun get (Ljavax/lang/model/element/VariableElement;)Lcom/squareup/kotlinpoet/ParameterSpec; - public final fun getAnnotations ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; public final fun getDefaultValue ()Lcom/squareup/kotlinpoet/CodeBlock; - public final fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; public final fun getModifiers ()Ljava/util/Set; public final fun getName ()Ljava/lang/String; public fun getTags ()Ljava/util/Map; @@ -578,28 +609,31 @@ public final class com/squareup/kotlinpoet/ParameterSpec : com/squareup/kotlinpo public static final fun unnamed (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/ParameterSpec; } -public final class com/squareup/kotlinpoet/ParameterSpec$Builder : com/squareup/kotlinpoet/Taggable$Builder { - public final fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public final fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public final fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public final fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public final fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public final fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public final fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; +public final class com/squareup/kotlinpoet/ParameterSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/Documentable$Builder, com/squareup/kotlinpoet/Taggable$Builder { + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; + public synthetic fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; + public synthetic fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; + public synthetic fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; + public synthetic fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; + public synthetic fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; public final fun addModifiers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; public final fun addModifiers ([Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; public final fun build ()Lcom/squareup/kotlinpoet/ParameterSpec; public final fun defaultValue (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; public final fun defaultValue (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public final fun getAnnotations ()Ljava/util/List; - public final fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock$Builder; + public fun getAnnotations ()Ljava/util/List; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock$Builder; public final fun getModifiers ()Ljava/util/List; public fun getTags ()Ljava/util/Map; public final fun jvmModifiers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public synthetic fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/ParameterSpec$Builder; - public synthetic fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; } public final class com/squareup/kotlinpoet/ParameterSpec$Companion { @@ -622,6 +656,7 @@ public final class com/squareup/kotlinpoet/ParameterizedTypeName : com/squareup/ public synthetic fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/TypeName; public final fun copy (ZLjava/util/List;Ljava/util/Map;Ljava/util/List;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; public static synthetic fun copy$default (Lcom/squareup/kotlinpoet/ParameterizedTypeName;ZLjava/util/List;Ljava/util/Map;Ljava/util/List;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; + public fun equals (Ljava/lang/Object;)Z public static final fun get (Lcom/squareup/kotlinpoet/ClassName;Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; public static final fun get (Lcom/squareup/kotlinpoet/ClassName;Ljava/util/List;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; public static final fun get (Lcom/squareup/kotlinpoet/ClassName;[Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; @@ -633,6 +668,7 @@ public final class com/squareup/kotlinpoet/ParameterizedTypeName : com/squareup/ public static final fun get (Lkotlin/reflect/KClass;[Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; public final fun getRawType ()Lcom/squareup/kotlinpoet/ClassName; public final fun getTypeArguments ()Ljava/util/List; + public fun hashCode ()I public final fun nestedClass (Ljava/lang/String;Ljava/util/List;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; public final fun plusParameter (Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; public final fun plusParameter (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; @@ -656,7 +692,7 @@ public final class com/squareup/kotlinpoet/ParameterizedTypeNames { public static final fun get (Ljava/lang/reflect/ParameterizedType;)Lcom/squareup/kotlinpoet/ParameterizedTypeName; } -public final class com/squareup/kotlinpoet/PropertySpec : com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/OriginatingElementsHolder, com/squareup/kotlinpoet/Taggable { +public final class com/squareup/kotlinpoet/PropertySpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/Documentable, com/squareup/kotlinpoet/OriginatingElementsHolder, com/squareup/kotlinpoet/Taggable { public static final field Companion Lcom/squareup/kotlinpoet/PropertySpec$Companion; public static final fun builder (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeName;Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public static final fun builder (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeName;[Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; @@ -665,12 +701,12 @@ public final class com/squareup/kotlinpoet/PropertySpec : com/squareup/kotlinpoe public static final fun builder (Ljava/lang/String;Lkotlin/reflect/KClass;Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public static final fun builder (Ljava/lang/String;Lkotlin/reflect/KClass;[Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public fun equals (Ljava/lang/Object;)Z - public final fun getAnnotations ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; public fun getContextReceiverTypes ()Ljava/util/List; public final fun getDelegated ()Z public final fun getGetter ()Lcom/squareup/kotlinpoet/FunSpec; public final fun getInitializer ()Lcom/squareup/kotlinpoet/CodeBlock; - public final fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; public final fun getModifiers ()Ljava/util/Set; public final fun getMutable ()Z public final fun getName ()Ljava/lang/String; @@ -690,27 +726,30 @@ public final class com/squareup/kotlinpoet/PropertySpec : com/squareup/kotlinpoe public fun toString ()Ljava/lang/String; } -public final class com/squareup/kotlinpoet/PropertySpec$Builder : com/squareup/kotlinpoet/ContextReceivable$Builder, com/squareup/kotlinpoet/OriginatingElementsHolder$Builder, com/squareup/kotlinpoet/Taggable$Builder { - public final fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public final fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public final fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public final fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public final fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public final fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public final fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; +public final class com/squareup/kotlinpoet/PropertySpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/ContextReceivable$Builder, com/squareup/kotlinpoet/Documentable$Builder, com/squareup/kotlinpoet/OriginatingElementsHolder$Builder, com/squareup/kotlinpoet/Taggable$Builder { + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; + public synthetic fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; + public synthetic fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; + public synthetic fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; + public synthetic fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; + public synthetic fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public final fun addModifiers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public final fun addModifiers ([Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public synthetic fun addOriginatingElement (Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/OriginatingElementsHolder$Builder; - public fun addOriginatingElement (Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public final fun addTypeVariable (Lcom/squareup/kotlinpoet/TypeVariableName;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public final fun addTypeVariables (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public final fun build ()Lcom/squareup/kotlinpoet/PropertySpec; - public synthetic fun contextReceivers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ContextReceivable$Builder; - public synthetic fun contextReceivers ([Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/ContextReceivable$Builder; public final fun delegate (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public final fun delegate (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public final fun getAnnotations ()Ljava/util/List; - public fun getContextReceiverTypes ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock$Builder; public final fun getModifiers ()Ljava/util/List; public fun getOriginatingElements ()Ljava/util/List; public fun getTags ()Ljava/util/Map; @@ -724,10 +763,6 @@ public final class com/squareup/kotlinpoet/PropertySpec$Builder : com/squareup/k public final fun receiver (Ljava/lang/reflect/Type;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public final fun receiver (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; public final fun setter (Lcom/squareup/kotlinpoet/FunSpec;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public synthetic fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/PropertySpec$Builder; - public synthetic fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; } public final class com/squareup/kotlinpoet/PropertySpec$Companion { @@ -740,15 +775,15 @@ public final class com/squareup/kotlinpoet/PropertySpec$Companion { } public abstract interface class com/squareup/kotlinpoet/Taggable { - public abstract fun getTags ()Ljava/util/Map; - public abstract fun tag (Ljava/lang/Class;)Ljava/lang/Object; - public abstract fun tag (Lkotlin/reflect/KClass;)Ljava/lang/Object; + public fun getTags ()Ljava/util/Map; + public fun tag (Ljava/lang/Class;)Ljava/lang/Object; + public fun tag (Lkotlin/reflect/KClass;)Ljava/lang/Object; } public abstract interface class com/squareup/kotlinpoet/Taggable$Builder { public abstract fun getTags ()Ljava/util/Map; - public abstract fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public abstract fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; + public fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; + public fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; } public final class com/squareup/kotlinpoet/Taggable$Builder$DefaultImpls { @@ -762,14 +797,14 @@ public final class com/squareup/kotlinpoet/Taggable$DefaultImpls { public static fun tag (Lcom/squareup/kotlinpoet/Taggable;Lkotlin/reflect/KClass;)Ljava/lang/Object; } -public final class com/squareup/kotlinpoet/TypeAliasSpec : com/squareup/kotlinpoet/Taggable { +public final class com/squareup/kotlinpoet/TypeAliasSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/Documentable, com/squareup/kotlinpoet/Taggable { public static final field Companion Lcom/squareup/kotlinpoet/TypeAliasSpec$Companion; public static final fun builder (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; public static final fun builder (Ljava/lang/String;Ljava/lang/reflect/Type;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; public static final fun builder (Ljava/lang/String;Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; public fun equals (Ljava/lang/Object;)Z - public final fun getAnnotations ()Ljava/util/List; - public final fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; + public fun getAnnotations ()Ljava/util/List; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; public final fun getModifiers ()Ljava/util/Set; public final fun getName ()Ljava/lang/String; public fun getTags ()Ljava/util/Map; @@ -785,27 +820,31 @@ public final class com/squareup/kotlinpoet/TypeAliasSpec : com/squareup/kotlinpo public fun toString ()Ljava/lang/String; } -public final class com/squareup/kotlinpoet/TypeAliasSpec$Builder : com/squareup/kotlinpoet/Taggable$Builder { - public final fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; - public final fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; - public final fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; - public final fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; - public final fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; - public final fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; - public final fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; +public final class com/squareup/kotlinpoet/TypeAliasSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/Documentable$Builder, com/squareup/kotlinpoet/Taggable$Builder { + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; + public synthetic fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; + public synthetic fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; + public synthetic fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; + public synthetic fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; + public synthetic fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; public final fun addModifiers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; public final fun addModifiers ([Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; public final fun addTypeVariable (Lcom/squareup/kotlinpoet/TypeVariableName;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; public final fun addTypeVariables (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; public final fun build ()Lcom/squareup/kotlinpoet/TypeAliasSpec; - public final fun getAnnotations ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock$Builder; public final fun getModifiers ()Ljava/util/Set; public fun getTags ()Ljava/util/Map; public final fun getTypeVariables ()Ljava/util/Set; - public synthetic fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; - public synthetic fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; } public final class com/squareup/kotlinpoet/TypeAliasSpec$Companion { @@ -814,7 +853,7 @@ public final class com/squareup/kotlinpoet/TypeAliasSpec$Companion { public final fun builder (Ljava/lang/String;Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/TypeAliasSpec$Builder; } -public abstract class com/squareup/kotlinpoet/TypeName : com/squareup/kotlinpoet/Taggable { +public abstract class com/squareup/kotlinpoet/TypeName : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/Taggable { public static final field Companion Lcom/squareup/kotlinpoet/TypeName$Companion; public synthetic fun <init> (ZLjava/util/List;Ljava/util/Map;Lkotlin/jvm/internal/DefaultConstructorMarker;)V public final fun copy (ZLjava/util/List;)Lcom/squareup/kotlinpoet/TypeName; @@ -822,7 +861,7 @@ public abstract class com/squareup/kotlinpoet/TypeName : com/squareup/kotlinpoet public static synthetic fun copy$default (Lcom/squareup/kotlinpoet/TypeName;ZLjava/util/List;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeName; public static synthetic fun copy$default (Lcom/squareup/kotlinpoet/TypeName;ZLjava/util/List;Ljava/util/Map;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeName; public fun equals (Ljava/lang/Object;)Z - public final fun getAnnotations ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; public fun getTags ()Ljava/util/Map; public fun hashCode ()I public final fun isAnnotated ()Z @@ -890,7 +929,7 @@ public final class com/squareup/kotlinpoet/TypeNames { public static final fun get (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/ClassName; } -public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/OriginatingElementsHolder, com/squareup/kotlinpoet/Taggable { +public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/Documentable, com/squareup/kotlinpoet/OriginatingElementsHolder, com/squareup/kotlinpoet/Taggable { public static final field Companion Lcom/squareup/kotlinpoet/TypeSpec$Companion; public static final fun annotationBuilder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public static final fun annotationBuilder (Ljava/lang/String;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; @@ -907,12 +946,13 @@ public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/Co public static final fun funInterfaceBuilder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public static final fun funInterfaceBuilder (Ljava/lang/String;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun getAnnotationSpecs ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; public fun getContextReceiverTypes ()Ljava/util/List; public final fun getEnumConstants ()Ljava/util/Map; public final fun getFunSpecs ()Ljava/util/List; public final fun getInitializerBlock ()Lcom/squareup/kotlinpoet/CodeBlock; public final fun getInitializerIndex ()I - public final fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock; public final fun getKind ()Lcom/squareup/kotlinpoet/TypeSpec$Kind; public final fun getModifiers ()Ljava/util/Set; public final fun getName ()Ljava/lang/String; @@ -945,24 +985,29 @@ public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/Co public static final fun valueClassBuilder (Ljava/lang/String;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; } -public final class com/squareup/kotlinpoet/TypeSpec$Builder : com/squareup/kotlinpoet/ContextReceivable$Builder, com/squareup/kotlinpoet/OriginatingElementsHolder$Builder, com/squareup/kotlinpoet/Taggable$Builder { - public final fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public final fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public final fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public final fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public final fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; +public final class com/squareup/kotlinpoet/TypeSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/ContextReceivable$Builder, com/squareup/kotlinpoet/Documentable$Builder, com/squareup/kotlinpoet/OriginatingElementsHolder$Builder, com/squareup/kotlinpoet/Taggable$Builder { + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/AnnotationSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public synthetic fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public synthetic fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Ljava/lang/Class;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public synthetic fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotation (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public synthetic fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/Annotatable$Builder; + public fun addAnnotations (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addEnumConstant (Ljava/lang/String;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addEnumConstant (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public static synthetic fun addEnumConstant$default (Lcom/squareup/kotlinpoet/TypeSpec$Builder;Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeSpec;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addFunction (Lcom/squareup/kotlinpoet/FunSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addFunctions (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addInitializerBlock (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public final fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public final fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public synthetic fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Lcom/squareup/kotlinpoet/CodeBlock;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; + public synthetic fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Documentable$Builder; + public fun addKdoc (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addModifiers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addModifiers ([Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public synthetic fun addOriginatingElement (Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/OriginatingElementsHolder$Builder; - public fun addOriginatingElement (Ljavax/lang/model/element/Element;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addProperties (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addProperty (Lcom/squareup/kotlinpoet/PropertySpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun addProperty (Ljava/lang/String;Lcom/squareup/kotlinpoet/TypeName;Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; @@ -988,11 +1033,12 @@ public final class com/squareup/kotlinpoet/TypeSpec$Builder : com/squareup/kotli public final fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun build ()Lcom/squareup/kotlinpoet/TypeSpec; public synthetic fun contextReceivers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ContextReceivable$Builder; - public synthetic fun contextReceivers ([Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/ContextReceivable$Builder; public final fun getAnnotationSpecs ()Ljava/util/List; + public fun getAnnotations ()Ljava/util/List; public final fun getEnumConstants ()Ljava/util/Map; public final fun getFunSpecs ()Ljava/util/List; public final fun getInitializerIndex ()I + public fun getKdoc ()Lcom/squareup/kotlinpoet/CodeBlock$Builder; public final fun getModifiers ()Ljava/util/Set; public fun getOriginatingElements ()Ljava/util/List; public final fun getPropertySpecs ()Ljava/util/List; @@ -1006,10 +1052,6 @@ public final class com/squareup/kotlinpoet/TypeSpec$Builder : com/squareup/kotli public final fun superclass (Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun superclass (Ljava/lang/reflect/Type;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; public final fun superclass (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public synthetic fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Ljava/lang/Class;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; - public synthetic fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/Taggable$Builder; - public fun tag (Lkotlin/reflect/KClass;Ljava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder; } public final class com/squareup/kotlinpoet/TypeSpec$Companion { @@ -1038,6 +1080,7 @@ public final class com/squareup/kotlinpoet/TypeSpec$Kind : java/lang/Enum { public static final field CLASS Lcom/squareup/kotlinpoet/TypeSpec$Kind; public static final field INTERFACE Lcom/squareup/kotlinpoet/TypeSpec$Kind; public static final field OBJECT Lcom/squareup/kotlinpoet/TypeSpec$Kind; + public static fun getEntries ()Lkotlin/enums/EnumEntries; public static fun valueOf (Ljava/lang/String;)Lcom/squareup/kotlinpoet/TypeSpec$Kind; public static fun values ()[Lcom/squareup/kotlinpoet/TypeSpec$Kind; } @@ -1048,6 +1091,7 @@ public final class com/squareup/kotlinpoet/TypeVariableName : com/squareup/kotli public synthetic fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/TypeName; public fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/TypeVariableName; public static synthetic fun copy$default (Lcom/squareup/kotlinpoet/TypeVariableName;ZLjava/util/List;Ljava/util/List;ZLjava/util/Map;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeVariableName; + public fun equals (Ljava/lang/Object;)Z public static final fun get (Ljava/lang/String;)Lcom/squareup/kotlinpoet/TypeVariableName; public static final fun get (Ljava/lang/String;Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/TypeVariableName; public static final fun get (Ljava/lang/String;Ljava/util/List;)Lcom/squareup/kotlinpoet/TypeVariableName; @@ -1065,6 +1109,7 @@ public final class com/squareup/kotlinpoet/TypeVariableName : com/squareup/kotli public static final fun getWithClasses (Ljava/lang/String;Ljava/lang/Iterable;Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/TypeVariableName; public static final fun getWithTypes (Ljava/lang/String;Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeVariableName; public static final fun getWithTypes (Ljava/lang/String;Ljava/lang/Iterable;Lcom/squareup/kotlinpoet/KModifier;)Lcom/squareup/kotlinpoet/TypeVariableName; + public fun hashCode ()I public final fun isReified ()Z } @@ -1105,8 +1150,10 @@ public final class com/squareup/kotlinpoet/WildcardTypeName : com/squareup/kotli public static final fun consumerOf (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/WildcardTypeName; public synthetic fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/TypeName; public fun copy (ZLjava/util/List;Ljava/util/Map;)Lcom/squareup/kotlinpoet/WildcardTypeName; + public fun equals (Ljava/lang/Object;)Z public final fun getInTypes ()Ljava/util/List; public final fun getOutTypes ()Ljava/util/List; + public fun hashCode ()I public static final fun producerOf (Lcom/squareup/kotlinpoet/TypeName;)Lcom/squareup/kotlinpoet/WildcardTypeName; public static final fun producerOf (Ljava/lang/reflect/Type;)Lcom/squareup/kotlinpoet/WildcardTypeName; public static final fun producerOf (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/WildcardTypeName; diff --git a/kotlinpoet/build.gradle.kts b/kotlinpoet/build.gradle.kts index 830f870f..9627b60a 100644 --- a/kotlinpoet/build.gradle.kts +++ b/kotlinpoet/build.gradle.kts @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - tasks.jar { manifest { attributes("Automatic-Module-Name" to "com.squareup.kotlinpoet") @@ -21,8 +20,8 @@ tasks.jar { } tasks.compileTestKotlin { - kotlinOptions { - freeCompilerArgs = listOf("-opt-in=com.squareup.kotlinpoet.DelicateKotlinPoetApi") + compilerOptions { + freeCompilerArgs.add("-opt-in=com.squareup.kotlinpoet.DelicateKotlinPoetApi") } } @@ -43,6 +42,7 @@ dependencies { implementation(libs.kotlin.reflect) testImplementation(libs.kotlin.junit) testImplementation(libs.truth) + testImplementation(libs.guava) testImplementation(libs.compileTesting) testImplementation(libs.jimfs) testImplementation(libs.ecj) diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Annotatable.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Annotatable.kt new file mode 100644 index 00000000..25533105 --- /dev/null +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Annotatable.kt @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.kotlinpoet + +import kotlin.reflect.KClass + +/** A spec or type which can be annotated. */ +public interface Annotatable { + public val annotations: List<AnnotationSpec> + + public interface Builder<out T : Builder<T>> { + public val annotations: MutableList<AnnotationSpec> + + @Suppress("UNCHECKED_CAST") + public fun addAnnotation(annotationSpec: AnnotationSpec): T = apply { + annotations += annotationSpec + } as T + + @Suppress("UNCHECKED_CAST") + public fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): T = apply { + for (annotationSpec in annotationSpecs) { + addAnnotation(annotationSpec) + } + } as T + + public fun addAnnotation(annotation: ClassName): T = addAnnotation(AnnotationSpec.builder(annotation).build()) + + @DelicateKotlinPoetApi( + message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + + "using the kotlinpoet-metadata APIs instead.", + ) + public fun addAnnotation(annotation: Class<*>): T = addAnnotation(annotation.asClassName()) + + public fun addAnnotation(annotation: KClass<*>): T = addAnnotation(annotation.asClassName()) + } +} diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/AnnotationSpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/AnnotationSpec.kt index d44264b6..a9390923 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/AnnotationSpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/AnnotationSpec.kt @@ -22,7 +22,8 @@ import javax.lang.model.element.AnnotationValue import javax.lang.model.element.TypeElement import javax.lang.model.element.VariableElement import javax.lang.model.type.TypeMirror -import javax.lang.model.util.SimpleAnnotationValueVisitor7 +import javax.lang.model.util.SimpleAnnotationValueVisitor8 +import kotlin.LazyThreadSafetyMode.NONE import kotlin.reflect.KClass /** A generated annotation on a declaration. */ @@ -40,6 +41,13 @@ public class AnnotationSpec private constructor( public val members: List<CodeBlock> = builder.members.toImmutableList() public val useSiteTarget: UseSiteTarget? = builder.useSiteTarget + /** Lazily-initialized toString of this AnnotationSpec. */ + private val cachedString by lazy(NONE) { + buildCodeString { + emit(this, inline = true, asParameter = false) + } + } + internal fun emit(codeWriter: CodeWriter, inline: Boolean, asParameter: Boolean = false) { if (!asParameter) { codeWriter.emit("@") @@ -96,9 +104,7 @@ public class AnnotationSpec private constructor( override fun hashCode(): Int = toString().hashCode() - override fun toString(): String = buildCodeString { - emit(this, inline = true, asParameter = false) - } + override fun toString(): String = cachedString public enum class UseSiteTarget(internal val keyword: String) { FILE("file"), @@ -156,7 +162,7 @@ public class AnnotationSpec private constructor( @OptIn(DelicateKotlinPoetApi::class) private class Visitor( val builder: CodeBlock.Builder, - ) : SimpleAnnotationValueVisitor7<CodeBlock.Builder, String>(builder) { + ) : SimpleAnnotationValueVisitor8<CodeBlock.Builder, String>(builder) { override fun defaultAction(o: Any, name: String) = builder.add(Builder.memberForValue(o)) @@ -209,7 +215,7 @@ public class AnnotationSpec private constructor( member.add("%L = ", method.name) if (value.javaClass.isArray) { member.add("arrayOf(⇥⇥") - for (i in 0 until Array.getLength(value)) { + for (i in 0..<Array.getLength(value)) { if (i > 0) member.add(", ") member.add(Builder.memberForValue(Array.get(value, i))) } diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ClassName.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ClassName.kt index 119d05af..5eeb21b0 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ClassName.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ClassName.kt @@ -17,6 +17,7 @@ package com.squareup.kotlinpoet +import java.util.ArrayDeque import javax.lang.model.element.Element import javax.lang.model.element.ElementKind import javax.lang.model.element.NestingKind.MEMBER @@ -74,6 +75,12 @@ public class ClassName internal constructor( /** From top to bottom. This will be `["java.util", "Map", "Entry"]` for `Map.Entry`. */ private val names = names.toImmutableList() + /** String representation of the names used when comparing to other ClassName */ + private val comparableNames = names.joinToString() + + /** String representation of the annotations used when comparing to other ClassName */ + private val comparableAnnotations = annotations.joinToString() + /** Fully qualified name using `.` as a separator, like `kotlin.collections.Map.Entry`. */ public val canonicalName: String = if (names[0].isEmpty()) names.subList(1, names.size).joinToString(".") else @@ -175,12 +182,31 @@ public class ClassName internal constructor( * com.example.Robot.Motor * com.example.RoboticVacuum * ``` + * Comparison is consistent with equals() */ - override fun compareTo(other: ClassName): Int = canonicalName.compareTo(other.canonicalName) + override fun compareTo(other: ClassName): Int = COMPARATOR.compare(this, other) override fun emit(out: CodeWriter) = out.emit(out.lookupName(this).escapeSegmentsIfNecessary()) + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + if (!super.equals(other)) return false + + other as ClassName + + if (names != other.names) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + names.hashCode() + return result + } + public companion object { /** * Returns a new [ClassName] instance for the given fully-qualified class name string. This @@ -212,6 +238,10 @@ public class ClassName internal constructor( require(names.size >= 2) { "couldn't make a guess for $classNameString" } return ClassName(names) } + + private val COMPARATOR: Comparator<ClassName> = compareBy<ClassName> { it.comparableNames } + .thenBy { it.isNullable } + .thenBy { it.comparableAnnotations } } } @@ -240,8 +270,45 @@ public fun Class<*>.asClassName(): ClassName { @JvmName("get") public fun KClass<*>.asClassName(): ClassName { - qualifiedName?.let { return ClassName.bestGuess(it) } - throw IllegalArgumentException("$this cannot be represented as a ClassName") + var qualifiedName = requireNotNull(qualifiedName) { "$this cannot be represented as a ClassName" } + + // First, check for Kotlin types whose enclosing class name is a type that is mapped to a JVM + // class. Thus, the class backing the nested Kotlin type does not have an enclosing class + // (i.e., a parent) and the normal algorithm will fail. + val names = when (qualifiedName) { + "kotlin.Boolean.Companion" -> listOf("kotlin", "Boolean", "Companion") + "kotlin.Byte.Companion" -> listOf("kotlin", "Byte", "Companion") + "kotlin.Char.Companion" -> listOf("kotlin", "Char", "Companion") + "kotlin.Double.Companion" -> listOf("kotlin", "Double", "Companion") + "kotlin.Enum.Companion" -> listOf("kotlin", "Enum", "Companion") + "kotlin.Float.Companion" -> listOf("kotlin", "Float", "Companion") + "kotlin.Int.Companion" -> listOf("kotlin", "Int", "Companion") + "kotlin.Long.Companion" -> listOf("kotlin", "Long", "Companion") + "kotlin.Short.Companion" -> listOf("kotlin", "Short", "Companion") + "kotlin.String.Companion" -> listOf("kotlin", "String", "Companion") + else -> { + val names = ArrayDeque<String>() + var target: Class<*>? = java + while (target != null) { + target = target.enclosingClass + + val dot = qualifiedName.lastIndexOf('.') + if (dot == -1) { + if (target != null) throw AssertionError(this) // More enclosing classes than dots. + names.addFirst(qualifiedName) + qualifiedName = "" + } else { + names.addFirst(qualifiedName.substring(dot + 1)) + qualifiedName = qualifiedName.substring(0, dot) + } + } + + names.addFirst(qualifiedName) + names.toList() + } + } + + return ClassName(names) } /** Returns the class name for `element`. */ diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeBlock.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeBlock.kt index 61b4b202..6c8e4bba 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeBlock.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeBlock.kt @@ -108,12 +108,12 @@ public class CodeBlock private constructor( firstFormatPart?.let { resultFormatParts.add(it) } - for (i in prefix.formatParts.size until formatParts.size) { + for (i in prefix.formatParts.size..<formatParts.size) { resultFormatParts.add(formatParts[i]) } val resultArgs = ArrayList<Any?>() - for (i in prefix.args.size until args.size) { + for (i in prefix.args.size..<args.size) { resultArgs.add(args[i]) } diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt index 2884c65b..ff1de015 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt @@ -428,13 +428,14 @@ internal class CodeWriter constructor( // We don't care about nullability and type annotations here, as it's irrelevant for imports. if (resolved == c.copy(nullable = false, annotations = emptyList())) { - if (alias != null) return alias - val suffixOffset = c.simpleNames.size - 1 - referencedNames.add(className.topLevelClassName().simpleName) - return className.simpleNames.subList( - suffixOffset, + if (alias == null) { + referencedNames.add(className.topLevelClassName().simpleName) + } + val nestedClassNames = className.simpleNames.subList( + c.simpleNames.size, className.simpleNames.size, ).joinToString(".") + return "$simpleName.$nestedClassNames" } c = c.enclosingClassName() } @@ -616,7 +617,7 @@ internal class CodeWriter constructor( } private fun emitIndentation() { - for (j in 0 until indentLevel) { + for (j in 0..<indentLevel) { out.appendNonWrapping(indent) } } @@ -638,6 +639,10 @@ internal class CodeWriter constructor( return true } + if (implicitModifiers.contains(KModifier.PUBLIC) && modifiers.contains(KModifier.OVERRIDE)) { + return false + } + if (!implicitModifiers.contains(KModifier.PUBLIC)) { return false } @@ -706,14 +711,12 @@ internal class CodeWriter constructor( .generateImports( generatedImports, canonicalName = ClassName::canonicalName, - packageName = ClassName::packageName, capitalizeAliases = true, ) val suggestedMemberImports = importsCollector.suggestedMemberImports() .generateImports( generatedImports, canonicalName = MemberName::canonicalName, - packageName = MemberName::packageName, capitalizeAliases = false, ) importsCollector.close() @@ -730,7 +733,6 @@ internal class CodeWriter constructor( private fun <T> Map<String, Set<T>>.generateImports( generatedImports: MutableMap<String, Import>, canonicalName: T.() -> String, - packageName: T.() -> String, capitalizeAliases: Boolean, ): Map<String, T> { return flatMap { (simpleName, qualifiedNames) -> @@ -740,7 +742,7 @@ internal class CodeWriter constructor( generatedImports[canonicalName] = Import(canonicalName) } } else { - generateImportAliases(simpleName, qualifiedNames, packageName, capitalizeAliases) + generateImportAliases(simpleName, qualifiedNames, canonicalName, capitalizeAliases) .onEach { (alias, qualifiedName) -> val canonicalName = qualifiedName.canonicalName() generatedImports[canonicalName] = Import(canonicalName, alias) @@ -752,11 +754,14 @@ internal class CodeWriter constructor( private fun <T> generateImportAliases( simpleName: String, qualifiedNames: Set<T>, - packageName: T.() -> String, + canonicalName: T.() -> String, capitalizeAliases: Boolean, ): List<Pair<String, T>> { - val packageNameSegments = qualifiedNames.associateWith { qualifiedName -> - qualifiedName.packageName().split('.').map { it.replaceFirstChar(Char::uppercaseChar) } + val canonicalNameSegments = qualifiedNames.associateWith { qualifiedName -> + qualifiedName.canonicalName().split('.') + .dropLast(1) // Last segment of the canonical name is the simple name, drop it to avoid repetition. + .filter { it != "Companion" } + .map { it.replaceFirstChar(Char::uppercaseChar) } } val aliasNames = mutableMapOf<String, T>() var segmentsToUse = 0 @@ -764,7 +769,7 @@ internal class CodeWriter constructor( while (aliasNames.size != qualifiedNames.size) { segmentsToUse += 1 aliasNames.clear() - for ((qualifiedName, segments) in packageNameSegments) { + for ((qualifiedName, segments) in canonicalNameSegments) { val aliasPrefix = segments.takeLast(min(segmentsToUse, segments.size)) .joinToString(separator = "") .replaceFirstChar { if (!capitalizeAliases) it.lowercaseChar() else it } diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ContextReceivable.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ContextReceivable.kt index 929096bc..127c3605 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ContextReceivable.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ContextReceivable.kt @@ -23,6 +23,7 @@ public interface ContextReceivable { public val contextReceiverTypes: List<TypeName> /** The builder analogue to [ContextReceivable] types. */ + @JvmDefaultWithCompatibility public interface Builder<out T : Builder<T>> { /** Mutable map of the current originating elements this builder contains. */ diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Documentable.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Documentable.kt new file mode 100644 index 00000000..3dff284e --- /dev/null +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Documentable.kt @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.kotlinpoet + +/** A spec which contains documentation. */ +public interface Documentable { + public val kdoc: CodeBlock + + @Suppress("UNCHECKED_CAST") + public interface Builder<out T : Builder<T>> { + public val kdoc: CodeBlock.Builder + + public fun addKdoc(format: String, vararg args: Any): T = apply { + kdoc.add(format, *args) + } as T + + public fun addKdoc(block: CodeBlock): T = apply { + kdoc.add(block) + } as T + } +} diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FileSpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FileSpec.kt index b2f2549d..ef3f032c 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FileSpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FileSpec.kt @@ -46,8 +46,8 @@ import kotlin.reflect.KClass public class FileSpec private constructor( builder: Builder, private val tagMap: TagMap = builder.buildTagMap(), -) : Taggable by tagMap { - public val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() +) : Taggable by tagMap, Annotatable { + override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() public val comment: CodeBlock = builder.comment.build() public val packageName: String = builder.packageName public val name: String = builder.name @@ -230,7 +230,8 @@ public class FileSpec private constructor( public val packageName: String, public val name: String, public val isScript: Boolean, - ) : Taggable.Builder<Builder> { + ) : Taggable.Builder<Builder>, Annotatable.Builder<Builder> { + override val annotations: MutableList<AnnotationSpec> = mutableListOf() internal val comment = CodeBlock.builder() internal val memberImports = sortedSetOf<Import>() internal var indent = DEFAULT_INDENT @@ -239,7 +240,6 @@ public class FileSpec private constructor( public val defaultImports: MutableSet<String> = mutableSetOf() public val imports: List<Import> get() = memberImports.toList() public val members: MutableList<Any> = mutableListOf() - public val annotations: MutableList<AnnotationSpec> = mutableListOf() internal val body = CodeBlock.builder() /** @@ -248,7 +248,7 @@ public class FileSpec private constructor( * The annotation must either have a [`file` use-site target][AnnotationSpec.UseSiteTarget.FILE] * or not have a use-site target specified (in which case it will be changed to `file`). */ - public fun addAnnotation(annotationSpec: AnnotationSpec): Builder = apply { + override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = apply { val spec = when (annotationSpec.useSiteTarget) { FILE -> annotationSpec null -> annotationSpec.toBuilder().useSiteTarget(FILE).build() @@ -259,15 +259,6 @@ public class FileSpec private constructor( annotations += spec } - public fun addAnnotation(annotation: ClassName): Builder = - addAnnotation(AnnotationSpec.builder(annotation).build()) - - public fun addAnnotation(annotation: Class<*>): Builder = - addAnnotation(annotation.asClassName()) - - public fun addAnnotation(annotation: KClass<*>): Builder = - addAnnotation(annotation.asClassName()) - /** Adds a file-site comment. This is prefixed to the start of the file and different from [addBodyComment]. */ public fun addFileComment(format: String, vararg args: Any): Builder = apply { comment.add(format.replace(' ', '·'), *args) @@ -501,6 +492,24 @@ public class FileSpec private constructor( body.clear() } + //region Overrides for binary compatibility + @Suppress("RedundantOverride") + override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = + super.addAnnotations(annotationSpecs) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: ClassName): Builder = super.addAnnotation(annotation) + + @DelicateKotlinPoetApi( + message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + + "using the kotlinpoet-metadata APIs instead.", + ) + override fun addAnnotation(annotation: Class<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: KClass<*>): Builder = super.addAnnotation(annotation) + //endregion + public fun build(): FileSpec { for (annotationSpec in annotations) { if (annotationSpec.useSiteTarget != FILE) { @@ -527,6 +536,10 @@ public class FileSpec private constructor( return builder(className.packageName, className.simpleName) } + @JvmStatic public fun builder(memberName: MemberName): Builder { + return builder(memberName.packageName, memberName.simpleName) + } + @JvmStatic public fun builder(packageName: String, fileName: String): Builder = Builder(packageName, fileName, isScript = false) diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FunSpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FunSpec.kt index 2aa75ffc..f42308ea 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FunSpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FunSpec.kt @@ -38,17 +38,21 @@ public class FunSpec private constructor( private val tagMap: TagMap = builder.buildTagMap(), private val delegateOriginatingElementsHolder: OriginatingElementsHolder = builder.buildOriginatingElements(), private val contextReceivers: ContextReceivers = builder.buildContextReceivers(), -) : Taggable by tagMap, OriginatingElementsHolder by delegateOriginatingElementsHolder, ContextReceivable by contextReceivers { +) : Taggable by tagMap, + OriginatingElementsHolder by delegateOriginatingElementsHolder, + ContextReceivable by contextReceivers, + Annotatable, + Documentable { public val name: String = builder.name - public val kdoc: CodeBlock = builder.kdoc.build() + override val kdoc: CodeBlock = builder.kdoc.build() public val returnKdoc: CodeBlock = builder.returnKdoc public val receiverKdoc: CodeBlock = builder.receiverKdoc - public val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() + override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() public val modifiers: Set<KModifier> = builder.modifiers.toImmutableSet() public val typeVariables: List<TypeVariableName> = builder.typeVariables.toImmutableList() public val receiverType: TypeName? = builder.receiverType - public val returnType: TypeName? = builder.returnType + public val returnType: TypeName = builder.returnType public val parameters: List<ParameterSpec> = builder.parameters.toImmutableList() public val delegateConstructor: String? = builder.delegateConstructor public val delegateConstructorArguments: List<CodeBlock> = @@ -165,10 +169,8 @@ public class FunSpec private constructor( } } - if (returnType != null) { + if (returnType != UNIT || emitUnitReturnType()) { codeWriter.emitCode(": %T", returnType) - } else if (emitUnitReturnType()) { - codeWriter.emitCode(": %T", UNIT) } if (delegateConstructor != null) { @@ -217,10 +219,7 @@ public class FunSpec private constructor( /** * Returns whether [Unit] should be emitted as the return type. * - * [Unit] is emitted as return type on a function unless: - * - It's a constructor - * - It's a getter/setter on a property - * - It's an expression body + * [Unit] is emitted as return type on a function only if it is an expression body. */ private fun emitUnitReturnType(): Boolean { if (isConstructor) { @@ -231,7 +230,7 @@ public class FunSpec private constructor( return false } - return body.asExpressionBody() == null + return body.asExpressionBody() != null } private fun CodeBlock.asExpressionBody(): CodeBlock? { @@ -304,49 +303,28 @@ public class FunSpec private constructor( public class Builder internal constructor( internal val name: String, - ) : Taggable.Builder<Builder>, OriginatingElementsHolder.Builder<Builder>, ContextReceivable.Builder<Builder> { - internal val kdoc = CodeBlock.builder() + ) : Taggable.Builder<Builder>, + OriginatingElementsHolder.Builder<Builder>, + ContextReceivable.Builder<Builder>, + Annotatable.Builder<Builder>, + Documentable.Builder<Builder> { internal var returnKdoc = CodeBlock.EMPTY internal var receiverKdoc = CodeBlock.EMPTY internal var receiverType: TypeName? = null - internal var returnType: TypeName? = null + internal var returnType: TypeName = UNIT internal var delegateConstructor: String? = null internal var delegateConstructorArguments = listOf<CodeBlock>() internal val body = CodeBlock.builder() - - public val annotations: MutableList<AnnotationSpec> = mutableListOf() + override val kdoc: CodeBlock.Builder = CodeBlock.builder() + override val annotations: MutableList<AnnotationSpec> = mutableListOf() public val modifiers: MutableList<KModifier> = mutableListOf() public val typeVariables: MutableList<TypeVariableName> = mutableListOf() public val parameters: MutableList<ParameterSpec> = mutableListOf() override val tags: MutableMap<KClass<*>, Any> = mutableMapOf() override val originatingElements: MutableList<Element> = mutableListOf() - override val contextReceiverTypes: MutableList<TypeName> = mutableListOf() - - public fun addKdoc(format: String, vararg args: Any): Builder = apply { - kdoc.add(format, *args) - } - - public fun addKdoc(block: CodeBlock): Builder = apply { - kdoc.add(block) - } - - public fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = apply { - this.annotations += annotationSpecs - } - - public fun addAnnotation(annotationSpec: AnnotationSpec): Builder = apply { - annotations += annotationSpec - } - - public fun addAnnotation(annotation: ClassName): Builder = apply { - annotations += AnnotationSpec.builder(annotation).build() - } - - public fun addAnnotation(annotation: Class<*>): Builder = - addAnnotation(annotation.asClassName()) - public fun addAnnotation(annotation: KClass<*>): Builder = - addAnnotation(annotation.asClassName()) + @ExperimentalKotlinPoetApi + override val contextReceiverTypes: MutableList<TypeName> = mutableListOf() public fun addModifiers(vararg modifiers: KModifier): Builder = apply { this.modifiers += modifiers @@ -558,6 +536,33 @@ public class FunSpec private constructor( body.clear() } + //region Overrides for binary compatibility + @Suppress("RedundantOverride") + override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = super.addAnnotation(annotationSpec) + + @Suppress("RedundantOverride") + override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = + super.addAnnotations(annotationSpecs) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: ClassName): Builder = super.addAnnotation(annotation) + + @DelicateKotlinPoetApi( + message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + + "using the kotlinpoet-metadata APIs instead.", + ) + override fun addAnnotation(annotation: Class<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: KClass<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addKdoc(format: String, vararg args: Any): Builder = super.addKdoc(format, *args) + + @Suppress("RedundantOverride") + override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block) + //endregion + public fun build(): FunSpec { check(typeVariables.isEmpty() || !name.isAccessor) { "$name cannot have type variables" } check(!(name == GETTER && parameters.isNotEmpty())) { "$name cannot have parameters" } @@ -581,6 +586,9 @@ public class FunSpec private constructor( @JvmStatic public fun builder(name: String): Builder = Builder(name) + /** Create a new function builder from [MemberName.simpleName] */ + @JvmStatic public fun builder(memberName: MemberName): Builder = Builder(memberName.simpleName) + @JvmStatic public fun constructorBuilder(): Builder = Builder(CONSTRUCTOR) @JvmStatic public fun getterBuilder(): Builder = Builder(GETTER) diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LambdaTypeName.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LambdaTypeName.kt index efb3b837..9f462f81 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LambdaTypeName.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LambdaTypeName.kt @@ -84,6 +84,31 @@ public class LambdaTypeName private constructor( return out } + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + if (!super.equals(other)) return false + + other as LambdaTypeName + + if (receiver != other.receiver) return false + if (contextReceivers != other.contextReceivers) return false + if (returnType != other.returnType) return false + if (isSuspending != other.isSuspending) return false + if (parameters != other.parameters) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + (receiver?.hashCode() ?: 0) + result = 31 * result + contextReceivers.hashCode() + result = 31 * result + returnType.hashCode() + result = 31 * result + isSuspending.hashCode() + result = 31 * result + parameters.hashCode() + return result + } public companion object { /** Returns a lambda type with `returnType` and parameters listed in `parameters`. */ @ExperimentalKotlinPoetApi @JvmStatic diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LineWrapper.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LineWrapper.kt index 83a155b0..3a1e9a6b 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LineWrapper.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LineWrapper.kt @@ -110,7 +110,7 @@ internal class LineWrapper( var start = 0 var columnCount = segments[0].length - for (i in 1 until segments.size) { + for (i in 1..<segments.size) { val segment = segments[i] val newColumnCount = columnCount + 1 + segment.length @@ -136,7 +136,7 @@ internal class LineWrapper( // If this is a wrapped line we need a newline and an indent. if (startIndex > 0) { out.append("\n") - for (i in 0 until indentLevel) { + for (i in 0..<indentLevel) { out.append(indent) } out.append(linePrefix) @@ -144,7 +144,7 @@ internal class LineWrapper( // Emit each segment separated by spaces. out.append(segments[startIndex]) - for (i in startIndex + 1 until endIndex) { + for (i in startIndex + 1..<endIndex) { out.append(" ") out.append(segments[i]) } diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/OriginatingElementsHolder.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/OriginatingElementsHolder.kt index 27008213..4e877742 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/OriginatingElementsHolder.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/OriginatingElementsHolder.kt @@ -24,6 +24,7 @@ public interface OriginatingElementsHolder { public val originatingElements: List<Element> /** The builder analogue to [OriginatingElementsHolder] types. */ + @JvmDefaultWithCompatibility public interface Builder<out T : Builder<T>> { /** Mutable map of the current originating elements this builder contains. */ diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterSpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterSpec.kt index 9c33ecd9..15cf4bf0 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterSpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterSpec.kt @@ -29,10 +29,10 @@ import kotlin.reflect.KClass public class ParameterSpec private constructor( builder: Builder, private val tagMap: TagMap = builder.buildTagMap(), -) : Taggable by tagMap { +) : Taggable by tagMap, Annotatable, Documentable { public val name: String = builder.name - public val kdoc: CodeBlock = builder.kdoc.build() - public val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() + override val kdoc: CodeBlock = builder.kdoc.build() + override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() public val modifiers: Set<KModifier> = builder.modifiers .also { LinkedHashSet(it).apply { @@ -96,39 +96,13 @@ public class ParameterSpec private constructor( public class Builder internal constructor( internal val name: String, internal val type: TypeName, - ) : Taggable.Builder<Builder> { + ) : Taggable.Builder<Builder>, Annotatable.Builder<Builder>, Documentable.Builder<Builder> { internal var defaultValue: CodeBlock? = null - public val kdoc: CodeBlock.Builder = CodeBlock.builder() - public val annotations: MutableList<AnnotationSpec> = mutableListOf() public val modifiers: MutableList<KModifier> = mutableListOf() + override val kdoc: CodeBlock.Builder = CodeBlock.builder() override val tags: MutableMap<KClass<*>, Any> = mutableMapOf() - - public fun addKdoc(format: String, vararg args: Any): Builder = apply { - kdoc.add(format, *args) - } - - public fun addKdoc(block: CodeBlock): Builder = apply { - kdoc.add(block) - } - - public fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = apply { - annotations += annotationSpecs - } - - public fun addAnnotation(annotationSpec: AnnotationSpec): Builder = apply { - annotations += annotationSpec - } - - public fun addAnnotation(annotation: ClassName): Builder = apply { - annotations += AnnotationSpec.builder(annotation).build() - } - - public fun addAnnotation(annotation: Class<*>): Builder = - addAnnotation(annotation.asClassName()) - - public fun addAnnotation(annotation: KClass<*>): Builder = - addAnnotation(annotation.asClassName()) + override val annotations: MutableList<AnnotationSpec> = mutableListOf() public fun addModifiers(vararg modifiers: KModifier): Builder = apply { this.modifiers += modifiers @@ -154,6 +128,33 @@ public class ParameterSpec private constructor( this.defaultValue = codeBlock } + //region Overrides for binary compatibility + @Suppress("RedundantOverride") + override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = super.addAnnotation(annotationSpec) + + @Suppress("RedundantOverride") + override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = + super.addAnnotations(annotationSpecs) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: ClassName): Builder = super.addAnnotation(annotation) + + @DelicateKotlinPoetApi( + message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + + "using the kotlinpoet-metadata APIs instead.", + ) + override fun addAnnotation(annotation: Class<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: KClass<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addKdoc(format: String, vararg args: Any): Builder = super.addKdoc(format, *args) + + @Suppress("RedundantOverride") + override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block) + //endregion + public fun build(): ParameterSpec = ParameterSpec(this) } diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterizedTypeName.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterizedTypeName.kt index ffbcf388..b6bdf798 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterizedTypeName.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterizedTypeName.kt @@ -103,6 +103,28 @@ public class ParameterizedTypeName internal constructor( public fun nestedClass(name: String, typeArguments: List<TypeName>): ParameterizedTypeName = ParameterizedTypeName(this, rawType.nestedClass(name), typeArguments) + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + if (!super.equals(other)) return false + + other as ParameterizedTypeName + + if (enclosingType != other.enclosingType) return false + if (rawType != other.rawType) return false + if (typeArguments != other.typeArguments) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + (enclosingType?.hashCode() ?: 0) + result = 31 * result + rawType.hashCode() + result = 31 * result + typeArguments.hashCode() + return result + } + public companion object { /** Returns a parameterized type, applying `typeArguments` to `this`. */ @JvmStatic diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/PropertySpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/PropertySpec.kt index 8fb58602..9ba9409c 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/PropertySpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/PropertySpec.kt @@ -30,12 +30,16 @@ public class PropertySpec private constructor( private val tagMap: TagMap = builder.buildTagMap(), private val delegateOriginatingElementsHolder: OriginatingElementsHolder = builder.buildOriginatingElements(), private val contextReceivers: ContextReceivers = builder.buildContextReceivers(), -) : Taggable by tagMap, OriginatingElementsHolder by delegateOriginatingElementsHolder, ContextReceivable by contextReceivers { +) : Taggable by tagMap, + OriginatingElementsHolder by delegateOriginatingElementsHolder, + ContextReceivable by contextReceivers, + Annotatable, + Documentable { public val mutable: Boolean = builder.mutable public val name: String = builder.name public val type: TypeName = builder.type - public val kdoc: CodeBlock = builder.kdoc.build() - public val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() + override val kdoc: CodeBlock = builder.kdoc.build() + override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() public val modifiers: Set<KModifier> = builder.modifiers.toImmutableSet() public val typeVariables: List<TypeVariableName> = builder.typeVariables.toImmutableList() public val initializer: CodeBlock? = builder.initializer @@ -56,12 +60,6 @@ public class PropertySpec private constructor( require(mutable || setter == null) { "only a mutable property can have a setter" } - if (contextReceiverTypes.isNotEmpty()) { - requireNotNull(getter) { "properties with context receivers require a $GETTER" } - if (mutable) { - requireNotNull(setter) { "mutable properties with context receivers require a $SETTER" } - } - } } internal fun emit( @@ -176,21 +174,25 @@ public class PropertySpec private constructor( internal val type: TypeName, ) : Taggable.Builder<Builder>, OriginatingElementsHolder.Builder<Builder>, - ContextReceivable.Builder<Builder> { + ContextReceivable.Builder<Builder>, + Annotatable.Builder<Builder>, + Documentable.Builder<Builder> { internal var isPrimaryConstructorParameter = false internal var mutable = false - internal val kdoc = CodeBlock.builder() internal var initializer: CodeBlock? = null internal var delegated = false internal var getter: FunSpec? = null internal var setter: FunSpec? = null internal var receiverType: TypeName? = null - public val annotations: MutableList<AnnotationSpec> = mutableListOf() public val modifiers: MutableList<KModifier> = mutableListOf() public val typeVariables: MutableList<TypeVariableName> = mutableListOf() override val tags: MutableMap<KClass<*>, Any> = mutableMapOf() + override val kdoc: CodeBlock.Builder = CodeBlock.builder() override val originatingElements: MutableList<Element> = mutableListOf() + override val annotations: MutableList<AnnotationSpec> = mutableListOf() + + @ExperimentalKotlinPoetApi override val contextReceiverTypes: MutableList<TypeName> = mutableListOf() /** True to create a `var` instead of a `val`. */ @@ -198,36 +200,6 @@ public class PropertySpec private constructor( this.mutable = mutable } - public fun addKdoc(format: String, vararg args: Any): Builder = apply { - kdoc.add(format, *args) - } - - public fun addKdoc(block: CodeBlock): Builder = apply { - kdoc.add(block) - } - - public fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = apply { - annotations += annotationSpecs - } - - public fun addAnnotation(annotationSpec: AnnotationSpec): Builder = apply { - annotations += annotationSpec - } - - public fun addAnnotation(annotation: ClassName): Builder = apply { - annotations += AnnotationSpec.builder(annotation).build() - } - - @DelicateKotlinPoetApi( - message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + - "using the kotlinpoet-metadata APIs instead.", - ) - public fun addAnnotation(annotation: Class<*>): Builder = - addAnnotation(annotation.asClassName()) - - public fun addAnnotation(annotation: KClass<*>): Builder = - addAnnotation(annotation.asClassName()) - public fun addModifiers(vararg modifiers: KModifier): Builder = apply { this.modifiers += modifiers } @@ -282,6 +254,33 @@ public class PropertySpec private constructor( public fun receiver(receiverType: KClass<*>): Builder = receiver(receiverType.asTypeName()) + //region Overrides for binary compatibility + @Suppress("RedundantOverride") + override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = super.addAnnotation(annotationSpec) + + @Suppress("RedundantOverride") + override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = + super.addAnnotations(annotationSpecs) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: ClassName): Builder = super.addAnnotation(annotation) + + @DelicateKotlinPoetApi( + message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + + "using the kotlinpoet-metadata APIs instead.", + ) + override fun addAnnotation(annotation: Class<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: KClass<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addKdoc(format: String, vararg args: Any): Builder = super.addKdoc(format, *args) + + @Suppress("RedundantOverride") + override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block) + //endregion + public fun build(): PropertySpec { if (KModifier.INLINE in modifiers) { throw IllegalArgumentException( diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Taggable.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Taggable.kt index 74ff690a..f3313aea 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Taggable.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Taggable.kt @@ -18,6 +18,7 @@ package com.squareup.kotlinpoet import kotlin.reflect.KClass /** A type that can be tagged with extra metadata of the user's choice. */ +@JvmDefaultWithCompatibility public interface Taggable { /** Returns all tags. */ @@ -33,6 +34,7 @@ public interface Taggable { } /** The builder analogue to [Taggable] types. */ + @JvmDefaultWithCompatibility public interface Builder<out T : Builder<T>> { /** Mutable map of the current tags this builder contains. */ diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeAliasSpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeAliasSpec.kt index a0a90e2e..f9a607fb 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeAliasSpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeAliasSpec.kt @@ -26,13 +26,13 @@ import kotlin.reflect.KClass public class TypeAliasSpec private constructor( builder: Builder, private val tagMap: TagMap = builder.buildTagMap(), -) : Taggable by tagMap { +) : Taggable by tagMap, Annotatable, Documentable { public val name: String = builder.name public val type: TypeName = builder.type public val modifiers: Set<KModifier> = builder.modifiers.toImmutableSet() public val typeVariables: List<TypeVariableName> = builder.typeVariables.toImmutableList() - public val kdoc: CodeBlock = builder.kdoc.build() - public val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() + override val kdoc: CodeBlock = builder.kdoc.build() + override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() internal fun emit(codeWriter: CodeWriter) { codeWriter.emitKdoc(kdoc.ensureEndsWithNewLine()) @@ -69,13 +69,12 @@ public class TypeAliasSpec private constructor( public class Builder internal constructor( internal val name: String, internal val type: TypeName, - ) : Taggable.Builder<Builder> { - internal val kdoc = CodeBlock.builder() - + ) : Taggable.Builder<Builder>, Annotatable.Builder<Builder>, Documentable.Builder<Builder> { public val modifiers: MutableSet<KModifier> = mutableSetOf() public val typeVariables: MutableSet<TypeVariableName> = mutableSetOf() - public val annotations: MutableList<AnnotationSpec> = mutableListOf() override val tags: MutableMap<KClass<*>, Any> = mutableMapOf() + override val kdoc: CodeBlock.Builder = CodeBlock.builder() + override val annotations: MutableList<AnnotationSpec> = mutableListOf() public fun addModifiers(vararg modifiers: KModifier): Builder = apply { modifiers.forEach(this::addModifier) @@ -97,35 +96,32 @@ public class TypeAliasSpec private constructor( typeVariables += typeVariable } - public fun addKdoc(format: String, vararg args: Any): Builder = apply { - kdoc.add(format, *args) - } - - public fun addKdoc(block: CodeBlock): Builder = apply { - kdoc.add(block) - } - - public fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = apply { - this.annotations += annotationSpecs - } + //region Overrides for binary compatibility + @Suppress("RedundantOverride") + override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = super.addAnnotation(annotationSpec) - public fun addAnnotation(annotationSpec: AnnotationSpec): Builder = apply { - annotations += annotationSpec - } + @Suppress("RedundantOverride") + override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = + super.addAnnotations(annotationSpecs) - public fun addAnnotation(annotation: ClassName): Builder = apply { - annotations += AnnotationSpec.builder(annotation).build() - } + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: ClassName): Builder = super.addAnnotation(annotation) @DelicateKotlinPoetApi( message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + "using the kotlinpoet-metadata APIs instead.", ) - public fun addAnnotation(annotation: Class<*>): Builder = - addAnnotation(annotation.asClassName()) + override fun addAnnotation(annotation: Class<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: KClass<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addKdoc(format: String, vararg args: Any): Builder = super.addKdoc(format, *args) - public fun addAnnotation(annotation: KClass<*>): Builder = - addAnnotation(annotation.asClassName()) + @Suppress("RedundantOverride") + override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block) + //endregion public fun build(): TypeAliasSpec { for (it in modifiers) { diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt index bffcf4f1..60dea8bf 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt @@ -33,7 +33,7 @@ import javax.lang.model.type.NoType import javax.lang.model.type.PrimitiveType import javax.lang.model.type.TypeKind import javax.lang.model.type.TypeMirror -import javax.lang.model.util.SimpleTypeVisitor7 +import javax.lang.model.util.SimpleTypeVisitor8 import kotlin.reflect.KClass import kotlin.reflect.typeOf @@ -66,8 +66,8 @@ public sealed class TypeName constructor( public val isNullable: Boolean, annotations: List<AnnotationSpec>, internal val tagMap: TagMap, -) : Taggable by tagMap { - public val annotations: List<AnnotationSpec> = annotations.toImmutableList() +) : Taggable by tagMap, Annotatable { + override val annotations: List<AnnotationSpec> = annotations.toImmutableList() /** Lazily-initialized toString of this type name. */ private val cachedString: String by lazy { @@ -95,12 +95,22 @@ public sealed class TypeName constructor( override fun equals(other: Any?): Boolean { if (this === other) return true - if (other == null) return false - if (javaClass != other.javaClass) return false - return toString() == other.toString() + if (javaClass != other?.javaClass) return false + + other as TypeName + + if (isNullable != other.isNullable) return false + if (annotations != other.annotations) return false + // do not check for equality of tags, these are considered side-channel data + + return true } - override fun hashCode(): Int = toString().hashCode() + override fun hashCode(): Int { + var result = isNullable.hashCode() + result = 31 * result + annotations.hashCode() + return result + } override fun toString(): String = cachedString @@ -125,7 +135,7 @@ public sealed class TypeName constructor( typeVariables: Map<TypeParameterElement, TypeVariableName>, ): TypeName { return mirror.accept( - object : SimpleTypeVisitor7<TypeName, Void?>() { + object : SimpleTypeVisitor8<TypeName, Void?>() { override fun visitPrimitive(t: PrimitiveType, p: Void?): TypeName { return when (t.kind) { TypeKind.BOOLEAN -> BOOLEAN diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt index c8abca97..5f52e4ff 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt @@ -31,6 +31,7 @@ import com.squareup.kotlinpoet.KModifier.SEALED import com.squareup.kotlinpoet.KModifier.VALUE import java.lang.reflect.Type import javax.lang.model.element.Element +import kotlin.DeprecationLevel.ERROR import kotlin.reflect.KClass /** A generated class, interface, or enum declaration. */ @@ -42,11 +43,15 @@ public class TypeSpec private constructor( .plus(builder.typeSpecs.flatMap(TypeSpec::originatingElements)) .buildOriginatingElements(), private val contextReceivers: ContextReceivers = builder.buildContextReceivers(), -) : Taggable by tagMap, OriginatingElementsHolder by delegateOriginatingElements, ContextReceivable by contextReceivers { +) : Taggable by tagMap, + OriginatingElementsHolder by delegateOriginatingElements, + ContextReceivable by contextReceivers, + Annotatable, + Documentable { public val kind: Kind = builder.kind public val name: String? = builder.name - public val kdoc: CodeBlock = builder.kdoc.build() - public val annotationSpecs: List<AnnotationSpec> = builder.annotationSpecs.toImmutableList() + override val kdoc: CodeBlock = builder.kdoc.build() + override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList() public val modifiers: Set<KModifier> = builder.modifiers.toImmutableSet() public val typeVariables: List<TypeVariableName> = builder.typeVariables.toImmutableList() public val primaryConstructor: FunSpec? = builder.primaryConstructor @@ -74,12 +79,15 @@ public class TypeSpec private constructor( public val typeSpecs: List<TypeSpec> = builder.typeSpecs.toImmutableList() internal val nestedTypesSimpleNames = typeSpecs.map { it.name }.toImmutableSet() + @Deprecated("Use annotations property", ReplaceWith("annotations"), ERROR) + public val annotationSpecs: List<AnnotationSpec> get() = annotations + @JvmOverloads public fun toBuilder(kind: Kind = this.kind, name: String? = this.name): Builder { val builder = Builder(kind, name) builder.modifiers += modifiers builder.kdoc.add(kdoc) - builder.annotationSpecs += annotationSpecs + builder.annotations += annotations builder.typeVariables += typeVariables builder.superclass = superclass builder.superclassConstructorParameters += superclassConstructorParameters @@ -116,8 +124,8 @@ public class TypeSpec private constructor( try { if (enumName != null) { - codeWriter.emitKdoc(kdocWithConstructorParameters()) - codeWriter.emitAnnotations(annotationSpecs, false) + codeWriter.emitKdoc(kdocWithConstructorDocs()) + codeWriter.emitAnnotations(annotations, false) codeWriter.emitCode("%N", enumName) if (superclassConstructorParametersBlock.isNotEmpty()) { codeWriter.emit("(") @@ -156,9 +164,9 @@ public class TypeSpec private constructor( } codeWriter.emit(" {\n") } else { - codeWriter.emitKdoc(kdocWithConstructorParameters()) + codeWriter.emitKdoc(kdocWithConstructorDocs()) codeWriter.emitContextReceivers(contextReceiverTypes, suffix = "\n") - codeWriter.emitAnnotations(annotationSpecs, false) + codeWriter.emitAnnotations(annotations, false) codeWriter.emitModifiers( modifiers, if (isNestedExternal) setOf(PUBLIC, EXTERNAL) else setOf(PUBLIC), @@ -331,7 +339,7 @@ public class TypeSpec private constructor( // Properties added after the initializer are not permitted to be inlined into the constructor // due to ordering concerns. val range = if (hasInitializer) { - 0 until initializerIndex + 0..<initializerIndex } else { propertySpecs.indices } @@ -363,15 +371,15 @@ public class TypeSpec private constructor( } /** - * Returns KDoc comments including those of primary constructor parameters. + * Returns KDoc comments including those of the primary constructor and its parameters. * * If the primary constructor parameter is not mapped to a property, or if the property doesn't * have its own KDoc - the parameter's KDoc will be attached to the parameter. Otherwise, if both * the parameter and the property have KDoc - the property's KDoc will be attached to the * property/parameter, and the parameter's KDoc will be printed in the type header. */ - private fun kdocWithConstructorParameters(): CodeBlock { - if (primaryConstructor == null || primaryConstructor.parameters.isEmpty()) { + private fun kdocWithConstructorDocs(): CodeBlock { + if (primaryConstructor == null) { return kdoc.ensureEndsWithNewLine() } val constructorProperties = constructorProperties() @@ -381,8 +389,11 @@ public class TypeSpec private constructor( parameter.kdoc != propertyKdoc } return with(kdoc.ensureEndsWithNewLine().toBuilder()) { - parametersWithKdoc.forEachIndexed { index, parameter -> - if (index == 0 && kdoc.isNotEmpty()) add("\n") + if (kdoc.isNotEmpty()) add("\n") + if (primaryConstructor.kdoc.isNotEmpty()) { + add("@constructor %L", primaryConstructor.kdoc.ensureEndsWithNewLine()) + } + parametersWithKdoc.forEach { parameter -> add("@param %L %L", parameter.name, parameter.kdoc.ensureEndsWithNewLine()) } build() @@ -441,7 +452,6 @@ public class TypeSpec private constructor( internal fun implicitFunctionModifiers(modifiers: Set<KModifier> = setOf()): Set<KModifier> { return defaultImplicitFunctionModifiers + when { - ANNOTATION in modifiers -> setOf(ABSTRACT) EXPECT in modifiers -> setOf(EXPECT) EXTERNAL in modifiers -> setOf(EXTERNAL) else -> emptySet() @@ -461,8 +471,11 @@ public class TypeSpec private constructor( internal var kind: Kind, internal val name: String?, vararg modifiers: KModifier, - ) : Taggable.Builder<Builder>, OriginatingElementsHolder.Builder<Builder>, ContextReceivable.Builder<Builder> { - internal val kdoc = CodeBlock.builder() + ) : Taggable.Builder<Builder>, + OriginatingElementsHolder.Builder<Builder>, + ContextReceivable.Builder<Builder>, + Annotatable.Builder<Builder>, + Documentable.Builder<Builder> { internal var primaryConstructor: FunSpec? = null internal var superclass: TypeName = ANY internal val initializerBlock = CodeBlock.builder() @@ -478,48 +491,23 @@ public class TypeSpec private constructor( internal val isFunInterface get() = kind == Kind.INTERFACE && FUN in modifiers override val tags: MutableMap<KClass<*>, Any> = mutableMapOf() + override val kdoc: CodeBlock.Builder = CodeBlock.builder() override val originatingElements: MutableList<Element> = mutableListOf() + override val annotations: MutableList<AnnotationSpec> = mutableListOf() @ExperimentalKotlinPoetApi override val contextReceiverTypes: MutableList<TypeName> = mutableListOf() public val modifiers: MutableSet<KModifier> = mutableSetOf(*modifiers) public val superinterfaces: MutableMap<TypeName, CodeBlock?> = mutableMapOf() public val enumConstants: MutableMap<String, TypeSpec> = mutableMapOf() - public val annotationSpecs: MutableList<AnnotationSpec> = mutableListOf() public val typeVariables: MutableList<TypeVariableName> = mutableListOf() public val superclassConstructorParameters: MutableList<CodeBlock> = mutableListOf() public val propertySpecs: MutableList<PropertySpec> = mutableListOf() public val funSpecs: MutableList<FunSpec> = mutableListOf() public val typeSpecs: MutableList<TypeSpec> = mutableListOf() - public fun addKdoc(format: String, vararg args: Any): Builder = apply { - kdoc.add(format, *args) - } - - public fun addKdoc(block: CodeBlock): Builder = apply { - kdoc.add(block) - } - - public fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = apply { - this.annotationSpecs += annotationSpecs - } - - public fun addAnnotation(annotationSpec: AnnotationSpec): Builder = apply { - annotationSpecs += annotationSpec - } - - public fun addAnnotation(annotation: ClassName): Builder = - addAnnotation(AnnotationSpec.builder(annotation).build()) - - @DelicateKotlinPoetApi( - message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + - "using the kotlinpoet-metadata APIs instead.", - ) - public fun addAnnotation(annotation: Class<*>): Builder = - addAnnotation(annotation.asClassName()) - - public fun addAnnotation(annotation: KClass<*>): Builder = - addAnnotation(annotation.asClassName()) + @Deprecated("Use annotations property", ReplaceWith("annotations"), ERROR) + public val annotationSpecs: MutableList<AnnotationSpec> get() = annotations public fun addModifiers(vararg modifiers: KModifier): Builder = apply { check(!isAnonymousClass) { "forbidden on anonymous types." } @@ -751,6 +739,33 @@ public class TypeSpec private constructor( contextReceiverTypes += receiverTypes } + //region Overrides for binary compatibility + @Suppress("RedundantOverride") + override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = super.addAnnotation(annotationSpec) + + @Suppress("RedundantOverride") + override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder = + super.addAnnotations(annotationSpecs) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: ClassName): Builder = super.addAnnotation(annotation) + + @DelicateKotlinPoetApi( + message = "Java reflection APIs don't give complete information on Kotlin types. Consider " + + "using the kotlinpoet-metadata APIs instead.", + ) + override fun addAnnotation(annotation: Class<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addAnnotation(annotation: KClass<*>): Builder = super.addAnnotation(annotation) + + @Suppress("RedundantOverride") + override fun addKdoc(format: String, vararg args: Any): Builder = super.addKdoc(format, *args) + + @Suppress("RedundantOverride") + override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block) + //endregion + public fun build(): TypeSpec { if (enumConstants.isNotEmpty()) { check(isEnum) { "$name is not an enum and cannot have enum constants" } @@ -771,8 +786,7 @@ public class TypeSpec private constructor( "typevariables are forbidden on anonymous types" } - val isAbstract = ABSTRACT in modifiers || SEALED in modifiers || kind != Kind.CLASS || - !isSimpleClass + val isAbstract = ABSTRACT in modifiers || SEALED in modifiers || kind == Kind.INTERFACE || isEnum for (funSpec in funSpecs) { require(isAbstract || ABSTRACT !in funSpec.modifiers) { "non-abstract type $name cannot declare abstract function ${funSpec.name}" @@ -782,9 +796,8 @@ public class TypeSpec private constructor( requireNoneOf(funSpec.modifiers, INTERNAL, PROTECTED) requireNoneOrOneOf(funSpec.modifiers, ABSTRACT, PRIVATE) } - isAnnotation -> require(funSpec.modifiers == kind.implicitFunctionModifiers(modifiers)) { - "annotation class $name.${funSpec.name} " + - "requires modifiers ${kind.implicitFunctionModifiers(modifiers)}" + isAnnotation -> { + throw IllegalArgumentException("annotation class $name cannot declare member function ${funSpec.name}") } EXPECT in modifiers -> require(funSpec.body.isEmpty()) { "functions in expect classes can't have bodies" @@ -792,6 +805,26 @@ public class TypeSpec private constructor( } } + for (propertySpec in propertySpecs) { + require(isAbstract || ABSTRACT !in propertySpec.modifiers) { + "non-abstract type $name cannot declare abstract property ${propertySpec.name}" + } + if (propertySpec.contextReceiverTypes.isNotEmpty()) { + if (ABSTRACT !in kind.implicitPropertyModifiers(modifiers) + propertySpec.modifiers) { + requireNotNull(propertySpec.getter) { "non-abstract properties with context receivers require a ${FunSpec.GETTER}" } + if (propertySpec.mutable) { + requireNotNull(propertySpec.setter) { "non-abstract mutable properties with context receivers require a ${FunSpec.SETTER}" } + } + } + } + } + + if (isAnnotation) { + primaryConstructor?.let { + requireNoneOf(it.modifiers, INTERNAL, PROTECTED, PRIVATE, ABSTRACT) + } + } + if (primaryConstructor == null) { require(funSpecs.none { it.isConstructor } || superclassConstructorParameters.isEmpty()) { "types without a primary constructor cannot specify secondary constructors and " + @@ -853,22 +886,32 @@ public class TypeSpec private constructor( public companion object { @JvmStatic public fun classBuilder(name: String): Builder = Builder(Kind.CLASS, name) - @JvmStatic public fun classBuilder(className: ClassName): Builder = - classBuilder(className.simpleName) + @JvmStatic public fun classBuilder(className: ClassName): Builder = classBuilder(className.simpleName) - @JvmStatic public fun expectClassBuilder(name: String): Builder = - Builder(Kind.CLASS, name, EXPECT) + @Deprecated( + "Use classBuilder() instead. This function will be removed in KotlinPoet 2.0.", + ReplaceWith("TypeSpec.classBuilder(name).addModifiers(KModifier.EXPECT)"), + ) + @JvmStatic + public fun expectClassBuilder(name: String): Builder = Builder(Kind.CLASS, name, EXPECT) - @JvmStatic public fun expectClassBuilder(className: ClassName): Builder = - expectClassBuilder(className.simpleName) + @Deprecated( + "Use classBuilder() instead. This function will be removed in KotlinPoet 2.0.", + ReplaceWith("TypeSpec.classBuilder(className).addModifiers(KModifier.EXPECT)"), + ) + @JvmStatic + public fun expectClassBuilder(className: ClassName): Builder = classBuilder(className.simpleName).addModifiers(EXPECT) - @JvmStatic public fun valueClassBuilder(name: String): Builder = - Builder(Kind.CLASS, name, VALUE) + @Deprecated( + "Use classBuilder() instead. This function will be removed in KotlinPoet 2.0.", + ReplaceWith("TypeSpec.classBuilder(name).addModifiers(KModifier.VALUE)"), + ) + @JvmStatic + public fun valueClassBuilder(name: String): Builder = Builder(Kind.CLASS, name, VALUE) @JvmStatic public fun objectBuilder(name: String): Builder = Builder(Kind.OBJECT, name) - @JvmStatic public fun objectBuilder(className: ClassName): Builder = - objectBuilder(className.simpleName) + @JvmStatic public fun objectBuilder(className: ClassName): Builder = objectBuilder(className.simpleName) @JvmStatic @JvmOverloads public fun companionObjectBuilder(name: String? = null): Builder = diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeVariableName.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeVariableName.kt index b2d7517a..3313b2c9 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeVariableName.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeVariableName.kt @@ -71,6 +71,30 @@ public class TypeVariableName private constructor( override fun emit(out: CodeWriter) = out.emit(name) + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + if (!super.equals(other)) return false + + other as TypeVariableName + + if (name != other.name) return false + if (bounds != other.bounds) return false + if (variance != other.variance) return false + if (isReified != other.isReified) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + name.hashCode() + result = 31 * result + bounds.hashCode() + result = 31 * result + (variance?.hashCode() ?: 0) + result = 31 * result + isReified.hashCode() + return result + } + public companion object { internal fun of( name: String, diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/WildcardTypeName.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/WildcardTypeName.kt index f7c4dc0c..bd1e0965 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/WildcardTypeName.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/WildcardTypeName.kt @@ -52,6 +52,26 @@ public class WildcardTypeName private constructor( } } + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (javaClass != other?.javaClass) return false + if (!super.equals(other)) return false + + other as WildcardTypeName + + if (outTypes != other.outTypes) return false + if (inTypes != other.inTypes) return false + + return true + } + + override fun hashCode(): Int { + var result = super.hashCode() + result = 31 * result + outTypes.hashCode() + result = 31 * result + inTypes.hashCode() + return result + } + public companion object { /** * Returns a type that represents an unknown type that produces `outType`. For example, if diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt index 6f18620e..fcaae681 100644 --- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt +++ b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt @@ -126,10 +126,19 @@ public fun TypeName.jvmWildcard(): TypeName = copy(annotations = this.annotations + AnnotationSpec.builder(JvmWildcard::class).build()) @Suppress("DEPRECATION") -@Deprecated("'JvmDefault' is deprecated. Switch to new -Xjvm-default modes: `all` or `all-compatibility`") -public fun PropertySpec.Builder.jvmDefault(): PropertySpec.Builder = - addAnnotation(JvmDefault::class) +@Deprecated( + """ + 'JvmDefault' is deprecated. Switch to new -Xjvm-default modes: `all` or `all-compatibility`. + In KotlinPoet 1.15.0 and newer, this method is a no-op. It will be deleted in KotlinPoet 2.0. +""", +) +public fun PropertySpec.Builder.jvmDefault(): PropertySpec.Builder = this @Suppress("DEPRECATION") -@Deprecated("'JvmDefault' is deprecated. Switch to new -Xjvm-default modes: `all` or `all-compatibility`") -public fun FunSpec.Builder.jvmDefault(): FunSpec.Builder = addAnnotation(JvmDefault::class) +@Deprecated( + """ + 'JvmDefault' is deprecated. Switch to new -Xjvm-default modes: `all` or `all-compatibility`. + In KotlinPoet 1.15.0 and newer, this method is a no-op. It will be deleted in KotlinPoet 2.0. +""", +) +public fun FunSpec.Builder.jvmDefault(): FunSpec.Builder = this diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotationSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotationSpecTest.kt index 4f770406..fff366f3 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotationSpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotationSpecTest.kt @@ -318,9 +318,8 @@ class AnnotationSpecTest { |package test | |import kotlin.Suppress - |import kotlin.Unit | - |public fun test(): Unit { + |public fun test() { | @Suppress("Things") | val annotatedString = "AnnotatedString" |} @@ -339,7 +338,7 @@ class AnnotationSpecTest { assertThat(funSpec.toString().trim()).isEqualTo( """ - |public fun operation(): kotlin.Unit { + |public fun operation() { | @Suppress("UNCHECKED_CAST") |} """.trimMargin(), @@ -474,6 +473,7 @@ class AnnotationSpecTest { FunSpec.builder("create") .addModifiers(OVERRIDE) .addParameter("parcel", parcel) + .returns(externalClass) .addStatement("return %T(parcel.readInt())", externalClass) .build(), ) @@ -558,16 +558,15 @@ class AnnotationSpecTest { package com.squareup.parceler import kotlin.Int - import kotlin.Unit public class ExternalClass( public val `value`: Int, ) public object ExternalClassParceler : Parceler<ExternalClass> { - public override fun create(parcel: Parcel) = ExternalClass(parcel.readInt()) + override fun create(parcel: Parcel): ExternalClass = ExternalClass(parcel.readInt()) - public override fun ExternalClass.write(parcel: Parcel, flags: Int): Unit { + override fun ExternalClass.write(parcel: Parcel, flags: Int) { parcel.writeInt(value) } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/Cased/Weird/Sup.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/Cased/Weird/Sup.kt new file mode 100644 index 00000000..8d3f439b --- /dev/null +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/Cased/Weird/Sup.kt @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.kotlinpoet.Cased.Weird // ktlint-disable package-name + +object Sup { + object Hi +} diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ClassNameTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ClassNameTest.kt index 6d06806c..92e4f144 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ClassNameTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ClassNameTest.kt @@ -17,6 +17,7 @@ package com.squareup.kotlinpoet import com.google.common.truth.Truth.assertThat import com.google.testing.compile.CompilationRule +import com.squareup.kotlinpoet.Cased.Weird.Sup import org.junit.Rule import kotlin.test.Test import kotlin.test.assertEquals @@ -109,6 +110,25 @@ class ClassNameTest { .isEqualTo("kotlin.Any") assertThat(OuterClass.InnerClass::class.asClassName().toString()) .isEqualTo("com.squareup.kotlinpoet.ClassNameTest.OuterClass.InnerClass") + + // Note: Do NOT rewrite this assertion to something more clever since behaviors + // like TypeName.equals may subvert the correct partitioning of package and names. + val hi = Sup.Hi::class.asClassName() + assertThat(hi.packageName).isEqualTo("com.squareup.kotlinpoet.Cased.Weird") + assertThat(hi.simpleNames).containsExactly("Sup", "Hi").inOrder() + } + + @Test fun classNameFromKClassSpecialCases() { + assertEquals(ClassName(listOf("kotlin", "Boolean", "Companion")), Boolean.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "Byte", "Companion")), Byte.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "Char", "Companion")), Char.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "Double", "Companion")), Double.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "Enum", "Companion")), Enum.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "Float", "Companion")), Float.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "Int", "Companion")), Int.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "Long", "Companion")), Long.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "Short", "Companion")), Short.Companion::class.asClassName()) + assertEquals(ClassName(listOf("kotlin", "String", "Companion")), String.Companion::class.asClassName()) } @Test fun peerClass() { @@ -188,9 +208,8 @@ class ClassNameTest { |package com.squareup.tacos | |import com.squareup.`taco factory`.`Taco Factory` - |import kotlin.Unit | - |public fun main(): Unit { + |public fun main() { | println(`Taco Factory`.produceTacos()) |} |""".trimMargin() @@ -220,4 +239,144 @@ class ClassNameTest { "[Foo, Bar, ]" ) } + + @Test fun equalsAndHashCode() { + val foo1 = ClassName(names = listOf("com.example", "Foo")) + val foo2 = ClassName(names = listOf("com.example", "Foo")) + assertThat(foo1).isEqualTo(foo2) + assertThat(foo1.hashCode()).isEqualTo(foo2.hashCode()) + } + + @Test fun equalsDifferentiatesPackagesFromSimpleNames() { + val outerFoo = ClassName("com.example.Foo", "Bar") + val packageFoo = ClassName("com.example", "Foo", "Bar") + + assertThat(outerFoo).isNotEqualTo(packageFoo) + } + + @Test fun equalsDifferentiatesNullabilityAndAnnotations() { + val foo = ClassName(names = listOf("com.example", "Foo")) + assertThat(foo.copy(annotations = listOf(AnnotationSpec.Builder(Suppress::class.asClassName()).build()))).isNotEqualTo(foo) + assertThat(foo.copy(nullable = true)).isNotEqualTo(foo) + } + + @Test fun equalsAndHashCodeIgnoreTags() { + val foo = ClassName(names = listOf("com.example", "Foo")) + val taggedFoo = foo.copy(tags = mapOf(String::class to "test")) + + assertThat(foo).isEqualTo(taggedFoo) + assertThat(foo.hashCode()).isEqualTo(taggedFoo.hashCode()) + } + + @Test fun compareTo() { + val robot = ClassName("com.example", "Robot") + val robotMotor = ClassName("com.example", "Robot", "Motor") + val roboticVacuum = ClassName("com.example", "RoboticVacuum") + + val list = listOf(robot, robotMotor, roboticVacuum) + + assertThat(list.sorted()).isEqualTo(listOf(robot, robotMotor, roboticVacuum)) + } + + @Test fun compareToConsistentWithEquals() { + val foo1 = ClassName(names = listOf("com.example", "Foo")) + val foo2 = ClassName(names = listOf("com.example", "Foo")) + assertThat(foo1.compareTo(foo2)).isEqualTo(0) + } + + @Test fun compareToDifferentiatesPackagesFromSimpleNames() { + val parentFooNestedBar = ClassName("com.example", "Foo", "Bar") + val packageFooClassBar = ClassName("com.example.Foo", "Bar") + val parentFooNestedBaz = ClassName("com.example", "Foo", "Baz") + val packageFooClassBaz = ClassName("com.example.Foo", "Baz") + val parentGooNestedBar = ClassName("com.example", "Goo", "Bar") + val packageGooClassBar = ClassName("com.example.Goo", "Bar") + + val list = listOf( + parentFooNestedBar, + packageFooClassBar, + parentFooNestedBaz, + packageFooClassBaz, + parentGooNestedBar, + packageGooClassBar, + ) + + assertThat(list.sorted()).isEqualTo( + listOf( + parentFooNestedBar, + parentFooNestedBaz, + parentGooNestedBar, + packageFooClassBar, + packageFooClassBaz, + packageGooClassBar, + ), + ) + } + + @Test fun compareToDifferentiatesNullabilityAndAnnotations() { + val plain = ClassName( + listOf("com.example", "Foo") + ) + val nullable = ClassName( + listOf("com.example", "Foo"), + nullable = true, + ) + val annotated = ClassName( + listOf("com.example", "Foo"), + nullable = true, + annotations = listOf( + AnnotationSpec.Builder(Suppress::class.asClassName()).build(), + ), + ) + + val list = listOf(plain, nullable, annotated) + + assertThat(list.sorted()).isEqualTo( + listOf(plain, nullable, annotated), + ) + } + + @Test fun compareToDifferentiatesByAnnotation() { + val noAnnotations = ClassName(listOf("com.example", "Foo")) + + val oneAnnotation = ClassName( + listOf("com.example", "Foo"), + annotations = listOf(AnnotationSpec.Builder(Suppress::class.asClassName()).build()), + ) + val twoAnnotations = ClassName( + listOf("com.example", "Foo"), + annotations = listOf( + AnnotationSpec.Builder(Suppress::class.asClassName()).build(), + AnnotationSpec.Builder(Test::class.asClassName()).build(), + ), + ) + val secondAnnotationOnly = ClassName( + listOf("com.example", "Foo"), + annotations = listOf( + AnnotationSpec.Builder(Test::class.asClassName()).build(), + ), + ) + + val list = listOf(noAnnotations, oneAnnotation, twoAnnotations, secondAnnotationOnly) + + assertThat(list.sorted()).isEqualTo( + listOf(noAnnotations, oneAnnotation, twoAnnotations, secondAnnotationOnly), + ) + } + + @Test fun compareToDoesNotDifferentiateByTag() { + val noTags = ClassName(listOf("com.example", "Foo")) + + val oneTag = ClassName( + listOf("com.example", "Foo"), + tags = mapOf(String::class to "test"), + ) + val twoTags = ClassName( + listOf("com.example", "Foo"), + tags = mapOf(String::class to "test", Int::class to 1), + ) + + assertThat(noTags.compareTo(oneTag)).isEqualTo(0) + assertThat(oneTag.compareTo(twoTags)).isEqualTo(0) + } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt index 23ef0568..dc52f38e 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt @@ -517,9 +517,7 @@ class CodeBlockTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | - |public fun test(): Unit { + |public fun test() { | if ("Very long string that would wrap the line " == | "Very long string that would wrap the line ") { | } else if ("Long string that would wrap the line 2 " == diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt index 5074b913..cc119be5 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt @@ -25,9 +25,9 @@ class CrossplatformTest { @Test fun crossplatform() { val expectTypeParam = TypeVariableName("V") val expectType = "AtomicRef" - val expectSpec = TypeSpec.expectClassBuilder(expectType) + val expectSpec = TypeSpec.classBuilder(expectType) .addTypeVariable(expectTypeParam) - .addModifiers(KModifier.INTERNAL) + .addModifiers(KModifier.INTERNAL, KModifier.EXPECT) .primaryConstructor( FunSpec.constructorBuilder() .addParameter("value", expectTypeParam) @@ -72,7 +72,6 @@ class CrossplatformTest { """ |import java.util.concurrent.atomic.AtomicReference |import kotlin.Boolean - |import kotlin.Unit | |internal expect class AtomicRef<V>( | `value`: V, @@ -81,7 +80,7 @@ class CrossplatformTest { | | public fun `get`(): V | - | public fun `set`(`value`: V): Unit + | public fun `set`(`value`: V) | | public fun getAndSet(`value`: V): V | @@ -95,8 +94,8 @@ class CrossplatformTest { } @Test fun expectWithSecondaryConstructors() { - val expectSpec = TypeSpec.expectClassBuilder("IoException") - .addModifiers(KModifier.OPEN) + val expectSpec = TypeSpec.classBuilder("IoException") + .addModifiers(KModifier.EXPECT, KModifier.OPEN) .superclass(Exception::class) .addFunction(FunSpec.constructorBuilder().build()) .addFunction( @@ -157,6 +156,7 @@ class CrossplatformTest { .addFunction( FunSpec.builder("f1") .addModifiers(KModifier.ACTUAL) + .returns(INT) .addStatement("return 1") .build(), ) @@ -168,7 +168,7 @@ class CrossplatformTest { | |public expect fun f1(): Int | - |public actual fun f1() = 1 + |public actual fun f1(): Int = 1 | """.trimMargin(), ) @@ -176,14 +176,16 @@ class CrossplatformTest { @Test fun initBlockInExpectForbidden() { assertThrows<IllegalStateException> { - TypeSpec.expectClassBuilder("AtomicRef") + TypeSpec.classBuilder("AtomicRef") + .addModifiers(KModifier.EXPECT) .addInitializerBlock(CodeBlock.of("println()")) }.hasMessageThat().isEqualTo("expect CLASS can't have initializer blocks") } @Test fun expectFunctionBodyForbidden() { assertThrows<IllegalArgumentException> { - TypeSpec.expectClassBuilder("AtomicRef") + TypeSpec.classBuilder("AtomicRef") + .addModifiers(KModifier.EXPECT) .addFunction( FunSpec.builder("print") .addStatement("println()") @@ -195,7 +197,8 @@ class CrossplatformTest { @Test fun expectPropertyInitializerForbidden() { assertThrows<IllegalArgumentException> { - TypeSpec.expectClassBuilder("AtomicRef") + TypeSpec.classBuilder("AtomicRef") + .addModifiers(KModifier.EXPECT) .addProperty( PropertySpec.builder("a", Boolean::class) .initializer("true") @@ -206,7 +209,8 @@ class CrossplatformTest { @Test fun expectPropertyGetterForbidden() { assertThrows<IllegalArgumentException> { - TypeSpec.expectClassBuilder("AtomicRef") + TypeSpec.classBuilder("AtomicRef") + .addModifiers(KModifier.EXPECT) .addProperty( PropertySpec.builder("a", Boolean::class) .getter( @@ -221,7 +225,8 @@ class CrossplatformTest { @Test fun expectPropertySetterForbidden() { assertThrows<IllegalArgumentException> { - TypeSpec.expectClassBuilder("AtomicRef") + TypeSpec.classBuilder("AtomicRef") + .addModifiers(KModifier.EXPECT) .addProperty( PropertySpec.builder("a", Boolean::class) .mutable() diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt index 5cb7753c..00b0c88c 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt @@ -26,7 +26,7 @@ class ExpectDeclarationsTest { assertThat(methodSpec.toString()).isEqualTo( """ - |public expect fun function(): kotlin.Unit + |public expect fun function() | """.trimMargin(), ) @@ -42,7 +42,7 @@ class ExpectDeclarationsTest { assertThat(builder.build().toString()).isEqualTo( """ |public expect class Test { - | public fun function(): kotlin.Unit + | public fun function() |} | """.trimMargin(), diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt index 42719c41..8cc5f496 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt @@ -26,7 +26,7 @@ class ExternalDeclarationsTest { assertThat(methodSpec.toString()).isEqualTo( """ - |public external fun function(): kotlin.Unit + |public external fun function() | """.trimMargin(), ) @@ -35,12 +35,13 @@ class ExternalDeclarationsTest { @Test fun externalFunDeclarationWithDefinedExternally() { val methodSpec = FunSpec.builder("function") .addModifiers(KModifier.EXTERNAL) + .returns(STRING) .addCode("return kotlin.js.definedExternally") .build() assertThat(methodSpec.toString()).isEqualTo( """ - |public external fun function() = kotlin.js.definedExternally + |public external fun function(): kotlin.String = kotlin.js.definedExternally | """.trimMargin(), ) @@ -54,7 +55,7 @@ class ExternalDeclarationsTest { assertThat(methodSpec.toString()).isEqualTo( """ - |public external fun function(): kotlin.Unit { + |public external fun function() { | kotlin.js.definedExternally |} | @@ -72,7 +73,7 @@ class ExternalDeclarationsTest { assertThat(builder.build().toString()).isEqualTo( """ |public external class Test { - | public fun function(): kotlin.Unit + | public fun function() |} | """.trimMargin(), @@ -83,6 +84,7 @@ class ExternalDeclarationsTest { val builder = TypeSpec.classBuilder("Test") .addModifiers(KModifier.EXTERNAL) val methodSpec = FunSpec.builder("function") + .returns(STRING) .addCode("return kotlin.js.definedExternally") .build() builder.addFunction(methodSpec) @@ -90,7 +92,7 @@ class ExternalDeclarationsTest { assertThat(builder.build().toString()).isEqualTo( """ |public external class Test { - | public fun function() = kotlin.js.definedExternally + | public fun function(): kotlin.String = kotlin.js.definedExternally |} | """.trimMargin(), @@ -109,7 +111,7 @@ class ExternalDeclarationsTest { assertThat(builder.build().toString()).isEqualTo( """ |public external class Test { - | public fun function(): kotlin.Unit { + | public fun function() { | kotlin.js.definedExternally | } |} diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileSpecTest.kt index 03b3cfc0..c363f592 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileSpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileSpecTest.kt @@ -413,9 +413,8 @@ class FileSpecTest { |package com.example | |import com.squareup.`taco factory`.TacoFactory - |import kotlin.Unit | - |public fun main(): Unit { + |public fun main() { | println(TacoFactory.produceTacos()) |} | @@ -437,10 +436,9 @@ class FileSpecTest { """ |package com.example | - |import kotlin.Unit |import com.squareup.`taco factory`.TacoFactory as `La Taqueria` | - |public fun main(): Unit { + |public fun main() { | println(`La Taqueria`.produceTacos()) |} | @@ -492,10 +490,9 @@ class FileSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit |import java.util.concurrent.TimeUnit.MINUTES as MINS | - |public fun sleepForFiveMins(): Unit { + |public fun sleepForFiveMins() { | MINS.sleep(5) |} | @@ -726,10 +723,9 @@ class FileSpecTest { |import java.lang.System |import kotlin.Array |import kotlin.String - |import kotlin.Unit | |public class HelloWorld { - | public fun main(args: Array<String>): Unit { + | public fun main(args: Array<String>) { | System.out.println("Hello World!"); | } |} @@ -1041,9 +1037,7 @@ class FileSpecTest { """ |package com.squareup.taco.enchilada.quesadillas.tamales.burritos.`super`.burritos.trying.to.`get`.a.really.large.packagename | - |import kotlin.Unit - | - |public fun foo(): Unit { + |public fun foo() { |} | """.trimMargin(), @@ -1123,16 +1117,15 @@ class FileSpecTest { | |import com.squareup.kotlinpoet.FileSpecTest |import kotlin.String - |import kotlin.Unit |import kotlin.collections.Collection |import kotlin.collections.List |import kotlin.collections.Map | - |public fun f1(): Unit { + |public fun f1() { | // this is a long line with a possibly long parameterized type with annotation: List<Map<in String, Collection<Map<FileSpecTest.WackyKey, out FileSpecTest.OhNoThisDoesNotCompile>>>> |} | - |public fun f2(): Unit { + |public fun f2() { | // this is a very very very very very very very very very very long line with a very long lambda type: suspend String.(foo: List<Map<in String, Collection<Map<FileSpecTest.WackyKey, out FileSpecTest.OhNoThisDoesNotCompile>>>>) -> String |} | @@ -1158,13 +1151,12 @@ class FileSpecTest { assertThat(spec.toString()).isEqualTo( """ |import kotlin.String - |import kotlin.Unit | |val prop: String = "hi" | |println("hello!") | - |public fun localFun(): Unit { + |public fun localFun() { |} | |public class Yay @@ -1212,4 +1204,11 @@ class FileSpecTest { FileSpec.builder(className) } } + + @Test fun memberNameFactory() { + val memberName = MemberName("com.example", "Example") + val spec = FileSpec.builder(memberName).build() + assertThat(spec.packageName).isEqualTo(memberName.packageName) + assertThat(spec.name).isEqualTo(memberName.simpleName) + } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileWritingTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileWritingTest.kt index 39807095..83574f31 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileWritingTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileWritingTest.kt @@ -260,12 +260,11 @@ class FileWritingTest { |import java.lang.System |import java.util.Date |import kotlin.Array - |import kotlin.Unit | |public class Test { |${"\t"}public val madeFreshDate: Date | - |${"\t"}public fun main(args: Array<String>): Unit { + |${"\t"}public fun main(args: Array<String>) { |${"\t\t"}System.out.println("Hello World!"); |${"\t"}} |} diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt index 1376cafc..4fff9fe3 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt @@ -168,7 +168,7 @@ class FunSpecTest { .build() assertThat(funSpec.toString()).isEqualTo( """ - |public fun foo(string: kotlin.String?): kotlin.Unit { + |public fun foo(string: kotlin.String?) { |} | """.trimMargin(), @@ -195,7 +195,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ - |public fun foo(): kotlin.Unit { + |public fun foo() { |} | """.trimMargin(), @@ -272,7 +272,7 @@ class FunSpecTest { | string: kotlin.String, | number: kotlin.Int, | nodoc: kotlin.Boolean, - |): kotlin.Unit { + |) { |} | """.trimMargin(), @@ -295,7 +295,7 @@ class FunSpecTest { |/** | * @param string A string parameter. This is non null | */ - |public fun foo(string: kotlin.String): kotlin.Unit { + |public fun foo(string: kotlin.String) { |} | """.trimMargin(), @@ -378,7 +378,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ - |public fun foo(): kotlin.Unit { + |public fun foo() { | throwOrDoSomethingElse() |} | @@ -388,12 +388,13 @@ class FunSpecTest { @Test fun expressionBodyIsDetectedReturnWithNonBreakingSpace() { val funSpec = FunSpec.builder("foo") + .returns(INT) .addStatement("return·1") .build() assertThat(funSpec.toString()).isEqualTo( """ - |public fun foo() = 1 + |public fun foo(): kotlin.Int = 1 | """.trimMargin(), ) @@ -493,7 +494,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ |context(kotlin.String) - |public fun foo(): kotlin.Unit { + |public fun foo() { |} | """.trimMargin(), @@ -511,7 +512,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ |context(kotlin.String, kotlin.Int, kotlin.Boolean) - |public fun foo(): kotlin.Unit { + |public fun foo() { |} | """.trimMargin(), @@ -528,7 +529,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ |context(T) - |public fun <T> foo(): kotlin.Unit { + |public fun <T> foo() { |} | """.trimMargin(), @@ -545,7 +546,7 @@ class FunSpecTest { """ |context(kotlin.String) |@com.squareup.kotlinpoet.FunSpecTest.TestAnnotation - |public fun foo(): kotlin.Unit { + |public fun foo() { |} | """.trimMargin(), @@ -561,7 +562,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ |context(@com.squareup.kotlinpoet.FunSpecTest.TestAnnotation kotlin.String) - |public fun foo(): kotlin.Unit { + |public fun foo() { |} | """.trimMargin(), @@ -715,7 +716,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ - |public private internal fun myMethod(): kotlin.Unit { + |public private internal fun myMethod() { |} | """.trimMargin(), @@ -730,7 +731,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ - |public fun myMethod(): kotlin.Unit { + |public fun myMethod() { |} | """.trimMargin(), @@ -847,7 +848,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ - |public fun `if`(): kotlin.Unit { + |public fun `if`() { |} | """.trimMargin(), @@ -860,7 +861,7 @@ class FunSpecTest { assertThat(funSpec.toString()).isEqualTo( """ - |public fun `with-hyphen`(): kotlin.Unit { + |public fun `with-hyphen`() { |} | """.trimMargin(), @@ -1044,7 +1045,7 @@ class FunSpecTest { assertThat(builder.build().toString()).isEqualTo( """ |@kotlin.jvm.JvmStatic - |internal fun staticMethod(): kotlin.Unit { + |internal fun staticMethod() { |} | """.trimMargin(), @@ -1057,7 +1058,7 @@ class FunSpecTest { assertThat(builder.build().toString()).isEqualTo( """ - |internal final fun finalMethod(): kotlin.Unit { + |internal final fun finalMethod() { |} | """.trimMargin(), @@ -1071,7 +1072,7 @@ class FunSpecTest { assertThat(builder.build().toString()).isEqualTo( """ |@kotlin.jvm.Synchronized - |internal fun synchronizedMethod(): kotlin.Unit { + |internal fun synchronizedMethod() { |} | """.trimMargin(), @@ -1085,7 +1086,7 @@ class FunSpecTest { assertThat(methodSpec.toString()).isEqualTo( """ - |public fun function(): kotlin.Unit { + |public fun function() { | codeWithNoNewline() |} | @@ -1101,7 +1102,7 @@ class FunSpecTest { assertThat(methodSpec.toString()).isEqualTo( """ - |public fun function(): kotlin.Unit { + |public fun function() { | codeWithNoNewline() |} | @@ -1112,12 +1113,13 @@ class FunSpecTest { // https://github.com/square/kotlinpoet/issues/947 @Test fun ensureTrailingNewlineWithExpressionBody() { val methodSpec = FunSpec.builder("function") + .returns(STRING) .addCode("return codeWithNoNewline()") .build() assertThat(methodSpec.toString()).isEqualTo( """ - |public fun function() = codeWithNoNewline() + |public fun function(): kotlin.String = codeWithNoNewline() | """.trimMargin(), ) @@ -1125,12 +1127,13 @@ class FunSpecTest { @Test fun ensureTrailingNewlineWithExpressionBodyAndExistingNewline() { val methodSpec = FunSpec.builder("function") + .returns(STRING) .addCode("return codeWithNoNewline()\n") // Have a newline already, so ensure we're not adding one .build() assertThat(methodSpec.toString()).isEqualTo( """ - |public fun function() = codeWithNoNewline() + |public fun function(): kotlin.String = codeWithNoNewline() | """.trimMargin(), ) @@ -1146,7 +1149,7 @@ class FunSpecTest { |/** | * This is a comment with no initial newline | */ - |public fun function(): kotlin.Unit { + |public fun function() { |} | """.trimMargin(), @@ -1164,7 +1167,7 @@ class FunSpecTest { |/** | * This is a comment with an initial newline | */ - |public fun function(): kotlin.Unit { + |public fun function() { |} | """.trimMargin(), @@ -1187,7 +1190,7 @@ class FunSpecTest { | |import kotlin.Unit | - |public fun (@Annotation () -> Unit).foo(): Unit { + |public fun (@Annotation () -> Unit).foo() { |} | """.trimMargin(), @@ -1216,4 +1219,18 @@ class FunSpecTest { """.trimMargin(), ) } + + @Test fun memberNameBuilder() { + val name = MemberName("com.example", "myCoolFunction") + val spec = FunSpec.builder(name) + .returns(STRING) + .addStatement("""return "hey"""") + .build() + assertThat(spec.toString()).isEqualTo( + """ + |public fun myCoolFunction(): kotlin.String = "hey" + | + """.trimMargin(), + ) + } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/KotlinPoetTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/KotlinPoetTest.kt index 9d3f1711..642b65c5 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/KotlinPoetTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/KotlinPoetTest.kt @@ -47,16 +47,15 @@ class KotlinPoetTest { |package com.squareup.tacos | |import kotlin.String - |import kotlin.Unit | - |public fun a(): Unit { + |public fun a() { |} | |public class B | |public val c: String = "C" | - |public fun d(): Unit { + |public fun d() { |} | |public class E @@ -224,19 +223,17 @@ class KotlinPoetTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public class Taco { - | public fun a(): Unit { + | public fun a() { | } | - | protected fun b(): Unit { + | protected fun b() { | } | - | internal fun c(): Unit { + | internal fun c() { | } | - | private fun d(): Unit { + | private fun d() { | } |} | @@ -260,10 +257,8 @@ class KotlinPoetTest { "" + "package com.squareup.tacos\n" + "\n" + - "import kotlin.Unit\n" + - "\n" + "public class Taco {\n" + - " public fun strings(): Unit {\n" + + " public fun strings() {\n" + " val a = \"basic string\"\n" + " val b = \"string with a \${\'\$\'} dollar sign\"\n" + " }\n" + @@ -305,10 +300,8 @@ class KotlinPoetTest { "" + "package com.squareup.tacos\n" + "\n" + - "import kotlin.Unit\n" + - "\n" + "public class Taco {\n" + - " public fun strings(): Unit {\n" + + " public fun strings() {\n" + " val a = \"\"\"\n" + " |\"\n" + " |\"\"\".trimMargin()\n" + @@ -351,10 +344,8 @@ class KotlinPoetTest { "" + "package com.squareup.tacos\n" + "\n" + - "import kotlin.Unit\n" + - "\n" + "public class Taco {\n" + - " public fun strings(): Unit {\n" + + " public fun strings() {\n" + " val a = \"\"\"\n" + " |\n" + " |\"\"\".trimMargin()\n" + @@ -387,10 +378,9 @@ class KotlinPoetTest { |package com.squareup.tacos | |import kotlin.String - |import kotlin.Unit | |public class Taco { - | public fun addCheese(kind: String = "monterey jack"): Unit { + | public fun addCheese(kind: String = "monterey jack") { | } |} | @@ -792,13 +782,11 @@ class KotlinPoetTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public var bar: suspend (Foo) -> Bar = { Bar() } | |public var nullBar: (suspend (Foo) -> Bar)? = null | - |public fun foo(bar: suspend (Foo) -> Bar): Unit { + |public fun foo(bar: suspend (Foo) -> Bar) { |} | """.trimMargin(), @@ -825,9 +813,8 @@ class KotlinPoetTest { | |import java.util.concurrent.TimeUnit |import kotlin.Long - |import kotlin.Unit | - |public fun timeout(duration: Long, timeUnit: TimeUnit = TimeUnit.MILLISECONDS): Unit { + |public fun timeout(duration: Long, timeUnit: TimeUnit = TimeUnit.MILLISECONDS) { | this.timeout = timeUnit.toMillis(duration) |} | @@ -864,9 +851,7 @@ class KotlinPoetTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | - |public fun dynamicTest(): Unit { + |public fun dynamicTest() { | val d1: dynamic = "Taco" | val d2: dynamic = 1f | // dynamics are dangerous! @@ -929,11 +914,10 @@ class KotlinPoetTest { |package com.squareup.tacos | |import kotlin.Int - |import kotlin.Unit |import kotlin.collections.List |import kotlin.jvm.JvmSuppressWildcards | - |public fun foo(a: List<@JvmSuppressWildcards Int>): Unit { + |public fun foo(a: List<@JvmSuppressWildcards Int>) { |} | """.trimMargin(), @@ -1031,11 +1015,9 @@ class KotlinPoetTest { |package com.squareup.tacos | |import kotlin.String - |import kotlin.Unit | |public - | fun functionWithAPrettyLongNameThatWouldCauseWrapping(parameterWithALongNameThatWouldAlsoCauseWrapping: String): - | Unit { + | fun functionWithAPrettyLongNameThatWouldCauseWrapping(parameterWithALongNameThatWouldAlsoCauseWrapping: String) { |} | """.trimMargin(), @@ -1154,9 +1136,8 @@ class KotlinPoetTest { |package com.squareup.example | |import com.squareup.tacos.Taco - |import kotlin.Unit | - |public fun main(): Unit { + |public fun main() { | println(${'"'}""Here's a taco: ${'$'}{Taco()}""${'"'}) |} | @@ -1179,10 +1160,9 @@ class KotlinPoetTest { """ |package com.squareup.example | - |import kotlin.Unit |import kotlin.collections.contentToString | - |public fun main(): Unit { + |public fun main() { | val ints = arrayOf(1, 2, 3) | println(${'"'}""${'$'}{ints.contentToString()}""${'"'}) |} @@ -1217,7 +1197,7 @@ class KotlinPoetTest { | * @param a Progress in % | * @param b Some other parameter with % | */ - |public fun test(a: kotlin.Int, b: kotlin.Int): kotlin.Unit { + |public fun test(a: kotlin.Int, b: kotlin.Int) { |} | """.trimMargin(), @@ -1248,10 +1228,8 @@ class KotlinPoetTest { """ |package test | - |import kotlin.Unit - | |public class Exception : kotlin.Exception() { - | public fun test(e: Exception): Unit { + | public fun test(e: Exception) { | } |} | @@ -1316,13 +1294,12 @@ class KotlinPoetTest { """ |package com.example | - |import kotlin.Unit |import com.squareup.cash.util.isNullOrEmpty as utilIsNullOrEmpty |import com.squareup.tacos.Taco as SquareupTacosTaco |import kotlin.text.isNullOrEmpty as textIsNullOrEmpty |import xyz.block.tacos.Taco as BlockTacosTaco | - |public fun main(): Unit { + |public fun main() { | val squareTaco = ::SquareupTacosTaco | val blockTaco = ::BlockTacosTaco | val isSquareTacoNull = "Taco".textIsNullOrEmpty() @@ -1333,6 +1310,40 @@ class KotlinPoetTest { ) } + // https://github.com/square/kotlinpoet/issues/1518 + @Test fun generatedImportAliasesSamePackageDifferentContainingClasses() { + val strokeCapRound = MemberName( + enclosingClassName = ClassName("androidx.compose.ui.graphics", "StrokeCap").nestedClass("Companion"), + simpleName = "Round", + ) + val strokeJoinRound = MemberName( + enclosingClassName = ClassName("androidx.compose.ui.graphics", "StrokeJoin").nestedClass("Companion"), + simpleName = "Round", + ) + val file = FileSpec.builder("com.example", "Test") + .addFunction( + FunSpec.builder("main") + .addStatement("val strokeCapRound = %M()", strokeCapRound) + .addStatement("val strokeJoinRound = %M()", strokeJoinRound) + .build(), + ) + .build() + assertThat(file.toString()).isEqualTo( + """ + |package com.example + | + |import androidx.compose.ui.graphics.StrokeCap.Companion.Round as strokeCapRound + |import androidx.compose.ui.graphics.StrokeJoin.Companion.Round as strokeJoinRound + | + |public fun main() { + | val strokeCapRound = strokeCapRound() + | val strokeJoinRound = strokeJoinRound() + |} + | + """.trimMargin(), + ) + } + @Test fun memberImportsOverGeneratedImportAliases() { val squareTaco = ClassName("com.squareup.tacos", "Taco") val blockTaco = ClassName("xyz.block.tacos", "Taco") @@ -1356,13 +1367,12 @@ class KotlinPoetTest { """ |package com.example | - |import kotlin.Unit |import com.squareup.cash.util.isNullOrEmpty as cashIsNullOrEmpty |import com.squareup.tacos.Taco as SquareTaco |import kotlin.text.isNullOrEmpty as kotlinIsNullOrEmpty |import xyz.block.tacos.Taco as BlockTaco | - |public fun main(): Unit { + |public fun main() { | val squareTaco = ::SquareTaco | val blockTaco = ::BlockTaco | val isSquareTacoNull = "Taco".kotlinIsNullOrEmpty() @@ -1372,4 +1382,60 @@ class KotlinPoetTest { """.trimMargin(), ) } + + // https://github.com/square/kotlinpoet/issues/1563 + @Test fun nestedClassesWithConflictingAutoGeneratedImports() { + val source = FileSpec.builder("com.squareup.tacos", "Taco") + .addType( + TypeSpec.classBuilder("Taco") + .addProperty("madeFreshDate", ClassName("java.util", "Date", "Builder")) + .addProperty("madeFreshDatabaseDate", ClassName("java.sql", "Date", "Builder")) + .build(), + ) + .build() + assertThat(source.toString()).isEqualTo( + """ + |package com.squareup.tacos + | + |import java.sql.Date as SqlDate + |import java.util.Date as UtilDate + | + |public class Taco { + | public val madeFreshDate: UtilDate.Builder + | + | public val madeFreshDatabaseDate: SqlDate.Builder + |} + | + """.trimMargin(), + ) + } + + // https://github.com/square/kotlinpoet/issues/1563 + @Test fun nestedClassesWithConflictingManuallySuppliedImports() { + val source = FileSpec.builder("com.squareup.tacos", "Taco") + .addAliasedImport(ClassName("java.util", "Date"), "UtilDate") + .addAliasedImport(ClassName("java.sql", "Date"), "SqlDate") + .addType( + TypeSpec.classBuilder("Taco") + .addProperty("madeFreshDate", ClassName("java.util", "Date", "Builder")) + .addProperty("madeFreshDatabaseDate", ClassName("java.sql", "Date", "Builder")) + .build(), + ) + .build() + assertThat(source.toString()).isEqualTo( + """ + |package com.squareup.tacos + | + |import java.sql.Date as SqlDate + |import java.util.Date as UtilDate + | + |public class Taco { + | public val madeFreshDate: UtilDate.Builder + | + | public val madeFreshDatabaseDate: SqlDate.Builder + |} + | + """.trimMargin(), + ) + } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LambdaTypeNameTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LambdaTypeNameTest.kt index 5b72b79d..1bcaef4a 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LambdaTypeNameTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LambdaTypeNameTest.kt @@ -192,4 +192,49 @@ class LambdaTypeNameTest { assertThat(typeName.toString()) .isEqualTo("((kotlin.Int) -> kotlin.Int) -> kotlin.Unit") } + + @Test fun equalsAndHashCode() { + val lambdaTypeName1 = LambdaTypeName.get( + parameters = arrayOf(INT), + returnType = INT, + ) + val lambdaTypeName2 = LambdaTypeName.get( + parameters = arrayOf(INT), + returnType = INT, + ) + assertThat(lambdaTypeName1).isEqualTo(lambdaTypeName2) + assertThat(lambdaTypeName1.hashCode()).isEqualTo(lambdaTypeName2.hashCode()) + assertThat(lambdaTypeName1.toString()).isEqualTo(lambdaTypeName2.toString()) + + val differentReceiver = LambdaTypeName.get( + parameters = arrayOf(INT), + returnType = INT, + receiver = ANY, + ) + assertThat(differentReceiver).isNotEqualTo(lambdaTypeName1) + + assertThat(lambdaTypeName1.copy(nullable = true)).isNotEqualTo(lambdaTypeName1) + + assertThat( + lambdaTypeName1.copy( + annotations = listOf( + AnnotationSpec.builder(Suppress::class.asClassName()).build(), + ), + ), + ).isNotEqualTo(lambdaTypeName1) + + assertThat(lambdaTypeName1.copy(suspending = true)).isNotEqualTo(lambdaTypeName1) + } + + @Test fun equalsAndHashCodeIgnoreTags() { + val lambdaTypeName = LambdaTypeName.get( + parameters = arrayOf(INT), + returnType = INT, + ) + + val tagged = lambdaTypeName.copy(tags = mapOf(String::class to "test")) + + assertThat(tagged).isEqualTo(lambdaTypeName) + assertThat(tagged.hashCode()).isEqualTo(lambdaTypeName.hashCode()) + } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrappingTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrappingTest.kt index 332a25b9..3471607e 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrappingTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrappingTest.kt @@ -21,6 +21,7 @@ import org.junit.Test class LineWrappingTest { @Test fun codeSpacesWrap() { val wrapMe = FunSpec.builder("wrapMe") + .returns(STRING) .addStatement( "return %L * %L * %L * %L * %L * %L * %L * %L * %L * %L * %L * %L", 10000000000, 20000000000, 30000000000, 40000000000, 50000000000, 60000000000, @@ -31,7 +32,9 @@ class LineWrappingTest { """ |package com.squareup.tacos | - |public fun wrapMe() = 10_000_000_000 * 20_000_000_000 * 30_000_000_000 * 40_000_000_000 * + |import kotlin.String + | + |public fun wrapMe(): String = 10_000_000_000 * 20_000_000_000 * 30_000_000_000 * 40_000_000_000 * | 50_000_000_000 * 60_000_000_000 * 70_000_000_000 * 80_000_000_000 * 90_000_000_000 * | 10_000_000_000 * 20_000_000_000 * 30_000_000_000 | @@ -41,6 +44,7 @@ class LineWrappingTest { @Test fun stringSpacesDoNotWrap() { val wrapMe = FunSpec.builder("wrapMe") + .returns(STRING) .addStatement( "return %S+%S+%S+%S+%S+%S+%S+%S+%S+%S+%S+%S", "Aaaa Aaaa", "Bbbb Bbbb", "Cccc Cccc", "Dddd Dddd", "Eeee Eeee", "Ffff Ffff", @@ -51,7 +55,9 @@ class LineWrappingTest { """ |package com.squareup.tacos | - |public fun wrapMe() = + |import kotlin.String + | + |public fun wrapMe(): String = | "Aaaa Aaaa"+"Bbbb Bbbb"+"Cccc Cccc"+"Dddd Dddd"+"Eeee Eeee"+"Ffff Ffff"+"Gggg Gggg"+"Hhhh Hhhh"+"Iiii Iiii"+"Jjjj Jjjj"+"Kkkk Kkkk"+"Llll Llll" | """.trimMargin(), @@ -60,6 +66,7 @@ class LineWrappingTest { @Test fun nonwrappingWhitespaceDoesNotWrap() { val wrapMe = FunSpec.builder("wrapMe") + .returns(STRING) .addStatement( "return %L·*·%L·*·%L·*·%L·*·%L·*·%L·*·%L·*·%L·*·%L·*·%L·*·%L·*·%L", 10000000000, 20000000000, 30000000000, 40000000000, 50000000000, 60000000000, @@ -70,7 +77,9 @@ class LineWrappingTest { """ |package com.squareup.tacos | - |public fun wrapMe() = + |import kotlin.String + | + |public fun wrapMe(): String = | 10_000_000_000 * 20_000_000_000 * 30_000_000_000 * 40_000_000_000 * 50_000_000_000 * 60_000_000_000 * 70_000_000_000 * 80_000_000_000 * 90_000_000_000 * 10_000_000_000 * 20_000_000_000 * 30_000_000_000 | """.trimMargin(), @@ -79,13 +88,16 @@ class LineWrappingTest { @Test fun nonwrappingWhitespaceIsRetainedInStrings() { val wrapMe = FunSpec.builder("wrapMe") + .returns(STRING) .addStatement("return %S", "a·b") .build() assertThat(toString(wrapMe)).isEqualTo( """ |package com.squareup.tacos | - |public fun wrapMe() = "a·b" + |import kotlin.String + | + |public fun wrapMe(): String = "a·b" | """.trimMargin(), ) @@ -102,9 +114,7 @@ class LineWrappingTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | - |public fun wrapMe(): Unit { + |public fun wrapMe() { | val a = 8 | val b = 64 | val c = 512 @@ -126,9 +136,7 @@ class LineWrappingTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | - |public fun wrapMe(): Unit { + |public fun wrapMe() { | val aaaaaa = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +1 | val bbbbbb = | "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +1 @@ -159,7 +167,6 @@ class LineWrappingTest { |package com.squareup.tacos | |import kotlin.String - |import kotlin.Unit | |public class Taco { | public fun call( @@ -195,7 +202,7 @@ class LineWrappingTest { | s29: String, | s30: String, | s31: String, - | ): Unit { + | ) { | call("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", | "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31") | } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/MemberNameTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/MemberNameTest.kt index 308aeb2c..69271d7d 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/MemberNameTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/MemberNameTest.kt @@ -39,9 +39,8 @@ class MemberNameTest { | |import com.squareup.tacos.bestTacoEver |import com.squareup.tacos.randomTaco - |import kotlin.Unit | - |public fun makeTastyTacos(): Unit { + |public fun makeTastyTacos() { | val randomTaco = randomTaco() | val bestTaco = bestTacoEver |} @@ -65,9 +64,8 @@ class MemberNameTest { |package com.example | |import com.squareup.tacos.Taco.Companion.createTaco - |import kotlin.Unit | - |public fun makeTastyTacos(): Unit { + |public fun makeTastyTacos() { | createTaco() |} | @@ -88,9 +86,7 @@ class MemberNameTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | - |public fun makeTastyTacos(): Unit { + |public fun makeTastyTacos() { | createTaco() |} | @@ -115,9 +111,8 @@ class MemberNameTest { |package com.squareup.tacos | |import com.squareup.tacos.Town.createTaco - |import kotlin.Unit | - |public fun makeTastyTacos(): Unit { + |public fun makeTastyTacos() { | createTaco() |} | @@ -140,11 +135,10 @@ class MemberNameTest { """ |package com.example | - |import kotlin.Unit |import com.squareup.tacos.createTaco as squareupTacosCreateTaco |import com.twitter.tacos.createTaco as twitterTacosCreateTaco | - |public fun makeTastyTacos(): Unit { + |public fun makeTastyTacos() { | squareupTacosCreateTaco() | twitterTacosCreateTaco() |} @@ -170,12 +164,11 @@ class MemberNameTest { """ |package com.example | - |import kotlin.Unit - |import com.squareup.tacos.SquareTacos.Companion.createTaco as squareupTacosCreateTaco + |import com.squareup.tacos.SquareTacos.Companion.createTaco as squareTacosCreateTaco |import com.twitter.tacos.TwitterTacos.Companion.createTaco as twitterTacosCreateTaco | - |public fun makeTastyTacos(): Unit { - | squareupTacosCreateTaco() + |public fun makeTastyTacos() { + | squareTacosCreateTaco() | twitterTacosCreateTaco() |} | @@ -199,9 +192,8 @@ class MemberNameTest { |package com.example | |import com.squareup.tacos.SquareTacos - |import kotlin.Unit | - |public fun makeTastyTacos(): Unit { + |public fun makeTastyTacos() { | val tacos = SquareTacos() | com.squareup.tacos.math.SquareTacos(tacos) |} @@ -232,14 +224,12 @@ class MemberNameTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public class TacoTest { - | public fun test(): Unit { + | public fun test() { | kotlin.error("errorText") | } | - | public fun error(): Unit { + | public fun error() { | } |} | @@ -274,14 +264,12 @@ class MemberNameTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public class Test { - | public fun error(): Unit { + | public fun error() { | } | | public inner class TacoTest { - | public fun test(): Unit { + | public fun test() { | kotlin.error("errorText") | } | } @@ -317,15 +305,14 @@ class MemberNameTest { """ |package com.squareup.tacos | - |import kotlin.Unit |import kotlin.error | |public class Test { - | public fun error(): Unit { + | public fun error() { | } | | public class TacoTest { - | public fun test(): Unit { + | public fun test() { | error("errorText") | } | } @@ -352,11 +339,10 @@ class MemberNameTest { """ |package com.example | - |import kotlin.Unit |import com.squareup.tacos.createTaco as createSquareTaco |import com.twitter.tacos.createTaco as createTwitterTaco | - |public fun makeTastyTacos(): Unit { + |public fun makeTastyTacos() { | createSquareTaco() | createTwitterTaco() |} @@ -383,13 +369,12 @@ class MemberNameTest { """ |package com.squareup.tacos | - |import kotlin.Unit |import org.junit.Before |import org.mockito.`when` | |public class TacoTest { | @Before - | public fun setUp(): Unit { + | public fun setUp() { | `when`(tacoService.createTaco()).thenReturn(tastyTaco()) | } |} @@ -415,12 +400,11 @@ class MemberNameTest { """ |package com.example | - |import kotlin.Unit - |import com.squareup.tacos.SquareTacos.Companion.`when` as squareupTacosWhen + |import com.squareup.tacos.SquareTacos.Companion.`when` as squareTacosWhen |import com.twitter.tacos.TwitterTacos.Companion.`when` as twitterTacosWhen | - |public fun whenTastyTacos(): Unit { - | squareupTacosWhen() + |public fun whenTastyTacos() { + | squareTacosWhen() | twitterTacosWhen() |} | @@ -445,9 +429,8 @@ class MemberNameTest { | |import com.squareup.tacos.TacoTruck |import com.squareup.tacos.randomTaco - |import kotlin.Unit | - |public fun makeTastyTacos(): Unit { + |public fun makeTastyTacos() { | val randomTacoFactory = ::randomTaco | val bestTacoFactory = TacoTruck::bestTacoEver |} @@ -470,9 +453,8 @@ class MemberNameTest { |package com.squareup.tacos | |import com.squareup.`taco factory`.`produce tacos` - |import kotlin.Unit | - |public fun main(): Unit { + |public fun main() { | println(`produce tacos`()) |} | @@ -514,10 +496,9 @@ class MemberNameTest { | |import com.squareup.tacos.Taco |import com.squareup.tacos.TacoPackager - |import kotlin.Unit |import kotlin.collections.List | - |public fun packageTacos(tacos: List<Taco>, packager: TacoPackager): Unit { + |public fun packageTacos(tacos: List<Taco>, packager: TacoPackager) { | packager.`package`(tacos) |} | @@ -549,9 +530,8 @@ class MemberNameTest { |import com.squareup.tacos.`internal`.iterator |import com.squareup.tacos.`internal`.minusAssign |import com.squareup.tacos.ingredient.Meat - |import kotlin.Unit | - |public fun makeTacoHealthy(taco: Taco): Unit { + |public fun makeTacoHealthy(taco: Taco) { | for (ingredient in taco) { | if (ingredient is Meat) taco -= ingredient | } @@ -596,7 +576,7 @@ class MemberNameTest { import kotlin.hashCode public class Message { - public override fun hashCode(): Int { + override fun hashCode(): Int { var result = super.hashCode if (result == 0) { result = result * 37 + embedded_message.hashCode() diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt index d764f441..5528e493 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt @@ -127,7 +127,7 @@ class ParameterSpecTest { | |import kotlin.Unit | - |public fun foo(bar: @Annotation () -> Unit): Unit { + |public fun foo(bar: @Annotation () -> Unit) { |} | """.trimMargin(), diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt index f4e5625b..a94dddd5 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt @@ -16,6 +16,7 @@ package com.squareup.kotlinpoet import com.google.common.truth.Truth.assertThat +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.plusParameter import java.io.Closeable import kotlin.reflect.KClass @@ -161,4 +162,31 @@ class ParameterizedTypeNameTest { assertThat(typeName.toString()) .isEqualTo("kotlin.collections.Map<kotlin.String, @Annotation () -> kotlin.Unit>") } + + private class Enclosing1 { + class GenericClass<T> + } + + private object Enclosing2 { + class Foo + } + + @Test fun equalsAndHashCode() { + val parameterizedTypeName1 = Enclosing1.GenericClass::class.parameterizedBy(Enclosing2.Foo::class) + val parameterizedTypeName2 = Enclosing1.GenericClass::class.parameterizedBy(Enclosing2.Foo::class) + assertThat(parameterizedTypeName1).isEqualTo(parameterizedTypeName2) + assertThat(parameterizedTypeName1.hashCode()).isEqualTo(parameterizedTypeName2.hashCode()) + + assertThat(parameterizedTypeName1.copy(nullable = true)).isNotEqualTo(parameterizedTypeName1) + + assertThat(parameterizedTypeName1.copy(annotations = listOf(AnnotationSpec.builder(Suppress::class).build()))).isNotEqualTo(parameterizedTypeName1) + } + + @Test fun equalsAndHashCodeIgnoreTags() { + val parameterizedTypeName = Enclosing1.GenericClass::class.parameterizedBy(Enclosing2.Foo::class) + val tagged = parameterizedTypeName.copy(tags = mapOf(String::class to "test")) + + assertThat(parameterizedTypeName).isEqualTo(tagged) + assertThat(parameterizedTypeName.hashCode()).isEqualTo(tagged.hashCode()) + } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt index 5eda0f78..af373c25 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt @@ -16,8 +16,6 @@ package com.squareup.kotlinpoet import com.google.common.truth.Truth.assertThat -import com.squareup.kotlinpoet.FunSpec.Companion.GETTER -import com.squareup.kotlinpoet.FunSpec.Companion.SETTER import com.squareup.kotlinpoet.KModifier.EXTERNAL import com.squareup.kotlinpoet.KModifier.PRIVATE import com.squareup.kotlinpoet.KModifier.PUBLIC @@ -650,44 +648,6 @@ class PropertySpecTest { ) } - @Test fun varWithContextReceiverWithoutCustomAccessors() { - val mutablePropertySpecBuilder = { - PropertySpec.builder("foo", STRING) - .mutable() - .contextReceivers(INT) - } - - assertThrows<IllegalArgumentException> { - mutablePropertySpecBuilder() - .getter( - FunSpec.getterBuilder() - .build(), - ) - .build() - }.hasMessageThat() - .isEqualTo("mutable properties with context receivers require a $SETTER") - - assertThrows<IllegalArgumentException> { - mutablePropertySpecBuilder() - .setter( - FunSpec.setterBuilder() - .build(), - ) - .build() - }.hasMessageThat() - .isEqualTo("properties with context receivers require a $GETTER") - } - - @Test fun valWithContextReceiverWithoutGetter() { - assertThrows<IllegalArgumentException> { - PropertySpec.builder("foo", STRING) - .mutable(false) - .contextReceivers(INT) - .build() - }.hasMessageThat() - .isEqualTo("properties with context receivers require a $GETTER") - } - @Test fun varWithContextReceiver() { val propertySpec = PropertySpec.builder("foo", INT) .mutable() diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/StringsTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/StringsTest.kt index 49bec351..d25ca4ed 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/StringsTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/StringsTest.kt @@ -22,19 +22,21 @@ class StringsTest { @Test fun singleLineStringWithDollarSymbols() { val stringWithTemplate = "$" + "annoyingUser" + " is annoying." val funSpec = FunSpec.builder("getString") + .returns(STRING) .addStatement("return %S", stringWithTemplate) .build() assertThat(funSpec.toString()) - .isEqualTo("public fun getString() = \"\${\'\$\'}annoyingUser is annoying.\"\n") + .isEqualTo("public fun getString(): kotlin.String = \"\${\'\$\'}annoyingUser is annoying.\"\n") } @Test fun multilineStringWithDollarSymbols() { val stringWithTemplate = "Some string\n" + "$" + "annoyingUser" + " is annoying." val funSpec = FunSpec.builder("getString") + .returns(STRING) .addStatement("return %S", stringWithTemplate) .build() assertThat(funSpec.toString()).isEqualTo( - "public fun getString() = \"\"\"\n" + + "public fun getString(): kotlin.String = \"\"\"\n" + "|Some string\n" + "|\${\'\$\'}annoyingUser is annoying.\n" + "\"\"\".trimMargin()\n", @@ -44,19 +46,21 @@ class StringsTest { @Test fun singleLineStringTemplate() { val stringWithTemplate = "$" + "annoyingUser" + " is annoying." val funSpec = FunSpec.builder("getString") + .returns(STRING) .addStatement("return %P", stringWithTemplate) .build() assertThat(funSpec.toString()) - .isEqualTo("public fun getString() = \"\"\"\$annoyingUser is annoying.\"\"\"\n") + .isEqualTo("public fun getString(): kotlin.String = \"\"\"\$annoyingUser is annoying.\"\"\"\n") } @Test fun multilineStringTemplate() { val stringWithTemplate = "Some string\n" + "$" + "annoyingUser" + " is annoying." val funSpec = FunSpec.builder("getString") + .returns(STRING) .addStatement("return %P", stringWithTemplate) .build() assertThat(funSpec.toString()).isEqualTo( - "public fun getString() = \"\"\"\n" + + "public fun getString(): kotlin.String = \"\"\"\n" + "|Some string\n" + "|\$annoyingUser is annoying.\n" + "\"\"\".trimMargin()\n", @@ -67,9 +71,10 @@ class StringsTest { @Test fun templateStringWithStringLiteralReference() { val string = "SELECT * FROM socialFeedItem WHERE message IS NOT NULL AND userId \${ if (userId == null) \"IS\" else \"=\" } ?1 ORDER BY datetime(creation_time) DESC" val funSpec = FunSpec.builder("getString") + .returns(STRING) .addStatement("return %P", string) .build() assertThat(funSpec.toString()) - .isEqualTo("public fun getString() = \"\"\"SELECT * FROM socialFeedItem WHERE message IS NOT NULL AND userId \${ if (userId == null) \"IS\" else \"=\" } ?1 ORDER BY datetime(creation_time) DESC\"\"\"\n") + .isEqualTo("public fun getString(): kotlin.String = \"\"\"SELECT * FROM socialFeedItem WHERE message IS NOT NULL AND userId \${ if (userId == null) \"IS\" else \"=\" } ?1 ORDER BY datetime(creation_time) DESC\"\"\"\n") } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt index cf6c3e29..ebac6356 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt @@ -25,6 +25,7 @@ import com.squareup.kotlinpoet.KModifier.INNER import com.squareup.kotlinpoet.KModifier.INTERNAL import com.squareup.kotlinpoet.KModifier.PRIVATE import com.squareup.kotlinpoet.KModifier.PUBLIC +import com.squareup.kotlinpoet.KModifier.SEALED import com.squareup.kotlinpoet.KModifier.VARARG import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.jvm.throws @@ -169,13 +170,11 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public class Taco { | public val NAME: Thing.Thang<Foo, Bar> = object : Thing.Thang<Foo, Bar>() { | public override fun call(thung: Thung<in Foo>): Thung<in Bar> = object : SimpleThung<Bar>(thung) | { - | public override fun doSomething(bar: Bar): Unit { + | public override fun doSomething(bar: Bar) { | /* code snippets */ | } | } @@ -240,11 +239,10 @@ class TypeSpecTest { | |import com.squareup.wire.Message |import java.lang.Runnable - |import kotlin.Unit | |public class Taco { | public val NAME: Runnable = object : Message(), Runnable { - | public override fun run(): Unit { + | public override fun run() { | /* code snippets */ | } | } @@ -622,16 +620,14 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public enum class Tortilla { | CORN { - | public override fun fold(): Unit { + | public override fun fold() { | } | }, | ; | - | public abstract fun fold(): Unit + | public abstract fun fold() |} | """.trimMargin(), @@ -701,12 +697,11 @@ class TypeSpecTest { |package com.squareup.tacos | |import kotlin.String - |import kotlin.Unit | |public sealed class Sealed { | public abstract val name: String | - | public abstract fun fold(): Unit + | public abstract fun fold() |} | """.trimMargin(), @@ -926,26 +921,25 @@ class TypeSpecTest { |package com.squareup.tacos | |import java.io.IOException - |import kotlin.Unit |import kotlin.jvm.Throws | |public abstract class Taco { | @Throws(IOException::class) - | public fun throwOne(): Unit { + | public fun throwOne() { | } | | @Throws( | IOException::class, | SourCreamException::class, | ) - | public fun throwTwo(): Unit { + | public fun throwTwo() { | } | | @Throws(IOException::class) - | public abstract fun abstractThrow(): Unit + | public abstract fun abstractThrow() | | @Throws(IOException::class) - | public external fun nativeThrow(): Unit + | public external fun nativeThrow() |} | """.trimMargin(), @@ -1208,12 +1202,10 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public fun interface Taco { - | public fun sam(): Unit + | public fun sam() | - | public fun notSam(): Unit { + | public fun notSam() { | } |} | @@ -1479,7 +1471,8 @@ class TypeSpecTest { } @Test fun expectClass() { - val classA = TypeSpec.expectClassBuilder("ClassA") + val classA = TypeSpec.classBuilder("ClassA") + .addModifiers(KModifier.EXPECT) .addFunction( FunSpec.builder("test") .build(), @@ -1489,7 +1482,7 @@ class TypeSpecTest { assertThat(classA.toString()).isEqualTo( """ |public expect class ClassA { - | public fun test(): kotlin.Unit + | public fun test() |} | """.trimMargin(), @@ -1497,7 +1490,8 @@ class TypeSpecTest { } @Test fun nestedExpectCompanionObjectWithFunction() { - val classA = TypeSpec.expectClassBuilder("ClassA") + val classA = TypeSpec.classBuilder("ClassA") + .addModifiers(KModifier.EXPECT) .addType( TypeSpec.companionObjectBuilder() .addFunction( @@ -1512,7 +1506,7 @@ class TypeSpecTest { """ |public expect class ClassA { | public companion object { - | public fun test(): kotlin.Unit + | public fun test() | } |} | @@ -1521,7 +1515,8 @@ class TypeSpecTest { } @Test fun nestedExpectClassWithFunction() { - val classA = TypeSpec.expectClassBuilder("ClassA") + val classA = TypeSpec.classBuilder("ClassA") + .addModifiers(KModifier.EXPECT) .addType( TypeSpec.classBuilder("ClassB") .addFunction( @@ -1536,7 +1531,7 @@ class TypeSpecTest { """ |public expect class ClassA { | public class ClassB { - | public fun test(): kotlin.Unit + | public fun test() | } |} | @@ -1545,7 +1540,8 @@ class TypeSpecTest { } @Test fun deeplyNestedExpectClassWithFunction() { - val classA = TypeSpec.expectClassBuilder("ClassA") + val classA = TypeSpec.classBuilder("ClassA") + .addModifiers(KModifier.EXPECT) .addType( TypeSpec.classBuilder("ClassB") .addType( @@ -1565,7 +1561,7 @@ class TypeSpecTest { |public expect class ClassA { | public class ClassB { | public class ClassC { - | public fun test(): kotlin.Unit + | public fun test() | } | } |} @@ -1575,7 +1571,8 @@ class TypeSpecTest { } @Test fun veryDeeplyNestedExpectClassWithFunction() { - val classA = TypeSpec.expectClassBuilder("ClassA") + val classA = TypeSpec.classBuilder("ClassA") + .addModifiers(KModifier.EXPECT) .addType( TypeSpec.classBuilder("ClassB") .addType( @@ -1600,7 +1597,7 @@ class TypeSpecTest { | public class ClassB { | public class ClassC { | public class ClassD { - | public fun test(): kotlin.Unit + | public fun test() | } | } | } @@ -1611,7 +1608,8 @@ class TypeSpecTest { } @Test fun deeplyNestedExpectClassWithConstructor() { - val classA = TypeSpec.expectClassBuilder("ClassA") + val classA = TypeSpec.classBuilder("ClassA") + .addModifiers(KModifier.EXPECT) .addType( TypeSpec.classBuilder("ClassB") .addType( @@ -1641,7 +1639,8 @@ class TypeSpecTest { } @Test fun veryDeeplyNestedExpectClassWithConstructor() { - val classA = TypeSpec.expectClassBuilder("ClassA") + val classA = TypeSpec.classBuilder("ClassA") + .addModifiers(KModifier.EXPECT) .addType( TypeSpec.classBuilder("ClassB") .addType( @@ -1695,15 +1694,13 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public interface Taco { - | public fun aMethod(): Unit + | public fun aMethod() | - | public fun aDefaultMethod(): Unit { + | public fun aDefaultMethod() { | } | - | private fun aPrivateMethod(): Unit { + | private fun aPrivateMethod() { | } |} | @@ -1891,7 +1888,6 @@ class TypeSpecTest { | |import java.util.Locale |import kotlin.Boolean - |import kotlin.Unit | |/** | * A hard or soft tortilla, loosely folded and filled with whatever @@ -1909,7 +1905,7 @@ class TypeSpecTest { | * | * For [Locale#KOREAN], the front may also be folded. | */ - | public fun refold(locale: Locale): Unit { + | public fun refold(locale: Locale) { | } |} | @@ -2056,10 +2052,9 @@ class TypeSpecTest { | |import java.lang.Runnable |import kotlin.Int - |import kotlin.Unit | |public class Taqueria { - | public fun prepare(workers: Int, vararg jobs: Runnable): Unit { + | public fun prepare(workers: Int, vararg jobs: Runnable) { | } |} | @@ -2084,14 +2079,13 @@ class TypeSpecTest { |import java.lang.Runnable |import kotlin.Boolean |import kotlin.Int - |import kotlin.Unit | |public class Taqueria { | public fun prepare( | workers: Int, | vararg jobs: Runnable, | start: Boolean, - | ): Unit { + | ) { | } |} | @@ -2107,7 +2101,7 @@ class TypeSpecTest { .build() val funBody = CodeBlock.builder() .addStatement("val size = %T.min(listA.size, listB.size)", Math::class) - .beginControlFlow("for (i in 0 until size)") + .beginControlFlow("for (i in 0..<size)") .addStatement("val %N = %N[i]", "a", "listA") .addStatement("val %N = %N[i]", "b", "listB") .add("%L", ifBlock) @@ -2161,7 +2155,7 @@ class TypeSpecTest { | | public fun commonPrefixLength(listA: List<String>, listB: List<String>): Int { | val size = Math.min(listA.size, listB.size) - | for (i in 0 until size) { + | for (i in 0..<size) { | val a = listA[i] | val b = listB[i] | if (a != b) { @@ -2193,10 +2187,9 @@ class TypeSpecTest { |package com.squareup.tacos | |import java.lang.System - |import kotlin.Unit | |public class Taco { - | public fun choices(): Unit { + | public fun choices() { | if (taco != null || taco == otherTaco) { | System.out.println("only one taco? NOO!") | } else if (taco.isSupreme() && otherTaco.isSupreme()) { @@ -2226,10 +2219,9 @@ class TypeSpecTest { |package com.squareup.tacos | |import java.lang.System - |import kotlin.Unit | |public class Taco { - | public fun choices(): Unit { + | public fun choices() { | if (5 < 4) { | System.out.println("wat") | } else if (5 < 6) { @@ -2255,10 +2247,9 @@ class TypeSpecTest { |package com.squareup.tacos | |import java.lang.System - |import kotlin.Unit | |public class Taco { - | public fun inlineIndent(): Unit { + | public fun inlineIndent() { | if (3 < 4) { | System.out.println("hello"); | } @@ -2333,7 +2324,6 @@ class TypeSpecTest { |import kotlin.Int |import kotlin.Long |import kotlin.String - |import kotlin.Unit | |public class Members { | public val W: String @@ -2344,16 +2334,16 @@ class TypeSpecTest { | | public constructor(o: Long) | - | public fun T(): Unit { + | public fun T() { | } | - | public fun S(): Unit { + | public fun S() { | } | - | public fun R(): Unit { + | public fun R() { | } | - | public fun Q(): Unit { + | public fun Q() { | } | | public class Z @@ -2486,7 +2476,7 @@ class TypeSpecTest { assertThat(type.toString()).isEqualTo( """ |object : java.lang.Runnable { - | public override fun run(): kotlin.Unit { + | public override fun run() { | } |} """.trimMargin(), @@ -2599,7 +2589,6 @@ class TypeSpecTest { |import java.util.Comparator |import kotlin.Int |import kotlin.String - |import kotlin.Unit |import kotlin.collections.List | |public class Taco { @@ -2614,7 +2603,7 @@ class TypeSpecTest { | } | } | - | public fun sortPrefix(list: List<String>, length: Int): Unit { + | public fun sortPrefix(list: List<String>, length: Int) { | Collections.sort( | list, | object : Comparator<String> { @@ -2832,10 +2821,8 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public class Taco { - | public fun addTopping(topping: Topping): Unit { + | public fun addTopping(topping: Topping) { | try { | /* do something tricky with the topping */ | } catch (e: IllegalToppingException) { @@ -2887,6 +2874,7 @@ class TypeSpecTest { .addFunction( FunSpec.builder("toppingPrice") .addParameter("topping", String::class) + .returns(INT) .beginControlFlow("return when(topping)") .addStatement("%S -> 1", "beef") .addStatement("%S -> 2", "lettuce") @@ -2900,10 +2888,11 @@ class TypeSpecTest { """ |package com.squareup.tacos | + |import kotlin.Int |import kotlin.String | |public class Taco { - | public fun toppingPrice(topping: String) = when(topping) { + | public fun toppingPrice(topping: String): Int = when(topping) { | "beef" -> 1 | "lettuce" -> 2 | "cheese" -> 3 @@ -3282,8 +3271,8 @@ class TypeSpecTest { } @Test fun generalExpectClassBuilderEqualityTest() { - val expectSpec = TypeSpec.expectClassBuilder("AtmoicRef") - .addModifiers(KModifier.INTERNAL) + val expectSpec = TypeSpec.classBuilder("AtmoicRef") + .addModifiers(KModifier.EXPECT, KModifier.INTERNAL) .primaryConstructor( FunSpec.constructorBuilder() .addParameter("value", Int::class) @@ -3383,7 +3372,6 @@ class TypeSpecTest { |package com.squareup.tacos | |import kotlin.Int - |import kotlin.Unit | |public object MyObject { | public val tacos: Int @@ -3391,7 +3379,7 @@ class TypeSpecTest { | init { | } | - | public fun test(): Unit { + | public fun test() { | } |} | @@ -3417,13 +3405,12 @@ class TypeSpecTest { |package com.squareup.tacos | |import com.squareup.wire.Message - |import kotlin.Unit | |public object MyObject : Message() { | init { | } | - | public fun test(): Unit { + | public fun test() { | } |} | @@ -3455,13 +3442,12 @@ class TypeSpecTest { |package com.squareup.tacos | |import kotlin.Int - |import kotlin.Unit | |public class MyClass { | public companion object { | public val tacos: Int = 42 | - | public fun test(): Unit { + | public fun test() { | } | } |} @@ -3523,11 +3509,9 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public class MyClass { | public companion object Factory { - | public fun tacos(): Unit { + | public fun tacos() { | } | } |} @@ -3554,11 +3538,9 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public interface MyInterface { | public companion object { - | public fun test(): Unit { + | public fun test() { | } | } |} @@ -3587,15 +3569,13 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public enum class MyEnum { | FOO, | BAR, | ; | | public companion object { - | public fun test(): Unit { + | public fun test() { | } | } |} @@ -3643,11 +3623,10 @@ class TypeSpecTest { |package com.squareup.tacos | |import com.squareup.wire.Message - |import kotlin.Unit | |public class MyClass { | public companion object : Message() { - | public fun test(): Unit { + | public fun test() { | } | } |} @@ -4074,28 +4053,58 @@ class TypeSpecTest { }.hasMessageThat().isEqualTo("modifiers [ABSTRACT, PRIVATE] must contain none or only one of [ABSTRACT, PRIVATE]") } - @Test fun internalFunForbiddenInAnnotation() { + @Test fun internalConstructorForbiddenInAnnotation() { + val type = TypeSpec.annotationBuilder("Taco") + + assertThrows<IllegalArgumentException> { + type.primaryConstructor( + FunSpec.constructorBuilder() + .addModifiers(INTERNAL) + .build(), + ) + .build() + }.hasMessageThat().isEqualTo("modifiers [INTERNAL] must contain none of [INTERNAL, PROTECTED, PRIVATE, ABSTRACT]") + } + + // https://github.com/square/kotlinpoet/issues/1557 + @Test fun memberFunForbiddenInAnnotation() { val type = TypeSpec.annotationBuilder("Taco") assertThrows<IllegalArgumentException> { type.addFunction( FunSpec.builder("eat") - .addModifiers(INTERNAL) .build(), ) .build() - }.hasMessageThat().isEqualTo("annotation class Taco.eat requires modifiers [PUBLIC, ABSTRACT]") + }.hasMessageThat().isEqualTo("annotation class Taco cannot declare member function eat") + } + + // https://github.com/square/kotlinpoet/issues/1557 + @Test fun secondaryConstructorForbiddenInAnnotation() { + val type = TypeSpec.annotationBuilder("Taco") assertThrows<IllegalArgumentException> { - type.addFunctions( - listOf( - FunSpec.builder("eat") - .addModifiers(INTERNAL) + type.primaryConstructor(FunSpec.constructorBuilder().build()) + .addFunction( + FunSpec.constructorBuilder() + .addParameter("value", String::class) .build(), - ), + ).build() + }.hasMessageThat().isEqualTo("annotation class Taco cannot declare member function constructor()") + } + + // https://github.com/square/kotlinpoet/issues/1556 + @Test fun abstractFunForbiddenInObject() { + val type = TypeSpec.objectBuilder("Taco") + + assertThrows<IllegalArgumentException> { + type.addFunction( + FunSpec.builder("eat") + .addModifiers(ABSTRACT) + .build(), ) .build() - }.hasMessageThat().isEqualTo("annotation class Taco.eat requires modifiers [PUBLIC, ABSTRACT]") + }.hasMessageThat().isEqualTo("non-abstract type Taco cannot declare abstract function eat") } @Test fun classHeaderFormatting() { @@ -4133,9 +4142,9 @@ class TypeSpecTest { |import kotlin.String | |public data class Person( - | public override val id: Int, - | public override val name: String, - | public override val surname: String, + | override val id: Int, + | override val name: String, + | override val surname: String, |) | """.trimMargin(), @@ -4218,10 +4227,9 @@ class TypeSpecTest { |package com.squareup.tacos | |import kotlin.String - |import kotlin.Unit | |public class Taco { - | public fun shell(): Unit { + | public fun shell() { | val taco1: String = "Taco!" | val taco2: String? = null | lateinit var taco3: String @@ -4423,10 +4431,8 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public external class Foo { - | public fun bar(): Unit + | public fun bar() |} | """.trimMargin(), @@ -4445,12 +4451,11 @@ class TypeSpecTest { |package com.squareup.tacos | |import kotlin.String - |import kotlin.Unit | |public external interface Foo { | public val baz: String | - | public fun bar(): Unit + | public fun bar() |} | """.trimMargin(), @@ -4469,12 +4474,11 @@ class TypeSpecTest { |package com.squareup.tacos | |import kotlin.String - |import kotlin.Unit | |public external object Foo { | public val baz: String | - | public fun bar(): Unit + | public fun bar() |} | """.trimMargin(), @@ -4508,19 +4512,17 @@ class TypeSpecTest { """ |package com.squareup.tacos | - |import kotlin.Unit - | |public external class Foo { | public class Nested1 { - | public fun baz(): Unit + | public fun baz() | | public object Nested2 { - | public fun bar(): Unit + | public fun bar() | } | } | | public companion object { - | public fun qux(): Unit + | public fun qux() | } |} | @@ -4625,10 +4627,10 @@ class TypeSpecTest { val javaWord = AnnotationSpec.builder(JvmName::class.asClassName()) .addMember("name = %S", "javaWord") .build() - builder.annotationSpecs.clear() - builder.annotationSpecs.add(javaWord) + builder.annotations.clear() + builder.annotations.add(javaWord) - assertThat(builder.build().annotationSpecs).containsExactly(javaWord) + assertThat(builder.build().annotations).containsExactly(javaWord) } @Test fun modifyTypeVariableNames() { @@ -4801,6 +4803,8 @@ class TypeSpecTest { """ |/** | * This is a thing for stuff. + | * + | * @constructor Construct a thing! | */ |public class MyType( | /** @@ -5138,7 +5142,7 @@ class TypeSpecTest { .build() assertThat(funSpec.toString()).isEqualTo( """ - |public fun printTaco(taco: com.squareup.tacos.Taco.`object`): kotlin.Unit { + |public fun printTaco(taco: com.squareup.tacos.Taco.`object`) { | print(taco) |} | @@ -5182,7 +5186,6 @@ class TypeSpecTest { package com.squareup.tacos import kotlin.String - import kotlin.Unit public interface Taco { public val foo: String @@ -5191,7 +5194,7 @@ class TypeSpecTest { public fun bar(): String - public fun barWithDefault(): Unit { + public fun barWithDefault() { } } @@ -5336,6 +5339,85 @@ class TypeSpecTest { ) } + // https://github.com/square/kotlinpoet/issues/1548 + @Test fun overrideInternalAbstractFunctionVisibility() { + val baseClass = TypeSpec.classBuilder("Base") + .addModifiers(PUBLIC, ABSTRACT) + .addFunction( + FunSpec.builder("foo") + .addModifiers(INTERNAL, ABSTRACT) + .build(), + ) + .build() + assertThat(baseClass.toString()).isEqualTo( + """ + |public abstract class Base { + | internal abstract fun foo() + |} + | + """.trimMargin(), + ) + val bassClassName = ClassName("", "Base") + val exampleClass = TypeSpec.classBuilder("Example") + .addModifiers(PUBLIC) + .superclass(bassClassName) + .addFunction( + FunSpec.builder("foo") + .addModifiers(KModifier.OVERRIDE) + .build(), + ) + .build() + assertThat(exampleClass.toString()).isEqualTo( + """ + |public class Example : Base() { + | override fun foo() { + | } + |} + | + """.trimMargin(), + ) + val example2Class = TypeSpec.classBuilder("Example2") + .addModifiers(PUBLIC) + .superclass(bassClassName) + .addFunction( + FunSpec.builder("foo") + .addModifiers(PUBLIC, KModifier.OVERRIDE) + .build(), + ) + .build() + // Don't omit the public modifier here, + // as we're explicitly increasing the visibility of this method in the subclass. + assertThat(example2Class.toString()).isEqualTo( + """ + |public class Example2 : Base() { + | public override fun foo() { + | } + |} + | + """.trimMargin(), + ) + val example3Class = TypeSpec.classBuilder("Example3") + .addModifiers(INTERNAL) + .superclass(bassClassName) + .addFunction( + FunSpec.builder("foo") + .addModifiers(PUBLIC, KModifier.OVERRIDE) + .build(), + ) + .build() + // Don't omit the public modifier here, + // as we're explicitly increasing the visibility of this method in the subclass. + assertThat(example3Class.toString()).isEqualTo( + """ + |internal class Example3 : Base() { + | public override fun foo() { + | } + |} + | + """.trimMargin(), + ) + } + @Test fun contextReceiver() { val typeSpec = TypeSpec.classBuilder("Example") .contextReceivers(STRING) @@ -5358,6 +5440,206 @@ class TypeSpecTest { assertThat(t).hasMessageThat().contains("contextReceivers can only be applied on simple classes") } + @Test fun valWithContextReceiverWithoutGetter() { + assertThrows<IllegalArgumentException> { + TypeSpec.classBuilder("Example") + .addProperty( + PropertySpec.builder("foo", STRING) + .mutable(false) + .contextReceivers(INT) + .build(), + ) + .build() + }.hasMessageThat() + .isEqualTo("non-abstract properties with context receivers require a get()") + } + + @Test fun varWithContextReceiverWithoutAccessors() { + assertThrows<IllegalArgumentException> { + TypeSpec.classBuilder("Example") + .addProperty( + PropertySpec.builder("foo", STRING) + .mutable() + .contextReceivers(INT) + .getter( + FunSpec.getterBuilder() + .build(), + ) + .build(), + ).build() + }.hasMessageThat() + .isEqualTo("non-abstract mutable properties with context receivers require a set()") + + assertThrows<IllegalArgumentException> { + TypeSpec.classBuilder("Example") + .addProperty( + PropertySpec.builder("foo", STRING) + .mutable() + .contextReceivers(INT) + .setter( + FunSpec.setterBuilder() + .build(), + ) + .build(), + ).build() + }.hasMessageThat() + .isEqualTo("non-abstract properties with context receivers require a get()") + } + + // https://github.com/square/kotlinpoet/issues/1525 + @Test fun propertyWithContextReceiverInInterface() { + val typeSpec = TypeSpec.interfaceBuilder("Bar") + .addProperty( + PropertySpec.builder("foo", Int::class) + .contextReceivers(STRING) + .build(), + ) + .addProperty( + PropertySpec.builder("bar", Int::class) + .contextReceivers(STRING) + .mutable(true) + .build(), + ) + .build() + + assertThat(typeSpec.toString()).isEqualTo( + """ + |public interface Bar { + | context(kotlin.String) + | public val foo: kotlin.Int + | + | context(kotlin.String) + | public var bar: kotlin.Int + |} + | + """.trimMargin(), + ) + } + + @Test fun nonAbstractPropertyWithContextReceiverInAbstractClass() { + assertThrows<IllegalArgumentException> { + TypeSpec.classBuilder("Bar") + .addModifiers(ABSTRACT) + .addProperty( + PropertySpec.builder("foo", Int::class) + .contextReceivers(STRING) + .build(), + ) + .build() + }.hasMessageThat().isEqualTo("non-abstract properties with context receivers require a get()") + } + + @Test fun abstractPropertyWithContextReceiverInAbstractClass() { + val typeSpec = TypeSpec.classBuilder("Bar") + .addModifiers(ABSTRACT) + .addProperty( + PropertySpec.builder("foo", Int::class) + .contextReceivers(STRING) + .addModifiers(ABSTRACT) + .build(), + ) + .build() + + assertThat(typeSpec.toString()).isEqualTo( + """ + |public abstract class Bar { + | context(kotlin.String) + | public abstract val foo: kotlin.Int + |} + | + """.trimMargin(), + ) + } + + @Test fun abstractPropertyInNonAbstractClass() { + assertThrows<IllegalArgumentException> { + TypeSpec.classBuilder("Bar") + .addProperty( + PropertySpec.builder("foo", Int::class) + .addModifiers(ABSTRACT) + .build(), + ) + .build() + }.hasMessageThat().isEqualTo("non-abstract type Bar cannot declare abstract property foo") + } + + @Test fun abstractPropertyInObject() { + assertThrows<IllegalArgumentException> { + TypeSpec.objectBuilder("Bar") + .addProperty( + PropertySpec.builder("foo", Int::class) + .addModifiers(ABSTRACT) + .build(), + ) + .build() + }.hasMessageThat().isEqualTo("non-abstract type Bar cannot declare abstract property foo") + } + + @Test fun abstractPropertyInEnum() { + val typeSpec = TypeSpec.enumBuilder("Bar") + .addProperty( + PropertySpec.builder("foo", Int::class) + .addModifiers(ABSTRACT) + .build(), + ) + .build() + + assertThat(typeSpec.toString()).isEqualTo( + """ + |public enum class Bar { + | ; + | public abstract val foo: kotlin.Int + |} + | + """.trimMargin(), + ) + } + + @Test fun abstractPropertyInSealedClass() { + val typeSpec = TypeSpec.classBuilder("Bar") + .addModifiers(SEALED) + .addProperty( + PropertySpec.builder("foo", Int::class) + .addModifiers(ABSTRACT) + .build(), + ) + .build() + + assertThat(typeSpec.toString()).isEqualTo( + """ + |public sealed class Bar { + | public abstract val foo: kotlin.Int + |} + | + """.trimMargin(), + ) + } + + // https://github.com/square/kotlinpoet/issues/1630 + @Test fun primaryConstructorKDoc() { + val type = TypeSpec.classBuilder("MyClass") + .addKdoc("This is my class") + .primaryConstructor( + FunSpec.constructorBuilder() + .addKdoc("This is my constructor") + .build(), + ) + .build() + + //language=kotlin + assertThat(type.toString()).isEqualTo( + """ + /** + * This is my class + * + * @constructor This is my constructor + */ + public class MyClass() + + """.trimIndent(), + ) + } + companion object { private const val donutsPackage = "com.squareup.donuts" } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeVariableNameTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeVariableNameTest.kt index bca1a7cb..628b569e 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeVariableNameTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeVariableNameTest.kt @@ -176,7 +176,7 @@ class TypeVariableNameTest { .build() assertThat(funSpec.toString()).isEqualTo( """ - |public inline fun <reified T> printMembers(): kotlin.Unit { + |public inline fun <reified T> printMembers() { | println(T::class.members) |} | @@ -251,4 +251,33 @@ class TypeVariableNameTest { } class GenericClass<T> + + @Test fun equalsAndHashCode() { + val typeVariableName1 = TypeVariableName("E", listOf(Number::class.asTypeName()), KModifier.IN) + + val typeVariableName2 = TypeVariableName("E", listOf(Number::class.asTypeName()), KModifier.IN) + assertThat(typeVariableName1).isEqualTo(typeVariableName2) + assertThat(typeVariableName1.hashCode()).isEqualTo(typeVariableName2.hashCode()) + assertThat(typeVariableName1.toString()).isEqualTo(typeVariableName2.toString()) + + assertThat(typeVariableName1.copy(nullable = true)).isNotEqualTo(typeVariableName1) + + assertThat( + typeVariableName1.copy( + annotations = listOf(AnnotationSpec.builder(Suppress::class.asTypeName()).build()), + ), + ).isNotEqualTo(typeVariableName1) + + assertThat(typeVariableName1.copy(bounds = listOf(Runnable::class.asTypeName()))).isNotEqualTo(typeVariableName1) + + assertThat(typeVariableName1.copy(reified = true)).isNotEqualTo(typeVariableName1) + } + + @Test fun equalsAndHashCodeIgnoreTags() { + val typeVariableName = TypeVariableName("E", listOf(Number::class.asTypeName()), KModifier.IN) + val tagged = typeVariableName.copy(tags = mapOf(String::class to "test")) + + assertThat(typeVariableName).isEqualTo(tagged) + assertThat(typeVariableName.hashCode()).isEqualTo(tagged.hashCode()) + } } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/UtilTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/UtilTest.kt index de3650b6..f8bfc0b9 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/UtilTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/UtilTest.kt @@ -124,9 +124,8 @@ class UtilTest { import kotlin.Function1 import kotlin.Int import kotlin.String - import kotlin.Unit - public fun foo(`aaa bbb`: Function1<Int, String>): Unit { + public fun foo(`aaa bbb`: Function1<Int, String>) { `aaa bbb`(0) + `aaa bbb`(1) + `aaa bbb`(2) + `aaa bbb`(3) + `aaa bbb`(4) + `aaa bbb`(5) + `aaa bbb`(6) + `aaa bbb`(7) + `aaa bbb`(8) + `aaa bbb`(9) + `aaa bbb`(100) } diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ValueTypeSpecTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ValueTypeSpecTest.kt index e6efa3fa..363b9898 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ValueTypeSpecTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ValueTypeSpecTest.kt @@ -40,7 +40,8 @@ class ValueTypeSpecTest(private val useValue: Boolean) { private val modifierString = modifier.keyword private fun classBuilder() = if (useValue) { - TypeSpec.valueClassBuilder("Guacamole") + TypeSpec.classBuilder("Guacamole") + .addModifiers(KModifier.VALUE) } else { TypeSpec.classBuilder("Guacamole") .addModifiers(modifier) diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/WildcardTypeNameTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/WildcardTypeNameTest.kt new file mode 100644 index 00000000..db42d003 --- /dev/null +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/WildcardTypeNameTest.kt @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2023 Square, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.squareup.kotlinpoet + +import com.google.common.truth.Truth.assertThat +import com.squareup.kotlinpoet.WildcardTypeName.Companion.consumerOf +import com.squareup.kotlinpoet.WildcardTypeName.Companion.producerOf +import org.junit.Test + +class WildcardTypeNameTest { + + @Test fun equalsAndHashCode() { + val anyProducer1 = producerOf(Any::class) + val anyProducer2 = producerOf(Any::class.asTypeName()) + assertThat(anyProducer1).isEqualTo(anyProducer2) + assertThat(anyProducer1.hashCode()).isEqualTo(anyProducer2.hashCode()) + assertThat(anyProducer1.toString()).isEqualTo(anyProducer2.toString()) + + val stringConsumer1 = consumerOf(String::class) + val stringConsumer2 = consumerOf(String::class.asTypeName()) + assertThat(stringConsumer1).isEqualTo(stringConsumer2) + assertThat(stringConsumer1.hashCode()).isEqualTo(stringConsumer2.hashCode()) + assertThat(stringConsumer1.toString()).isEqualTo(stringConsumer2.toString()) + } + + @Test fun equalsDifferentiatesNullabilityAndAnnotations() { + val anyProducer = producerOf(Any::class) + + assertThat(anyProducer.copy(nullable = true)).isNotEqualTo(anyProducer) + + assertThat(anyProducer.copy(annotations = listOf(AnnotationSpec.builder(Suppress::class).build()))).isNotEqualTo(anyProducer) + } + + @Test fun equalsAndHashCodeIgnoreTags() { + val anyProducer = producerOf(Any::class) + val tagged = anyProducer.copy(tags = mapOf(String::class to "test")) + + assertThat(anyProducer).isEqualTo(tagged) + assertThat(anyProducer.hashCode()).isEqualTo(tagged.hashCode()) + } +} diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt index f0b68a10..66147363 100644 --- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt +++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt @@ -19,6 +19,7 @@ import com.google.common.truth.Truth.assertThat import com.squareup.kotlinpoet.ClassName import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.FunSpec +import com.squareup.kotlinpoet.KModifier import com.squareup.kotlinpoet.KModifier.DATA import com.squareup.kotlinpoet.ParameterSpec import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy @@ -271,14 +272,13 @@ class JvmAnnotationsTest { | |import java.io.IOException |import java.lang.IllegalArgumentException - |import kotlin.Unit |import kotlin.jvm.Throws | |@Throws( | IOException::class, | IllegalArgumentException::class, |) - |public fun foo(): Unit { + |public fun foo() { |} | """.trimMargin(), @@ -297,11 +297,10 @@ class JvmAnnotationsTest { """ |package com.squareup.tacos | - |import kotlin.Unit |import kotlin.jvm.Throws | |@Throws(IllegalTacoException::class) - |public fun foo(): Unit { + |public fun foo() { |} | """.trimMargin(), @@ -419,11 +418,10 @@ class JvmAnnotationsTest { | |import kotlin.Int |import kotlin.String - |import kotlin.Unit |import kotlin.jvm.JvmOverloads | |@JvmOverloads - |public fun foo(bar: Int, baz: String = "baz"): Unit { + |public fun foo(bar: Int, baz: String = "baz") { |} | """.trimMargin(), @@ -515,11 +513,10 @@ class JvmAnnotationsTest { """ |package com.squareup.tacos | - |import kotlin.Unit |import kotlin.jvm.JvmName | |@JvmName("getFoo") - |public fun foo(): Unit { + |public fun foo() { |} | """.trimMargin(), @@ -649,11 +646,10 @@ class JvmAnnotationsTest { """ |package com.squareup.tacos | - |import kotlin.Unit |import kotlin.jvm.JvmSuppressWildcards | |@JvmSuppressWildcards(suppress = false) - |public fun foo(): Unit { + |public fun foo() { |} | """.trimMargin(), @@ -721,11 +717,10 @@ class JvmAnnotationsTest { |package com.squareup.tacos | |import kotlin.Int - |import kotlin.Unit |import kotlin.collections.List |import kotlin.jvm.JvmSuppressWildcards | - |public fun foo(a: List<@JvmSuppressWildcards Int>): Unit { + |public fun foo(a: List<@JvmSuppressWildcards Int>) { |} | """.trimMargin(), @@ -749,11 +744,10 @@ class JvmAnnotationsTest { |package com.squareup.tacos | |import kotlin.Int - |import kotlin.Unit |import kotlin.collections.List |import kotlin.jvm.JvmWildcard | - |public fun foo(a: List<@JvmWildcard Int>): Unit { + |public fun foo(a: List<@JvmWildcard Int>) { |} | """.trimMargin(), @@ -765,6 +759,7 @@ class JvmAnnotationsTest { .addFunction( FunSpec.builder("foo") .synchronized() + .returns(STRING) .addStatement("return %S", "foo") .build(), ) @@ -773,10 +768,11 @@ class JvmAnnotationsTest { """ |package com.squareup.tacos | + |import kotlin.String |import kotlin.jvm.Synchronized | |@Synchronized - |public fun foo() = "foo" + |public fun foo(): String = "foo" | """.trimMargin(), ) @@ -986,11 +982,10 @@ class JvmAnnotationsTest { """ |package com.squareup.tacos | - |import kotlin.Unit |import kotlin.jvm.Strictfp | |@Strictfp - |public fun foo(): Unit { + |public fun foo() { |} | """.trimMargin(), @@ -1085,69 +1080,11 @@ class JvmAnnotationsTest { ) } - @Test fun jvmDefaultProperty() { - val file = FileSpec.builder("com.squareup.tacos", "Taco") - .addType( - TypeSpec.interfaceBuilder("Taco") - .addProperty( - PropertySpec.builder("foo", String::class) - .jvmDefault() - .initializer("%S", "foo") - .build(), - ) - .build(), - ) - .build() - assertThat(file.toString()).isEqualTo( - """ - |package com.squareup.tacos - | - |import kotlin.String - |import kotlin.jvm.JvmDefault - | - |public interface Taco { - | @JvmDefault - | public val foo: String = "foo" - |} - | - """.trimMargin(), - ) - } - - @Test fun jvmDefaultFunction() { - val file = FileSpec.builder("com.squareup.tacos", "Taco") - .addType( - TypeSpec.interfaceBuilder("Taco") - .addFunction( - FunSpec.builder("foo") - .jvmDefault() - .returns(String::class) - .addStatement("return %S", "foo") - .build(), - ) - .build(), - ) - .build() - assertThat(file.toString()).isEqualTo( - """ - |package com.squareup.tacos - | - |import kotlin.String - |import kotlin.jvm.JvmDefault - | - |public interface Taco { - | @JvmDefault - | public fun foo(): String = "foo" - |} - | - """.trimMargin(), - ) - } - @Test fun jvmInlineClass() { val file = FileSpec.builder("com.squareup.tacos", "Taco") .addType( - TypeSpec.valueClassBuilder("Taco") + TypeSpec.classBuilder("Taco") + .addModifiers(KModifier.VALUE) .jvmInline() .primaryConstructor( FunSpec.constructorBuilder() diff --git a/renovate.json b/renovate.json index 7ebea239..47fc816a 100644 --- a/renovate.json +++ b/renovate.json @@ -7,6 +7,13 @@ { "matchManagers": ["pip_requirements"], "automerge": true + }, + { + "matchPackagePatterns": [ + "^org\\.jetbrains\\.kotlin:(?:[\\w-]+)$", + "^com\\.google\\.devtools\\.ksp:(?:[\\w-]+)$" + ], + "groupName": "Kotlin and KSP" } ] } diff --git a/settings.gradle.kts b/settings.gradle.kts index 3e23cc20..4aefa8ec 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -20,10 +20,18 @@ pluginManagement { } } +plugins { + id("org.gradle.toolchains.foojay-resolver-convention") version("0.6.0") +} + include( - ":kotlinpoet", - ":interop:javapoet", - ":interop:kotlinx-metadata", - ":interop:ksp", - ":interop:ksp:test-processor", + ":kotlinpoet", + ":interop:javapoet", + ":interop:kotlinx-metadata", + ":interop:ksp", + ":interop:ksp:test-processor", ) + +rootProject.name = "kotlinpoet-root" + +enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS") |