1 package com.google.devtools.ksp.visitor 2 3 import com.google.devtools.ksp.symbol.* 4 5 open class KSValidateVisitor( 6 private val predicate: (KSNode?, KSNode) -> Boolean 7 ) : KSDefaultVisitor<KSNode?, Boolean>() { validateTypenull8 private fun validateType(type: KSType): Boolean { 9 return !type.isError && !type.arguments.any { it.type?.accept(this, null) == false } 10 } 11 defaultHandlernull12 override fun defaultHandler(node: KSNode, data: KSNode?): Boolean { 13 return true 14 } 15 visitDeclarationnull16 override fun visitDeclaration(declaration: KSDeclaration, data: KSNode?): Boolean { 17 if (!predicate(data, declaration)) { 18 return true 19 } 20 if (declaration.typeParameters.any { !it.accept(this, declaration) }) { 21 return false 22 } 23 return this.visitAnnotated(declaration, data) 24 } 25 visitDeclarationContainernull26 override fun visitDeclarationContainer(declarationContainer: KSDeclarationContainer, data: KSNode?): Boolean { 27 return declarationContainer.declarations.all { 28 !predicate(declarationContainer, it) || it.accept( 29 this, 30 declarationContainer 31 ) 32 } 33 } 34 visitTypeParameternull35 override fun visitTypeParameter(typeParameter: KSTypeParameter, data: KSNode?): Boolean { 36 return !predicate(data, typeParameter) || typeParameter.bounds.all { it.accept(this, typeParameter) } 37 } 38 visitAnnotatednull39 override fun visitAnnotated(annotated: KSAnnotated, data: KSNode?): Boolean { 40 return !predicate(data, annotated) || annotated.annotations.all { it.accept(this, annotated) } 41 } 42 visitAnnotationnull43 override fun visitAnnotation(annotation: KSAnnotation, data: KSNode?): Boolean { 44 if (!predicate(data, annotation)) { 45 return true 46 } 47 if (!annotation.annotationType.accept(this, annotation)) { 48 return false 49 } 50 if (annotation.arguments.any { !it.accept(this, it) }) { 51 return false 52 } 53 return true 54 } 55 visitTypeReferencenull56 override fun visitTypeReference(typeReference: KSTypeReference, data: KSNode?): Boolean { 57 return validateType(typeReference.resolve()) 58 } 59 visitClassDeclarationnull60 override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: KSNode?): Boolean { 61 if (classDeclaration.asStarProjectedType().isError) { 62 return false 63 } 64 if (!classDeclaration.superTypes.all { it.accept(this, classDeclaration) }) { 65 return false 66 } 67 if (!this.visitDeclaration(classDeclaration, data)) { 68 return false 69 } 70 if (!this.visitDeclarationContainer(classDeclaration, data)) { 71 return false 72 } 73 return true 74 } 75 visitFunctionDeclarationnull76 override fun visitFunctionDeclaration(function: KSFunctionDeclaration, data: KSNode?): Boolean { 77 if (function.returnType != null && 78 predicate(function, function.returnType!!) && !function.returnType!!.accept(this, data) 79 ) { 80 return false 81 } 82 if (!function.parameters.all { it.accept(this, function) }) { 83 return false 84 } 85 if (!this.visitDeclaration(function, data)) { 86 return false 87 } 88 return true 89 } 90 visitPropertyDeclarationnull91 override fun visitPropertyDeclaration(property: KSPropertyDeclaration, data: KSNode?): Boolean { 92 if (predicate(property, property.type) && !property.type.accept(this, data)) { 93 return false 94 } 95 if (!this.visitDeclaration(property, data)) { 96 return false 97 } 98 return true 99 } 100 visitValueArgumentnull101 override fun visitValueArgument(valueArgument: KSValueArgument, data: KSNode?): Boolean { 102 fun visitValue(value: Any?): Boolean = when (value) { 103 is KSType -> this.validateType(value) 104 is KSAnnotation -> this.visitAnnotation(value, data) 105 is List<*> -> value.all { visitValue(it) } 106 else -> true 107 } 108 return visitValue(valueArgument.value) 109 } 110 visitValueParameternull111 override fun visitValueParameter(valueParameter: KSValueParameter, data: KSNode?): Boolean { 112 return valueParameter.type.accept(this, valueParameter) 113 } 114 } 115