creating astts the painful truth

Post on 14-Apr-2017

777 Views

Category:

Software

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1

2

3 . 1

3 . 1

3 . 1

… …

3 . 1

3 . 2

4 . 1

4 . 1

4 . 1

4 . 1

4 . 2

5

5

5

5

6 . 1

6 . 2

6 . 3

6 . 3

6 . 3

6 . 4

6 . 5

6 . 6

6 . 7

⇒1==1

6 . 8

⇒1==1

6 . 8

⇒1==1

6 . 8

⇒1==1

6 . 8

⇒ ⇒ref.myMethod(3)

6 . 9

⇒ ⇒ref.myMethod(3)

6 . 9

⇒ ⇒ref.myMethod(3)

6 . 9

⇒ ⇒ref.myMethod(3)

6 . 9

6 . 10

if(booleanExpression){println"hello"//statement}

6 . 11

if(booleanExpression){println"hello"//statement}

6 . 11

if(booleanExpression){println"hello"//statement}

6 . 11

publicvoidmain(String[]args){//blockstarts//thisisinsideablockstatement}//blockends

6 . 12

publicvoidmain(String[]args){//blockstarts//thisisinsideablockstatement}//blockends

6 . 12

publicvoidmain(String[]args){//blockstarts//thisisinsideablockstatement}//blockends

6 . 12

publicStringgreetings(){return"HelloGreach"}

6 . 13

6 . 14

6 . 15

6 . 15

6 . 15

6 . 15

6 . 15

6 . 15

classA{//ClassNodeStringgreetings//FieldNode

Stringhello(){//MethodNode

}}

6 . 16

classA{//ClassNode

Stringhello()//MethodNode{//blockStatement{

return"Hello"//returnStatement(constantExpression)

}//}}

6 . 17

7 . 1

7 . 2

7 . 3

7 . 3

7 . 3

7 . 5

7 . 5

7 . 5

7 . 6

8 . 1

8 . 2

8 . 3

8 . 4

8 . 5

8 . 6

9

10 . 1

10 . 2

10 . 3

10 . 5

10 . 5

10 . 5

10 . 5

11 . 1

packagegreach.local

classA{@WithLoggingvoiddoSomething(){//println"StartingdoSomething"

println"mystuff"

//println"EndingdoSomething"}}

11 . 2

11 . 3

11 . 3

11 . 3

11 . 4

11 . 4

11 . 4

packagegreach.local

importorg.codehaus.groovy.transform.GroovyASTTransformationClassimportjava.lang.annotation.*

(1)@Retention(RetentionPolicy.SOURCE)@Target([ElementType.METHOD])(2)@GroovyASTTransformationClass(["greach.local.WithLoggingExplainedTransformation"])@interfaceWithLoggingExplained{}

11 . 5

11 . 6

importorg.codehaus.groovy.ast.expr.*

importorg.codehaus.groovy.ast.stmt.*

importorg.codehaus.groovy.ast.*

importorg.codehaus.groovy.transform.*

11 . 7

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classWithLoggingExplainedTransformationimplementsASTTransformation{

11 . 8

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classWithLoggingExplainedTransformationimplementsASTTransformation{

11 . 8

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classWithLoggingExplainedTransformationimplementsASTTransformation{

11 . 8

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classWithLoggingExplainedTransformationimplementsASTTransformation{

11 . 8

@Overridevoidvisit(ASTNode[]nodes,SourceUnitsourceUnit){MethodNodemethod=(MethodNode)nodes[1](1)

defstartMessage=createPrintlnAst("Starting$method.name")defendMessage=createPrintlnAst("Ending$method.name")

defexistingStatements=((BlockStatement)method.code).statements(2)existingStatements.add(0,startMessage)existingStatements.add(endMessage)

}

11 . 9

11 . 10

11 . 10

11 . 10

privatestaticStatementcreatePrintlnAst(Stringmessage){newExpressionStatement(newMethodCallExpression(newVariableExpression("this"),newConstantExpression("println"),newArgumentListExpression(newConstantExpression(message))))}

11 . 11

11 . 12

11 . 12

11 . 12

12 . 1

12 . 2

12 . 3

importstaticorg.codehaus.groovy.ast.tools.GeneralUtils.*

12 . 4

12 . 5

12 . 5

12 . 5

privatestaticStatementcreatePrintlnAst(Stringmessage){newExpressionStatement(newMethodCallExpression(newVariableExpression("this"),newConstantExpression("println"),newArgumentListExpression(newConstantExpression(message))))}

12 . 6

privatestaticStatementcreatePrintlnAst(Stringmessage){returnstmt(callThisX("println",args(constX(message))))}

12 . 7

privatestaticStatementcreatePrintlnAst(Stringmessage){newExpressionStatement(newMethodCallExpression(newVariableExpression("this"),newConstantExpression("println"),newArgumentListExpression(newConstantExpression(message))))}

privatestaticStatementcreatePrintlnAst(Stringmessage){returnstmt(callThisX("println",args(constX(message))))}

12 . 8

12 . 9

12 . 10

BlockStatementgetBlockStmt(){ASTNode[]stmts=newAstBuilder().buildFromCode{returnnumber%2==0}

returnstmts.first()asBlockStatement}

12 . 11

BlockStatementgetMD5Code(finalStringpropertyName){defblockStatement=newAstBuilder().buildFromString"""java.security.MessageDigest.getInstance('MD5').digest(${propertyName}.getBytes('UTF-8')).encodeHex().toString()"""

returnblockStatement.first()asBlockStatement}

12 . 12

12 . 13

13 . 1

@GroovyASTTransformation(phase=CompilePhase.INSTRUCTION_SELECTION)classPlayAstextendsExceptionFriendlyAst{

staticfinalPLAY_METHOD_NAME="play"staticfinalPLAY_METHOD_PARAM_NAME="params"

/*WeneedtoinjectaDataFlowsinstanceinavariablecalled"flow"*/voidprocessNodes(ASTNode[]astNodes,SourceUnitsourceUnit){/*Checkingconstraints*/if(!astNodes)returnif(!astNodes[0]||!astNodes[1])returnif(!(astNodes[0]instanceofAnnotationNode))returnif(astNodes[0].classNode?.name!=Play.class.name)returnif(!(astNodes[1]instanceofMethodNode))return

13 . 2

……

packagegreach.builder

classOrder{@ToMD5Stringname@ToMD5Stringdescription}

Orderorder=newOrder(name:"john",description:"desc")

assertorder.nameToMD5()=="527bd5b5d689e2c32ae974c6229ff785"assertorder.descriptionToMD5()=="1dee80c7d5ab2c1c90aa8d2f7dd47256"

13 . 3

@CompileStatic@LocalTransformation(A.PHASE_LOCAL.INSTRUCTION_SELECTION)classToMD5ImplextendsLocalTransformationImpl<ToMD5,FieldNode>{

@OverridevoiddoVisit(AnnotationNodeannotation,FieldNodefieldNode,SourceUnitsourceUnit){MethodNodemd5Method=getMD5Method(fieldNode.name)

fieldNode.declaringClass.addMethod(md5Method)}

13 . 4

@GroovyASTTransformation(phase=CompilePhase.CANONICALIZATION)classMacroExpandAstextendsAbstractASTTransformation{

voidvisit(ASTNode[]nodes,SourceUnitsourceUnit){sourceUnit.AST.classes.each{ClassNodeclassNode->newMacroExpandTransformer().visitClass(classNode)}}

}

13 . 5

13 . 6

13 . 7

classMacroExpandTransformerextendsClassCodeExpressionTransformer{

privateSourceUnitsourceUnit

MacroExpandTransformer(SourceUnitsourceUnit){//PASSINGSOURCEUNITthis.sourceUnit=sourceUnit}

publicExpressiontransform(Expressionexpression){//CHECKINGAGAINif(expressioninstanceofMethodCallExpression&&expression.methodAsString=='let'){//CASTINGSMethodCallExpressionmethodCallExpression=(MethodCallExpression)expression

13 . 8

@GlobalTransformation(A.PHASE_GLOBAL.SEMANTIC)classAddTransformationextendsGlobalTransformationImpl{

List<Class<Transformer>>getTransformers(){return[AddPropertyTransformer,AddMethodTransformer]}}

13 . 9

classChangeTripleXToPlusOneextendsExpressionTransformer<MethodCallExpression>{

ChangeTripleXToPlusOne(finalSourceUnitsourceUnit){super(sourceUnit,methodCallByNameEq('xxx'))}

ExpressiontransformExpression(finalMethodCallExpressiontarget){returnA.EXPR.constX(1)}}

13 . 10

classChangeTripleXToPlusOneextendsExpressionTransformer<MethodCallExpression>{

ChangeTripleXToPlusOne(finalSourceUnitsourceUnit){super(sourceUnit,methodCallByNameEq('xxx'))}

ExpressiontransformExpression(finalMethodCallExpressiontarget){returnA.EXPR.constX(1)}}

13 . 10

classChangeTripleXToPlusOneextendsExpressionTransformer<MethodCallExpression>{

ChangeTripleXToPlusOne(finalSourceUnitsourceUnit){super(sourceUnit,methodCallByNameEq('xxx'))}

ExpressiontransformExpression(finalMethodCallExpressiontarget){returnA.EXPR.constX(1)}}

13 . 10

14 . 1

14 . 2

packagegreach.builder

importorg.codehaus.groovy.transform.GroovyASTTransformationClass

importjava.lang.annotation.ElementTypeimportjava.lang.annotation.Retentionimportjava.lang.annotation.RetentionPolicyimportjava.lang.annotation.Target

@Retention(RetentionPolicy.SOURCE)@Target([ElementType.TYPE])@GroovyASTTransformationClass(["greach.builder.EvenCheckerImpl"])@interfaceEvenCheckerJava{}

14 . 3

packagegreach.builder

importasteroid.local.Local

@Local(EvenCheckerImpl)@interfaceEvenChecker{}

14 . 4

packagegreach.builder

importasteroid.local.Local

@Local(EvenCheckerImpl)@interfaceEvenChecker{}

14 . 4

packagegreach.builder

importasteroid.local.Local

@Local(EvenCheckerImpl)@interfaceEvenChecker{}

14 . 4

14 . 5

14 . 6

packagegreach.meta

importgroovy.transform.ToStringimportgroovy.transform.AnnotationCollector

@ToJson@ToString@AnnotationCollector@interfaceToEverything{}

14 . 7

packagegreach.meta

@ToEverythingclassA{Stringname}

AaInstance=newA()

assertaInstance.toJson()assertaInstance.toString()

14 . 8

packagegreach.meta

@ToEverythingclassA{Stringname}

AaInstance=newA()

assertaInstance.toJson()assertaInstance.toString()

14 . 8

packagegreach.meta

@ToEverythingclassA{Stringname}

AaInstance=newA()

assertaInstance.toJson()assertaInstance.toString()

14 . 8

15 . 1

@CompileStatic@LocalTransformation(A.PHASE_LOCAL.INSTRUCTION_SELECTION)classSerializableImplextendsLocalTransformationImpl<Serializable,ClassNode>{@OverridevoiddoVisit(AnnotationNodeannotation,ClassNodeclassNode,SourceUnitsource){check:'packagestartswithasteroid'classNode.packageName.startsWith('asteroid')

check:'thereareatmost2methods'classNode.methods.size()<3

then:'makeitimplementsSerializableandCloneable'addInterfaces(classNode,java.io.Serializable,Cloneable)}}

15 . 2

15 . 3

15 . 4

@ASTTest({assertnode.properties.every{it.type==ClassHelper.make(Integer)}})@EvenCheckerclassA{IntegermaxIntegermin

StringtoString(){return"A"}}

15 . 5

16 . 1

16 . 2

packagegreach.builder

classToMD5TestextendsGroovyTestCase{

16 . 3

packagegreach.builder

classToMD5TestextendsGroovyTestCase{

16 . 3

packagegreach.builder

classToMD5TestextendsGroovyTestCase{

16 . 3

voidtestAddingToMD5(){assertScript'''packagegreach.builder

classOrder{@ToMD5Stringname@ToMD5Stringdescription}

Orderorder=newOrder(name:"john",description:"desc")

assertorder.nameToMD5()=="527bd5b5d689e2c32ae974c6229ff785"assertorder.descriptionToMD5()=="1dee80c7d5ab2c1c90aa8d2f7dd47256"'''}

16 . 4

voidtestFailsToUseAnInteger(){shouldFail'''packagegreach.builder

classOrder{@ToMD5Integermonth}'''}

16 . 5

16 . 6

17 . 1

17 . 2

17 . 3

17 . 4

BlockStatementresult=macro(true){println"foo"}

17 . 5

BlockStatementresult=macro(true){println"foo"}

//VS

defexpected=block(stmt(callThisX("println",args(constX("foo")))))

//CHECKEDBYAstAssert.assertSyntaxTree([expected],[result]);

17 . 6

BlockStatementresult=macro(true){println"foo"}

//VS

defexpected=block(stmt(callThisX("println",args(constX("foo")))))

//CHECKEDBYAstAssert.assertSyntaxTree([expected],[result]);

17 . 6

BlockStatementresult=macro(true){println"foo"}

//VS

defexpected=block(stmt(callThisX("println",args(constX("foo")))))

//CHECKEDBYAstAssert.assertSyntaxTree([expected],[result]);

17 . 6

BlockStatementresult=macro(true){println"foo"}

//VS

defexpected=block(stmt(callThisX("println",args(constX("foo")))))

//CHECKEDBYAstAssert.assertSyntaxTree([expected],[result]);

17 . 6

17 . 7

voidtestClosureExpression(){defast1=macro{{->a}}defast2=macro{{->a}}defast3=macro{{->b}}defast4=macro{{a->a}}defast5=macro{{a->a}}defast6=macro{{a,b->a}}defast7=macro{{inta->a}}assertASTMatcher.matches(ast1,ast1)assertASTMatcher.matches(ast1,ast2)assertASTMatcher.matches(ast2,ast1)assert!ASTMatcher.matches(ast1,ast3)assert!ASTMatcher.matches(ast1,ast4)assertASTMatcher.matches(ast4,ast5)assert!ASTMatcher.matches(ast5,ast6)assert!ASTMatcher.matches(ast5,ast7)}

17 . 8

17 . 9

17 . 10

17 . 11

18 . 1

top related