Skip to content

Commit

Permalink
Code cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
Foso committed Oct 6, 2023
1 parent 5a296c7 commit d73ca85
Show file tree
Hide file tree
Showing 15 changed files with 156 additions and 191 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ jobs:
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Build and test with Gradle
run: ./gradlew clean licensee :ktorfit-annotations:publishToMavenLocal :ktorfit-ksp:test :ktorfit-lib-common:jvmTest
run: ./gradlew licensee :ktorfit-annotations:publishToMavenLocal :ktorfit-ksp:test :ktorfit-lib-common:jvmTest :ktorfit-converters:call:publishToMavenLocal
2 changes: 1 addition & 1 deletion ktorfit-converters/call/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ licensee {
}


val enableSigning = true
val enableSigning = project.hasProperty("signingInMemoryKey")

mavenPublishing {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ public class CallConverterFactory : Converter.Factory {
?: response.body(typeData.typeArgs.first().typeInfo)
callBack.onResponse(convertedBody, response)
} catch (ex: Exception) {
println(ex)
callBack.onError(ex)
}
}
Expand All @@ -40,16 +39,6 @@ public class CallConverterFactory : Converter.Factory {
}
}

override fun responseConverter(
typeData: TypeData,
ktorfit: Ktorfit
): Converter.ResponseConverter<HttpResponse, *>? {
if (typeData.typeInfo.type == Call::class) {
return CallResponseConverter(typeData, ktorfit)
}
return null
}

