问题
I want to build an annotation processor that generates a public "non-mutable class" getter function of a private "mutable class" field (e.g. returning a LiveData
version of a MutableLiveData
field).
What I want to write:
class MyClass {
@WithGetNonMutable
private val popup: MutableLiveData<PopupTO?> = MutableLiveData()
}
What I want to generate
class MyClass {
private val popup: MutableLiveData<PopupTO?> = MutableLiveData()
fun getPopup(): LiveData<PopupTO?> = popup
}
Generating the function with the correct return type is no problem:
val liveDataType = ClassName("android.arch.lifecycle", "LiveData")
val returnType = liveDataType.parameterizedBy(genericDataType)
val function = FunSpec.builder("get${element.simpleName}")
.addModifiers(KModifier.PUBLIC)
.addStatement("return ${element.simpleName}")
.returns(returnType)
.build()
The problem is that the variable (popup
) is private - so to access it my generated function also needs to be part of that class (it can't be a simple extension function in a new file). The KotlinPoet example all write to new files - but there's no way to access the private field (or is there?) so I'd need to write the function in the actual class file? How can I achieve this?
回答1:
Annotation Processors cannot modify existing code, they can only generate new code.
That said, you could maybe modify your approach and generate an extension function instead of a member function.
- Keep your
MyClass
(withprivate
modifier changed tointernal
):
class MyClass {
@WithGetNonMutable
internal val popup: MutableLiveData<PopupTO?> = MutableLiveData()
}
- Generate a new file (within the same package), with the following contents:
fun MyClass.getPopup(): LiveData<PopupTO?> = this.popup
If you completely can't modify the MyClass
(you can't change private
to internal
), you can (it's not that elegant, but you can do it):
In the generated extension function use Reflection
to access a private field.
来源:https://stackoverflow.com/questions/53806135/kotlinpoet-add-function-to-existing-class