Skip to content

Commit a84ed35

Browse files
authored
Add KSP2 support (#790)
1 parent 7657756 commit a84ed35

File tree

6 files changed

+180
-34
lines changed

6 files changed

+180
-34
lines changed

docs/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ and this project orients towards [Semantic Versioning](http://semver.org/spec/v2
77
Note: This project needs KSP to work and every new Ktorfit with an update of the KSP version is technically a breaking change.
88
But there is no intent to bump the Ktorfit major version for every KSP update.
99

10+
# Unreleased
11+
12+
## Added
13+
- Add KSP2 support
14+
1015
# [2.3.0]()
1116

1217
2.3.0 - 2025-02-16

gradle.properties

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,6 @@ POM_LICENCE_DIST=repo
2424
POM_DEVELOPER_ID=Foso
2525
POM_DEVELOPER_NAME=Jens Klingenberg
2626
POM_DEVELOPER_URL=https://www.jensklingenberg.de
27-
SONATYPE_STAGING_PROFILE=de.jensklingenberg
27+
SONATYPE_STAGING_PROFILE=de.jensklingenberg
28+
29+
#ksp.useKSP2=true

gradle/libs.versions.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ktorfitFlowConverter = "2.3.0"
1919
ktorfitResponseConverter = "2.3.0"
2020
ktorfitGradle = "2.3.0"
2121

22-
ktorfitGradlePlugin = "2.2.0"
22+
ktorfitGradlePlugin = "2.3.0"
2323
ktorVersion = "3.1.0"
2424
mockk = "1.13.16"
2525
mockito-kotlin = "4.1.0"

ktorfit-gradle-plugin/src/main/java/de/jensklingenberg/ktorfit/gradle/KtorfitGradlePlugin.kt

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -75,9 +75,17 @@ class KtorfitGradlePlugin : Plugin<Project> {
7575
if (singleTarget) {
7676
argMethod.invoke(kspExtension, "Ktorfit_MultiplatformWithSingleTarget", true.toString())
7777
} else {
78-
tasks.withType(KotlinCompilationTask::class.java).configureEach {
79-
if (name != "kspCommonMainKotlinMetadata") {
80-
dependsOn("kspCommonMainKotlinMetadata")
78+
val useKsp2 = project.findProperty("ksp.useKSP2")?.toString()?.toBoolean() ?: false
79+
80+
if (useKsp2) {
81+
tasks.filter { it.name != "kspCommonMainKotlinMetadata" }.forEach {
82+
it.dependsOn("kspCommonMainKotlinMetadata")
83+
}
84+
} else {
85+
tasks.withType(KotlinCompilationTask::class.java).configureEach {
86+
if (name != "kspCommonMainKotlinMetadata") {
87+
dependsOn("kspCommonMainKotlinMetadata")
88+
}
8189
}
8290
}
8391
}

ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/model/ParameterData.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ fun KSValueParameter.createParameterData(logger: KSPLogger): ParameterData {
3939
)
4040
}
4141

42-
if (hasRequestBuilderAnno && parameterType.resolveTypeName() != "[@kotlin.ExtensionFunctionType] Function1<HttpRequestBuilder, Unit>") {
42+
if (hasRequestBuilderAnno && !parameterType.resolveTypeName().contains("HttpRequestBuilder")) {
4343
logger.error(
4444
KtorfitError.REQ_BUILDER_PARAMETER_TYPE_NEEDS_TO_BE_HTTP_REQUEST_BUILDER,
4545
ksValueParameter,

ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/utils/KSValueParameterExt.kt

Lines changed: 159 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -27,99 +27,230 @@ private const val KTORFIT_DEFAULT_VALUE = "KTORFIT_DEFAULT_VALUE"
2727

2828
@OptIn(KspExperimental::class)
2929
fun KSValueParameter.getPathAnnotation(): Path? {
30-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Path::class).firstOrNull()?.let {
31-
return Path(it.value.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()), it.encoded)
30+
try {
31+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Path::class).firstOrNull()?.let {
32+
return Path(it.value.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()), it.encoded)
33+
}
34+
} catch (e: Exception) {
35+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
36+
return this.annotations.firstOrNull {
37+
it.shortName.getShortName() == "Path"
38+
}?.let {
39+
val encoded = it.getArgumentValueByName<Boolean>("encoded") ?: false
40+
return Path(it.getArgumentValueByName<String>("value")?.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()) ?: this.name.safeString(), encoded)
41+
}
3242
}
3343
}
3444

3545
@OptIn(KspExperimental::class)
3646
fun KSValueParameter.getHeaderAnnotation(): Header? {
37-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Header::class).firstOrNull()?.let {
38-
return Header(it.value)
47+
try {
48+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Header::class).firstOrNull()?.let {
49+
return Header(it.value)
50+
}
51+
} catch (e: Exception) {
52+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
53+
return this.annotations.firstOrNull {
54+
it.shortName.getShortName() == "Header"
55+
}?.let {
56+
return Header(it.getArgumentValueByName<String>("value") ?: this.name.safeString())
57+
}
3958
}
4059
}
4160

4261
@OptIn(KspExperimental::class)
4362
fun KSValueParameter.getHeaderMapAnnotation(): HeaderMap? {
44-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.HeaderMap::class).firstOrNull()?.let {
45-
return HeaderMap
63+
try {
64+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.HeaderMap::class).firstOrNull()?.let {
65+
return HeaderMap
66+
}
67+
} catch (e: Exception) {
68+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
69+
return this.annotations.firstOrNull {
70+
it.shortName.getShortName() == "HeaderMap"
71+
}?.let {
72+
return HeaderMap
73+
}
4674
}
4775
}
4876

4977
@OptIn(KspExperimental::class)
5078
fun KSValueParameter.getQueryAnnotation(): Query? {
51-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Query::class).firstOrNull()?.let {
52-
return Query(it.value.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()), it.encoded)
79+
try {
80+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Query::class).firstOrNull()?.let {
81+
return Query(it.value.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()), it.encoded)
82+
}
83+
} catch (e: Exception) {
84+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
85+
return this.annotations.firstOrNull {
86+
it.shortName.getShortName() == "Query"
87+
}?.let {
88+
val encoded = it.getArgumentValueByName<Boolean>("encoded") ?: false
89+
return Query(it.getArgumentValueByName<String>("value")?.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()) ?: this.name.safeString(), encoded)
90+
}
5391
}
5492
}
5593