private class CallSuspendResponseConverter(val typeData: TypeData, val ktorfit: Ktorfit) :
Converter.SuspendResponseConverter<HttpResponse, Call<Any?>> {
override suspend fun convert(response: HttpResponse): Call<Any?> {
Expand All @@ -72,6 +61,17 @@ public class CallConverterFactory : Converter.Factory {
}
}

override fun responseConverter(
typeData: TypeData,
ktorfit: Ktorfit
): Converter.ResponseConverter<HttpResponse, *>? {
if (typeData.typeInfo.type == Call::class) {
return CallResponseConverter(typeData, ktorfit)
}
return null
}


override fun suspendResponseConverter(
typeData: TypeData,
ktorfit: Ktorfit
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ public class FlowConverterFactory : Converter.Factory {
override fun convert(getResponse: suspend () -> HttpResponse): Flow<Any?> {
val requestType = typeData.typeArgs.first()
return flow {
try {
val response = getResponse()
if (requestType.typeInfo.type == HttpResponse::class) {
emit(response)
Expand All @@ -35,13 +34,8 @@ public class FlowConverterFactory : Converter.Factory {
typeData.typeArgs.first()
)?.convert(response)
?: response.body(typeData.typeArgs.first().typeInfo)
Response.success(convertedBody, response)

emit(convertedBody)
}
} catch (exception: Exception) {
throw exception
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@ fun ClassData.getImplClassFileSource(resolver: Resolver): String {
.addMember("InternalKtorfitApi::class")
.build()


val createExtensionFunctionSpec = getCreateExtensionFunctionSpec(classData)


val properties = classData.properties.map { property ->
val propBuilder = PropertySpec.builder(
property.simpleName.asString(),
Expand Down Expand Up @@ -108,7 +106,6 @@ fun ClassData.getImplClassFileSource(resolver: Resolver): String {
private fun getCreateExtensionFunctionSpec(
classData: ClassData
): FunSpec {

return FunSpec.builder("create${classData.name}")
.addModifiers(classData.modifiers)
.addStatement("return this.create(_${classData.name}Impl())")
Expand All @@ -125,11 +122,14 @@ private fun getCreateExtensionFunctionSpec(
*/
fun KSClassDeclaration.toClassData(logger: KSPLogger): ClassData {
val ksClassDeclaration = this
val imports = ksClassDeclaration.getFileImports().toMutableList().also {
it.add("io.ktor.util.reflect.*")
it.add("io.ktor.client.request.*")
it.add("io.ktor.http.*")
val imports = ksClassDeclaration.getFileImports().toMutableList().apply {
add("io.ktor.util.reflect.*")
add("io.ktor.client.request.*")
add("io.ktor.http.*")
add(ktorfitClass.packageName + "." + ktorfitClass.name)
add("de.jensklingenberg.ktorfit.internal.*")
}

val packageName = ksClassDeclaration.packageName.asString()
val className = ksClassDeclaration.simpleName.asString()

Expand All @@ -140,8 +140,10 @@ fun KSClassDeclaration.toClassData(logger: KSPLogger): ClassData {
return@map funcDeclaration.toFunctionData(logger)
}

if (functionDataList.any { it -> it.annotations.any { it is FormUrlEncoded || it is Multipart } ||
it.parameterDataList.any { param -> param.hasAnnotation<Field>() || param.hasAnnotation<Part>() } }) {
if (functionDataList.any { it ->
it.annotations.any { it is FormUrlEncoded || it is Multipart } ||
it.parameterDataList.any { param -> param.hasAnnotation<Field>() || param.hasAnnotation<Part>() }
}) {
imports.add("io.ktor.client.request.forms.*")
}

Expand All @@ -156,7 +158,6 @@ fun KSClassDeclaration.toClassData(logger: KSPLogger): ClassData {
}
val properties = ksClassDeclaration.getAllProperties().toList()


return ClassData(
name = className,
packageName = packageName,
Expand All @@ -165,19 +166,21 @@ fun KSClassDeclaration.toClassData(logger: KSPLogger): ClassData {
superClasses = filteredSupertypes,
properties = properties,
modifiers = ksClassDeclaration.modifiers.mapNotNull { it.toKModifier() },
ksFile = this.getKsFile()
ksFile = ksClassDeclaration.getKsFile()
)
}

private fun checkClassForErrors(ksClassDeclaration: KSClassDeclaration, logger: KSPLogger) {
val isJavaClass = ksClassDeclaration.origin.name == "JAVA"
if (isJavaClass) {
logger.error(KtorfitError.JAVA_INTERFACES_ARE_NOT_SUPPORTED, ksClassDeclaration)
return
}

val isInterface = ksClassDeclaration.classKind == ClassKind.INTERFACE
if (!isInterface) {
logger.error(KtorfitError.API_DECLARATIONS_MUST_BE_INTERFACES, ksClassDeclaration)
return
}

val hasTypeParameters = ksClassDeclaration.typeParameters.isNotEmpty()
Expand All @@ -186,10 +189,12 @@ private fun checkClassForErrors(ksClassDeclaration: KSClassDeclaration, logger:
KtorfitError.TYPE_PARAMETERS_ARE_UNSUPPORTED_ON + " ${ksClassDeclaration.simpleName.asString()}",
ksClassDeclaration
)
return
}

if (ksClassDeclaration.packageName.asString().isEmpty()) {
logger.error(KtorfitError.INTERFACE_NEEDS_TO_HAVE_A_PACKAGE, ksClassDeclaration)
return
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package de.jensklingenberg.ktorfit.model

class KtorfitError {
internal class KtorfitError {

companion object {
const val FUNCTION_OR_PARAMETERS_TYPES_MUST_NOT_INCLUDE_ATYPE_VARIABLE_OR_WILDCARD =
Expand All @@ -12,7 +12,6 @@ class KtorfitError {
const val QUERY_MAP_PARAMETER_TYPE_MUST_BE_MAP = "@QueryMap parameter type must be Map."
const val QUERY_MAP_KEYS_MUST_BE_OF_TYPE_STRING = "@QueryMap keys must be of type String:"
const val URL_PARAMETER_TYPE_MAY_NOT_BE_NULLABLE = "Url parameter type may not be nullable"

const val FIELD_MAP_PARAMETER_TYPE_MUST_BE_MAP = "@FieldMap parameter type must be Map."
const val FIELD_MAP_KEYS_MUST_BE_OF_TYPE_STRING = "@FieldMap keys must be of type String:"
const val ONLY_ONE_REQUEST_BUILDER_IS_ALLOWED = "Only one RequestBuilder is allowed."
Expand All @@ -26,22 +25,12 @@ class KtorfitError {
const val PART_PARAMETER_TYPE_MAY_NOT_BE_NULLABLE = "Part parameter type may not be nullable"
const val PATH_PARAMETER_TYPE_MAY_NOT_BE_NULLABLE = "Path parameter type may not be nullable"
const val API_DECLARATIONS_MUST_BE_INTERFACES = "API declarations must be interfaces."

const val PATH_CAN_ONLY_BE_USED_WITH_RELATIVE_URL_ON = "@Path can only be used with relative url on "
const val NON_BODY_HTTP_METHOD_CANNOT_CONTAIN_BODY = "Non-body HTTP method cannot contain @Body"
const val BODY_PARAMETERS_CANNOT_BE_USED_WITH_FORM_OR_MULTI_PART_ENCODING =
"@Body parameters cannot be used with form or multi-part encoding"
const val FOR_STREAMING_THE_RETURN_TYPE_MUST_BE_HTTP_STATEMENT =
"For streaming the return type must be io.ktor.client.statement.HttpStatement"

fun MISSING_EITHER_KEYWORD_URL_OrURL_PARAMETER(keyword: String) =
"Missing either @$keyword URL or @Url parameter"

fun NO_KTORFIT_ANNOTATION_FOUND_AT(parameterName: String): String {
return "No Ktorfit Annotation found at $parameterName"
}

fun MISSING_X_IN_RELATIVE_URL_PATH(keyword: String) = "Missing {${keyword}} in relative url path"
const val JAVA_INTERFACES_ARE_NOT_SUPPORTED = "Java Interfaces are not supported"
const val INTERFACE_NEEDS_TO_HAVE_A_PACKAGE = "Interface needs to have a package"
const val ONLY_ONE_HTTP_METHOD_IS_ALLOWED = "Only one HTTP method is allowed."
Expand All @@ -53,11 +42,13 @@ class KtorfitError {
const val MULTIPART_CAN_ONLY_BE_SPECIFIED_ON_HTTPMETHODS =
"Multipart can only be specified on HTTP methods with request body (e.g., @POST)"
const val VARARG_NOT_SUPPORTED_USE_LIST_OR_ARRAY = "vararg not supported use List or Array"
const val NULLABLE_PARAMETERS_ARE_NOT_SUPPORTED = "Nullable Parameters Are Not Supported"
fun NO_HTTP_ANNOTATION_AT(functionName: String) = "No Http annotation at $functionName"
fun URL_CAN_ONLY_BE_USED_WITH_EMPY(keyword: String) = "@Url can only be used with empty @${keyword} URL value"
const val HEADERS_VALUE_MUST_BE_IN_FORM = "@Headers value must be in the form \"Name: Value\". Found: "
const val PROPERTIES_NOT_SUPPORTED = "throw IllegalStateException(\"Properties not supported by Ktorfit\")"

fun MISSING_EITHER_KEYWORD_URL_OrURL_PARAMETER(keyword: String) = "Missing either @$keyword URL or @Url parameter"
fun NO_KTORFIT_ANNOTATION_FOUND_AT(parameterName: String): String = "No Ktorfit Annotation found at $parameterName"
fun MISSING_X_IN_RELATIVE_URL_PATH(keyword: String) = "Missing {${keyword}} in relative url path"
fun NO_HTTP_ANNOTATION_AT(functionName: String) = "No Http annotation at $functionName"
fun URL_CAN_ONLY_BE_USED_WITH_EMPY(keyword: String) = "@Url can only be used with empty @${keyword} URL value"
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
package de.jensklingenberg.ktorfit.model.annotations

enum class HttpMethod(val keyword: String) {
GET("GET"), POST("POST"), PUT("PUT"), DELETE("DELETE"), HEAD("HEAD"), PATCH("PATCH"), CUSTOM("")
GET("GET"),
POST("POST"),
PUT("PUT"),
DELETE("DELETE"),
HEAD("HEAD"),
PATCH("PATCH"),
CUSTOM("")
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,5 @@ import de.jensklingenberg.ktorfit.model.ParameterData
import de.jensklingenberg.ktorfit.model.annotations.ParameterAnnotation.Body

fun getBodyDataText(params: List<ParameterData>): String {
return params.firstOrNull { it.hasAnnotation<Body>() }?.let {
"setBody(%s)".format(it.name)
} ?: ""
return params.firstOrNull { it.hasAnnotation<Body>() }?.name?.let { "setBody($it)" } ?: ""
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ import com.google.devtools.ksp.symbol.KSType
import com.squareup.kotlinpoet.FileSpec
import de.jensklingenberg.ktorfit.model.FunctionData
import de.jensklingenberg.ktorfit.model.WILDCARDIMPORT
import de.jensklingenberg.ktorfit.model.ktorfitClass
import java.io.File

fun KSType?.resolveTypeName(): String {
//TODO: Find better way to handle type alias Types
return this.toString().removePrefix("[typealias ").removeSuffix("]")
}


inline fun <reified T> FunctionData.findAnnotationOrNull(): T? {
return this.annotations.firstOrNull { it is T } as? T
}


fun String.prefixIfNotEmpty(s: String): String {
return (s + this).takeIf { this.isNotEmpty() } ?: this
}
Expand All @@ -32,28 +29,17 @@ fun String.surroundIfNotEmpty(prefix: String = "", postFix: String = ""): String
return this.prefixIfNotEmpty(prefix).postfixIfNotEmpty(postFix)
}


fun String.surroundWith(s: String): String {
return s + this + s
}

/**
* Gets the imports of a class by reading the imports from the file
* which contains the class
* TODO: Find better way to get imports
*/
fun KSClassDeclaration.getFileImports(): List<String> {
val importList =
File(this.containingFile!!.filePath)
.readLines()
.filter { it.trimStart().startsWith("import") }
.filter { !it.startsWith("import de.jensklingenberg.ktorfit.http.") }
.toMutableSet()

importList.add(ktorfitClass.packageName + "." + ktorfitClass.name)
importList.add("de.jensklingenberg.ktorfit.internal.*")

return importList.map { it.removePrefix("import ") }
return File(this.containingFile!!.filePath)
.readLines()
.filter { it.trimStart().startsWith("import") && !it.startsWith("import de.jensklingenberg.ktorfit.http.") }
.toMutableSet()
.map { it.removePrefix("import ") }
}


Expand Down
Loading

0 comments on commit d73ca85

Please sign in to comment.