edrd
10/11/2020, 10:20 PMSymbolProcessor#init like annotation processor interfaces do? Having init and process in the same interface forces the declaration of `var`s to reference arguments from init for later usage in process. IMO a better approach would be a factory/provider interface:
// ServiceLoader would load this instead
interface SymbolProcessorFactory {
// same args passed to init
fun create(codeGenerator: CodeGenerator, ...): SymbolProcessor
}
interface SymbolProcessor {
fun process(...)
fun finish()
}
Although it would be a little more work to implement, there are some pretty concise ways of doing it:
class Processor(private val codeGenerator: CodeGenerator) : SymbolProcessor {
override fun process(...) { ... }
object Factory : SymbolProcessorFactory {
override fun create(codeGenerator: CodeGenerator, ...) = Processor(codeGenerator)
}
}
This would allow full immutability.Zac Sweers
10/12/2020, 1:18 AMlateinit var properties are effectively immutable and can be guarded with visibility if you're worried about others touching them, seems like an unnecessary amount of abstraction just to be able to use val in a class that has pretty clear guarantees about its lifecycle within the compilationedrd
10/12/2020, 1:27 PMinit won't be called more than once, which I imagine could happen when compiling multiple modules or something like that. Besides usage of var (which can be reassigned, even with lateinit), this would be a problem in case I did some heavy processing inside init, so things such as isInitialized start to appear.
The proposed abstraction would eliminate these concerns with a contract that is clear and allows immutability. Besides that, it's a common pattern to deal with runtime dependencies and avoid temporal coupling.edrd
10/12/2020, 1:32 PMedrd
10/12/2020, 1:34 PMZac Sweers
10/13/2020, 2:35 AMThe problem is that I have to read the documentation to know for sure that theIs the function being namedwon’t be called more than onceinit
init not enough context?
I think you’re overthinking this a bit. Compilers have lifecycles, I don’t think it’s unreasonable for KSP to expose those callbacks.edrd
10/16/2020, 3:33 PMclass Processor : SymbolProcessor {
private lateinit var codeGenerator: CodeGenerator
fun init(codeGenerator: CodeGenerator, ...) {
this.codeGenerator = codeGenerator
}
fun process(...) {}
}
(proposed)
class Processor(private val codeGenerator: CodeGenerator) : SymbolProcessor {
fun process(...) {}
object Provider : SymbolProcessorProvider {
override fun create(codeGenerator: CodeGenerator, ...) = Processor(codeGenerator)
}
}