Comments 35
Таки решился:)
От себя скажу, что AST трансформации — определённо киллер фича Groovy. Если мы раньше использовали AOP, и это казалось чем-то крутым и решающим 100% наших проблем, то Groovy расширил эти 100% в разы, показав нам насколько мы ошибались.
На правах рекламы хочу поделиться примером активного использования ASTT — compile-time генератор конверторов объектов для JVM (Прощай Dozer):
github.com/bsideup/GOM/blob/master/src/test/groovy/ru/trylogic/gom/tests/TestConfigBuilder.groovy
github.com/bsideup/GOM/blob/master/src/test/groovy/ru/trylogic/gom/tests/SimpleTest.groovy
Причем сам код конвертации конкретных значений не такой уж и сложный в итоге:
github.com/bsideup/GOM/tree/master/src/main/groovy/ru/trylogic/gom/converters
Спасибо за развитие интереса к ASTT и упоминание моей статьи про MacroGroovy;) Будем совместными усилиями развивать тему.
От себя скажу, что AST трансформации — определённо киллер фича Groovy. Если мы раньше использовали AOP, и это казалось чем-то крутым и решающим 100% наших проблем, то Groovy расширил эти 100% в разы, показав нам насколько мы ошибались.
На правах рекламы хочу поделиться примером активного использования ASTT — compile-time генератор конверторов объектов для JVM (Прощай Dozer):
github.com/bsideup/GOM/blob/master/src/test/groovy/ru/trylogic/gom/tests/TestConfigBuilder.groovy
github.com/bsideup/GOM/blob/master/src/test/groovy/ru/trylogic/gom/tests/SimpleTest.groovy
Причем сам код конвертации конкретных значений не такой уж и сложный в итоге:
github.com/bsideup/GOM/tree/master/src/main/groovy/ru/trylogic/gom/converters
Спасибо за развитие интереса к ASTT и упоминание моей статьи про MacroGroovy;) Будем совместными усилиями развивать тему.
Про MacroGroovy не только тут упомянул, но и добавил в доклады на JPoint и JavaDay. Офигительная штука.
Cédric Champeau обещал посмотреть через неделю внимательней, вроде как его тоже заинтересовал. Постараюсь продвинуть его в groovy-core, где ему и место имхо.
К слову, саму идею я взял из Haxe-a: haxe.org/manual/macros
К слову, саму идею я взял из Haxe-a: haxe.org/manual/macros
Не, выглядит круто, вопрос в том, что как с этим в IDE дела обстоят? Тот же ломбок весь проект красным красит, если открывать его в Идее — плагины для него это буэ и непереносимость сред. Хотелось бы видеть все это уже bundled.
Барух, я не понял — я могу эти трансформации на Ява классы навешивать? Кто в рантайме это все применять будет?
Можно аннотировать Java-классы, если используется Groovy-компилятор, а не стандартный javac. Все AST трансформации происходят на этапе компиляции и меняют результатирующий байт-код
P.S. больная тема, поэтому суюсь везде с ответом:) Сори, если ожидался ответ именно от Баруха
P.S. больная тема, поэтому суюсь везде с ответом:) Сори, если ожидался ответ именно от Баруха
Да без разницы, я бы написал тоже самое (ибо ФАКТ).
1. как это выглядит в грейдле?
2. как скажется на скорости компиляции?
3. Что скажет дебагер, когда я начну заходить в метод, которого нет?
2. как скажется на скорости компиляции?
3. Что скажет дебагер, когда я начну заходить в метод, которого нет?
1. Кладешь java классы в директорию src/main/groovy
2. Медленно.
3. Идея знает про ASTT, так что зайти туда не получится.
2. Медленно.
3. Идея знает про ASTT, так что зайти туда не получится.
Т.е. по сути это будут груви классы? Или по расширению оно будет знать что это Ява?
Я смогу в них писать def?
Я смогу в них писать def?
Если расширение .java, то синтаксис Джавы, если .groovy, то Груви. Нахождение в src/main/whatever означает, каким компилятором компилировать, а не какой синтакс в файлах. Это от типа файла зависит.
Например, если ты положишь Груви файл в src/main/resources, то он будет переписан в classes не скомпилированным вообще.
Например, если ты положишь Груви файл в src/main/resources, то он будет переписан в classes не скомпилированным вообще.
А надо как-то в градле включать процессинг груви-аннотаций для java-классов? java-классы в src/main/groovy компилятся без применения этих аннотаций. Документация говорит, что есть инкубационный флажок, но вот так не помогло:
tasks.withType(GroovyCompile) {groovyOptions.javaAnnotationProcessing = true}
при этом в груви-классах ast выполняются.
tasks.withType(GroovyCompile) {groovyOptions.javaAnnotationProcessing = true}
при этом в груви-классах ast выполняются.
Еще вопрос — есть ли на английском -то то ( я не могу найти) про применение груви трансформаций для Ява классов? Мне бы товарищам показать…
Астрологи объявили неделю AST трансформаций, количество проектов увеличилось вдвое.
Для тех, кто хочет поиграться с ASTT, я создал проект, позволяющий писать трансформации Inline. Встречайте — @InlineTransform :)
github.com/bsideup/GroovyInlineTransform/blob/master/src/test/groovy/ru/trylogic/groovy/transform/inline/tests/BasicTest.groovy
Залил в Maven central ( search.maven.org/#search%7Cga%7C1%7Cgroovy-inline-transform ), ждёт синхронизации, могу ещё послать в jCenter :)
Для тех, кто хочет поиграться с ASTT, я создал проект, позволяющий писать трансформации Inline. Встречайте — @InlineTransform :)
github.com/bsideup/GroovyInlineTransform/blob/master/src/test/groovy/ru/trylogic/groovy/transform/inline/tests/BasicTest.groovy
Залил в Maven central ( search.maven.org/#search%7Cga%7C1%7Cgroovy-inline-transform ), ждёт синхронизации, могу ещё послать в jCenter :)
Ух ты, жесть какая! Круто, правда совершенно не-читаемо :)
А на счет central/jcenter — Ну, во первых да, всё крутое в Груви уже давно в jcenter. А во-вторых, если уже на бинтрее, то в central можно попасть значительно проще оттуда — blog.bintray.com/2014/02/11/bintray-as-pain-free-gateway-to-maven-central/
пы.сы. www.trylogic.ru/ дает forbidden.
А на счет central/jcenter — Ну, во первых да, всё крутое в Груви уже давно в jcenter. А во-вторых, если уже на бинтрее, то в central можно попасть значительно проще оттуда — blog.bintray.com/2014/02/11/bintray-as-pain-free-gateway-to-maven-central/
пы.сы. www.trylogic.ru/ дает forbidden.
да, всё никак руки не дойдут перейти полностью на bintray, выходил в централ ещё старыми sonatype способами:)
внезапно(!) в разговоре с Седриком обнаружилась уже готовая аннотация в groovy-core (since 2.0.0):
groovy.codehaus.org/gapi/groovy/transform/ASTTest.html
правда создана была для другого:)
groovy.codehaus.org/gapi/groovy/transform/ASTTest.html
правда создана была для другого:)
@Immutable делает класс неизменяемым, а конкретно:WAT?! Зачем вообще сеттеры Immutable-классу?
1. сеттеры кидают ReadOnlyPropertyException
Любопытно! А есть ли что-нибудь готовое для тех, кто не хочет каждый раз писать:
но чтобы было достаточно любой из этих срок, для установления двусторонней связи между container и item?
container.getItems().add(item); item.setContainer(container);
но чтобы было достаточно любой из этих срок, для установления двусторонней связи между container и item?
Вообще-то для этого не требуются AST трансформации.
class Container {
Items items;
Constructor() {
items = new Items(this);
}
}
class Items {
WeakReference<Container> container;
protected List<Item> internalItems = [];
Items(Container container) {
this.container = new WeakReference<Container>(container);
}
Item addItem(Item item) {
internalItems.add(item);
item.container = this.container.get();
}
}
class Item {
WeakReference<Container> container;
void setContainer(Container container) {
container.items.addItem(this)
}
}
container.items.addItem(new Item())
> Вообще-то для этого не требуются AST трансформации
AST трансформации, формально, вообще нигде не требуются. Но они уменьшают количество boilerplate-кода, и это, согласитесь, здорово.
Ваше решение, как и многие другие не избавлено от этого недостатка. Приходится создавать вспомогательные методы или классы.
Скорее всего я найду свободное время чтобы расчехлить AST и «спрятать» весь boilerplate в моей текущей реализации bidirectional assocations с глаз долой. Первым комментарием хотел лишь внести для себя определенность, что не изобрету тем самым велосипед.
AST трансформации, формально, вообще нигде не требуются. Но они уменьшают количество boilerplate-кода, и это, согласитесь, здорово.
Ваше решение, как и многие другие не избавлено от этого недостатка. Приходится создавать вспомогательные методы или классы.
Скорее всего я найду свободное время чтобы расчехлить AST и «спрятать» весь boilerplate в моей текущей реализации bidirectional assocations с глаз долой. Первым комментарием хотел лишь внести для себя определенность, что не изобрету тем самым велосипед.
jbaruch: вопрос о @ Delegate:
обычно хочется (требуется) в классе
но и реализовать в классе
ибо говорить о duck typing применительно к Java бессмысленно,
а @ Delegate реализует именно duck typing.
Это как-то можно сделать?
обычно хочется (требуется) в классе
A
не только переадресовать все вызовы экземпляру класса B
, содержащемуся в классе A
в кач-ве поля,но и реализовать в классе
A
некий суперинтерфейс B
,ибо говорить о duck typing применительно к Java бессмысленно,
а @ Delegate реализует именно duck typing.
Это как-то можно сделать?
Я не пробовал (может сегодня будет время, попробую), но логика подсказывает, что можно поставить implements. Поскольку класс компилируется groovy компилятором, должно сработать.
Очень хорошо.
В том же ламбоке можно было указать, что, например, при генерации equals/hashCode/toString нужно исключать какие-то поля.
Типичный пример — ссылка на родительский элемент, тогда как родительский элемент содержит список детей. В таком случае свалится с SO можно запросто.
Еще один момент — можно ли как-то влиять на поведение генерируемого кода — т.н. setter производит какую-то базовую проверку аргумента, например, недопустимо передавать null?
В том же ламбоке можно было указать, что, например, при генерации equals/hashCode/toString нужно исключать какие-то поля.
Типичный пример — ссылка на родительский элемент, тогда как родительский элемент содержит список детей. В таком случае свалится с SO можно запросто.
Еще один момент — можно ли как-то влиять на поведение генерируемого кода — т.н. setter производит какую-то базовую проверку аргумента, например, недопустимо передавать null?
Помогите пожалуста, я не совсем понял как это можно использовать сильно не уходя от явы — «способом протащить Groovy в ваш проект». Попытался скомпилировать пример:

Метод 'setFirstName' сгенерировался, а вот использование конструктора с map выдаёт ошибку.

Метод 'setFirstName' сгенерировался, а вот использование конструктора с map выдаёт ошибку.
Sign up to leave a comment.
Трансформации AST — Первый шаг к тяжёлым веществам