Skip to content

Instantly share code, notes, and snippets.

@OdaShinsuke
Last active December 19, 2015 08:39
Show Gist options
  • Save OdaShinsuke/5927702 to your computer and use it in GitHub Desktop.
Save OdaShinsuke/5927702 to your computer and use it in GitHub Desktop.
Xtend ActiveAnnotation メソッドの事前条件埋めてみた
package contracts
import java.lang.annotation.ElementType
import java.lang.annotation.Target
import org.eclipse.xtend.lib.macro.AbstractMethodProcessor
import org.eclipse.xtend.lib.macro.Active
import org.eclipse.xtend.lib.macro.TransformationContext
import org.eclipse.xtend.lib.macro.declaration.MutableMethodDeclaration
import org.eclipse.xtend.lib.macro.declaration.Visibility
@Target(ElementType::METHOD)
@Active(typeof(PreConditionProcessor))
annotation PreCondition {
public String expression
}
class PreConditionProcessor extends AbstractMethodProcessor {
override doTransform(MutableMethodDeclaration annotatedMethod, extension TransformationContext context) {
val conditions = annotatedMethod.annotations.filter[annotationTypeDeclaration.qualifiedName == "contracts.PreCondition"];
val asserts = conditions.map[getValue("expression")]
val name = annotatedMethod.simpleName
val realMethodName = "__" + name
annotatedMethod.simpleName = realMethodName
annotatedMethod.visibility = Visibility::PRIVATE
annotatedMethod.declaringType.addMethod(name) [
docComment = annotatedMethod.docComment
returnType = annotatedMethod.returnType
for (p : annotatedMethod.parameters) {
addParameter(p.simpleName, p.type)
}
exceptions = annotatedMethod.exceptions
body = ['''
«FOR a : asserts»assert «a» : "assert error";«ENDFOR»
«IF !annotatedMethod.returnType.void»return «ENDIF»«realMethodName»(«FOR p : annotatedMethod.parameters SEPARATOR ', '»«p.simpleName»«ENDFOR»);''']
]
}
}
package contracts
import org.eclipse.xtend.core.compiler.batch.XtendCompilerTester
import org.junit.Test
class ReqMethodTest {
extension XtendCompilerTester compilerTester = XtendCompilerTester::newXtendCompilerTester(typeof(PreCondition))
@Test def void testReturn() {
'''
import contracts.PreCondition
class MyClass {
@PreCondition(expression="myParam == null")
def String doStuff(String myParam) throws IllegalArgumentException {
return myParam
}
}
'''.assertCompilesTo(
'''
import contracts.PreCondition;
@SuppressWarnings("all")
public class MyClass {
@PreCondition(expression = "myParam == null")
private String __doStuff(final String myParam) throws IllegalArgumentException {
return myParam;
}
public String doStuff(final String myParam) throws IllegalArgumentException {
assert myParam == null : "assert error";
return __doStuff(myParam);
}
}
''')
}
@Test def void testVoid() {
'''
import contracts.PreCondition
class MyClass {
@PreCondition(expression="myParam == null")
def void doStuff(String myParam) throws IllegalArgumentException {
// doSomething
}
}
'''.assertCompilesTo(
'''
import contracts.PreCondition;
@SuppressWarnings("all")
public class MyClass {
@PreCondition(expression = "myParam == null")
private void __doStuff(final String myParam) throws IllegalArgumentException {
}
public void doStuff(final String myParam) throws IllegalArgumentException {
assert myParam == null : "assert error";
__doStuff(myParam);
}
}
''')
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment