31
Groovy AST

Ast transformations

Embed Size (px)

DESCRIPTION

Groovy AST - 18va reunion Spring Hispano

Citation preview

Page 1: Ast transformations

Groovy  AST  

Page 2: Ast transformations
Page 3: Ast transformations

Agenda  

•  Local  ASTTransforma5ons  – Groovy  – Grails  – Griffon  

•  Como  funcionan?  

•  Otras  formas  de  modificar  AST  

Page 4: Ast transformations

LISTADO  DE  TRANSFORMACIONES  DE  AST  (NO  EXHAUSTIVO)  

Page 5: Ast transformations

@Singleton  

@Singleton

class AccountManager {

void process(Account account) { ... } }

def account = new Account() AccountManager.instance.process(account)

Page 6: Ast transformations

@Delegate  class Event { @Delegate Date when String title, url }

df = new SimpleDateFormat("MM/dd/yyyy") so2gx = new Event(title: "SpringOne2GX", url: "http://springone2gx.com", when: df.parse("10/19/2010")) oredev = new Event(title: "Oredev", url: "http://oredev.org", when: df.parse("11/02/2010")) assert oredev.after(so2gx.when)

Page 7: Ast transformations

@Immutable  

@Immutable

class Person {

String name

}

def person1 = new Person("ABC") def person2 = new Person(name: "ABC")

assert person1 == person2

person1.name = "Boom!” // error!

Page 8: Ast transformations

@Category  @Category(Integer) class Pouncer { String pounce() { (1..this).collect([]) { 'boing!' }.join(' ') } }

use(Pouncer) { 3.pounce() // boing! boing! boing! }

Page 9: Ast transformations

@Mixin  class Pouncer { String pounce() { (1..this.times).collect([]) { 'boing!' }.join(' ') } }

@Mixin(Pouncer) class Person{ int times }

person1 = new Person(times: 2) person1.pounce() // boing! boing!

Page 10: Ast transformations

@Grab  

@Grab('net.sf.json-lib:json-lib:2.3:jdk15')

def builder = new net.sf.json.groovy.JsonGroovyBuilder()

def books = builder.books {

book(title: "Groovy in Action",

name: "Dierk Koenig")

}

assert books.name == ["Dierk Koenig"]

Page 11: Ast transformations

@Log  @groovy.util.logging.Log class Person { String name void talk() { log.info("$name is talking…") } }

def person = new Person(name: "Duke") person.talk() // Oct 7, 2010 10:36:09 PM sun.reflect.NativeMethodAccessorImpl invoke0

// INFO: Duke is talking…  

Page 12: Ast transformations

@InheritConstructors  

@groovy.transform.InheritConstructors class MyException extends RuntimeException {}

def x1 = new MyException("Error message")

def x2 = new MyException(x1)

assert x2.cause == x1

Page 13: Ast transformations

@Canonical  

@groovy.transform.Canonical class Person { String name }

def person1 = new Person("Duke") def person2 = new Person(name: "Duke") assert person1 == person2 person2.name = "Tux" assert person1 != person2

Page 14: Ast transformations

@Scalify  

trait Output {

@scala.reflect.BeanProperty

var output:String = "" }

@groovyx.transform.Scalify class GroovyOutput implements Output {

String output

}

Page 15: Ast transformations

@En5ty  

@grails.persistence.Entity

class Book {

String title

}

def book = new Book().save() assert book.id

assert book.version

Page 16: Ast transformations

@Bindable  @groovy.beans.Bindable class Book { String title }

def book = new Book() book.addPropertyChangeListener({e -> println "$e.propertyName $e.oldValue -> $e.newValue" } as java.beans.PropertyChangeListener) book.title = "Foo” // prints "title Foo" book.title = "Bar” // prints "title Foo Bar"

Page 17: Ast transformations

@Listener  @groovy.beans.Bindable class Book { @griffon.beans.Listener(snooper) String title private snooper = {e -> println "$e.propertyName $e.oldValue -> $e.newValue" } }

def book = new Book() book.title = "Foo" // prints "title Foo" book.title = "Bar" // prints "title Foo Bar"

Page 18: Ast transformations

@EventPublisher  @Singleton @griffon.util.EventPublisher class AccountManager { void process(Account account) { publishEvent("AccountProcessed", [account)] } } def am = AccountManager.instance am.addEventListener("AccountProcessed") { account -> println "Processed account $account" } def acc = new Account() AccountManager.instance.process(acc) // prints "Processed account Account:1"

Page 19: Ast transformations

@Scaffold  class Book { String title }

@griffon.presentation.Scaffold class BookBeanModel {}

def model = new BookBeanModel() def book = new Book(title: "Foo") model.value = book assert book.title == model.title.value model.value = null assert !model.title.value assert model.title

Page 20: Ast transformations

@En5ty  

@griffon.persistence.Entity(‘gsql’)

class Book {

String title

}

def book = new Book().save() assert book.id

assert book.version

Page 21: Ast transformations

Y  otras  tantas  …  

•  @PackageScope  •  @Lazy  •  @Newify  •  @Field  •  @Synchronized  •  @Vetoable  •  @ToString,  @EqualsAndHashCode,  @TupleConstructor  

•  @AutoClone,  @AutoExternalize  •  …  

Page 22: Ast transformations

LA  RECETA  SECRETA  PARA  HACER  TRANSFORMACIONES  DE  AST  

Page 23: Ast transformations

1  Definir  interface  @Retention(RetentionPolicy.SOURCE)

@Target({ElementType.FIELD, ElementType.TYPE})

@GroovyASTTransformationClass("org.codehaus.griffon.ast.ListenerASTTransformation")

public @interface Listener {

String value();

}

Page 24: Ast transformations

2  Implementar  la  transformacion  import org.codehaus.groovy.control.CompilePhase;

import org.codehaus.groovy.transform.ASTTransformation;

import org.codehaus.groovy.transform.GroovyASTTransformation;

@GroovyASTTransformation(phase=CompilationPhase.CANONICALIZATION)

public class ListenerASTTransformation

implements ASTTransformation {

public void visit(ASTNode[] nodes, SourceUnit source) {

// MAGIC GOES HERE, REALLY! =)

}

}

Page 25: Ast transformations

3  Anotar  el  codigo  

@groovy.beans.Bindable

class Book {

@griffon.beans.Listener(snooper) String title

private snooper = {e ->

// awesome code …

}

}

Page 26: Ast transformations

OTRO  TIPO  DE  TRANSFORMACIONES  

Page 27: Ast transformations

GContracts  

Page 28: Ast transformations

Spock  

Page 29: Ast transformations

CodeNarc  

Page 30: Ast transformations

Griffon  

Page 31: Ast transformations

Gracias!  

@aalmiray  hXp://jroller.com/aalmiray