From 96db58ec4ac643e302fa3a51515cf02479d955cb Mon Sep 17 00:00:00 2001 From: Jens Klingenberg Date: Thu, 16 May 2024 19:09:46 +0200 Subject: [PATCH] Release 2.0.0-beta2 --- docs/CHANGELOG.md | 5 ++ .../androidonlyexample/MainActivity.kt | 7 +++ gradle/libs.versions.toml | 15 +++--- ktorfit-compiler-plugin/build.gradle.kts | 2 +- .../ktorfit/CreateFuncTransformer.kt | 7 ++- .../ktorfit/ElementTransformer.kt | 31 +++++++++++-- .../ktorfit/FunctionTransformerTest.kt | 24 +++++----- ktorfit-gradle-plugin/build.gradle.kts | 2 +- .../gradle/KtorfitCompilerSubPlugin.kt | 2 +- ktorfit-ksp/build.gradle.kts | 6 ++- .../ktorfit/model/ClassData.kt | 46 +++++++++++++------ .../ktorfit/model/KtorfitClass.kt | 4 +- .../reqBuilderExtension/UrlCodeGeneration.kt | 4 +- .../ktorfit/HttpAnnotationTest.kt | 2 +- .../ktorfit/QueryAnnotationsTest.kt | 10 ++-- .../ktorfit/RequestConverterTextKtTest.kt | 2 +- .../ktorfit/RequestTypeTest.kt | 2 +- .../ktorfit/ReturnTypeDataTest.kt | 2 +- .../ktorfit/StreamingAnnotationTest.kt | 2 +- .../de/jensklingenberg/ktorfit/UrlTest.kt | 10 ++-- .../UrlArgumentTextKtTest.kt | 10 ++-- .../de/jensklingenberg/ktorfit/Ktorfit.kt | 10 ++-- .../internal/KtorfitConverterHelper.kt | 5 +- .../ktorfit/internal/KtorfitInterface.kt | 8 ++-- .../de/jensklingenberg/ktorfit/BodyTest.kt | 2 +- .../de/jensklingenberg/ktorfit/BuilderTest.kt | 2 +- .../ktorfit/converter/ConverterFactoryTest.kt | 4 +- .../ktorfit/internal/KtorfitClientTest.kt | 6 +-- .../kotlin/com/example/api/GithubService.kt | 26 ++++++++++- .../jensklingenberg/ktorfit/demo/JvMMain.kt | 10 +++- .../ktorfit/demo/JvmPlaceHolderApi.kt | 2 +- 31 files changed, 181 insertions(+), 89 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 72e7a8fc5..ee8c4d410 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -7,6 +7,11 @@ and this project orients towards [Semantic Versioning](http://semver.org/spec/v2 Note: This project needs KSP to work and every new Ktorfit with an update of the KSP version is technically a breaking change. But there is no intent to bump the Ktorfit major version for every KSP update. +2.0.0-beta2 - 2024-05-16 +======================================== +- Build with KSP 1.0.20, Kotlin 2.0.0-RC3, Ktor 2.3.11 +- Optimize code generation + 2.0.0-beta1 - 2024-04-28 ======================================== ### Breaking Changes diff --git a/example/AndroidOnlyExample/app/src/main/java/de/jensklingenberg/androidonlyexample/MainActivity.kt b/example/AndroidOnlyExample/app/src/main/java/de/jensklingenberg/androidonlyexample/MainActivity.kt index 3c9696520..ddec5b049 100644 --- a/example/AndroidOnlyExample/app/src/main/java/de/jensklingenberg/androidonlyexample/MainActivity.kt +++ b/example/AndroidOnlyExample/app/src/main/java/de/jensklingenberg/androidonlyexample/MainActivity.kt @@ -17,6 +17,8 @@ import de.jensklingenberg.ktorfit.converter.ResponseConverterFactory import de.jensklingenberg.ktorfit.ktorfit import io.ktor.client.HttpClient import io.ktor.client.plugins.contentnegotiation.ContentNegotiation +import io.ktor.client.request.prepareRequest +import io.ktor.client.request.takeFrom import io.ktor.serialization.kotlinx.json.json import kotlinx.coroutines.launch import kotlinx.serialization.json.Json @@ -58,7 +60,12 @@ class MainActivity : ComponentActivity() { } } + + lifecycleScope.launch { + ktorfit.httpClient.prepareRequest { + this.method = io.ktor.http.HttpMethod.Post + } peopleState.value = api.getPerson(1) } } diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 497f89dda..39b8315dd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -2,16 +2,19 @@ autoService = "1.1.1" autoServiceKsp = "1.10" binaryCompatibilityValidator = "0.13.2" -coroutines = "1.7.3" -detekt = "1.23.1" +coroutines = "1.8.0" +detekt = "1.23.6" junit = "4.13.2" kctfork = "0.4.1" -kotlin = "2.0.0-RC1" +kotlin = "2.0.0-RC3" kotlinPoet = "1.16.0" -kspVersion = "2.0.0-RC1-1.0.20" -ktorfit = "2.0.0-beta1" +kspVersion = "2.0.0-RC3-1.0.20" +ktorfit = "2.0.0-beta2-SNAPSHOT" +ktorfitKsp = "2.0.0-beta2-SNAPSHOT" +ktorfitCompiler = "2.0.0-beta2-SNAPSHOT" + ktorfitGradlePlugin = "1.14.0" -ktorVersion = "2.3.10" +ktorVersion = "2.3.11" mockk = "1.13.8" mockito-kotlin = "4.1.0" gradleMavenPublishPlugin = "0.25.3" diff --git a/ktorfit-compiler-plugin/build.gradle.kts b/ktorfit-compiler-plugin/build.gradle.kts index f4e52fa41..081149c3a 100644 --- a/ktorfit-compiler-plugin/build.gradle.kts +++ b/ktorfit-compiler-plugin/build.gradle.kts @@ -21,7 +21,7 @@ licensee { } mavenPublishing { - coordinates("de.jensklingenberg.ktorfit", "compiler-plugin", libs.versions.ktorfit.get()) + coordinates("de.jensklingenberg.ktorfit", "compiler-plugin", libs.versions.ktorfitCompiler.get()) publishToMavenCentral() // publishToMavenCentral(SonatypeHost.S01) for publishing through s01.oss.sonatype.org if (enableSigning) { diff --git a/ktorfit-compiler-plugin/src/main/java/de/jensklingenberg/ktorfit/CreateFuncTransformer.kt b/ktorfit-compiler-plugin/src/main/java/de/jensklingenberg/ktorfit/CreateFuncTransformer.kt index cba537eba..c72332a4c 100644 --- a/ktorfit-compiler-plugin/src/main/java/de/jensklingenberg/ktorfit/CreateFuncTransformer.kt +++ b/ktorfit-compiler-plugin/src/main/java/de/jensklingenberg/ktorfit/CreateFuncTransformer.kt @@ -8,6 +8,7 @@ import org.jetbrains.kotlin.ir.expressions.impl.IrConstructorCallImpl import org.jetbrains.kotlin.ir.types.classFqName import org.jetbrains.kotlin.ir.types.defaultType import org.jetbrains.kotlin.ir.types.impl.originalKotlinType +import org.jetbrains.kotlin.ir.util.companionObject import org.jetbrains.kotlin.ir.util.constructors import org.jetbrains.kotlin.ir.util.isInterface import org.jetbrains.kotlin.name.ClassId @@ -73,13 +74,15 @@ class CreateFuncTransformer( ) ) ?: throw IllegalStateException(ERROR_IMPL_NOT_FOUND(argumentType.originalKotlinType.toString())) - val newConstructor = implClassSymbol.constructors.first() + val compo = implClassSymbol.owner.companionObject()!!.symbol + + val newConstructor = compo!!.constructors.first() //Create the constructor call for _ExampleApiImpl() val newCall = IrConstructorCallImpl( 0, 0, - type = implClassSymbol.defaultType, + type = compo.defaultType, symbol = newConstructor, 0, 0, diff --git a/ktorfit-compiler-plugin/src/main/java/de/jensklingenberg/ktorfit/ElementTransformer.kt b/ktorfit-compiler-plugin/src/main/java/de/jensklingenberg/ktorfit/ElementTransformer.kt index feb70214d..e3784a47e 100644 --- a/ktorfit-compiler-plugin/src/main/java/de/jensklingenberg/ktorfit/ElementTransformer.kt +++ b/ktorfit-compiler-plugin/src/main/java/de/jensklingenberg/ktorfit/ElementTransformer.kt @@ -4,9 +4,7 @@ import org.jetbrains.kotlin.backend.common.IrElementTransformerVoidWithContext import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext import org.jetbrains.kotlin.ir.IrStatement import org.jetbrains.kotlin.ir.declarations.* -import org.jetbrains.kotlin.ir.expressions.IrCall -import org.jetbrains.kotlin.ir.expressions.IrExpression -import org.jetbrains.kotlin.ir.expressions.IrFunctionExpression +import org.jetbrains.kotlin.ir.expressions.* class ElementTransformer( private val pluginContext: IrPluginContext, @@ -33,6 +31,33 @@ class ElementTransformer( return super.visitVariable(declaration) } + override fun visitBlock(expression: IrBlock): IrExpression { + expression.transform(CreateFuncTransformer(pluginContext, debugLogger), null) + return super.visitBlock(expression) + } + + override fun visitFunctionNew(declaration: IrFunction): IrStatement { + declaration.transform(CreateFuncTransformer(pluginContext, debugLogger), null) + + return super.visitFunctionNew(declaration) + } + + override fun visitExpression(expression: IrExpression): IrExpression { + expression.transform(CreateFuncTransformer(pluginContext, debugLogger), null) + + return super.visitExpression(expression) + } + + override fun visitFunctionReference(expression: IrFunctionReference): IrExpression { + expression.transform(CreateFuncTransformer(pluginContext, debugLogger), null) + + return super.visitFunctionReference(expression) + } + + override fun visitBlockBody(body: IrBlockBody): IrBody { + body.transform(CreateFuncTransformer(pluginContext, debugLogger), null) + return super.visitBlockBody(body) + } override fun visitFunctionExpression(expression: IrFunctionExpression): IrExpression { expression.transform(CreateFuncTransformer(pluginContext, debugLogger), null) diff --git a/ktorfit-compiler-plugin/src/test/kotlin/de/jensklingenberg/ktorfit/FunctionTransformerTest.kt b/ktorfit-compiler-plugin/src/test/kotlin/de/jensklingenberg/ktorfit/FunctionTransformerTest.kt index 9437eb470..918085b6f 100644 --- a/ktorfit-compiler-plugin/src/test/kotlin/de/jensklingenberg/ktorfit/FunctionTransformerTest.kt +++ b/ktorfit-compiler-plugin/src/test/kotlin/de/jensklingenberg/ktorfit/FunctionTransformerTest.kt @@ -25,14 +25,12 @@ class FunctionTransformerTest { package de.jensklingenberg.ktorfit class Ktorfit(){ - fun create(ktorfitService: KtorfitService? = null): T { + fun create(ktorfitService: ClassProvider? = null): T { return ktorfitService as T } } -interface KtorfitService - -class Default : KtorfitService +interface ClassProvider """ ) @@ -41,10 +39,12 @@ class Default : KtorfitService package com.example.api import de.jensklingenberg.ktorfit.Ktorfit - import de.jensklingenberg.ktorfit.KtorfitService + import de.jensklingenberg.ktorfit.ClassProvider interface TestService - class _TestServiceImpl : TestService, KtorfitService + class _TestServiceImpl : TestService{ + companion object : ClassProvider + } class TestClass{ val api = Ktorfit().create() @@ -69,11 +69,9 @@ package de.jensklingenberg.ktorfit class Ktorfit() -interface KtorfitService +interface ClassProvider -class Default : KtorfitService - -fun Ktorfit.create(ktorfitService: KtorfitService = Default()): T { +fun Ktorfit.create(ktorfitService: ClassProvider? = null): T { return this.create(ktorfitService) } @@ -84,10 +82,12 @@ fun Ktorfit.create(ktorfitService: KtorfitService = Default()): T { package com.example.api import de.jensklingenberg.ktorfit.Ktorfit import de.jensklingenberg.ktorfit.create - import de.jensklingenberg.ktorfit.KtorfitService + import de.jensklingenberg.ktorfit.ClassProvider interface TestService - class _TestServiceImpl : TestService, KtorfitService + class _TestServiceImpl : TestService{ + companion object : ClassProvider + } class TestClass{ diff --git a/ktorfit-gradle-plugin/build.gradle.kts b/ktorfit-gradle-plugin/build.gradle.kts index ba1bd0609..72c8ad9fb 100644 --- a/ktorfit-gradle-plugin/build.gradle.kts +++ b/ktorfit-gradle-plugin/build.gradle.kts @@ -59,7 +59,7 @@ mavenPublishing { coordinates( "de.jensklingenberg.ktorfit", "ktorfit-gradle-plugin", - libs.versions.ktorfit.get() + libs.versions.ktorfitCompiler.get() ) publishToMavenCentral() // publishToMavenCentral(SonatypeHost.S01) for publishing through s01.oss.sonatype.org diff --git a/ktorfit-gradle-plugin/src/main/java/de/jensklingenberg/ktorfit/gradle/KtorfitCompilerSubPlugin.kt b/ktorfit-gradle-plugin/src/main/java/de/jensklingenberg/ktorfit/gradle/KtorfitCompilerSubPlugin.kt index 4bfadf890..e55743424 100644 --- a/ktorfit-gradle-plugin/src/main/java/de/jensklingenberg/ktorfit/gradle/KtorfitCompilerSubPlugin.kt +++ b/ktorfit-gradle-plugin/src/main/java/de/jensklingenberg/ktorfit/gradle/KtorfitCompilerSubPlugin.kt @@ -47,7 +47,7 @@ internal class KtorfitCompilerSubPlugin : KotlinCompilerPluginSupportPlugin { return SubpluginArtifact( groupId = SERIALIZATION_GROUP_NAME, artifactId = ARTIFACT_NAME, - version = "2.0.0-beta1" // remember to bump this version before any release! + version = "2.0.0-beta2-2.0.0-RC3" // remember to bump this version before any release! ) } } diff --git a/ktorfit-ksp/build.gradle.kts b/ktorfit-ksp/build.gradle.kts index 7caa33995..cc967e9e5 100644 --- a/ktorfit-ksp/build.gradle.kts +++ b/ktorfit-ksp/build.gradle.kts @@ -27,7 +27,11 @@ tasks.withType { } mavenPublishing { - coordinates("de.jensklingenberg.ktorfit", "ktorfit-ksp", libs.versions.ktorfit.get()) + coordinates( + "de.jensklingenberg.ktorfit", + "ktorfit-ksp", + (libs.versions.ktorfitKsp.get()) + ) publishToMavenCentral() // publishToMavenCentral(SonatypeHost.S01) for publishing through s01.oss.sonatype.org if (enableSigning) { diff --git a/ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/model/ClassData.kt b/ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/model/ClassData.kt index e76576b68..b45be3fc6 100644 --- a/ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/model/ClassData.kt +++ b/ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/model/ClassData.kt @@ -3,21 +3,16 @@ package de.jensklingenberg.ktorfit.model import com.google.devtools.ksp.getDeclaredFunctions import com.google.devtools.ksp.processing.KSPLogger import com.google.devtools.ksp.processing.Resolver -import com.google.devtools.ksp.symbol.ClassKind -import com.google.devtools.ksp.symbol.KSClassDeclaration -import com.google.devtools.ksp.symbol.KSFile -import com.google.devtools.ksp.symbol.KSPropertyDeclaration -import com.google.devtools.ksp.symbol.KSTypeReference +import com.google.devtools.ksp.symbol.* import com.squareup.kotlinpoet.* +import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy import com.squareup.kotlinpoet.ksp.toKModifier import com.squareup.kotlinpoet.ksp.toTypeName import de.jensklingenberg.ktorfit.KtorfitOptions import de.jensklingenberg.ktorfit.model.KtorfitError.Companion.PROPERTIES_NOT_SUPPORTED import de.jensklingenberg.ktorfit.model.annotations.FormUrlEncoded import de.jensklingenberg.ktorfit.model.annotations.Multipart -import de.jensklingenberg.ktorfit.model.annotations.ParameterAnnotation.Field -import de.jensklingenberg.ktorfit.model.annotations.ParameterAnnotation.Part -import de.jensklingenberg.ktorfit.model.annotations.ParameterAnnotation.RequestType +import de.jensklingenberg.ktorfit.model.annotations.ParameterAnnotation.* import de.jensklingenberg.ktorfit.utils.addImports /** @@ -81,19 +76,40 @@ fun ClassData.getImplClassFileSource(resolver: Resolver, ktorfitOptions: Ktorfit val implClassName = "_${classData.name}Impl" val converterProperty = - PropertySpec.builder(converterHelper.objectName, converterHelper.toClassName()) - .addModifiers(KModifier.LATEINIT, KModifier.OVERRIDE) - .mutable(true) + PropertySpec.builder(converterHelper.objectName, converterHelper.toClassName()).initializer("KtorfitConverterHelper(_ktorfit)") + .addModifiers(KModifier.PRIVATE) .build() + val companion = TypeSpec.companionObjectBuilder() + .addSuperinterface(exampleInterface.toClassName().parameterizedBy(ClassName(classData.packageName, classData.name))) + .addFunction( + FunSpec.builder("create") + .returns(ClassName(classData.packageName, classData.name)) + .addStatement("return _${classData.name}Impl(_ktorfit)") + .addModifiers( KModifier.OVERRIDE) + .addParameter(ktorfitClass.objectName, ktorfitClass.toClassName()) + .build() + ) + .build() val implClassSpec = TypeSpec.classBuilder(implClassName) - + .primaryConstructor( + FunSpec.constructorBuilder() + .addParameter(ktorfitClass.objectName, ktorfitClass.toClassName()) + .build() + ) + .addProperty( + PropertySpec.builder("_ktorfit", ktorfitClass.toClassName()) + .initializer(ktorfitClass.objectName) + .addModifiers(KModifier.PRIVATE) + .build() + ) .addAnnotation( optinAnnotation ) + .addType(companion) .addModifiers(classData.modifiers) .addSuperinterface(ClassName(classData.packageName, classData.name)) - .addSuperinterface(ktorfitInterface.toClassName()) + //.addSuperinterface(ktorfitInterface.toClassName()) .addKtorfitSuperInterface(classData.superClasses) .addProperties(listOf(converterProperty) + properties) .addFunctions(classData.functions.map { it.toFunSpec(resolver, ktorfitOptions.setQualifiedType) }) @@ -118,7 +134,7 @@ private fun getCreateExtensionFunctionSpec( val functionName = "create${classData.name}" return FunSpec.builder(functionName) .addModifiers(classData.modifiers) - .addStatement("return this.create(_${classData.name}Impl().apply { ${converterHelper.objectName}= ${converterHelper.name}(this@$functionName) })") + .addStatement("return _${classData.name}Impl(this)") .receiver(ktorfitClass.toClassName()) .returns(ClassName(classData.packageName, classData.name)) .build() @@ -233,7 +249,7 @@ private fun TypeSpec.Builder.addKtorfitSuperInterface(superClasses: List Unit", "", "_ext") val formParameters = KtorfitClass("", "", "__formParameters") -val converterHelper = KtorfitClass("KtorfitConverterHelper","de.jensklingenberg.ktorfit.internal", "_converter") +val converterHelper = KtorfitClass("KtorfitConverterHelper","de.jensklingenberg.ktorfit.internal", "_helper") val internalApi = ClassName("de.jensklingenberg.ktorfit.internal", "InternalKtorfitApi") fun KtorfitClass.toClassName() = ClassName(packageName, name) \ No newline at end of file diff --git a/ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/reqBuilderExtension/UrlCodeGeneration.kt b/ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/reqBuilderExtension/UrlCodeGeneration.kt index c0b6dff3f..5560deb3f 100644 --- a/ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/reqBuilderExtension/UrlCodeGeneration.kt +++ b/ktorfit-ksp/src/main/kotlin/de/jensklingenberg/ktorfit/reqBuilderExtension/UrlCodeGeneration.kt @@ -20,8 +20,8 @@ fun getUrlCode(params: List, methodAnnotation: HttpMethodAnnotati "" } else { params.firstOrNull { it.hasAnnotation() }?.let { parameterData -> - "(${converterHelper.objectName}.baseUrl.takeIf{ !${parameterData.name}.startsWith(\"http\")} ?: \"\") + " - } ?: "${converterHelper.objectName}.baseUrl + " + "(${ktorfitClass.objectName}.baseUrl.takeIf{ !${parameterData.name}.startsWith(\"http\")} ?: \"\") + " + } ?: "${ktorfitClass.objectName}.baseUrl + " } params.filter { it.hasAnnotation() }.forEach { parameterData -> diff --git a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/HttpAnnotationTest.kt b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/HttpAnnotationTest.kt index 0c967f902..328de5376 100644 --- a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/HttpAnnotationTest.kt +++ b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/HttpAnnotationTest.kt @@ -96,7 +96,7 @@ interface TestService { val expectedFunctionText = """val _ext: HttpRequestBuilder.() -> Unit = { method = HttpMethod.parse("GET2") url{ - takeFrom(_converter.baseUrl + "user") + takeFrom(_ktorfit.baseUrl + "user") } setBody(body) }""" diff --git a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/QueryAnnotationsTest.kt b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/QueryAnnotationsTest.kt index 1093d40b9..bd165cb3f 100644 --- a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/QueryAnnotationsTest.kt +++ b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/QueryAnnotationsTest.kt @@ -30,7 +30,7 @@ interface TestService { ) val expectedQueriesArgumentText = "url{\n" + - " takeFrom(_converter.baseUrl + \"posts\")\n" + + " takeFrom(_ktorfit.baseUrl + \"posts\")\n" + " testQuery?.let{ parameter(\"name\", \"\$it\") }\n" + " testQuery2?.let{ encodedParameters.append(\"testQuery2\", \"\$it\") }\n" + " }" @@ -66,7 +66,7 @@ interface TestService { ) val expectedQueriesArgumentText = "url{\n" + - " takeFrom(_converter.baseUrl + \"posts\")\n" + + " takeFrom(_ktorfit.baseUrl + \"posts\")\n" + " testQuery2?.filterNotNull()?.forEach { encodedParameters.append(\"user\", \"\$it\") }\n" + " }" @@ -100,7 +100,7 @@ interface TestService { ) val expectedQueriesArgumentText = "url{\n" + - " takeFrom(_converter.baseUrl + \"posts\")\n" + + " takeFrom(_ktorfit.baseUrl + \"posts\")\n" + " parameters.appendAll(\"\$testQueryName\", emptyList())\n" + " parameters.appendAll(\"\$testQueryName2\", emptyList())\n" + " }" @@ -138,7 +138,7 @@ interface TestService { val expectedQueriesArgumentText = "url{\n" + - " takeFrom(_converter.baseUrl + \"posts\")\n" + + " takeFrom(_ktorfit.baseUrl + \"posts\")\n" + " testQueryMap?.forEach { entry -> entry.value?.let{ parameter(entry.key, \"\${entry.value}\") }\n" + " }\n" + " testQueryMap2?.forEach { entry -> entry.value?.let{ encodedParameters.append(entry.key,\n" + @@ -178,7 +178,7 @@ fun example(@Query("name") testQuery: String, @QueryName testQueryName: String, val expectedQueriesArgumentText = "url{\n" + - " takeFrom(_converter.baseUrl + \"posts\")\n" + + " takeFrom(_ktorfit.baseUrl + \"posts\")\n" + " testQuery?.let{ parameter(\"name\", \"\$it\") }\n" + " parameters.appendAll(\"\$testQueryName\", emptyList())\n" + " name?.forEach { entry -> entry.value?.let{ encodedParameters.append(entry.key,\n" + diff --git a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/RequestConverterTextKtTest.kt b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/RequestConverterTextKtTest.kt index f7a063704..75246bdf5 100644 --- a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/RequestConverterTextKtTest.kt +++ b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/RequestConverterTextKtTest.kt @@ -17,7 +17,7 @@ class RequestConverterTextKtTest { @Test fun generateCorrectFunction() { val expected = """public fun TestFunction() { - val test1: com.example.Test = _converter.convertParameterType(test1,test1::class,com.example.Test::class) + val test1: com.example.Test = _helper.convertParameterType(test1,test1::class,com.example.Test::class) } """ diff --git a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/RequestTypeTest.kt b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/RequestTypeTest.kt index 069b79353..8a027e31a 100644 --- a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/RequestTypeTest.kt +++ b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/RequestTypeTest.kt @@ -25,7 +25,7 @@ interface TestService { """ ) - val expectedFunctionSource = """val postId: Int = _converter.convertParameterType(postId,postId::class,Int::class)""" + val expectedFunctionSource = """val postId: Int = _helper.convertParameterType(postId,postId::class,Int::class)""" val compilation = getCompilation(listOf(source)) val result = compilation.compile() diff --git a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/ReturnTypeDataTest.kt b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/ReturnTypeDataTest.kt index 0179647a2..24718d414 100644 --- a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/ReturnTypeDataTest.kt +++ b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/ReturnTypeDataTest.kt @@ -32,7 +32,7 @@ interface TestService { """val _ext: HttpRequestBuilder.() -> Unit = { method = HttpMethod.parse("POST") url{ - takeFrom(_converter.baseUrl + "user") + takeFrom(_ktorfit.baseUrl + "user") } setBody(id) }""" diff --git a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/StreamingAnnotationTest.kt b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/StreamingAnnotationTest.kt index 313ea5e36..95fab46e1 100644 --- a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/StreamingAnnotationTest.kt +++ b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/StreamingAnnotationTest.kt @@ -39,7 +39,7 @@ interface TestService { ) - val expectedFunctionText = """return _converter.suspendRequest(_typeData,_ext)!!""" + val expectedFunctionText = """return _helper.suspendRequest(_typeData,_ext)!!""" val compilation = getCompilation(listOf(httpStatement, source)) val result = compilation.compile() diff --git a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/UrlTest.kt b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/UrlTest.kt index f5f62047b..c7e227b2a 100644 --- a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/UrlTest.kt +++ b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/UrlTest.kt @@ -14,7 +14,7 @@ class UrlTest { @Test fun testFunctionWithGET() { val expectedFunctionSource = """url{ - takeFrom(_converter.baseUrl + "user") + takeFrom(_ktorfit.baseUrl + "user") }""" val source = SourceFile.kotlin( @@ -63,7 +63,7 @@ interface TestService { val expectedFunctionText = """url{ - takeFrom(_converter.baseUrl + "user/$\{"$\userId".encodeURLPath()}") + takeFrom(_ktorfit.baseUrl + "user/$\{"$\userId".encodeURLPath()}") } """.replace("$\\", "$") val compilation = getCompilation(listOf(source)) @@ -102,7 +102,7 @@ interface TestService { val expectedFunctionText = """url{ - takeFrom(_converter.baseUrl + "user/$\{"$\userId".encodeURLPath()}") + takeFrom(_ktorfit.baseUrl + "user/$\{"$\userId".encodeURLPath()}") } """.replace("$\\", "$") val compilation = getCompilation(listOf(source)) @@ -124,7 +124,7 @@ interface TestService { @Test fun testFunctionWithGETAndUrlAnno() { val expectedFunctionSource = """url{ - takeFrom((_converter.baseUrl.takeIf{ !url.startsWith("http")} ?: "") + "$\{url}") + takeFrom((_ktorfit.baseUrl.takeIf{ !url.startsWith("http")} ?: "") + "$\{url}") }""".replace("$\\", "$") @@ -220,7 +220,7 @@ interface TestService { ) val expectedFunctionText = """url{ - takeFrom(_converter.baseUrl + "user/$\{"$\id"}") + takeFrom(_ktorfit.baseUrl + "user/$\{"$\id"}") }""".replace("$\\", "$") val compilation = getCompilation(listOf(source)) diff --git a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/reqBuilderExtension/UrlArgumentTextKtTest.kt b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/reqBuilderExtension/UrlArgumentTextKtTest.kt index c92db42e3..b7423e313 100644 --- a/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/reqBuilderExtension/UrlArgumentTextKtTest.kt +++ b/ktorfit-ksp/src/test/kotlin/de/jensklingenberg/ktorfit/reqBuilderExtension/UrlArgumentTextKtTest.kt @@ -17,7 +17,7 @@ class UrlArgumentTextKtTest { val params = listOf(parameterData) val text = getUrlCode(params, HttpMethodAnnotation("posts", HttpMethod.GET), "") val expected = "url{\n" + - "takeFrom(_converter.baseUrl + \"posts\")\n" + + "takeFrom(_ktorfit.baseUrl + \"posts\")\n" + "}".trimMargin() assertEquals( expected, text @@ -33,7 +33,7 @@ class UrlArgumentTextKtTest { val text = getUrlCode(params, HttpMethodAnnotation("posts", HttpMethod.GET), "") assertEquals( "url{\n" + - "takeFrom((_converter.baseUrl.takeIf{ !test1.startsWith(\"http\")} ?: \"\") + \"posts\")\n" + + "takeFrom((_ktorfit.baseUrl.takeIf{ !test1.startsWith(\"http\")} ?: \"\") + \"posts\")\n" + "}", text ) @@ -48,7 +48,7 @@ class UrlArgumentTextKtTest { val text = getUrlCode(params, HttpMethodAnnotation("", HttpMethod.GET), "") val expected = String.format( "url{\n" + - "takeFrom((_converter.baseUrl.takeIf{ !test1.startsWith(\"http\")} ?: \"\") + \"%s{test1}\")\n" + + "takeFrom((_ktorfit.baseUrl.takeIf{ !test1.startsWith(\"http\")} ?: \"\") + \"%s{test1}\")\n" + "}", "$" ) @@ -60,7 +60,7 @@ class UrlArgumentTextKtTest { val parameterData = ParameterData("test1", ReturnTypeData("String", null)) val params = listOf(parameterData) val text = getUrlCode(params, HttpMethodAnnotation("", HttpMethod.GET), "") - assertEquals("url{\ntakeFrom(_converter.baseUrl + \"\")\n}", text) + assertEquals("url{\ntakeFrom(_ktorfit.baseUrl + \"\")\n}", text) } @Test @@ -72,7 +72,7 @@ class UrlArgumentTextKtTest { val text = getUrlCode(params, HttpMethodAnnotation("user/{testValue}", HttpMethod.GET), "") assertEquals( """url{ -takeFrom(_converter.baseUrl + "user/$/{"$/test1".encodeURLPath()}") +takeFrom(_ktorfit.baseUrl + "user/$/{"$/test1".encodeURLPath()}") }""".replace("$/", "$"), text ) diff --git a/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/Ktorfit.kt b/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/Ktorfit.kt index 6caed7db8..bfdf92724 100644 --- a/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/Ktorfit.kt +++ b/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/Ktorfit.kt @@ -75,15 +75,15 @@ public class Ktorfit private constructor( /** * This will return an implementation of [T] if [T] is an interface * with Ktorfit annotations. - * @param data Please keep the default parameter, it will be replaced + * @param classProvider Please keep the default parameter, it will be replaced * by the compiler plugin */ - public fun create(data: KtorfitInterface? = null): T { - if (data == null) { + public fun create(classProvider: ClassProvider? = null): T { + + if (classProvider == null) { throw IllegalArgumentException(ENABLE_GRADLE_PLUGIN) } - data._converter = KtorfitConverterHelper(this) - return data as T + return classProvider.create(this) } diff --git a/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitConverterHelper.kt b/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitConverterHelper.kt index 0d862bbbd..7cffc3a64 100644 --- a/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitConverterHelper.kt +++ b/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitConverterHelper.kt @@ -21,7 +21,6 @@ import kotlin.reflect.cast public class KtorfitConverterHelper(private val ktorfit: Ktorfit) { private val httpClient: HttpClient = ktorfit.httpClient - public val baseUrl: String = ktorfit.baseUrl /** * This will handle all requests for functions without suspend modifier @@ -47,7 +46,7 @@ public class KtorfitConverterHelper(private val ktorfit: Ktorfit) { return if (typeIsNullable) { null } else { - throw IllegalStateException("Add a ResponseConverter for " + returnTypeData.qualifiedName + " or make function suspend") + throw IllegalStateException("Add a ResponseConverter for " + returnTypeData.typeInfo + " or make function suspend") } } @@ -79,7 +78,7 @@ public class KtorfitConverterHelper(private val ktorfit: Ktorfit) { return it.convert(result) as ReturnType? } - throw IllegalStateException("No SuspendResponseConverter found to convert ${typeData.qualifiedName}") + throw IllegalStateException("No SuspendResponseConverter found to convert ${typeData.typeInfo}") } catch (exception: Exception) { val typeIsNullable = typeData.typeInfo.kotlinType?.isMarkedNullable ?: false diff --git a/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitInterface.kt b/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitInterface.kt index b3f2d48d0..b5d1e258a 100644 --- a/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitInterface.kt +++ b/ktorfit-lib-core/src/commonMain/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitInterface.kt @@ -1,7 +1,7 @@ package de.jensklingenberg.ktorfit.internal -@OptIn(InternalKtorfitApi::class) -public interface KtorfitInterface{ - public var _converter: KtorfitConverterHelper -} +import de.jensklingenberg.ktorfit.Ktorfit +public interface ClassProvider { + public fun create(_ktorfit: Ktorfit): T +} \ No newline at end of file diff --git a/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/BodyTest.kt b/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/BodyTest.kt index 0efbe6e04..d56c306ed 100644 --- a/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/BodyTest.kt +++ b/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/BodyTest.kt @@ -38,7 +38,7 @@ class BodyTest { .build() runBlocking { - ktorfit.create(_BodyTestApiImpl()).testBody("testBody") + ktorfit.create(_BodyTestApiImpl.Companion).testBody("testBody") } } catch (ex: Exception) { diff --git a/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/BuilderTest.kt b/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/BuilderTest.kt index 5a7b19d83..61c0db1fb 100644 --- a/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/BuilderTest.kt +++ b/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/BuilderTest.kt @@ -71,7 +71,7 @@ class BuilderTest { val ktorfit = Ktorfit.Builder().baseUrl(testBaseUrl, false).httpClient(HttpClient(engine)).build() runBlocking { - ktorfit.create(_BuilderTestApiImpl()).checkIfBaseUrlIsSetWhenUrlCheckIsDisabled() + ktorfit.create(_BuilderTestApiImpl.Companion).checkIfBaseUrlIsSetWhenUrlCheckIsDisabled() } } } \ No newline at end of file diff --git a/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/converter/ConverterFactoryTest.kt b/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/converter/ConverterFactoryTest.kt index ce520e692..670349b7e 100644 --- a/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/converter/ConverterFactoryTest.kt +++ b/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/converter/ConverterFactoryTest.kt @@ -68,7 +68,7 @@ class ConverterFactoryTest { .build() runBlocking { - ktorfit.create(_ConverterFactoryTestApiImpl()).suspendClientException() + ktorfit.create(_ConverterFactoryTestApiImpl.Companion).suspendClientException() } @@ -113,7 +113,7 @@ class ConverterFactoryTest { .build() runBlocking { - ktorfit.create(_ConverterFactoryTestApiImpl()).clientException().collect() + ktorfit.create(_ConverterFactoryTestApiImpl.Companion).clientException().collect() } diff --git a/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitClientTest.kt b/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitClientTest.kt index f5c27929f..f3be2bdf5 100644 --- a/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitClientTest.kt +++ b/ktorfit-lib-core/src/jvmTest/kotlin/de/jensklingenberg/ktorfit/internal/KtorfitClientTest.kt @@ -44,7 +44,7 @@ class ClientTest { val ktorfit = Ktorfit.Builder().baseUrl(testBaseUrl).httpClient(HttpClient(engine)).build() runBlocking { - ktorfit.create(_ClientTestApiImpl()).checkCorrectHttpMethod() + ktorfit.create(_ClientTestApiImpl.Companion).checkCorrectHttpMethod() } } @@ -67,7 +67,7 @@ class ClientTest { val ktorfit = Ktorfit.Builder().baseUrl("http://www.test.de/").httpClient(client).build() runBlocking { - ktorfit.create(_ClientTestApiImpl()).converterMissing() + ktorfit.create(_ClientTestApiImpl.Companion).converterMissing() } } catch (exception: Exception) { @@ -107,7 +107,7 @@ class ClientTest { val ktorfit = Ktorfit.Builder().baseUrl("http://www.example1.com/").httpClient(HttpClient(engine)).build() try { runBlocking { - ktorfit.create(_ClientTestApiImpl()).whenUrlValueContainsBaseUrl_ThenRemoveBaseUrl() + ktorfit.create(_ClientTestApiImpl.Companion).whenUrlValueContainsBaseUrl_ThenRemoveBaseUrl() } } catch (ex: Exception) { diff --git a/sandbox/src/commonMain/kotlin/com/example/api/GithubService.kt b/sandbox/src/commonMain/kotlin/com/example/api/GithubService.kt index 3cb4897e3..0aa371dbb 100644 --- a/sandbox/src/commonMain/kotlin/com/example/api/GithubService.kt +++ b/sandbox/src/commonMain/kotlin/com/example/api/GithubService.kt @@ -4,6 +4,7 @@ import com.example.model.github.GithubFollowerResponseItem import com.example.model.github.Issuedata import com.example.model.github.TestReeeItem import de.jensklingenberg.ktorfit.Call +import de.jensklingenberg.ktorfit.Ktorfit import de.jensklingenberg.ktorfit.http.* import kotlinx.coroutines.flow.Flow @@ -24,7 +25,6 @@ interface GithubService { @POST("repos/foso/experimental/issues") suspend fun createIssue2(@Body body: Issuedata, @Header("Acci") headi: String?): Call> - @Headers( "Accept: application/vnd.github.v3+json", "Authorization: token ghp_abcdefgh", @@ -41,4 +41,26 @@ interface GithubService { @GET("repos/{owner}/{repo}/commits") fun listCommits(@Path owner: String, @Path repo: String): Flow> -} \ No newline at end of file + + // fun myTest() = "Hallo Welt!" +} + +class MyTest : GithubService{ + override suspend fun createIssue(body: Map<*, String>, headi: String?): String { + TODO("Not yet implemented") + } + + override suspend fun createIssue2(body: Issuedata, headi: String?): Call> { + TODO("Not yet implemented") + } + + override fun getFollowers(): Flow> { + TODO("Not yet implemented") + } + + override fun listCommits(owner: String, repo: String): Flow> { + TODO("Not yet implemented") + } + +} + diff --git a/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/JvMMain.kt b/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/JvMMain.kt index 0fbde3275..2ed1e5f52 100644 --- a/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/JvMMain.kt +++ b/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/JvMMain.kt @@ -2,10 +2,13 @@ package de.jensklingenberg.ktorfit.demo import com.example.UserFactory +import com.example.api.API import com.example.api.JsonPlaceHolderApi +import com.example.api._APIImpl import com.example.model.ExampleApi import com.example.model.MyOwnResponse import com.example.model.MyOwnResponseConverterFactory +import de.jensklingenberg.ktorfit.Ktorfit import de.jensklingenberg.ktorfit.converter.CallConverterFactory import de.jensklingenberg.ktorfit.converter.FlowConverterFactory import de.jensklingenberg.ktorfit.ktorfit @@ -38,6 +41,7 @@ val jvmClient = HttpClient { val jvmKtorfit = ktorfit { baseUrl(JsonPlaceHolderApi.baseUrl) httpClient(jvmClient) + } @@ -51,13 +55,13 @@ val userKtorfit = ktorfit { UserFactory(), CallConverterFactory() ) -} +}.create() fun main() { runBlocking { - val user = userKtorfit.create().getUserResponse() + val user = myOwnResponse() when (user) { is MyOwnResponse.Success -> { @@ -73,3 +77,5 @@ fun main() { } +private suspend fun myOwnResponse() = userKtorfit.getUserResponse() + diff --git a/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/JvmPlaceHolderApi.kt b/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/JvmPlaceHolderApi.kt index 8f4890924..2bdb9b061 100644 --- a/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/JvmPlaceHolderApi.kt +++ b/sandbox/src/jvmMain/kotlin/de/jensklingenberg/ktorfit/demo/JvmPlaceHolderApi.kt @@ -7,7 +7,7 @@ import de.jensklingenberg.ktorfit.Call import de.jensklingenberg.ktorfit.http.* import io.ktor.client.statement.* -interface JvmPlaceHolderApi : StarWarsApi { +internal interface JvmPlaceHolderApi : StarWarsApi { @GET("people/{id}/") suspend fun getPersonById2(@Path("id") peopleId: Int): People