creating astts the painful truth

170
1

Upload: mario-garcia

Post on 14-Apr-2017

777 views

Category:

Software


0 download

TRANSCRIPT

Page 1: Creating ASTTs The painful truth

1

Page 2: Creating ASTTs The painful truth

2

Page 3: Creating ASTTs The painful truth

3 . 1

Page 4: Creating ASTTs The painful truth

3 . 1

Page 5: Creating ASTTs The painful truth

3 . 1

Page 6: Creating ASTTs The painful truth

… …

3 . 1

Page 7: Creating ASTTs The painful truth

3 . 2

Page 8: Creating ASTTs The painful truth

4 . 1

Page 9: Creating ASTTs The painful truth

4 . 1

Page 10: Creating ASTTs The painful truth

4 . 1

Page 11: Creating ASTTs The painful truth

4 . 1

Page 12: Creating ASTTs The painful truth

4 . 2

Page 13: Creating ASTTs The painful truth

5

Page 14: Creating ASTTs The painful truth

5

Page 15: Creating ASTTs The painful truth

5

Page 16: Creating ASTTs The painful truth

5

Page 17: Creating ASTTs The painful truth

6 . 1

Page 18: Creating ASTTs The painful truth

6 . 2

Page 19: Creating ASTTs The painful truth

6 . 3

Page 20: Creating ASTTs The painful truth

6 . 3

Page 21: Creating ASTTs The painful truth

6 . 3

Page 22: Creating ASTTs The painful truth

6 . 4

Page 23: Creating ASTTs The painful truth

6 . 5

Page 24: Creating ASTTs The painful truth

6 . 6

Page 25: Creating ASTTs The painful truth

6 . 7

Page 26: Creating ASTTs The painful truth

⇒1==1

6 . 8

Page 27: Creating ASTTs The painful truth

⇒1==1

6 . 8

Page 28: Creating ASTTs The painful truth

⇒1==1

6 . 8

Page 29: Creating ASTTs The painful truth

⇒1==1

6 . 8

Page 30: Creating ASTTs The painful truth

⇒ ⇒ref.myMethod(3)

6 . 9

Page 31: Creating ASTTs The painful truth

⇒ ⇒ref.myMethod(3)

6 . 9

Page 32: Creating ASTTs The painful truth

⇒ ⇒ref.myMethod(3)

6 . 9

Page 33: Creating ASTTs The painful truth

⇒ ⇒ref.myMethod(3)

6 . 9

Page 34: Creating ASTTs The painful truth

6 . 10

Page 35: Creating ASTTs The painful truth

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

6 . 11

Page 36: Creating ASTTs The painful truth

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

6 . 11

Page 37: Creating ASTTs The painful truth

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

6 . 11

Page 38: Creating ASTTs The painful truth

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

6 . 12

Page 39: Creating ASTTs The painful truth

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

6 . 12

Page 40: Creating ASTTs The painful truth

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

6 . 12

Page 41: Creating ASTTs The painful truth

publicStringgreetings(){return"HelloGreach"}

6 . 13

Page 42: Creating ASTTs The painful truth

6 . 14

Page 43: Creating ASTTs The painful truth

6 . 15

Page 44: Creating ASTTs The painful truth

6 . 15

Page 45: Creating ASTTs The painful truth

6 . 15

Page 46: Creating ASTTs The painful truth

6 . 15

Page 47: Creating ASTTs The painful truth

6 . 15

Page 48: Creating ASTTs The painful truth

6 . 15

Page 49: Creating ASTTs The painful truth

classA{//ClassNodeStringgreetings//FieldNode

Stringhello(){//MethodNode

}}

6 . 16

Page 50: Creating ASTTs The painful truth

classA{//ClassNode

Stringhello()//MethodNode{//blockStatement{

return"Hello"//returnStatement(constantExpression)

}//}}

6 . 17

Page 51: Creating ASTTs The painful truth

7 . 1

Page 52: Creating ASTTs The painful truth

7 . 2

Page 53: Creating ASTTs The painful truth

7 . 3

Page 54: Creating ASTTs The painful truth

7 . 3

Page 55: Creating ASTTs The painful truth

7 . 3

Page 57: Creating ASTTs The painful truth

7 . 5

Page 58: Creating ASTTs The painful truth

7 . 5

Page 59: Creating ASTTs The painful truth

7 . 5

Page 60: Creating ASTTs The painful truth

7 . 6

Page 61: Creating ASTTs The painful truth

8 . 1

Page 62: Creating ASTTs The painful truth

8 . 2

Page 63: Creating ASTTs The painful truth

8 . 3

Page 64: Creating ASTTs The painful truth

8 . 4

Page 65: Creating ASTTs The painful truth

8 . 5

Page 66: Creating ASTTs The painful truth