5694
@OptIn(KspExperimental::class)
5795
fun KSValueParameter.getQueryNameAnnotation(): QueryName? {
58-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.QueryName::class).firstOrNull()?.let {
59-
return QueryName(it.encoded)
96+
try {
97+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.QueryName::class).firstOrNull()?.let {
98+
return QueryName(it.encoded)
99+
}
100+
} catch (e: Exception) {
101+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
102+
return this.annotations.firstOrNull {
103+
it.shortName.getShortName() == "QueryName"
104+
}?.let {
105+
val encoded = it.getArgumentValueByName<Boolean>("encoded") ?: false
106+
return QueryName(encoded)
107+
}
60108
}
61109
}
62110

63111
@OptIn(KspExperimental::class)
64112
fun KSValueParameter.getQueryMapAnnotation(): QueryMap? {
65-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.QueryMap::class).firstOrNull()?.let {
66-
return QueryMap(it.encoded)
113+
try {
114+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.QueryMap::class).firstOrNull()?.let {
115+
return QueryMap(it.encoded)
116+
}
117+
} catch (e: Exception) {
118+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
119+
return this.annotations.firstOrNull {
120+
it.shortName.getShortName() == "QueryMap"
121+
}?.let {
122+
val encoded = it.getArgumentValueByName<Boolean>("encoded") ?: false
123+
return QueryMap(encoded)
124+
}
67125
}
68126
}
69127

70128
@OptIn(KspExperimental::class)
71129
fun KSValueParameter.getFieldAnnotation(): Field? {
72-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Field::class).firstOrNull()?.let {
73-
return Field(it.value.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()), it.encoded)
130+
try {
131+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Field::class).firstOrNull()?.let {
132+
return Field(it.value.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()), it.encoded)
133+
}
134+
} catch (e: Exception) {
135+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
136+
return this.annotations.firstOrNull {
137+
it.shortName.getShortName() == "Field"
138+
}?.let {
139+
val encoded = it.getArgumentValueByName<Boolean>("encoded") ?: false
140+
return Field(it.getArgumentValueByName<String>("value")?.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()) ?: this.name.safeString(), encoded)
141+
}
74142
}
75143
}
76144

