Комментарии 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;) Будем совместными усилиями развивать тему.
+1
Про MacroGroovy не только тут упомянул, но и добавил в доклады на JPoint и JavaDay. Офигительная штука.
+2
Cédric Champeau обещал посмотреть через неделю внимательней, вроде как его тоже заинтересовал. Постараюсь продвинуть его в groovy-core, где ему и место имхо.
К слову, саму идею я взял из Haxe-a: haxe.org/manual/macros
К слову, саму идею я взял из Haxe-a: haxe.org/manual/macros
+1
Не, выглядит круто, вопрос в том, что как с этим в IDE дела обстоят? Тот же ломбок весь проект красным красит, если открывать его в Идее — плагины для него это буэ и непереносимость сред. Хотелось бы видеть все это уже bundled.
+2
Барух, я не понял — я могу эти трансформации на Ява классы навешивать? Кто в рантайме это все применять будет?
+2
Можно аннотировать Java-классы, если используется Groovy-компилятор, а не стандартный javac. Все AST трансформации происходят на этапе компиляции и меняют результатирующий байт-код
P.S. больная тема, поэтому суюсь везде с ответом:) Сори, если ожидался ответ именно от Баруха
P.S. больная тема, поэтому суюсь везде с ответом:) Сори, если ожидался ответ именно от Баруха
+3
Да без разницы, я бы написал тоже самое (ибо ФАКТ).
+1
1. как это выглядит в грейдле?
2. как скажется на скорости компиляции?
3. Что скажет дебагер, когда я начну заходить в метод, которого нет?
2. как скажется на скорости компиляции?
3. Что скажет дебагер, когда я начну заходить в метод, которого нет?
0
1. Кладешь java классы в директорию src/main/groovy
2. Медленно.
3. Идея знает про ASTT, так что зайти туда не получится.
2. Медленно.
3. Идея знает про ASTT, так что зайти туда не получится.
+1
Т.е. по сути это будут груви классы? Или по расширению оно будет знать что это Ява?
Я смогу в них писать def?
Я смогу в них писать def?
0
Если расширение .java, то синтаксис Джавы, если .groovy, то Груви. Нахождение в src/main/whatever означает, каким компилятором компилировать, а не какой синтакс в файлах. Это от типа файла зависит.
Например, если ты положишь Груви файл в src/main/resources, то он будет переписан в classes не скомпилированным вообще.
Например, если ты положишь Груви файл в src/main/resources, то он будет переписан в classes не скомпилированным вообще.
+4
А надо как-то в градле включать процессинг груви-аннотаций для java-классов? java-классы в src/main/groovy компилятся без применения этих аннотаций. Документация говорит, что есть инкубационный флажок, но вот так не помогло:
tasks.withType(GroovyCompile) {groovyOptions.javaAnnotationProcessing = true}
при этом в груви-классах ast выполняются.
tasks.withType(GroovyCompile) {groovyOptions.javaAnnotationProcessing = true}
при этом в груви-классах ast выполняются.
0
Еще вопрос — есть ли на английском -то то ( я не могу найти) про применение груви трансформаций для Ява классов? Мне бы товарищам показать…
+1
Астрологи объявили неделю 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 :)
+3
Ух ты, жесть какая! Круто, правда совершенно не-читаемо :)
А на счет 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.
+2
да, всё никак руки не дойдут перейти полностью на bintray, выходил в централ ещё старыми sonatype способами:)
0
внезапно(!) в разговоре с Седриком обнаружилась уже готовая аннотация в groovy-core (since 2.0.0):
groovy.codehaus.org/gapi/groovy/transform/ASTTest.html
правда создана была для другого:)
groovy.codehaus.org/gapi/groovy/transform/ASTTest.html
правда создана была для другого:)
+1
@Immutable делает класс неизменяемым, а конкретно:WAT?! Зачем вообще сеттеры Immutable-классу?
1. сеттеры кидают ReadOnlyPropertyException
+2
Любопытно! А есть ли что-нибудь готовое для тех, кто не хочет каждый раз писать:
но чтобы было достаточно любой из этих срок, для установления двусторонней связи между container и item?
container.getItems().add(item); item.setContainer(container);
но чтобы было достаточно любой из этих срок, для установления двусторонней связи между container и item?
-1
Вообще-то для этого не требуются 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())
0
> Вообще-то для этого не требуются AST трансформации
AST трансформации, формально, вообще нигде не требуются. Но они уменьшают количество boilerplate-кода, и это, согласитесь, здорово.
Ваше решение, как и многие другие не избавлено от этого недостатка. Приходится создавать вспомогательные методы или классы.
Скорее всего я найду свободное время чтобы расчехлить AST и «спрятать» весь boilerplate в моей текущей реализации bidirectional assocations с глаз долой. Первым комментарием хотел лишь внести для себя определенность, что не изобрету тем самым велосипед.
AST трансформации, формально, вообще нигде не требуются. Но они уменьшают количество boilerplate-кода, и это, согласитесь, здорово.
Ваше решение, как и многие другие не избавлено от этого недостатка. Приходится создавать вспомогательные методы или классы.
Скорее всего я найду свободное время чтобы расчехлить AST и «спрятать» весь boilerplate в моей текущей реализации bidirectional assocations с глаз долой. Первым комментарием хотел лишь внести для себя определенность, что не изобрету тем самым велосипед.
0
jbaruch: вопрос о @ Delegate:
обычно хочется (требуется) в классе
но и реализовать в классе
ибо говорить о duck typing применительно к Java бессмысленно,
а @ Delegate реализует именно duck typing.
Это как-то можно сделать?
обычно хочется (требуется) в классе
A
не только переадресовать все вызовы экземпляру класса B
, содержащемуся в классе A
в кач-ве поля,но и реализовать в классе
A
некий суперинтерфейс B
,ибо говорить о duck typing применительно к Java бессмысленно,
а @ Delegate реализует именно duck typing.
Это как-то можно сделать?
0
Я не пробовал (может сегодня будет время, попробую), но логика подсказывает, что можно поставить implements. Поскольку класс компилируется groovy компилятором, должно сработать.
+1
Очень хорошо.
В том же ламбоке можно было указать, что, например, при генерации equals/hashCode/toString нужно исключать какие-то поля.
Типичный пример — ссылка на родительский элемент, тогда как родительский элемент содержит список детей. В таком случае свалится с SO можно запросто.
Еще один момент — можно ли как-то влиять на поведение генерируемого кода — т.н. setter производит какую-то базовую проверку аргумента, например, недопустимо передавать null?
В том же ламбоке можно было указать, что, например, при генерации equals/hashCode/toString нужно исключать какие-то поля.
Типичный пример — ссылка на родительский элемент, тогда как родительский элемент содержит список детей. В таком случае свалится с SO можно запросто.
Еще один момент — можно ли как-то влиять на поведение генерируемого кода — т.н. setter производит какую-то базовую проверку аргумента, например, недопустимо передавать null?
0
Помогите пожалуста, я не совсем понял как это можно использовать сильно не уходя от явы — «способом протащить Groovy в ваш проект». Попытался скомпилировать пример:
Метод 'setFirstName' сгенерировался, а вот использование конструктора с map выдаёт ошибку.
Метод 'setFirstName' сгенерировался, а вот использование конструктора с map выдаёт ошибку.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Трансформации AST — Первый шаг к тяжёлым веществам