8 . 6

Page 67: Creating ASTTs The painful truth

9

Page 68: Creating ASTTs The painful truth

10 . 1

Page 69: Creating ASTTs The painful truth

10 . 2

Page 70: Creating ASTTs The painful truth

10 . 3

Page 72: Creating ASTTs The painful truth

10 . 5

Page 73: Creating ASTTs The painful truth

10 . 5

Page 74: Creating ASTTs The painful truth

10 . 5

Page 75: Creating ASTTs The painful truth

10 . 5

Page 76: Creating ASTTs The painful truth

11 . 1

Page 77: Creating ASTTs The painful truth

packagegreach.local

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

println"mystuff"

//println"EndingdoSomething"}}

11 . 2

Page 78: Creating ASTTs The painful truth

11 . 3

Page 79: Creating ASTTs The painful truth

11 . 3

Page 80: Creating ASTTs The painful truth

11 . 3

Page 81: Creating ASTTs The painful truth

11 . 4

Page 82: Creating ASTTs The painful truth

11 . 4

Page 83: Creating ASTTs The painful truth

11 . 4

Page 84: Creating ASTTs The painful truth

packagegreach.local

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

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

11 . 5

Page 85: Creating ASTTs The painful truth

11 . 6

Page 86: Creating ASTTs The painful truth

importorg.codehaus.groovy.ast.expr.*

importorg.codehaus.groovy.ast.stmt.*

importorg.codehaus.groovy.ast.*

importorg.codehaus.groovy.transform.*

11 . 7

