Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
An active annotation that declares constructors delegating to super constructors.
package superConstr
import org.eclipse.xtend.lib.macro.AbstractClassProcessor
import org.eclipse.xtend.lib.macro.Active
import org.eclipse.xtend.lib.macro.TransformationContext
import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration
import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
import org.eclipse.xtend.lib.macro.declaration.Visibility
@Active(SuperProcessor)
annotation Super {
}
class SuperProcessor extends AbstractClassProcessor {
override doTransform(MutableClassDeclaration annotatedClass, extension TransformationContext context) {
val superClass = annotatedClass.extendedClass.type as ClassDeclaration
if (superClass == object.type) {
annotatedClass.addError("A class annotated with super must extend another class")
return;
}
val superConstructors = superClass.declaredConstructors.filter[!parameters.empty]
if (superConstructors.empty) {
annotatedClass.addWarning('''The extended class «superClass.simpleName» doesn't declare any non-default constructors.''')
return;
}
val locallyDeclaredConstructors = annotatedClass.declaredConstructors.filter[!parameters.empty]
// add contructors delegating directly to super constructors
for (superConst : superConstructors) {
annotatedClass.addConstructor[
for (param : superConst.parameters) {
addParameter(param.simpleName, param.type)
}
body = ['''
super(«superConst.parameters.map[simpleName].join(', ')»);
''']
]
}
// enhance existing constructors and add new ones
for (constructor : locallyDeclaredConstructors) {
val localParameters = constructor.parameters
val superConst = superConstructors.head
for (param : superConst.parameters) {
constructor.addParameter(param.simpleName, param.type)
}
annotatedClass.addMethod('init') [
visibility = Visibility.PRIVATE
for (param : localParameters) {
addParameter(param.simpleName, param.type)
}
body = constructor.body
]
constructor.body = ['''
super(«superConst.parameters.map[simpleName].join(', ')»);
init(«constructor.parameters.map[simpleName].join(', ')»);
''']
// now let's add constrcutors for the remaining super constructors.
for (superConstructor : superConstructors.tail) {
annotatedClass.addConstructor[
// first the locally declared params
for (param : localParameters) {
addParameter(param.simpleName, param.type)
}
// second the params from super constructor
for (param : superConstructor.parameters) {
addParameter(param.simpleName, param.type)
}
body = ['''
super(«superConstructor.parameters.map[simpleName].join(', ')»);
init(«localParameters.map[simpleName].join(', ')»);
''']
]
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.