77145
@OptIn(KspExperimental::class)
78146
fun KSValueParameter.getFieldMapAnnotation(): FieldMap? {
79-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.FieldMap::class).firstOrNull()?.let {
80-
return FieldMap(it.encoded)
147+
try {
148+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.FieldMap::class).firstOrNull()?.let {
149+
return FieldMap(it.encoded)
150+
}
151+
} catch (e: Exception) {
152+
return this.annotations.firstOrNull {
153+
it.shortName.getShortName() == "FieldMap"
154+
}?.let {
155+
val encoded = it.getArgumentValueByName<Boolean>("encoded") ?: false
156+
return FieldMap(encoded)
157+
}
81158
}
82159
}
83160

84161
@OptIn(KspExperimental::class)
85162
fun KSValueParameter.getPartAnnotation(): Part? {
86-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Part::class).firstOrNull()?.let {
87-
return Part(it.value, "binary")
163+
try {
164+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Part::class).firstOrNull()?.let {
165+
return Part(it.value, "binary")
166+
}
167+
} catch (e: Exception) {
168+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
169+
return this.annotations.firstOrNull {
170+
it.shortName.getShortName() == "Part"
171+
}?.let {
172+
return Part(it.getArgumentValueByName<String>("value") ?: this.name.safeString(), "binary")
173+
}
88174
}
89175
}
90176

91177
@OptIn(KspExperimental::class)
92178
fun KSValueParameter.getPartMapAnnotation(): PartMap? {
93-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.PartMap::class).firstOrNull()?.let {
94-
return PartMap(it.encoding)
179+
try {
180+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.PartMap::class).firstOrNull()?.let {
181+
return PartMap(it.encoding)
182+
}
183+
} catch (e: Exception) {
184+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
185+
return this.annotations.firstOrNull {
186+
it.shortName.getShortName() == "PartMap"
187+
}?.let {
188+
return PartMap(it.getArgumentValueByName<String>("encoding") ?: "binary")
189+
}
95190
}
96191
}
97192

98193
@OptIn(KspExperimental::class)
99194
fun KSValueParameter.getRequestBuilderAnnotation(): RequestBuilder? {
100-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.ReqBuilder::class).firstOrNull()?.let {
101-
return RequestBuilder
195+
try {
196+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.ReqBuilder::class).firstOrNull()?.let {
197+
return RequestBuilder
198+
}
199+
} catch (e: Exception) {
200+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
201+
return this.annotations.firstOrNull {
202+
it.shortName.getShortName() == "ReqBuilder"
203+
}?.let {
204+
return RequestBuilder
205+
}
102206
}
103207
}
104208

105209
@OptIn(KspExperimental::class)
106210
fun KSValueParameter.getUrlAnnotation(): Url? {
107-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Url::class).firstOrNull()?.let {
108-
return Url
211+
try {
212+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Url::class).firstOrNull()?.let {
213+
return Url
214+
}
215+
} catch (e: Exception) {
216+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
217+
return this.annotations.firstOrNull {
218+
it.shortName.getShortName() == "Url"
219+
}?.let {
220+
return Url
221+
}
109222
}
110223
}
111224

112225
@OptIn(KspExperimental::class)
113226
fun KSValueParameter.getBodyAnnotation(): Body? {
114-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Body::class).firstOrNull()?.let {
115-
return Body
227+
try {
228+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Body::class).firstOrNull()?.let {
229+
return Body
230+
}
231+
} catch (e: Exception) {
232+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
233+
return this.annotations.firstOrNull {
234+
it.shortName.getShortName() == "Body"
235+
}?.let {
236+
return Body
237+
}
116238
}
117239
}
118240

119241
@OptIn(KspExperimental::class)
120242
fun KSValueParameter.getTagAnnotation(): Tag? {
121-
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Tag::class).firstOrNull()?.let {
122-
return Tag(it.value.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()))
243+
try {
244+
return this.getAnnotationsByType(de.jensklingenberg.ktorfit.http.Tag::class).firstOrNull()?.let {
245+
return Tag(it.value.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()))
246+
}
247+
} catch (e: Exception) {
248+
// TODO Workaround for KSP2 cant find annotation,check if still needed when KSP2 out of beta
249+
return this.annotations.firstOrNull {
250+
it.shortName.getShortName() == "Tag"
251+
}?.let {
252+
return Tag(it.getArgumentValueByName<String>("value")?.replace(KTORFIT_DEFAULT_VALUE, this.name.safeString()) ?: this.name.safeString())
253+
}
123254
}
124255
}
125256

0 commit comments

Comments
 (0)