Как стать автором
Обновить

Комментарии 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;) Будем совместными усилиями развивать тему.
Про MacroGroovy не только тут упомянул, но и добавил в доклады на JPoint и JavaDay. Офигительная штука.
Cédric Champeau обещал посмотреть через неделю внимательней, вроде как его тоже заинтересовал. Постараюсь продвинуть его в groovy-core, где ему и место имхо.

К слову, саму идею я взял из Haxe-a: haxe.org/manual/macros
Раз так, я Седрику тоже тогда на мозг капну при случае, ибо сейчас почти каждый день общаемся (они релизы на Бинтрей переводят).
Буду благодарен, форс от такого большого дядьки мира Groovy ускорил бы процесс в разы.
Не, выглядит круто, вопрос в том, что как с этим в IDE дела обстоят? Тот же ломбок весь проект красным красит, если открывать его в Идее — плагины для него это буэ и непереносимость сред. Хотелось бы видеть все это уже bundled.
Практически для всех аннотаций, перечисленных в статье, есть отличная поддержка IDEA, она понимает, что как генерирует и позволяет с этим работать с блекджеком и автокомплитом
Барух, я не понял — я могу эти трансформации на Ява классы навешивать? Кто в рантайме это все применять будет?
Можно аннотировать Java-классы, если используется Groovy-компилятор, а не стандартный javac. Все AST трансформации происходят на этапе компиляции и меняют результатирующий байт-код

P.S. больная тема, поэтому суюсь везде с ответом:) Сори, если ожидался ответ именно от Баруха
Да без разницы, я бы написал тоже самое (ибо ФАКТ).
1. как это выглядит в грейдле?
2. как скажется на скорости компиляции?
3. Что скажет дебагер, когда я начну заходить в метод, которого нет?
1. Кладешь java классы в директорию src/main/groovy
2. Медленно.
3. Идея знает про ASTT, так что зайти туда не получится.
Т.е. по сути это будут груви классы? Или по расширению оно будет знать что это Ява?
Я смогу в них писать def?
Если расширение .java, то синтаксис Джавы, если .groovy, то Груви. Нахождение в src/main/whatever означает, каким компилятором компилировать, а не какой синтакс в файлах. Это от типа файла зависит.

Например, если ты положишь Груви файл в src/main/resources, то он будет переписан в classes не скомпилированным вообще.
Да… классно, спасибо!
my pleasure!
А надо как-то в градле включать процессинг груви-аннотаций для java-классов? java-классы в src/main/groovy компилятся без применения этих аннотаций. Документация говорит, что есть инкубационный флажок, но вот так не помогло:

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 :)
Ух ты, жесть какая! Круто, правда совершенно не-читаемо :)

А на счет 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

правда создана была для другого:)
@Immutable делает класс неизменяемым, а конкретно:
1. сеттеры кидают ReadOnlyPropertyException
WAT?! Зачем вообще сеттеры Immutable-классу?
Любопытно! А есть ли что-нибудь готовое для тех, кто не хочет каждый раз писать:

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 с глаз долой. Первым комментарием хотел лишь внести для себя определенность, что не изобрету тем самым велосипед.
jbaruch: вопрос о @ Delegate:
обычно хочется (требуется) в классе A не только переадресовать все вызовы экземпляру класса B, содержащемуся в классе A в кач-ве поля,
но и реализовать в классе A некий суперинтерфейс B,
ибо говорить о duck typing применительно к Java бессмысленно,
а @ Delegate реализует именно duck typing.

Это как-то можно сделать?
Я не пробовал (может сегодня будет время, попробую), но логика подсказывает, что можно поставить implements. Поскольку класс компилируется groovy компилятором, должно сработать.
Спасибо.
@ Delegate позволяет добавить подпись интерфейсов к классу, в котором он объявлен, никакого Duck Typing, всё статично.
Очень хорошо.

В том же ламбоке можно было указать, что, например, при генерации equals/hashCode/toString нужно исключать какие-то поля.
Типичный пример — ссылка на родительский элемент, тогда как родительский элемент содержит список детей. В таком случае свалится с SO можно запросто.

Еще один момент — можно ли как-то влиять на поведение генерируемого кода — т.н. setter производит какую-то базовую проверку аргумента, например, недопустимо передавать null?
Большинство этих аннотаций принимают параметры, которые конфигурируют генерируемый код. Например @Canonical принимает слисок полей для исключения.

На поведение генерируемого кода повлиять нельзя, можно просто методы, которые должны делать что-то отличное, от бойлерплейта, прописать вручную.
Помогите пожалуста, я не совсем понял как это можно использовать сильно не уходя от явы — «способом протащить Groovy в ваш проект». Попытался скомпилировать пример:

image

Метод 'setFirstName' сгенерировался, а вот использование конструктора с map выдаёт ошибку.
A у вас groovy в runtime classpath остался?
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации