Created
August 29, 2013 07:00
-
-
Save svenefftinge/6374978 to your computer and use it in GitHub Desktop.
An active annotation that declares constructors delegating to super constructors.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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