myotive
03/01/2022, 11:52 PM@SerializedName
annotation and Moshi’s @Json
annotation to all the properties of a data class. Everything seems to be working in my transformer (IrElementTransformerVoidWithContext
) , but the resulting class doesn’t seem to have the annotations when I try to run a unit test (which loads the class from a temp working directory).
If anyone has any documentation or resources that could help, I would be most grateful. Thanks!rnett
03/02/2022, 5:13 PMmyotive
03/02/2022, 6:50 PMpackage com.test.models
import com.example.annotations.DDJson
@DDJson
data class SampleClassModel(val sampleProperty: String)
From this class, I’m trying to produce:
@JsonClass(generateAdapter = true)
data class SampleClassModel(
@Json(name = "sample_property")
@SeralizedName(value = "sample_property")
val sampleProperty: String
)
declaration.dump()
rnett
03/02/2022, 6:52 PMmyotive
03/02/2022, 6:54 PMpublic final data class SampleClassModel public constructor(sampleProperty: kotlin.String) {
public final val sampleProperty: kotlin.String /* compiled code */
public final operator fun component1(): kotlin.String { /* compiled code */ }
}
rnett
03/02/2022, 7:55 PMComponentRegistrar
to KotlinCompilation.compilerPlugins
and didn't do anything else. Is the IR dump from the test run?myotive
03/02/2022, 8:06 PMcompilerPlugins = listOf(DDJsonComponentRegistrar())
private fun prepareCompilation(
vararg sourceFiles: SourceFile
): KotlinCompilation {
return KotlinCompilation().apply {
workingDir = temporaryFolder.root
compilerPlugins = listOf(DDJsonComponentRegistrar())
val processor = DDJsonCommandLineProcessor()
commandLineProcessors = listOf(processor)
pluginOptions =
listOf(
processor.option(KEY_ENABLED, "true"),
)
inheritClassPath = true
sources = sourceFiles.asList()
verbose = false
jvmTarget = JvmTarget.fromString(System.getenv()["ci_java_version"] ?: "1.8")!!.description
}
}
Also - yeah, the IR dump is from the test run:
override fun visitClassNew(declaration: IrClass): IrStatement {
// todo = fix this hardcoded reference
declaration.annotations = listOf(JsonClassNameAnnotation(pluginContext, declaration, true))
val propertyTransformer = PropertyTransformer()
declaration.properties.forEach {
it.transform(propertyTransformer, null)
}
....
---> println(declaration.dump())
return super.visitClassNew(declaration)
}
rnett
03/02/2022, 8:26 PMmyotive
03/02/2022, 8:38 PM@AutoService(ComponentRegistrar::class)
class DDJsonComponentRegistrar : ComponentRegistrar {
override fun registerProjectComponents(
project: MockProject,
configuration: CompilerConfiguration
) {
if (configuration[KEY_ENABLED] == false) return
val messageCollector =
configuration.get(CLIConfigurationKeys.MESSAGE_COLLECTOR_KEY, MessageCollector.NONE)
IrGenerationExtension.registerExtension(
project,
DDJsonIrGenerationExtension(messageCollector)
)
}
}
And then inside DDJsonIrGenerationExtension
, I call the transform (DDJsonIrVisitor
):
class DDJsonIrGenerationExtension(
private val messageCollector: MessageCollector,
) : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
val fqName = FqName(DDJson::class.java.canonicalName)
val ddjsonAnnotatedClass = pluginContext.referenceClass(fqName)!!
val redactedTransformer = DDJsonIrVisitor(pluginContext, ddjsonAnnotatedClass, messageCollector)
moduleFragment.transform(redactedTransformer, null)
}
}
rnett
03/02/2022, 8:47 PMmoduleFragment.transform
returns the transformed module, instead of applying it in-place. I've used redactedTransformer.lower(moduleFragment)
in the past, maybe try thatmyotive
03/02/2022, 9:17 PMlower
method on the IrElementTransformerVoidWithContext
class (redactedTransformer
is extending that). Am I using the wrong transformer?rnett
03/02/2022, 9:21 PMFileLoweringPass
myotive
03/02/2022, 9:46 PMclass DDJsonIrVisitor(
private val pluginContext: IrPluginContext,
private val ddjsonAnnotatedClass: IrClassSymbol,
private val messageCollector: MessageCollector
) : IrElementTransformerVoidWithContext(), FileLoweringPass {
...
override fun lower(irFile: IrFile) {
irFile.transformChildrenVoid()
}
}
class DDJsonIrGenerationExtension(
private val messageCollector: MessageCollector,
) : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment, pluginContext: IrPluginContext) {
val fqName = FqName(DDJson::class.java.canonicalName)
val ddjsonAnnotatedClass = pluginContext.referenceClass(fqName)!!
val ddjsonVisitor = DDJsonIrVisitor(pluginContext, ddjsonAnnotatedClass, messageCollector)
ddjsonVisitor.lower(moduleFragment)
}
}
It seems like the call to `DDJsonIrVisitor`’s lower method is happening before any of the visitClassNew
methods get called.
I found this project that was doing something similar…rnett
03/03/2022, 5:21 AMvisitPackageFragment
stuff, I would think just calling visitFile
in lower
is good enough, but idkmyotive
03/03/2022, 10:15 PM