From 20f035261587dcb92c1d55bb864c86ff1d682ae0 Mon Sep 17 00:00:00 2001 From: GerardPaligot Date: Wed, 7 Oct 2015 11:04:48 +0200 Subject: [PATCH] doc: #322 Templating source code in the spoon website. Closes #322 --- doc/_jekyll/_data/sidebar_doc.yml | 35 +++++ doc/_jekyll/_data/tags_doc.yml | 1 + doc/_jekyll/images/template-overview.svg | 178 +++++++++++++++++++++++ doc/faq.md | 3 - doc/template_can_be_templated.md | 30 ++++ doc/template_definition.md | 53 +++++++ doc/template_instantiation.md | 33 +++++ doc/template_parameter.md | 39 +++++ 8 files changed, 369 insertions(+), 3 deletions(-) create mode 100644 doc/_jekyll/images/template-overview.svg create mode 100644 doc/template_can_be_templated.md create mode 100644 doc/template_definition.md create mode 100644 doc/template_instantiation.md create mode 100644 doc/template_parameter.md diff --git a/doc/_jekyll/_data/sidebar_doc.yml b/doc/_jekyll/_data/sidebar_doc.yml index a45eaa146eb..1ea2142bb08 100755 --- a/doc/_jekyll/_data/sidebar_doc.yml +++ b/doc/_jekyll/_data/sidebar_doc.yml @@ -136,3 +136,38 @@ entries: platform: all product: all version: all + + - title: Templating source code + audience: writers, designers + platform: all + product: all + version: all + + items: + - title: Template definition + url: /template_definition.html + audience: writers, designers + platform: all + product: all + version: all + + - title: Template instantiation + url: /template_instantiation.html + audience: writers, designers + platform: all + product: all + version: all + + - title: What can be templated? + url: /template_can_be_templated.html + audience: writers, designers + platform: all + product: all + version: all + + - title: Literal Template Parameter + url: /template_parameter.html + audience: writers, designers + platform: all + product: all + version: all diff --git a/doc/_jekyll/_data/tags_doc.yml b/doc/_jekyll/_data/tags_doc.yml index 09e02f0ce86..5b6ea0ef8ff 100755 --- a/doc/_jekyll/_data/tags_doc.yml +++ b/doc/_jekyll/_data/tags_doc.yml @@ -4,3 +4,4 @@ allowed-tags: - meta-model - quering - processor + - template diff --git a/doc/_jekyll/images/template-overview.svg b/doc/_jekyll/images/template-overview.svg new file mode 100644 index 00000000000..3e66c13022e --- /dev/null +++ b/doc/_jekyll/images/template-overview.svg @@ -0,0 +1,178 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Java Program (source code) + + + + + + Program Model + + + + + + + + Template Engine + + + + + + + Template code (source code) + + + + + + + + + + + + + Transformed Java Program + + + + + + + + + + + + + + + + + <<Well-typed>> + + + + + <<Well-typed>> + + + + + <<Well-typed>> + + + + + + + + + + + + Template Model + + + + + + + + + + + + + \ No newline at end of file diff --git a/doc/faq.md b/doc/faq.md index ab05920a0e1..bfe7e9117a2 100644 --- a/doc/faq.md +++ b/doc/faq.md @@ -38,9 +38,6 @@ for(CtSimpleType s : factory.Class().getAll()) { {% endhighlight %} ## Advanced -### How to implement program transformations with well-typed templates? - -See the section Generative Programming with Spoon of the Tutorial. ### How to prevent Annotation processors from consuming the annotations that they process? diff --git a/doc/template_can_be_templated.md b/doc/template_can_be_templated.md new file mode 100644 index 00000000000..3cb41d10aa7 --- /dev/null +++ b/doc/template_can_be_templated.md @@ -0,0 +1,30 @@ +--- +title: What can be templated? +tags: [template] +keywords: template, substitution, code, java +last_updated: October 7, 2015 +--- + +All meta-model elements can be templated. For instance, one can +template a try/catch block as shown in the class `TryCatchOutOfBoundTemplate`. +This template type-checks, and can be used as input by the substitution +engine to wrap a method body into a try/catch block. The substitution engine +contains various methods that implement different substitution scenarios. +For instance, method `insertAllMethods` inserts all the methods of a template +in an existing class. It can be used for instance, to inject getters and setters. + + +```java +public class TryCatchOutOfBoundTemplate extends BlockTemplate { + TemplateParameter _body_; // the body to surround + + @Override + public void block() { + try { + _body_.S(); + } catch (OutOfBoundException e) { + e.printStackTrace(); + } + } +} +``` \ No newline at end of file diff --git a/doc/template_definition.md b/doc/template_definition.md new file mode 100644 index 00000000000..5cc953447a9 --- /dev/null +++ b/doc/template_definition.md @@ -0,0 +1,53 @@ +--- +title: Template definition +tags: [template] +keywords: template, definition, code, java +last_updated: October 7, 2015 +--- + +Spoon provides developers a way of writing code transformations: +code templates. Those templates are statically type-checked, in +order to ensure statically that the generated code will be correct. +Our key idea behind Spoon templates is that they are regular Java code. +Hence, the type-checking is that of the Java compiler itself. + +![Overview of Spoon's Templating System]({{ "/images/template-overview.svg" | prepend: site.baseurl }}) + +A Spoon template is a Java class that is type-checked by the Java compiler, +then taken as input by the Spoon templating engine to perform a transformation. +This is summarized in Figure above. A Spoon template can be seen as a +higher-order program, which takes program elements as arguments, and returns a +transformed program. Like any function, a template can be used in different +contexts and give different results, depending on its parameters. + +```java +public class CheckBoundTemplate extends StatementTemplate { + TemplateParameter> _col_; + @Override + public void statement() { + if (_col_.S().size() > 10) + throw new OutOfBoundException(); + } +} +``` + +Class `CheckBoundTemplate` defines a Spoon template. This template specifies a +statement (in method `statement`) that is a precondition to check that a list +is smaller than a certain size. This piece of code will be injected at the +beginning of all methods dealing with size-bounded lists. This template has +one single template parameter called `_col_`, typed by `TemplateParameter` ([javadoc](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/template/TemplateParameter.html)). +In this case, the template parameter is meant to be an expression (`CtExpression`) +that returns a Collection (see constructor, line 3). All meta-model classes, +incl. `CtExpression` ([javadoc](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/reflect/code/CtExpression.html)), +implement interface `TemplateParameter`. A template parameter has a special method +(named `S`, for Substitution) that is used as a marker to indicate the places where +a template parameter substitution should occur. For a `CtExpression`, method `S()` +returns the return type of the expression. + +A method `S()` is never executed, its only goal is to get the template statically +checked. Instead of being executed, the template source code is taken as input by the +templating engine which is described above. Consequently, the template source is +well-typed, compiles, but the binary code of the template is thrown away. + +There are three kinds of templates: block templates, statement templates and +expression templates. Their names denote the code grain they respectively address. diff --git a/doc/template_instantiation.md b/doc/template_instantiation.md new file mode 100644 index 00000000000..53e9d224e59 --- /dev/null +++ b/doc/template_instantiation.md @@ -0,0 +1,33 @@ +--- +title: Template instantiation +tags: [template] +keywords: template, instantiation, code, java +last_updated: October 7, 2015 +--- + +In order to be correctly substituted, the template parameters need +to be bound to actual values. This is done during template instantiation. + +The code at the end of this page shows how to use the check-bound +of template, `CheckBoundTemplate`, presented in the previous section. +One first instantiates a template, then one sets the template parameters, +and finally, one calls the template engine. In last line, the bound check +is injected at the beginning of a method body. + +Since the template is given the first method parameter which is in the +scope of the insertion location, the generated code is guaranteed to compile. +The Java compiler ensures that the template compiles with a given scope, the +developer is responsible for checking that the scope where she uses +template-generated code is consistent with the template scope. + +```java +// creating a template instance +Template t = new CheckBoundTemplate(); +t._col_ = createVariableAccess(method.getParameters().get(0)); + +// getting the final AST +CtStatement injectedCode = t.apply(); + +// adds the bound check at the beginning of a method +method.getBody().insertBegin(injectedCode); +``` \ No newline at end of file diff --git a/doc/template_parameter.md b/doc/template_parameter.md new file mode 100644 index 00000000000..83551c3d158 --- /dev/null +++ b/doc/template_parameter.md @@ -0,0 +1,39 @@ +--- +title: Literal Template Parameter +tags: [template] +keywords: template, substitution, code, java +last_updated: October 7, 2015 +--- + +We have already seen one kind of template parameter (`TemplateParameter` ([javadoc](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/template/TemplateParameter.html))). +Sometimes, templates are parameterized literal values. This can be done with +a template parameter set to a `CtLiteral` ([javadoc](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/reflect/code/CtLiteral.html)), +for instance, + +``` +// with TemplateParameter +TemplateParameter val; +... +val = Factory.createLiteral(5); +... +if (list.size()>val.S()) {...} + +// with literal template parameter +@Parameter +int val; +... +val = 5; +... +if (list.size()>val) {...} +``` + +For convenience, Spoon provides developers with another kind of template +parameters called *literal template parameters*. When the parameter is known to +be a literal (primitive types, `String`, `Class` or a one-dimensional array of +these types), a template parameter enables one to simplify the template code. +To indicate to the substitution engine that a given field is a template parameter, +it has to be annotated with a `@Parameter` ([javadoc](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/spoon/template/Parameter.html)) +annotation. The code above illustrates this feature with two equivalent templates. +By using a literal template parameter, it is not necessary to call the `S()` method +for substitution: the templating engine looks up all usages of the field annotated with +`@Parameter`. The listing above shows those differences. \ No newline at end of file