-
Notifications
You must be signed in to change notification settings - Fork 1
Description
Macro
This is a proposal to implement a function that intercepts and apply effects in different parts of the compilation.
Motivation
Since K2 release Kotlin stabilized FIR and IR APIs so developers apply metaprogramming with compiler plugins. There're some considerations a developer should have in mind when create a compiler plugin: A basic knowledge about compilers and Kotlin compiler is necessary, compiler plugins documentation in general is poor, a good amount of code is necessary to apply simple checks or transformations in FIR / IR.
Macro functions
The proposal to mitigate these considerations is provide a function that intercepts parts of the compilation and provides a way to developers apply effects on it. Macros are declared using the annotation @Macro
:
private val FOO by diagnosticError()
@Macro
fun MacroContext.foo(klass: FirClass): MacroCompilation {
return diagnostics {
if (klass.nameOrSpecialName.identifier == "Foo") {
klass.report(FOO, "A class cannot be called Foo")
}
}
}
class Foo // Compile time error: A class cannot be called Foo
In Kotlin most of metaprogramming related solutions uses annotations as an entry point to some compile time logic, so macros support that natively:
annotation class Warning
private val WarningReport by diagnosticWarning()
@Macro(target = Warning::class)
fun MacroContext.foo(klass: FirClass): MacroCompilation {
return diagnostics {
klass.report(WarningReport, "A sample warning message")
}
}
@Warning
class Foo // Compile time warning: A sample warning message
Conventions
To create a macro, the function structure should follow some conventions:
- The function should be annotated with
@Macro
annotation - The first parameter or context should be a
MacroContext
- The second parameter should be a FIR or IR element
- The return type should be a
MacroCompilation
A macro will be created to verify those and alert developers if it breaks some convention
Macro annotation
This is the entry point to let arrow-reflection internals scans macro functions before FIR / IR extension registrations.
MacroContext
A type responsible to build a MacroCompilation
type. diagnostics {}
is an example of function provided by this type which creates a diagnostic macro compilation type.
MacroCompilation
This type is responsible to wrap some kind of effect that will be done during the compilation phase, because of this wrapping we can have a better control in how and what order this effect is applied. DiagnosticsCompilation
is one example of effect we can apply during the compilation.