Обработка новых линий, отступов и пробелов может быть сложной иногда в Акчелео. Вы можете просмотреть эту страницу: http://help.eclipse.org/juno/topic/org.eclipse.acceleo.doc/pages/reference/textproductionrules.html, она представляет собой текстовые правила.
Кроме того, поскольку Acceleo является воплощением стандарта MOFM2T (стандарт OMG). Существует также дополнительная информация в самой спецификации: http://www.omg.org/spec/MOFM2T/1.0/PDF/
Как быстрый ответ, шаблон вызывает «помнить» отступ, используемый при его вызове.
Вот пример:
[template public generate(c : Class)]
[comment @main/]
[file (c.name, false, 'UTF-8')]
Class [c.name/]
[c.ownedAttribute.gen()/] [comment using implicit iterator/]
[/file]
[/template]
[template public gen(p : Property)]
name=[p.name/], type=[p.type.name/]
[comment notice the new line/]
[/template]
И тот же самый, но с использованием for
вместо неявного итератора:
[template public generate(c : Class)]
[comment @main/]
[file (c.name, false, 'UTF-8')]
Class [c.name/]
[for (p : Property | c.ownedAttribute)]
[p.gen()/]
[/for]
[/file]
[/template]
[template public gen(p : Property)]
name=[p.name/], type=[p.type.name/] [comment no more new line/]
[/template]
здесь полученный выход (в обоих случаях):
Class MyClass
name=attribute, type=MyInterface
name=attribute2, type=Boolean
name=attribute3, type=Char
EDIT> Относительно вашего нового вопроса a bout indentation (на следующий ответ этой темы). Вы можете легко управлять отступом как частью шаблона, но обычно вам нужно избегать нахождения общего шаблона любой ценой в противном случае, это часто приводит к сложному сценарию для чтения и обслуживания.
Вот небольшой пример, по-прежнему использующий UML в качестве входной метамодели с использованием рекурсивных шаблонов.
вход test.uml
<uml:Model xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:uml="http://www.eclipse.org/uml2/4.0.0/UML" xmi:version="2.0" xmi:id="_wfUKcIkNEeWSIKoWblTvZg" name="HelloModel">
<packageImport xmi:id="_wfUKc4kNEeWSIKoWblTvZg">
<importedPackage href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#/"/>
</packageImport>
<packageImport xmi:id="_wfUKdokNEeWSIKoWblTvZg">
<importedPackage href="pathmap://GENMYMODEL_LIBRARIES/GenMyModelPrimitiveTypes.library.uml#/"/>
</packageImport>
<packagedElement xsi:type="uml:Package" xmi:id="_wfUKeYkNEeWSIKoWblTvZg" name="TOP">
<packagedElement xsi:type="uml:Class" xmi:id="_wfUKfIkNEeWSIKoWblTvZg" name="Class1">
<ownedAttribute xmi:id="_wfUKf4kNEeWSIKoWblTvZg" name="a1">
<type xsi:type="uml:PrimitiveType" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Boolean"/>
</ownedAttribute>
<ownedAttribute xmi:id="_wfUKgokNEeWSIKoWblTvZg" name="a2">
<type xsi:type="uml:PrimitiveType" href="pathmap://GENMYMODEL_LIBRARIES/GenMyModelPrimitiveTypes.library.uml#//Char"/>
</ownedAttribute>
</packagedElement>
<packagedElement xsi:type="uml:Package" xmi:id="_wfUKhYkNEeWSIKoWblTvZg" name="INNER">
<packagedElement xsi:type="uml:Class" xmi:id="_wfUKiIkNEeWSIKoWblTvZg" name="Class2">
<ownedAttribute xmi:id="_wfUKi4kNEeWSIKoWblTvZg" name="a1">
<type xsi:type="uml:PrimitiveType" href="pathmap://GENMYMODEL_LIBRARIES/GenMyModelPrimitiveTypes.library.uml#//Double"/>
</ownedAttribute>
<ownedAttribute xmi:id="_wfUKjokNEeWSIKoWblTvZg" name="a2">
<type xsi:type="uml:PrimitiveType" href="pathmap://UML_LIBRARIES/UMLPrimitiveTypes.library.uml#//Integer"/>
</ownedAttribute>
</packagedElement>
</packagedElement>
</packagedElement>
</uml:Model>
Визуальное представление здесь (вы также можете просматривать дерево модели): https://repository.genmymodel.com/vincent.aranega/test1
И сценарий я использовал:
[module example_stack('http://www.eclipse.org/uml2/4.0.0/UML')/]
[template public generate(m : Model)]
[comment @main/]
[file ('res.txt', false, 'UTF-8')]
[m.name/]
['['/]
[for (p : Package | m.packagedElement.oclAsType(Package)) separator('\n,\n')]
[p.gen()/][/for]
]
[/file]
[/template]
[template public gen(o : OclAny)/]
[template public gen(p : Package)]
Container [p.name/]
['['/]
[for (o : OclAny | p.packagedElement)]
[o.gen()/][if (p.packagedElement->asOrderedSet()->last() <> o)],[/if]
[/for]
]
[/template]
[template public gen(c : Class)]
Module [c.name/]
['['/]
In
['['/]
[for (p : Property | c.ownedAttribute)]
[p.gen()/][if (c.ownedAttribute->last() <> p)],[/if]
[/for]
]
]
[/template]
[template public gen(p : Property)]
[p.name/] : [p.type.name/]
[/template]
И вывод:
HelloModel
[
Container TOP
[
Module Class1
[
In
[
a1 : Boolean,
a2 : Char
]
],
Container INNER
[
Module Class2
[
In
[
a1 : Double,
a2 : Integer
]
]
]
]
]
Идея состоит в том, чтобы создать специальный шаблон для каждого элемента, а не только один общий. Таким образом, вы управляете рекурсивным вызовом и отступом. В этом скрипте есть одна вещь, которой я не горжусь, так это управление «,» (используя if вместо separator
). Вероятно, есть лучший способ сделать это.
Спасибо за ваш ответ, я пересмотрел документы и протестировал новую строку и отступы. Поставьте на мой вопрос еще один пример –