Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 11 additions & 3 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -55,14 +55,19 @@ The form of the test itself is flexible as long as the logic is covered.
> [!NOTE]
> The `test-utils` directory is deprecated. Unit tests should be placed in `kotlin-analysis-api`.

Here are some [sample test processors](compiler-plugin/src/test/kotlin/com/google/devtools/ksp/processor) for your reference.
Here are some [sample test processors](kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/processor) for your reference.

#### Steps for writing a test
* KSP needs to be built with JDK 11+, because of test dependencies.
* Create a test processor under the sample processor folder.
* Write your logic by overriding corresponding functions.
* Test is performed by running test processor and getting a collection of test results in the form of `List<String>`.
* Make sure you override `toResult()` function to collect test results.
* [required] Ensure your test processor is in the package `com.google.devtools.ksp.processor`.
* [required] The test processor must extend the `AbstractTestProcessor` class.
* [required] Make sure you override `toResult()` function to collect test results.
* [required] The test processor must have a constructor parameter of type boolean.
Specifically, it must override the `enableNewFeatures` property in `AbstractTestProcessor`.
In other words, the constructor parameter list must be as follows: `class MyProcessor(override val enableNewFeatures: Boolean)`.
* Leverage visitors for easy traversal of the test case.
* To help with easy testing, you can create an annotation for test, and annotate the specific part of the code to avoid doing excess filtering when traveling along the program.
* Write your test case to work with the test processor.
Expand All @@ -74,6 +79,7 @@ Here are some [sample test processors](compiler-plugin/src/test/kotlin/com/googl
* [optional] Add `// PROCESSOR INPUT: <input/predicate>` to specify inputs or predicates for the test processor (e.g. `// PROCESSOR INPUT: Anno` or `// PROCESSOR INPUT: kotlin.annotation.Retention, kotlin.annotation.Target`, as in [`aliasedAnnotation.kt`](kotlin-analysis-api/testData/getSymbolsWithAnnotation/aliasedAnnotation.kt)).
Note: for a processor to accept input, its constructor must have a single `List<String>` parameter.
This is a handy way of writing a parametric test processor.
The `List<String>` parameter list must come before the `enableNewFeatures` property.
* Immediately after the test processor line(s), start your expected result lines. Every line should start with `// ` (with a space after `//`).
* Add `// END` to indicate the end of expected test results.
* Then follows the virtual files section till the end of the test file.
Expand All @@ -83,7 +89,9 @@ Here are some [sample test processors](compiler-plugin/src/test/kotlin/com/googl
* Annotate the test with `@Bug` and `@BugState`.
* The `@Bug` annotation requires a link to an open or existing GitHub issue (e.g., `@Bug("https://github.com/google/ksp/issues/<issue_number>", BugState.OPEN)`).
* Use the `@Negative` marker annotation if applicable.
* Run generated tests with `:compiler-plugin:test` and `:kotlin-analysis-api:test` gradle tasks.
* Run generated tests with the `:kotlin-analysis-api:test` gradle task.
* This will execute all tests in the KSP test suite. To run your test only, specify the test name with
`--tests "com.google.devtools.ksp.test.KSPUnitTestSuite.<name of your test>"`
* Make sure your change is not breaking any existing test as well :).
* [optional] You can run the `./gradlew check` task as well to run all tests.
* This task runs all integration tests as well, so it might take a while to complete.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

class AnnotationArrayValueTypeProcessor : AbstractTestProcessor() {
class AnnotationArrayValueTypeProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
private val results = mutableListOf<String>()

override fun process(resolver: Resolver): List<KSAnnotated> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import com.google.devtools.ksp.symbol.Location
import com.google.devtools.ksp.symbol.NonExistLocation
import com.google.devtools.ksp.visitor.KSTopDownVisitor

class AnnotationsInDependenciesProcessor : AbstractTestProcessor() {
class AnnotationsInDependenciesProcessor(override val enableNewFeatures: Boolean) : AbstractTestProcessor() {
private val results = mutableListOf<String>()
override fun toResult() = results

Expand Down Expand Up @@ -69,7 +69,7 @@ class AnnotationsInDependenciesProcessor : AbstractTestProcessor() {
private fun collectAnnotations(resolver: Resolver, qName: String): Map<KSAnnotated, List<KSAnnotation>> {
val output = mutableMapOf<KSAnnotated, List<KSAnnotation>>()
resolver.getClassDeclarationByName(qName)?.accept(
AnnotationVisitor(),
AnnotationVisitor(enableNewFeatures),
output
)
return output
Expand All @@ -83,6 +83,7 @@ class AnnotationsInDependenciesProcessor : AbstractTestProcessor() {
is KSValueParameter -> name?.let {
"parameter ${it.asString()} ${this.location.lineNumber}"
} ?: "no-name-value-parameter ${this.location.lineNumber}"

is KSPropertyGetter -> "getter of ${receiver.toSignature()}" // lineNumber handled by recursive call
is KSPropertySetter -> "setter of ${receiver.toSignature()}" // lineNumber handled by recursive call
is KSBackingField -> "field of ${property.toSignature()}" // lineNumber handled by recursive call
Expand All @@ -108,7 +109,8 @@ class AnnotationsInDependenciesProcessor : AbstractTestProcessor() {
is NonExistLocation -> "<no line>"
}

class AnnotationVisitor : KSTopDownVisitor<MutableMap<KSAnnotated, List<KSAnnotation>>, Unit>() {
class AnnotationVisitor(enableNewFeatures: Boolean) :
KSTopDownVisitor<MutableMap<KSAnnotated, List<KSAnnotation>>, Unit>(enableNewFeatures) {
override fun defaultHandler(node: KSNode, data: MutableMap<KSAnnotated, List<KSAnnotation>>) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.google.devtools.ksp.impl.symbol.kotlin.KSTypeImpl
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

class DefaultKClassValueProcessor : AbstractTestProcessor() {
class DefaultKClassValueProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

class EnumModifierProcessor(val declarationNames: List<String>) : AbstractTestProcessor() {
class EnumModifierProcessor(val declarationNames: List<String>, override val enableNewFeatures: Boolean) : AbstractTestProcessor() {
private val result: MutableList<String> = mutableListOf()

override fun toResult(): List<String> = result.sorted()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ import com.google.devtools.ksp.symbol.KSNode
import com.google.devtools.ksp.symbol.KSTypeReference
import com.google.devtools.ksp.visitor.KSTopDownVisitor

open class EquivalentJavaWildcardProcessor : AbstractTestProcessor() {
open class EquivalentJavaWildcardProcessor(override val enableNewFeatures: Boolean) : AbstractTestProcessor() {
val results = mutableListOf<String>()

@OptIn(KspExperimental::class)
override fun process(resolver: Resolver): List<KSAnnotated> {
resolver.getNewFiles().forEach {
resolver.getNewFiles().forEach {
it.accept(RefVisitor(results, resolver), "")
it.accept(RefVisitor(results, resolver, enableNewFeatures), "")
}
}

Expand All @@ -43,10 +43,8 @@ open class EquivalentJavaWildcardProcessor : AbstractTestProcessor() {
return results
}

private class RefVisitor(
val results: MutableList<String>,
val resolver: Resolver
) : KSTopDownVisitor<String, Unit>() {
private class RefVisitor(val results: MutableList<String>, val resolver: Resolver, enableNewFeatures: Boolean) :
KSTopDownVisitor<String, Unit>(enableNewFeatures) {
override fun defaultHandler(node: KSNode, data: String) = Unit

private fun KSTypeReference.pretty(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSFile
import com.google.devtools.ksp.symbol.KSNode

class ExplicitBackingFieldsSubtypingProcessor : AbstractTestProcessor() {
class ExplicitBackingFieldsSubtypingProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

class GetDeclarationsProcessor(val declarationNames: List<String>) : AbstractTestProcessor() {
class GetDeclarationsProcessor(val declarationNames: List<String>, override val enableNewFeatures: Boolean) : AbstractTestProcessor() {
private val result = mutableListOf<String>()

override fun toResult(): List<String> = result
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSFile
import com.google.devtools.ksp.symbol.KSNode

class GetSymbolsWithAnnotationProcessor(val annotationNames: List<String>) : AbstractTestProcessor() {
class GetSymbolsWithAnnotationProcessor(val annotationNames: List<String>, override val enableNewFeatures: Boolean) : AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ package com.google.devtools.ksp.processor
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*

class HelloProcessor : AbstractTestProcessor() {
class HelloProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()
val visitor = HelloVisitor()

Expand All @@ -35,7 +35,7 @@ class HelloProcessor : AbstractTestProcessor() {
return results.sorted()
}

inner class HelloVisitor : KSVisitorVoid() {
inner class HelloVisitor : KSVisitorVoid(enableNewFeatures) {
override fun visitClassDeclaration(classDeclaration: KSClassDeclaration, data: Unit) {
results.add(classDeclaration.qualifiedName?.asString() ?: "<error>")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSDeclaration
import com.google.devtools.ksp.symbol.KSPropertyDeclaration

class ImplicitElementProcessor : AbstractTestProcessor() {
class ImplicitElementProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val result: MutableList<String> = mutableListOf()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.google.devtools.ksp.getDeclaredProperties
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

class JavaBackingFieldProcessor : AbstractTestProcessor() {
class JavaBackingFieldProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSClassDeclaration

class JavaModifierJvmStaticAnnotationProcessor(val classNames: List<String>) : AbstractTestProcessor() {
class JavaModifierJvmStaticAnnotationProcessor(val classNames: List<String>, override val enableNewFeatures: Boolean) :
AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import com.google.devtools.ksp.symbol.*
import com.google.devtools.ksp.symbol.KSPropertyDeclaration
import com.google.devtools.ksp.visitor.KSTopDownVisitor

class JavaModifierProcessor : AbstractTestProcessor() {
class JavaModifierProcessor(override val enableNewFeatures: Boolean) : AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down Expand Up @@ -59,7 +59,7 @@ class JavaModifierProcessor : AbstractTestProcessor() {
return emptyList()
}

inner class ModifierVisitor(val resolver: Resolver) : KSTopDownVisitor<Unit, Unit>() {
inner class ModifierVisitor(val resolver: Resolver) : KSTopDownVisitor<Unit, Unit>(enableNewFeatures) {
override fun defaultHandler(node: KSNode, data: Unit) {
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*
import com.google.devtools.ksp.visitor.KSTopDownVisitor

open class JavaWildcard2Processor : AbstractTestProcessor() {
open class JavaWildcard2Processor(override val enableNewFeatures: Boolean) : AbstractTestProcessor() {
val results = mutableListOf<String>()

@OptIn(KspExperimental::class)
override fun process(resolver: Resolver): List<KSAnnotated> {
resolver.getNewFiles().forEach {
resolver.getNewFiles().forEach {
it.accept(RefVisitor(results, resolver), "")
it.accept(RefVisitor(results, resolver, enableNewFeatures), "")
}
}

Expand All @@ -40,10 +40,8 @@ open class JavaWildcard2Processor : AbstractTestProcessor() {
return results
}

private class RefVisitor(
val results: MutableList<String>,
val resolver: Resolver
) : KSTopDownVisitor<String, Unit>() {
private class RefVisitor(val results: MutableList<String>, val resolver: Resolver, enableNewFeatures: Boolean) :
KSTopDownVisitor<String, Unit>(enableNewFeatures) {
override fun defaultHandler(node: KSNode, data: String) = Unit

private fun KSTypeReference.pretty(): String {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.google.devtools.ksp.KspExperimental
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*

class NativePackageDeclarationProcessor(val packageNames: List<String>) : AbstractTestProcessor() {
class NativePackageDeclarationProcessor(val packageNames: List<String>, override val enableNewFeatures: Boolean) : AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.google.devtools.ksp.getDeclaredProperties
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

class NestedAnnotationProcessor : AbstractTestProcessor() {
class NestedAnnotationProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val result = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.google.devtools.ksp.getDeclaredFunctions
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

class ParentOfJavaMethodOverridingKotlinPropertyProcessor : AbstractTestProcessor() {
class ParentOfJavaMethodOverridingKotlinPropertyProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
private val result = mutableListOf<String>()

override fun process(resolver: Resolver): List<KSAnnotated> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.google.devtools.ksp.impl.ResolverAAImpl
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*

class RecordJavaAsMemberOfProcessor : AbstractTestProcessor() {
class RecordJavaAsMemberOfProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.google.devtools.ksp.impl.ResolverAAImpl
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*

class RecordJavaGetAllMembersProcessor : AbstractTestProcessor() {
class RecordJavaGetAllMembersProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.google.devtools.ksp.impl.ResolverAAImpl
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*

class RecordJavaOverridesProcessor : AbstractTestProcessor() {
class RecordJavaOverridesProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*
import com.google.devtools.ksp.validate

class RecordJavaProcessor : AbstractTestProcessor() {
class RecordJavaProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import com.google.devtools.ksp.impl.ResolverAAImpl
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.*

class RecordJavaSupertypesProcessor : AbstractTestProcessor() {
class RecordJavaSupertypesProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand All @@ -33,7 +33,7 @@ class RecordJavaSupertypesProcessor : AbstractTestProcessor() {
override fun process(resolver: Resolver): List<KSAnnotated> {
val types = mutableSetOf<KSType>()
resolver.getAllFiles().forEach {
it.accept(TypeCollectorNoAccessor(), types)
it.accept(TypeCollectorNoAccessor(enableNewFeatures), types)
}
types.forEach {
resolver.builtIns.anyType.isAssignableFrom(it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSAnnotation
import com.google.devtools.ksp.symbol.KSPropertyDeclaration

class TypeAnnotationClassReferenceProcessor : AbstractTestProcessor() {
class TypeAnnotationClassReferenceProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
private val results = mutableListOf<String>()

override fun process(resolver: Resolver): List<KSAnnotated> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import com.google.devtools.ksp.getClassDeclarationByName
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.symbol.KSAnnotated

class ValueParameterProcessor : AbstractTestProcessor() {
class ValueParameterProcessor(override val enableNewFeatures: Boolean): AbstractTestProcessor() {
val results = mutableListOf<String>()

override fun toResult(): List<String> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ package com.google.devtools.ksp.test
import org.jetbrains.kotlin.test.TestMetadata
import org.junit.jupiter.api.Test

class AAConfiguredUnitTestSuite : KSPUnitTestSuite(experimentalPsiResolution = false) {
abstract class AAConfiguredUnitTestSuiteBase(
enableNewFeatures: Boolean
) : KSPUnitTestSuite(experimentalPsiResolution = false, enableNewFeatures) {

@TestMetadata("getSymbolsWithAnnotation/aliasedAnnotation.kt")
@Test
Expand Down Expand Up @@ -58,3 +60,7 @@ class AAConfiguredUnitTestSuite : KSPUnitTestSuite(experimentalPsiResolution = f
runTest("$AA_PATH/javaSubtypeOfKotlinInterface.kt")
}
}

class AAConfiguredUnitTestSuite : AAConfiguredUnitTestSuiteBase(enableNewFeatures = false)

class AAConfiguredNewFeaturesUnitTestSuite : AAConfiguredUnitTestSuiteBase(enableNewFeatures = true)
Loading
Loading