aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSadaf Ebrahimi <sadafebrahimi@google.com>2024-02-20 16:39:45 +0000
committerAutomerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>2024-02-20 16:39:45 +0000
commit8f0503c359a4d94cf537a29a4dc9df7885be9cc5 (patch)
treeef6bae21f79804e20e6449e174536d7dca972376
parent42861d32915d16a42f84d4758782d2fff26e6c17 (diff)
parentaf7bd99cda5997a81e801e1220bc78a696ec147d (diff)
downloadkotlinpoet-8f0503c359a4d94cf537a29a4dc9df7885be9cc5.tar.gz
Upgrade kotlinpoet to 1.16.0 am: af7bd99cdaHEADmastermain
Original change: https://android-review.googlesource.com/c/platform/external/kotlinpoet/+/2967683 Change-Id: I5922082e30e41d299676b15095b223a761ca1b40 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r--.github/workflows/build.yml25
-rw-r--r--.github/workflows/gradle-wrapper.yaml15
-rw-r--r--.github/workflows/mkdocs-requirements.txt16
-rw-r--r--.github/workflows/release.yml4
-rw-r--r--.gitignore1
-rw-r--r--Android.bp10
-rw-r--r--METADATA23
-rw-r--r--RELEASING.md4
-rw-r--r--build.gradle.kts73
-rw-r--r--docs/annotations.md118
-rw-r--r--docs/anonymous-inner-classes.md44
-rw-r--r--docs/callable-references.md45
-rw-r--r--docs/changelog.md69
-rw-r--r--docs/code-block-format-strings.md36
-rw-r--r--docs/code-control-flow.md76
-rw-r--r--docs/constructors.md80
-rw-r--r--docs/enums.md78
-rw-r--r--docs/functions.md160
-rw-r--r--docs/index.md1480
-rw-r--r--docs/interfaces.md45
-rw-r--r--docs/kotlin-reflect.md45
-rw-r--r--docs/l-for-literals.md25
-rw-r--r--docs/m-for-members.md122
-rw-r--r--docs/n-for-names.md70
-rw-r--r--docs/objects.md42
-rw-r--r--docs/p-for-string-templates.md67
-rw-r--r--docs/parameters.md25
-rw-r--r--docs/properties.md142
-rw-r--r--docs/s-for-strings.md41
-rw-r--r--docs/t-for-types.md161
-rw-r--r--docs/type-aliases.md49
-rw-r--r--gradle.properties2
-rw-r--r--gradle/libs.versions.toml19
-rw-r--r--gradle/wrapper/gradle-wrapper.jarbin63721 -> 43462 bytes
-rw-r--r--gradle/wrapper/gradle-wrapper.properties2
-rw-r--r--interop/javapoet/build.gradle.kts3
-rw-r--r--interop/kotlinx-metadata/build.gradle.kts3
-rw-r--r--interop/ksp/build.gradle.kts3
-rw-r--r--interop/ksp/src/main/kotlin/com/squareup/kotlinpoet/ksp/KsTypes.kt15
-rw-r--r--interop/ksp/test-processor/build.gradle.kts1
-rw-r--r--interop/ksp/test-processor/src/main/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessor.kt9
-rw-r--r--interop/ksp/test-processor/src/test/kotlin/com/squareup/kotlinpoet/ksp/test/processor/TestProcessorTest.kt44
-rw-r--r--kotlinpoet/api/kotlinpoet.api39
-rw-r--r--kotlinpoet/build.gradle.kts71
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Annotatable.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/Annotatable.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/AnnotationSpec.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/AnnotationSpec.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ClassName.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/ClassName.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/CodeBlock.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeBlock.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/CodeWriter.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt)14
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ContextReceivable.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/ContextReceivable.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/DelicateKotlinPoetApi.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/DelicateKotlinPoetApi.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Documentable.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/Documentable.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Dynamic.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/Dynamic.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ExperimentalKotlinPoetApi.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/ExperimentalKotlinPoetApi.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FileSpec.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/FileSpec.kt)82
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FunSpec.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/FunSpec.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Import.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/Import.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/KModifier.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/KModifier.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/KOperator.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/KOperator.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/LambdaTypeName.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/LambdaTypeName.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/LineWrapper.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/LineWrapper.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/MemberName.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/MemberName.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/NameAllocator.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/NameAllocator.kt)36
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/OriginatingElementsHolder.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/OriginatingElementsHolder.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ParameterSpec.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterSpec.kt)2
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ParameterizedTypeName.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterizedTypeName.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/PropertySpec.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/PropertySpec.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Taggable.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/Taggable.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeAliasSpec.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeAliasSpec.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeName.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpec.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt)55
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpecHolder.kt31
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeVariableName.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeVariableName.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Util.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/Util.kt)2
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/WildcardTypeName.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/WildcardTypeName.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt)0
-rw-r--r--kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/tags/TypeAliasTag.kt (renamed from kotlinpoet/src/main/java/com/squareup/kotlinpoet/tags/TypeAliasTag.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AbstractTypesTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/AbstractTypesTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AnnotatedTypeNameTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotatedTypeNameTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AnnotationSpecTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotationSpecTest.kt)48
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AssertThrows.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/AssertThrows.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/Cased/Weird/Sup.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/Cased/Weird/Sup.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ClassNameTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/ClassNameTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/CodeBlockTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/CrossplatformTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/DelegatedConstructorCallTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/DelegatedConstructorCallTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileReadingTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileReadingTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileSpecTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileSpecTest.kt)31
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileWritingTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileWritingTest.kt)47
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FunSpecTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/KotlinPoetTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/KotlinPoetTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LambdaTypeNameTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/LambdaTypeNameTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LineWrapperTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrapperTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LineWrappingTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrappingTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/MemberNameTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/MemberNameTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/NameAllocatorTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/NameAllocatorTest.kt)6
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ParameterSpecTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/PropertySpecTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/StringsTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/StringsTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TaggableTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TaggableTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TestFiler.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TestFiler.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeAliasSpecTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeAliasSpecTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeNameKotlinTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeNameKotlinTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeSpecTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt)38
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeVariableNameTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeVariableNameTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypesEclipseTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypesEclipseTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypesTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypesTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/UtilTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/UtilTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ValueTypeSpecTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/ValueTypeSpecTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/WildcardTypeNameTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/WildcardTypeNameTest.kt)0
-rw-r--r--kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt)0
-rw-r--r--kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/JavaAnnotationSpecTest.kt78
-rw-r--r--kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/JavaClassWithArrayValueAnnotation.java (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/JavaClassWithArrayValueAnnotation.java)0
-rw-r--r--kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/TypeNameTest.java (renamed from kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeNameTest.java)0
-rw-r--r--mkdocs.yml28
-rw-r--r--renovate.json1
-rw-r--r--settings.gradle.kts2
120 files changed, 2166 insertions, 1737 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index 0bd44d18..187d0acf 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -13,24 +13,33 @@ env:
jobs:
jvm:
- runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ os:
+ - macos-latest
+ - ubuntu-latest
+ - windows-latest
+
+ runs-on: ${{ matrix.os }}
steps:
- name: Checkout
uses: actions/checkout@v4
- - name: Validate Gradle Wrapper
- uses: gradle/wrapper-validation-action@v1
-
- name: Configure JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 19
- - name: Test
+ - name: Full build
+ if: matrix.os == 'ubuntu-latest'
run: ./gradlew build
+ - name: KotlinPoet check
+ if: "matrix.os != 'ubuntu-latest'"
+ run: ./gradlew :kotlinpoet:check
+
build-docs:
runs-on: ubuntu-latest
if: github.repository == 'square/kotlinpoet'
@@ -40,7 +49,7 @@ jobs:
uses: actions/checkout@v4
- name: Configure JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 19
@@ -49,7 +58,7 @@ jobs:
run: ./gradlew dokkaHtml
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: 3.8
diff --git a/.github/workflows/gradle-wrapper.yaml b/.github/workflows/gradle-wrapper.yaml
new file mode 100644
index 00000000..d82e2914
--- /dev/null
+++ b/.github/workflows/gradle-wrapper.yaml
@@ -0,0 +1,15 @@
+name: gradle-wrapper
+
+on:
+ pull_request:
+ paths:
+ - 'gradlew'
+ - 'gradlew.bat'
+ - 'gradle/wrapper/**'
+
+jobs:
+ validate:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: gradle/wrapper-validation-action@v1
diff --git a/.github/workflows/mkdocs-requirements.txt b/.github/workflows/mkdocs-requirements.txt
index 213346e0..5f787ffa 100644
--- a/.github/workflows/mkdocs-requirements.txt
+++ b/.github/workflows/mkdocs-requirements.txt
@@ -1,18 +1,18 @@
click==8.1.7
future==0.18.3
-Jinja2==3.1.2
+Jinja2==3.1.3
livereload==2.6.3
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
+mkdocs-macros-plugin==1.0.5
+mkdocs-material==9.5.4
+mkdocs-material-extensions==1.3.1
+Pygments==2.17.2
+pymdown-extensions==10.7
python-dateutil==2.8.2
PyYAML==6.0.1
repackage==0.7.3
six==1.16.0
-termcolor==2.3.0
-tornado==6.3.3
+termcolor==2.4.0
+tornado==6.4
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index cb8950a9..1a2f3f98 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -20,7 +20,7 @@ jobs:
uses: actions/checkout@v4
- name: Configure JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v4
with:
distribution: 'zulu'
java-version: 19
@@ -36,7 +36,7 @@ jobs:
run: ./gradlew dokkaHtml
- name: Set up Python
- uses: actions/setup-python@v4
+ uses: actions/setup-python@v5
with:
python-version: 3.8
diff --git a/.gitignore b/.gitignore
index 75e7808e..9310aea4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -18,6 +18,7 @@ classes
# Mkdocs files
docs/1.x/*
+site
obj
diff --git a/Android.bp b/Android.bp
index 87c062c4..1505c4ad 100644
--- a/Android.bp
+++ b/Android.bp
@@ -15,12 +15,14 @@ license {
java_library_host {
name: "kotlinpoet",
- srcs: ["kotlinpoet/src/main/**/*.kt"],
+ srcs: [
+ "kotlinpoet/src/commonMain/**/*.kt",
+ ],
kotlincflags: ["-Xjvm-default=all"],
static_libs: [
"kotlin-stdlib-jdk8",
"kotlin-reflect",
- ]
+ ],
}
java_library_host {
@@ -30,6 +32,6 @@ java_library_host {
static_libs: [
"javapoet",
"kotlin-stdlib-jdk8",
- "kotlinpoet"
- ]
+ "kotlinpoet",
+ ],
}
diff --git a/METADATA b/METADATA
index fbd58313..127fc451 100644
--- a/METADATA
+++ b/METADATA
@@ -1,23 +1,20 @@
# This project was upgraded with external_updater.
-# Usage: tools/external_updater/updater.sh update kotlinpoet
+# Usage: tools/external_updater/updater.sh update external/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
- value: "https://square.github.io/kotlinpoet/"
- }
- url {
- type: GIT
- value: "https://github.com/square/kotlinpoet.git"
- }
- version: "562b5c4a5297e85ae2727fc9f6c4e96e770d7420"
license_type: NOTICE
last_upgrade_date {
- year: 2023
- month: 10
- day: 10
+ year: 2024
+ month: 2
+ day: 15
+ }
+ homepage: "https://square.github.io/kotlinpoet/"
+ identifier {
+ type: "Git"
+ value: "https://github.com/square/kotlinpoet.git"
+ version: "1.16.0"
}
}
diff --git a/RELEASING.md b/RELEASING.md
index 418d9523..7c064c74 100644
--- a/RELEASING.md
+++ b/RELEASING.md
@@ -10,4 +10,6 @@ Releasing
7. `git push && git push --tags`.
This will trigger a GitHub Action workflow which will create a GitHub release and upload the
-release artifacts to Maven Central.
+release artifacts to [Maven Central][maven-central].
+
+ [maven-central]: https://repo.maven.apache.org/maven2/com/squareup/kotlinpoet/
diff --git a/build.gradle.kts b/build.gradle.kts
index 35223751..16fa8722 100644
--- a/build.gradle.kts
+++ b/build.gradle.kts
@@ -17,10 +17,12 @@ 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.KotlinMultiplatformExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinProjectExtension
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
plugins {
+ alias(libs.plugins.kotlin.multiplatform) apply false
alias(libs.plugins.kotlin.jvm) apply false
alias(libs.plugins.ksp) apply false
alias(libs.plugins.dokka) apply false
@@ -53,12 +55,18 @@ subprojects {
options.release.set(8)
}
- apply(plugin = "org.jetbrains.kotlin.jvm")
if ("test" !in name && buildFile.exists()) {
apply(plugin = "org.jetbrains.dokka")
apply(plugin = "com.vanniktech.maven.publish")
- configure<KotlinProjectExtension> {
- explicitApi()
+ pluginManager.withPlugin("org.jetbrains.kotlin.multiplatform") {
+ configure<KotlinMultiplatformExtension> {
+ explicitApi()
+ }
+ }
+ pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
+ configure<KotlinProjectExtension> {
+ explicitApi()
+ }
}
afterEvaluate {
tasks.named<DokkaTask>("dokkaHtml") {
@@ -70,7 +78,6 @@ subprojects {
}
}
}
-
apply(plugin = "com.diffplug.spotless")
configure<SpotlessExtension> {
kotlin {
@@ -98,7 +105,7 @@ subprojects {
| * See the License for the specific language governing permissions and
| * limitations under the License.
| */
- """.trimMargin()
+ """.trimMargin(),
)
}
}
@@ -106,32 +113,44 @@ subprojects {
// 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)
- })
+ fun Project.setupCheckTask(testTaskName: String) {
+ // 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)
+ },
+ )
+
+ 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>(testTaskName)
- // Copy inputs from normal Test task.
- val testTask = tasks.getByName<Test>("test")
- classpath = testTask.classpath
- testClassesDirs = testTask.testClassesDirs
+ classpath = testTask.classpath
+ testClassesDirs = testTask.testClassesDirs
- testLogging {
- exceptionFormat = TestExceptionFormat.FULL
+ testLogging {
+ exceptionFormat = TestExceptionFormat.FULL
+ }
+ }
+ tasks.named("check").configure {
+ dependsOn(jdkTest)
}
}
- tasks.named("check").configure {
- dependsOn(jdkTest)
- }
+ }
+ pluginManager.withPlugin("org.jetbrains.kotlin.multiplatform") {
+ setupCheckTask("jvmTest")
+ }
+ pluginManager.withPlugin("org.jetbrains.kotlin.jvm") {
+ setupCheckTask("test")
}
}
}
@@ -140,6 +159,6 @@ apiValidation {
nonPublicMarkers += "com.squareup.kotlinpoet.ExperimentalKotlinPoetApi"
ignoredProjects += listOf(
"interop", // Empty middle package
- "test-processor" // Test only
+ "test-processor", // Test only
)
}
diff --git a/docs/annotations.md b/docs/annotations.md
new file mode 100644
index 00000000..47a2cd95
--- /dev/null
+++ b/docs/annotations.md
@@ -0,0 +1,118 @@
+Annotations
+===========
+
+Simple annotations are easy:
+
+```kotlin
+val test = FunSpec.builder("test string equality")
+ .addAnnotation(Test::class)
+ .addStatement("assertThat(%1S).isEqualTo(%1S)", "foo")
+ .build()
+```
+
+Which generates this function with an `@Test` annotation:
+
+```kotlin
+@Test
+fun `test string equality`() {
+ assertThat("foo").isEqualTo("foo")
+}
+```
+
+Use `AnnotationSpec.builder()` to set properties on annotations:
+
+```kotlin
+val logRecord = FunSpec.builder("recordEvent")
+ .addModifiers(KModifier.ABSTRACT)
+ .addAnnotation(
+ AnnotationSpec.builder(Headers::class)
+ .addMember("accept = %S", "application/json; charset=utf-8")
+ .addMember("userAgent = %S", "Square Cash")
+ .build()
+ )
+ .addParameter("logRecord", LogRecord::class)
+ .returns(LogReceipt::class)
+ .build()
+```
+
+Which generates this annotation with `accept` and `userAgent` properties:
+
+```kotlin
+@Headers(
+ accept = "application/json; charset=utf-8",
+ userAgent = "Square Cash"
+)
+abstract fun recordEvent(logRecord: LogRecord): LogReceipt
+```
+
+When you get fancy, annotation values can be annotations themselves. Use `%L` for embedded
+annotations:
+
+```kotlin
+val headerList = ClassName("", "HeaderList")
+val header = ClassName("", "Header")
+val logRecord = FunSpec.builder("recordEvent")
+ .addModifiers(KModifier.ABSTRACT)
+ .addAnnotation(
+ AnnotationSpec.builder(headerList)
+ .addMember(
+ "[\n⇥%L,\n%L⇤\n]",
+ AnnotationSpec.builder(header)
+ .addMember("name = %S", "Accept")
+ .addMember("value = %S", "application/json; charset=utf-8")
+ .build(),
+ AnnotationSpec.builder(header)
+ .addMember("name = %S", "User-Agent")
+ .addMember("value = %S", "Square Cash")
+ .build()
+ )
+ .build()
+ )
+ .addParameter("logRecord", logRecordName)
+ .returns(logReceipt)
+ .build()
+```
+
+Which generates this:
+
+```kotlin
+@HeaderList(
+ [
+ Header(name = "Accept", value = "application/json; charset=utf-8"),
+ Header(name = "User-Agent", value = "Square Cash")
+ ]
+)
+abstract fun recordEvent(logRecord: LogRecord): LogReceipt
+```
+
+KotlinPoet supports use-site targets for annotations:
+
+```kotlin
+val utils = FileSpec.builder("com.example", "Utils")
+ .addAnnotation(
+ AnnotationSpec.builder(JvmName::class)
+ .useSiteTarget(UseSiteTarget.FILE)
+ .build()
+ )
+ .addFunction(
+ FunSpec.builder("abs")
+ .receiver(Int::class)
+ .returns(Int::class)
+ .addStatement("return if (this < 0) -this else this")
+ .build()
+ )
+ .build()
+```
+
+Will output this:
+
+```kotlin
+@file:JvmName
+
+package com.example
+
+import kotlin.Int
+import kotlin.jvm.JvmName
+
+fun Int.abs(): Int = if (this < 0) -this else this
+```
diff --git a/docs/anonymous-inner-classes.md b/docs/anonymous-inner-classes.md
new file mode 100644
index 00000000..a2f35daa
--- /dev/null
+++ b/docs/anonymous-inner-classes.md
@@ -0,0 +1,44 @@
+Anonymous Inner Classes
+=======================
+
+In the enum code, we used `TypeSpec.anonymousClassBuilder()`. Anonymous inner classes can also be
+used in code blocks. They are values that can be referenced with `%L`:
+
+```kotlin
+val comparator = TypeSpec.anonymousClassBuilder()
+ .addSuperinterface(Comparator::class.parameterizedBy(String::class))
+ .addFunction(
+ FunSpec.builder("compare")
+ .addModifiers(KModifier.OVERRIDE)
+ .addParameter("a", String::class)
+ .addParameter("b", String::class)
+ .returns(Int::class)
+ .addStatement("return %N.length - %N.length", "a", "b")
+ .build()
+ )
+ .build()
+
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .addFunction(
+ FunSpec.builder("sortByLength")
+ .addParameter("strings", List::class.parameterizedBy(String::class))
+ .addStatement("%N.sortedWith(%L)", "strings", comparator)
+ .build()
+ )
+ .build()
+```
+
+This generates a method that contains a class that contains a method:
+
+```kotlin
+class HelloWorld {
+ fun sortByLength(strings: List<String>) {
+ strings.sortedWith(object : Comparator<String> {
+ override fun compare(a: String, b: String): Int = a.length - b.length
+ })
+ }
+}
+```
+
+One particularly tricky part of defining anonymous inner classes is the arguments to the superclass
+constructor. To pass them use `TypeSpec.Builder`'s `addSuperclassConstructorParameter()` method.
diff --git a/docs/callable-references.md b/docs/callable-references.md
new file mode 100644
index 00000000..a7bbdc83
--- /dev/null
+++ b/docs/callable-references.md
@@ -0,0 +1,45 @@
+Callable References
+===================
+
+[Callable references][callable-references] to constructors, functions, and properties may be emitted
+via:
+
+- `ClassName.constructorReference()` for constructors
+- `MemberName.reference()` for functions and properties
+
+For example,
+
+```kotlin
+val helloClass = ClassName("com.example.hello", "Hello")
+val worldFunction: MemberName = helloClass.member("world")
+val byeProperty: MemberName = helloClass.nestedClass("World").member("bye")
+
+val factoriesFun = FunSpec.builder("factories")
+ .addStatement("val hello = %L", helloClass.constructorReference())
+ .addStatement("val world = %L", worldFunction.reference())
+ .addStatement("val bye = %L", byeProperty.reference())
+ .build()
+
+FileSpec.builder("com.example", "HelloWorld")
+ .addFunction(factoriesFun)
+ .build()
+```
+
+would generate:
+
+```kotlin
+package com.example
+
+import com.example.hello.Hello
+
+fun factories() {
+ val hello = ::Hello
+ val world = Hello::world
+ val bye = Hello.World::bye
+}
+```
+
+Top-level classes and members with conflicting names may require aliased imports, as with
+[member names](m-for-members.md).
+
+ [callable-references]: https://kotlinlang.org/docs/reference/reflection.html#callable-references
diff --git a/docs/changelog.md b/docs/changelog.md
index 108d8e0b..8f971fe3 100644
--- a/docs/changelog.md
+++ b/docs/changelog.md
@@ -3,6 +3,71 @@ Change Log
## Unreleased
+## Version 1.16.0
+
+Thanks to [@drawers][drawers], [@rickclephas][rickclephas] for contributing to this release.
+
+_2024-01-18_
+
+ * New: Kotlin 1.9.22.
+ * New: KSP 1.9.22-1.0.16.
+ * New: Add `NameAllocator` API to control keyword pre-allocation (#1803).
+ * Fix: Fix issue with missing `suspend` modifier in `KSTypeReference.toTypeName` (#1793).
+ * Fix: Honour same-package import aliases (#1794).
+ * Fix: Always include parameter docs in the type header (#1800).
+
+## Version 1.15.3
+
+Thanks to [@gabrielittner][gabrielittner] for contributing to this release.
+
+_2023-12-04_
+
+ * Fix: Fix nullability of lambdas in `KSTypeReference.toTypeName` (#1756).
+
+## Version 1.15.2
+
+Thanks to [@evant][evant] for contributing to this release.
+
+_2023-11-30_
+
+ * New: Kotlin 1.9.21.
+ * New: KSP 1.9.21-1.0.15.
+ * New: KSP: more accurately represent function types (#1742).
+
+## Version 1.15.1
+
+_2023-11-19_
+
+ * Fix: Fix a regression introduced by #1637, where a superfluous newline is added to a type's KDoc
+ if it has a primary constructor with no docs (#1727).
+
+## Version 1.15.0
+
+_2023-11-18_
+
+Thanks to [@drawers][drawers], [@fejesjoco][fejesjoco], [@takahirom][takahirom],
+[@martinbonnin][martinbonnin], [@mcarleio][mcarleio] for contributing to this release.
+
+In this release the `:kotlinpoet` module has been converted to a Kotlin Multiplatform module
+(#1654), though for now it only supports the JVM target. **Important**: unless you're building
+with Gradle, you will now need to depend on the `kotlinpoet-jvm` artifact, instead of `kotlinpoet` -
+see [Downloads](index.md#download) for instructions.
+
+ * New: Kotlin 1.9.20.
+ * New: KSP 1.9.20-1.0.14.
+ * New: Extract `TypeSpecHolder` interface for constructs that can hold a TypeSpec and their builders (#1723).
+ * New: Expose relative path from `FileSpec` (#1720).
+ * New: Return the generated path from `FileSpec.writeTo()`. (#1514).
+ * New: Remove default compatibility from unstable types (#1662).
+ * New: Deprecate `TypeSpec.expectClassBuilder()` and `TypeSpec.valueClassBuilder()` (#1589).
+ * New: Add option to convert `KSAnnotation` to `AnnotationSpec` while omitting default values (#1538).
+ * New: Add `FileSpec.builder` convenience for `MemberName` (#1585).
+ * Fix: Set `DecimalFormatSymbols.minusSign` for consistency across locales (#1658).
+ * Fix: Fix link to incremental KSP in KDoc (#1638).
+ * Fix: Emit primary constructor KDoc (#1637).
+ * Change: kotlinx-metadata 0.7.0. This is a breaking change for users of the `:kotlinpoet-metadata`
+ module, as most `Flags`-API extensions have been removed in favor of the now-available first-party versions.
+
## Version 1.14.2
_2023-05-30_
@@ -716,3 +781,7 @@ _2017-05-16_
[Squiry]: https://github.com/Squiry
[Omico]: https://github.com/Omico
[RBusarow]: https://github.com/RBusarow
+ [fejesjoco]: https://github.com/fejesjoco
+ [takahirom]: https://github.com/takahirom
+ [mcarleio]: https://github.com/mcarleio
+ [gabrielittner]: https://github.com/gabrielittner
diff --git a/docs/code-block-format-strings.md b/docs/code-block-format-strings.md
new file mode 100644
index 00000000..86547b11
--- /dev/null
+++ b/docs/code-block-format-strings.md
@@ -0,0 +1,36 @@
+Code Block Format Strings
+=========================
+
+Code blocks may specify the values for their placeholders in a few ways. Only one style may be used
+for each operation on a code block.
+
+## Relative Arguments
+
+Pass an argument value for each placeholder in the format string to `CodeBlock.add()`. In each
+example, we generate code to say "I ate 3 tacos"
+
+```kotlin
+CodeBlock.builder().add("I ate %L %L", 3, "tacos")
+```
+
+## Positional Arguments
+
+Place an integer index (1-based) before the placeholder in the format string to specify which
+argument to use.
+
+```kotlin
+CodeBlock.builder().add("I ate %2L %1L", "tacos", 3)
+```
+
+## Named Arguments
+
+Use the syntax `%argumentName:X` where `X` is the format character and call `CodeBlock.addNamed()`
+with a map containing all argument keys in the format string. Argument names use characters in
+`a-z`, `A-Z`, `0-9`, and `_`, and must start with a lowercase character.
+
+```kotlin
+val map = LinkedHashMap<String, Any>()
+map += "food" to "tacos"
+map += "count" to 3
+CodeBlock.builder().addNamed("I ate %count:L %food:L", map)
+```
diff --git a/docs/code-control-flow.md b/docs/code-control-flow.md
new file mode 100644
index 00000000..f2a12f6f
--- /dev/null
+++ b/docs/code-control-flow.md
@@ -0,0 +1,76 @@
+Code & Control Flow
+===================
+
+Most of KotlinPoet's API uses immutable Kotlin objects. There's also builders, method chaining
+and varargs to make the API friendly. KotlinPoet offers models for Kotlin files (`FileSpec`),
+classes, interfaces & objects (`TypeSpec`), type aliases (`TypeAliasSpec`),
+properties (`PropertySpec`), functions & constructors (`FunSpec`), parameters (`ParameterSpec`) and
+annotations (`AnnotationSpec`).
+
+But the _body_ of methods and constructors is not modeled. There's no expression class, no
+statement class or syntax tree nodes. Instead, KotlinPoet uses strings for code blocks, and you can
+take advantage of Kotlin's multiline strings to make this look nice:
+
+```kotlin
+val main = FunSpec.builder("main")
+ .addCode("""
+ |var total = 0
+ |for (i in 0..<10) {
+ | total += i
+ |}
+ |""".trimMargin())
+ .build()
+```
+
+Which generates this:
+
+```kotlin
+fun main() {
+ var total = 0
+ for (i in 0..<10) {
+ total += i
+ }
+}
+```
+
+There are additional APIs to assist with newlines, braces and indentation:
+
+```kotlin
+val main = FunSpec.builder("main")
+ .addStatement("var total = 0")
+ .beginControlFlow("for (i in 0..<10)")
+ .addStatement("total += i")
+ .endControlFlow()
+ .build()
+```
+
+This example is lame because the generated code is constant! Suppose instead of just adding 0 to 10,
+we want to make the operation and range configurable. Here's a method that generates a method:
+
+```kotlin
+private fun computeRange(name: String, from: Int, to: Int, op: String): FunSpec {
+ return FunSpec.builder(name)
+ .returns(Int::class)
+ .addStatement("var result = 1")
+ .beginControlFlow("for (i in $from..<$to)")
+ .addStatement("result = result $op i")
+ .endControlFlow()
+ .addStatement("return result")
+ .build()
+}
+```
+
+And here's what we get when we call `computeRange("multiply10to20", 10, 20, "*")`:
+
+```kotlin
+fun multiply10to20(): kotlin.Int {
+ var result = 1
+ for (i in 10..<20) {
+ result = result * i
+ }
+ return result
+}
+```
+
+Methods generating methods! And since KotlinPoet generates source instead of bytecode, you can
+read through it to make sure it's right.
diff --git a/docs/constructors.md b/docs/constructors.md
new file mode 100644
index 00000000..65eef43b
--- /dev/null
+++ b/docs/constructors.md
@@ -0,0 +1,80 @@
+Constructors
+============
+
+`FunSpec` is a slight misnomer; it can also be used for constructors:
+
+```kotlin
+val flux = FunSpec.constructorBuilder()
+ .addParameter("greeting", String::class)
+ .addStatement("this.%N = %N", "greeting", "greeting")
+ .build()
+
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .addProperty("greeting", String::class, KModifier.PRIVATE)
+ .addFunction(flux)
+ .build()
+```
+
+Which generates this:
+
+```kotlin
+class HelloWorld {
+ private val greeting: String
+
+ constructor(greeting: String) {
+ this.greeting = greeting
+ }
+}
+```
+
+For the most part, constructors work just like methods. When emitting code, KotlinPoet will place
+constructors before methods in the output file.
+
+Often times you'll need to generate the primary constructor for a class:
+
+```kotlin
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .primaryConstructor(flux)
+ .addProperty("greeting", String::class, KModifier.PRIVATE)
+ .build()
+```
+
+This code, however, generates the following:
+
+```kotlin
+class HelloWorld(greeting: String) {
+ private val greeting: String
+
+ init {
+ this.greeting = greeting
+ }
+}
+```
+
+By default, KotlinPoet won't merge primary constructor parameters and properties, even if they share
+the same name. To achieve the effect, you have to tell KotlinPoet that the property is initialized
+via the constructor parameter:
+
+```kotlin
+val flux = FunSpec.constructorBuilder()
+ .addParameter("greeting", String::class)
+ .build()
+
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .primaryConstructor(flux)
+ .addProperty(
+ PropertySpec.builder("greeting", String::class)
+ .initializer("greeting")
+ .addModifiers(KModifier.PRIVATE)
+ .build()
+ )
+ .build()
+```
+
+Now we're getting the following output:
+
+```kotlin
+class HelloWorld(private val greeting: String)
+```
+
+Notice that KotlinPoet omits `{}` for classes with empty bodies.
diff --git a/docs/enums.md b/docs/enums.md
new file mode 100644
index 00000000..229f98ce
--- /dev/null
+++ b/docs/enums.md
@@ -0,0 +1,78 @@
+Enums
+=====
+
+Use `enumBuilder` to create the enum type, and `addEnumConstant()` for each value:
+
+```kotlin
+val helloWorld = TypeSpec.enumBuilder("Roshambo")
+ .addEnumConstant("ROCK")
+ .addEnumConstant("SCISSORS")
+ .addEnumConstant("PAPER")
+ .build()
+```
+
+To generate this:
+
+```kotlin
+enum class Roshambo {
+ ROCK,
+
+ SCISSORS,
+
+ PAPER
+}
+```
+
+Fancy enums are supported, where the enum values override methods or call a superclass constructor.
+Here's a comprehensive example:
+
+```kotlin
+val helloWorld = TypeSpec.enumBuilder("Roshambo")
+ .primaryConstructor(
+ FunSpec.constructorBuilder()
+ .addParameter("handsign", String::class)
+ .build()
+ )
+ .addEnumConstant(
+ "ROCK", TypeSpec.anonymousClassBuilder()
+ .addSuperclassConstructorParameter("%S", "fist")
+ .addFunction(
+ FunSpec.builder("toString")
+ .addModifiers(KModifier.OVERRIDE)
+ .addStatement("return %S", "avalanche!")
+ .returns(String::class)
+ .build()
+ )
+ .build()
+ )
+ .addEnumConstant(
+ "SCISSORS", TypeSpec.anonymousClassBuilder()
+ .addSuperclassConstructorParameter("%S", "peace")
+ .build()
+ )
+ .addEnumConstant(
+ "PAPER", TypeSpec.anonymousClassBuilder()
+ .addSuperclassConstructorParameter("%S", "flat")
+ .build()
+ )
+ .addProperty(
+ PropertySpec.builder("handsign", String::class, KModifier.PRIVATE)
+ .initializer("handsign")
+ .build()
+ )
+ .build()
+```
+
+Which generates this:
+
+```kotlin
+enum class Roshambo(private val handsign: String) {
+ ROCK("fist") {
+ override fun toString(): String = "avalanche!"
+ },
+
+ SCISSORS("peace"),
+
+ PAPER("flat");
+}
+```
diff --git a/docs/functions.md b/docs/functions.md
new file mode 100644
index 00000000..f24d19d6
--- /dev/null
+++ b/docs/functions.md
@@ -0,0 +1,160 @@
+Functions
+=========
+
+All of the above functions have a code body. Use `KModifier.ABSTRACT` to get a function without any
+body. This is only legal if it is enclosed by an abstract class or an interface.
+
+```kotlin
+val flux = FunSpec.builder("flux")
+ .addModifiers(KModifier.ABSTRACT, KModifier.PROTECTED)
+ .build()
+
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .addModifiers(KModifier.ABSTRACT)
+ .addFunction(flux)
+ .build()
+```
+
+Which generates this:
+
+```kotlin
+abstract class HelloWorld {
+ protected abstract fun flux()
+}
+```
+
+The other modifiers work where permitted.
+
+Methods also have parameters, varargs, KDoc, annotations, type variables, return type and receiver
+type for extension functions. All of these are configured with `FunSpec.Builder`.
+
+## Extension functions
+
+Extension functions can be generated by specifying a `receiver`.
+
+```kotlin
+val square = FunSpec.builder("square")
+ .receiver(Int::class)
+ .returns(Int::class)
+ .addStatement("var s = this * this")
+ .addStatement("return s")
+ .build()
+```
+
+Which outputs:
+
+```kotlin
+fun Int.square(): Int {
+ val s = this * this
+ return s
+}
+```
+
+## Single-expression functions
+
+KotlinPoet can recognize single-expression functions and print them out properly. It treats
+each function with a body that starts with `return` as a single-expression function:
+
+```kotlin
+val abs = FunSpec.builder("abs")
+ .addParameter("x", Int::class)
+ .returns(Int::class)
+ .addStatement("return if (x < 0) -x else x")
+ .build()
+```
+
+Which outputs:
+
+```kotlin
+fun abs(x: Int): Int = if (x < 0) -x else x
+```
+
+## Default function arguments
+
+Consider the example below.
+Function argument `b` has a default value of 0 to avoid overloading this function.
+
+```kotlin
+fun add(a: Int, b: Int = 0) {
+ print("a + b = ${a + b}")
+}
+```
+
+Use the `defaultValue()` builder function to declare default value for a function argument.
+
+```kotlin
+FunSpec.builder("add")
+ .addParameter("a", Int::class)
+ .addParameter(
+ ParameterSpec.builder("b", Int::class)
+ .defaultValue("%L", 0)
+ .build()
+ )
+ .addStatement("print(\"a + b = ${a + b}\")")
+ .build()
+```
+
+## Spaces wrap by default!
+
+In order to provide meaningful formatting, KotlinPoet would replace spaces, found in blocks of code,
+with new line symbols, in cases when the line of code exceeds the length limit. Let's take this
+function for example:
+
+```kotlin
+val funSpec = FunSpec.builder("foo")
+ .addStatement("return (100..10000).map { number -> number * number }.map { number -> number.toString() }.also { string -> println(string) }")
+ .build()
+```
+
+Depending on where it's found in the file, it may end up being printed out like this:
+
+```kotlin
+fun foo() = (100..10000).map { number -> number * number }.map { number -> number.toString() }.also
+{ string -> println(string) }
+```
+
+Unfortunately this code is broken: the compiler expects `also` and `{` to be on the same line.
+KotlinPoet is unable to understand the context of the expression and fix the formatting for you, but
+there's a trick you can use to declare a non-breaking space - use the `·` symbol where you would
+otherwise use a space. Let's apply this to our example:
+
+```kotlin
+val funSpec = FunSpec.builder("foo")
+ .addStatement("return (100..10000).map·{ number -> number * number }.map·{ number -> number.toString() }.also·{ string -> println(string) }")
+ .build()
+```
+
+This will now produce the following result:
+
+```kotlin
+fun foo() = (100..10000).map { number -> number * number }.map { number ->
+ number.toString()
+}.also { string -> println(string) }
+```
+
+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.md)):
+
+```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.
diff --git a/docs/index.md b/docs/index.md
index 683f40e6..27db6f37 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -7,7 +7,7 @@ Source file generation can be useful when doing things such as annotation proces
with metadata files (e.g., database schemas, protocol formats). By generating code, you eliminate
the need to write boilerplate while also keeping a single source of truth for the metadata.
-### Example
+## Example
Here's a `HelloWorld` file:
@@ -62,1470 +62,8 @@ The [KDoc][kdoc] catalogs the complete KotlinPoet API, which is inspired by [Jav
**Note:** In order to maximize portability, KotlinPoet generates code with explicit visibility
modifiers. This ensures compatibility with both standard Kotlin projects as well as projects
-using [explicit API mode](https://kotlinlang.org/docs/whatsnew14.html#explicit-api-mode-for-library-authors).
-Examples in this file omit those modifiers for brevity.
-
-### Code & Control Flow
-
-Most of KotlinPoet's API uses immutable Kotlin objects. There's also builders, method chaining
-and varargs to make the API friendly. KotlinPoet offers models for Kotlin files (`FileSpec`),
-classes, interfaces & objects (`TypeSpec`), type aliases (`TypeAliasSpec`),
-properties (`PropertySpec`), functions & constructors (`FunSpec`), parameters (`ParameterSpec`) and
-annotations (`AnnotationSpec`).
-
-But the _body_ of methods and constructors is not modeled. There's no expression class, no
-statement class or syntax tree nodes. Instead, KotlinPoet uses strings for code blocks, and you can
-take advantage of Kotlin's multiline strings to make this look nice:
-
-```kotlin
-val main = FunSpec.builder("main")
- .addCode("""
- |var total = 0
- |for (i in 0..<10) {
- | total += i
- |}
- |""".trimMargin())
- .build()
-```
-
-Which generates this:
-
-```kotlin
-fun main() {
- var total = 0
- for (i in 0..<10) {
- total += i
- }
-}
-```
-
-There are additional APIs to assist with newlines, braces and indentation:
-
-```kotlin
-val main = FunSpec.builder("main")
- .addStatement("var total = 0")
- .beginControlFlow("for (i in 0..<10)")
- .addStatement("total += i")
- .endControlFlow()
- .build()
-```
-
-This example is lame because the generated code is constant! Suppose instead of just adding 0 to 10,
-we want to make the operation and range configurable. Here's a method that generates a method:
-
-```kotlin
-private fun computeRange(name: String, from: Int, to: Int, op: String): FunSpec {
- return FunSpec.builder(name)
- .returns(Int::class)
- .addStatement("var result = 1")
- .beginControlFlow("for (i in $from..<$to)")
- .addStatement("result = result $op i")
- .endControlFlow()
- .addStatement("return result")
- .build()
-}
-```
-
-And here's what we get when we call `computeRange("multiply10to20", 10, 20, "*")`:
-
-```kotlin
-fun multiply10to20(): kotlin.Int {
- var result = 1
- for (i in 10..<20) {
- result = result * i
- }
- return result
-}
-```
-
-Methods generating methods! And since KotlinPoet generates source instead of bytecode, you can
-read through it to make sure it's right.
-
-### %S for Strings
-
-When emitting code that includes string literals, we can use **`%S`** to emit a **string**, complete
-with wrapping quotation marks and escaping. Here's a program that emits 3 methods, each of which
-returns its own name:
-
-```kotlin
-fun main(args: Array<String>) {
- val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .addFunction(whatsMyNameYo("slimShady"))
- .addFunction(whatsMyNameYo("eminem"))
- .addFunction(whatsMyNameYo("marshallMathers"))
- .build()
-
- val kotlinFile = FileSpec.builder("com.example.helloworld", "HelloWorld")
- .addType(helloWorld)
- .build()
-
- kotlinFile.writeTo(System.out)
-}
-
-private fun whatsMyNameYo(name: String): FunSpec {
- return FunSpec.builder(name)
- .returns(String::class)
- .addStatement("return %S", name)
- .build()
-}
-```
-
-In this case, using `%S` gives us quotation marks:
-
-```kotlin
-class HelloWorld {
- fun slimShady(): String = "slimShady"
-
- fun eminem(): String = "eminem"
-
- fun marshallMathers(): String = "marshallMathers"
-}
-```
-
-### %P for String Templates
-
-`%S` also handles the escaping of dollar signs (`$`), to avoid inadvertent creation of string
-templates, which may fail to compile in generated code:
-
-```kotlin
-val stringWithADollar = "Your total is " + "$" + "50"
-val funSpec = FunSpec.builder("printTotal")
- .returns(String::class)
- .addStatement("return %S", stringWithADollar)
- .build()
-```
-
-produces:
-
-```kotlin
-fun printTotal(): String = "Your total is ${'$'}50"
-```
-
-If you need to generate string templates, use `%P`, which doesn't escape dollars:
-
-```kotlin
-val amount = 50
-val stringWithADollar = "Your total is " + "$" + "amount"
-val funSpec = FunSpec.builder("printTotal")
- .returns(String::class)
- .addStatement("return %P", stringWithADollar)
- .build()
-```
-
-produces:
-
-```kotlin
-fun printTotal(): String = "Your total is $amount"
-```
-
-You can also use `CodeBlock`s as arguments to `%P`, which is handy when you need to reference
-importable types or members inside the string template:
-
-```kotlin
-val file = FileSpec.builder("com.example", "Digits")
- .addFunction(
- FunSpec.builder("print")
- .addParameter("digits", IntArray::class)
- .addStatement("println(%P)", buildCodeBlock {
- val contentToString = MemberName("kotlin.collections", "contentToString")
- add("These are the digits: \${digits.%M()}", contentToString)
- })
- .build()
- )
- .build()
-println(file)
-```
-
-The snippet above will produce the following output, handling the imports properly:
-
-```kotlin
-package com.example
-
-import kotlin.IntArray
-import kotlin.collections.contentToString
-
-fun print(digits: IntArray) {
- println("""These are the digits: ${digits.contentToString()}""")
-}
-```
-
-### %T for Types
-
-KotlinPoet has rich built-in support for types, including automatic generation of `import`
-statements. Just use **`%T`** to reference **types**:
-
-```kotlin
-val today = FunSpec.builder("today")
- .returns(Date::class)
- .addStatement("return %T()", Date::class)
- .build()
-
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .addFunction(today)
- .build()
-
-val kotlinFile = FileSpec.builder("com.example.helloworld", "HelloWorld")
- .addType(helloWorld)
- .build()
-
-kotlinFile.writeTo(System.out)
-```
-
-That generates the following `.kt` file, complete with the necessary `import`:
-
-```kotlin
-package com.example.helloworld
-
-import java.util.Date
-
-class HelloWorld {
- fun today(): Date = Date()
-}
-```
-
-We passed `Date::class` to reference a class that just-so-happens to be available when we're
-generating code. This doesn't need to be the case. Here's a similar example, but this one
-references a class that doesn't exist (yet):
-
-```kotlin
-val hoverboard = ClassName("com.mattel", "Hoverboard")
-
-val tomorrow = FunSpec.builder("tomorrow")
- .returns(hoverboard)
- .addStatement("return %T()", hoverboard)
- .build()
-```
-
-And that not-yet-existent class is imported as well:
-
-```kotlin
-package com.example.helloworld
-
-import com.mattel.Hoverboard
-
-class HelloWorld {
- fun tomorrow(): Hoverboard = Hoverboard()
-}
-```
-
-The `ClassName` type is very important, and you'll need it frequently when you're using KotlinPoet.
-It can identify any _declared_ class. Declared types are just the beginning of Kotlin's rich type
-system: we also have arrays, parameterized types, wildcard types, lambda types and type variables.
-KotlinPoet has classes for building each of these:
-
-```kotlin
-import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
-import com.squareup.kotlinpoet.STAR
-
-val hoverboard = ClassName("com.mattel", "Hoverboard")
-val list = ClassName("kotlin.collections", "List")
-val arrayList = ClassName("kotlin.collections", "ArrayList")
-val listOfHoverboards = list.parameterizedBy(hoverboard)
-val arrayListOfHoverboards = arrayList.parameterizedBy(hoverboard)
-
-val thing = ClassName("com.misc", "Thing")
-val array = ClassName("kotlin", "Array")
-val producerArrayOfThings = array.parameterizedBy(WildcardTypeName.producerOf(thing))
-
-val beyond = FunSpec.builder("beyond")
- .returns(listOfHoverboards)
- .addStatement("val result = %T()", arrayListOfHoverboards)
- .addStatement("result += %T()", hoverboard)
- .addStatement("result += %T()", hoverboard)
- .addStatement("result += %T()", hoverboard)
- .addStatement("return result")
- .build()
-
-val printThings = FunSpec.builder("printThings")
- .addParameter("things", producerArrayOfThings)
- .addStatement("println(things)")
- .build()
-
-val printKClass = FunSpec.builder("printKClass")
- .addParameter("kClass", KClass::class.asClassName().parameterizedBy(STAR))
- .addStatement("println(kClass)")
- .build()
-```
-
-The `STAR` is represented as `*` in KotlinPoet. You can find more in the [KDoc][kdoc].
-
-KotlinPoet will decompose each type and import its components where possible.
-
-```kotlin
-package com.example.helloworld
-
-import com.mattel.Hoverboard
-import com.misc.Thing
-import kotlin.Array
-import kotlin.collections.ArrayList
-import kotlin.collections.List
-import kotlin.reflect.KClass
-
-class HelloWorld {
- fun beyond(): List<Hoverboard> {
- val result = ArrayList<Hoverboard>()
- result += Hoverboard()
- result += Hoverboard()
- result += Hoverboard()
- return result
- }
-
- fun printThings(things: Array<out Thing>) {
- println(things)
- }
-
- fun printKClass(kClass: KClass<*>) {
- println(kClass)
- }
-}
-```
-
-#### Nullable Types
-
-KotlinPoet supports nullable types. To convert a `TypeName` into its nullable counterpart, use the
-`copy()` method with `nullable` parameter set to `true`:
-
-```kotlin
-val java = PropertySpec.builder("java", String::class.asTypeName().copy(nullable = true))
- .mutable()
- .addModifiers(KModifier.PRIVATE)
- .initializer("null")
- .build()
-
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .addProperty(java)
- .addProperty("kotlin", String::class, KModifier.PRIVATE)
- .build()
-```
-
-generates:
-
-```kotlin
-class HelloWorld {
- private var java: String? = null
-
- private val kotlin: String
-}
-```
-
-### %M for Members
-
-Similar to types, KotlinPoet has a special placeholder for **members** (functions and properties),
-which comes handy when your code needs to access top-level members and members declared inside
-objects. Use **`%M`** to reference members, pass an instance of `MemberName` as the argument for the
-placeholder, and KotlinPoet will handle imports automatically:
-
-```kotlin
-val createTaco = MemberName("com.squareup.tacos", "createTaco")
-val isVegan = MemberName("com.squareup.tacos", "isVegan")
-val file = FileSpec.builder("com.squareup.example", "TacoTest")
- .addFunction(
- FunSpec.builder("main")
- .addStatement("val taco = %M()", createTaco)
- .addStatement("println(taco.%M)", isVegan)
- .build()
- )
- .build()
-println(file)
-```
-
-The code above generates the following file:
-
-```kotlin
-package com.squareup.example
-
-import com.squareup.tacos.createTaco
-import com.squareup.tacos.isVegan
-
-fun main() {
- val taco = createTaco()
- println(taco.isVegan)
-}
-```
-
-As you can see, it's also possible to use `%M` to reference extension functions and properties. You
-just need to make sure the member can be imported without simple name collisions, otherwise
-importing will fail and the code generator output will not pass compilation. There's a way to work
-around such cases though - use `FileSpec.addAliasedImport()` to create an alias for a clashing
-`MemberName`:
-
-```kotlin
-val createTaco = MemberName("com.squareup.tacos", "createTaco")
-val createCake = MemberName("com.squareup.cakes", "createCake")
-val isTacoVegan = MemberName("com.squareup.tacos", "isVegan")
-val isCakeVegan = MemberName("com.squareup.cakes", "isVegan")
-val file = FileSpec.builder("com.squareup.example", "Test")
- .addAliasedImport(isTacoVegan, "isTacoVegan")
- .addAliasedImport(isCakeVegan, "isCakeVegan")
- .addFunction(
- FunSpec.builder("main")
- .addStatement("val taco = %M()", createTaco)
- .addStatement("val cake = %M()", createCake)
- .addStatement("println(taco.%M)", isTacoVegan)
- .addStatement("println(cake.%M)", isCakeVegan)
- .build()
- )
- .build()
-println(file)
-```
-
-KotlinPoet will produce an aliased import for `com.squareup.tacos2.isVegan`:
-
-```kotlin
-package com.squareup.example
-
-import com.squareup.cakes.createCake
-import com.squareup.tacos.createTaco
-import com.squareup.cakes.isVegan as isCakeVegan
-import com.squareup.tacos.isVegan as isTacoVegan
-
-fun main() {
- val taco = createTaco()
- val cake = createCake()
- println(taco.isTacoVegan)
- println(cake.isCakeVegan)
-}
-```
-
-#### MemberName and operators
-
-MemberName also supports operators, you can use `MemberName(String, KOperator)`
-or `MemberName(ClassName, KOperator)` to import and reference operators.
-
-```kotlin
-val taco = ClassName("com.squareup.tacos", "Taco")
-val meat = ClassName("com.squareup.tacos.ingredient", "Meat")
-val iterator = MemberName("com.squareup.tacos.internal", KOperator.ITERATOR)
-val minusAssign = MemberName("com.squareup.tacos.internal", KOperator.MINUS_ASSIGN)
-val file = FileSpec.builder("com.example", "Test")
- .addFunction(
- FunSpec.builder("makeTacoHealthy")
- .addParameter("taco", taco)
- .beginControlFlow("for (ingredient %M taco)", iterator)
- .addStatement("if (ingredient is %T) taco %M ingredient", meat, minusAssign)
- .endControlFlow()
- .addStatement("return taco")
- .build()
- )
- .build()
-println(file)
-```
-
-KotlinPoet will import the extension operator functions and emit the operator.
-
-```kotlin
-package com.example
-
-import com.squareup.tacos.Taco
-import com.squareup.tacos.ingredient.Meat
-import com.squareup.tacos.internal.iterator
-import com.squareup.tacos.internal.minusAssign
-
-fun makeTacoHealthy(taco: Taco) {
- for (ingredient in taco) {
- if (ingredient is Meat) taco -= ingredient
- }
- return taco
-}
-
-```
-
-### %N for Names
-
-Generated code is often self-referential. Use **`%N`** to refer to another generated declaration by
-its name. Here's a method that calls another:
-
-```kotlin
-fun byteToHex(b: Int): String {
- val result = CharArray(2)
- result[0] = hexDigit((b ushr 4) and 0xf)
- result[1] = hexDigit(b and 0xf)
- return String(result)
-}
-
-fun hexDigit(i: Int): Char {
- return (if (i < 10) i + '0'.toInt() else i - 10 + 'a'.toInt()).toChar()
-}
-```
-
-When generating the code above, we pass the `hexDigit()` method as an argument to the `byteToHex()`
-method using `%N`:
-
-```kotlin
-val hexDigit = FunSpec.builder("hexDigit")
- .addParameter("i", Int::class)
- .returns(Char::class)
- .addStatement("return (if (i < 10) i + '0'.toInt() else i - 10 + 'a'.toInt()).toChar()")
- .build()
-
-val byteToHex = FunSpec.builder("byteToHex")
- .addParameter("b", Int::class)
- .returns(String::class)
- .addStatement("val result = CharArray(2)")
- .addStatement("result[0] = %N((b ushr 4) and 0xf)", hexDigit)
- .addStatement("result[1] = %N(b and 0xf)", hexDigit)
- .addStatement("return String(result)")
- .build()
-```
-
-Another handy feature that `%N` provides is automatically escaping names that contain illegal
-identifier characters with double ticks. Suppose your code creates a `MemberName` with a Kotlin
-keyword as the simple name:
-
-```kotlin
-val taco = ClassName("com.squareup.tacos", "Taco")
-val packager = ClassName("com.squareup.tacos", "TacoPackager")
-val file = FileSpec.builder("com.example", "Test")
- .addFunction(
- FunSpec.builder("packageTacos")
- .addParameter("tacos", LIST.parameterizedBy(taco))
- .addParameter("packager", packager)
- .addStatement("packager.%N(tacos)", packager.member("package"))
- .build()
- )
- .build()
-```
-
-`%N` will escape the name for you, ensuring that the output will pass compilation:
-
-```kotlin
-package com.example
-
-import com.squareup.tacos.Taco
-import com.squareup.tacos.TacoPackager
-import kotlin.collections.List
-
-fun packageTacos(tacos: List<Taco>, packager: TacoPackager) {
- packager.`package`(tacos)
-}
-```
-
-### %L for Literals
-
-Although Kotlin's string templates usually work well in cases when you want to include literals into
-generated code, KotlinPoet offers additional syntax inspired-by but incompatible-with
-[`String.format()`][formatter]. It accepts **`%L`** to emit a **literal** value in the output. This
-works just like `Formatter`'s `%s`:
-
-```kotlin
-private fun computeRange(name: String, from: Int, to: Int, op: String): FunSpec {
- return FunSpec.builder(name)
- .returns(Int::class)
- .addStatement("var result = 0")
- .beginControlFlow("for (i in %L..<%L)", from, to)
- .addStatement("result = result %L i", op)
- .endControlFlow()
- .addStatement("return result")
- .build()
-}
-```
-
-Literals are emitted directly to the output code with no escaping. Arguments for literals may be
-strings, primitives, and a few KotlinPoet types described below.
-
-### Code block format strings
-
-Code blocks may specify the values for their placeholders in a few ways. Only one style may be used
-for each operation on a code block.
-
-#### Relative Arguments
-
-Pass an argument value for each placeholder in the format string to `CodeBlock.add()`. In each
-example, we generate code to say "I ate 3 tacos"
-
-```kotlin
-CodeBlock.builder().add("I ate %L %L", 3, "tacos")
-```
-
-#### Positional Arguments
-
-Place an integer index (1-based) before the placeholder in the format string to specify which
-argument to use.
-
-```kotlin
-CodeBlock.builder().add("I ate %2L %1L", "tacos", 3)
-```
-
-#### Named Arguments
-
-Use the syntax `%argumentName:X` where `X` is the format character and call `CodeBlock.addNamed()`
-with a map containing all argument keys in the format string. Argument names use characters in
-`a-z`, `A-Z`, `0-9`, and `_`, and must start with a lowercase character.
-
-```kotlin
-val map = LinkedHashMap<String, Any>()
-map += "food" to "tacos"
-map += "count" to 3
-CodeBlock.builder().addNamed("I ate %count:L %food:L", map)
-```
-
-### Functions
-
-All of the above functions have a code body. Use `KModifier.ABSTRACT` to get a function without any
-body. This is only legal if it is enclosed by an abstract class or an interface.
-
-```kotlin
-val flux = FunSpec.builder("flux")
- .addModifiers(KModifier.ABSTRACT, KModifier.PROTECTED)
- .build()
-
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .addModifiers(KModifier.ABSTRACT)
- .addFunction(flux)
- .build()
-```
-
-Which generates this:
-
-```kotlin
-abstract class HelloWorld {
- protected abstract fun flux()
-}
-```
-
-The other modifiers work where permitted.
-
-Methods also have parameters, varargs, KDoc, annotations, type variables, return type and receiver
-type for extension functions. All of these are configured with `FunSpec.Builder`.
-
-#### Extension functions
-
-Extension functions can be generated by specifying a `receiver`.
-
-```kotlin
-val square = FunSpec.builder("square")
- .receiver(Int::class)
- .returns(Int::class)
- .addStatement("var s = this * this")
- .addStatement("return s")
- .build()
-```
-
-Which outputs:
-
-```kotlin
-fun Int.square(): Int {
- val s = this * this
- return s
-}
-```
-
-#### Single-expression functions
-
-KotlinPoet can recognize single-expression functions and print them out properly. It treats
-each function with a body that starts with `return` as a single-expression function:
-
-```kotlin
-val abs = FunSpec.builder("abs")
- .addParameter("x", Int::class)
- .returns(Int::class)
- .addStatement("return if (x < 0) -x else x")
- .build()
-```
-
-Which outputs:
-
-```kotlin
-fun abs(x: Int): Int = if (x < 0) -x else x
-```
-
-#### Default function arguments
-
-Consider the example below.
-Function argument `b` has a default value of 0 to avoid overloading this function.
-
-```kotlin
-fun add(a: Int, b: Int = 0) {
- print("a + b = ${a + b}")
-}
-```
-
-Use the `defaultValue()` builder function to declare default value for a function argument.
-
-```kotlin
-FunSpec.builder("add")
- .addParameter("a", Int::class)
- .addParameter(
- ParameterSpec.builder("b", Int::class)
- .defaultValue("%L", 0)
- .build()
- )
- .addStatement("print(\"a + b = ${a + b}\")")
- .build()
-```
-
-#### Spaces wrap by default!
-
-In order to provide meaningful formatting, KotlinPoet would replace spaces, found in blocks of code,
-with new line symbols, in cases when the line of code exceeds the length limit. Let's take this
-function for example:
-
-```kotlin
-val funSpec = FunSpec.builder("foo")
- .addStatement("return (100..10000).map { number -> number * number }.map { number -> number.toString() }.also { string -> println(string) }")
- .build()
-```
-
-Depending on where it's found in the file, it may end up being printed out like this:
-
-```kotlin
-fun foo() = (100..10000).map { number -> number * number }.map { number -> number.toString() }.also
-{ string -> println(string) }
-```
-
-Unfortunately this code is broken: the compiler expects `also` and `{` to be on the same line.
-KotlinPoet is unable to understand the context of the expression and fix the formatting for you, but
-there's a trick you can use to declare a non-breaking space - use the `·` symbol where you would
-otherwise use a space. Let's apply this to our example:
-
-```kotlin
-val funSpec = FunSpec.builder("foo")
- .addStatement("return (100..10000).map·{ number -> number * number }.map·{ number -> number.toString() }.also·{ string -> println(string) }")
- .build()
-```
-
-This will now produce the following result:
-
-```kotlin
-fun foo() = (100..10000).map { number -> number * number }.map { number ->
- number.toString()
-}.also { string -> println(string) }
-```
-
-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:
-
-```kotlin
-val flux = FunSpec.constructorBuilder()
- .addParameter("greeting", String::class)
- .addStatement("this.%N = %N", "greeting", "greeting")
- .build()
-
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .addProperty("greeting", String::class, KModifier.PRIVATE)
- .addFunction(flux)
- .build()
-```
-
-Which generates this:
-
-```kotlin
-class HelloWorld {
- private val greeting: String
-
- constructor(greeting: String) {
- this.greeting = greeting
- }
-}
-```
-
-For the most part, constructors work just like methods. When emitting code, KotlinPoet will place
-constructors before methods in the output file.
-
-Often times you'll need to generate the primary constructor for a class:
-
-```kotlin
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .primaryConstructor(flux)
- .addProperty("greeting", String::class, KModifier.PRIVATE)
- .build()
-```
-
-This code, however, generates the following:
-
-```kotlin
-class HelloWorld(greeting: String) {
- private val greeting: String
-
- init {
- this.greeting = greeting
- }
-}
-```
-
-By default, KotlinPoet won't merge primary constructor parameters and properties, even if they share
-the same name. To achieve the effect, you have to tell KotlinPoet that the property is initialized
-via the constructor parameter:
-
-```kotlin
-val flux = FunSpec.constructorBuilder()
- .addParameter("greeting", String::class)
- .build()
-
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .primaryConstructor(flux)
- .addProperty(
- PropertySpec.builder("greeting", String::class)
- .initializer("greeting")
- .addModifiers(KModifier.PRIVATE)
- .build()
- )
- .build()
-```
-
-Now we're getting the following output:
-
-```kotlin
-class HelloWorld(private val greeting: String)
-```
-
-Notice that KotlinPoet omits `{}` for classes with empty bodies.
-
-### Parameters
-
-Declare parameters on methods and constructors with either `ParameterSpec.builder()` or
-`FunSpec`'s convenient `addParameter()` API:
-
-```kotlin
-val android = ParameterSpec.builder("android", String::class)
- .defaultValue("\"pie\"")
- .build()
-
-val welcomeOverlords = FunSpec.builder("welcomeOverlords")
- .addParameter(android)
- .addParameter("robot", String::class)
- .build()
-```
-
-The code above generates:
-
-```kotlin
-fun welcomeOverlords(android: String = "pie", robot: String) {
-}
-```
-
-The extended `Builder` form is necessary when the parameter has annotations (such as `@Inject`).
-
-### Properties
-
-Like parameters, properties can be created either with builders or by using convenient helper
-methods:
-
-```kotlin
-val android = PropertySpec.builder("android", String::class)
- .addModifiers(KModifier.PRIVATE)
- .build()
-
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .addProperty(android)
- .addProperty("robot", String::class, KModifier.PRIVATE)
- .build()
-```
-
-Which generates:
-
-```kotlin
-class HelloWorld {
- private val android: String
-
- private val robot: String
-}
-```
-
-The extended `Builder` form is necessary when a field has KDoc, annotations, or a field
-initializer. Field initializers use the same [`String.format()`][formatter]-like syntax as the code
-blocks above:
-
-```kotlin
-val android = PropertySpec.builder("android", String::class)
- .addModifiers(KModifier.PRIVATE)
- .initializer("%S + %L", "Oreo v.", 8.1)
- .build()
-```
-
-Which generates:
-
-```kotlin
-private val android: String = "Oreo v." + 8.1
-```
-
-By default `PropertySpec.Builder` produces `val` properties. Use `mutable()` if you need a
-`var`:
-
-```kotlin
-val android = PropertySpec.builder("android", String::class)
- .mutable()
- .addModifiers(KModifier.PRIVATE)
- .initializer("%S + %L", "Oreo v.", 8.1)
- .build()
-```
-
-#### Inline properties
-
-The way KotlinPoet models inline properties deserves special mention. The following snippet of code:
-
-```kotlin
-val android = PropertySpec.builder("android", String::class)
- .mutable()
- .addModifiers(KModifier.INLINE)
- .build()
-```
-
-will produce an error:
-
-```
-java.lang.IllegalArgumentException: KotlinPoet doesn't allow setting the inline modifier on
-properties. You should mark either the getter, the setter, or both inline.
-```
-
-Indeed, a property marked with `inline` should have at least one accessor which will be inlined by
-the compiler. Let's add a getter to this property:
-
-```kotlin
-val android = PropertySpec.builder("android", String::class)
- .mutable()
- .getter(
- FunSpec.getterBuilder()
- .addModifiers(KModifier.INLINE)
- .addStatement("return %S", "foo")
- .build()
- )
- .build()
-```
-
-The result is the following:
-
-```kotlin
-var android: kotlin.String
- inline get() = "foo"
-```
-
-Now, what if we wanted to add a non-inline setter to the property above? We can do so without
-modifying any of the code we wrote previously:
-
-```kotlin
-val android = PropertySpec.builder("android", String::class)
- .mutable()
- .getter(
- FunSpec.getterBuilder()
- .addModifiers(KModifier.INLINE)
- .addStatement("return %S", "foo")
- .build()
- )
- .setter(
- FunSpec.setterBuilder()
- .addParameter("value", String::class)
- .build()
- )
- .build()
-```
-
-We get the expected result:
-
-```kotlin
-var android: kotlin.String
- inline get() = "foo"
- set(`value`) {
- }
-```
-
-Finally, if we go back and add `KModifier.INLINE` to the setter, KotlinPoet can wrap it nicely and
-produce the following result:
-
-```kotlin
-inline var android: kotlin.String
- get() = "foo"
- set(`value`) {
- }
-```
-
-Removing the modifier from either the getter or the setter will unwrap the expression back.
-
-If, on the other hand, KotlinPoet had allowed marking a property `inline` directly, the programmer
-would have had to manually add/remove the modifier whenever the state of the accessors changes in
-order to get correct and compilable output. We're solving this problem by making accessors the
-source of truth for the `inline` modifier.
-
-### Interfaces
-
-KotlinPoet has no trouble with interfaces. Note that interface methods must always be `ABSTRACT`.
-The modifier is necessary when defining the interface:
-
-```kotlin
-val helloWorld = TypeSpec.interfaceBuilder("HelloWorld")
- .addProperty("buzz", String::class)
- .addFunction(
- FunSpec.builder("beep")
- .addModifiers(KModifier.ABSTRACT)
- .build()
- )
- .build()
-```
-
-But these modifiers are omitted when the code is generated. These are the default so we don't need
-to include them for `kotlinc`'s benefit!
-
-```kotlin
-interface HelloWorld {
- val buzz: String
-
- fun beep()
-}
-```
-
-Kotlin 1.4 adds support for functional interfaces via `fun interface` syntax. To create this in
-KotlinPoet, use `TypeSpec.funInterfaceBuilder()`.
-
-```kotlin
-val helloWorld = TypeSpec.funInterfaceBuilder("HelloWorld")
- .addFunction(
- FunSpec.builder("beep")
- .addModifiers(KModifier.ABSTRACT)
- .build()
- )
- .build()
-
-// Generates...
-fun interface HelloWorld {
- fun beep()
-}
-```
-
-### Objects
-
-KotlinPoet supports objects:
-
-```kotlin
-val helloWorld = TypeSpec.objectBuilder("HelloWorld")
- .addProperty(
- PropertySpec.builder("buzz", String::class)
- .initializer("%S", "buzz")
- .build()
- )
- .addFunction(
- FunSpec.builder("beep")
- .addStatement("println(%S)", "Beep!")
- .build()
- )
- .build()
-```
-
-Similarly, you can create companion objects and add them to classes using `addType()`:
-
-```kotlin
-val companion = TypeSpec.companionObjectBuilder()
- .addProperty(
- PropertySpec.builder("buzz", String::class)
- .initializer("%S", "buzz")
- .build()
- )
- .addFunction(
- FunSpec.builder("beep")
- .addStatement("println(%S)", "Beep!")
- .build()
- )
- .build()
-
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .addType(companion)
- .build()
-```
-
-You can provide an optional name for a companion object.
-
-### Enums
-
-Use `enumBuilder` to create the enum type, and `addEnumConstant()` for each value:
-
-```kotlin
-val helloWorld = TypeSpec.enumBuilder("Roshambo")
- .addEnumConstant("ROCK")
- .addEnumConstant("SCISSORS")
- .addEnumConstant("PAPER")
- .build()
-```
-
-To generate this:
-
-```kotlin
-enum class Roshambo {
- ROCK,
-
- SCISSORS,
-
- PAPER
-}
-```
-
-Fancy enums are supported, where the enum values override methods or call a superclass constructor.
-Here's a comprehensive example:
-
-```kotlin
-val helloWorld = TypeSpec.enumBuilder("Roshambo")
- .primaryConstructor(
- FunSpec.constructorBuilder()
- .addParameter("handsign", String::class)
- .build()
- )
- .addEnumConstant(
- "ROCK", TypeSpec.anonymousClassBuilder()
- .addSuperclassConstructorParameter("%S", "fist")
- .addFunction(
- FunSpec.builder("toString")
- .addModifiers(KModifier.OVERRIDE)
- .addStatement("return %S", "avalanche!")
- .returns(String::class)
- .build()
- )
- .build()
- )
- .addEnumConstant(
- "SCISSORS", TypeSpec.anonymousClassBuilder()
- .addSuperclassConstructorParameter("%S", "peace")
- .build()
- )
- .addEnumConstant(
- "PAPER", TypeSpec.anonymousClassBuilder()
- .addSuperclassConstructorParameter("%S", "flat")
- .build()
- )
- .addProperty(
- PropertySpec.builder("handsign", String::class, KModifier.PRIVATE)
- .initializer("handsign")
- .build()
- )
- .build()
-```
-
-Which generates this:
-
-```kotlin
-enum class Roshambo(private val handsign: String) {
- ROCK("fist") {
- override fun toString(): String = "avalanche!"
- },
-
- SCISSORS("peace"),
-
- PAPER("flat");
-}
-```
-
-### Anonymous Inner Classes
-
-In the enum code, we used `TypeSpec.anonymousClassBuilder()`. Anonymous inner classes can also be
-used in code blocks. They are values that can be referenced with `%L`:
-
-```kotlin
-val comparator = TypeSpec.anonymousClassBuilder()
- .addSuperinterface(Comparator::class.parameterizedBy(String::class))
- .addFunction(
- FunSpec.builder("compare")
- .addModifiers(KModifier.OVERRIDE)
- .addParameter("a", String::class)
- .addParameter("b", String::class)
- .returns(Int::class)
- .addStatement("return %N.length - %N.length", "a", "b")
- .build()
- )
- .build()
-
-val helloWorld = TypeSpec.classBuilder("HelloWorld")
- .addFunction(
- FunSpec.builder("sortByLength")
- .addParameter("strings", List::class.parameterizedBy(String::class))
- .addStatement("%N.sortedWith(%L)", "strings", comparator)
- .build()
- )
- .build()
-```
-
-This generates a method that contains a class that contains a method:
-
-```kotlin
-class HelloWorld {
- fun sortByLength(strings: List<String>) {
- strings.sortedWith(object : Comparator<String> {
- override fun compare(a: String, b: String): Int = a.length - b.length
- })
- }
-}
-```
-
-One particularly tricky part of defining anonymous inner classes is the arguments to the superclass
-constructor. To pass them use `TypeSpec.Builder`'s `addSuperclassConstructorParameter()` method.
-
-### Annotations
-
-Simple annotations are easy:
-
-```kotlin
-val test = FunSpec.builder("test string equality")
- .addAnnotation(Test::class)
- .addStatement("assertThat(%1S).isEqualTo(%1S)", "foo")
- .build()
-```
-
-Which generates this function with an `@Test` annotation:
-
-```kotlin
-@Test
-fun `test string equality`() {
- assertThat("foo").isEqualTo("foo")
-}
-```
-
-Use `AnnotationSpec.builder()` to set properties on annotations:
-
-```kotlin
-val logRecord = FunSpec.builder("recordEvent")
- .addModifiers(KModifier.ABSTRACT)
- .addAnnotation(
- AnnotationSpec.builder(Headers::class)
- .addMember("accept = %S", "application/json; charset=utf-8")
- .addMember("userAgent = %S", "Square Cash")
- .build()
- )
- .addParameter("logRecord", LogRecord::class)
- .returns(LogReceipt::class)
- .build()
-```
-
-Which generates this annotation with `accept` and `userAgent` properties:
-
-```kotlin
-@Headers(
- accept = "application/json; charset=utf-8",
- userAgent = "Square Cash"
-)
-abstract fun recordEvent(logRecord: LogRecord): LogReceipt
-```
-
-When you get fancy, annotation values can be annotations themselves. Use `%L` for embedded
-annotations:
-
-```kotlin
-val headerList = ClassName("", "HeaderList")
-val header = ClassName("", "Header")
-val logRecord = FunSpec.builder("recordEvent")
- .addModifiers(KModifier.ABSTRACT)
- .addAnnotation(
- AnnotationSpec.builder(headerList)
- .addMember(
- "[\n⇥%L,\n%L⇤\n]",
- AnnotationSpec.builder(header)
- .addMember("name = %S", "Accept")
- .addMember("value = %S", "application/json; charset=utf-8")
- .build(),
- AnnotationSpec.builder(header)
- .addMember("name = %S", "User-Agent")
- .addMember("value = %S", "Square Cash")
- .build()
- )
- .build()
- )
- .addParameter("logRecord", logRecordName)
- .returns(logReceipt)
- .build()
-```
-
-Which generates this:
-
-```kotlin
-@HeaderList(
- [
- Header(name = "Accept", value = "application/json; charset=utf-8"),
- Header(name = "User-Agent", value = "Square Cash")
- ]
-)
-abstract fun recordEvent(logRecord: LogRecord): LogReceipt
-```
-
-KotlinPoet supports use-site targets for annotations:
-
-```kotlin
-val utils = FileSpec.builder("com.example", "Utils")
- .addAnnotation(
- AnnotationSpec.builder(JvmName::class)
- .useSiteTarget(UseSiteTarget.FILE)
- .build()
- )
- .addFunction(
- FunSpec.builder("abs")
- .receiver(Int::class)
- .returns(Int::class)
- .addStatement("return if (this < 0) -this else this")
- .build()
- )
- .build()
-```
-
-Will output this:
-
-```kotlin
-@file:JvmName
-
-package com.example
-
-import kotlin.Int
-import kotlin.jvm.JvmName
-
-fun Int.abs(): Int = if (this < 0) -this else this
-```
-
-### Type Aliases
-
-KotlinPoet provides API for creating Type Aliases, which supports simple class names, parameterized
-types and lambdas:
-
-```kotlin
-val k = TypeVariableName("K")
-val t = TypeVariableName("T")
-
-val fileTable = Map::class.asClassName()
- .parameterizedBy(k, Set::class.parameterizedBy(File::class))
-
-val predicate = LambdaTypeName.get(
- parameters = arrayOf(t),
- returnType = Boolean::class.asClassName()
-)
-val helloWorld = FileSpec.builder("com.example", "HelloWorld")
- .addTypeAlias(TypeAliasSpec.builder("Word", String::class).build())
- .addTypeAlias(
- TypeAliasSpec.builder("FileTable", fileTable)
- .addTypeVariable(k)
- .build()
- )
- .addTypeAlias(
- TypeAliasSpec.builder("Predicate", predicate)
- .addTypeVariable(t)
- .build()
- )
- .build()
-```
-
-Which generates the following:
-
-```kotlin
-package com.example
-
-import java.io.File
-import kotlin.Boolean
-import kotlin.String
-import kotlin.collections.Map
-import kotlin.collections.Set
-
-typealias Word = String
-
-typealias FileTable<K> = Map<K, Set<File>>
-
-typealias Predicate<T> = (T) -> Boolean
-```
-
-### Callable References
-
-[Callable references](https://kotlinlang.org/docs/reference/reflection.html#callable-references) to
-constructors, functions, and properties may be emitted via:
-
-- `ClassName.constructorReference()` for constructors
-- `MemberName.reference()` for functions and properties
-
-For example,
-
-```kotlin
-val helloClass = ClassName("com.example.hello", "Hello")
-val worldFunction: MemberName = helloClass.member("world")
-val byeProperty: MemberName = helloClass.nestedClass("World").member("bye")
-
-val factoriesFun = FunSpec.builder("factories")
- .addStatement("val hello = %L", helloClass.constructorReference())
- .addStatement("val world = %L", worldFunction.reference())
- .addStatement("val bye = %L", byeProperty.reference())
- .build()
-
-FileSpec.builder("com.example", "HelloWorld")
- .addFunction(factoriesFun)
- .build()
-```
-
-would generate:
-
-```kotlin
-package com.example
-
-import com.example.hello.Hello
-
-fun factories() {
- val hello = ::Hello
- val world = Hello::world
- val bye = Hello.World::bye
-}
-```
-
-Top-level classes and members with conflicting names may require aliased imports, as with
-[member names](#m-for-members).
-
-kotlin-reflect
---------
-
-To generate source code from
-any [`KType`](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-type/), including
-information that's not accessible to the builtin reflection APIs, KotlinPoet depends
-on [kotlin-reflect](https://kotlinlang.org/docs/reflection.html#jvm-dependency). `kotlin-reflect`
-can read the metadata of your classes and access this extra information. KotlinPoet can for an
-example, read the type parameters and
-their [variance](https://kotlinlang.org/docs/generics.html#variance) from a generic `KType` and
-generate appropriate source code.
-
-`kotlin-reflect` is a relatively big dependency though and in some cases it is desirable to remove
-it from the final executable to save some space and/or simplify the proguard/R8 setup (for example
-for a Gradle plugin that generates Kotlin code). It is possible to do so and still use most of the
-KotlinPoet APIs:
-
-```kotlin
-dependencies {
- implementation("com.squareup:kotlinpoet:<version>") {
- exclude(module = "kotlin-reflect")
- }
-}
-```
-
-The main APIs that require `kotlin-reflect`
-are [`KType.asTypeName()`](https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet/com.squareup.kotlinpoet/as-type-name.html)
-and [`typeNameOf<T>()`](https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet/com.squareup.kotlinpoet/type-name-of.html).
-If you're calling one of these without `kotlin-reflect` in the classpath and the type is generic
-or has annotations you will get a crash.
-
-You can replace it with code that passes type parameters or annotations explicitly and doesn't
-need `kotlin-reflect`. For example:
-
-```kotlin
-// Replace
-// kotlin-reflect needed
-val typeName = typeNameOf<List<Int?>>()
-
-// With
-// kotlin-reflect not needed
-val typeName =
- List::class.asClassName().parameterizedBy(Int::class.asClassName().copy(nullable = true))
-```
+using [explicit API mode][explicit-api]. Examples in the documentation omit those modifiers for
+brevity.
Download
--------
@@ -1537,7 +75,7 @@ Download [the latest .jar][dl] or depend via Maven:
```xml
<dependency>
<groupId>com.squareup</groupId>
- <artifactId>kotlinpoet</artifactId>
+ <artifactId>kotlinpoet-jvm</artifactId>
<version>[version]</version>
</dependency>
```
@@ -1550,7 +88,6 @@ implementation("com.squareup:kotlinpoet:[version]")
Snapshots of the development version are available in [Sonatype's `snapshots` repository][snap].
-
License
-------
@@ -1568,10 +105,9 @@ License
See the License for the specific language governing permissions and
limitations under the License.
-
- [dl]: https://search.maven.org/remote_content?g=com.squareup&a=kotlinpoet&v=LATEST
- [version-shield]: https://img.shields.io/maven-central/v/com.squareup/kotlinpoet
- [snap]: https://s01.oss.sonatype.org/content/repositories/snapshots/com/squareup/kotlinpoet/
[kdoc]: https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet/com.squareup.kotlinpoet/
[javapoet]: https://github.com/square/javapoet/
- [formatter]: https://developer.android.com/reference/java/util/Formatter.html
+ [explicit-api]: https://kotlinlang.org/docs/whatsnew14.html#explicit-api-mode-for-library-authors
+ [version-shield]: https://img.shields.io/maven-central/v/com.squareup/kotlinpoet
+ [dl]: https://search.maven.org/remote_content?g=com.squareup&a=kotlinpoet-jvm&v=LATEST
+ [snap]: https://s01.oss.sonatype.org/content/repositories/snapshots/com/squareup/kotlinpoet/
diff --git a/docs/interfaces.md b/docs/interfaces.md
new file mode 100644
index 00000000..52682b4e
--- /dev/null
+++ b/docs/interfaces.md
@@ -0,0 +1,45 @@
+Interfaces
+==========
+
+KotlinPoet has no trouble with interfaces. Note that interface methods must always be `ABSTRACT`.
+The modifier is necessary when defining the interface:
+
+```kotlin
+val helloWorld = TypeSpec.interfaceBuilder("HelloWorld")
+ .addProperty("buzz", String::class)
+ .addFunction(
+ FunSpec.builder("beep")
+ .addModifiers(KModifier.ABSTRACT)
+ .build()
+ )
+ .build()
+```
+
+But these modifiers are omitted when the code is generated. These are the default so we don't need
+to include them for `kotlinc`'s benefit!
+
+```kotlin
+interface HelloWorld {
+ val buzz: String
+
+ fun beep()
+}
+```
+
+Kotlin 1.4 adds support for functional interfaces via `fun interface` syntax. To create this in
+KotlinPoet, use `TypeSpec.funInterfaceBuilder()`.
+
+```kotlin
+val helloWorld = TypeSpec.funInterfaceBuilder("HelloWorld")
+ .addFunction(
+ FunSpec.builder("beep")
+ .addModifiers(KModifier.ABSTRACT)
+ .build()
+ )
+ .build()
+
+// Generates...
+fun interface HelloWorld {
+ fun beep()
+}
+```
diff --git a/docs/kotlin-reflect.md b/docs/kotlin-reflect.md
new file mode 100644
index 00000000..0bda13ad
--- /dev/null
+++ b/docs/kotlin-reflect.md
@@ -0,0 +1,45 @@
+kotlin-reflect
+==============
+
+To generate source code from any [`KType`][k-type], including information that's not accessible to
+the builtin reflection APIs, KotlinPoet depends on [kotlin-reflect][kotlin-reflect]. `kotlin-reflect`
+can read the metadata of your classes and access this extra information. KotlinPoet can for an
+example, read the type parameters and their [variance][variance] from a generic `KType` and
+generate appropriate source code.
+
+`kotlin-reflect` is a relatively big dependency though and in some cases it is desirable to remove
+it from the final executable to save some space and/or simplify the proguard/R8 setup (for example
+for a Gradle plugin that generates Kotlin code). It is possible to do so and still use most of the
+KotlinPoet APIs:
+
+```kotlin
+dependencies {
+ implementation("com.squareup:kotlinpoet:<version>") {
+ exclude(module = "kotlin-reflect")
+ }
+}
+```
+
+The main APIs that require `kotlin-reflect` are [`KType.asTypeName()`][as-type-name] and
+[`typeNameOf<T>()`][type-name-of]. If you're calling one of these without `kotlin-reflect` in the
+classpath and the type is generic or has annotations you will get a crash.
+
+You can replace it with code that passes type parameters or annotations explicitly and doesn't
+need `kotlin-reflect`. For example:
+
+```kotlin
+// Replace
+// kotlin-reflect needed
+val typeName = typeNameOf<List<Int?>>()
+
+// With
+// kotlin-reflect not needed
+val typeName =
+ List::class.asClassName().parameterizedBy(Int::class.asClassName().copy(nullable = true))
+```
+
+ [k-type]: https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect/-k-type/
+ [kotlin-reflect]: https://kotlinlang.org/docs/reflection.html#jvm-dependency
+ [variance]: https://kotlinlang.org/docs/generics.html#variance
+ [as-type-name]: https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet/com.squareup.kotlinpoet/as-type-name.html
+ [type-name-of]: https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet/com.squareup.kotlinpoet/type-name-of.html
diff --git a/docs/l-for-literals.md b/docs/l-for-literals.md
new file mode 100644
index 00000000..82a0d0a1
--- /dev/null
+++ b/docs/l-for-literals.md
@@ -0,0 +1,25 @@
+%L for Literals
+===============
+
+Although Kotlin's string templates usually work well in cases when you want to include literals into
+generated code, KotlinPoet offers additional syntax inspired-by but incompatible-with
+[`String.format()`][formatter]. It accepts **`%L`** to emit a **literal** value in the output. This
+works just like `Formatter`'s `%s`:
+
+```kotlin
+private fun computeRange(name: String, from: Int, to: Int, op: String): FunSpec {
+ return FunSpec.builder(name)
+ .returns(Int::class)
+ .addStatement("var result = 0")
+ .beginControlFlow("for (i in %L..<%L)", from, to)
+ .addStatement("result = result %L i", op)
+ .endControlFlow()
+ .addStatement("return result")
+ .build()
+}
+```
+
+Literals are emitted directly to the output code with no escaping. Arguments for literals may be
+strings, primitives, and a few KotlinPoet types described below.
+
+ [formatter]: https://developer.android.com/reference/java/util/Formatter.html
diff --git a/docs/m-for-members.md b/docs/m-for-members.md
new file mode 100644
index 00000000..0a683c78
--- /dev/null
+++ b/docs/m-for-members.md
@@ -0,0 +1,122 @@
+%M for Members
+==============
+
+Similar to types, KotlinPoet has a special placeholder for **members** (functions and properties),
+which comes handy when your code needs to access top-level members and members declared inside
+objects. Use **`%M`** to reference members, pass an instance of `MemberName` as the argument for the
+placeholder, and KotlinPoet will handle imports automatically:
+
+```kotlin
+val createTaco = MemberName("com.squareup.tacos", "createTaco")
+val isVegan = MemberName("com.squareup.tacos", "isVegan")
+val file = FileSpec.builder("com.squareup.example", "TacoTest")
+ .addFunction(
+ FunSpec.builder("main")
+ .addStatement("val taco = %M()", createTaco)
+ .addStatement("println(taco.%M)", isVegan)
+ .build()
+ )
+ .build()
+println(file)
+```
+
+The code above generates the following file:
+
+```kotlin
+package com.squareup.example
+
+import com.squareup.tacos.createTaco
+import com.squareup.tacos.isVegan
+
+fun main() {
+ val taco = createTaco()
+ println(taco.isVegan)
+}
+```
+
+As you can see, it's also possible to use `%M` to reference extension functions and properties. You
+just need to make sure the member can be imported without simple name collisions, otherwise
+importing will fail and the code generator output will not pass compilation. There's a way to work
+around such cases though - use `FileSpec.addAliasedImport()` to create an alias for a clashing
+`MemberName`:
+
+```kotlin
+val createTaco = MemberName("com.squareup.tacos", "createTaco")
+val createCake = MemberName("com.squareup.cakes", "createCake")
+val isTacoVegan = MemberName("com.squareup.tacos", "isVegan")
+val isCakeVegan = MemberName("com.squareup.cakes", "isVegan")
+val file = FileSpec.builder("com.squareup.example", "Test")
+ .addAliasedImport(isTacoVegan, "isTacoVegan")
+ .addAliasedImport(isCakeVegan, "isCakeVegan")
+ .addFunction(
+ FunSpec.builder("main")
+ .addStatement("val taco = %M()", createTaco)
+ .addStatement("val cake = %M()", createCake)
+ .addStatement("println(taco.%M)", isTacoVegan)
+ .addStatement("println(cake.%M)", isCakeVegan)
+ .build()
+ )
+ .build()
+println(file)
+```
+
+KotlinPoet will produce an aliased import for `com.squareup.tacos2.isVegan`:
+
+```kotlin
+package com.squareup.example
+
+import com.squareup.cakes.createCake
+import com.squareup.tacos.createTaco
+import com.squareup.cakes.isVegan as isCakeVegan
+import com.squareup.tacos.isVegan as isTacoVegan
+
+fun main() {
+ val taco = createTaco()
+ val cake = createCake()
+ println(taco.isTacoVegan)
+ println(cake.isCakeVegan)
+}
+```
+
+## MemberName and operators
+
+MemberName also supports operators, you can use `MemberName(String, KOperator)`
+or `MemberName(ClassName, KOperator)` to import and reference operators.
+
+```kotlin
+val taco = ClassName("com.squareup.tacos", "Taco")
+val meat = ClassName("com.squareup.tacos.ingredient", "Meat")
+val iterator = MemberName("com.squareup.tacos.internal", KOperator.ITERATOR)
+val minusAssign = MemberName("com.squareup.tacos.internal", KOperator.MINUS_ASSIGN)
+val file = FileSpec.builder("com.example", "Test")
+ .addFunction(
+ FunSpec.builder("makeTacoHealthy")
+ .addParameter("taco", taco)
+ .beginControlFlow("for (ingredient %M taco)", iterator)
+ .addStatement("if (ingredient is %T) taco %M ingredient", meat, minusAssign)
+ .endControlFlow()
+ .addStatement("return taco")
+ .build()
+ )
+ .build()
+println(file)
+```
+
+KotlinPoet will import the extension operator functions and emit the operator.
+
+```kotlin
+package com.example
+
+import com.squareup.tacos.Taco
+import com.squareup.tacos.ingredient.Meat
+import com.squareup.tacos.internal.iterator
+import com.squareup.tacos.internal.minusAssign
+
+fun makeTacoHealthy(taco: Taco) {
+ for (ingredient in taco) {
+ if (ingredient is Meat) taco -= ingredient
+ }
+ return taco
+}
+
+```
diff --git a/docs/n-for-names.md b/docs/n-for-names.md
new file mode 100644
index 00000000..cc3783af
--- /dev/null
+++ b/docs/n-for-names.md
@@ -0,0 +1,70 @@
+%N for Names
+============
+
+Generated code is often self-referential. Use **`%N`** to refer to another generated declaration by
+its name. Here's a method that calls another:
+
+```kotlin
+fun byteToHex(b: Int): String {
+ val result = CharArray(2)
+ result[0] = hexDigit((b ushr 4) and 0xf)
+ result[1] = hexDigit(b and 0xf)
+ return String(result)
+}
+
+fun hexDigit(i: Int): Char {
+ return (if (i < 10) i + '0'.toInt() else i - 10 + 'a'.toInt()).toChar()
+}
+```
+
+When generating the code above, we pass the `hexDigit()` method as an argument to the `byteToHex()`
+method using `%N`:
+
+```kotlin
+val hexDigit = FunSpec.builder("hexDigit")
+ .addParameter("i", Int::class)
+ .returns(Char::class)
+ .addStatement("return (if (i < 10) i + '0'.toInt() else i - 10 + 'a'.toInt()).toChar()")
+ .build()
+
+val byteToHex = FunSpec.builder("byteToHex")
+ .addParameter("b", Int::class)
+ .returns(String::class)
+ .addStatement("val result = CharArray(2)")
+ .addStatement("result[0] = %N((b ushr 4) and 0xf)", hexDigit)
+ .addStatement("result[1] = %N(b and 0xf)", hexDigit)
+ .addStatement("return String(result)")
+ .build()
+```
+
+Another handy feature that `%N` provides is automatically escaping names that contain illegal
+identifier characters with double ticks. Suppose your code creates a `MemberName` with a Kotlin
+keyword as the simple name:
+
+```kotlin
+val taco = ClassName("com.squareup.tacos", "Taco")
+val packager = ClassName("com.squareup.tacos", "TacoPackager")
+val file = FileSpec.builder("com.example", "Test")
+ .addFunction(
+ FunSpec.builder("packageTacos")
+ .addParameter("tacos", LIST.parameterizedBy(taco))
+ .addParameter("packager", packager)
+ .addStatement("packager.%N(tacos)", packager.member("package"))
+ .build()
+ )
+ .build()
+```
+
+`%N` will escape the name for you, ensuring that the output will pass compilation:
+
+```kotlin
+package com.example
+
+import com.squareup.tacos.Taco
+import com.squareup.tacos.TacoPackager
+import kotlin.collections.List
+
+fun packageTacos(tacos: List<Taco>, packager: TacoPackager) {
+ packager.`package`(tacos)
+}
+```
diff --git a/docs/objects.md b/docs/objects.md
new file mode 100644
index 00000000..75d9aab4
--- /dev/null
+++ b/docs/objects.md
@@ -0,0 +1,42 @@
+Objects
+=======
+
+KotlinPoet supports objects:
+
+```kotlin
+val helloWorld = TypeSpec.objectBuilder("HelloWorld")
+ .addProperty(
+ PropertySpec.builder("buzz", String::class)
+ .initializer("%S", "buzz")
+ .build()
+ )
+ .addFunction(
+ FunSpec.builder("beep")
+ .addStatement("println(%S)", "Beep!")
+ .build()
+ )
+ .build()
+```
+
+Similarly, you can create companion objects and add them to classes using `addType()`:
+
+```kotlin
+val companion = TypeSpec.companionObjectBuilder()
+ .addProperty(
+ PropertySpec.builder("buzz", String::class)
+ .initializer("%S", "buzz")
+ .build()
+ )
+ .addFunction(
+ FunSpec.builder("beep")
+ .addStatement("println(%S)", "Beep!")
+ .build()
+ )
+ .build()
+
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .addType(companion)
+ .build()
+```
+
+You can provide an optional name for a companion object.
diff --git a/docs/p-for-string-templates.md b/docs/p-for-string-templates.md
new file mode 100644
index 00000000..6b27e6af
--- /dev/null
+++ b/docs/p-for-string-templates.md
@@ -0,0 +1,67 @@
+%P for String Templates
+=======================
+
+`%S` also handles the escaping of dollar signs (`$`), to avoid inadvertent creation of string
+templates, which may fail to compile in generated code:
+
+```kotlin
+val stringWithADollar = "Your total is " + "$" + "50"
+val funSpec = FunSpec.builder("printTotal")
+ .returns(String::class)
+ .addStatement("return %S", stringWithADollar)
+ .build()
+```
+
+produces:
+
+```kotlin
+fun printTotal(): String = "Your total is ${'$'}50"
+```
+
+If you need to generate string templates, use `%P`, which doesn't escape dollars:
+
+```kotlin
+val amount = 50
+val stringWithADollar = "Your total is " + "$" + "amount"
+val funSpec = FunSpec.builder("printTotal")
+ .returns(String::class)
+ .addStatement("return %P", stringWithADollar)
+ .build()
+```
+
+produces:
+
+```kotlin
+fun printTotal(): String = "Your total is $amount"
+```
+
+You can also use `CodeBlock`s as arguments to `%P`, which is handy when you need to reference
+importable types or members inside the string template:
+
+```kotlin
+val file = FileSpec.builder("com.example", "Digits")
+ .addFunction(
+ FunSpec.builder("print")
+ .addParameter("digits", IntArray::class)
+ .addStatement("println(%P)", buildCodeBlock {
+ val contentToString = MemberName("kotlin.collections", "contentToString")
+ add("These are the digits: \${digits.%M()}", contentToString)
+ })
+ .build()
+ )
+ .build()
+println(file)
+```
+
+The snippet above will produce the following output, handling the imports properly:
+
+```kotlin
+package com.example
+
+import kotlin.IntArray
+import kotlin.collections.contentToString
+
+fun print(digits: IntArray) {
+ println("""These are the digits: ${digits.contentToString()}""")
+}
+```
diff --git a/docs/parameters.md b/docs/parameters.md
new file mode 100644
index 00000000..d8165082
--- /dev/null
+++ b/docs/parameters.md
@@ -0,0 +1,25 @@
+Parameters
+==========
+
+Declare parameters on methods and constructors with either `ParameterSpec.builder()` or
+`FunSpec`'s convenient `addParameter()` API:
+
+```kotlin
+val android = ParameterSpec.builder("android", String::class)
+ .defaultValue("\"pie\"")
+ .build()
+
+val welcomeOverlords = FunSpec.builder("welcomeOverlords")
+ .addParameter(android)
+ .addParameter("robot", String::class)
+ .build()
+```
+
+The code above generates:
+
+```kotlin
+fun welcomeOverlords(android: String = "pie", robot: String) {
+}
+```
+
+The extended `Builder` form is necessary when the parameter has annotations (such as `@Inject`).
diff --git a/docs/properties.md b/docs/properties.md
new file mode 100644
index 00000000..cb878ab2
--- /dev/null
+++ b/docs/properties.md
@@ -0,0 +1,142 @@
+Properties
+==========
+
+Like parameters, properties can be created either with builders or by using convenient helper
+methods:
+
+```kotlin
+val android = PropertySpec.builder("android", String::class)
+ .addModifiers(KModifier.PRIVATE)
+ .build()
+
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .addProperty(android)
+ .addProperty("robot", String::class, KModifier.PRIVATE)
+ .build()
+```
+
+Which generates:
+
+```kotlin
+class HelloWorld {
+ private val android: String
+
+ private val robot: String
+}
+```
+
+The extended `Builder` form is necessary when a field has KDoc, annotations, or a field
+initializer. Field initializers use the same [`String.format()`][formatter]-like syntax as the code
+blocks above:
+
+```kotlin
+val android = PropertySpec.builder("android", String::class)
+ .addModifiers(KModifier.PRIVATE)
+ .initializer("%S + %L", "Oreo v.", 8.1)
+ .build()
+```
+
+Which generates:
+
+```kotlin
+private val android: String = "Oreo v." + 8.1
+```
+
+By default `PropertySpec.Builder` produces `val` properties. Use `mutable()` if you need a
+`var`:
+
+```kotlin
+val android = PropertySpec.builder("android", String::class)
+ .mutable()
+ .addModifiers(KModifier.PRIVATE)
+ .initializer("%S + %L", "Oreo v.", 8.1)
+ .build()
+```
+
+## Inline properties
+
+The way KotlinPoet models inline properties deserves special mention. The following snippet of code:
+
+```kotlin
+val android = PropertySpec.builder("android", String::class)
+ .mutable()
+ .addModifiers(KModifier.INLINE)
+ .build()
+```
+
+will produce an error:
+
+```
+java.lang.IllegalArgumentException: KotlinPoet doesn't allow setting the inline modifier on
+properties. You should mark either the getter, the setter, or both inline.
+```
+
+Indeed, a property marked with `inline` should have at least one accessor which will be inlined by
+the compiler. Let's add a getter to this property:
+
+```kotlin
+val android = PropertySpec.builder("android", String::class)
+ .mutable()
+ .getter(
+ FunSpec.getterBuilder()
+ .addModifiers(KModifier.INLINE)
+ .addStatement("return %S", "foo")
+ .build()
+ )
+ .build()
+```
+
+The result is the following:
+
+```kotlin
+var android: kotlin.String
+ inline get() = "foo"
+```
+
+Now, what if we wanted to add a non-inline setter to the property above? We can do so without
+modifying any of the code we wrote previously:
+
+```kotlin
+val android = PropertySpec.builder("android", String::class)
+ .mutable()
+ .getter(
+ FunSpec.getterBuilder()
+ .addModifiers(KModifier.INLINE)
+ .addStatement("return %S", "foo")
+ .build()
+ )
+ .setter(
+ FunSpec.setterBuilder()
+ .addParameter("value", String::class)
+ .build()
+ )
+ .build()
+```
+
+We get the expected result:
+
+```kotlin
+var android: kotlin.String
+ inline get() = "foo"
+ set(`value`) {
+ }
+```
+
+Finally, if we go back and add `KModifier.INLINE` to the setter, KotlinPoet can wrap it nicely and
+produce the following result:
+
+```kotlin
+inline var android: kotlin.String
+ get() = "foo"
+ set(`value`) {
+ }
+```
+
+Removing the modifier from either the getter or the setter will unwrap the expression back.
+
+If, on the other hand, KotlinPoet had allowed marking a property `inline` directly, the programmer
+would have had to manually add/remove the modifier whenever the state of the accessors changes in
+order to get correct and compilable output. We're solving this problem by making accessors the
+source of truth for the `inline` modifier.
+
+ [formatter]: https://developer.android.com/reference/java/util/Formatter.html
diff --git a/docs/s-for-strings.md b/docs/s-for-strings.md
new file mode 100644
index 00000000..d14d7e7e
--- /dev/null
+++ b/docs/s-for-strings.md
@@ -0,0 +1,41 @@
+%S for Strings
+==============
+
+When emitting code that includes string literals, we can use **`%S`** to emit a **string**, complete
+with wrapping quotation marks and escaping. Here's a program that emits 3 methods, each of which
+returns its own name:
+
+```kotlin
+fun main(args: Array<String>) {
+ val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .addFunction(whatsMyNameYo("slimShady"))
+ .addFunction(whatsMyNameYo("eminem"))
+ .addFunction(whatsMyNameYo("marshallMathers"))
+ .build()
+
+ val kotlinFile = FileSpec.builder("com.example.helloworld", "HelloWorld")
+ .addType(helloWorld)
+ .build()
+
+ kotlinFile.writeTo(System.out)
+}
+
+private fun whatsMyNameYo(name: String): FunSpec {
+ return FunSpec.builder(name)
+ .returns(String::class)
+ .addStatement("return %S", name)
+ .build()
+}
+```
+
+In this case, using `%S` gives us quotation marks:
+
+```kotlin
+class HelloWorld {
+ fun slimShady(): String = "slimShady"
+
+ fun eminem(): String = "eminem"
+
+ fun marshallMathers(): String = "marshallMathers"
+}
+```
diff --git a/docs/t-for-types.md b/docs/t-for-types.md
new file mode 100644
index 00000000..d0bfa4ad
--- /dev/null
+++ b/docs/t-for-types.md
@@ -0,0 +1,161 @@
+%T for Types
+============
+
+KotlinPoet has rich built-in support for types, including automatic generation of `import`
+statements. Just use **`%T`** to reference **types**:
+
+```kotlin
+val today = FunSpec.builder("today")
+ .returns(Date::class)
+ .addStatement("return %T()", Date::class)
+ .build()
+
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .addFunction(today)
+ .build()
+
+val kotlinFile = FileSpec.builder("com.example.helloworld", "HelloWorld")
+ .addType(helloWorld)
+ .build()
+
+kotlinFile.writeTo(System.out)
+```
+
+That generates the following `.kt` file, complete with the necessary `import`:
+
+```kotlin
+package com.example.helloworld
+
+import java.util.Date
+
+class HelloWorld {
+ fun today(): Date = Date()
+}
+```
+
+We passed `Date::class` to reference a class that just-so-happens to be available when we're
+generating code. This doesn't need to be the case. Here's a similar example, but this one
+references a class that doesn't exist (yet):
+
+```kotlin
+val hoverboard = ClassName("com.mattel", "Hoverboard")
+
+val tomorrow = FunSpec.builder("tomorrow")
+ .returns(hoverboard)
+ .addStatement("return %T()", hoverboard)
+ .build()
+```
+
+And that not-yet-existent class is imported as well:
+
+```kotlin
+package com.example.helloworld
+
+import com.mattel.Hoverboard
+
+class HelloWorld {
+ fun tomorrow(): Hoverboard = Hoverboard()
+}
+```
+
+The `ClassName` type is very important, and you'll need it frequently when you're using KotlinPoet.
+It can identify any _declared_ class. Declared types are just the beginning of Kotlin's rich type
+system: we also have arrays, parameterized types, wildcard types, lambda types and type variables.
+KotlinPoet has classes for building each of these:
+
+```kotlin
+import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
+import com.squareup.kotlinpoet.STAR
+
+val hoverboard = ClassName("com.mattel", "Hoverboard")
+val list = ClassName("kotlin.collections", "List")
+val arrayList = ClassName("kotlin.collections", "ArrayList")
+val listOfHoverboards = list.parameterizedBy(hoverboard)
+val arrayListOfHoverboards = arrayList.parameterizedBy(hoverboard)
+
+val thing = ClassName("com.misc", "Thing")
+val array = ClassName("kotlin", "Array")
+val producerArrayOfThings = array.parameterizedBy(WildcardTypeName.producerOf(thing))
+
+val beyond = FunSpec.builder("beyond")
+ .returns(listOfHoverboards)
+ .addStatement("val result = %T()", arrayListOfHoverboards)
+ .addStatement("result += %T()", hoverboard)
+ .addStatement("result += %T()", hoverboard)
+ .addStatement("result += %T()", hoverboard)
+ .addStatement("return result")
+ .build()
+
+val printThings = FunSpec.builder("printThings")
+ .addParameter("things", producerArrayOfThings)
+ .addStatement("println(things)")
+ .build()
+
+val printKClass = FunSpec.builder("printKClass")
+ .addParameter("kClass", KClass::class.asClassName().parameterizedBy(STAR))
+ .addStatement("println(kClass)")
+ .build()
+```
+
+The `STAR` is represented as `*` in KotlinPoet. You can find more in the [KDoc][kdoc].
+
+KotlinPoet will decompose each type and import its components where possible.
+
+```kotlin
+package com.example.helloworld
+
+import com.mattel.Hoverboard
+import com.misc.Thing
+import kotlin.Array
+import kotlin.collections.ArrayList
+import kotlin.collections.List
+import kotlin.reflect.KClass
+
+class HelloWorld {
+ fun beyond(): List<Hoverboard> {
+ val result = ArrayList<Hoverboard>()
+ result += Hoverboard()
+ result += Hoverboard()
+ result += Hoverboard()
+ return result
+ }
+
+ fun printThings(things: Array<out Thing>) {
+ println(things)
+ }
+
+ fun printKClass(kClass: KClass<*>) {
+ println(kClass)
+ }
+}
+```
+
+## Nullable Types
+
+KotlinPoet supports nullable types. To convert a `TypeName` into its nullable counterpart, use the
+`copy()` method with `nullable` parameter set to `true`:
+
+```kotlin
+val java = PropertySpec.builder("java", String::class.asTypeName().copy(nullable = true))
+ .mutable()
+ .addModifiers(KModifier.PRIVATE)
+ .initializer("null")
+ .build()
+
+val helloWorld = TypeSpec.classBuilder("HelloWorld")
+ .addProperty(java)
+ .addProperty("kotlin", String::class, KModifier.PRIVATE)
+ .build()
+```
+
+generates:
+
+```kotlin
+class HelloWorld {
+ private var java: String? = null
+
+ private val kotlin: String
+}
+```
+
+ [kdoc]: https://square.github.io/kotlinpoet/1.x/kotlinpoet/kotlinpoet/com.squareup.kotlinpoet/
diff --git a/docs/type-aliases.md b/docs/type-aliases.md
new file mode 100644
index 00000000..c4aa2a7b
--- /dev/null
+++ b/docs/type-aliases.md
@@ -0,0 +1,49 @@
+Type Aliases
+============
+
+KotlinPoet provides API for creating Type Aliases, which supports simple class names, parameterized
+types and lambdas:
+
+```kotlin
+val k = TypeVariableName("K")
+val t = TypeVariableName("T")
+
+val fileTable = Map::class.asClassName()
+ .parameterizedBy(k, Set::class.parameterizedBy(File::class))
+
+val predicate = LambdaTypeName.get(
+ parameters = arrayOf(t),
+ returnType = Boolean::class.asClassName()
+)
+val helloWorld = FileSpec.builder("com.example", "HelloWorld")
+ .addTypeAlias(TypeAliasSpec.builder("Word", String::class).build())
+ .addTypeAlias(
+ TypeAliasSpec.builder("FileTable", fileTable)
+ .addTypeVariable(k)
+ .build()
+ )
+ .addTypeAlias(
+ TypeAliasSpec.builder("Predicate", predicate)
+ .addTypeVariable(t)
+ .build()
+ )
+ .build()
+```
+
+Which generates the following:
+
+```kotlin
+package com.example
+
+import java.io.File
+import kotlin.Boolean
+import kotlin.String
+import kotlin.collections.Map
+import kotlin.collections.Set
+
+typealias Word = String
+
+typealias FileTable<K> = Map<K, Set<File>>
+
+typealias Predicate<T> = (T) -> Boolean
+```
diff --git a/gradle.properties b/gradle.properties
index dc6f7256..5ee29f62 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,7 +1,7 @@
org.gradle.jvmargs='-Dfile.encoding=UTF-8'
GROUP=com.squareup
-VERSION_NAME=1.15.0-SNAPSHOT
+VERSION_NAME=1.16.0
POM_URL=https://github.com/square/kotlinpoet
POM_SCM_URL=https://github.com/square/kotlinpoet
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index 6bba5ebc..1f39d95b 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -13,22 +13,23 @@
# limitations under the License.
[versions]
-kotlin = "1.9.10"
-kct = "0.3.2"
-ksp = "1.9.10-1.0.13"
+kotlin = "1.9.22"
+kct = "0.4.0"
+ksp = "1.9.22-1.0.16"
ktlint = "0.48.2"
[plugins]
+kotlin-multiplatform = { id = "org.jetbrains.kotlin.multiplatform", version.ref = "kotlin" }
kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
-dokka = { id = "org.jetbrains.dokka", version = "1.9.0" }
+dokka = { id = "org.jetbrains.dokka", version = "1.9.10" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }
-spotless = { id = "com.diffplug.spotless", version = "6.22.0" }
-mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.25.3" }
+spotless = { id = "com.diffplug.spotless", version = "6.24.0" }
+mavenPublish = { id = "com.vanniktech.maven.publish", version = "0.27.0" }
kotlinBinaryCompatibilityValidator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version = "0.13.2" }
[libraries]
autoCommon = { module = "com.google.auto:auto-common", version = "1.2.2" }
-guava = { module = "com.google.guava:guava", version = "32.1.2-jre" }
+guava = { module = "com.google.guava:guava", version = "33.0.0-jre" }
javapoet = "com.squareup:javapoet:1.13.0"
autoService = "com.google.auto.service:auto-service-annotations:1.1.1"
@@ -38,12 +39,12 @@ kotlin-compilerEmbeddable = { module = "org.jetbrains.kotlin:kotlin-compiler-emb
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.7.0" }
+kotlin-metadata = { module = "org.jetbrains.kotlinx:kotlinx-metadata-jvm", version = "0.8.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.5" }
+truth = { module = "com.google.truth:truth", version = "1.2.0" }
compileTesting = { module = "com.google.testing.compile:compile-testing", version = "0.21.0" }
jimfs = { module = "com.google.jimfs:jimfs", version = "1.3.0" }
ecj = { module = "org.eclipse.jdt.core.compiler:ecj", version = "4.6.1" }
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 7f93135c..d64cd491 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 8838ba97..e6aba251 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-all.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
diff --git a/interop/javapoet/build.gradle.kts b/interop/javapoet/build.gradle.kts
index 734d934f..8fd35cbc 100644
--- a/interop/javapoet/build.gradle.kts
+++ b/interop/javapoet/build.gradle.kts
@@ -13,6 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+plugins {
+ kotlin("jvm")
+}
tasks.jar {
manifest {
diff --git a/interop/kotlinx-metadata/build.gradle.kts b/interop/kotlinx-metadata/build.gradle.kts
index a828789d..6ac626e0 100644
--- a/interop/kotlinx-metadata/build.gradle.kts
+++ b/interop/kotlinx-metadata/build.gradle.kts
@@ -13,6 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+plugins {
+ kotlin("jvm")
+}
tasks.jar {
manifest {
diff --git a/interop/ksp/build.gradle.kts b/interop/ksp/build.gradle.kts
index 3d615a39..782d151b 100644
--- a/interop/ksp/build.gradle.kts
+++ b/interop/ksp/build.gradle.kts
@@ -13,6 +13,9 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+plugins {
+ kotlin("jvm")
+}
tasks.jar {
manifest {
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 8d072201..3c57aad0 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,6 +15,7 @@
*/
package com.squareup.kotlinpoet.ksp
+import com.google.devtools.ksp.symbol.KSCallableReference
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSType
import com.google.devtools.ksp.symbol.KSTypeAlias
@@ -27,6 +28,8 @@ import com.google.devtools.ksp.symbol.Variance.COVARIANT
import com.google.devtools.ksp.symbol.Variance.INVARIANT
import com.squareup.kotlinpoet.ClassName
import com.squareup.kotlinpoet.KModifier
+import com.squareup.kotlinpoet.LambdaTypeName
+import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.STAR
import com.squareup.kotlinpoet.TypeName
import com.squareup.kotlinpoet.TypeVariableName
@@ -179,5 +182,15 @@ public fun KSTypeArgument.toTypeName(
public fun KSTypeReference.toTypeName(
typeParamResolver: TypeParameterResolver = TypeParameterResolver.EMPTY,
): TypeName {
- return resolve().toTypeName(typeParamResolver, element?.typeArguments.orEmpty())
+ val type = resolve()
+ return when (val elem = element) {
+ is KSCallableReference -> {
+ LambdaTypeName.get(
+ receiver = elem.receiverType?.toTypeName(typeParamResolver),
+ parameters = elem.functionParameters.map { ParameterSpec.unnamed(it.type.toTypeName(typeParamResolver)) },
+ returnType = elem.returnType.toTypeName(typeParamResolver),
+ ).copy(nullable = type.isMarkedNullable, suspending = type.isSuspendFunctionType)
+ }
+ else -> type.toTypeName(typeParamResolver, element?.typeArguments.orEmpty())
+ }
}
diff --git a/interop/ksp/test-processor/build.gradle.kts b/interop/ksp/test-processor/build.gradle.kts
index f0a4d71d..d2e3fb77 100644
--- a/interop/ksp/test-processor/build.gradle.kts
+++ b/interop/ksp/test-processor/build.gradle.kts
@@ -15,6 +15,7 @@
*/
plugins {
id("com.google.devtools.ksp")
+ kotlin("jvm")
}
tasks.compileTestKotlin {
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 82064c85..fb0a5f01 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
@@ -171,7 +171,14 @@ class TestProcessor(private val env: SymbolProcessorEnvironment) : SymbolProcess
)
.addParameters(
function.parameters.map { parameter ->
- val parameterType = parameter.type.toValidatedTypeName(functionTypeParams).let {
+ // Function references can't be obtained from a resolved KSType because it resolves to FunctionN<> which
+ // loses the necessary context, skip validation in these cases as we know they won't match.
+ val typeName = if (parameter.type.resolve().run { isFunctionType || isSuspendFunctionType }) {
+ parameter.type.toTypeName(functionTypeParams)
+ } else {
+ parameter.type.toValidatedTypeName(functionTypeParams)
+ }
+ val parameterType = typeName.let {
if (unwrapTypeAliases) {
it.unwrapTypeAlias()
} else {
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 1aaa1edb..06bf588d 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
@@ -129,7 +129,12 @@ class TestProcessorTest {
suspend fun functionD(
param1: () -> String,
param2: (String) -> String,
- param3: String.() -> String
+ param3: String.() -> String,
+ param4: Function0<String>,
+ param5: Function1<String, String>,
+ param6: (Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int, Int) -> Unit,
+ param7: ((String) -> String)?,
+ param8: suspend () -> String,
) {
}
@@ -188,6 +193,7 @@ class TestProcessorTest {
import kotlin.Int
import kotlin.IntArray
import kotlin.String
+ import kotlin.Unit
import kotlin.collections.List
import kotlin.collections.Map
import kotlin.collections.MutableList
@@ -261,9 +267,39 @@ class TestProcessorTest {
}
public suspend fun functionD(
- param1: Function0<String>,
- param2: Function1<String, String>,
- param3: Function1<String, String>,
+ param1: () -> String,
+ param2: (String) -> String,
+ param3: String.() -> String,
+ param4: Function0<String>,
+ param5: Function1<String, String>,
+ param6: (
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ Int,
+ ) -> Unit,
+ param7: ((String) -> String)?,
+ param8: suspend () -> String,
) {
}
diff --git a/kotlinpoet/api/kotlinpoet.api b/kotlinpoet/api/kotlinpoet.api
index 114bd190..4e92873d 100644
--- a/kotlinpoet/api/kotlinpoet.api
+++ b/kotlinpoet/api/kotlinpoet.api
@@ -181,7 +181,7 @@ public final class com/squareup/kotlinpoet/Dynamic : com/squareup/kotlinpoet/Typ
public abstract interface annotation class com/squareup/kotlinpoet/ExperimentalKotlinPoetApi : java/lang/annotation/Annotation {
}
-public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/Taggable {
+public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/Taggable, com/squareup/kotlinpoet/TypeSpecHolder {
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;
@@ -195,7 +195,9 @@ public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/An
public final fun getMembers ()Ljava/util/List;
public final fun getName ()Ljava/lang/String;
public final fun getPackageName ()Ljava/lang/String;
+ public final fun getRelativePath ()Ljava/lang/String;
public fun getTags ()Ljava/util/Map;
+ public fun getTypeSpecs ()Ljava/util/List;
public fun hashCode ()I
public final fun isScript ()Z
public static final fun scriptBuilder (Ljava/lang/String;Ljava/lang/String;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
@@ -207,13 +209,15 @@ public final class com/squareup/kotlinpoet/FileSpec : com/squareup/kotlinpoet/An
public static synthetic fun toBuilder$default (Lcom/squareup/kotlinpoet/FileSpec;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
public final fun toJavaFileObject ()Ljavax/tools/JavaFileObject;
public fun toString ()Ljava/lang/String;
- public final fun writeTo (Ljava/io/File;)V
+ public final fun writeTo (Ljava/io/File;)Ljava/io/File;
+ public final synthetic fun writeTo (Ljava/io/File;)V
public final fun writeTo (Ljava/lang/Appendable;)V
- public final fun writeTo (Ljava/nio/file/Path;)V
+ public final fun writeTo (Ljava/nio/file/Path;)Ljava/nio/file/Path;
+ public final synthetic fun writeTo (Ljava/nio/file/Path;)V
public final fun writeTo (Ljavax/annotation/processing/Filer;)V
}
-public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/Taggable$Builder {
+public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotlinpoet/Annotatable$Builder, com/squareup/kotlinpoet/Taggable$Builder, com/squareup/kotlinpoet/TypeSpecHolder$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;
@@ -251,8 +255,11 @@ public final class com/squareup/kotlinpoet/FileSpec$Builder : com/squareup/kotli
public final fun addNamedCode (Ljava/lang/String;Ljava/util/Map;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
public final fun addProperty (Lcom/squareup/kotlinpoet/PropertySpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
public final fun addStatement (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
- public final fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
+ public fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
+ public synthetic fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder;
public final fun addTypeAlias (Lcom/squareup/kotlinpoet/TypeAliasSpec;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
+ public fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
+ public synthetic fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder;
public final fun beginControlFlow (Ljava/lang/String;[Ljava/lang/Object;)Lcom/squareup/kotlinpoet/FileSpec$Builder;
public final fun build ()Lcom/squareup/kotlinpoet/FileSpec;
public final fun clearBody ()Lcom/squareup/kotlinpoet/FileSpec$Builder;
@@ -554,6 +561,7 @@ public final class com/squareup/kotlinpoet/MemberName$Companion {
public final class com/squareup/kotlinpoet/NameAllocator {
public fun <init> ()V
+ public fun <init> (Z)V
public final fun copy ()Lcom/squareup/kotlinpoet/NameAllocator;
public final fun get (Ljava/lang/Object;)Ljava/lang/String;
public final fun newName (Ljava/lang/String;)Ljava/lang/String;
@@ -925,7 +933,7 @@ public final class com/squareup/kotlinpoet/TypeNames {
public static final fun get (Lkotlin/reflect/KClass;)Lcom/squareup/kotlinpoet/ClassName;
}
-public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/Annotatable, com/squareup/kotlinpoet/ContextReceivable, com/squareup/kotlinpoet/Documentable, 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, com/squareup/kotlinpoet/TypeSpecHolder {
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;
@@ -959,7 +967,7 @@ public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/An
public final fun getSuperclassConstructorParameters ()Ljava/util/List;
public final fun getSuperinterfaces ()Ljava/util/Map;
public fun getTags ()Ljava/util/Map;
- public final fun getTypeSpecs ()Ljava/util/List;
+ public fun getTypeSpecs ()Ljava/util/List;
public final fun getTypeVariables ()Ljava/util/List;
public fun hashCode ()I
public static final fun interfaceBuilder (Lcom/squareup/kotlinpoet/ClassName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
@@ -981,7 +989,7 @@ public final class com/squareup/kotlinpoet/TypeSpec : com/squareup/kotlinpoet/An
public static final fun valueClassBuilder (Ljava/lang/String;)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 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, com/squareup/kotlinpoet/TypeSpecHolder$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;
@@ -1023,10 +1031,12 @@ public final class com/squareup/kotlinpoet/TypeSpec$Builder : com/squareup/kotli
public static synthetic fun addSuperinterface$default (Lcom/squareup/kotlinpoet/TypeSpec$Builder;Ljava/lang/reflect/Type;Lcom/squareup/kotlinpoet/CodeBlock;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
public static synthetic fun addSuperinterface$default (Lcom/squareup/kotlinpoet/TypeSpec$Builder;Lkotlin/reflect/KClass;Lcom/squareup/kotlinpoet/CodeBlock;ILjava/lang/Object;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
public final fun addSuperinterfaces (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
- public final fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
+ public fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
+ public synthetic fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder;
public final fun addTypeVariable (Lcom/squareup/kotlinpoet/TypeVariableName;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
public final fun addTypeVariables (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
- public final fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
+ public fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpec$Builder;
+ public synthetic fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder;
public final fun build ()Lcom/squareup/kotlinpoet/TypeSpec;
public synthetic fun contextReceivers (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/ContextReceivable$Builder;
public final fun getAnnotationSpecs ()Ljava/util/List;
@@ -1081,6 +1091,15 @@ public final class com/squareup/kotlinpoet/TypeSpec$Kind : java/lang/Enum {
public static fun values ()[Lcom/squareup/kotlinpoet/TypeSpec$Kind;
}
+public abstract interface class com/squareup/kotlinpoet/TypeSpecHolder {
+ public abstract fun getTypeSpecs ()Ljava/util/List;
+}
+
+public abstract interface class com/squareup/kotlinpoet/TypeSpecHolder$Builder {
+ public abstract fun addType (Lcom/squareup/kotlinpoet/TypeSpec;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder;
+ public fun addTypes (Ljava/lang/Iterable;)Lcom/squareup/kotlinpoet/TypeSpecHolder$Builder;
+}
+
public final class com/squareup/kotlinpoet/TypeVariableName : com/squareup/kotlinpoet/TypeName {
public static final field Companion Lcom/squareup/kotlinpoet/TypeVariableName$Companion;
public final fun copy (ZLjava/util/List;Ljava/util/List;ZLjava/util/Map;)Lcom/squareup/kotlinpoet/TypeVariableName;
diff --git a/kotlinpoet/build.gradle.kts b/kotlinpoet/build.gradle.kts
index 9627b60a..48669b33 100644
--- a/kotlinpoet/build.gradle.kts
+++ b/kotlinpoet/build.gradle.kts
@@ -13,40 +13,59 @@
* 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")
- }
-}
-
-tasks.compileTestKotlin {
- compilerOptions {
- freeCompilerArgs.add("-opt-in=com.squareup.kotlinpoet.DelicateKotlinPoetApi")
- }
+plugins {
+ kotlin("multiplatform")
}
spotless {
kotlin {
targetExclude(
// Non-Square licensed files
- "src/main/java/com/squareup/kotlinpoet/ClassName.kt",
- "src/test/java/com/squareup/kotlinpoet/AbstractTypesTest.kt",
- "src/test/java/com/squareup/kotlinpoet/ClassNameTest.kt",
- "src/test/java/com/squareup/kotlinpoet/TypesEclipseTest.kt",
- "src/test/java/com/squareup/kotlinpoet/TypesTest.kt",
+ "src/commonMain/kotlin/com/squareup/kotlinpoet/ClassName.kt",
+ "src/commonTest/kotlin/com/squareup/kotlinpoet/AbstractTypesTest.kt",
+ "src/commonTest/kotlin/com/squareup/kotlinpoet/ClassNameTest.kt",
+ "src/commonTest/kotlin/com/squareup/kotlinpoet/TypesEclipseTest.kt",
+ "src/commonTest/kotlin/com/squareup/kotlinpoet/TypesTest.kt",
)
}
}
-dependencies {
- implementation(libs.kotlin.reflect)
- testImplementation(libs.kotlin.junit)
- testImplementation(libs.truth)
- testImplementation(libs.guava)
- testImplementation(libs.compileTesting)
- testImplementation(libs.jimfs)
- testImplementation(libs.ecj)
- testImplementation(libs.kotlinCompileTesting)
- testImplementation(libs.kotlin.annotationProcessingEmbeddable)
- testImplementation(libs.kotlin.compilerEmbeddable)
+kotlin {
+ jvm {
+ withJava()
+ }
+
+ sourceSets {
+ val commonMain by getting {
+ dependencies {
+ implementation(libs.kotlin.reflect)
+ }
+ }
+ val commonTest by getting {
+ dependencies {
+ implementation(libs.kotlin.junit)
+ implementation(libs.truth)
+ implementation(libs.guava)
+ implementation(libs.compileTesting)
+ implementation(libs.jimfs)
+ implementation(libs.ecj)
+ implementation(libs.kotlinCompileTesting)
+ implementation(libs.kotlin.annotationProcessingEmbeddable)
+ implementation(libs.kotlin.compilerEmbeddable)
+ }
+ }
+ }
+}
+
+tasks.withType(org.gradle.jvm.tasks.Jar::class.java) {
+ manifest {
+ attributes("Automatic-Module-Name" to "com.squareup.kotlinpoet")
+ }
}
+
+tasks.named<org.jetbrains.kotlin.gradle.tasks.KotlinCompile>("compileTestKotlinJvm") {
+ compilerOptions {
+ freeCompilerArgs.add("-opt-in=com.squareup.kotlinpoet.DelicateKotlinPoetApi")
+ }
+}
+
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Annotatable.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Annotatable.kt
index 25533105..25533105 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Annotatable.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Annotatable.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/AnnotationSpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/AnnotationSpec.kt
index a9390923..a9390923 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/AnnotationSpec.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/AnnotationSpec.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ClassName.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ClassName.kt
index 5eeb21b0..5eeb21b0 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ClassName.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ClassName.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeBlock.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/CodeBlock.kt
index 6a99631c..6a99631c 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeBlock.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/CodeBlock.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/CodeWriter.kt
index ff1de015..d4489f24 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/CodeWriter.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/CodeWriter.kt
@@ -445,8 +445,8 @@ internal class CodeWriter constructor(
return className.canonicalName
}
- // If the class is in the same package, we're done.
- if (packageName == className.packageName) {
+ // If the class is in the same package and there's no import alias for that class, we're done.
+ if (packageName == className.packageName && imports[className.canonicalName]?.alias == null) {
referencedNames.add(className.topLevelClassName().simpleName)
return className.simpleNames.joinToString(".")
}
@@ -722,11 +722,11 @@ internal class CodeWriter constructor(
importsCollector.close()
return CodeWriter(
- out,
- indent,
- memberImports + generatedImports.filterKeys { it !in memberImports },
- suggestedTypeImports,
- suggestedMemberImports,
+ out = out,
+ indent = indent,
+ imports = memberImports + generatedImports.filterKeys { it !in memberImports },
+ importedTypes = suggestedTypeImports,
+ importedMembers = suggestedMemberImports,
)
}
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ContextReceivable.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ContextReceivable.kt
index 929096bc..929096bc 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ContextReceivable.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ContextReceivable.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/DelicateKotlinPoetApi.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/DelicateKotlinPoetApi.kt
index 11369334..11369334 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/DelicateKotlinPoetApi.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/DelicateKotlinPoetApi.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Documentable.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Documentable.kt
index 3dff284e..3dff284e 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Documentable.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Documentable.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Dynamic.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Dynamic.kt
index 413b7b7a..413b7b7a 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Dynamic.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Dynamic.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ExperimentalKotlinPoetApi.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ExperimentalKotlinPoetApi.kt
index 2e58556d..2e58556d 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ExperimentalKotlinPoetApi.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ExperimentalKotlinPoetApi.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FileSpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FileSpec.kt
index ef3f032c..288848c9 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FileSpec.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FileSpec.kt
@@ -20,16 +20,19 @@ import java.io.ByteArrayInputStream
import java.io.File
import java.io.IOException
import java.io.InputStream
-import java.io.OutputStreamWriter
import java.net.URI
import java.nio.charset.StandardCharsets.UTF_8
-import java.nio.file.Files
import java.nio.file.Path
import javax.annotation.processing.Filer
import javax.tools.JavaFileObject
import javax.tools.JavaFileObject.Kind
import javax.tools.SimpleJavaFileObject
import javax.tools.StandardLocation
+import kotlin.DeprecationLevel.HIDDEN
+import kotlin.io.path.createDirectories
+import kotlin.io.path.isDirectory
+import kotlin.io.path.notExists
+import kotlin.io.path.outputStream
import kotlin.reflect.KClass
/**
@@ -46,8 +49,9 @@ import kotlin.reflect.KClass
public class FileSpec private constructor(
builder: Builder,
private val tagMap: TagMap = builder.buildTagMap(),
-) : Taggable by tagMap, Annotatable {
+) : Taggable by tagMap, Annotatable, TypeSpecHolder {
override val annotations: List<AnnotationSpec> = builder.annotations.toImmutableList()
+ override val typeSpecs: List<TypeSpec> = builder.members.filterIsInstance<TypeSpec>().toImmutableList()
public val comment: CodeBlock = builder.comment.build()
public val packageName: String = builder.packageName
public val name: String = builder.name
@@ -59,6 +63,20 @@ public class FileSpec private constructor(
private val indent = builder.indent
private val extension = if (isScript) "kts" else "kt"
+ /**
+ * The relative path of the file which would be produced by a call to [writeTo].
+ * This value always uses unix-style path separators (`/`).
+ */
+ public val relativePath: String = buildString {
+ for (packageComponent in packageName.split('.').dropLastWhile { it.isEmpty() }) {
+ append(packageComponent)
+ append('/')
+ }
+ append(name)
+ append('.')
+ append(extension)
+ }
+
@Throws(IOException::class)
public fun writeTo(out: Appendable) {
val codeWriter = CodeWriter.withCollectedImports(
@@ -71,28 +89,39 @@ public class FileSpec private constructor(
codeWriter.close()
}
- /** Writes this to `directory` as UTF-8 using the standard directory structure. */
+ @Deprecated("", level = HIDDEN)
+ @JvmName("writeTo") // For binary compatibility.
+ public fun oldWriteTo(directory: Path) {
+ writeTo(directory)
+ }
+
+ /**
+ * Writes this to [directory] as UTF-8 using the standard directory structure
+ * and returns the newly output path.
+ */
@Throws(IOException::class)
- public fun writeTo(directory: Path) {
- require(Files.notExists(directory) || Files.isDirectory(directory)) {
+ public fun writeTo(directory: Path): Path {
+ require(directory.notExists() || directory.isDirectory()) {
"path $directory exists but is not a directory."
}
- var outputDirectory = directory
- if (packageName.isNotEmpty()) {
- for (packageComponent in packageName.split('.').dropLastWhile { it.isEmpty() }) {
- outputDirectory = outputDirectory.resolve(packageComponent)
- }
- }
-
- Files.createDirectories(outputDirectory)
+ val outputPath = directory.resolve(relativePath)
+ outputPath.parent.createDirectories()
+ outputPath.outputStream().bufferedWriter().use(::writeTo)
+ return outputPath
+ }
- val outputPath = outputDirectory.resolve("$name.$extension")
- OutputStreamWriter(Files.newOutputStream(outputPath), UTF_8).use { writer -> writeTo(writer) }
+ @Deprecated("", level = HIDDEN)
+ @JvmName("writeTo") // For binary compatibility.
+ public fun oldWriteTo(directory: File) {
+ writeTo(directory)
}
- /** Writes this to `directory` as UTF-8 using the standard directory structure. */
+ /**
+ * Writes this to [directory] as UTF-8 using the standard directory structure
+ * and returns the newly output file.
+ */
@Throws(IOException::class)
- public fun writeTo(directory: File): Unit = writeTo(directory.toPath())
+ public fun writeTo(directory: File): File = writeTo(directory.toPath()).toFile()
/** Writes this to `filer`. */
@Throws(IOException::class)
@@ -191,13 +220,7 @@ public class FileSpec private constructor(
override fun toString(): String = buildString { writeTo(this) }
public fun toJavaFileObject(): JavaFileObject {
- val uri = URI.create(
- if (packageName.isEmpty()) {
- name
- } else {
- packageName.replace('.', '/') + '/' + name
- } + ".$extension",
- )
+ val uri = URI.create(relativePath)
return object : SimpleJavaFileObject(uri, Kind.SOURCE) {
private val lastModified = System.currentTimeMillis()
override fun getCharContent(ignoreEncodingErrors: Boolean): String {
@@ -230,7 +253,7 @@ public class FileSpec private constructor(
public val packageName: String,
public val name: String,
public val isScript: Boolean,
- ) : Taggable.Builder<Builder>, Annotatable.Builder<Builder> {
+ ) : Taggable.Builder<Builder>, Annotatable.Builder<Builder>, TypeSpecHolder.Builder<Builder> {
override val annotations: MutableList<AnnotationSpec> = mutableListOf()
internal val comment = CodeBlock.builder()
internal val memberImports = sortedSetOf<Import>()
@@ -275,7 +298,7 @@ public class FileSpec private constructor(
comment.clear()
}
- public fun addType(typeSpec: TypeSpec): Builder = apply {
+ override fun addType(typeSpec: TypeSpec): Builder = apply {
if (isScript) {
body.add("%L", typeSpec)
} else {
@@ -283,6 +306,11 @@ public class FileSpec private constructor(
}
}
+ //region Overrides for binary compatibility
+ @Suppress("RedundantOverride")
+ override fun addTypes(typeSpecs: Iterable<TypeSpec>): Builder = super.addTypes(typeSpecs)
+ //endregion
+
public fun addFunction(funSpec: FunSpec): Builder = apply {
require(!funSpec.isConstructor && !funSpec.isAccessor) {
"cannot add ${funSpec.name} to file $name"
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FunSpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FunSpec.kt
index f42308ea..f42308ea 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/FunSpec.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/FunSpec.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Import.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Import.kt
index 59b6b12e..59b6b12e 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Import.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Import.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/KModifier.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/KModifier.kt
index 81d03570..81d03570 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/KModifier.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/KModifier.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/KOperator.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/KOperator.kt
index 461a39f2..461a39f2 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/KOperator.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/KOperator.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LambdaTypeName.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/LambdaTypeName.kt
index 9f462f81..9f462f81 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LambdaTypeName.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/LambdaTypeName.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LineWrapper.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/LineWrapper.kt
index 3a1e9a6b..3a1e9a6b 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/LineWrapper.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/LineWrapper.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/MemberName.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/MemberName.kt
index c70a10ac..c70a10ac 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/MemberName.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/MemberName.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/NameAllocator.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/NameAllocator.kt
index cda10042..a6c570b9 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/NameAllocator.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/NameAllocator.kt
@@ -77,7 +77,39 @@ public class NameAllocator private constructor(
private val allocatedNames: MutableSet<String>,
private val tagToName: MutableMap<Any, String>,
) {
- public constructor() : this(mutableSetOf(), mutableMapOf())
+ public constructor() : this(preallocateKeywords = true)
+
+ /**
+ * @param preallocateKeywords If true, all Kotlin keywords will be preallocated. Requested names which
+ * collide with keywords will be suffixed with underscores to avoid being used as identifiers:
+ *
+ * ```kotlin
+ * val nameAllocator = NameAllocator(preallocateKeywords = true)
+ * println(nameAllocator.newName("when")) // prints "when_"
+ * ```
+ *
+ * If false, keywords will not get any special treatment:
+ *
+ * ```kotlin
+ * val nameAllocator = NameAllocator(preallocateKeywords = false)
+ * println(nameAllocator.newName("when")) // prints "when"
+ * ```
+ *
+ * Note that you can use the `%N` placeholder when emitting a name produced by [NameAllocator] to
+ * ensure it's properly escaped for use as an identifier:
+ *
+ * ```kotlin
+ * val nameAllocator = NameAllocator(preallocateKeywords = false)
+ * println(CodeBlock.of("%N", nameAllocator.newName("when"))) // prints "`when`"
+ * ```
+ *
+ * The default behaviour of [NameAllocator] is to preallocate keywords - this is the behaviour you'll
+ * get when using the no-arg constructor.
+ */
+ public constructor(preallocateKeywords: Boolean) : this(
+ allocatedNames = if (preallocateKeywords) KEYWORDS.toMutableSet() else mutableSetOf(),
+ tagToName = mutableMapOf(),
+ )
/**
* Return a new name using `suggestion` that will not be a Java identifier or clash with other
@@ -89,7 +121,7 @@ public class NameAllocator private constructor(
tag: Any = UUID.randomUUID().toString(),
): String {
var result = toJavaIdentifier(suggestion)
- while (result.isKeyword || !allocatedNames.add(result)) {
+ while (!allocatedNames.add(result)) {
result += "_"
}
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/OriginatingElementsHolder.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/OriginatingElementsHolder.kt
index 4e877742..4e877742 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/OriginatingElementsHolder.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/OriginatingElementsHolder.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterSpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ParameterSpec.kt
index 15cf4bf0..91dc8b06 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterSpec.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ParameterSpec.kt
@@ -54,10 +54,8 @@ public class ParameterSpec private constructor(
internal fun emit(
codeWriter: CodeWriter,
includeType: Boolean = true,
- emitKdoc: Boolean = false,
inlineAnnotations: Boolean = true,
) {
- if (emitKdoc) codeWriter.emitKdoc(kdoc.ensureEndsWithNewLine())
codeWriter.emitAnnotations(annotations, inlineAnnotations)
codeWriter.emitModifiers(modifiers)
if (name.isNotEmpty()) codeWriter.emitCode("%N", this)
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterizedTypeName.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ParameterizedTypeName.kt
index b6bdf798..b6bdf798 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/ParameterizedTypeName.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/ParameterizedTypeName.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/PropertySpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/PropertySpec.kt
index 9ba9409c..9ba9409c 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/PropertySpec.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/PropertySpec.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Taggable.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Taggable.kt
index f3313aea..f3313aea 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Taggable.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Taggable.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeAliasSpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeAliasSpec.kt
index f9a607fb..f9a607fb 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeAliasSpec.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeAliasSpec.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeName.kt
index 60dea8bf..60dea8bf 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeName.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeName.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpec.kt
index 5f52e4ff..af0613b3 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeSpec.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpec.kt
@@ -47,7 +47,8 @@ public class TypeSpec private constructor(
OriginatingElementsHolder by delegateOriginatingElements,
ContextReceivable by contextReceivers,
Annotatable,
- Documentable {
+ Documentable,
+ TypeSpecHolder {
public val kind: Kind = builder.kind
public val name: String? = builder.name
override val kdoc: CodeBlock = builder.kdoc.build()
@@ -76,7 +77,7 @@ public class TypeSpec private constructor(
public val initializerBlock: CodeBlock = builder.initializerBlock.build()
public val initializerIndex: Int = builder.initializerIndex
public val funSpecs: List<FunSpec> = builder.funSpecs.toImmutableList()
- public val typeSpecs: List<TypeSpec> = builder.typeSpecs.toImmutableList()
+ public override val typeSpecs: List<TypeSpec> = builder.typeSpecs.toImmutableList()
internal val nestedTypesSimpleNames = typeSpecs.map { it.name }.toImmutableSet()
@Deprecated("Use annotations property", ReplaceWith("annotations"), ERROR)
@@ -208,7 +209,7 @@ public class TypeSpec private constructor(
)
param.emitDefaultValue(codeWriter)
} else {
- param.emit(codeWriter, emitKdoc = true, inlineAnnotations = false)
+ param.emit(codeWriter, inlineAnnotations = false)
}
}
@@ -373,31 +374,25 @@ public class TypeSpec private constructor(
/**
* 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.
+ * Parameters' KDocs, if present, will always be printed in the type header.
*/
private fun kdocWithConstructorDocs(): CodeBlock {
- if (primaryConstructor == null) {
- return kdoc.ensureEndsWithNewLine()
- }
- val constructorProperties = constructorProperties()
- val parametersWithKdoc = primaryConstructor.parameters.filter { parameter ->
- val propertyKdoc = constructorProperties[parameter.name]?.kdoc ?: CodeBlock.EMPTY
- return@filter parameter.kdoc.isNotEmpty() && propertyKdoc.isNotEmpty() &&
- parameter.kdoc != propertyKdoc
- }
- return with(kdoc.ensureEndsWithNewLine().toBuilder()) {
- 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())
+ val classKdoc = kdoc.ensureEndsWithNewLine()
+ val constructorKdoc = buildCodeBlock {
+ if (primaryConstructor != null) {
+ if (primaryConstructor.kdoc.isNotEmpty()) {
+ add("@constructor %L", primaryConstructor.kdoc.ensureEndsWithNewLine())
+ }
+ primaryConstructor.parameters.forEach { parameter ->
+ if (parameter.kdoc.isNotEmpty()) {
+ add("@param %L %L", parameter.name, parameter.kdoc.ensureEndsWithNewLine())
+ }
+ }
}
- build()
}
+ return listOf(classKdoc, constructorKdoc)
+ .filter(CodeBlock::isNotEmpty)
+ .joinToCode(separator = "\n")
}
private val hasInitializer: Boolean get() = initializerIndex != -1 && initializerBlock.isNotEmpty()
@@ -475,7 +470,8 @@ public class TypeSpec private constructor(
OriginatingElementsHolder.Builder<Builder>,
ContextReceivable.Builder<Builder>,
Annotatable.Builder<Builder>,
- Documentable.Builder<Builder> {
+ Documentable.Builder<Builder>,
+ TypeSpecHolder.Builder<Builder> {
internal var primaryConstructor: FunSpec? = null
internal var superclass: TypeName = ANY
internal val initializerBlock = CodeBlock.builder()
@@ -725,11 +721,7 @@ public class TypeSpec private constructor(
funSpecs += funSpec
}
- public fun addTypes(typeSpecs: Iterable<TypeSpec>): Builder = apply {
- this.typeSpecs += typeSpecs
- }
-
- public fun addType(typeSpec: TypeSpec): Builder = apply {
+ override fun addType(typeSpec: TypeSpec): Builder = apply {
typeSpecs += typeSpec
}
@@ -764,6 +756,9 @@ public class TypeSpec private constructor(
@Suppress("RedundantOverride")
override fun addKdoc(block: CodeBlock): Builder = super.addKdoc(block)
+
+ @Suppress("RedundantOverride")
+ override fun addTypes(typeSpecs: Iterable<TypeSpec>): Builder = super.addTypes(typeSpecs)
//endregion
public fun build(): TypeSpec {
diff --git a/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpecHolder.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpecHolder.kt
new file mode 100644
index 00000000..aad67e63
--- /dev/null
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeSpecHolder.kt
@@ -0,0 +1,31 @@
+/*
+ * 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 can contain other [TypeSpec] */
+public interface TypeSpecHolder {
+ public val typeSpecs: List<TypeSpec>
+
+ public interface Builder<out T : Builder<T>> {
+
+ public fun addType(typeSpec: TypeSpec): T
+
+ @Suppress("UNCHECKED_CAST")
+ public fun addTypes(typeSpecs: Iterable<TypeSpec>): T = apply {
+ for (typeSpec in typeSpecs) addType(typeSpec)
+ } as T
+ }
+}
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeVariableName.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeVariableName.kt
index 3313b2c9..3313b2c9 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/TypeVariableName.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/TypeVariableName.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Util.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Util.kt
index 16a443dd..c226f397 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/Util.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/Util.kt
@@ -169,7 +169,7 @@ private val IDENTIFIER_REGEX =
internal val String.isIdentifier get() = IDENTIFIER_REGEX.matches(this)
// https://kotlinlang.org/docs/reference/keyword-reference.html
-private val KEYWORDS = setOf(
+internal val KEYWORDS = setOf(
// Hard keywords
"as",
"break",
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/WildcardTypeName.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/WildcardTypeName.kt
index bd1e0965..bd1e0965 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/WildcardTypeName.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/WildcardTypeName.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt
index fcaae681..fcaae681 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/jvm/JvmAnnotations.kt
diff --git a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/tags/TypeAliasTag.kt b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/tags/TypeAliasTag.kt
index 22be037b..22be037b 100644
--- a/kotlinpoet/src/main/java/com/squareup/kotlinpoet/tags/TypeAliasTag.kt
+++ b/kotlinpoet/src/commonMain/kotlin/com/squareup/kotlinpoet/tags/TypeAliasTag.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AbstractTypesTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AbstractTypesTest.kt
index b78a96e8..b78a96e8 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AbstractTypesTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AbstractTypesTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotatedTypeNameTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AnnotatedTypeNameTest.kt
index 3e7b766c..3e7b766c 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotatedTypeNameTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AnnotatedTypeNameTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotationSpecTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AnnotationSpecTest.kt
index fff366f3..b35e65f2 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AnnotationSpecTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AnnotationSpecTest.kt
@@ -345,32 +345,6 @@ class AnnotationSpecTest {
)
}
- @Test fun getOnValueArrayTypeMirrorShouldNameValueArg() {
- val myClazz = compilation.elements
- .getTypeElement(JavaClassWithArrayValueAnnotation::class.java.canonicalName)
- val classBuilder = TypeSpec.classBuilder("Result")
-
- myClazz.annotationMirrors.map { AnnotationSpec.get(it) }
- .forEach {
- classBuilder.addAnnotation(it)
- }
-
- assertThat(toString(classBuilder.build())).isEqualTo(
- """
- |package com.squareup.tacos
- |
- |import com.squareup.kotlinpoet.JavaClassWithArrayValueAnnotation
- |import java.lang.Boolean
- |import java.lang.Object
- |
- |@JavaClassWithArrayValueAnnotation.AnnotationWithArrayValue(value = arrayOf(Object::class,
- | Boolean::class))
- |public class Result
- |
- """.trimMargin(),
- )
- }
-
@Test fun getOnVarargMirrorShouldNameValueArg() {
val myClazz = compilation.elements
.getTypeElement(KotlinClassWithVarargAnnotation::class.java.canonicalName)
@@ -399,28 +373,6 @@ class AnnotationSpecTest {
)
}
- @Test fun getOnValueArrayTypeAnnotationShouldNameValueArg() {
- val annotation = JavaClassWithArrayValueAnnotation::class.java.getAnnotation(
- JavaClassWithArrayValueAnnotation.AnnotationWithArrayValue::class.java,
- )
- val classBuilder = TypeSpec.classBuilder("Result")
- .addAnnotation(AnnotationSpec.get(annotation))
-
- assertThat(toString(classBuilder.build()).trim()).isEqualTo(
- """
- |package com.squareup.tacos
- |
- |import com.squareup.kotlinpoet.JavaClassWithArrayValueAnnotation
- |import java.lang.Boolean
- |import java.lang.Object
- |
- |@JavaClassWithArrayValueAnnotation.AnnotationWithArrayValue(value = arrayOf(Object::class,
- | Boolean::class))
- |public class Result
- """.trimMargin(),
- )
- }
-
@Test fun getOnVarargAnnotationShouldNameValueArg() {
val annotation = KotlinClassWithVarargAnnotation::class.java
.getAnnotation(AnnotationWithArrayValue::class.java)
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AssertThrows.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AssertThrows.kt
index facd7022..facd7022 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/AssertThrows.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/AssertThrows.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/Cased/Weird/Sup.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/Cased/Weird/Sup.kt
index 8d3f439b..8d3f439b 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/Cased/Weird/Sup.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/Cased/Weird/Sup.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ClassNameTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ClassNameTest.kt
index 92e4f144..92e4f144 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ClassNameTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ClassNameTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/CodeBlockTest.kt
index be4e62dd..be4e62dd 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CodeBlockTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/CodeBlockTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/CrossplatformTest.kt
index cc119be5..cc119be5 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/CrossplatformTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/CrossplatformTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/DelegatedConstructorCallTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/DelegatedConstructorCallTest.kt
index 80a90358..80a90358 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/DelegatedConstructorCallTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/DelegatedConstructorCallTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt
index 00b0c88c..00b0c88c 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ExpectDeclarationsTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt
index 8cc5f496..8cc5f496 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ExternalDeclarationsTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileReadingTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileReadingTest.kt
index 35719cf8..35719cf8 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileReadingTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileReadingTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileSpecTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileSpecTest.kt
index c363f592..a855cddc 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileSpecTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileSpecTest.kt
@@ -500,6 +500,37 @@ class FileSpecTest {
)
}
+ // https://github.com/square/kotlinpoet/issues/1696
+ @Test fun aliasedImportInSamePackage() {
+ val packageName = "com.mypackage"
+ val className = ClassName(packageName, "StringKey")
+ val source = FileSpec.builder(packageName, "K")
+ .addAliasedImport(className, "S")
+ .addType(
+ TypeSpec
+ .objectBuilder("K")
+ .addProperty(
+ PropertySpec.builder("test", className)
+ .initializer("%T(%L)", className, 0)
+ .build(),
+ )
+ .build(),
+ )
+ .build()
+ assertThat(source.toString()).isEqualTo(
+ """
+ |package com.mypackage
+ |
+ |import com.mypackage.StringKey as S
+ |
+ |public object K {
+ | public val test: S = S(0)
+ |}
+ |
+ """.trimMargin(),
+ )
+ }
+
@Test fun conflictingParentName() {
val source = FileSpec.builder("com.squareup.tacos", "A")
.addType(
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileWritingTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileWritingTest.kt
index 83574f31..0e79ac7e 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FileWritingTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FileWritingTest.kt
@@ -69,37 +69,46 @@ class FileWritingTest {
@Test fun pathDefaultPackage() {
val type = TypeSpec.classBuilder("Test").build()
- FileSpec.get("", type).writeTo(fsRoot)
+ val fileSpec = FileSpec.get("", type)
+ assertThat(fileSpec.relativePath).isEqualTo("Test.kt")
- val testPath = fsRoot.resolve("Test.kt")
+ val testPath = fileSpec.writeTo(fsRoot)
+ assertThat(testPath).isEqualTo(fsRoot.resolve("Test.kt"))
assertThat(Files.exists(testPath)).isTrue()
}
@Test fun pathDefaultPackageWithSubdirectory() {
val type = TypeSpec.classBuilder("Test").build()
- FileSpec.get("", type).writeTo(fsRoot.resolve("sub"))
+ val testPath = FileSpec.get("", type).writeTo(fsRoot.resolve("sub"))
- val testPath = fsRoot.resolve("sub/Test.kt")
+ assertThat(testPath).isEqualTo(fsRoot.resolve("sub/Test.kt"))
assertThat(Files.exists(testPath)).isTrue()
}
@Test fun fileDefaultPackage() {
val type = TypeSpec.classBuilder("Test").build()
- FileSpec.get("", type).writeTo(tmp.root)
+ val testFile = FileSpec.get("", type).writeTo(tmp.root)
- val testFile = File(tmp.root, "Test.kt")
+ assertThat(testFile).isEqualTo(File(tmp.root, "Test.kt"))
assertThat(testFile.exists()).isTrue()
}
@Test fun pathNestedClasses() {
val type = TypeSpec.classBuilder("Test").build()
- FileSpec.get("foo", type).writeTo(fsRoot)
- FileSpec.get("foo.bar", type).writeTo(fsRoot)
- FileSpec.get("foo.bar.baz", type).writeTo(fsRoot)
-
- val fooPath = fsRoot.resolve(fs.getPath("foo", "Test.kt"))
- val barPath = fsRoot.resolve(fs.getPath("foo", "bar", "Test.kt"))
- val bazPath = fsRoot.resolve(fs.getPath("foo", "bar", "baz", "Test.kt"))
+ val fooSpec = FileSpec.get("foo", type)
+ val barSpec = FileSpec.get("foo.bar", type)
+ val bazSpec = FileSpec.get("foo.bar.baz", type)
+ assertThat(fooSpec.relativePath).isEqualTo("foo/Test.kt")
+ assertThat(barSpec.relativePath).isEqualTo("foo/bar/Test.kt")
+ assertThat(bazSpec.relativePath).isEqualTo("foo/bar/baz/Test.kt")
+
+ val fooPath = fooSpec.writeTo(fsRoot)
+ val barPath = barSpec.writeTo(fsRoot)
+ val bazPath = bazSpec.writeTo(fsRoot)
+
+ assertThat(fooPath).isEqualTo(fsRoot.resolve(fs.getPath("foo", "Test.kt")))
+ assertThat(barPath).isEqualTo(fsRoot.resolve(fs.getPath("foo", "bar", "Test.kt")))
+ assertThat(bazPath).isEqualTo(fsRoot.resolve(fs.getPath("foo", "bar", "baz", "Test.kt")))
assertThat(Files.exists(fooPath)).isTrue()
assertThat(Files.exists(barPath)).isTrue()
assertThat(Files.exists(bazPath)).isTrue()
@@ -107,16 +116,16 @@ class FileWritingTest {
@Test fun fileNestedClasses() {
val type = TypeSpec.classBuilder("Test").build()
- FileSpec.get("foo", type).writeTo(tmp.root)
- FileSpec.get("foo.bar", type).writeTo(tmp.root)
- FileSpec.get("foo.bar.baz", type).writeTo(tmp.root)
+ val fooFile = FileSpec.get("foo", type).writeTo(tmp.root)
+ val barFile = FileSpec.get("foo.bar", type).writeTo(tmp.root)
+ val bazFile = FileSpec.get("foo.bar.baz", type).writeTo(tmp.root)
val fooDir = File(tmp.root, "foo")
- val fooFile = File(fooDir, "Test.kt")
+ assertThat(fooFile).isEqualTo(File(fooDir, "Test.kt"))
val barDir = File(fooDir, "bar")
- val barFile = File(barDir, "Test.kt")
+ assertThat(barFile).isEqualTo(File(barDir, "Test.kt"))
val bazDir = File(barDir, "baz")
- val bazFile = File(bazDir, "Test.kt")
+ assertThat(bazFile).isEqualTo(File(bazDir, "Test.kt"))
assertThat(fooFile.exists()).isTrue()
assertThat(barFile.exists()).isTrue()
assertThat(bazFile.exists()).isTrue()
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FunSpecTest.kt
index 4fff9fe3..4fff9fe3 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/FunSpecTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/FunSpecTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/KotlinPoetTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/KotlinPoetTest.kt
index 642b65c5..642b65c5 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/KotlinPoetTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/KotlinPoetTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LambdaTypeNameTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LambdaTypeNameTest.kt
index 1bcaef4a..1bcaef4a 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LambdaTypeNameTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LambdaTypeNameTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrapperTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LineWrapperTest.kt
index 8fdbda83..8fdbda83 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrapperTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LineWrapperTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrappingTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LineWrappingTest.kt
index 3471607e..3471607e 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/LineWrappingTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/LineWrappingTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/MemberNameTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/MemberNameTest.kt
index 69271d7d..69271d7d 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/MemberNameTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/MemberNameTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/NameAllocatorTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/NameAllocatorTest.kt
index 28c7d34d..a61877c0 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/NameAllocatorTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/NameAllocatorTest.kt
@@ -70,6 +70,12 @@ class NameAllocatorTest {
assertThat(nameAllocator[1]).isEqualTo("when_")
}
+ @Test fun kotlinKeywordNotPreAllocated() {
+ val nameAllocator = NameAllocator(preallocateKeywords = false)
+ assertThat(nameAllocator.newName("when", 1)).isEqualTo("when")
+ assertThat(nameAllocator[1]).isEqualTo("when")
+ }
+
@Test fun tagReuseForbidden() {
val nameAllocator = NameAllocator()
nameAllocator.newName("foo", 1)
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ParameterSpecTest.kt
index 5528e493..5528e493 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterSpecTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ParameterSpecTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt
index a94dddd5..a94dddd5 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ParameterizedTypeNameTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/PropertySpecTest.kt
index af373c25..af373c25 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/PropertySpecTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/PropertySpecTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/StringsTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/StringsTest.kt
index d25ca4ed..d25ca4ed 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/StringsTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/StringsTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TaggableTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TaggableTest.kt
index 504798b6..504798b6 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TaggableTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TaggableTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TestFiler.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TestFiler.kt
index bb24d564..bb24d564 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TestFiler.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TestFiler.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeAliasSpecTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeAliasSpecTest.kt
index f5c7eb22..f5c7eb22 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeAliasSpecTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeAliasSpecTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeNameKotlinTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeNameKotlinTest.kt
index 3c16242a..3c16242a 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeNameKotlinTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeNameKotlinTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeSpecTest.kt
index ebac6356..94732b61 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeSpecTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeSpecTest.kt
@@ -1975,14 +1975,12 @@ class TypeSpecTest {
| * [random][java.util.Random] tex-mex stuff we could find in the pantry
| * and some [kotlin.String] cheese.
| *
+ | * @param temperature Taco temperature. Can be as cold as the famous ice tacos from
+ | * the Andes, or hot with lava-like cheese from the depths of
+ | * the Ninth Circle.
| * @param mild Whether the taco is mild (ew) or crunchy (ye).
| */
|public class Taco(
- | /**
- | * Taco temperature. Can be as cold as the famous ice tacos from
- | * the Andes, or hot with lava-like cheese from the depths of
- | * the Ninth Circle.
- | */
| temperature: Double,
| /**
| * True for a soft flour tortilla; false for a crunchy corn tortilla.
@@ -4805,6 +4803,9 @@ class TypeSpecTest {
| * This is a thing for stuff.
| *
| * @constructor Construct a thing!
+ | * @param first the first thing
+ | * @param second the second thing
+ | * @param third the third thing
| */
|public class MyType(
| /**
@@ -4839,10 +4840,10 @@ class TypeSpecTest {
.build()
assertThat(typeSpec.toString()).isEqualTo(
"""
+ |/**
+ | * @param first the first thing
+ | */
|public class MyType(
- | /**
- | * the first thing
- | */
| first: kotlin.Int,
|)
|
@@ -5615,6 +5616,27 @@ class TypeSpecTest {
)
}
+ @Test fun classKdoc() {
+ val type = TypeSpec.classBuilder("MyClass")
+ .addKdoc("This is my class")
+ .primaryConstructor(
+ FunSpec.constructorBuilder()
+ .build(),
+ )
+ .build()
+
+ //language=kotlin
+ assertThat(type.toString()).isEqualTo(
+ """
+ /**
+ * This is my class
+ */
+ public class MyClass()
+
+ """.trimIndent(),
+ )
+ }
+
// https://github.com/square/kotlinpoet/issues/1630
@Test fun primaryConstructorKDoc() {
val type = TypeSpec.classBuilder("MyClass")
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeVariableNameTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeVariableNameTest.kt
index 628b569e..628b569e 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeVariableNameTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypeVariableNameTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypesEclipseTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypesEclipseTest.kt
index a3ae52b5..a3ae52b5 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypesEclipseTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypesEclipseTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypesTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypesTest.kt
index 43bdbb7c..43bdbb7c 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypesTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/TypesTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/UtilTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/UtilTest.kt
index f8bfc0b9..f8bfc0b9 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/UtilTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/UtilTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ValueTypeSpecTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ValueTypeSpecTest.kt
index 363b9898..363b9898 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/ValueTypeSpecTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/ValueTypeSpecTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/WildcardTypeNameTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/WildcardTypeNameTest.kt
index db42d003..db42d003 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/WildcardTypeNameTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/WildcardTypeNameTest.kt
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt
index 66147363..66147363 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt
+++ b/kotlinpoet/src/commonTest/kotlin/com/squareup/kotlinpoet/jvm/JvmAnnotationsTest.kt
diff --git a/kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/JavaAnnotationSpecTest.kt b/kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/JavaAnnotationSpecTest.kt
new file mode 100644
index 00000000..4b265964
--- /dev/null
+++ b/kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/JavaAnnotationSpecTest.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2015 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.google.testing.compile.CompilationRule
+import kotlin.test.Test
+import org.junit.Rule
+
+class JavaAnnotationSpecTest {
+
+ @Rule @JvmField
+ val compilation = CompilationRule()
+
+ @Test fun getOnValueArrayTypeMirrorShouldNameValueArg() {
+ val myClazz = compilation.elements
+ .getTypeElement(JavaClassWithArrayValueAnnotation::class.java.canonicalName)
+ val classBuilder = TypeSpec.classBuilder("Result")
+
+ myClazz.annotationMirrors.map { AnnotationSpec.get(it) }
+ .forEach {
+ classBuilder.addAnnotation(it)
+ }
+
+ assertThat(toString(classBuilder.build())).isEqualTo(
+ """
+ |package com.squareup.tacos
+ |
+ |import com.squareup.kotlinpoet.JavaClassWithArrayValueAnnotation
+ |import java.lang.Boolean
+ |import java.lang.Object
+ |
+ |@JavaClassWithArrayValueAnnotation.AnnotationWithArrayValue(value = arrayOf(Object::class,
+ | Boolean::class))
+ |public class Result
+ |
+ """.trimMargin(),
+ )
+ }
+
+ @Test fun getOnValueArrayTypeAnnotationShouldNameValueArg() {
+ val annotation = JavaClassWithArrayValueAnnotation::class.java.getAnnotation(
+ JavaClassWithArrayValueAnnotation.AnnotationWithArrayValue::class.java,
+ )
+ val classBuilder = TypeSpec.classBuilder("Result")
+ .addAnnotation(AnnotationSpec.get(annotation))
+
+ assertThat(toString(classBuilder.build()).trim()).isEqualTo(
+ """
+ |package com.squareup.tacos
+ |
+ |import com.squareup.kotlinpoet.JavaClassWithArrayValueAnnotation
+ |import java.lang.Boolean
+ |import java.lang.Object
+ |
+ |@JavaClassWithArrayValueAnnotation.AnnotationWithArrayValue(value = arrayOf(Object::class,
+ | Boolean::class))
+ |public class Result
+ """.trimMargin(),
+ )
+ }
+
+ private fun toString(typeSpec: TypeSpec) =
+ FileSpec.get("com.squareup.tacos", typeSpec).toString()
+}
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/JavaClassWithArrayValueAnnotation.java b/kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/JavaClassWithArrayValueAnnotation.java
index c48b3a4c..c48b3a4c 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/JavaClassWithArrayValueAnnotation.java
+++ b/kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/JavaClassWithArrayValueAnnotation.java
diff --git a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeNameTest.java b/kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/TypeNameTest.java
index 70019f9d..70019f9d 100644
--- a/kotlinpoet/src/test/java/com/squareup/kotlinpoet/TypeNameTest.java
+++ b/kotlinpoet/src/jvmTest/java/com/squareup/kotlinpoet/TypeNameTest.java
diff --git a/mkdocs.yml b/mkdocs.yml
index 74caf790..abd937be 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -55,10 +55,30 @@ markdown_extensions:
nav:
- 'Overview':
- - 'KotlinPoet': index.md
- - 'Interop - JavaPoet': interop-javapoet.md
- - 'Interop - kotlinx-metadata': interop-kotlinx-metadata.md
- - 'Interop - KSP': interop-ksp.md
+ - 'Code & Control Flow': code-control-flow.md
+ - 'Format Specifiers':
+ - '%S for Strings': s-for-strings.md
+ - '%P for String Templates': p-for-string-templates.md
+ - '%T for Types': t-for-types.md
+ - '%M for Members': m-for-members.md
+ - '%N for Names': n-for-names.md
+ - '%L for Literals': l-for-literals.md
+ - 'Code Block Format Strings': code-block-format-strings.md
+ - 'Functions': functions.md
+ - 'Constructors': constructors.md
+ - 'Parameters': parameters.md
+ - 'Properties': properties.md
+ - 'Interfaces': interfaces.md
+ - 'Objects': objects.md
+ - 'Enums': enums.md
+ - 'Anonymous Inner Classes': anonymous-inner-classes.md
+ - 'Annotations': annotations.md
+ - 'Type Aliases': type-aliases.md
+ - 'Callable References': callable-references.md
+ - 'kotlin-reflect': kotlin-reflect.md
+ - 'Interop - JavaPoet': interop-javapoet.md
+ - 'Interop - kotlinx-metadata': interop-kotlinx-metadata.md
+ - 'Interop - KSP': interop-ksp.md
- 'API':
- 'kotlinpoet': 1.x/kotlinpoet/index.html
- 'interop-javapoet': 1.x/interop-javapoet/index.html
diff --git a/renovate.json b/renovate.json
index 47fc816a..d77f3a63 100644
--- a/renovate.json
+++ b/renovate.json
@@ -3,6 +3,7 @@
"extends": [
"config:base"
],
+ "semanticCommits": "disabled",
"packageRules": [
{
"matchManagers": ["pip_requirements"],
diff --git a/settings.gradle.kts b/settings.gradle.kts
index 465f238c..c9b262e9 100644
--- a/settings.gradle.kts
+++ b/settings.gradle.kts
@@ -21,7 +21,7 @@ pluginManagement {
}
plugins {
- id("org.gradle.toolchains.foojay-resolver-convention") version("0.7.0")
+ id("org.gradle.toolchains.foojay-resolver-convention") version("0.8.0")
}
include(