Page 87: Creating ASTTs The painful truth

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classWithLoggingExplainedTransformationimplementsASTTransformation{

11 . 8

Page 88: Creating ASTTs The painful truth

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classWithLoggingExplainedTransformationimplementsASTTransformation{

11 . 8

Page 89: Creating ASTTs The painful truth

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classWithLoggingExplainedTransformationimplementsASTTransformation{

11 . 8

Page 90: Creating ASTTs The painful truth

@GroovyASTTransformation(phase=CompilePhase.SEMANTIC_ANALYSIS)classWithLoggingExplainedTransformationimplementsASTTransformation{

11 . 8

Page 91: Creating ASTTs The painful truth

@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

Page 92: Creating ASTTs The painful truth

11 . 10

Page 93: Creating ASTTs The painful truth

11 . 10

Page 94: Creating ASTTs The painful truth

11 . 10

Page 95: Creating ASTTs The painful truth

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

11 . 11

Page 96: Creating ASTTs The painful truth

11 . 12

Page 97: Creating ASTTs The painful truth

11 . 12

Page 98: Creating ASTTs The painful truth

11 . 12

Page 99: Creating ASTTs The painful truth

12 . 1

Page 100: Creating ASTTs The painful truth

12 . 2

Page 101: Creating ASTTs The painful truth

12 . 3

Page 102: Creating ASTTs The painful truth

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

12 . 4

Page 103: Creating ASTTs The painful truth

12 . 5

Page 104: Creating ASTTs The painful truth

12 . 5

Page 105: Creating ASTTs The painful truth

12 . 5

Page 106: Creating ASTTs The painful truth

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

12 . 6

Page 107: Creating ASTTs The painful truth

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

12 . 7

Page 108: Creating ASTTs The painful truth

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

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

12 . 8

Page 109: Creating ASTTs The painful truth

12 . 9

Page 110: Creating ASTTs The painful truth

12 . 10

Page 111: Creating ASTTs The painful truth

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

returnstmts.first()asBlockStatement}

12 . 11

Page 112: Creating ASTTs The painful truth

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

returnblockStatement.first()asBlockStatement}

12 . 12

Page 113: Creating ASTTs The painful truth

12 . 13

Page 114: Creating ASTTs The painful truth

13 . 1

Page 115: Creating ASTTs The painful truth

@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

Page 116: Creating ASTTs The painful truth

……

packagegreach.builder

classOrder{@ToMD5Stringname@ToMD5Stringdescription}

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

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

13 . 3

Page 117: Creating ASTTs The painful truth

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

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

fieldNode.declaringClass.addMethod(md5Method)}

13 . 4

Page 118: Creating ASTTs The painful truth

@GroovyASTTransformation(phase=CompilePhase.CANONICALIZATION)classMacroExpandAstextendsAbstractASTTransformation{

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

}

13 . 5

Page 119: Creating ASTTs The painful truth

13 . 6

Page 120: Creating ASTTs The painful truth

13 . 7

Page 121: Creating ASTTs The painful truth

classMacroExpandTransformerextendsClassCodeExpressionTransformer{

privateSourceUnitsourceUnit

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

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

13 . 8

Page 122: Creating ASTTs The painful truth

@GlobalTransformation(A.PHASE_GLOBAL.SEMANTIC)classAddTransformationextendsGlobalTransformationImpl{

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

13 . 9

Page 123: Creating ASTTs The painful truth

classChangeTripleXToPlusOneextendsExpressionTransformer<MethodCallExpression>{

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

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

13 . 10

Page 124: Creating ASTTs The painful truth

classChangeTripleXToPlusOneextendsExpressionTransformer<MethodCallExpression>{

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

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

13 . 10

Page 125: Creating ASTTs The painful truth

classChangeTripleXToPlusOneextendsExpressionTransformer<MethodCallExpression>{

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

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

13 . 10

Page 126: Creating ASTTs The painful truth

14 . 1

Page 127: Creating ASTTs The painful truth

14 . 2

Page 128: Creating ASTTs The painful truth

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

Page 129: Creating ASTTs The painful truth

packagegreach.builder

importasteroid.local.Local

@Local(EvenCheckerImpl)@interfaceEvenChecker{}

14 . 4

Page 130: Creating ASTTs The painful truth

packagegreach.builder

importasteroid.local.Local

@Local(EvenCheckerImpl)@interfaceEvenChecker{}

14 . 4

Page 131: Creating ASTTs The painful truth

packagegreach.builder

importasteroid.local.Local

@Local(EvenCheckerImpl)@interfaceEvenChecker{}

14 . 4

Page 132: Creating ASTTs The painful truth

14 . 5

Page 133: Creating ASTTs The painful truth

14 . 6

Page 134: Creating ASTTs The painful truth

packagegreach.meta

importgroovy.transform.ToStringimportgroovy.transform.AnnotationCollector

@ToJson@ToString@AnnotationCollector@interfaceToEverything{}

14 . 7

Page 135: Creating ASTTs The painful truth

packagegreach.meta

@ToEverythingclassA{Stringname}

AaInstance=newA()

assertaInstance.toJson()assertaInstance.toString()

14 . 8

Page 136: Creating ASTTs The painful truth

packagegreach.meta

@ToEverythingclassA{Stringname}

AaInstance=newA()

assertaInstance.toJson()assertaInstance.toString()

14 . 8

Page 137: Creating ASTTs The painful truth

packagegreach.meta

@ToEverythingclassA{Stringname}

AaInstance=newA()

assertaInstance.toJson()assertaInstance.toString()

14 . 8

Page 138: Creating ASTTs The painful truth

15 . 1

Page 139: Creating ASTTs The painful truth

@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

Page 140: Creating ASTTs The painful truth

15 . 3

Page 141: Creating ASTTs The painful truth

15 . 4

Page 142: Creating ASTTs The painful truth

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

StringtoString(){return"A"}}

15 . 5

Page 143: Creating ASTTs The painful truth

16 . 1

Page 144: Creating ASTTs The painful truth

16 . 2

Page 145: Creating ASTTs The painful truth

packagegreach.builder

classToMD5TestextendsGroovyTestCase{

16 . 3

Page 146: Creating ASTTs The painful truth

packagegreach.builder

classToMD5TestextendsGroovyTestCase{

16 . 3

Page 147: Creating ASTTs The painful truth

packagegreach.builder

classToMD5TestextendsGroovyTestCase{

16 . 3

Page 148: Creating ASTTs The painful truth

voidtestAddingToMD5(){assertScript'''packagegreach.builder

classOrder{@ToMD5Stringname@ToMD5Stringdescription}

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

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

16 . 4

Page 149: Creating ASTTs The painful truth

voidtestFailsToUseAnInteger(){shouldFail'''packagegreach.builder

classOrder{@ToMD5Integermonth}'''}

16 . 5

Page 150: Creating ASTTs The painful truth

16 . 6

Page 151: Creating ASTTs The painful truth

17 . 1

Page 152: Creating ASTTs The painful truth

17 . 2

Page 153: Creating ASTTs The painful truth

17 . 3

Page 154: Creating ASTTs The painful truth

17 . 4

Page 155: Creating ASTTs The painful truth

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

17 . 5

Page 156: Creating ASTTs The painful truth

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

//VS

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

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

17 . 6

Page 157: Creating ASTTs The painful truth

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

//VS

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

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

17 . 6

Page 158: Creating ASTTs The painful truth

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

//VS

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

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

17 . 6

Page 159: Creating ASTTs The painful truth

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

//VS

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

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

17 . 6

Page 160: Creating ASTTs The painful truth

17 . 7

Page 161: Creating ASTTs The painful truth

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

Page 162: Creating ASTTs The painful truth

17 . 9

Page 163: Creating ASTTs The painful truth

17 . 10

Page 164: Creating ASTTs The painful truth

17 . 11

Page 165: Creating ASTTs The painful truth

18 . 1