Коммит 10d7024d создал по автору Ilya Pankratov's avatar Ilya Pankratov
Просмотр файлов

Implement generation of bindings for the suspend methods

Suspend method or function is wrapped with cSuspend function that
helps to manage coroutine state.
владелец 79662e3f
/**
* SPDX-FileCopyrightText: Copyright 2025 Open Mobile Platform LLC <community@omp.ru>
* SPDX-License-Identifier: BSD-3-Clause
*/
package ru.aurora.kmp.qtbindings.ksp
import com.google.devtools.ksp.symbol.KSAnnotation
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSDeclaration
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
import com.squareup.kotlinpoet.FunSpec
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
import com.squareup.kotlinpoet.ksp.TypeParameterResolver
import com.squareup.kotlinpoet.ksp.toAnnotationSpec
import com.squareup.kotlinpoet.ksp.toClassName
import com.squareup.kotlinpoet.ksp.toTypeName
import com.squareup.kotlinpoet.ksp.toTypeParameterResolver
internal fun KSFunctionDeclaration.toCSuspendFunction(): FunSpec? {
if (!isSuspend) return null
val typeParameterResolver = typeParameterResolver()
val classDeclaration = parentDeclaration as? KSClassDeclaration
val funcName = simpleName.asString()
val funcAsyncName = "${funcName}Async"
val isMethod = classDeclaration != null
val isExtension = extensionReceiver != null
val builder = FunSpec.builder(funcAsyncName)
val returnType = cPointerClassName.parameterizedBy(kotlinCoroutineLauncherClassName).copy(false)
val parameters = parameters.map { it.toParameterSpec(typeParameterResolver) }
val parametersCode = parameters.joinToString { if (KModifier.VARARG in it.modifiers) "*%N" else "%N" }
docString?.trim()?.let { builder.addKdoc(it) }
builder.addAnnotations(annotations.filter { !it.isQtExport() }.map { it.toAnnotationSpec() }.asIterable())
builder.addAnnotation(createOptInAnnotationSpec(experimentalForeignApiClassName))
builder.addModifiers(KModifier.PUBLIC)
builder.returns(returnType)
if (isMethod) {
builder.receiver(classDeclaration.toClassName())
if (isExtension) {
val type = extensionReceiver!!.toTypeName(typeParameterResolver)
val receiverParameter = ParameterSpec.builder("receiver", type).build()
builder.addParameter(receiverParameter)
builder.addParameters(parameters)
builder.addCode(
"return %M { %N.%N(${parametersCode}) }",
cSuspendFunctionMemberName,
receiverParameter,
funcName,
*parameters.toTypedArray()
)
return builder.build()
}
} else if (isExtension) {
builder.receiver(extensionReceiver!!.toTypeName(typeParameterResolver))
}
// Cases: topLevelFunction, class method, extension function
builder.addParameters(parameters)
builder.addCode(
"return %M { %N(${parametersCode}) }",
cSuspendFunctionMemberName,
funcName,
*parameters.toTypedArray()
)
return builder.build()
}
private fun KSAnnotation.isQtExport(): Boolean {
return annotationType.resolve().toClassName() == qtExportClassName
}
private fun KSDeclaration.typeParameterResolver(): TypeParameterResolver =
typeParameters.toTypeParameterResolver(parentDeclaration?.typeParameterResolver())
/**
* SPDX-FileCopyrightText: Copyright 2025 Open Mobile Platform LLC <community@omp.ru>
* SPDX-License-Identifier: BSD-3-Clause
*/
package ru.aurora.kmp.qtbindings.ksp
import com.google.devtools.ksp.symbol.KSValueParameter
import com.squareup.kotlinpoet.KModifier
import com.squareup.kotlinpoet.ParameterSpec
import com.squareup.kotlinpoet.ksp.TypeParameterResolver
import com.squareup.kotlinpoet.ksp.toAnnotationSpec
import com.squareup.kotlinpoet.ksp.toTypeName
internal fun KSValueParameter.toParameterSpec(
typeParameterResolver: TypeParameterResolver
): ParameterSpec {
val name = name?.asString() ?: ""
val type = type.toTypeName(typeParameterResolver)
val builder = ParameterSpec.builder(name, type)
builder.addAnnotations(annotations.map { it.toAnnotationSpec() }.asIterable())
if (isVararg) {
builder.addModifiers(KModifier.VARARG)
}
return builder.build()
}
/**
* SPDX-FileCopyrightText: Copyright 2025 Open Mobile Platform LLC <community@omp.ru>
* SPDX-License-Identifier: BSD-3-Clause
*/
package ru.aurora.kmp.qtbindings.ksp
import com.squareup.kotlinpoet.AnnotationSpec
import com.squareup.kotlinpoet.TypeName
internal fun createOptInAnnotationSpec(vararg types: TypeName): AnnotationSpec {
val builder = AnnotationSpec.builder(optInClassName)
types.forEach { builder.addMember("%T::class", it) }
return builder.build()
}
\ Нет новой строки в конце файла
/**
* SPDX-FileCopyrightText: Copyright 2025 Open Mobile Platform LLC <community@omp.ru>
* SPDX-License-Identifier: BSD-3-Clause
*/
package ru.aurora.kmp.qtbindings.ksp
import com.google.devtools.ksp.symbol.KSFunctionDeclaration
import com.google.devtools.ksp.symbol.Modifier
internal val KSFunctionDeclaration.isSuspend
get() = modifiers.contains(Modifier.SUSPEND)
internal fun String.capitalizeFirstChar(): String {
return replaceFirstChar { if (it.isTitleCase()) it else it.titlecaseChar() }
}
internal fun String.lowercaseFirstChar(): String {
return replaceFirstChar { if (it.isLowerCase()) it else it.titlecaseChar() }
}
internal fun List<String>.toCamelCase(): String {
return this.mapIndexed { index, word ->
if (index == 0) word.lowercaseFirstChar() else word.capitalizeFirstChar()
}.joinToString("")
}
internal fun String.removeKotlinExtension(): String {
return this.removeSuffix(".kt")
}
Поддерживает Markdown
0% или .
You are about to add 0 people to the discussion. Proceed with caution.
Сначала завершите редактирование этого сообщения!
Пожалуйста, зарегистрируйтесь или чтобы прокомментировать