1 /* 2 * Copyright 2020 Google LLC 3 * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. 4 * 5 * Licensed under the Apache License, Version 2.0 (the "License"); 6 * you may not use this file except in compliance with the License. 7 * You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package com.google.devtools.ksp.processor 19 20 import com.google.devtools.ksp.closestClassDeclaration 21 import com.google.devtools.ksp.getClassDeclarationByName 22 import com.google.devtools.ksp.processing.Resolver 23 import com.google.devtools.ksp.symbol.* 24 25 @Suppress("unused") // used by tests 26 class OverrideeProcessor : AbstractTestProcessor() { 27 private val results = mutableListOf<String>() 28 toResultnull29 override fun toResult() = results 30 31 override fun process(resolver: Resolver): List<KSAnnotated> { 32 logSubject(resolver, "NoOverride") 33 logSubject(resolver, "Subject") 34 logSubject(resolver, "JavaSubject.Subject") 35 logSubject(resolver, "lib.Subject") 36 logSubject(resolver, "ConflictingSubject1") 37 logSubject(resolver, "ConflictingSubject2") 38 logSubject(resolver, "ConflictingSubject3") 39 logSubject(resolver, "ConflictingSubject4") 40 logSubject(resolver, "OverrideOrder1") 41 logSubject(resolver, "OverrideOrder2") 42 logSubject(resolver, "JavaAccessorImpl") 43 logSubject(resolver, "JavaAnno") 44 logSubject(resolver, "JavaAnnos") 45 logSubject(resolver, "PrimaryConstructorOverride") 46 return emptyList() 47 } 48 logSubjectnull49 private fun logSubject(resolver: Resolver, qName: String) { 50 results.add("$qName:") 51 val subject = resolver.getClassDeclarationByName(qName)!! 52 subject.declarations.filterIsInstance<KSClassDeclaration>().forEach { 53 logClass(it) 54 } 55 logClass(subject) 56 } 57 logClassnull58 private fun logClass(subject: KSClassDeclaration) { 59 subject.declarations.filterIsInstance<KSPropertyDeclaration>() 60 .forEach { 61 checkOverridee(it) 62 } 63 subject.declarations.filterIsInstance<KSFunctionDeclaration>() 64 .filterNot { it.simpleName.asString() in IGNORED_METHOD_NAMES } 65 .forEach { 66 checkOverridee(it) 67 } 68 } 69 checkOverrideenull70 private fun checkOverridee(declaration: KSDeclaration) { 71 val signature = if (declaration is KSPropertyDeclaration) declaration.toSignature() else 72 (declaration as KSFunctionDeclaration).toSignature() 73 val overrideeSignature = if (declaration is KSPropertyDeclaration) declaration.findOverridee()?.toSignature() 74 else (declaration as KSFunctionDeclaration).findOverridee()?.toSignature() 75 results.add("$signature -> $overrideeSignature") 76 } 77 toSignaturenull78 private fun KSDeclaration.toSignature(): String { 79 return when (this) { 80 is KSFunctionDeclaration -> this.toSignature() 81 is KSPropertyDeclaration -> this.toSignature() 82 else -> throw IllegalStateException() 83 } 84 } 85 KSFunctionDeclarationnull86 private fun KSFunctionDeclaration.toSignature(): String { 87 val self = this 88 return buildString { 89 append(self.closestClassDeclaration()?.simpleName?.asString()) 90 append(".") 91 append(self.simpleName.asString()) 92 append( 93 self.parameters.joinToString(", ", prefix = "(", postfix = ")") { 94 "${it.name?.asString()}:${it.type.resolve().declaration.simpleName.asString()}" 95 } 96 ) 97 } 98 } 99 toSignaturenull100 private fun KSPropertyDeclaration.toSignature(): String { 101 val self = this 102 return buildString { 103 append(self.closestClassDeclaration()?.simpleName?.asString()) 104 append(".") 105 append(self.simpleName.asString()) 106 } 107 } 108 109 companion object { 110 // ignore these methods as we receive syntetics of it from compiled code 111 private val IGNORED_METHOD_NAMES = listOf("equals", "hashCode", "toString", "<init>") 112 } 113 } 114