[automerger skipped] Add build targets for Kotlinpoet am: 53a89f1790 -s ours

am skip reason: Merged-In Iff95eecc39e90d69c4e660f805fbf739eb67e5d2 with SHA-1 a0c72c794d is already in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/external/kotlinpoet/+/25491460

Change-Id: Ie53bebf688480ebae8442251aded3b4dad5ccc92
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/.editorconfig b/.editorconfig
index 3ac5661..f69b685 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -10,3 +10,4 @@
 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 46c3189..0bd44d1 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"
@@ -11,7 +17,7 @@
 
     steps:
       - name: Checkout
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Validate Gradle Wrapper
         uses: gradle/wrapper-validation-action@v1
@@ -20,24 +26,24 @@
         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
-        uses: actions/checkout@v3
+        uses: actions/checkout@v4
 
       - name: Configure JDK
         uses: actions/setup-java@v3
         with:
           distribution: 'zulu'
-          java-version: 18
+          java-version: 19
 
       - name: Prep docs
         run: ./gradlew dokkaHtml
@@ -51,47 +57,3 @@
         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 67c640f..213346e 100644
--- a/.github/workflows/mkdocs-requirements.txt
+++ b/.github/workflows/mkdocs-requirements.txt
@@ -1,19 +1,18 @@
-click==8.1.3
+click==8.1.7
 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
-mkdocs-material-extensions==1.1.1
-Pygments==2.14.0
-pymdown-extensions==9.9.2
+lunr==0.7.0.post1
+MarkupSafe==2.1.3
+mkdocs==1.5.3
+mkdocs-macros-plugin==1.0.4
+mkdocs-material==9.4.5
+mkdocs-material-extensions==1.2
+Pygments==2.16.1
+pymdown-extensions==10.3
 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.3
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..cb8950a
--- /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@v4
+
+      - 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
diff --git a/Android.bp b/Android.bp
index a8df6dc..87c062c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -16,6 +16,7 @@
 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 {
     name: "kotlinpoet-javapoet",
     srcs: ["interop/javapoet/src/main/**/*.kt"],
+    kotlincflags: ["-Xjvm-default=all"],
     static_libs: [
         "javapoet",
         "kotlin-stdlib-jdk8",
diff --git a/METADATA b/METADATA
index 95ed8d4..fbd5831 100644
--- a/METADATA
+++ b/METADATA
@@ -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/+/main: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 @@
     type: GIT
     value: "https://github.com/square/kotlinpoet.git"
   }
-  version: "c99ed244c6e4c7f8594f75566bb19ec62fa9c80d"
-  last_upgrade_date { year: 2023 month: 1 day: 31 }
+  version: "562b5c4a5297e85ae2727fc9f6c4e96e770d7420"
   license_type: NOTICE
+  last_upgrade_date {
+    year: 2023
+    month: 10
+    day: 10
+  }
 }
diff --git a/RELEASING.md b/RELEASING.md
index f987b6e..418d952 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -4,23 +4,10 @@
  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 421de38..3522375 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 @@
 }
 
 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 @@
 
 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 @@
     }
   }
 
