Skip to content

Instantly share code, notes, and snippets.

@svenefftinge
Created August 29, 2013 07:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save svenefftinge/6374978 to your computer and use it in GitHub Desktop.
Save svenefftinge/6374978 to your computer and use it in GitHub Desktop.
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