-
Notifications
You must be signed in to change notification settings - Fork 401
Fix getJvmName for @JvmRecord data class properties #2813
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
3ea3c0e
43df4e0
3dffe96
dbcb5df
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -495,6 +495,12 @@ abstract class KSPUnitTestSuite( | |||
| runTest("$AA_PATH/jvmName.kt") | ||||
| } | ||||
|
|
||||
| @TestMetadata("jvmNameRecord.kt") | ||||
| @Test | ||||
| fun testJvmNameRecord() { | ||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be great if you could annotate the test with the ksp/kotlin-analysis-api/src/test/kotlin/com/google/devtools/ksp/test/KSPUnitTestSuite.kt Line 705 in c116b82
|
||||
| runTest("../kotlin-analysis-api/testData/jvmNameRecord.kt") | ||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You can just use |
||||
| } | ||||
|
|
||||
| @TestMetadata("lateinitProperties.kt") | ||||
| @Test | ||||
| fun testLateinitProperties() { | ||||
|
|
||||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we add a test where one of the properties of the data class is also a data class / jvm record? Also, missing copyright header :) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,64 @@ | ||
| // TEST PROCESSOR: JvmNameRecordProcessor | ||
| // EXPECTED: | ||
| // Aliased.z: z | ||
| // Couple.first: first | ||
| // Couple.second: second | ||
| // GenericRecord.g: g | ||
| // GenericRecord.h: h | ||
| // LibRecord.w: w | ||
| // NamedRecord.id: id | ||
| // NamedRecord.name: name | ||
| // Single.x: x | ||
| // WithBody.a: a | ||
| // WithBody.computed: computed | ||
| // WithBody.mutable: mutable, mutable | ||
| // WithJvmName.n: customName | ||
| // END | ||
| // JVM_TARGET: 17 | ||
| // MODULE: lib | ||
| // FILE: LibRecord.kt | ||
| @JvmRecord | ||
| data class LibRecord(val w: Int) | ||
| // MODULE: main(lib) | ||
| // FILE: records.kt | ||
| interface Named { | ||
| val name: String | ||
| } | ||
|
|
||
| interface Generic<A> { | ||
| val g: A | ||
| } | ||
|
|
||
| @JvmRecord | ||
| data class Single(val x: Int) | ||
|
|
||
| @JvmRecord | ||
| data class Couple(val first: Int, val second: String) | ||
|
|
||
| // @JvmRecord classes cannot extend other classes (they extend java.lang.Record), | ||
| // so implementing interfaces is the only supertype case. | ||
| @JvmRecord | ||
| data class NamedRecord(override val name: String, val id: Int) : Named | ||
|
|
||
| @JvmRecord | ||
| data class GenericRecord<A, B>(override val g: A, val h: B) : Generic<A> | ||
|
|
||
| // @JvmRecord constructor properties must be vals; mutable properties are only | ||
| // possible in the class body and without a backing field. | ||
| @JvmRecord | ||
| data class WithBody(val a: Int) { | ||
| val computed: Int | ||
| get() = a * 2 | ||
| var mutable: Int | ||
| get() = a | ||
| set(value) {} | ||
| } | ||
|
|
||
| // An explicit @JvmName takes precedence over the record accessor naming. | ||
| @JvmRecord | ||
| data class WithJvmName(@get:JvmName("customName") val n: Int) | ||
| // FILE: aliased.kt | ||
| import kotlin.jvm.JvmRecord as JR | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In addition to this, can we also create a test where we use a type alias for the annotation? |
||
|
|
||
| @JR | ||
| data class Aliased(val z: Int) | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missing copyright header :) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| package com.google.devtools.ksp.processor | ||
|
|
||
| import com.google.devtools.ksp.KspExperimental | ||
| import com.google.devtools.ksp.getClassDeclarationByName | ||
| import com.google.devtools.ksp.processing.Resolver | ||
| import com.google.devtools.ksp.symbol.KSAnnotated | ||
| import com.google.devtools.ksp.symbol.KSClassDeclaration | ||
|
|
||
| class JvmNameRecordProcessor : AbstractTestProcessor() { | ||
| val results = mutableListOf<String>() | ||
| override fun toResult(): List<String> { | ||
| return results | ||
|
jaschdoc marked this conversation as resolved.
|
||
| } | ||
|
|
||
| @OptIn(KspExperimental::class) | ||
| override fun process(resolver: Resolver): List<KSAnnotated> { | ||
| // getSymbolsWithAnnotation only returns symbols in the current compilation, | ||
| // so the record class from the library module is looked up explicitly. | ||
| val sourceRecords = resolver.getSymbolsWithAnnotation("kotlin.jvm.JvmRecord") | ||
| .filterIsInstance<KSClassDeclaration>() | ||
| val libRecords = listOfNotNull(resolver.getClassDeclarationByName("LibRecord")) | ||
| (sourceRecords + libRecords) | ||
| .flatMap { cls -> | ||
| cls.getAllProperties().map { property -> | ||
| val accessorNames = listOfNotNull( | ||
| property.getter?.let { resolver.getJvmName(it) }, | ||
| property.setter?.let { resolver.getJvmName(it) }, | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think we should also get the jvm name of the setter parameter. |
||
| ) | ||
| "${cls.simpleName.asString()}.${property.simpleName.asString()}: ${accessorNames.joinToString()}" | ||
| } | ||
| } | ||
| .sorted() | ||
| .let { results.addAll(it) } | ||
| return emptyList() | ||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please revert this :)