-  // 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 05680e6..108d8e0 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 @@
  [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 4b8ec1a..683f40e 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -81,7 +81,7 @@
 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 @@
 ```kotlin
 fun main() {
   var total = 0
-  for (i in 0 until 10) {
+  for (i in 0..<10) {
     total += i
   }
 }
@@ -104,7 +104,7 @@
 ```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 @@
   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 @@
 ```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 @@
 
 ```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 @@
   .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 kotlin.Array
 import kotlin.collections.ArrayList
 import kotlin.collections.List
+import kotlin.reflect.KClass
 
 class HelloWorld {
   fun beyond(): List<Hoverboard> {
@@ -364,6 +373,10 @@
   fun printThings(things: Array<out Thing>) {
     println(things)
   }
+
+  fun printKClass(kClass: KClass<*>) {
+    println(kClass)
+  }
 }
 ```
 
@@ -599,7 +612,7 @@
   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 @@
 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 f0543f0..dc6f725 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 @@
 
 SONATYPE_HOST=S01
 RELEASE_SIGNING_ENABLED=true
+SONATYPE_AUTOMATIC_RELEASE=true
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 523b9bc..6bba5eb 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.10"
+kct = "0.3.2"
+ksp = "1.9.10-1.0.13"
 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.9.0" }
 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.22.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.2-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
index 249e583..7f93135 100644
--- a/gradle/wrapper/gradle-wrapper.jar
+++ b/gradle/wrapper/gradle-wrapper.jar
Binary files differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 8fad3f5..8838ba9 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.4-all.zip
+networkTimeout=10000
+validateDistributionUrl=true
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index a69d9cb..1aa94a4 100755
--- a/gradlew
+++ b/gradlew
@@ -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,11 @@
     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"'
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
 
 # Use the maximum available, or set MAX_FD != -1 to use that value.
 MAX_FD=maximum
@@ -133,22 +131,29 @@
     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=SC2039,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=SC2039,SC3045
         ulimit -n "$MAX_FD" ||
             warn "Could not set maximum file descriptor limit to $MAX_FD"
     esac
@@ -193,11 +198,15 @@
     done
 fi
 
-# 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
-#     double quotes to make sure that they get re-expanded; and
-#   * put everything else in single quotes, so that it's not re-expanded.
+
+# 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, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+#     and any embedded shellness will be escaped.
+#   * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+#     treated as '${Hostname}' itself on the command line.
 
 set -- \
         "-Dorg.gradle.appname=$APP_BASE_NAME" \
diff --git a/gradlew.bat b/gradlew.bat
index f127cfd..93e3f59 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -26,6 +26,7 @@
 
 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 9899d9c..734d934 100644
--- a/interop/javapoet/build.gradle.kts
+++ b/interop/javapoet/build.gradle.kts
@@ -21,7 +21,7 @@
 }
 
 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 b622e6b..9700bde 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 @@
       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 @@
       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 @@
       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 96f47c0..091b303 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 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 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,17 +181,13 @@
 	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 final class com/squareup/kotlinpoet/metadata/specs/JvmModifier$DefaultImpls {
-	public static fun annotationSpec (Lcom/squareup/kotlinpoet/metadata/specs/JvmModifier;)Lcom/squareup/kotlinpoet/AnnotationSpec;
+	public fun annotationSpec ()Lcom/squareup/kotlinpoet/AnnotationSpec;
 }
 
 public final class com/squareup/kotlinpoet/metadata/specs/KmTypesKt {
diff --git a/interop/kotlinx-metadata/build.gradle.kts b/interop/kotlinx-metadata/build.gradle.kts
index df75e1a..a828789 100644
--- a/interop/kotlinx-metadata/build.gradle.kts
+++ b/interop/kotlinx-metadata/build.gradle.kts
@@ -21,10 +21,11 @@
 }
 
 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 @@
   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 4745dda..0000000
--- 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 6cb3c91..bae2474 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.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 @@
 @KotlinPoetMetadataPreview
 public fun Metadata.toKmClass(): KmClass {
   return toKotlinClassMetadata<KotlinClassMetadata.Class>()
-    .toKmClass()
+    .kmClass
 }
 
 @KotlinPoetMetadataPreview
@@ -99,8 +98,8 @@
   }
 }
 
-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 d9caa83..1bbf694 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.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 @@
    * 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 d4f7786..0282913 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.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.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.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.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 @@
 
     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 @@
   }
 
   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 @@
     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 @@
     }
   }
 
+  @OptIn(DelicateKotlinPoetApi::class)
   private fun VariableElement.annotationSpecs(): List<AnnotationSpec> {
-    @Suppress("DEPRECATION")
     return filterOutNullabilityAnnotations(
       annotationMirrors.map { AnnotationSpec.get(it) },
     )
@@ -185,15 +185,15 @@
     }
   }
 
+  @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 @@
     }
   }
 
+  @OptIn(DelicateKotlinPoetApi::class)
   override fun containerData(
     declarationContainer: KmDeclarationContainer,
     className: ClassName,
@@ -311,7 +312,7 @@
     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 @@
 
     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 @@
           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 @@
           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 @@
         }
 
         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 @@
           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 @@
       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 @@
               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 @@
         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 @@
                 }
                 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 235e5e8..aea3213 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.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.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 @@
  *
  * @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 @@
  *
  * 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 @@
   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 fc31ba0..d4c74eb 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.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.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.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 @@
 
     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 @@
 
   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 @@
   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 @@
   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 @@
     }
   }
 
+  @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 @@
     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 @@
   }
 
   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 @@
     return lookupClass(className)?.lookupMethod(methodSignature) != null
   }
 
+  @OptIn(DelicateKotlinPoetApi::class)
   override fun containerData(
     declarationContainer: KmDeclarationContainer,
     className: ClassName,
@@ -293,7 +298,7 @@
     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 @@
 
     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 @@
           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 @@
           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 @@
         }
 
         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 @@
           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 @@
 
     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 @@
         }
         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 @@
               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/KmTypes.kt b/interop/kotlinx-metadata/src/main/kotlin/com/squareup/kotlinpoet/metadata/specs/KmTypes.kt
index cd12479..23e793d 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.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.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 @@
   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 @@
   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 6c0730a..88c7b25 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.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.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.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.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 @@
 ): 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 @@
   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 @@
     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 @@
     }
     ?.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 @@
     }
   }
 
-  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 @@
     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 @@
   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 @@
             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 @@
   return FunSpec.constructorBuilder()
     .apply {
       addAnnotations(constructorData?.allAnnotations.orEmpty())
-      visibilityFrom(flags) { addModifiers(it) }
+      visibilityFrom(visibility) { addModifiers(it) }
       addParameters(
         [email protected] { index, param ->
           param.toParameterSpec(
@@ -516,7 +503,7 @@
           )
         },
       )
-      if (!isPrimary) {
+      if ([email protected]) {
         // TODO How do we know when to add callSuperConstructor()?
       }
     }
@@ -563,14 +550,14 @@
   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 @@
       if (isInline) {
         addModifiers(INLINE)
       }
-      if (isTailRec) {
+      if (isTailrec) {
         addModifiers(TAILREC)
       }
       if (isExternal) {
@@ -612,7 +599,7 @@
       val returnTypeName = [email protected](typeParamsResolver)
       if (returnTypeName != UNIT) {
         returns(returnTypeName)
-        if (!flags.isAbstract) {
+        if (modality != Modality.ABSTRACT) {
           addStatement(NOT_IMPLEMENTED)
         }
       }
@@ -627,17 +614,17 @@
   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 @@
     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 @@
           !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 @@
         }
         .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 @@
           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 @@
       // 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 @@
 @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 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 = [email protected]
           .map { it.toAnnotationSpec() }
         addAnnotations(annotationSpecs)
@@ -886,21 +869,8 @@
 )
 
 @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 @@
   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 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 f6b4467..671147f 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 @@
     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 0000000..ab30c8e
--- /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 adea853..e31c0cc 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 @@
       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 @@
       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 @@
       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 @@
       import kotlin.jvm.Synchronized
 
       @JvmName(name = "jvmStaticFunction")
-      public fun jvmNameFunction(): Unit {
+      public fun jvmNameFunction() {
       }
 
       @JvmOverloads
@@ -202,14 +200,14 @@
         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 c7928b4..a2ad9d1 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 @@
   @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 9198dbc..2dd54bb 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 @@
       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 @@
     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 @@
     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 @@
   }
 
   @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 @@
     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 @@
     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 @@
         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 @@
         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 @@
       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()
 
-        public fun noDefault(): kotlin.Unit
+        public fun noDefaultWithInput(input: kotlin.String)
 
-        public fun noDefaultWithInput(input: kotlin.String): kotlin.Unit
-
-        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 @@
     assertThat(subInterfaceSpec.trimmedToString()).isEqualTo(
       """
       public interface SubInterface : com.squareup.kotlinpoet.metadata.specs.KotlinPoetMetadataSpecsTest.TestInterface {
-        public override fun hasDefault(): kotlin.Unit {
+        override fun hasDefault() {
         }
 
-        @kotlin.jvm.JvmDefault
-        public override fun hasJvmDefault(): kotlin.Unit {
-        }
-
-        public fun subInterfaceFunction(): kotlin.Unit {
+        public fun subInterfaceFunction() {
         }
       }
       """.trimIndent(),
@@ -706,13 +682,13 @@
     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 @@
 
     fun noDefaultWithInputDefault(input: String = "")
 
-    @JvmDefault
-    fun hasJvmDefault() {
-    }
-
     fun hasDefault() {
     }
 
@@ -751,11 +723,6 @@
     fun subInterfaceFunction() {
     }
 
-    @JvmDefault
-    override fun hasJvmDefault() {
-      super.hasJvmDefault()
-    }
-
     override fun hasDefault() {
       super.hasDefault()
     }
@@ -838,19 +805,19 @@
     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 @@
         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 @@
         public var volatileProp: kotlin.String? = null
 
         @kotlin.jvm.Synchronized
-        public fun synchronizedFun(): kotlin.Unit {
+        public fun synchronizedFun() {
         }
       }
       """.trimIndent(),
@@ -1238,11 +1205,7 @@
     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 @@
   }
 
   interface JvmAnnotationsInterface {
-    @JvmDefault
-    fun defaultMethod() {
-    }
     fun notDefaultMethod()
   }
 
@@ -1317,7 +1277,7 @@
         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 @@
 
             @kotlin.jvm.JvmName(name = "jvmStaticFunction")
             @kotlin.jvm.JvmStatic
-            public fun staticFunction(): kotlin.Unit {
+            public fun staticFunction() {
             }
           }
         }
@@ -1364,7 +1324,7 @@
         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 @@
 
             @kotlin.jvm.JvmName(name = "jvmStaticFunction")
             @kotlin.jvm.JvmStatic
-            public fun staticFunction(): kotlin.Unit {
+            public fun staticFunction() {
             }
           }
         }
@@ -1439,7 +1399,7 @@
           param1: kotlin.String,
           optionalParam2: kotlin.String = throw NotImplementedError("Stub!"),
           nullableParam3: kotlin.String? = throw NotImplementedError("Stub!"),
-        ): kotlin.Unit {
+        ) {
         }
       }
       """.trimIndent(),
@@ -1573,7 +1533,7 @@
          * 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 @@
            * 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 @@
              */
             @kotlin.jvm.JvmStatic
             @kotlin.jvm.JvmSynthetic
-            public fun staticFunction(): kotlin.Unit {
+            public fun staticFunction() {
             }
           }
         }
@@ -1638,7 +1598,7 @@
          * 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 @@
            * 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 @@
              * 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 @@
         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 @@
         @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 @@
         @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 @@
       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 @@
     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 @@
 
         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 @@
       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 @@
     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 @@
     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 @@
     assertThat(funInterface.trimmedToString()).isEqualTo(
       """
       public fun interface FunInterface {
-        public fun example(): kotlin.Unit
+        public fun example()
       }
       """.trimIndent(),
     )
@@ -2240,8 +2200,6 @@
   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 cb7c21d..6bb9192 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 @@
   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 cc8cb2b..edc736d 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 c18fa7c..3d615a3 100644
--- a/interop/ksp/build.gradle.kts
+++ b/interop/ksp/build.gradle.kts
@@ -21,7 +21,7 @@
 }
 
 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 7964de2..b5dd38c 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.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 @@
   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 @@
   }
 }
 
-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 @@
       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 @@
         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 0572b73..8d07220 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.toTypeName(
   typeParamResolver: TypeParameterResolver = TypeParameterResolver.EMPTY,
-): TypeName = toTypeName(typeParamResolver, emptyList())
+): TypeName = toTypeName(typeParamResolver, arguments)
 
 internal fun KSType.toTypeName(
   typeParamResolver: TypeParameterResolver,
@@ -64,12 +63,6 @@
   }
   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 f7c40b3..c8373e2 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 @@
  * 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 9fc212e..f0a4d71 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 b1d41d4..82064c8 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.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 @@
     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 @@
         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 @@
       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 @@
           )
           .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 @@
             },
           )
           .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 993222e..1d76346 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 @@
 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 b392f37..8da749d 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 @@
       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 06518ef..1aaa1ed 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 @@
            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 @@
              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 @@
       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 @@
       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 @@
         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 @@
           param1: Function0<String>,
           param2: Function1<String, String>,
           param3: Function1<String, String>,
-        ): Unit {
+        ) {
         }
 
         public fun wildTypes(
@@ -252,7 +291,7 @@
           genericAlias: GenericTypeAlias,
           parameterizedTypeAlias: ParameterizedTypeAlias<String>,
           nestedArray: Array<Map<String, Any>>?,
-        ): Unit {
+        ) {
         }
       }
 
@@ -302,7 +341,6 @@
 
       import kotlin.Int
       import kotlin.String
-      import kotlin.Unit
       import kotlin.collections.List
       import kotlin.collections.Map
 
@@ -313,7 +351,7 @@
           genericMapAlias: Map<Int, String>,
           t1Unused: Map<Int, String>,
           a1: Map<String, Int>,
-        ): Unit {
+        ) {
         }
       }
 
@@ -322,6 +360,75 @@
   }
 
   @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 @@
     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 @@
       """
     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 @@
     )
   }
 
+  @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 59f04dc..114bd19 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 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 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 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,20 +153,25 @@
 }
 
 public abstract interface class com/squareup/kotlinpoet/ContextReceivable {
-	public abstract fun getContextReceiverTypes ()Ljava/util/List;
 }
 
 public abstract interface class com/squareup/kotlinpoet/ContextReceivable$Builder {
-	public abstract fun getContextReceiverTypes ()Ljava/util/List;
-}
-
-public final class com/squareup/kotlinpoet/ContextReceivable$Builder$DefaultImpls {
 }
 
 public abstract interface annotation class com/squareup/kotlinpoet/DelicateKotlinPoetApi : java/lang/annotation/Annotation {
 	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 +181,14 @@
 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 +213,22 @@
 	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 +259,7 @@
 	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 +269,29 @@
 	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 +317,27 @@
 	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 +363,9 @@
 	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 +395,10 @@
 	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 +454,7 @@
 	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 +485,7 @@
 	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 +496,14 @@
 	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 +566,7 @@
 }
 
 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 +574,7 @@
 	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 +586,9 @@
 	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 +605,31 @@
 	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 +652,7 @@
 	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 +664,7 @@
 	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 +688,7 @@
 	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 +697,12 @@
 	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 +722,30 @@
 	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 +759,6 @@
 	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 +771,15 @@
 }
 
 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 +793,14 @@
 	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 +816,31 @@
 	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 +849,7 @@
 	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 +857,7 @@
 	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 +925,7 @@
 	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 +942,13 @@
 	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 +981,29 @@
 	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 +1029,12 @@
 	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 +1048,6 @@
 	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 +1076,7 @@
 	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 +1087,7 @@
 	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 +1105,7 @@
 	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 +1146,10 @@
 	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 830f870..9627b60 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.compileTestKotlin {
-  kotlinOptions {
-    freeCompilerArgs = listOf("-opt-in=com.squareup.kotlinpoet.DelicateKotlinPoetApi")
+  compilerOptions {
+    freeCompilerArgs.add("-opt-in=com.squareup.kotlinpoet.DelicateKotlinPoetApi")
   }
 }
 
@@ -43,6 +42,7 @@
   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 0000000..2553310
--- /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 d44264b..a939092 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.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 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 @@
 
   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 @@
   @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 @@
           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 119d05a..5eeb21b 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 @@
   /** 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 @@
    * 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 @@
       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 @@
 
 @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 61b4b20..6a99631 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 @@
     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])
     }
 
@@ -371,6 +371,7 @@
       val format = DecimalFormatSymbols().apply {
         decimalSeparator = '.'
         groupingSeparator = '_'
+        minusSign = '-'
       }
 
       val precision = if (o is Float || o is Double) o.toString().split(".").last().length else 0
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt
index 2884c65..ff1de01 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 @@
 
       // 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 @@
   }
 
   private fun emitIndentation() {
-    for (j in 0 until indentLevel) {
+    for (j in 0..<indentLevel) {
       out.appendNonWrapping(indent)
     }
   }
@@ -638,6 +639,10 @@
       return true
     }
 
+    if (implicitModifiers.contains(KModifier.PUBLIC) && modifiers.contains(KModifier.OVERRIDE)) {
+      return false
+    }
+
     if (!implicitModifiers.contains(KModifier.PUBLIC)) {
       return false
     }
@@ -706,14 +711,12 @@
         .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 @@
     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 @@
             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 @@
     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 @@
       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/Documentable.kt b/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Documentable.kt
new file mode 100644
index 0000000..3dff284
--- /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 b2f2549..ef3f032 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 @@
 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 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 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 @@
      * 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 @@
       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 @@
       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 @@
       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 2aa75ff..f42308e 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 @@
   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 @@
       }
     }
 
-    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 @@
   /**
    * 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 @@
       return false
     }
 
-    return body.asExpressionBody() == null
+    return body.asExpressionBody() != null
   }
 
   private fun CodeBlock.asExpressionBody(): CodeBlock? {
@@ -304,50 +303,29 @@
 
   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()
+
+    @ExperimentalKotlinPoetApi
     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())
-
     public fun addModifiers(vararg modifiers: KModifier): Builder = apply {
       this.modifiers += modifiers
     }
@@ -558,6 +536,33 @@
       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 @@
 
     @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 efb3b83..9f462f8 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 @@
     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 83a155b..3a1e9a6 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 @@
     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 @@
     // 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 @@
 
     // 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 2700821..4e87774 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 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 9c33ecd..15cf4bf 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 @@
 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 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 @@
       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 ffbcf38..b6bdf79 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 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 8fb5860..9ba9409 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 @@
   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 @@
     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 @@
     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 @@
       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 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 74ff690..f3313ae 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 @@
 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 @@
   }
 
   /** 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 a0a90e2..f9a607f 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 @@
 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 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 @@
       typeVariables += typeVariable
     }
 
-    public fun addKdoc(format: String, vararg args: Any): Builder = apply {
-      kdoc.add(format, *args)
-    }
+    //region Overrides for binary compatibility
+    @Suppress("RedundantOverride")
+    override fun addAnnotation(annotationSpec: AnnotationSpec): Builder = super.addAnnotation(annotationSpec)
 
-    public fun addKdoc(block: CodeBlock): Builder = apply {
-      kdoc.add(block)
-    }
+    @Suppress("RedundantOverride")
+    override fun addAnnotations(annotationSpecs: Iterable<AnnotationSpec>): Builder =
+      super.addAnnotations(annotationSpecs)
 
-    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()
-    }
+    @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)
 
-    public fun addAnnotation(annotation: KClass<*>): Builder =
-      addAnnotation(annotation.asClassName())
+    @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(): 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 bffcf4f..60dea8b 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.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 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 @@
 
   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 @@
       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 c8abca9..5f52e4f 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.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 @@
     .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 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 @@
 
     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 @@
         }
         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 @@
     // 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 @@
   }
 
   /**
-   * 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 @@
         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 @@
 
     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 @@
     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 @@
     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 @@
       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 @@
         "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 @@
             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 @@
         }
       }
 
+      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 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 b2d7517..3313b2c 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 @@
 
   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 f7c4dc0..bd1e096 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 @@
     }
   }
 
+  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 6f18620..fcaae68 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 @@
   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 4f77040..fff366f 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 @@
       |package test
       |
       |import kotlin.Suppress
-      |import kotlin.Unit
       |
-      |public fun test(): Unit {
+      |public fun test() {
       |  @Suppress("Things")
       |  val annotatedString = "AnnotatedString"
       |}
@@ -339,7 +338,7 @@
 
     assertThat(funSpec.toString().trim()).isEqualTo(
       """
-      |public fun operation(): kotlin.Unit {
+      |public fun operation() {
       |  @Suppress("UNCHECKED_CAST")
       |}
       """.trimMargin(),
@@ -474,6 +473,7 @@
         FunSpec.builder("create")
           .addModifiers(OVERRIDE)
           .addParameter("parcel", parcel)
+          .returns(externalClass)
           .addStatement("return %T(parcel.readInt())", externalClass)
           .build(),
       )
@@ -558,16 +558,15 @@
       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 0000000..8d3f439
--- /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 6d06806..92e4f14 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 @@
 
 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 @@
       .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 @@
       |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 @@
         "[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 23ef056..be4e62d 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt
+++ b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt
@@ -17,6 +17,7 @@
 
 import com.google.common.truth.Truth.assertThat
 import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
+import java.util.Locale
 import kotlin.test.Test
 
 class CodeBlockTest {
@@ -517,9 +518,7 @@
       """
       |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 " ==
@@ -629,4 +628,16 @@
     assertThat(CodeBlock.of("%S", 10000.12345678901).toString()).isEqualTo("\"10000.12345678901\"")
     assertThat(CodeBlock.of("%S", 1281.toShort()).toString()).isEqualTo("\"1281\"")
   }
+
+  // https://github.com/square/kotlinpoet/issues/1657
+  @Test fun minusSignInSwedishLocale() {
+    val defaultLocale = Locale.getDefault()
+    Locale.setDefault(Locale.forLanguageTag("sv"))
+
+    val i = -42
+    val s = CodeBlock.of("val i = %L", i)
+    assertThat(s.toString()).isEqualTo("val i = -42")
+
+    Locale.setDefault(defaultLocale)
+  }
 }
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt b/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt
index 5074b91..cc119be 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 @@
   @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 @@
       """
       |import java.util.concurrent.atomic.AtomicReference
       |import kotlin.Boolean
-      |import kotlin.Unit
       |
       |internal expect class AtomicRef<V>(
       |  `value`: V,
@@ -81,7 +80,7 @@
       |
       |  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 @@
   }
 
   @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 @@
       .addFunction(
         FunSpec.builder("f1")
           .addModifiers(KModifier.ACTUAL)
+          .returns(INT)
           .addStatement("return 1")
           .build(),
       )
@@ -168,7 +168,7 @@
       |
       |public expect fun f1(): Int
       |
-      |public actual fun f1() = 1
+      |public actual fun f1(): Int = 1
       |
       """.trimMargin(),
     )
@@ -176,14 +176,16 @@
 
   @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 @@
 
   @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 @@
 
   @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 @@
 
   @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 5cb7753..00b0c88 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 @@
 
     assertThat(methodSpec.toString()).isEqualTo(
       """
-      |public expect fun function(): kotlin.Unit
+      |public expect fun function()
       |
       """.trimMargin(),
     )
@@ -42,7 +42,7 @@
     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 42719c4..8cc5f49 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 @@
 
     assertThat(methodSpec.toString()).isEqualTo(
       """
-      |public external fun function(): kotlin.Unit
+      |public external fun function()
       |
       """.trimMargin(),
     )
@@ -35,12 +35,13 @@
   @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 @@
 
     assertThat(methodSpec.toString()).isEqualTo(
       """
-      |public external fun function(): kotlin.Unit {
+      |public external fun function() {
       |  kotlin.js.definedExternally
       |}
       |
@@ -72,7 +73,7 @@
     assertThat(builder.build().toString()).isEqualTo(
       """
         |public external class Test {
-        |  public fun function(): kotlin.Unit
+        |  public fun function()
         |}
         |
       """.trimMargin(),
@@ -83,6 +84,7 @@
     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 @@
     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 @@
     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 03b3cfc..c363f59 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 @@
       |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 @@
       """
       |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 @@
       """
       |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 @@
         |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 @@
       """
       |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 @@
       |
       |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 @@
     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 @@
       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 3980709..83574f3 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 @@
         |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 1376caf..4fff9fe 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 @@
       .build()
     assertThat(funSpec.toString()).isEqualTo(
       """
-      |public fun foo(string: kotlin.String?): kotlin.Unit {
+      |public fun foo(string: kotlin.String?) {
       |}
       |
       """.trimMargin(),
@@ -195,7 +195,7 @@
 
     assertThat(funSpec.toString()).isEqualTo(
       """
-      |public fun foo(): kotlin.Unit {
+      |public fun foo() {
       |}
       |
       """.trimMargin(),
@@ -272,7 +272,7 @@
       |  string: kotlin.String,
       |  number: kotlin.Int,
       |  nodoc: kotlin.Boolean,
-      |): kotlin.Unit {
+      |) {
       |}
       |
       """.trimMargin(),
@@ -295,7 +295,7 @@
       |/**
       | * @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 @@
 
     assertThat(funSpec.toString()).isEqualTo(
       """
-      |public fun foo(): kotlin.Unit {
+      |public fun foo() {
       |  throwOrDoSomethingElse()
       |}
       |
@@ -388,12 +388,13 @@
 
   @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 @@
     assertThat(funSpec.toString()).isEqualTo(
       """
       |context(kotlin.String)
-      |public fun foo(): kotlin.Unit {
+      |public fun foo() {
       |}
       |
       """.trimMargin(),
@@ -511,7 +512,7 @@
     assertThat(funSpec.toString()).isEqualTo(
       """
       |context(kotlin.String, kotlin.Int, kotlin.Boolean)
-      |public fun foo(): kotlin.Unit {
+      |public fun foo() {
       |}
       |
       """.trimMargin(),
@@ -528,7 +529,7 @@
     assertThat(funSpec.toString()).isEqualTo(
       """
       |context(T)
-      |public fun <T> foo(): kotlin.Unit {
+      |public fun <T> foo() {
       |}
       |
       """.trimMargin(),
@@ -545,7 +546,7 @@
       """
       |context(kotlin.String)
       |@com.squareup.kotlinpoet.FunSpecTest.TestAnnotation
-      |public fun foo(): kotlin.Unit {
+      |public fun foo() {
       |}
       |
       """.trimMargin(),
@@ -561,7 +562,7 @@
     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 @@
 
     assertThat(funSpec.toString()).isEqualTo(
       """
-      |public private internal fun myMethod(): kotlin.Unit {
+      |public private internal fun myMethod() {
       |}
       |
       """.trimMargin(),
@@ -730,7 +731,7 @@
 
     assertThat(funSpec.toString()).isEqualTo(
       """
-      |public fun myMethod(): kotlin.Unit {
+      |public fun myMethod() {
       |}
       |
       """.trimMargin(),
@@ -847,7 +848,7 @@
 
     assertThat(funSpec.toString()).isEqualTo(
       """
-      |public fun `if`(): kotlin.Unit {
+      |public fun `if`() {
       |}
       |
       """.trimMargin(),
@@ -860,7 +861,7 @@
 
     assertThat(funSpec.toString()).isEqualTo(
       """
-      |public fun `with-hyphen`(): kotlin.Unit {
+      |public fun `with-hyphen`() {
       |}
       |
       """.trimMargin(),
@@ -1044,7 +1045,7 @@
     assertThat(builder.build().toString()).isEqualTo(
       """
       |@kotlin.jvm.JvmStatic
-      |internal fun staticMethod(): kotlin.Unit {
+      |internal fun staticMethod() {
       |}
       |
       """.trimMargin(),
@@ -1057,7 +1058,7 @@
 
     assertThat(builder.build().toString()).isEqualTo(
       """
-      |internal final fun finalMethod(): kotlin.Unit {
+      |internal final fun finalMethod() {
       |}
       |
       """.trimMargin(),
@@ -1071,7 +1072,7 @@
     assertThat(builder.build().toString()).isEqualTo(
       """
       |@kotlin.jvm.Synchronized
-      |internal fun synchronizedMethod(): kotlin.Unit {
+      |internal fun synchronizedMethod() {
       |}
       |
       """.trimMargin(),
@@ -1085,7 +1086,7 @@
 
     assertThat(methodSpec.toString()).isEqualTo(
       """
-      |public fun function(): kotlin.Unit {
+      |public fun function() {
       |  codeWithNoNewline()
       |}
       |
@@ -1101,7 +1102,7 @@
 
     assertThat(methodSpec.toString()).isEqualTo(
       """
-      |public fun function(): kotlin.Unit {
+      |public fun function() {
       |  codeWithNoNewline()
       |}
       |
@@ -1112,12 +1113,13 @@
   // 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 @@
 
   @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 @@
       |/**
       | * This is a comment with no initial newline
       | */
-      |public fun function(): kotlin.Unit {
+      |public fun function() {
       |}
       |
       """.trimMargin(),
@@ -1164,7 +1167,7 @@
       |/**
       | * This is a comment with an initial newline
       | */
-      |public fun function(): kotlin.Unit {
+      |public fun function() {
       |}
       |
       """.trimMargin(),
@@ -1187,7 +1190,7 @@
       |
       |import kotlin.Unit
       |
-      |public fun (@Annotation () -> Unit).foo(): Unit {
+      |public fun (@Annotation () -> Unit).foo() {
       |}
       |
       """.trimMargin(),
@@ -1216,4 +1219,18 @@
       """.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 9d3f171..642b65c 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 @@
         |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 @@
       """
         |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 @@
       "" +
         "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 @@
       "" +
         "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 @@
       "" +
         "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 @@
         |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 @@
       """
       |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 @@
       |
       |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 @@
       """
       |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 @@
       |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 @@
       |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 @@
       |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 @@
       """
       |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 @@
       | * @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 @@
       """
       |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 @@
       """
       |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 @@
     )
   }
 
+  // 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 @@
       """
       |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 @@
       """.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 5b72b79..1bcaef4 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 @@
     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 332a25b..3471607 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 @@
 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 @@
       """
         |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 @@
 
   @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 @@
       """
         |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 @@
 
   @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 @@
       """
         |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 @@
 
   @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 @@
       """
         |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 @@
       """
         |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 @@
         |package com.squareup.tacos
         |
         |import kotlin.String
-        |import kotlin.Unit
         |
         |public class Taco {
         |  public fun call(
@@ -195,7 +202,7 @@
         |    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 308aeb2..69271d7 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 @@
       |
       |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 @@
       |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 @@
       """
       |package com.squareup.tacos
       |
-      |import kotlin.Unit
-      |
-      |public fun makeTastyTacos(): Unit {
+      |public fun makeTastyTacos() {
       |  createTaco()
       |}
       |
@@ -115,9 +111,8 @@
       |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 @@
       """
       |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 @@
       """
       |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 @@
       |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 @@
       """
       |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 @@
       """
       |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 @@
       """
       |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 @@
       """
       |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 @@
       """
       |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 @@
       """
       |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 @@
       |
       |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 @@
       |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 @@
       |
       |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 @@
       |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 @@
       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 d764f44..5528e49 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 @@
       |
       |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 f4e5625..a94dddd 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 @@
     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 5eda0f7..af373c2 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 @@
     )
   }
 
-  @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 49bec35..d25ca4e 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 @@
   @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 @@
   @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 @@
   @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 cf6c3e2..ebac635 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.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 @@
       """
         |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 @@
         |
         |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 @@
       """
         |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 @@
         |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 @@
         |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 @@
       """
         |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 @@
   }
 
   @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 @@
     assertThat(classA.toString()).isEqualTo(
       """
       |public expect class ClassA {
-      |  public fun test(): kotlin.Unit
+      |  public fun test()
       |}
       |
       """.trimMargin(),
@@ -1497,7 +1490,8 @@
   }
 
   @Test fun nestedExpectCompanionObjectWithFunction() {
-    val classA = TypeSpec.expectClassBuilder("ClassA")
+    val classA = TypeSpec.classBuilder("ClassA")
+      .addModifiers(KModifier.EXPECT)
       .addType(
         TypeSpec.companionObjectBuilder()
           .addFunction(
@@ -1512,7 +1506,7 @@
       """
       |public expect class ClassA {
       |  public companion object {
-      |    public fun test(): kotlin.Unit
+      |    public fun test()
       |  }
       |}
       |
@@ -1521,7 +1515,8 @@
   }
 
   @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 @@
       """
       |public expect class ClassA {
       |  public class ClassB {
-      |    public fun test(): kotlin.Unit
+      |    public fun test()
       |  }
       |}
       |
@@ -1545,7 +1540,8 @@
   }
 
   @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 @@
       |public expect class ClassA {
       |  public class ClassB {
       |    public class ClassC {
-      |      public fun test(): kotlin.Unit
+      |      public fun test()
       |    }
       |  }
       |}
@@ -1575,7 +1571,8 @@
   }
 
   @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 @@
       |  public class ClassB {
       |    public class ClassC {
       |      public class ClassD {
-      |        public fun test(): kotlin.Unit
+      |        public fun test()
       |      }
       |    }
       |  }
@@ -1611,7 +1608,8 @@
   }
 
   @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 @@
   }
 
   @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 @@
       """
         |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 @@
         |
         |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 @@
         |   *
         |   * For [Locale#KOREAN], the front may also be folded.
         |   */
-        |  public fun refold(locale: Locale): Unit {
+        |  public fun refold(locale: Locale) {
         |  }
         |}
         |
@@ -2056,10 +2052,9 @@
         |
         |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 @@
         |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 @@
       .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 @@
         |
         |  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 @@
         |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 @@
         |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 @@
         |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 @@
         |import kotlin.Int
         |import kotlin.Long
         |import kotlin.String
-        |import kotlin.Unit
         |
         |public class Members {
         |  public val W: String
@@ -2344,16 +2334,16 @@
         |
         |  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 @@
     assertThat(type.toString()).isEqualTo(
       """
         |object : java.lang.Runnable {
-        |  public override fun run(): kotlin.Unit {
+        |  public override fun run() {
         |  }
         |}
       """.trimMargin(),
@@ -2599,7 +2589,6 @@
         |import java.util.Comparator
         |import kotlin.Int
         |import kotlin.String
-        |import kotlin.Unit
         |import kotlin.collections.List
         |
         |public class Taco {
@@ -2614,7 +2603,7 @@
         |    }
         |  }
         |
-        |  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 @@
       """
         |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 @@
       .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 @@
       """
         |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 @@
   }
 
   @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 @@
         |package com.squareup.tacos
         |
         |import kotlin.Int
-        |import kotlin.Unit
         |
         |public object MyObject {
         |  public val tacos: Int
@@ -3391,7 +3379,7 @@
         |  init {
         |  }
         |
-        |  public fun test(): Unit {
+        |  public fun test() {
         |  }
         |}
         |
@@ -3417,13 +3405,12 @@
         |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 @@
         |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 @@
       """
         |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 @@
       """
         |package com.squareup.tacos
         |
-        |import kotlin.Unit
-        |
         |public interface MyInterface {
         |  public companion object {
-        |    public fun test(): Unit {
+        |    public fun test() {
         |    }
         |  }
         |}
@@ -3587,15 +3569,13 @@
       """
         |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 @@
         |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 @@
     }.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 @@
       |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 @@
         |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 @@
       """
       |package com.squareup.tacos
       |
-      |import kotlin.Unit
-      |
       |public external class Foo {
-      |  public fun bar(): Unit
+      |  public fun bar()
       |}
       |
       """.trimMargin(),
@@ -4445,12 +4451,11 @@
       |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 @@
       |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 @@
       """
       |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 @@
     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 @@
       """
       |/**
       | * This is a thing for stuff.
+      | *
+      | * @constructor Construct a thing!
       | */
       |public class MyType(
       |  /**
@@ -5138,7 +5142,7 @@
       .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 @@
       package com.squareup.tacos
 
       import kotlin.String
-      import kotlin.Unit
 
       public interface Taco {
         public val foo: String
@@ -5191,7 +5194,7 @@
 
         public fun bar(): String
 
-        public fun barWithDefault(): Unit {
+        public fun barWithDefault() {
         }
       }
 
@@ -5336,6 +5339,85 @@
     )
   }
 
+  // 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 @@
     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 bca1a7c..628b569 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 @@
       .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 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 de3650b..f8bfc0b 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 @@
       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 e6efa3f..363b989 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 @@
   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 0000000..db42d00
--- /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 f0b68a1..6614736 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.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 @@
       |
       |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 @@
       """
       |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 @@
       |
       |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 @@
       """
       |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 @@
       """
       |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 @@
       |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 @@
       |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 @@
       .addFunction(
         FunSpec.builder("foo")
           .synchronized()
+          .returns(STRING)
           .addStatement("return %S", "foo")
           .build(),
       )
@@ -773,10 +768,11 @@
       """
       |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 @@
       """
       |package com.squareup.tacos
       |
-      |import kotlin.Unit
       |import kotlin.jvm.Strictfp
       |
       |@Strictfp
-      |public fun foo(): Unit {
+      |public fun foo() {
       |}
       |
       """.trimMargin(),
@@ -1085,69 +1080,11 @@
     )
   }
 
-  @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 7ebea23..47fc816 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 3e23cc2..465f238 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -20,10 +20,18 @@
   }
 }
 
+plugins {
+  id("org.gradle.toolchains.foojay-resolver-convention") version("0.7.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")