ast transformations
DESCRIPTION
Groovy AST - 18va reunion Spring HispanoTRANSCRIPT
Groovy AST
Agenda
• Local ASTTransforma5ons – Groovy – Grails – Griffon
• Como funcionan?
• Otras formas de modificar AST
LISTADO DE TRANSFORMACIONES DE AST (NO EXHAUSTIVO)
@Singleton
@Singleton
class AccountManager {
void process(Account account) { ... } }
def account = new Account() AccountManager.instance.process(account)
@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)
@Immutable
@Immutable
class Person {
String name
}
def person1 = new Person("ABC") def person2 = new Person(name: "ABC")
assert person1 == person2
person1.name = "Boom!” // error!
@Category @Category(Integer) class Pouncer { String pounce() { (1..this).collect([]) { 'boing!' }.join(' ') } }
use(Pouncer) { 3.pounce() // boing! boing! boing! }
@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!
@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"]
@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…
@InheritConstructors
@groovy.transform.InheritConstructors class MyException extends RuntimeException {}
def x1 = new MyException("Error message")
def x2 = new MyException(x1)
assert x2.cause == x1
@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
@Scalify
trait Output {
@scala.reflect.BeanProperty
var output:String = "" }
@groovyx.transform.Scalify class GroovyOutput implements Output {
String output
}
@En5ty
@grails.persistence.Entity
class Book {
String title
}
def book = new Book().save() assert book.id
assert book.version
@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"
@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"
@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"
@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
@En5ty
@griffon.persistence.Entity(‘gsql’)
class Book {
String title
}
def book = new Book().save() assert book.id
assert book.version
Y otras tantas …
• @PackageScope • @Lazy • @Newify • @Field • @Synchronized • @Vetoable • @ToString, @EqualsAndHashCode, @TupleConstructor
• @AutoClone, @AutoExternalize • …
LA RECETA SECRETA PARA HACER TRANSFORMACIONES DE AST
1 Definir interface @Retention(RetentionPolicy.SOURCE)
@Target({ElementType.FIELD, ElementType.TYPE})
@GroovyASTTransformationClass("org.codehaus.griffon.ast.ListenerASTTransformation")
public @interface Listener {
String value();
}
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! =)
}
}
3 Anotar el codigo
@groovy.beans.Bindable
class Book {
@griffon.beans.Listener(snooper) String title
private snooper = {e ->
// awesome code …
}
}
OTRO TIPO DE TRANSFORMACIONES
GContracts
Spock
CodeNarc
Griffon
Gracias!
@aalmiray hXp://jroller.com/aalmiray