The whole split abstract class for different generators is nice in theory, but in reality, it is just a pain.
I have a proof of concept idea which is nearly complete.
For this to be performant, my latest changes to scalameta contrib will need to be pulled in, but this is not an issue at present.
Current
Discover generators
Match on generator type
Apply based on Input Tree Type
Proposed
Discover Generators
Match on Input tree type.
Apply ALL generators
Abort or skip if generator incompatibility is detected
How it works
My recent changes to scalameta contrib short circuit structural equality when the object is identical.
I've added a method to scalagen like withStats that can short-circuit
I'm undecided on whether we want this to be the default as it requires both Extract and Replace instances present, which is a large binary incompatibility.
It runs all generators on the input tree, in parallel.
It then checks if more then one of the incompatible generators modified the tree. (aka is not identical to the source)
If it did not abort, it will apply the transformations.
Incompatibilties
E = Extension
CE = CompanionExtension
M = Manipulation
T = Transmutation
P = Param
_
E
CE
M
T
P
E
_
X
X
CE
_
M
X
_
X
T
X
X
_
P
_
As you can see, You cannot extend and manipulate the same Tree. You can, however, replicate this behavior by choosing the order as a generator author. By calling directly into the relevant method.
Examples
// Abort - tried to manipulate class twice
class Foo extends Generator("Foo") {
def manipulate(c: Defn.Class): Defn.Class = ???
def extend(c: Defn.Class): List[Stat] = ???
}
// Success - different tree types are fine
class Foo extends Generator("Foo") {
def manipulate(c: Defn.Class): Defn.Class = ???
def extend(c: Defn.Trait): List[Stat] = ???
}
// Success - no conflict as the Companion and class are different objects
class Foo extends Generator("Foo") {
def extendCompanion(c: Defn.Class): List[Stat] = ???
def extend(c: Defn.Class): List[Stat] = ???
}
The whole split abstract class for different generators is nice in theory, but in reality, it is just a pain.
I have a proof of concept idea which is nearly complete.
For this to be performant, my latest changes to scalameta contrib will need to be pulled in, but this is not an issue at present.
Current
Proposed
How it works
Incompatibilties
E = Extension CE = CompanionExtension M = Manipulation T = Transmutation P = Param
As you can see, You cannot extend and manipulate the same Tree. You can, however, replicate this behavior by choosing the order as a generator author. By calling directly into the relevant method.
Examples