Code Generation idioms with Xtend

60
Code Generation Idioms with Holger Schill

Transcript of Code Generation idioms with Xtend

Code Generation Idioms with

Holger Schill

AST

What is a Code Generator?

Generator Code

What languages are out there…

“Template” written in Java

The default formatting for that…

Template using Velocity

Template using Velocity

// Generates Java classes source code // by using Apache Velocity GeneratorUtility utility = new GeneratorUtility(); for (int i = 0; i < classes.size(); i++) {

VelocityContext context = new VelocityContext(); ClassDescriptor cl = (ClassDescriptor) classes.get(i); context.put("class", cl); context.put("utility", utility);

Template template = Velocity.getTemplate(templateFile);

BufferedWriter writer = new BufferedWriter(new FileWriter(cl.getName()+”.java”));

template.merge(context, writer); writer.flush(); writer.close();

Template using Velocity

// Generates Java classes source code // by using Apache Velocity GeneratorUtility utility = new GeneratorUtility(); for (int i = 0; i < classes.size(); i++) {

VelocityContext context = new VelocityContext(); ClassDescriptor cl = (ClassDescriptor) classes.get(i); context.put("class", cl); context.put("utility", utility);

Template template = Velocity.getTemplate(templateFile);

BufferedWriter writer = new BufferedWriter(new FileWriter(cl.getName()+”.java”));

template.merge(context, writer); writer.flush(); writer.close();

Template using Velocity

Template using Velocity

And there are many more…

XpandAcceleo

Jet…

And there are many more…

XpandAcceleo

Jet…

Every whitespace goes into the output

And there are many more…

XpandAcceleo

Jet…

Every whitespace goes into the output

Bad tooling

And there are many more…

XpandAcceleo

Every whitespace goes into the output

Interpreted

Bad tooling

Slow

And there are many more…

Jet…

Every whitespace goes into the output

Translates to Java

Bad tooling

Fast

Let’s see what can do for us…

Let’s see what can do for us…It feels a bit like Java

Static Typing

Let’s see what can do for us…

Compiles to Java

Seamless integrationIt feels a bit like Java

Let’s see what can do for us…

But can do more than that…Compiles to Java

It feels a bit like Java

Template Expressions(aka String Concatenation)

GreyspaceShows what makes it in the generated code

Makes readable templates possible

GreyspaceIndentation of call is taken into account

Model Navigation

Model Navigation

val eClasses = myEPackage.EClassifiers.filter(EClass)

val abstractEClasses = eClasses.filter[isAbstract]

val namesOfAbstractClasses = abstractEClasses.map[name]

val commaSeparatedNamesOfAbstractClasses = namesOfAbstractClasses.join(',')

CommaSeparatedNamesOfAbstractClasses

Model Navigation

filter

map

fold

sortBy

head

reduce

Build your own! It’s just library!Higher-Order Functions

ExtensionsAdd new API where you need it

Extensions

Extensions

Dynamic Dispatch

Dynamic Dispatch

Dynamic DispatchGenerated Java

Dynamic Dispatch

IDE Support

Extract methodRenameRefactoring

Content AssistQuick Assist

Formatting

Type Hierarchy

Call Hierarchy

Syntax Coloring

Outline

etc…

Debugging

Debugging

Debugging

Debugging

Debugging

Debugging

Modularization

Feature Models?

AOP?

Dependency Injection

’s easy usage

No Engine needed

No ContextObject needed

’s easy usage

No Engine needed

No ContextObject needed

At the end it’s feels like using Java

but better…

Best practices

Write readable and understandable codeShould be self-evident but …

Write readable and understandable codeShould be self-evident but …

Make use of dependency injection

Guice

Use incremental code generators

Use incremental code generatorsFast turnarounds

Use incremental code generatorsFast turnarounds

Just having it run on a server is no option

The m - 1 Problem

BeanBeanObject

Reso

urce

Configuration File

BeanBeanObject

Reso

urce

BeanBeanObject

Reso

urce

ResourceSet

ResourceSet

The m - 1 Problem

BeanBeanObject

Reso

urce

Configuration File

BeanBeanObject

Reso

urce

BeanBeanObject

Reso

urce

It’s worth to think about a merging strategy

Incremental code generators in Xtext// generator APIfragment = generator.GeneratorFragment auto-inject {}

Incremental code generators in Xtext// generator APIfragment = generator.GeneratorFragment auto-inject {}

class MyDslGenerator implements IGenerator {

override void doGenerate(Resource resource, IFileSystemAccess fsa) {// fsa.generateFile('greetings.txt', 'People to greet: ' + // resource.allContents// .filter(typeof(Greeting))// .map[name]// .join(', '))

}}

Incremental code generators in Xtext// generator APIfragment = generator.GeneratorFragment auto-inject {}

class MyDslGenerator implements IGenerator {

override void doGenerate(Resource resource, IFileSystemAccess fsa) {// fsa.generateFile('greetings.txt', 'People to greet: ' + // resource.allContents// .filter(typeof(Greeting))// .map[name]// .join(', '))

}}

Customisable mechanism is taking care to recompile affected resources

Incremental code generators in Xtext// generator APIfragment = generator.GeneratorFragment auto-inject {}

class MyDslGenerator implements IGenerator {

override void doGenerate(Resource resource, IFileSystemAccess fsa) {// fsa.generateFile('greetings.txt', 'People to greet: ' + // resource.allContents// .filter(typeof(Greeting))// .map[name]// .join(', '))

}}

http://www.eclipse.org/Xtext/documentation/350_continuous_integration.html

Get Maven integration for free

more than just a code-gen language…

http://www.xtend-lang.org/

Questions ?