Last active
August 19, 2024 15:55
-
-
Save NikolaDespotoski/5bbb254cf988a0f529a3385fc55114a7 to your computer and use it in GitHub Desktop.
KSP extensions
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.google.devtools.ksp.getClassDeclarationByName | |
import com.google.devtools.ksp.processing.Resolver | |
import com.google.devtools.ksp.symbol.* | |
/** | |
* Reified function to check if receiver [KSType] is assignable from [T] class | |
*/ | |
inline fun <reified T> KSType.isAssignableFrom(resolver: Resolver): Boolean { | |
val classDeclaration = requireNotNull(resolver.getClassDeclarationByName<T>()) { | |
"Unable to resolve ${KSClassDeclaration::class.simpleName} for type ${T::class.simpleName}" | |
} | |
return isAssignableFrom(classDeclaration.asStarProjectedType()) | |
} | |
/** | |
* Checks if [KSTypeReference] (which has to be [KSClassDeclaration]) | |
* belongs in [packageName] | |
* @param packageName package name | |
* @return true if [KSClassDeclaration] belongs to the [packageName] | |
*/ | |
fun Resolver.isFromPackage(type: KSTypeReference, packageName: String): Boolean { | |
val returnTypeClassDeclaration = type.resolve().declaration as KSClassDeclaration | |
val kotlinCollections = getKSNameFromString(packageName) | |
return kotlinCollections == returnTypeClassDeclaration.packageName | |
} | |
/** | |
* Checks if [KSTypeReference] (which has to be [KSClassDeclaration] | |
* belongs in [java.util] package | |
*/ | |
fun Resolver.isJvmCollection(type: KSTypeReference) = | |
isFromPackage(type = type, packageName = "java.util") | |
/** | |
* Checks if [KSTypeReference] (which has to be [KSClassDeclaration] | |
* belongs in [kotlin.collections] package | |
*/ | |
fun Resolver.isKtCollection(type: KSTypeReference) = | |
isFromPackage(type = type, packageName = "kotlin.collections") | |
/** | |
* Returns the parameter type of the return type of [KSClassDeclaration] | |
* e.g: In | |
* fun getAllDevices() : List<Device> | |
* | |
* will return the Device class as [KSType] | |
* @return returns parametrized type as [KSType] | |
*/ | |
fun KSFunctionDeclaration.returnTypeParametrized(resolver: Resolver): KSType { | |
val returnType = requireNotNull(returnType) { | |
"Function has no return type" | |
} | |
check(returnType.resolve().declaration.qualifiedName == resolver.builtIns.unitType) { | |
"Function ${simpleName.asString()} has kotlin.Unit type. It can't be parametrized." | |
} | |
return returnType.element!!.typeArguments.first().type!!.resolve() | |
} | |
/** | |
@returns [KSAnnotation] for typed T or null if not found | |
*/ | |
inline fun <reified T> KSDeclaration.findAnnotation(resolver: Resolver): KSAnnotation? { | |
val annotationKsName = resolver.getKSNameFromString(T::class.simpleName!!) | |
return annotations.firstOrNull { it.shortName.asString() == annotationKsName.asString() } | |
} | |
operator fun KSAnnotation.get(argumentName: String): KSValueArgument? { | |
return arguments.find { it.name?.asString() == argumentName } | |
} | |
/** | |
* @returns typed value of annotation argument | |
*/ | |
inline fun <reified V> KSAnnotation.getArgumentValue(argumentName: String): V { | |
return arguments.first { it.name?.asString() == argumentName }.value as V | |
} | |
/** | |
* @param className [ClassName] | |
* @return returns [KSAnnotation] given [ClassName] | |
*/ | |
fun KSFunctionDeclaration.getAnnotationsByClassName(className: ClassName): KSAnnotation? { | |
return annotations.find { | |
it.shortName.asString() == className.simpleName | |
&& it.annotationType.resolve().run { | |
declaration.packageName.asString() == className.packageName | |
} | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment