blob: d28ccb4f8191626f565ffbf38b102aa422f0d57c [file] [log] [blame]
package com.google.devtools.ksp.visitor
import com.google.devtools.ksp.ExceptionMessage
import com.google.devtools.ksp.symbol.*
class KSValidateVisitor(private val predicate: (KSNode, KSNode) -> Boolean) : KSDefaultVisitor<Unit, Boolean>() {
private fun validateDeclarations(declarationContainer: KSDeclarationContainer): Boolean {
return !declarationContainer.declarations.any { predicate(declarationContainer, it) && !it.accept(this, Unit) }
}
private fun validateTypeParameters(declaration: KSDeclaration): Boolean {
return !declaration.typeParameters.any { predicate(declaration, it) && !it.accept(this, Unit) }
}
private fun validateType(type: KSType): Boolean {
return !type.isError && !type.arguments.any { it.type?.accept(this, Unit) == false }
}
override fun defaultHandler(node: KSNode, data: Unit): Boolean {
throw IllegalStateException("unhandled validation condition, $ExceptionMessage")
}
override fun visitTypeReference(typeReference: KSTypeReference, data: Unit): Boolean {
return validateType(typeReference.resolve())
}
override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit): Boolean {
if (!validateTypeParameters(classDeclaration)) {
return false
}
if (classDeclaration.asStarProjectedType().isError) {
return false
}
if (classDeclaration.superTypes.any { predicate(classDeclaration, it) && !it.accept(this, Unit) }) {
return false
}
if (!validateDeclarations(classDeclaration)) {
return false
}
return true
}
override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: Unit): Boolean {
if (function.returnType != null && !(predicate(function, function.returnType!!) && function.returnType!!.accept(this, data))) {
return false
}
if (function.parameters.any { predicate(function, it) && !it.accept(this, Unit)}) {
return false
}
if (!validateTypeParameters(function)) {
return false
}
if (!validateDeclarations(function)) {
return false
}
return true
}
override fun visitPropertyDeclaration(property: KSPropertyDeclaration, data: Unit): Boolean {
if (predicate(property, property.type) && property.type.resolve().isError) {
return false
}
if (!validateTypeParameters(property)) {
return false
}
return true
}
override fun visitTypeParameter(typeParameter: KSTypeParameter, data: Unit): Boolean {
if (typeParameter.bounds.any { predicate(typeParameter, it) && !it.accept(this, Unit) }) {
return false
}
return true
}
override fun visitValueParameter(valueParameter: KSValueParameter, data: Unit): Boolean {
return valueParameter.type?.accept(this, Unit) != false
}
}