Internal change

PiperOrigin-RevId: 383873010
Change-Id: I1f63711443465a646be744593eee76446a4d0eee
diff --git a/java/org/eclipse/xtend/lib/Data.java b/java/org/eclipse/xtend/lib/Data.java
new file mode 100644
index 0000000..961476c
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/Data.java
@@ -0,0 +1,27 @@
+package org.eclipse.xtend.lib;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.eclipse.xtend.lib.macro.Active;
+
+/**
+ * This annotation is used by the Xtend compiler.
+ * It turns an annotated class into an immutable value object.
+ * 
+ * All fields become final and a getter method is added.
+ * The fields' name are prepended with an underscore (i.e. <tt>myField</tt> becomes <tt>_myField</tt>)
+ * One constructor for initializing the uninitialized fields is added.
+ * {@link Object#equals(Object)} and {@link Object#hashCode()} implementations are added.
+ * {@link Object#toString()} implementation is added.
+ * 
+ * @author Sven Efftinge
+ * @deprecated use {@link org.eclipse.xtend.lib.annotations.Data} instead
+ */
+@Target(ElementType.TYPE)
+@Active(DataProcessor.class)
+@Deprecated
+@Documented
+@SuppressWarnings("all")
+public @interface Data {
+}
diff --git a/java/org/eclipse/xtend/lib/Data.xtend b/java/org/eclipse/xtend/lib/Data.xtend
new file mode 100644
index 0000000..d822c01
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/Data.xtend
@@ -0,0 +1,110 @@
+package org.eclipse.xtend.lib
+
+import java.lang.annotation.Documented
+import java.lang.annotation.ElementType
+import java.lang.annotation.Target
+import org.eclipse.xtend.lib.annotations.AccessorsProcessor
+import org.eclipse.xtend.lib.annotations.EqualsHashCodeProcessor
+import org.eclipse.xtend.lib.annotations.FinalFieldsConstructorProcessor
+import org.eclipse.xtend.lib.annotations.ToStringProcessor
+import org.eclipse.xtend.lib.macro.AbstractClassProcessor
+import org.eclipse.xtend.lib.macro.Active
+import org.eclipse.xtend.lib.macro.TransformationContext
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.Visibility
+
+/**
+ * This annotation is used by the Xtend compiler.
+ * It turns an annotated class into an immutable value object.
+ * 
+ * All fields become final and a getter method is added.
+ * The fields' name are prepended with an underscore (i.e. <tt>myField</tt> becomes <tt>_myField</tt>)
+ * One constructor for initializing the uninitialized fields is added.
+ * {@link Object#equals(Object)} and {@link Object#hashCode()} implementations are added.
+ * {@link Object#toString()} implementation is added.  
+ * 
+ * @author Sven Efftinge
+ * @deprecated use {@link org.eclipse.xtend.lib.annotations.Data} instead
+ */
+@Target(ElementType.TYPE)
+@Active(DataProcessor)
+@Deprecated
+@Documented
+annotation Data {
+}
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Deprecated
+class DataProcessor extends AbstractClassProcessor {
+	override doTransform(MutableClassDeclaration it, extension TransformationContext context) {
+		extension val util = new DataProcessor.Util(context)
+		extension val getterUtil = new AccessorsProcessor.Util(context)
+		extension val ehUtil = new EqualsHashCodeProcessor.Util(context)
+		extension val toStringUtil = new ToStringProcessor.Util(context)
+		extension val requiredArgsUtil = new FinalFieldsConstructorProcessor.Util(context)
+
+		dataFields.forEach [
+			final = true
+		]
+		if (needsFinalFieldConstructor) {
+			addFinalFieldsConstructor
+		}
+		if (!hasHashCode) {
+			addHashCode(dataFields, hasSuperHashCode)
+		}
+		if (!hasEquals) {
+			addEquals(dataFields, hasSuperEquals)
+		}
+		if (!hasToString) {
+			addDataToString
+		}
+		dataFields.forEach [
+			if (shouldAddGetter) {
+				addGetter(Visibility.PUBLIC)
+			}
+			simpleName = "_" + simpleName.toFirstLower
+		]
+	}
+
+	/**
+	 * @since 2.7
+	 * @noextend
+	 * @noreference
+ 	 */
+	@Deprecated
+	static class Util {
+
+		extension TransformationContext context
+
+		new(TransformationContext context) {
+			this.context = context
+		}
+
+		def getDataFields(ClassDeclaration it) {
+			declaredFields.filter[!static && isThePrimaryGeneratedJavaElement]
+		}
+
+		def getDataFields(MutableClassDeclaration it) {
+			declaredFields.filter[!static && isThePrimaryGeneratedJavaElement]
+		}
+		
+		def void addDataToString(MutableClassDeclaration cls) {
+			cls.addMethod("toString") [
+				primarySourceElement = cls.primarySourceElement
+				returnType = string
+				addAnnotation(newAnnotationReference(Override))
+				addAnnotation(newAnnotationReference(Pure))
+				body = '''
+					String result = new «org.eclipse.xtext.xbase.lib.util.ToStringHelper»().toString(this);
+					return result;
+				'''
+			]
+		}
+	}
+
+}
diff --git a/java/org/eclipse/xtend/lib/DataProcessor.java b/java/org/eclipse/xtend/lib/DataProcessor.java
new file mode 100644
index 0000000..dda2ca9
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/DataProcessor.java
@@ -0,0 +1,130 @@
+package org.eclipse.xtend.lib;
+
+import java.util.function.Consumer;
+import org.eclipse.xtend.lib.annotations.AccessorsProcessor;
+import org.eclipse.xtend.lib.annotations.EqualsHashCodeProcessor;
+import org.eclipse.xtend.lib.annotations.FinalFieldsConstructorProcessor;
+import org.eclipse.xtend.lib.annotations.ToStringProcessor;
+import org.eclipse.xtend.lib.macro.AbstractClassProcessor;
+import org.eclipse.xtend.lib.macro.TransformationContext;
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableMethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.Visibility;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.lib.Pure;
+import org.eclipse.xtext.xbase.lib.StringExtensions;
+import org.eclipse.xtext.xbase.lib.util.ToStringHelper;
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Deprecated
+@SuppressWarnings("all")
+public class DataProcessor extends AbstractClassProcessor {
+  /**
+   * @since 2.7
+   * @noextend
+   * @noreference
+   */
+  @Deprecated
+  public static class Util {
+    @Extension
+    private TransformationContext context;
+    
+    public Util(final TransformationContext context) {
+      this.context = context;
+    }
+    
+    public Iterable<? extends FieldDeclaration> getDataFields(final ClassDeclaration it) {
+      final Function1<FieldDeclaration, Boolean> _function = (FieldDeclaration it_1) -> {
+        return Boolean.valueOf(((!it_1.isStatic()) && this.context.isThePrimaryGeneratedJavaElement(it_1)));
+      };
+      return IterableExtensions.filter(it.getDeclaredFields(), _function);
+    }
+    
+    public Iterable<? extends MutableFieldDeclaration> getDataFields(final MutableClassDeclaration it) {
+      final Function1<MutableFieldDeclaration, Boolean> _function = (MutableFieldDeclaration it_1) -> {
+        return Boolean.valueOf(((!it_1.isStatic()) && this.context.isThePrimaryGeneratedJavaElement(it_1)));
+      };
+      return IterableExtensions.filter(it.getDeclaredFields(), _function);
+    }
+    
+    public void addDataToString(final MutableClassDeclaration cls) {
+      final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration it) -> {
+        this.context.setPrimarySourceElement(it, this.context.getPrimarySourceElement(cls));
+        it.setReturnType(this.context.getString());
+        it.addAnnotation(this.context.newAnnotationReference(Override.class));
+        it.addAnnotation(this.context.newAnnotationReference(Pure.class));
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("String result = new ");
+            _builder.append(ToStringHelper.class);
+            _builder.append("().toString(this);");
+            _builder.newLineIfNotEmpty();
+            _builder.append("return result;");
+            _builder.newLine();
+          }
+        };
+        it.setBody(_client);
+      };
+      cls.addMethod("toString", _function);
+    }
+  }
+  
+  @Override
+  public void doTransform(final MutableClassDeclaration it, @Extension final TransformationContext context) {
+    @Extension
+    final DataProcessor.Util util = new DataProcessor.Util(context);
+    @Extension
+    final AccessorsProcessor.Util getterUtil = new AccessorsProcessor.Util(context);
+    @Extension
+    final EqualsHashCodeProcessor.Util ehUtil = new EqualsHashCodeProcessor.Util(context);
+    @Extension
+    final ToStringProcessor.Util toStringUtil = new ToStringProcessor.Util(context);
+    @Extension
+    final FinalFieldsConstructorProcessor.Util requiredArgsUtil = new FinalFieldsConstructorProcessor.Util(context);
+    final Consumer<MutableFieldDeclaration> _function = (MutableFieldDeclaration it_1) -> {
+      it_1.setFinal(true);
+    };
+    util.getDataFields(it).forEach(_function);
+    boolean _needsFinalFieldConstructor = requiredArgsUtil.needsFinalFieldConstructor(it);
+    if (_needsFinalFieldConstructor) {
+      requiredArgsUtil.addFinalFieldsConstructor(it);
+    }
+    boolean _hasHashCode = ehUtil.hasHashCode(it);
+    boolean _not = (!_hasHashCode);
+    if (_not) {
+      ehUtil.addHashCode(it, util.getDataFields(it), ehUtil.hasSuperHashCode(it));
+    }
+    boolean _hasEquals = ehUtil.hasEquals(it);
+    boolean _not_1 = (!_hasEquals);
+    if (_not_1) {
+      ehUtil.addEquals(it, util.getDataFields(it), ehUtil.hasSuperEquals(it));
+    }
+    boolean _hasToString = toStringUtil.hasToString(it);
+    boolean _not_2 = (!_hasToString);
+    if (_not_2) {
+      util.addDataToString(it);
+    }
+    final Consumer<MutableFieldDeclaration> _function_1 = (MutableFieldDeclaration it_1) -> {
+      boolean _shouldAddGetter = getterUtil.shouldAddGetter(it_1);
+      if (_shouldAddGetter) {
+        getterUtil.addGetter(it_1, Visibility.PUBLIC);
+      }
+      String _firstLower = StringExtensions.toFirstLower(it_1.getSimpleName());
+      String _plus = ("_" + _firstLower);
+      it_1.setSimpleName(_plus);
+    };
+    util.getDataFields(it).forEach(_function_1);
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/Lib.gwt.xml b/java/org/eclipse/xtend/lib/Lib.gwt.xml
new file mode 100644
index 0000000..4f9f808
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/Lib.gwt.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
+<module>
+	<source path=""/>
+	<inherits name="org.eclipse.xtext.xbase.lib.Lib" />
+</module>
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/Property.java b/java/org/eclipse/xtend/lib/Property.java
new file mode 100644
index 0000000..e228f04
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/Property.java
@@ -0,0 +1,24 @@
+package org.eclipse.xtend.lib;
+
+import com.google.common.annotations.GwtCompatible;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.eclipse.xtend.lib.annotations.Accessors;
+import org.eclipse.xtend.lib.macro.Active;
+
+/**
+ * Creates a getter and setter method for the annotated field.
+ * Prepends the field name with an underscore (e.g. <code>_myField</code>)
+ * 
+ * @author Sven Efftinge
+ * @deprecated use {@link Accessors} instead
+ */
+@GwtCompatible
+@Target(ElementType.FIELD)
+@Active(PropertyProcessor.class)
+@Deprecated
+@Documented
+@SuppressWarnings("all")
+public @interface Property {
+}
diff --git a/java/org/eclipse/xtend/lib/Property.xtend b/java/org/eclipse/xtend/lib/Property.xtend
new file mode 100644
index 0000000..80b7403
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/Property.xtend
@@ -0,0 +1,48 @@
+package org.eclipse.xtend.lib
+
+import com.google.common.annotations.GwtCompatible
+import java.lang.annotation.ElementType
+import java.lang.annotation.Target
+import org.eclipse.xtend.lib.annotations.Accessors
+import org.eclipse.xtend.lib.annotations.AccessorsProcessor
+import org.eclipse.xtend.lib.macro.AbstractFieldProcessor
+import org.eclipse.xtend.lib.macro.Active
+import org.eclipse.xtend.lib.macro.TransformationContext
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration
+import org.eclipse.xtend.lib.macro.declaration.Visibility
+import java.lang.annotation.Documented
+
+/**
+ * Creates a getter and setter method for the annotated field.
+ * Prepends the field name with an underscore (e.g. <code>_myField</code>)
+ * 
+ * @author Sven Efftinge
+ * @deprecated use {@link Accessors} instead
+ */
+@GwtCompatible
+@Target(ElementType.FIELD)
+@Active(PropertyProcessor)
+@Deprecated
+@Documented
+annotation Property {
+}
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Deprecated
+class PropertyProcessor extends AbstractFieldProcessor {
+	
+	override doTransform(MutableFieldDeclaration it, extension TransformationContext context) {
+		extension val util = new AccessorsProcessor.Util(context)
+		if (!hasGetter) {
+			addGetter(Visibility.PUBLIC)
+		}
+		if (!final && !hasSetter) {
+			addSetter(Visibility.PUBLIC)
+		}
+		simpleName = "_" + simpleName.toFirstLower
+	}
+}
diff --git a/java/org/eclipse/xtend/lib/PropertyProcessor.java b/java/org/eclipse/xtend/lib/PropertyProcessor.java
new file mode 100644
index 0000000..a3e746c
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/PropertyProcessor.java
@@ -0,0 +1,35 @@
+package org.eclipse.xtend.lib;
+
+import org.eclipse.xtend.lib.annotations.AccessorsProcessor;
+import org.eclipse.xtend.lib.macro.AbstractFieldProcessor;
+import org.eclipse.xtend.lib.macro.TransformationContext;
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.Visibility;
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.eclipse.xtext.xbase.lib.StringExtensions;
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Deprecated
+@SuppressWarnings("all")
+public class PropertyProcessor extends AbstractFieldProcessor {
+  @Override
+  public void doTransform(final MutableFieldDeclaration it, @Extension final TransformationContext context) {
+    @Extension
+    final AccessorsProcessor.Util util = new AccessorsProcessor.Util(context);
+    boolean _hasGetter = util.hasGetter(it);
+    boolean _not = (!_hasGetter);
+    if (_not) {
+      util.addGetter(it, Visibility.PUBLIC);
+    }
+    if (((!it.isFinal()) && (!util.hasSetter(it)))) {
+      util.addSetter(it, Visibility.PUBLIC);
+    }
+    String _firstLower = StringExtensions.toFirstLower(it.getSimpleName());
+    String _plus = ("_" + _firstLower);
+    it.setSimpleName(_plus);
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/AccessorType.java b/java/org/eclipse/xtend/lib/annotations/AccessorType.java
new file mode 100644
index 0000000..7b60ef3
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/AccessorType.java
@@ -0,0 +1,39 @@
+/**
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ * 
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * @since 2.7
+ * @noreference
+ */
+@Beta
+@GwtCompatible
+@SuppressWarnings("all")
+public enum AccessorType {
+  PUBLIC_GETTER,
+  
+  PROTECTED_GETTER,
+  
+  PACKAGE_GETTER,
+  
+  PRIVATE_GETTER,
+  
+  PUBLIC_SETTER,
+  
+  PROTECTED_SETTER,
+  
+  PACKAGE_SETTER,
+  
+  PRIVATE_SETTER,
+  
+  NONE;
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/Accessors.java b/java/org/eclipse/xtend/lib/annotations/Accessors.java
new file mode 100644
index 0000000..8cc25fd
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/Accessors.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ * 
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.eclipse.xtend.lib.macro.Active;
+
+/**
+ * Creates getters and setters for annotated fields or for all fields in an annotated class.
+ * <p>
+ * Annotated on a field
+ * <ul>
+ * <li>Creates a getter for that field if none exists. For primitive boolean properties, the "is"-prefix is used.</li>
+ * <li>Creates a setter for that field if it is not final and no setter exists</li>
+ * <li>By default the accessors are public</li>
+ * <li>If the {@link AccessorType}[] argument is given, only the listed
+ * accessors with the specified visibility will be generated</li>
+ * <li>By default the accessors will be deprecated if the field is annotated as such.
+ * This can be changed by explicitly providing {@link Accessors#deprecationPolicy deprecationPolicy}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Annotated on a class
+ * <ul>
+ * <li>Creates accessors for all non-static fields of that class as specified
+ * above</li>
+ * <li>Creates a constructor taking all final fields of the class if no
+ * constructor exists yet. If there already is a constructor and you want the
+ * default one on top of that, you can use the {@link FinalFieldsConstructor}
+ * annotation.</li>
+ * </ul>
+ * </p>
+ * Field-level annotations have precedence over a class-level annotation. Accessors can be suppressed completely by using {@link AccessorType#NONE}.
+ * This annotation can also be used to fine-tune the getters generated by {@link Data}.
+ * @since 2.7
+ */
+@GwtCompatible
+@Target({ ElementType.FIELD, ElementType.TYPE })
+@Active(AccessorsProcessor.class)
+@Documented
+@SuppressWarnings("all")
+public @interface Accessors {
+  /**
+   * Describes the access modifiers for generated accessors. Valid combinations
+   * include at most one type for getters and one for setters.
+   * Accessors may be suppressed by passing {@link AccessorType#NONE}.
+   */
+  public AccessorType[] value() default { AccessorType.PUBLIC_GETTER, AccessorType.PUBLIC_SETTER };
+  /**
+   * Describes when {@code @Deprecated} will be added to generated accessors.<br>
+   * If it is not wanted or needed, pass {@link AccessorsDeprecationPolicy#NEVER} to prevent the annotation from being added.
+   * @since 2.23
+   */
+  @Beta
+  public AccessorsDeprecationPolicy deprecationPolicy() default AccessorsDeprecationPolicy.SAME_AS_FIELD;
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/Accessors.xtend b/java/org/eclipse/xtend/lib/annotations/Accessors.xtend
new file mode 100644
index 0000000..a929f67
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/Accessors.xtend
@@ -0,0 +1,363 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.annotations
+
+import com.google.common.annotations.Beta
+import com.google.common.annotations.GwtCompatible
+import java.lang.annotation.ElementType
+import java.lang.annotation.Target
+import java.util.List
+import org.eclipse.xtend.lib.macro.Active
+import org.eclipse.xtend.lib.macro.TransformationContext
+import org.eclipse.xtend.lib.macro.TransformationParticipant
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference
+import org.eclipse.xtend.lib.macro.declaration.AnnotationTarget
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableMemberDeclaration
+import org.eclipse.xtend.lib.macro.declaration.TypeReference
+import org.eclipse.xtend.lib.macro.declaration.Visibility
+import java.lang.annotation.Documented
+
+/**
+ * Creates getters and setters for annotated fields or for all fields in an annotated class.
+ * <p>
+ * Annotated on a field
+ * <ul>
+ * <li>Creates a getter for that field if none exists. For primitive boolean properties, the "is"-prefix is used.</li>
+ * <li>Creates a setter for that field if it is not final and no setter exists</li>
+ * <li>By default the accessors are public</li>
+ * <li>If the {@link AccessorType}[] argument is given, only the listed
+ * accessors with the specified visibility will be generated</li>
+ * <li>By default the accessors will be deprecated if the field is annotated as such.
+ * This can be changed by explicitly providing {@link Accessors#deprecationPolicy deprecationPolicy}</li>
+ * </ul>
+ * </p>
+ * <p>
+ * Annotated on a class
+ * <ul>
+ * <li>Creates accessors for all non-static fields of that class as specified
+ * above</li>
+ * <li>Creates a constructor taking all final fields of the class if no
+ * constructor exists yet. If there already is a constructor and you want the
+ * default one on top of that, you can use the {@link FinalFieldsConstructor}
+ * annotation.</li>
+ * </ul>
+ * </p>
+ * Field-level annotations have precedence over a class-level annotation. Accessors can be suppressed completely by using {@link AccessorType#NONE}.
+ * This annotation can also be used to fine-tune the getters generated by {@link Data}.
+ * @since 2.7
+ */
+@GwtCompatible
+@Target(ElementType.FIELD, ElementType.TYPE)
+@Active(AccessorsProcessor)
+@Documented
+annotation Accessors {
+	/**
+	 * Describes the access modifiers for generated accessors. Valid combinations
+	 * include at most one type for getters and one for setters.
+	 * Accessors may be suppressed by passing {@link AccessorType#NONE}.
+	 */
+	AccessorType[] value = #[AccessorType.PUBLIC_GETTER, AccessorType.PUBLIC_SETTER]
+	/**
+	 * Describes when {@code @Deprecated} will be added to generated accessors.<br>
+	 * If it is not wanted or needed, pass {@link AccessorsDeprecationPolicy#NEVER} to prevent the annotation from being added.
+	 * @since 2.23
+	 */
+	@Beta
+	AccessorsDeprecationPolicy deprecationPolicy = AccessorsDeprecationPolicy.SAME_AS_FIELD
+}
+
+/**
+ * @since 2.7
+ * @noreference
+ */
+@Beta
+@GwtCompatible
+enum AccessorType {
+	PUBLIC_GETTER,
+	PROTECTED_GETTER,
+	PACKAGE_GETTER,
+	PRIVATE_GETTER,
+	PUBLIC_SETTER,
+	PROTECTED_SETTER,
+	PACKAGE_SETTER,
+	PRIVATE_SETTER,
+	NONE
+}
+
+/**
+ * @since 2.23
+ */
+@Beta
+@GwtCompatible
+enum AccessorsDeprecationPolicy {
+	SAME_AS_FIELD,
+	ONLY_GETTER,
+	ONLY_SETTER,
+	ALWAYS,
+	NEVER
+}
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+class AccessorsProcessor implements TransformationParticipant<MutableMemberDeclaration> {
+
+	override doTransform(List<? extends MutableMemberDeclaration> elements, extension TransformationContext context) {
+		elements.forEach[transform(context)]
+	}
+
+	def dispatch void transform(MutableFieldDeclaration it, extension TransformationContext context) {
+		extension val util = new AccessorsProcessor.Util(context)
+		val annot = accessorsAnnotation
+
+		if (shouldAddGetter) {
+			addGetter(getterType.toVisibility)
+		}
+		else if (annot !== null && annot.deprecationPolicyAsEnum === AccessorsDeprecationPolicy.ONLY_GETTER){
+			it.addWarning(
+					'''
+					Field «simpleName» needs no getter, but deprecationPolicy is ONLY_GETTER.
+					Explicitly setting it has no effect, as no getter will be generated.
+					Use deprecation policy NEVER to disable accessors deprecation and remove this warning.
+					'''
+				)
+		}
+
+		if (shouldAddSetter) {
+			addSetter(setterType.toVisibility)
+		}
+		else if(annot !== null && annot.deprecationPolicyAsEnum === AccessorsDeprecationPolicy.ONLY_SETTER){
+			it.addWarning(
+				'''
+				Field «simpleName» needs no setter, but deprecationPolicy is ONLY_SETTER.
+				Explicitly setting it has no effect, as no setter will be generated.
+				Use deprecation policy NEVER to disable accessors deprecation and remove this warning.
+				'''
+			)
+		}
+	}
+
+	def dispatch void transform(MutableClassDeclaration it, extension TransformationContext context) {
+		if (findAnnotation(Data.findTypeGlobally) !== null) {
+			return
+		}
+		val extension requiredArgsUtil = new FinalFieldsConstructorProcessor.Util(context)
+		if (needsFinalFieldConstructor || findAnnotation(FinalFieldsConstructor.findTypeGlobally) !== null) {
+			addFinalFieldsConstructor
+		}
+		declaredFields.filter[!static && thePrimaryGeneratedJavaElement].forEach[_transform(context)]
+	}
+
+	/**
+	 * @since 2.7
+	 * @noextend
+	 * @noreference
+	 */
+	@Beta
+	static class Util {
+		extension TransformationContext context
+
+		new(TransformationContext context) {
+			this.context = context
+		}
+
+		def toVisibility(AccessorType type) {
+			switch type {
+				case PUBLIC_GETTER: Visibility.PUBLIC
+				case PROTECTED_GETTER: Visibility.PROTECTED
+				case PACKAGE_GETTER: Visibility.DEFAULT
+				case PRIVATE_GETTER: Visibility.PRIVATE
+				case PUBLIC_SETTER: Visibility.PUBLIC
+				case PROTECTED_SETTER: Visibility.PROTECTED
+				case PACKAGE_SETTER: Visibility.DEFAULT
+				case PRIVATE_SETTER: Visibility.PRIVATE
+				default: throw new IllegalArgumentException('''Cannot convert «type»''')
+			}
+		}
+
+		def hasGetter(FieldDeclaration it) {
+			possibleGetterNames.exists[name| declaringType.findDeclaredMethod(name) !== null]
+		}
+
+		def shouldAddGetter(FieldDeclaration it) {
+			!hasGetter && getterType !== AccessorType.NONE
+		}
+
+		@SuppressWarnings('unchecked')
+		def getGetterType(FieldDeclaration it) {
+			val annotation = accessorsAnnotation ?: declaringType.accessorsAnnotation
+			if (annotation !== null) {
+				val types = annotation.getEnumArrayValue("value").map[AccessorType.valueOf(simpleName)]
+				return types.findFirst[name.endsWith("GETTER")] ?: AccessorType.NONE
+			}
+			return null;
+		}
+
+		def getAccessorsAnnotation(AnnotationTarget it) {
+			findAnnotation(Accessors.findTypeGlobally)
+		}
+
+		def getDeprecatedAnnotation(AnnotationTarget it) {
+			findAnnotation(Deprecated.findTypeGlobally)
+		}
+
+		def getDeprecationPolicyAsEnum(AnnotationReference annot){
+			AccessorsDeprecationPolicy.valueOf(annot.getEnumValue('deprecationPolicy').simpleName) 
+		}
+
+		def validateGetter(MutableFieldDeclaration field) {
+		}
+
+		def getGetterName(FieldDeclaration it) {
+			possibleGetterNames.head
+		}
+		
+		def List<String> getPossibleGetterNames(FieldDeclaration it) {
+			val names = newArrayList
+			// common case: a boolean field already starts with 'is'. Allow field name as getter method name
+			if (type.orObject.isBooleanType && simpleName.startsWith('is') && simpleName.length>2 && Character.isUpperCase(simpleName.charAt(2))) {
+				names += simpleName
+			}
+			names.addAll((if(type.orObject.isBooleanType) #["is", "get"] else #["get"]).map[prefix|prefix + simpleName.toFirstUpper])
+			return names
+		}
+
+		def isBooleanType(TypeReference it) {
+			!inferred && it == primitiveBoolean
+		}
+
+		def void addGetter(MutableFieldDeclaration field, Visibility visibility) {
+			field.validateGetter
+			field.markAsRead
+			field.declaringType.addMethod(field.getterName) [
+				primarySourceElement = field.primarySourceElement
+				addAnnotation(newAnnotationReference(Pure))
+				
+				// Generate Override if not overriding a final method
+				val superGetters = overriddenOrImplementedMethods
+				if(!superGetters.empty){
+					if(superGetters.exists[final]) {
+						field.addError('''Adding a getter to the field «field.simpleName» would override a final method.''')
+					}
+					else {
+						addAnnotation(newAnnotationReference(Override))
+					}
+				}
+				
+				val annot = field.accessorsAnnotation
+				if(annot !== null) {
+					// Enforce deprecation policy for getter
+					switch annot.deprecationPolicyAsEnum {
+					case ALWAYS,
+					case ONLY_GETTER:
+						addAnnotation(newAnnotationReference(Deprecated))
+					case SAME_AS_FIELD:
+						if(field.deprecatedAnnotation !== null)
+							addAnnotation(newAnnotationReference(Deprecated))
+					case ONLY_SETTER,
+					case NEVER: {} // No-op
+					default: throw new IllegalArgumentException('''Cannot determine deprecation policy for field «field.simpleName»''')
+					}
+				} // if(annot !== null)
+
+				returnType = field.type.orObject
+				body = '''return «field.fieldOwner».«field.simpleName»;'''
+				static = field.static
+				it.visibility = visibility
+			]
+		}
+
+		@SuppressWarnings('unchecked')
+		def getSetterType(FieldDeclaration it) {
+			val annotation = accessorsAnnotation ?: declaringType.accessorsAnnotation
+			if (annotation !== null) {
+				val types = annotation.getEnumArrayValue("value").map[AccessorType.valueOf(simpleName)]
+				return types.findFirst[name.endsWith("SETTER")] ?: AccessorType.NONE
+			}
+			return null
+		}
+
+		private def fieldOwner(MutableFieldDeclaration it) {
+			if(static) declaringType.newTypeReference else "this"
+		}
+
+		def hasSetter(FieldDeclaration it) {
+			declaringType.findDeclaredMethod(setterName, type.orObject) !== null
+		}
+
+		def getSetterName(FieldDeclaration it) {
+			"set" + simpleName.toFirstUpper
+		}
+
+		def shouldAddSetter(FieldDeclaration it) {
+			!final && !hasSetter && setterType !== AccessorType.NONE
+		}
+
+		def validateSetter(MutableFieldDeclaration field) {
+			if (field.final) {
+				field.addError("Cannot set a final field")
+			}
+			if (field.type === null || field.type.inferred) {
+				field.addError("Type cannot be inferred.")
+				return
+			}
+		}
+
+		def void addSetter(MutableFieldDeclaration field, Visibility visibility) {
+			field.validateSetter
+			field.declaringType.addMethod(field.setterName) [
+				primarySourceElement = field.primarySourceElement
+				returnType = primitiveVoid
+				
+				// Generate Override if not overriding a final method
+				val superSetters = overriddenOrImplementedMethods
+				if(!superSetters.empty){
+					if(superSetters.exists[final]) {
+						field.addError('''Adding a setter to the field «field.simpleName» would override a final method.''')
+					}
+					else {
+						addAnnotation(newAnnotationReference(Override))
+					}
+				}
+
+				val annot = field.accessorsAnnotation
+				if(annot !== null) {
+					// Enforce deprecation policy for setter
+					switch annot.deprecationPolicyAsEnum {
+					case ALWAYS,
+					case ONLY_SETTER:
+						addAnnotation(newAnnotationReference(Deprecated))
+					case SAME_AS_FIELD:
+						if(field.deprecatedAnnotation !== null)
+							addAnnotation(newAnnotationReference(Deprecated))
+					case ONLY_GETTER,
+					case NEVER: {} // No-op
+					default: throw new IllegalArgumentException('''Cannot determine deprecation policy for field «field.simpleName»''')
+					}
+				} // if(annot !== null)
+
+				val param = addParameter(field.simpleName, field.type.orObject)
+				body = '''«field.fieldOwner».«field.simpleName» = «param.simpleName»;'''
+				static = field.static
+				it.visibility = visibility
+			]
+		}
+		
+		private def orObject(TypeReference ref) {
+			if (ref === null) object else ref
+		}
+	}
+
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/AccessorsDeprecationPolicy.java b/java/org/eclipse/xtend/lib/annotations/AccessorsDeprecationPolicy.java
new file mode 100644
index 0000000..7f537dd
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/AccessorsDeprecationPolicy.java
@@ -0,0 +1,30 @@
+/**
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ * 
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * @since 2.23
+ */
+@Beta
+@GwtCompatible
+@SuppressWarnings("all")
+public enum AccessorsDeprecationPolicy {
+  SAME_AS_FIELD,
+  
+  ONLY_GETTER,
+  
+  ONLY_SETTER,
+  
+  ALWAYS,
+  
+  NEVER;
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/AccessorsProcessor.java b/java/org/eclipse/xtend/lib/annotations/AccessorsProcessor.java
new file mode 100644
index 0000000..62ba3e6
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/AccessorsProcessor.java
@@ -0,0 +1,517 @@
+/**
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ * 
+ * SPDX-License-Identifier: EPL-2.0
+ */
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+import java.util.function.Consumer;
+import org.eclipse.xtend.lib.annotations.FinalFieldsConstructorProcessor;
+import org.eclipse.xtend.lib.macro.TransformationContext;
+import org.eclipse.xtend.lib.macro.TransformationParticipant;
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
+import org.eclipse.xtend.lib.macro.declaration.AnnotationTarget;
+import org.eclipse.xtend.lib.macro.declaration.EnumerationValueDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableMemberDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableMethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableParameterDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+import org.eclipse.xtend.lib.macro.declaration.Visibility;
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.Conversions;
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.ListExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.lib.Pure;
+import org.eclipse.xtext.xbase.lib.StringExtensions;
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+@SuppressWarnings("all")
+public class AccessorsProcessor implements TransformationParticipant<MutableMemberDeclaration> {
+  /**
+   * @since 2.7
+   * @noextend
+   * @noreference
+   */
+  @Beta
+  public static class Util {
+    @Extension
+    private TransformationContext context;
+    
+    public Util(final TransformationContext context) {
+      this.context = context;
+    }
+    
+    public Visibility toVisibility(final AccessorType type) {
+      Visibility _switchResult = null;
+      if (type != null) {
+        switch (type) {
+          case PUBLIC_GETTER:
+            _switchResult = Visibility.PUBLIC;
+            break;
+          case PROTECTED_GETTER:
+            _switchResult = Visibility.PROTECTED;
+            break;
+          case PACKAGE_GETTER:
+            _switchResult = Visibility.DEFAULT;
+            break;
+          case PRIVATE_GETTER:
+            _switchResult = Visibility.PRIVATE;
+            break;
+          case PUBLIC_SETTER:
+            _switchResult = Visibility.PUBLIC;
+            break;
+          case PROTECTED_SETTER:
+            _switchResult = Visibility.PROTECTED;
+            break;
+          case PACKAGE_SETTER:
+            _switchResult = Visibility.DEFAULT;
+            break;
+          case PRIVATE_SETTER:
+            _switchResult = Visibility.PRIVATE;
+            break;
+          default:
+            StringConcatenation _builder = new StringConcatenation();
+            _builder.append("Cannot convert ");
+            _builder.append(type);
+            throw new IllegalArgumentException(_builder.toString());
+        }
+      } else {
+        StringConcatenation _builder = new StringConcatenation();
+        _builder.append("Cannot convert ");
+        _builder.append(type);
+        throw new IllegalArgumentException(_builder.toString());
+      }
+      return _switchResult;
+    }
+    
+    public boolean hasGetter(final FieldDeclaration it) {
+      final Function1<String, Boolean> _function = (String name) -> {
+        MethodDeclaration _findDeclaredMethod = it.getDeclaringType().findDeclaredMethod(name);
+        return Boolean.valueOf((_findDeclaredMethod != null));
+      };
+      return IterableExtensions.<String>exists(this.getPossibleGetterNames(it), _function);
+    }
+    
+    public boolean shouldAddGetter(final FieldDeclaration it) {
+      return ((!this.hasGetter(it)) && (this.getGetterType(it) != AccessorType.NONE));
+    }
+    
+    @SuppressWarnings("unchecked")
+    public AccessorType getGetterType(final FieldDeclaration it) {
+      AnnotationReference _elvis = null;
+      AnnotationReference _accessorsAnnotation = this.getAccessorsAnnotation(it);
+      if (_accessorsAnnotation != null) {
+        _elvis = _accessorsAnnotation;
+      } else {
+        AnnotationReference _accessorsAnnotation_1 = this.getAccessorsAnnotation(it.getDeclaringType());
+        _elvis = _accessorsAnnotation_1;
+      }
+      final AnnotationReference annotation = _elvis;
+      if ((annotation != null)) {
+        final Function1<EnumerationValueDeclaration, AccessorType> _function = (EnumerationValueDeclaration it_1) -> {
+          return AccessorType.valueOf(it_1.getSimpleName());
+        };
+        final List<AccessorType> types = ListExtensions.<EnumerationValueDeclaration, AccessorType>map(((List<EnumerationValueDeclaration>)Conversions.doWrapArray(annotation.getEnumArrayValue("value"))), _function);
+        AccessorType _elvis_1 = null;
+        final Function1<AccessorType, Boolean> _function_1 = (AccessorType it_1) -> {
+          return Boolean.valueOf(it_1.name().endsWith("GETTER"));
+        };
+        AccessorType _findFirst = IterableExtensions.<AccessorType>findFirst(types, _function_1);
+        if (_findFirst != null) {
+          _elvis_1 = _findFirst;
+        } else {
+          _elvis_1 = AccessorType.NONE;
+        }
+        return _elvis_1;
+      }
+      return null;
+    }
+    
+    public AnnotationReference getAccessorsAnnotation(final AnnotationTarget it) {
+      return it.findAnnotation(this.context.findTypeGlobally(Accessors.class));
+    }
+    
+    public AnnotationReference getDeprecatedAnnotation(final AnnotationTarget it) {
+      return it.findAnnotation(this.context.findTypeGlobally(Deprecated.class));
+    }
+    
+    public AccessorsDeprecationPolicy getDeprecationPolicyAsEnum(final AnnotationReference annot) {
+      return AccessorsDeprecationPolicy.valueOf(annot.getEnumValue("deprecationPolicy").getSimpleName());
+    }
+    
+    public Object validateGetter(final MutableFieldDeclaration field) {
+      return null;
+    }
+    
+    public String getGetterName(final FieldDeclaration it) {
+      return IterableExtensions.<String>head(this.getPossibleGetterNames(it));
+    }
+    
+    public List<String> getPossibleGetterNames(final FieldDeclaration it) {
+      final ArrayList<String> names = CollectionLiterals.<String>newArrayList();
+      if ((((this.isBooleanType(this.orObject(it.getType())) && it.getSimpleName().startsWith("is")) && (it.getSimpleName().length() > 2)) && Character.isUpperCase(it.getSimpleName().charAt(2)))) {
+        String _simpleName = it.getSimpleName();
+        names.add(_simpleName);
+      }
+      List<String> _xifexpression = null;
+      boolean _isBooleanType = this.isBooleanType(this.orObject(it.getType()));
+      if (_isBooleanType) {
+        _xifexpression = Collections.<String>unmodifiableList(CollectionLiterals.<String>newArrayList("is", "get"));
+      } else {
+        _xifexpression = Collections.<String>unmodifiableList(CollectionLiterals.<String>newArrayList("get"));
+      }
+      final Function1<String, String> _function = (String prefix) -> {
+        String _firstUpper = StringExtensions.toFirstUpper(it.getSimpleName());
+        return (prefix + _firstUpper);
+      };
+      names.addAll(ListExtensions.<String, String>map(_xifexpression, _function));
+      return names;
+    }
+    
+    public boolean isBooleanType(final TypeReference it) {
+      return ((!it.isInferred()) && Objects.equal(it, this.context.getPrimitiveBoolean()));
+    }
+    
+    public void addGetter(final MutableFieldDeclaration field, final Visibility visibility) {
+      this.validateGetter(field);
+      field.markAsRead();
+      final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration it) -> {
+        this.context.setPrimarySourceElement(it, this.context.getPrimarySourceElement(field));
+        it.addAnnotation(this.context.newAnnotationReference(Pure.class));
+        final Iterable<? extends MethodDeclaration> superGetters = it.getOverriddenOrImplementedMethods();
+        boolean _isEmpty = IterableExtensions.isEmpty(superGetters);
+        boolean _not = (!_isEmpty);
+        if (_not) {
+          final Function1<MethodDeclaration, Boolean> _function_1 = (MethodDeclaration it_1) -> {
+            return Boolean.valueOf(it_1.isFinal());
+          };
+          boolean _exists = IterableExtensions.exists(superGetters, _function_1);
+          if (_exists) {
+            StringConcatenation _builder = new StringConcatenation();
+            _builder.append("Adding a getter to the field ");
+            String _simpleName = field.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append(" would override a final method.");
+            this.context.addError(field, _builder.toString());
+          } else {
+            it.addAnnotation(this.context.newAnnotationReference(Override.class));
+          }
+        }
+        final AnnotationReference annot = this.getAccessorsAnnotation(field);
+        if ((annot != null)) {
+          AccessorsDeprecationPolicy _deprecationPolicyAsEnum = this.getDeprecationPolicyAsEnum(annot);
+          if (_deprecationPolicyAsEnum != null) {
+            switch (_deprecationPolicyAsEnum) {
+              case ALWAYS:
+              case ONLY_GETTER:
+                it.addAnnotation(this.context.newAnnotationReference(Deprecated.class));
+                break;
+              case SAME_AS_FIELD:
+                AnnotationReference _deprecatedAnnotation = this.getDeprecatedAnnotation(field);
+                boolean _tripleNotEquals = (_deprecatedAnnotation != null);
+                if (_tripleNotEquals) {
+                  it.addAnnotation(this.context.newAnnotationReference(Deprecated.class));
+                }
+                break;
+              case ONLY_SETTER:
+              case NEVER:
+                break;
+              default:
+                StringConcatenation _builder_1 = new StringConcatenation();
+                _builder_1.append("Cannot determine deprecation policy for field ");
+                String _simpleName_1 = field.getSimpleName();
+                _builder_1.append(_simpleName_1);
+                throw new IllegalArgumentException(_builder_1.toString());
+            }
+          } else {
+            StringConcatenation _builder_1 = new StringConcatenation();
+            _builder_1.append("Cannot determine deprecation policy for field ");
+            String _simpleName_1 = field.getSimpleName();
+            _builder_1.append(_simpleName_1);
+            throw new IllegalArgumentException(_builder_1.toString());
+          }
+        }
+        it.setReturnType(this.orObject(field.getType()));
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("return ");
+            Object _fieldOwner = Util.this.fieldOwner(field);
+            _builder.append(_fieldOwner);
+            _builder.append(".");
+            String _simpleName = field.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append(";");
+          }
+        };
+        it.setBody(_client);
+        it.setStatic(field.isStatic());
+        it.setVisibility(visibility);
+      };
+      field.getDeclaringType().addMethod(this.getGetterName(field), _function);
+    }
+    
+    @SuppressWarnings("unchecked")
+    public AccessorType getSetterType(final FieldDeclaration it) {
+      AnnotationReference _elvis = null;
+      AnnotationReference _accessorsAnnotation = this.getAccessorsAnnotation(it);
+      if (_accessorsAnnotation != null) {
+        _elvis = _accessorsAnnotation;
+      } else {
+        AnnotationReference _accessorsAnnotation_1 = this.getAccessorsAnnotation(it.getDeclaringType());
+        _elvis = _accessorsAnnotation_1;
+      }
+      final AnnotationReference annotation = _elvis;
+      if ((annotation != null)) {
+        final Function1<EnumerationValueDeclaration, AccessorType> _function = (EnumerationValueDeclaration it_1) -> {
+          return AccessorType.valueOf(it_1.getSimpleName());
+        };
+        final List<AccessorType> types = ListExtensions.<EnumerationValueDeclaration, AccessorType>map(((List<EnumerationValueDeclaration>)Conversions.doWrapArray(annotation.getEnumArrayValue("value"))), _function);
+        AccessorType _elvis_1 = null;
+        final Function1<AccessorType, Boolean> _function_1 = (AccessorType it_1) -> {
+          return Boolean.valueOf(it_1.name().endsWith("SETTER"));
+        };
+        AccessorType _findFirst = IterableExtensions.<AccessorType>findFirst(types, _function_1);
+        if (_findFirst != null) {
+          _elvis_1 = _findFirst;
+        } else {
+          _elvis_1 = AccessorType.NONE;
+        }
+        return _elvis_1;
+      }
+      return null;
+    }
+    
+    private Object fieldOwner(final MutableFieldDeclaration it) {
+      Object _xifexpression = null;
+      boolean _isStatic = it.isStatic();
+      if (_isStatic) {
+        _xifexpression = this.context.newTypeReference(it.getDeclaringType());
+      } else {
+        _xifexpression = "this";
+      }
+      return _xifexpression;
+    }
+    
+    public boolean hasSetter(final FieldDeclaration it) {
+      MethodDeclaration _findDeclaredMethod = it.getDeclaringType().findDeclaredMethod(this.getSetterName(it), this.orObject(it.getType()));
+      return (_findDeclaredMethod != null);
+    }
+    
+    public String getSetterName(final FieldDeclaration it) {
+      String _firstUpper = StringExtensions.toFirstUpper(it.getSimpleName());
+      return ("set" + _firstUpper);
+    }
+    
+    public boolean shouldAddSetter(final FieldDeclaration it) {
+      return (((!it.isFinal()) && (!this.hasSetter(it))) && (this.getSetterType(it) != AccessorType.NONE));
+    }
+    
+    public void validateSetter(final MutableFieldDeclaration field) {
+      boolean _isFinal = field.isFinal();
+      if (_isFinal) {
+        this.context.addError(field, "Cannot set a final field");
+      }
+      if (((field.getType() == null) || field.getType().isInferred())) {
+        this.context.addError(field, "Type cannot be inferred.");
+        return;
+      }
+    }
+    
+    public void addSetter(final MutableFieldDeclaration field, final Visibility visibility) {
+      this.validateSetter(field);
+      final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration it) -> {
+        this.context.setPrimarySourceElement(it, this.context.getPrimarySourceElement(field));
+        it.setReturnType(this.context.getPrimitiveVoid());
+        final Iterable<? extends MethodDeclaration> superSetters = it.getOverriddenOrImplementedMethods();
+        boolean _isEmpty = IterableExtensions.isEmpty(superSetters);
+        boolean _not = (!_isEmpty);
+        if (_not) {
+          final Function1<MethodDeclaration, Boolean> _function_1 = (MethodDeclaration it_1) -> {
+            return Boolean.valueOf(it_1.isFinal());
+          };
+          boolean _exists = IterableExtensions.exists(superSetters, _function_1);
+          if (_exists) {
+            StringConcatenation _builder = new StringConcatenation();
+            _builder.append("Adding a setter to the field ");
+            String _simpleName = field.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append(" would override a final method.");
+            this.context.addError(field, _builder.toString());
+          } else {
+            it.addAnnotation(this.context.newAnnotationReference(Override.class));
+          }
+        }
+        final AnnotationReference annot = this.getAccessorsAnnotation(field);
+        if ((annot != null)) {
+          AccessorsDeprecationPolicy _deprecationPolicyAsEnum = this.getDeprecationPolicyAsEnum(annot);
+          if (_deprecationPolicyAsEnum != null) {
+            switch (_deprecationPolicyAsEnum) {
+              case ALWAYS:
+              case ONLY_SETTER:
+                it.addAnnotation(this.context.newAnnotationReference(Deprecated.class));
+                break;
+              case SAME_AS_FIELD:
+                AnnotationReference _deprecatedAnnotation = this.getDeprecatedAnnotation(field);
+                boolean _tripleNotEquals = (_deprecatedAnnotation != null);
+                if (_tripleNotEquals) {
+                  it.addAnnotation(this.context.newAnnotationReference(Deprecated.class));
+                }
+                break;
+              case ONLY_GETTER:
+              case NEVER:
+                break;
+              default:
+                StringConcatenation _builder_1 = new StringConcatenation();
+                _builder_1.append("Cannot determine deprecation policy for field ");
+                String _simpleName_1 = field.getSimpleName();
+                _builder_1.append(_simpleName_1);
+                throw new IllegalArgumentException(_builder_1.toString());
+            }
+          } else {
+            StringConcatenation _builder_1 = new StringConcatenation();
+            _builder_1.append("Cannot determine deprecation policy for field ");
+            String _simpleName_1 = field.getSimpleName();
+            _builder_1.append(_simpleName_1);
+            throw new IllegalArgumentException(_builder_1.toString());
+          }
+        }
+        final MutableParameterDeclaration param = it.addParameter(field.getSimpleName(), this.orObject(field.getType()));
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            Object _fieldOwner = Util.this.fieldOwner(field);
+            _builder.append(_fieldOwner);
+            _builder.append(".");
+            String _simpleName = field.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append(" = ");
+            String _simpleName_1 = param.getSimpleName();
+            _builder.append(_simpleName_1);
+            _builder.append(";");
+          }
+        };
+        it.setBody(_client);
+        it.setStatic(field.isStatic());
+        it.setVisibility(visibility);
+      };
+      field.getDeclaringType().addMethod(this.getSetterName(field), _function);
+    }
+    
+    private TypeReference orObject(final TypeReference ref) {
+      TypeReference _xifexpression = null;
+      if ((ref == null)) {
+        _xifexpression = this.context.getObject();
+      } else {
+        _xifexpression = ref;
+      }
+      return _xifexpression;
+    }
+  }
+  
+  @Override
+  public void doTransform(final List<? extends MutableMemberDeclaration> elements, @Extension final TransformationContext context) {
+    final Consumer<MutableMemberDeclaration> _function = (MutableMemberDeclaration it) -> {
+      this.transform(it, context);
+    };
+    elements.forEach(_function);
+  }
+  
+  protected void _transform(final MutableFieldDeclaration it, @Extension final TransformationContext context) {
+    @Extension
+    final AccessorsProcessor.Util util = new AccessorsProcessor.Util(context);
+    final AnnotationReference annot = util.getAccessorsAnnotation(it);
+    boolean _shouldAddGetter = util.shouldAddGetter(it);
+    if (_shouldAddGetter) {
+      util.addGetter(it, util.toVisibility(util.getGetterType(it)));
+    } else {
+      if (((annot != null) && (util.getDeprecationPolicyAsEnum(annot) == AccessorsDeprecationPolicy.ONLY_GETTER))) {
+        StringConcatenation _builder = new StringConcatenation();
+        _builder.append("Field ");
+        String _simpleName = it.getSimpleName();
+        _builder.append(_simpleName);
+        _builder.append(" needs no getter, but deprecationPolicy is ONLY_GETTER.");
+        _builder.newLineIfNotEmpty();
+        _builder.append("Explicitly setting it has no effect, as no getter will be generated.");
+        _builder.newLine();
+        _builder.append("Use deprecation policy NEVER to disable accessors deprecation and remove this warning.");
+        _builder.newLine();
+        context.addWarning(it, _builder.toString());
+      }
+    }
+    boolean _shouldAddSetter = util.shouldAddSetter(it);
+    if (_shouldAddSetter) {
+      util.addSetter(it, util.toVisibility(util.getSetterType(it)));
+    } else {
+      if (((annot != null) && (util.getDeprecationPolicyAsEnum(annot) == AccessorsDeprecationPolicy.ONLY_SETTER))) {
+        StringConcatenation _builder_1 = new StringConcatenation();
+        _builder_1.append("Field ");
+        String _simpleName_1 = it.getSimpleName();
+        _builder_1.append(_simpleName_1);
+        _builder_1.append(" needs no setter, but deprecationPolicy is ONLY_SETTER.");
+        _builder_1.newLineIfNotEmpty();
+        _builder_1.append("Explicitly setting it has no effect, as no setter will be generated.");
+        _builder_1.newLine();
+        _builder_1.append("Use deprecation policy NEVER to disable accessors deprecation and remove this warning.");
+        _builder_1.newLine();
+        context.addWarning(it, _builder_1.toString());
+      }
+    }
+  }
+  
+  protected void _transform(final MutableClassDeclaration it, @Extension final TransformationContext context) {
+    AnnotationReference _findAnnotation = it.findAnnotation(context.findTypeGlobally(Data.class));
+    boolean _tripleNotEquals = (_findAnnotation != null);
+    if (_tripleNotEquals) {
+      return;
+    }
+    @Extension
+    final FinalFieldsConstructorProcessor.Util requiredArgsUtil = new FinalFieldsConstructorProcessor.Util(context);
+    if ((requiredArgsUtil.needsFinalFieldConstructor(it) || (it.findAnnotation(context.findTypeGlobally(FinalFieldsConstructor.class)) != null))) {
+      requiredArgsUtil.addFinalFieldsConstructor(it);
+    }
+    final Function1<MutableFieldDeclaration, Boolean> _function = (MutableFieldDeclaration it_1) -> {
+      return Boolean.valueOf(((!it_1.isStatic()) && context.isThePrimaryGeneratedJavaElement(it_1)));
+    };
+    final Consumer<MutableFieldDeclaration> _function_1 = (MutableFieldDeclaration it_1) -> {
+      this._transform(it_1, context);
+    };
+    IterableExtensions.filter(it.getDeclaredFields(), _function).forEach(_function_1);
+  }
+  
+  public void transform(final MutableMemberDeclaration it, final TransformationContext context) {
+    if (it instanceof MutableClassDeclaration) {
+      _transform((MutableClassDeclaration)it, context);
+      return;
+    } else if (it instanceof MutableFieldDeclaration) {
+      _transform((MutableFieldDeclaration)it, context);
+      return;
+    } else {
+      throw new IllegalArgumentException("Unhandled parameter types: " +
+        Arrays.<Object>asList(it, context).toString());
+    }
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/Data.java b/java/org/eclipse/xtend/lib/annotations/Data.java
new file mode 100644
index 0000000..2c1010c
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/Data.java
@@ -0,0 +1,30 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.GwtCompatible;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.eclipse.xtend.lib.macro.Active;
+
+/**
+ * Turns this class into a read-only Data object.
+ * 
+ * <p>All non-static, non-transient fields ("data fields") become final and a getter is created for each one. For primitive boolean properties, the "is"-prefix is used.
+ * The generation of getters can be customized using the {@link Accessors} annotation.</p>
+ * <p>If there is no user-defined constructor, a constructor taking all data fields will be generated.
+ * If there already is a constructor, but you want the default one on top of that, you can use the {@link FinalFieldsConstructor} annotation.</p>
+ * <p>Default implementations for {@link Object#equals(Object) equals} and {@link Object#hashCode hashCode} are added if they don't exist yet. See {@link EqualsHashCode} for details.
+ * A {@link Object#toString toString} method is added if it doesn't exist yet. See {@link ToString} for details and customization options.</p>
+ * 
+ * <p>Note: Although no setters are generated, this annotation does not enforce immutability.
+ * Objects passed into the constructor or returned by the getters could be modified by clients.
+ * If immutability is required, you need to implement appropriate defensive copying.</p>
+ * @since 2.7
+ */
+@Target(ElementType.TYPE)
+@Active(DataProcessor.class)
+@Documented
+@GwtCompatible
+@SuppressWarnings("all")
+public @interface Data {
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/Data.xtend b/java/org/eclipse/xtend/lib/annotations/Data.xtend
new file mode 100644
index 0000000..65275d4
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/Data.xtend
@@ -0,0 +1,100 @@
+package org.eclipse.xtend.lib.annotations
+
+import com.google.common.annotations.Beta
+import com.google.common.annotations.GwtCompatible
+import java.lang.annotation.Documented
+import java.lang.annotation.ElementType
+import java.lang.annotation.Target
+import org.eclipse.xtend.lib.macro.AbstractClassProcessor
+import org.eclipse.xtend.lib.macro.Active
+import org.eclipse.xtend.lib.macro.TransformationContext
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration
+import org.eclipse.xtend.lib.macro.declaration.Modifier
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.Visibility
+
+/**
+ * Turns this class into a read-only Data object. 
+ * 
+ * <p>All non-static, non-transient fields ("data fields") become final and a getter is created for each one. For primitive boolean properties, the "is"-prefix is used.
+ * The generation of getters can be customized using the {@link Accessors} annotation.</p>
+ * <p>If there is no user-defined constructor, a constructor taking all data fields will be generated. 
+ * If there already is a constructor, but you want the default one on top of that, you can use the {@link FinalFieldsConstructor} annotation.</p> 
+ * <p>Default implementations for {@link Object#equals(Object) equals} and {@link Object#hashCode hashCode} are added if they don't exist yet. See {@link EqualsHashCode} for details.
+ * A {@link Object#toString toString} method is added if it doesn't exist yet. See {@link ToString} for details and customization options.</p>
+ * 
+ * <p>Note: Although no setters are generated, this annotation does not enforce immutability. 
+ * Objects passed into the constructor or returned by the getters could be modified by clients. 
+ * If immutability is required, you need to implement appropriate defensive copying.</p>
+ * @since 2.7
+ */
+@Target(ElementType.TYPE)
+@Active(DataProcessor)
+@Documented
+@GwtCompatible
+annotation Data {
+}
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+class DataProcessor extends AbstractClassProcessor {
+	override doTransform(MutableClassDeclaration it, extension TransformationContext context) {
+		extension val util = new DataProcessor.Util(context)
+		extension val getterUtil = new AccessorsProcessor.Util(context)
+		extension val ehUtil = new EqualsHashCodeProcessor.Util(context)
+		extension val toStringUtil = new ToStringProcessor.Util(context)
+		extension val requiredArgsUtil = new FinalFieldsConstructorProcessor.Util(context)
+
+		dataFields.forEach [
+			if ((primarySourceElement as FieldDeclaration).modifiers.contains(Modifier.VAR)) {
+				addError("Cannot use the 'var' keyword on a data field")
+			}
+			final = true
+		]
+		if (needsFinalFieldConstructor || findAnnotation(FinalFieldsConstructor.findTypeGlobally) !== null) {
+			addFinalFieldsConstructor
+		}
+		if (!hasHashCode) {
+			addHashCode(dataFields, hasSuperHashCode)
+		}
+		if (!hasEquals) {
+			addEquals(dataFields, hasSuperEquals)
+		}
+		if (!hasToString) {
+			if (superConstructor === null) {
+				addToString(dataFields, toStringConfig ?: new ToStringConfiguration)
+			} else {
+				addReflectiveToString(toStringConfig ?: new ToStringConfiguration)
+			}
+		}
+		dataFields.forEach [
+			if (shouldAddGetter) {
+				addGetter(getterType?.toVisibility ?: Visibility.PUBLIC)
+			}
+		]
+	}
+
+	/**
+	 * @since 2.7
+	 * @noextend
+	 * @noreference
+	 */
+	@Beta
+	static class Util {
+
+		extension TransformationContext context
+
+		new(TransformationContext context) {
+			this.context = context
+		}
+
+		def getDataFields(MutableClassDeclaration it) {
+			declaredFields.filter[!static && ! transient && isThePrimaryGeneratedJavaElement]
+		}
+	}
+
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/DataProcessor.java b/java/org/eclipse/xtend/lib/annotations/DataProcessor.java
new file mode 100644
index 0000000..8a617c0
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/DataProcessor.java
@@ -0,0 +1,133 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import java.util.function.Consumer;
+import org.eclipse.xtend.lib.annotations.AccessorsProcessor;
+import org.eclipse.xtend.lib.annotations.EqualsHashCodeProcessor;
+import org.eclipse.xtend.lib.annotations.FinalFieldsConstructorProcessor;
+import org.eclipse.xtend.lib.annotations.ToStringProcessor;
+import org.eclipse.xtend.lib.macro.AbstractClassProcessor;
+import org.eclipse.xtend.lib.macro.TransformationContext;
+import org.eclipse.xtend.lib.macro.declaration.Element;
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.Modifier;
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.ResolvedConstructor;
+import org.eclipse.xtend.lib.macro.declaration.Visibility;
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+@SuppressWarnings("all")
+public class DataProcessor extends AbstractClassProcessor {
+  /**
+   * @since 2.7
+   * @noextend
+   * @noreference
+   */
+  @Beta
+  public static class Util {
+    @Extension
+    private TransformationContext context;
+    
+    public Util(final TransformationContext context) {
+      this.context = context;
+    }
+    
+    public Iterable<? extends MutableFieldDeclaration> getDataFields(final MutableClassDeclaration it) {
+      final Function1<MutableFieldDeclaration, Boolean> _function = (MutableFieldDeclaration it_1) -> {
+        return Boolean.valueOf((((!it_1.isStatic()) && (!it_1.isTransient())) && this.context.isThePrimaryGeneratedJavaElement(it_1)));
+      };
+      return IterableExtensions.filter(it.getDeclaredFields(), _function);
+    }
+  }
+  
+  @Override
+  public void doTransform(final MutableClassDeclaration it, @Extension final TransformationContext context) {
+    @Extension
+    final DataProcessor.Util util = new DataProcessor.Util(context);
+    @Extension
+    final AccessorsProcessor.Util getterUtil = new AccessorsProcessor.Util(context);
+    @Extension
+    final EqualsHashCodeProcessor.Util ehUtil = new EqualsHashCodeProcessor.Util(context);
+    @Extension
+    final ToStringProcessor.Util toStringUtil = new ToStringProcessor.Util(context);
+    @Extension
+    final FinalFieldsConstructorProcessor.Util requiredArgsUtil = new FinalFieldsConstructorProcessor.Util(context);
+    final Consumer<MutableFieldDeclaration> _function = (MutableFieldDeclaration it_1) -> {
+      Element _primarySourceElement = context.getPrimarySourceElement(it_1);
+      boolean _contains = ((FieldDeclaration) _primarySourceElement).getModifiers().contains(Modifier.VAR);
+      if (_contains) {
+        context.addError(it_1, "Cannot use the \'var\' keyword on a data field");
+      }
+      it_1.setFinal(true);
+    };
+    util.getDataFields(it).forEach(_function);
+    if ((requiredArgsUtil.needsFinalFieldConstructor(it) || (it.findAnnotation(context.findTypeGlobally(FinalFieldsConstructor.class)) != null))) {
+      requiredArgsUtil.addFinalFieldsConstructor(it);
+    }
+    boolean _hasHashCode = ehUtil.hasHashCode(it);
+    boolean _not = (!_hasHashCode);
+    if (_not) {
+      ehUtil.addHashCode(it, util.getDataFields(it), ehUtil.hasSuperHashCode(it));
+    }
+    boolean _hasEquals = ehUtil.hasEquals(it);
+    boolean _not_1 = (!_hasEquals);
+    if (_not_1) {
+      ehUtil.addEquals(it, util.getDataFields(it), ehUtil.hasSuperEquals(it));
+    }
+    boolean _hasToString = toStringUtil.hasToString(it);
+    boolean _not_2 = (!_hasToString);
+    if (_not_2) {
+      ResolvedConstructor _superConstructor = requiredArgsUtil.getSuperConstructor(it);
+      boolean _tripleEquals = (_superConstructor == null);
+      if (_tripleEquals) {
+        Iterable<? extends MutableFieldDeclaration> _dataFields = util.getDataFields(it);
+        ToStringConfiguration _elvis = null;
+        ToStringConfiguration _toStringConfig = toStringUtil.getToStringConfig(it);
+        if (_toStringConfig != null) {
+          _elvis = _toStringConfig;
+        } else {
+          ToStringConfiguration _toStringConfiguration = new ToStringConfiguration();
+          _elvis = _toStringConfiguration;
+        }
+        toStringUtil.addToString(it, _dataFields, _elvis);
+      } else {
+        ToStringConfiguration _elvis_1 = null;
+        ToStringConfiguration _toStringConfig_1 = toStringUtil.getToStringConfig(it);
+        if (_toStringConfig_1 != null) {
+          _elvis_1 = _toStringConfig_1;
+        } else {
+          ToStringConfiguration _toStringConfiguration_1 = new ToStringConfiguration();
+          _elvis_1 = _toStringConfiguration_1;
+        }
+        toStringUtil.addReflectiveToString(it, _elvis_1);
+      }
+    }
+    final Consumer<MutableFieldDeclaration> _function_1 = (MutableFieldDeclaration it_1) -> {
+      boolean _shouldAddGetter = getterUtil.shouldAddGetter(it_1);
+      if (_shouldAddGetter) {
+        Visibility _elvis_2 = null;
+        AccessorType _getterType = getterUtil.getGetterType(it_1);
+        Visibility _visibility = null;
+        if (_getterType!=null) {
+          _visibility=getterUtil.toVisibility(_getterType);
+        }
+        if (_visibility != null) {
+          _elvis_2 = _visibility;
+        } else {
+          _elvis_2 = Visibility.PUBLIC;
+        }
+        getterUtil.addGetter(it_1, _elvis_2);
+      }
+    };
+    util.getDataFields(it).forEach(_function_1);
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/Delegate.java b/java/org/eclipse/xtend/lib/annotations/Delegate.java
new file mode 100644
index 0000000..d385af6
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/Delegate.java
@@ -0,0 +1,62 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.eclipse.xtend.lib.macro.Active;
+
+/**
+ * Implements interfaces by forwarding method calls to an annotated field or method.
+ * 
+ * <p>
+ * <pre>
+ * interface I {
+ *  def String m()
+ * }
+ * class Foo implements I {
+ *  override String m() {
+ *   "Foo"
+ *  }
+ * }
+ * class Bar implements I {
+ *  //This will generate a method m(), which calls foo.m()
+ *  &#64;Delegate val foo = new Foo
+ * }
+ * </pre>
+ * 
+ * For each interface that the declaring class and the delegate have in common,
+ * an implementation for each method is added if it does not yet exist. This
+ * implementation forwards all calls directly to the delegate. You can restrict
+ * which interfaces to implement using the {@link Class}[] value of this
+ * annotation. This is especially useful when there are several delegates that
+ * have some interfaces in common.
+ * 
+ * </p>
+ * Delegate methods can either take
+ * <ul>
+ * <li>no arguments</li>
+ * <li>the name of the method to be called (String)</li>
+ * <li>the name of the method to be called (String), its parameter types
+ * (Class[]) and the actual arguments (Object[]) of the call</li>
+ * </ul>
+ * This allows you to generate meaningful error messages or to dynamically
+ * dispatch based on the arguments.
+ * 
+ * @since 2.7
+ */
+@Beta
+@GwtCompatible
+@Target({ ElementType.FIELD, ElementType.METHOD })
+@Active(DelegateProcessor.class)
+@Documented
+@SuppressWarnings("all")
+public @interface Delegate {
+  /**
+   * Optional list of interfaces that this delegate is restricted to.
+   * Defaults to the common interfaces of the context type and the annotated
+   * element.
+   */
+  public Class<?>[] value() default {};
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/Delegate.xtend b/java/org/eclipse/xtend/lib/annotations/Delegate.xtend
new file mode 100644
index 0000000..1c0b741
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/Delegate.xtend
@@ -0,0 +1,306 @@
+package org.eclipse.xtend.lib.annotations
+
+import com.google.common.annotations.Beta
+import com.google.common.annotations.GwtCompatible
+import com.google.common.collect.Sets
+import java.lang.annotation.ElementType
+import java.lang.annotation.Target
+import java.util.List
+import java.util.Set
+import org.eclipse.xtend.lib.macro.Active
+import org.eclipse.xtend.lib.macro.TransformationContext
+import org.eclipse.xtend.lib.macro.TransformationParticipant
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration
+import org.eclipse.xtend.lib.macro.declaration.InterfaceDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MemberDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MethodDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableMemberDeclaration
+import org.eclipse.xtend.lib.macro.declaration.ResolvedMethod
+import org.eclipse.xtend.lib.macro.declaration.TypeDeclaration
+import org.eclipse.xtend.lib.macro.declaration.TypeReference
+import java.util.Map
+import java.lang.annotation.Documented
+
+/**
+ * Implements interfaces by forwarding method calls to an annotated field or method.
+ * 
+ * <p>
+ * <pre>
+ * interface I {
+ *  def String m()
+ * }
+ * class Foo implements I {
+ *  override String m() {
+ *   "Foo"
+ *  }
+ * }
+ * class Bar implements I {
+ *  //This will generate a method m(), which calls foo.m()
+ *  &#64;Delegate val foo = new Foo
+ * }
+ * </pre>
+ * 
+ * For each interface that the declaring class and the delegate have in common,
+ * an implementation for each method is added if it does not yet exist. This
+ * implementation forwards all calls directly to the delegate. You can restrict
+ * which interfaces to implement using the {@link Class}[] value of this
+ * annotation. This is especially useful when there are several delegates that
+ * have some interfaces in common.
+ * 
+ * </p>
+ * Delegate methods can either take
+ * <ul>
+ * <li>no arguments</li>
+ * <li>the name of the method to be called (String)</li>
+ * <li>the name of the method to be called (String), its parameter types
+ * (Class[]) and the actual arguments (Object[]) of the call</li>
+ * </ul>
+ * This allows you to generate meaningful error messages or to dynamically
+ * dispatch based on the arguments.
+ * 
+ * @since 2.7
+ */
+@Beta
+@GwtCompatible
+@Target(ElementType.FIELD, ElementType.METHOD)
+@Active(DelegateProcessor)
+@Documented
+annotation Delegate {
+	/**
+	 * Optional list of interfaces that this delegate is restricted to.
+	 * Defaults to the common interfaces of the context type and the annotated
+	 * element.
+	 */
+	Class<?>[] value = #[]
+}
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+class DelegateProcessor implements TransformationParticipant<MutableMemberDeclaration> {
+
+	override doTransform(List<? extends MutableMemberDeclaration> elements, extension TransformationContext context) {
+		val extension util = new DelegateProcessor.Util(context)
+		elements.forEach [
+			if (validDelegate) {
+				methodsToImplement.forEach[method|implementMethod(method)]
+			}
+		]
+	}
+
+	/**
+	 * @since 2.7
+	 * @noextend
+	 * @noreference
+ 	*/
+ 	@Beta
+	static class Util {
+		extension TransformationContext context
+
+		new(TransformationContext context) {
+			this.context = context
+		}
+		
+		def dispatch isValidDelegate(FieldDeclaration it) {
+			hasValidType && !hasDelegationConflicts && areListedInterfacesValid
+		}
+
+		def dispatch isValidDelegate(MethodDeclaration it) {
+			hasValidType && hasValidSignature && !hasDelegationConflicts && areListedInterfacesValid
+		}
+
+		def hasValidType(MemberDeclaration it) {
+			if (type === null || type.inferred) {
+				addError("Cannot use inferred types on delegates")
+				false
+			} else {
+				true
+			}
+		}
+		
+		def dispatch getType(FieldDeclaration it) {
+			type
+		}
+
+		def dispatch getType(MethodDeclaration it) {
+			returnType
+		}
+		
+		def hasValidSignature(MethodDeclaration it) {
+			switch parameters.map[type].toList {
+				case #[],
+				case #[string],
+				case #[string, Class.newTypeReference(newWildcardTypeReference).newArrayTypeReference, object.newArrayTypeReference]:
+					true
+				default: {
+					addError("Not a valid delegate signature, use () or (String methodName) or (String methodName, Class<?>[] argumentTypes, Object[] arguments)")
+					false
+				}
+			}
+		}
+
+		def hasDelegationConflicts(MemberDeclaration delegate) {
+			var conflict = false
+			for (other : delegate.otherDelegates) {
+				val otherInterfaces = other.delegatedInterfaces
+				for (iface : delegate.delegatedInterfaces) {
+					if (otherInterfaces.contains(iface)) {
+						conflict = true
+						delegate.addError('''The interface «iface.simpleName» is also implemented by the delegate «other.simpleName»''')
+					}
+				}
+			}
+			conflict
+		}
+		
+		def otherDelegates(MemberDeclaration delegate) {
+			delegate.declaringType.delegates.filter[it != delegate]
+		}
+
+		def areListedInterfacesValid(MemberDeclaration delegate) {
+			val declaringType = delegate.declaringType.newSelfTypeReference
+			val interfacesOfDeclaringType = declaringType.implementedInterfaces
+			val availableInterfaces = delegate.type.implementedInterfaces
+			val listedInterfaces = delegate.listedInterfaces
+			var valid = true
+			for(iface : listedInterfaces) {
+				if (!availableInterfaces.exists[type == iface.type]) {
+					delegate.addError('''«delegate.type.simpleName» does not implement «iface.simpleName»''')
+					valid = false
+				}
+				if (!interfacesOfDeclaringType.exists[type == iface.type]) {
+					delegate.addError('''«declaringType.simpleName» does not implement «iface.simpleName»''')
+					valid = false
+				}
+			}
+			if (listedInterfaces.empty && Sets.intersection(interfacesOfDeclaringType, availableInterfaces).empty) {
+				delegate.addError('''«delegate.type.simpleName» and «declaringType.simpleName» have no interfaces in common''')
+				valid = false
+			}
+			valid
+		}
+
+		def getDelegates(TypeDeclaration it) {
+			declaredMembers.filter[findAnnotation(findTypeGlobally(Delegate)) !== null]
+		}
+		
+		def listedInterfaces(MemberDeclaration it) {
+			findAnnotation(findTypeGlobally(Delegate)).getClassArrayValue("value").toSet
+		}
+
+		def Set<TypeReference> getImplementedInterfaces(TypeReference it) {
+			val seen = newLinkedHashSet
+			collectAllSuperTypes(seen)
+			seen.filter[type instanceof InterfaceDeclaration].toSet
+		}
+		
+		private def void collectAllSuperTypes(TypeReference it, Set<TypeReference> seen) {
+			val cycle = !seen.add(it)
+			if (cycle)
+				return;
+			declaredSuperTypes.forEach[collectAllSuperTypes(seen)]
+		}
+
+		def getDelegatedInterfaces(MemberDeclaration delegate) {
+			val interfacesOfDeclaringType = delegate.declaringType.newSelfTypeReference.implementedInterfaces
+			val listedInterfaces = delegate.listedInterfaces
+			val availableInterfaces = delegate.type.implementedInterfaces
+			availableInterfaces.filter[iface|
+				interfacesOfDeclaringType.contains(iface)
+				&& (listedInterfaces.empty || listedInterfaces.exists[iface.isAssignableFrom(it)])
+			].toSet
+		}
+
+		def getMethodsToImplement(MemberDeclaration delegate) {
+			delegate.delegatedInterfaces.map[declaredResolvedMethods].flatten
+				.filter[delegate.declaringType.findDeclaredMethod(declaration.simpleName, resolvedParameters.map[resolvedType]) === null]
+				.filter[!isObjectMethod]
+				.filter[!isStatic]
+				.groupBy[simpleSignature].values.map[head]
+				.sortBy[simpleSignature]
+				.toSet
+		}
+	
+		def isObjectMethod(ResolvedMethod it) {
+			val name = declaration.simpleName
+			val parameterTypes = resolvedParameters.map[resolvedType].toList
+			
+			name == "hashCode" && parameterTypes.empty
+			|| name == "toString" && parameterTypes.empty
+			|| name == "equals" && parameterTypes == #[object]
+			|| name == "finalize" && parameterTypes.empty
+			|| name == "clone" && parameterTypes.empty
+		}
+
+		def isStatic(ResolvedMethod it) {
+			declaration.isStatic
+		}
+
+		def implementMethod(MutableMemberDeclaration delegate, ResolvedMethod resolvedMethod) {
+			delegate.markAsRead
+			val declaration = resolvedMethod.declaration
+			delegate.declaringType.addMethod(declaration.simpleName) [ impl |
+				impl.primarySourceElement = delegate.primarySourceElement
+				val typeParameterMappings = newHashMap
+				resolvedMethod.resolvedTypeParameters.forEach[param|
+					val copy = impl.addTypeParameter(param.declaration.simpleName, param.resolvedUpperBounds)
+					typeParameterMappings.put(param.declaration.newTypeReference, copy.newTypeReference)
+					copy.upperBounds = copy.upperBounds.map[replace(typeParameterMappings)]
+				]
+				impl.exceptions = resolvedMethod.resolvedExceptionTypes.map[replace(typeParameterMappings)]
+				impl.varArgs = declaration.varArgs
+				impl.returnType = resolvedMethod.resolvedReturnType.replace(typeParameterMappings)
+				resolvedMethod.resolvedParameters.forEach[p|impl.addParameter(p.declaration.simpleName, p.resolvedType.replace(typeParameterMappings))]
+				impl.body = '''
+					«resolvedMethod.returnIfNeeded»«delegate.delegateAccess(declaration)».«declaration.simpleName»(«declaration.parameters.join(", ")[simpleName]»);
+				'''
+			]
+		}
+		
+		def TypeReference replace(TypeReference target, Map<? extends TypeReference, ? extends TypeReference> mappings) {
+			mappings.entrySet.fold(target)[result, mapping|result.replace(mapping.key, mapping.value)]
+		}
+		
+		def TypeReference replace(TypeReference target, TypeReference oldType, TypeReference newType) {
+			if (target == oldType)
+				return newType
+			if (!target.actualTypeArguments.isEmpty)
+				return newTypeReference(target.type, target.actualTypeArguments.map[replace(oldType, newType)])
+			if (target.wildCard) {
+				if (target.upperBound != object)
+					return target.upperBound.replace(oldType, newType).newWildcardTypeReference
+				else if (!target.lowerBound.isAnyType)
+					return target.lowerBound.replace(oldType, newType).newWildcardTypeReferenceWithLowerBound
+			}
+			if (target.isArray)
+				return target.arrayComponentType.replace(oldType, newType).newArrayTypeReference
+			return target
+		}
+		
+		def dispatch delegateAccess(FieldDeclaration it, MethodDeclaration method) {
+			'''this.«simpleName»'''
+		}
+
+		def dispatch delegateAccess(MethodDeclaration it, MethodDeclaration method) {
+			switch parameters.map[type].toList {
+				case #[]: 
+					'''this.«simpleName»()'''
+				case #[string]: 
+					'''this.«simpleName»("«method.simpleName»")'''
+				case #[string, Class.newTypeReference(newWildcardTypeReference).newArrayTypeReference, object.newArrayTypeReference]: {
+					'''this.«simpleName»("«method.simpleName»", new Class[]{«method.parameters.join(", ")[type.type.simpleName + ".class"]»}, new Object[]{«method.parameters.join(", ")[simpleName]»})'''
+				}
+				default:
+					throw new IllegalArgumentException("delegate signature")
+			}
+		}
+
+		def returnIfNeeded(ResolvedMethod it) {
+			if(resolvedReturnType.isVoid) "" else "return "
+		}
+	}
+
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/DelegateProcessor.java b/java/org/eclipse/xtend/lib/annotations/DelegateProcessor.java
new file mode 100644
index 0000000..a28f0b6
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/DelegateProcessor.java
@@ -0,0 +1,566 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Consumer;
+import org.eclipse.xtend.lib.macro.TransformationContext;
+import org.eclipse.xtend.lib.macro.TransformationParticipant;
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.InterfaceDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MemberDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableMemberDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableMethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableTypeParameterDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.ParameterDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.ResolvedMethod;
+import org.eclipse.xtend.lib.macro.declaration.ResolvedParameter;
+import org.eclipse.xtend.lib.macro.declaration.ResolvedTypeParameter;
+import org.eclipse.xtend.lib.macro.declaration.Type;
+import org.eclipse.xtend.lib.macro.declaration.TypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.Conversions;
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.Functions.Function2;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.ListExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+@SuppressWarnings("all")
+public class DelegateProcessor implements TransformationParticipant<MutableMemberDeclaration> {
+  /**
+   * @since 2.7
+   * @noextend
+   * @noreference
+   */
+  @Beta
+  public static class Util {
+    @Extension
+    private TransformationContext context;
+    
+    public Util(final TransformationContext context) {
+      this.context = context;
+    }
+    
+    protected boolean _isValidDelegate(final FieldDeclaration it) {
+      return ((this.hasValidType(it) && (!this.hasDelegationConflicts(it))) && this.areListedInterfacesValid(it));
+    }
+    
+    protected boolean _isValidDelegate(final MethodDeclaration it) {
+      return (((this.hasValidType(it) && this.hasValidSignature(it)) && (!this.hasDelegationConflicts(it))) && this.areListedInterfacesValid(it));
+    }
+    
+    public boolean hasValidType(final MemberDeclaration it) {
+      boolean _xifexpression = false;
+      if (((this.getType(it) == null) || this.getType(it).isInferred())) {
+        boolean _xblockexpression = false;
+        {
+          this.context.addError(it, "Cannot use inferred types on delegates");
+          _xblockexpression = false;
+        }
+        _xifexpression = _xblockexpression;
+      } else {
+        _xifexpression = true;
+      }
+      return _xifexpression;
+    }
+    
+    protected TypeReference _getType(final FieldDeclaration it) {
+      return it.getType();
+    }
+    
+    protected TypeReference _getType(final MethodDeclaration it) {
+      return it.getReturnType();
+    }
+    
+    public boolean hasValidSignature(final MethodDeclaration it) {
+      boolean _switchResult = false;
+      final Function1<ParameterDeclaration, TypeReference> _function = (ParameterDeclaration it_1) -> {
+        return it_1.getType();
+      };
+      List<TypeReference> _list = IterableExtensions.<TypeReference>toList(IterableExtensions.map(it.getParameters(), _function));
+      boolean _matched = false;
+      if (Objects.equal(_list, Collections.<Object>unmodifiableList(CollectionLiterals.<Object>newArrayList()))) {
+        _matched=true;
+      }
+      if (!_matched) {
+        TypeReference _string = this.context.getString();
+        if (Objects.equal(_list, Collections.<TypeReference>unmodifiableList(CollectionLiterals.<TypeReference>newArrayList(_string)))) {
+          _matched=true;
+        }
+      }
+      if (!_matched) {
+        TypeReference _string_1 = this.context.getString();
+        TypeReference _newArrayTypeReference = this.context.newArrayTypeReference(this.context.newTypeReference(Class.class, this.context.newWildcardTypeReference()));
+        TypeReference _newArrayTypeReference_1 = this.context.newArrayTypeReference(this.context.getObject());
+        if (Objects.equal(_list, Collections.<TypeReference>unmodifiableList(CollectionLiterals.<TypeReference>newArrayList(_string_1, _newArrayTypeReference, _newArrayTypeReference_1)))) {
+          _matched=true;
+        }
+      }
+      if (_matched) {
+        _switchResult = true;
+      }
+      if (!_matched) {
+        boolean _xblockexpression = false;
+        {
+          this.context.addError(it, "Not a valid delegate signature, use () or (String methodName) or (String methodName, Class<?>[] argumentTypes, Object[] arguments)");
+          _xblockexpression = false;
+        }
+        _switchResult = _xblockexpression;
+      }
+      return _switchResult;
+    }
+    
+    public boolean hasDelegationConflicts(final MemberDeclaration delegate) {
+      boolean _xblockexpression = false;
+      {
+        boolean conflict = false;
+        Iterable<? extends MemberDeclaration> _otherDelegates = this.otherDelegates(delegate);
+        for (final MemberDeclaration other : _otherDelegates) {
+          {
+            final Set<TypeReference> otherInterfaces = this.getDelegatedInterfaces(other);
+            Set<TypeReference> _delegatedInterfaces = this.getDelegatedInterfaces(delegate);
+            for (final TypeReference iface : _delegatedInterfaces) {
+              boolean _contains = otherInterfaces.contains(iface);
+              if (_contains) {
+                conflict = true;
+                StringConcatenation _builder = new StringConcatenation();
+                _builder.append("The interface ");
+                String _simpleName = iface.getSimpleName();
+                _builder.append(_simpleName);
+                _builder.append(" is also implemented by the delegate ");
+                String _simpleName_1 = other.getSimpleName();
+                _builder.append(_simpleName_1);
+                this.context.addError(delegate, _builder.toString());
+              }
+            }
+          }
+        }
+        _xblockexpression = conflict;
+      }
+      return _xblockexpression;
+    }
+    
+    public Iterable<? extends MemberDeclaration> otherDelegates(final MemberDeclaration delegate) {
+      final Function1<MemberDeclaration, Boolean> _function = (MemberDeclaration it) -> {
+        return Boolean.valueOf((!Objects.equal(it, delegate)));
+      };
+      return IterableExtensions.filter(this.getDelegates(delegate.getDeclaringType()), _function);
+    }
+    
+    public boolean areListedInterfacesValid(final MemberDeclaration delegate) {
+      boolean _xblockexpression = false;
+      {
+        final TypeReference declaringType = this.context.newSelfTypeReference(delegate.getDeclaringType());
+        final Set<TypeReference> interfacesOfDeclaringType = this.getImplementedInterfaces(declaringType);
+        final Set<TypeReference> availableInterfaces = this.getImplementedInterfaces(this.getType(delegate));
+        final Set<TypeReference> listedInterfaces = this.listedInterfaces(delegate);
+        boolean valid = true;
+        for (final TypeReference iface : listedInterfaces) {
+          {
+            final Function1<TypeReference, Boolean> _function = (TypeReference it) -> {
+              Type _type = it.getType();
+              Type _type_1 = iface.getType();
+              return Boolean.valueOf(Objects.equal(_type, _type_1));
+            };
+            boolean _exists = IterableExtensions.<TypeReference>exists(availableInterfaces, _function);
+            boolean _not = (!_exists);
+            if (_not) {
+              StringConcatenation _builder = new StringConcatenation();
+              String _simpleName = this.getType(delegate).getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(" does not implement ");
+              String _simpleName_1 = iface.getSimpleName();
+              _builder.append(_simpleName_1);
+              this.context.addError(delegate, _builder.toString());
+              valid = false;
+            }
+            final Function1<TypeReference, Boolean> _function_1 = (TypeReference it) -> {
+              Type _type = it.getType();
+              Type _type_1 = iface.getType();
+              return Boolean.valueOf(Objects.equal(_type, _type_1));
+            };
+            boolean _exists_1 = IterableExtensions.<TypeReference>exists(interfacesOfDeclaringType, _function_1);
+            boolean _not_1 = (!_exists_1);
+            if (_not_1) {
+              StringConcatenation _builder_1 = new StringConcatenation();
+              String _simpleName_2 = declaringType.getSimpleName();
+              _builder_1.append(_simpleName_2);
+              _builder_1.append(" does not implement ");
+              String _simpleName_3 = iface.getSimpleName();
+              _builder_1.append(_simpleName_3);
+              this.context.addError(delegate, _builder_1.toString());
+              valid = false;
+            }
+          }
+        }
+        if ((listedInterfaces.isEmpty() && Sets.<TypeReference>intersection(interfacesOfDeclaringType, availableInterfaces).isEmpty())) {
+          StringConcatenation _builder = new StringConcatenation();
+          String _simpleName = this.getType(delegate).getSimpleName();
+          _builder.append(_simpleName);
+          _builder.append(" and ");
+          String _simpleName_1 = declaringType.getSimpleName();
+          _builder.append(_simpleName_1);
+          _builder.append(" have no interfaces in common");
+          this.context.addError(delegate, _builder.toString());
+          valid = false;
+        }
+        _xblockexpression = valid;
+      }
+      return _xblockexpression;
+    }
+    
+    public Iterable<? extends MemberDeclaration> getDelegates(final TypeDeclaration it) {
+      final Function1<MemberDeclaration, Boolean> _function = (MemberDeclaration it_1) -> {
+        AnnotationReference _findAnnotation = it_1.findAnnotation(this.context.findTypeGlobally(Delegate.class));
+        return Boolean.valueOf((_findAnnotation != null));
+      };
+      return IterableExtensions.filter(it.getDeclaredMembers(), _function);
+    }
+    
+    public Set<TypeReference> listedInterfaces(final MemberDeclaration it) {
+      return IterableExtensions.<TypeReference>toSet(((Iterable<TypeReference>)Conversions.doWrapArray(it.findAnnotation(this.context.findTypeGlobally(Delegate.class)).getClassArrayValue("value"))));
+    }
+    
+    public Set<TypeReference> getImplementedInterfaces(final TypeReference it) {
+      Set<TypeReference> _xblockexpression = null;
+      {
+        final LinkedHashSet<TypeReference> seen = CollectionLiterals.<TypeReference>newLinkedHashSet();
+        this.collectAllSuperTypes(it, seen);
+        final Function1<TypeReference, Boolean> _function = (TypeReference it_1) -> {
+          Type _type = it_1.getType();
+          return Boolean.valueOf((_type instanceof InterfaceDeclaration));
+        };
+        _xblockexpression = IterableExtensions.<TypeReference>toSet(IterableExtensions.<TypeReference>filter(seen, _function));
+      }
+      return _xblockexpression;
+    }
+    
+    private void collectAllSuperTypes(final TypeReference it, final Set<TypeReference> seen) {
+      boolean _add = seen.add(it);
+      final boolean cycle = (!_add);
+      if (cycle) {
+        return;
+      }
+      final Consumer<TypeReference> _function = (TypeReference it_1) -> {
+        this.collectAllSuperTypes(it_1, seen);
+      };
+      it.getDeclaredSuperTypes().forEach(_function);
+    }
+    
+    public Set<TypeReference> getDelegatedInterfaces(final MemberDeclaration delegate) {
+      Set<TypeReference> _xblockexpression = null;
+      {
+        final Set<TypeReference> interfacesOfDeclaringType = this.getImplementedInterfaces(this.context.newSelfTypeReference(delegate.getDeclaringType()));
+        final Set<TypeReference> listedInterfaces = this.listedInterfaces(delegate);
+        final Set<TypeReference> availableInterfaces = this.getImplementedInterfaces(this.getType(delegate));
+        final Function1<TypeReference, Boolean> _function = (TypeReference iface) -> {
+          return Boolean.valueOf((interfacesOfDeclaringType.contains(iface) && (listedInterfaces.isEmpty() || IterableExtensions.<TypeReference>exists(listedInterfaces, ((Function1<TypeReference, Boolean>) (TypeReference it) -> {
+            return Boolean.valueOf(iface.isAssignableFrom(it));
+          })))));
+        };
+        _xblockexpression = IterableExtensions.<TypeReference>toSet(IterableExtensions.<TypeReference>filter(availableInterfaces, _function));
+      }
+      return _xblockexpression;
+    }
+    
+    public Set<ResolvedMethod> getMethodsToImplement(final MemberDeclaration delegate) {
+      final Function1<TypeReference, Iterable<? extends ResolvedMethod>> _function = (TypeReference it) -> {
+        return it.getDeclaredResolvedMethods();
+      };
+      final Function1<ResolvedMethod, Boolean> _function_1 = (ResolvedMethod it) -> {
+        final Function1<ResolvedParameter, TypeReference> _function_2 = (ResolvedParameter it_1) -> {
+          return it_1.getResolvedType();
+        };
+        MethodDeclaration _findDeclaredMethod = delegate.getDeclaringType().findDeclaredMethod(it.getDeclaration().getSimpleName(), ((TypeReference[])Conversions.unwrapArray(IterableExtensions.map(it.getResolvedParameters(), _function_2), TypeReference.class)));
+        return Boolean.valueOf((_findDeclaredMethod == null));
+      };
+      final Function1<ResolvedMethod, Boolean> _function_2 = (ResolvedMethod it) -> {
+        boolean _isObjectMethod = this.isObjectMethod(it);
+        return Boolean.valueOf((!_isObjectMethod));
+      };
+      final Function1<ResolvedMethod, Boolean> _function_3 = (ResolvedMethod it) -> {
+        boolean _isStatic = this.isStatic(it);
+        return Boolean.valueOf((!_isStatic));
+      };
+      final Function1<ResolvedMethod, String> _function_4 = (ResolvedMethod it) -> {
+        return it.getSimpleSignature();
+      };
+      final Function1<List<ResolvedMethod>, ResolvedMethod> _function_5 = (List<ResolvedMethod> it) -> {
+        return IterableExtensions.<ResolvedMethod>head(it);
+      };
+      final Function1<ResolvedMethod, String> _function_6 = (ResolvedMethod it) -> {
+        return it.getSimpleSignature();
+      };
+      return IterableExtensions.<ResolvedMethod>toSet(IterableExtensions.<ResolvedMethod, String>sortBy(IterableExtensions.<List<ResolvedMethod>, ResolvedMethod>map(IterableExtensions.<String, ResolvedMethod>groupBy(IterableExtensions.<ResolvedMethod>filter(IterableExtensions.<ResolvedMethod>filter(IterableExtensions.<ResolvedMethod>filter(Iterables.<ResolvedMethod>concat(IterableExtensions.<TypeReference, Iterable<? extends ResolvedMethod>>map(this.getDelegatedInterfaces(delegate), _function)), _function_1), _function_2), _function_3), _function_4).values(), _function_5), _function_6));
+    }
+    
+    public boolean isObjectMethod(final ResolvedMethod it) {
+      boolean _xblockexpression = false;
+      {
+        final String name = it.getDeclaration().getSimpleName();
+        final Function1<ResolvedParameter, TypeReference> _function = (ResolvedParameter it_1) -> {
+          return it_1.getResolvedType();
+        };
+        final List<TypeReference> parameterTypes = IterableExtensions.<TypeReference>toList(IterableExtensions.map(it.getResolvedParameters(), _function));
+        _xblockexpression = (((((Objects.equal(name, "hashCode") && parameterTypes.isEmpty()) || (Objects.equal(name, "toString") && parameterTypes.isEmpty())) || (Objects.equal(name, "equals") && Objects.equal(parameterTypes, Collections.<TypeReference>unmodifiableList(CollectionLiterals.<TypeReference>newArrayList(this.context.getObject()))))) || (Objects.equal(name, "finalize") && parameterTypes.isEmpty())) || (Objects.equal(name, "clone") && parameterTypes.isEmpty()));
+      }
+      return _xblockexpression;
+    }
+    
+    public boolean isStatic(final ResolvedMethod it) {
+      return it.getDeclaration().isStatic();
+    }
+    
+    public MutableMethodDeclaration implementMethod(final MutableMemberDeclaration delegate, final ResolvedMethod resolvedMethod) {
+      MutableMethodDeclaration _xblockexpression = null;
+      {
+        delegate.markAsRead();
+        final MethodDeclaration declaration = resolvedMethod.getDeclaration();
+        final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration impl) -> {
+          this.context.setPrimarySourceElement(impl, this.context.getPrimarySourceElement(delegate));
+          final HashMap<TypeReference, TypeReference> typeParameterMappings = CollectionLiterals.<TypeReference, TypeReference>newHashMap();
+          final Consumer<ResolvedTypeParameter> _function_1 = (ResolvedTypeParameter param) -> {
+            final MutableTypeParameterDeclaration copy = impl.addTypeParameter(param.getDeclaration().getSimpleName(), ((TypeReference[])Conversions.unwrapArray(param.getResolvedUpperBounds(), TypeReference.class)));
+            typeParameterMappings.put(this.context.newTypeReference(param.getDeclaration()), this.context.newTypeReference(copy));
+            final Function1<TypeReference, TypeReference> _function_2 = (TypeReference it) -> {
+              return this.replace(it, typeParameterMappings);
+            };
+            copy.setUpperBounds(IterableExtensions.map(copy.getUpperBounds(), _function_2));
+          };
+          resolvedMethod.getResolvedTypeParameters().forEach(_function_1);
+          final Function1<TypeReference, TypeReference> _function_2 = (TypeReference it) -> {
+            return this.replace(it, typeParameterMappings);
+          };
+          impl.setExceptions(((TypeReference[])Conversions.unwrapArray(IterableExtensions.map(resolvedMethod.getResolvedExceptionTypes(), _function_2), TypeReference.class)));
+          impl.setVarArgs(declaration.isVarArgs());
+          impl.setReturnType(this.replace(resolvedMethod.getResolvedReturnType(), typeParameterMappings));
+          final Consumer<ResolvedParameter> _function_3 = (ResolvedParameter p) -> {
+            impl.addParameter(p.getDeclaration().getSimpleName(), this.replace(p.getResolvedType(), typeParameterMappings));
+          };
+          resolvedMethod.getResolvedParameters().forEach(_function_3);
+          StringConcatenationClient _client = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              String _returnIfNeeded = Util.this.returnIfNeeded(resolvedMethod);
+              _builder.append(_returnIfNeeded);
+              CharSequence _delegateAccess = Util.this.delegateAccess(delegate, declaration);
+              _builder.append(_delegateAccess);
+              _builder.append(".");
+              String _simpleName = declaration.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append("(");
+              final Function1<ParameterDeclaration, CharSequence> _function = (ParameterDeclaration it) -> {
+                return it.getSimpleName();
+              };
+              String _join = IterableExtensions.join(declaration.getParameters(), ", ", _function);
+              _builder.append(_join);
+              _builder.append(");");
+              _builder.newLineIfNotEmpty();
+            }
+          };
+          impl.setBody(_client);
+        };
+        _xblockexpression = delegate.getDeclaringType().addMethod(declaration.getSimpleName(), _function);
+      }
+      return _xblockexpression;
+    }
+    
+    public TypeReference replace(final TypeReference target, final Map<? extends TypeReference, ? extends TypeReference> mappings) {
+      final Function2<TypeReference, Map.Entry<? extends TypeReference, ? extends TypeReference>, TypeReference> _function = (TypeReference result, Map.Entry<? extends TypeReference, ? extends TypeReference> mapping) -> {
+        return this.replace(result, mapping.getKey(), mapping.getValue());
+      };
+      return IterableExtensions.fold(mappings.entrySet(), target, _function);
+    }
+    
+    public TypeReference replace(final TypeReference target, final TypeReference oldType, final TypeReference newType) {
+      boolean _equals = Objects.equal(target, oldType);
+      if (_equals) {
+        return newType;
+      }
+      boolean _isEmpty = target.getActualTypeArguments().isEmpty();
+      boolean _not = (!_isEmpty);
+      if (_not) {
+        final Function1<TypeReference, TypeReference> _function = (TypeReference it) -> {
+          return this.replace(it, oldType, newType);
+        };
+        return this.context.newTypeReference(target.getType(), ((TypeReference[])Conversions.unwrapArray(ListExtensions.<TypeReference, TypeReference>map(target.getActualTypeArguments(), _function), TypeReference.class)));
+      }
+      boolean _isWildCard = target.isWildCard();
+      if (_isWildCard) {
+        TypeReference _upperBound = target.getUpperBound();
+        TypeReference _object = this.context.getObject();
+        boolean _notEquals = (!Objects.equal(_upperBound, _object));
+        if (_notEquals) {
+          return this.context.newWildcardTypeReference(this.replace(target.getUpperBound(), oldType, newType));
+        } else {
+          boolean _isAnyType = target.getLowerBound().isAnyType();
+          boolean _not_1 = (!_isAnyType);
+          if (_not_1) {
+            return this.context.newWildcardTypeReferenceWithLowerBound(this.replace(target.getLowerBound(), oldType, newType));
+          }
+        }
+      }
+      boolean _isArray = target.isArray();
+      if (_isArray) {
+        return this.context.newArrayTypeReference(this.replace(target.getArrayComponentType(), oldType, newType));
+      }
+      return target;
+    }
+    
+    protected CharSequence _delegateAccess(final FieldDeclaration it, final MethodDeclaration method) {
+      StringConcatenation _builder = new StringConcatenation();
+      _builder.append("this.");
+      String _simpleName = it.getSimpleName();
+      _builder.append(_simpleName);
+      return _builder;
+    }
+    
+    protected CharSequence _delegateAccess(final MethodDeclaration it, final MethodDeclaration method) {
+      CharSequence _switchResult = null;
+      final Function1<ParameterDeclaration, TypeReference> _function = (ParameterDeclaration it_1) -> {
+        return it_1.getType();
+      };
+      List<TypeReference> _list = IterableExtensions.<TypeReference>toList(IterableExtensions.map(it.getParameters(), _function));
+      boolean _matched = false;
+      if (Objects.equal(_list, Collections.<Object>unmodifiableList(CollectionLiterals.<Object>newArrayList()))) {
+        _matched=true;
+        StringConcatenation _builder = new StringConcatenation();
+        _builder.append("this.");
+        String _simpleName = it.getSimpleName();
+        _builder.append(_simpleName);
+        _builder.append("()");
+        _switchResult = _builder;
+      }
+      if (!_matched) {
+        TypeReference _string = this.context.getString();
+        if (Objects.equal(_list, Collections.<TypeReference>unmodifiableList(CollectionLiterals.<TypeReference>newArrayList(_string)))) {
+          _matched=true;
+          StringConcatenation _builder_1 = new StringConcatenation();
+          _builder_1.append("this.");
+          String _simpleName_1 = it.getSimpleName();
+          _builder_1.append(_simpleName_1);
+          _builder_1.append("(\"");
+          String _simpleName_2 = method.getSimpleName();
+          _builder_1.append(_simpleName_2);
+          _builder_1.append("\")");
+          _switchResult = _builder_1;
+        }
+      }
+      if (!_matched) {
+        TypeReference _string_1 = this.context.getString();
+        TypeReference _newArrayTypeReference = this.context.newArrayTypeReference(this.context.newTypeReference(Class.class, this.context.newWildcardTypeReference()));
+        TypeReference _newArrayTypeReference_1 = this.context.newArrayTypeReference(this.context.getObject());
+        if (Objects.equal(_list, Collections.<TypeReference>unmodifiableList(CollectionLiterals.<TypeReference>newArrayList(_string_1, _newArrayTypeReference, _newArrayTypeReference_1)))) {
+          _matched=true;
+          StringConcatenation _builder_2 = new StringConcatenation();
+          _builder_2.append("this.");
+          String _simpleName_3 = it.getSimpleName();
+          _builder_2.append(_simpleName_3);
+          _builder_2.append("(\"");
+          String _simpleName_4 = method.getSimpleName();
+          _builder_2.append(_simpleName_4);
+          _builder_2.append("\", new Class[]{");
+          final Function1<ParameterDeclaration, CharSequence> _function_1 = (ParameterDeclaration it_1) -> {
+            String _simpleName_5 = it_1.getType().getType().getSimpleName();
+            return (_simpleName_5 + ".class");
+          };
+          String _join = IterableExtensions.join(method.getParameters(), ", ", _function_1);
+          _builder_2.append(_join);
+          _builder_2.append("}, new Object[]{");
+          final Function1<ParameterDeclaration, CharSequence> _function_2 = (ParameterDeclaration it_1) -> {
+            return it_1.getSimpleName();
+          };
+          String _join_1 = IterableExtensions.join(method.getParameters(), ", ", _function_2);
+          _builder_2.append(_join_1);
+          _builder_2.append("})");
+          _switchResult = _builder_2;
+        }
+      }
+      if (!_matched) {
+        throw new IllegalArgumentException("delegate signature");
+      }
+      return _switchResult;
+    }
+    
+    public String returnIfNeeded(final ResolvedMethod it) {
+      String _xifexpression = null;
+      boolean _isVoid = it.getResolvedReturnType().isVoid();
+      if (_isVoid) {
+        _xifexpression = "";
+      } else {
+        _xifexpression = "return ";
+      }
+      return _xifexpression;
+    }
+    
+    public boolean isValidDelegate(final MemberDeclaration it) {
+      if (it instanceof MethodDeclaration) {
+        return _isValidDelegate((MethodDeclaration)it);
+      } else if (it instanceof FieldDeclaration) {
+        return _isValidDelegate((FieldDeclaration)it);
+      } else {
+        throw new IllegalArgumentException("Unhandled parameter types: " +
+          Arrays.<Object>asList(it).toString());
+      }
+    }
+    
+    public TypeReference getType(final MemberDeclaration it) {
+      if (it instanceof MethodDeclaration) {
+        return _getType((MethodDeclaration)it);
+      } else if (it instanceof FieldDeclaration) {
+        return _getType((FieldDeclaration)it);
+      } else {
+        throw new IllegalArgumentException("Unhandled parameter types: " +
+          Arrays.<Object>asList(it).toString());
+      }
+    }
+    
+    public CharSequence delegateAccess(final MemberDeclaration it, final MethodDeclaration method) {
+      if (it instanceof MethodDeclaration) {
+        return _delegateAccess((MethodDeclaration)it, method);
+      } else if (it instanceof FieldDeclaration) {
+        return _delegateAccess((FieldDeclaration)it, method);
+      } else {
+        throw new IllegalArgumentException("Unhandled parameter types: " +
+          Arrays.<Object>asList(it, method).toString());
+      }
+    }
+  }
+  
+  @Override
+  public void doTransform(final List<? extends MutableMemberDeclaration> elements, @Extension final TransformationContext context) {
+    @Extension
+    final DelegateProcessor.Util util = new DelegateProcessor.Util(context);
+    final Consumer<MutableMemberDeclaration> _function = (MutableMemberDeclaration it) -> {
+      boolean _isValidDelegate = util.isValidDelegate(it);
+      if (_isValidDelegate) {
+        final Consumer<ResolvedMethod> _function_1 = (ResolvedMethod method) -> {
+          util.implementMethod(it, method);
+        };
+        util.getMethodsToImplement(it).forEach(_function_1);
+      }
+    };
+    elements.forEach(_function);
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/EqualsHashCode.java b/java/org/eclipse/xtend/lib/annotations/EqualsHashCode.java
new file mode 100644
index 0000000..5037fa7
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/EqualsHashCode.java
@@ -0,0 +1,24 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.Arrays;
+import org.eclipse.xtend.lib.macro.Active;
+
+/**
+ * Creates default implementations for {@link Object#equals(Object) equals} and {@link Object#hashCode hashCode}.
+ * 
+ * All non-static, non-transient fields are used. Subclasses are never equal to their superclasses.
+ * If there is a superclass that overrides equals, then <code>super.equals()</code> and <code>super.hashCode</code> are also called.
+ * Array-valued fields are compared using #{@link Arrays#deepEquals}.
+ * @since 2.7
+ */
+@Beta
+@GwtCompatible
+@Target(ElementType.TYPE)
+@Active(EqualsHashCodeProcessor.class)
+@SuppressWarnings("all")
+public @interface EqualsHashCode {
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/EqualsHashCode.xtend b/java/org/eclipse/xtend/lib/annotations/EqualsHashCode.xtend
new file mode 100644
index 0000000..0f5f228
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/EqualsHashCode.xtend
@@ -0,0 +1,241 @@
+package org.eclipse.xtend.lib.annotations
+
+import com.google.common.annotations.Beta
+import com.google.common.annotations.GwtCompatible
+import java.lang.annotation.ElementType
+import java.lang.annotation.Target
+import org.eclipse.xtend.lib.macro.AbstractClassProcessor
+import org.eclipse.xtend.lib.macro.Active
+import org.eclipse.xtend.lib.macro.TransformationContext
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.TypeReference
+import org.eclipse.xtend2.lib.StringConcatenationClient
+import java.util.Arrays
+
+/**
+ * Creates default implementations for {@link Object#equals(Object) equals} and {@link Object#hashCode hashCode}.
+ * 
+ * All non-static, non-transient fields are used. Subclasses are never equal to their superclasses. 
+ * If there is a superclass that overrides equals, then <code>super.equals()</code> and <code>super.hashCode</code> are also called.
+ * Array-valued fields are compared using #{@link Arrays#deepEquals}.
+ * @since 2.7
+ */
+@Beta
+@GwtCompatible
+@Target(ElementType.TYPE)
+@Active(EqualsHashCodeProcessor)
+annotation EqualsHashCode {
+}
+
+/**
+ * @since 2.7
+ * @noreference
+ * @noextend
+ */
+@Beta
+class EqualsHashCodeProcessor extends AbstractClassProcessor {
+
+	override doTransform(MutableClassDeclaration it, extension TransformationContext context) {
+		if (findAnnotation(Data.findTypeGlobally) !== null) {
+			return
+		}
+		extension val util = new Util(context)
+		if (hasEquals) {
+			val annotation = findAnnotation(EqualsHashCode.findTypeGlobally)
+			annotation.addWarning("equals is already defined, this annotation has no effect")
+		} else if (hasHashCode) {
+			addWarning("hashCode is already defined, this annotation has no effect")
+		} else {
+			val fields = declaredFields.filter[!static && !transient && thePrimaryGeneratedJavaElement]
+			addEquals(fields, hasSuperEquals)
+			addHashCode(fields, hasSuperHashCode)
+		}
+	}
+
+	/**
+	 * @since 2.7
+	 * @noextend
+	 * @noreference
+ 	 */
+	@Beta
+	static class Util {
+
+		static final int PRIME_VALUE = 31
+		extension TransformationContext context
+
+		new(TransformationContext context) {
+			this.context = context
+		}
+
+		def hasHashCode(ClassDeclaration it) {
+			findDeclaredMethod("hashCode") !== null
+		}
+
+		def hasEquals(ClassDeclaration it) {
+			declaredMethods.exists [
+				simpleName == "equals" && parameters.size == 1 && parameters.head.type == object
+			]
+		}
+
+		def boolean hasSuperEquals(ClassDeclaration cls) {
+			val superClass = (cls.extendedClass.type as ClassDeclaration)
+			if (superClass.newTypeReference.equals(object)) {
+				false
+			} else if (superClass.hasEquals) {
+				true
+			} else {
+				superClass.hasSuperEquals
+			}
+		}
+		def boolean hasSuperHashCode(ClassDeclaration cls) {
+			val superClass = (cls.extendedClass.type as ClassDeclaration)
+			if (superClass.newTypeReference.equals(object)) {
+				false
+			} else if (superClass.hasHashCode) {
+				true
+			} else {
+				superClass.hasSuperHashCode
+			}
+		}
+
+		def void addEquals(MutableClassDeclaration cls, Iterable<? extends FieldDeclaration> includedFields,
+			boolean includeSuper) {
+			cls.addMethod("equals") [
+				primarySourceElement = cls.primarySourceElement
+				returnType = primitiveBoolean
+				addAnnotation(newAnnotationReference(Override))
+				addAnnotation(newAnnotationReference(Pure))
+				addParameter("obj", object)
+				body = '''
+					if (this == obj)
+					  return true;
+					if (obj == null)
+					  return false;
+					if (getClass() != obj.getClass())
+					  return false;
+					«IF includeSuper»
+						if (!super.equals(obj))
+						  return false;
+					«ENDIF»
+					«IF includedFields.size>0»
+						«cls.newWildCardSelfTypeReference» other = («cls.newWildCardSelfTypeReference») obj;
+					«ENDIF»
+					«FOR field : includedFields»
+						«field.contributeToEquals»
+					«ENDFOR»
+					return true;
+				'''
+			]
+		}
+
+		private def newWildCardSelfTypeReference(ClassDeclaration cls) {
+			cls.newTypeReference(cls.typeParameters.map[object.newWildcardTypeReference])
+		}
+
+		def StringConcatenationClient contributeToEquals(FieldDeclaration it) {
+			switch (type.orObject.name) {
+				case Double.TYPE.name: '''
+					if («Double».doubleToLongBits(other.«simpleName») != «Double».doubleToLongBits(this.«simpleName»))
+					  return false; 
+				'''
+				case Float.TYPE.name: '''
+					if («Float».floatToIntBits(other.«simpleName») != «Float».floatToIntBits(this.«simpleName»))
+					  return false; 
+				'''
+				case Boolean.TYPE.name,
+				case Integer.TYPE.name,
+				case Character.TYPE.name,
+				case Byte.TYPE.name,
+				case Short.TYPE.name,
+				case Long.TYPE.name: '''
+					if (other.«simpleName» != this.«simpleName»)
+					  return false;
+				'''
+				default: '''
+					if (this.«simpleName» == null) {
+					  if (other.«simpleName» != null)
+					    return false;
+					} else if (!«deepEquals»)
+					  return false;
+				'''
+			}
+		}
+		
+		def StringConcatenationClient deepEquals(FieldDeclaration it) {
+			if (type.isArray) {
+				if (type.arrayComponentType.isPrimitive) {
+					'''«Arrays».equals(this.«simpleName», other.«simpleName»)'''
+				} else {
+					'''«Arrays».deepEquals(this.«simpleName», other.«simpleName»)'''
+				}
+			} else {
+				'''this.«simpleName».equals(other.«simpleName»)'''
+			}
+		}
+
+		def void addHashCode(MutableClassDeclaration cls, Iterable<? extends FieldDeclaration> includedFields,
+			boolean includeSuper) {
+			val defaultBase = if(includeSuper) "super.hashCode()" else "1"
+			val fields = includedFields.size
+
+			cls.addMethod("hashCode") [
+				primarySourceElement = cls.primarySourceElement
+				returnType = primitiveInt
+				addAnnotation(newAnnotationReference(Override))
+				addAnnotation(newAnnotationReference(Pure))
+				body = '''
+					«IF fields >= 2»
+						final int prime = «PRIME_VALUE»;
+						int result = «defaultBase»;
+						«FOR i : 0 ..< fields»
+							«IF i == fields - 1»return«ELSE»result =«ENDIF» prime * result + «includedFields.get(i).contributeToHashCode»;
+						«ENDFOR»
+					«ELSEIF fields == 1»
+						return «PRIME_VALUE» * «defaultBase» + «includedFields.head.contributeToHashCode»;
+					«ELSE»
+						return «defaultBase»;
+					«ENDIF»
+				'''
+			]
+		}
+
+		def StringConcatenationClient contributeToHashCode(FieldDeclaration it) {
+			switch (type.orObject.name) {
+				case Double.TYPE.name:
+					'''(int) («Double».doubleToLongBits(this.«simpleName») ^ («Double».doubleToLongBits(this.«simpleName») >>> 32))'''
+				case Float.TYPE.name:
+					'''«Float».floatToIntBits(this.«simpleName»)'''
+				case Boolean.TYPE.name:
+					'''(this.«simpleName» ? 1231 : 1237)'''
+				case Integer.TYPE.name,
+				case Character.TYPE.name,
+				case Byte.TYPE.name,
+				case Short.TYPE.name:
+					'''this.«simpleName»'''
+				case Long.TYPE.name:
+					'''(int) (this.«simpleName» ^ (this.«simpleName» >>> 32))'''
+				default:
+					'''((this.«simpleName»== null) ? 0 : «deepHashCode»)'''
+			}
+		}
+		
+		def StringConcatenationClient deepHashCode(FieldDeclaration it) {
+			val type = type.orObject
+			if (type.isArray) {
+				if (type.arrayComponentType.isPrimitive) {
+					'''«Arrays».hashCode(this.«simpleName»)'''
+				} else {
+					'''«Arrays».deepHashCode(this.«simpleName»)'''
+				}
+			} else {
+				'''this.«simpleName».hashCode()'''
+			}
+		}
+		
+		private def orObject(TypeReference ref) {
+			ref ?: object
+		}
+	}
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/EqualsHashCodeProcessor.java b/java/org/eclipse/xtend/lib/annotations/EqualsHashCodeProcessor.java
new file mode 100644
index 0000000..9d0a92a
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/EqualsHashCodeProcessor.java
@@ -0,0 +1,672 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import java.util.Arrays;
+import org.eclipse.xtend.lib.macro.AbstractClassProcessor;
+import org.eclipse.xtend.lib.macro.TransformationContext;
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableMethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.Type;
+import org.eclipse.xtend.lib.macro.declaration.TypeParameterDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+import org.eclipse.xtext.xbase.lib.Conversions;
+import org.eclipse.xtext.xbase.lib.ExclusiveRange;
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.lib.Pure;
+
+/**
+ * @since 2.7
+ * @noreference
+ * @noextend
+ */
+@Beta
+@SuppressWarnings("all")
+public class EqualsHashCodeProcessor extends AbstractClassProcessor {
+  /**
+   * @since 2.7
+   * @noextend
+   * @noreference
+   */
+  @Beta
+  public static class Util {
+    private static final int PRIME_VALUE = 31;
+    
+    @Extension
+    private TransformationContext context;
+    
+    public Util(final TransformationContext context) {
+      this.context = context;
+    }
+    
+    public boolean hasHashCode(final ClassDeclaration it) {
+      MethodDeclaration _findDeclaredMethod = it.findDeclaredMethod("hashCode");
+      return (_findDeclaredMethod != null);
+    }
+    
+    public boolean hasEquals(final ClassDeclaration it) {
+      final Function1<MethodDeclaration, Boolean> _function = (MethodDeclaration it_1) -> {
+        return Boolean.valueOf(((Objects.equal(it_1.getSimpleName(), "equals") && (IterableExtensions.size(it_1.getParameters()) == 1)) && Objects.equal(IterableExtensions.head(it_1.getParameters()).getType(), this.context.getObject())));
+      };
+      return IterableExtensions.exists(it.getDeclaredMethods(), _function);
+    }
+    
+    public boolean hasSuperEquals(final ClassDeclaration cls) {
+      boolean _xblockexpression = false;
+      {
+        Type _type = cls.getExtendedClass().getType();
+        final ClassDeclaration superClass = ((ClassDeclaration) _type);
+        boolean _xifexpression = false;
+        boolean _equals = this.context.newTypeReference(superClass).equals(this.context.getObject());
+        if (_equals) {
+          _xifexpression = false;
+        } else {
+          boolean _xifexpression_1 = false;
+          boolean _hasEquals = this.hasEquals(superClass);
+          if (_hasEquals) {
+            _xifexpression_1 = true;
+          } else {
+            _xifexpression_1 = this.hasSuperEquals(superClass);
+          }
+          _xifexpression = _xifexpression_1;
+        }
+        _xblockexpression = _xifexpression;
+      }
+      return _xblockexpression;
+    }
+    
+    public boolean hasSuperHashCode(final ClassDeclaration cls) {
+      boolean _xblockexpression = false;
+      {
+        Type _type = cls.getExtendedClass().getType();
+        final ClassDeclaration superClass = ((ClassDeclaration) _type);
+        boolean _xifexpression = false;
+        boolean _equals = this.context.newTypeReference(superClass).equals(this.context.getObject());
+        if (_equals) {
+          _xifexpression = false;
+        } else {
+          boolean _xifexpression_1 = false;
+          boolean _hasHashCode = this.hasHashCode(superClass);
+          if (_hasHashCode) {
+            _xifexpression_1 = true;
+          } else {
+            _xifexpression_1 = this.hasSuperHashCode(superClass);
+          }
+          _xifexpression = _xifexpression_1;
+        }
+        _xblockexpression = _xifexpression;
+      }
+      return _xblockexpression;
+    }
+    
+    public void addEquals(final MutableClassDeclaration cls, final Iterable<? extends FieldDeclaration> includedFields, final boolean includeSuper) {
+      final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration it) -> {
+        this.context.setPrimarySourceElement(it, this.context.getPrimarySourceElement(cls));
+        it.setReturnType(this.context.getPrimitiveBoolean());
+        it.addAnnotation(this.context.newAnnotationReference(Override.class));
+        it.addAnnotation(this.context.newAnnotationReference(Pure.class));
+        it.addParameter("obj", this.context.getObject());
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("if (this == obj)");
+            _builder.newLine();
+            _builder.append("  ");
+            _builder.append("return true;");
+            _builder.newLine();
+            _builder.append("if (obj == null)");
+            _builder.newLine();
+            _builder.append("  ");
+            _builder.append("return false;");
+            _builder.newLine();
+            _builder.append("if (getClass() != obj.getClass())");
+            _builder.newLine();
+            _builder.append("  ");
+            _builder.append("return false;");
+            _builder.newLine();
+            {
+              if (includeSuper) {
+                _builder.append("if (!super.equals(obj))");
+                _builder.newLine();
+                _builder.append("  ");
+                _builder.append("return false;");
+                _builder.newLine();
+              }
+            }
+            {
+              int _size = IterableExtensions.size(includedFields);
+              boolean _greaterThan = (_size > 0);
+              if (_greaterThan) {
+                TypeReference _newWildCardSelfTypeReference = Util.this.newWildCardSelfTypeReference(cls);
+                _builder.append(_newWildCardSelfTypeReference);
+                _builder.append(" other = (");
+                TypeReference _newWildCardSelfTypeReference_1 = Util.this.newWildCardSelfTypeReference(cls);
+                _builder.append(_newWildCardSelfTypeReference_1);
+                _builder.append(") obj;");
+                _builder.newLineIfNotEmpty();
+              }
+            }
+            {
+              for(final FieldDeclaration field : includedFields) {
+                StringConcatenationClient _contributeToEquals = Util.this.contributeToEquals(field);
+                _builder.append(_contributeToEquals);
+                _builder.newLineIfNotEmpty();
+              }
+            }
+            _builder.append("return true;");
+            _builder.newLine();
+          }
+        };
+        it.setBody(_client);
+      };
+      cls.addMethod("equals", _function);
+    }
+    
+    private TypeReference newWildCardSelfTypeReference(final ClassDeclaration cls) {
+      final Function1<TypeParameterDeclaration, TypeReference> _function = (TypeParameterDeclaration it) -> {
+        return this.context.newWildcardTypeReference(this.context.getObject());
+      };
+      return this.context.newTypeReference(cls, ((TypeReference[])Conversions.unwrapArray(IterableExtensions.map(cls.getTypeParameters(), _function), TypeReference.class)));
+    }
+    
+    public StringConcatenationClient contributeToEquals(final FieldDeclaration it) {
+      StringConcatenationClient _switchResult = null;
+      String _name = this.orObject(it.getType()).getName();
+      boolean _matched = false;
+      String _name_1 = Double.TYPE.getName();
+      if (Objects.equal(_name, _name_1)) {
+        _matched=true;
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("if (");
+            _builder.append(Double.class);
+            _builder.append(".doubleToLongBits(other.");
+            String _simpleName = it.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append(") != ");
+            _builder.append(Double.class);
+            _builder.append(".doubleToLongBits(this.");
+            String _simpleName_1 = it.getSimpleName();
+            _builder.append(_simpleName_1);
+            _builder.append("))");
+            _builder.newLineIfNotEmpty();
+            _builder.append("  ");
+            _builder.append("return false; ");
+            _builder.newLine();
+          }
+        };
+        _switchResult = _client;
+      }
+      if (!_matched) {
+        String _name_2 = Float.TYPE.getName();
+        if (Objects.equal(_name, _name_2)) {
+          _matched=true;
+          StringConcatenationClient _client_1 = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append("if (");
+              _builder.append(Float.class);
+              _builder.append(".floatToIntBits(other.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(") != ");
+              _builder.append(Float.class);
+              _builder.append(".floatToIntBits(this.");
+              String _simpleName_1 = it.getSimpleName();
+              _builder.append(_simpleName_1);
+              _builder.append("))");
+              _builder.newLineIfNotEmpty();
+              _builder.append("  ");
+              _builder.append("return false; ");
+              _builder.newLine();
+            }
+          };
+          _switchResult = _client_1;
+        }
+      }
+      if (!_matched) {
+        String _name_3 = Boolean.TYPE.getName();
+        if (Objects.equal(_name, _name_3)) {
+          _matched=true;
+        }
+        if (!_matched) {
+          String _name_4 = Integer.TYPE.getName();
+          if (Objects.equal(_name, _name_4)) {
+            _matched=true;
+          }
+        }
+        if (!_matched) {
+          String _name_5 = Character.TYPE.getName();
+          if (Objects.equal(_name, _name_5)) {
+            _matched=true;
+          }
+        }
+        if (!_matched) {
+          String _name_6 = Byte.TYPE.getName();
+          if (Objects.equal(_name, _name_6)) {
+            _matched=true;
+          }
+        }
+        if (!_matched) {
+          String _name_7 = Short.TYPE.getName();
+          if (Objects.equal(_name, _name_7)) {
+            _matched=true;
+          }
+        }
+        if (!_matched) {
+          String _name_8 = Long.TYPE.getName();
+          if (Objects.equal(_name, _name_8)) {
+            _matched=true;
+          }
+        }
+        if (_matched) {
+          StringConcatenationClient _client_2 = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append("if (other.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(" != this.");
+              String _simpleName_1 = it.getSimpleName();
+              _builder.append(_simpleName_1);
+              _builder.append(")");
+              _builder.newLineIfNotEmpty();
+              _builder.append("  ");
+              _builder.append("return false;");
+              _builder.newLine();
+            }
+          };
+          _switchResult = _client_2;
+        }
+      }
+      if (!_matched) {
+        StringConcatenationClient _client_3 = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("if (this.");
+            String _simpleName = it.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append(" == null) {");
+            _builder.newLineIfNotEmpty();
+            _builder.append("  ");
+            _builder.append("if (other.");
+            String _simpleName_1 = it.getSimpleName();
+            _builder.append(_simpleName_1, "  ");
+            _builder.append(" != null)");
+            _builder.newLineIfNotEmpty();
+            _builder.append("    ");
+            _builder.append("return false;");
+            _builder.newLine();
+            _builder.append("} else if (!");
+            StringConcatenationClient _deepEquals = Util.this.deepEquals(it);
+            _builder.append(_deepEquals);
+            _builder.append(")");
+            _builder.newLineIfNotEmpty();
+            _builder.append("  ");
+            _builder.append("return false;");
+            _builder.newLine();
+          }
+        };
+        _switchResult = _client_3;
+      }
+      return _switchResult;
+    }
+    
+    public StringConcatenationClient deepEquals(final FieldDeclaration it) {
+      StringConcatenationClient _xifexpression = null;
+      boolean _isArray = it.getType().isArray();
+      if (_isArray) {
+        StringConcatenationClient _xifexpression_1 = null;
+        boolean _isPrimitive = it.getType().getArrayComponentType().isPrimitive();
+        if (_isPrimitive) {
+          StringConcatenationClient _client = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append(Arrays.class);
+              _builder.append(".equals(this.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(", other.");
+              String _simpleName_1 = it.getSimpleName();
+              _builder.append(_simpleName_1);
+              _builder.append(")");
+            }
+          };
+          _xifexpression_1 = _client;
+        } else {
+          StringConcatenationClient _client_1 = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append(Arrays.class);
+              _builder.append(".deepEquals(this.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(", other.");
+              String _simpleName_1 = it.getSimpleName();
+              _builder.append(_simpleName_1);
+              _builder.append(")");
+            }
+          };
+          _xifexpression_1 = _client_1;
+        }
+        _xifexpression = _xifexpression_1;
+      } else {
+        StringConcatenationClient _client_2 = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("this.");
+            String _simpleName = it.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append(".equals(other.");
+            String _simpleName_1 = it.getSimpleName();
+            _builder.append(_simpleName_1);
+            _builder.append(")");
+          }
+        };
+        _xifexpression = _client_2;
+      }
+      return _xifexpression;
+    }
+    
+    public void addHashCode(final MutableClassDeclaration cls, final Iterable<? extends FieldDeclaration> includedFields, final boolean includeSuper) {
+      String _xifexpression = null;
+      if (includeSuper) {
+        _xifexpression = "super.hashCode()";
+      } else {
+        _xifexpression = "1";
+      }
+      final String defaultBase = _xifexpression;
+      final int fields = IterableExtensions.size(includedFields);
+      final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration it) -> {
+        this.context.setPrimarySourceElement(it, this.context.getPrimarySourceElement(cls));
+        it.setReturnType(this.context.getPrimitiveInt());
+        it.addAnnotation(this.context.newAnnotationReference(Override.class));
+        it.addAnnotation(this.context.newAnnotationReference(Pure.class));
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            {
+              if ((fields >= 2)) {
+                _builder.append("final int prime = ");
+                _builder.append(EqualsHashCodeProcessor.Util.PRIME_VALUE);
+                _builder.append(";");
+                _builder.newLineIfNotEmpty();
+                _builder.append("int result = ");
+                _builder.append(defaultBase);
+                _builder.append(";");
+                _builder.newLineIfNotEmpty();
+                {
+                  ExclusiveRange _doubleDotLessThan = new ExclusiveRange(0, fields, true);
+                  for(final Integer i : _doubleDotLessThan) {
+                    {
+                      if (((i).intValue() == (fields - 1))) {
+                        _builder.append("return");
+                      } else {
+                        _builder.append("result =");
+                      }
+                    }
+                    _builder.append(" prime * result + ");
+                    StringConcatenationClient _contributeToHashCode = Util.this.contributeToHashCode(((FieldDeclaration[])Conversions.unwrapArray(includedFields, FieldDeclaration.class))[(i).intValue()]);
+                    _builder.append(_contributeToHashCode);
+                    _builder.append(";");
+                    _builder.newLineIfNotEmpty();
+                  }
+                }
+              } else {
+                if ((fields == 1)) {
+                  _builder.append("return ");
+                  _builder.append(EqualsHashCodeProcessor.Util.PRIME_VALUE);
+                  _builder.append(" * ");
+                  _builder.append(defaultBase);
+                  _builder.append(" + ");
+                  StringConcatenationClient _contributeToHashCode_1 = Util.this.contributeToHashCode(IterableExtensions.head(includedFields));
+                  _builder.append(_contributeToHashCode_1);
+                  _builder.append(";");
+                  _builder.newLineIfNotEmpty();
+                } else {
+                  _builder.append("return ");
+                  _builder.append(defaultBase);
+                  _builder.append(";");
+                  _builder.newLineIfNotEmpty();
+                }
+              }
+            }
+          }
+        };
+        it.setBody(_client);
+      };
+      cls.addMethod("hashCode", _function);
+    }
+    
+    public StringConcatenationClient contributeToHashCode(final FieldDeclaration it) {
+      StringConcatenationClient _switchResult = null;
+      String _name = this.orObject(it.getType()).getName();
+      boolean _matched = false;
+      String _name_1 = Double.TYPE.getName();
+      if (Objects.equal(_name, _name_1)) {
+        _matched=true;
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("(int) (");
+            _builder.append(Double.class);
+            _builder.append(".doubleToLongBits(this.");
+            String _simpleName = it.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append(") ^ (");
+            _builder.append(Double.class);
+            _builder.append(".doubleToLongBits(this.");
+            String _simpleName_1 = it.getSimpleName();
+            _builder.append(_simpleName_1);
+            _builder.append(") >>> 32))");
+          }
+        };
+        _switchResult = _client;
+      }
+      if (!_matched) {
+        String _name_2 = Float.TYPE.getName();
+        if (Objects.equal(_name, _name_2)) {
+          _matched=true;
+          StringConcatenationClient _client_1 = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append(Float.class);
+              _builder.append(".floatToIntBits(this.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(")");
+            }
+          };
+          _switchResult = _client_1;
+        }
+      }
+      if (!_matched) {
+        String _name_3 = Boolean.TYPE.getName();
+        if (Objects.equal(_name, _name_3)) {
+          _matched=true;
+          StringConcatenationClient _client_2 = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append("(this.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(" ? 1231 : 1237)");
+            }
+          };
+          _switchResult = _client_2;
+        }
+      }
+      if (!_matched) {
+        String _name_4 = Integer.TYPE.getName();
+        if (Objects.equal(_name, _name_4)) {
+          _matched=true;
+        }
+        if (!_matched) {
+          String _name_5 = Character.TYPE.getName();
+          if (Objects.equal(_name, _name_5)) {
+            _matched=true;
+          }
+        }
+        if (!_matched) {
+          String _name_6 = Byte.TYPE.getName();
+          if (Objects.equal(_name, _name_6)) {
+            _matched=true;
+          }
+        }
+        if (!_matched) {
+          String _name_7 = Short.TYPE.getName();
+          if (Objects.equal(_name, _name_7)) {
+            _matched=true;
+          }
+        }
+        if (_matched) {
+          StringConcatenationClient _client_3 = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append("this.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+            }
+          };
+          _switchResult = _client_3;
+        }
+      }
+      if (!_matched) {
+        String _name_8 = Long.TYPE.getName();
+        if (Objects.equal(_name, _name_8)) {
+          _matched=true;
+          StringConcatenationClient _client_4 = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append("(int) (this.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(" ^ (this.");
+              String _simpleName_1 = it.getSimpleName();
+              _builder.append(_simpleName_1);
+              _builder.append(" >>> 32))");
+            }
+          };
+          _switchResult = _client_4;
+        }
+      }
+      if (!_matched) {
+        StringConcatenationClient _client_5 = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("((this.");
+            String _simpleName = it.getSimpleName();
+            _builder.append(_simpleName);
+            _builder.append("== null) ? 0 : ");
+            StringConcatenationClient _deepHashCode = Util.this.deepHashCode(it);
+            _builder.append(_deepHashCode);
+            _builder.append(")");
+          }
+        };
+        _switchResult = _client_5;
+      }
+      return _switchResult;
+    }
+    
+    public StringConcatenationClient deepHashCode(final FieldDeclaration it) {
+      StringConcatenationClient _xblockexpression = null;
+      {
+        final TypeReference type = this.orObject(it.getType());
+        StringConcatenationClient _xifexpression = null;
+        boolean _isArray = type.isArray();
+        if (_isArray) {
+          StringConcatenationClient _xifexpression_1 = null;
+          boolean _isPrimitive = type.getArrayComponentType().isPrimitive();
+          if (_isPrimitive) {
+            StringConcatenationClient _client = new StringConcatenationClient() {
+              @Override
+              protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+                _builder.append(Arrays.class);
+                _builder.append(".hashCode(this.");
+                String _simpleName = it.getSimpleName();
+                _builder.append(_simpleName);
+                _builder.append(")");
+              }
+            };
+            _xifexpression_1 = _client;
+          } else {
+            StringConcatenationClient _client_1 = new StringConcatenationClient() {
+              @Override
+              protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+                _builder.append(Arrays.class);
+                _builder.append(".deepHashCode(this.");
+                String _simpleName = it.getSimpleName();
+                _builder.append(_simpleName);
+                _builder.append(")");
+              }
+            };
+            _xifexpression_1 = _client_1;
+          }
+          _xifexpression = _xifexpression_1;
+        } else {
+          StringConcatenationClient _client_2 = new StringConcatenationClient() {
+            @Override
+            protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+              _builder.append("this.");
+              String _simpleName = it.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(".hashCode()");
+            }
+          };
+          _xifexpression = _client_2;
+        }
+        _xblockexpression = _xifexpression;
+      }
+      return _xblockexpression;
+    }
+    
+    private TypeReference orObject(final TypeReference ref) {
+      TypeReference _elvis = null;
+      if (ref != null) {
+        _elvis = ref;
+      } else {
+        TypeReference _object = this.context.getObject();
+        _elvis = _object;
+      }
+      return _elvis;
+    }
+  }
+  
+  @Override
+  public void doTransform(final MutableClassDeclaration it, @Extension final TransformationContext context) {
+    AnnotationReference _findAnnotation = it.findAnnotation(context.findTypeGlobally(Data.class));
+    boolean _tripleNotEquals = (_findAnnotation != null);
+    if (_tripleNotEquals) {
+      return;
+    }
+    @Extension
+    final EqualsHashCodeProcessor.Util util = new EqualsHashCodeProcessor.Util(context);
+    boolean _hasEquals = util.hasEquals(it);
+    if (_hasEquals) {
+      final AnnotationReference annotation = it.findAnnotation(context.findTypeGlobally(EqualsHashCode.class));
+      context.addWarning(annotation, "equals is already defined, this annotation has no effect");
+    } else {
+      boolean _hasHashCode = util.hasHashCode(it);
+      if (_hasHashCode) {
+        context.addWarning(it, "hashCode is already defined, this annotation has no effect");
+      } else {
+        final Function1<MutableFieldDeclaration, Boolean> _function = (MutableFieldDeclaration it_1) -> {
+          return Boolean.valueOf((((!it_1.isStatic()) && (!it_1.isTransient())) && context.isThePrimaryGeneratedJavaElement(it_1)));
+        };
+        final Iterable<? extends MutableFieldDeclaration> fields = IterableExtensions.filter(it.getDeclaredFields(), _function);
+        util.addEquals(it, fields, util.hasSuperEquals(it));
+        util.addHashCode(it, fields, util.hasSuperHashCode(it));
+      }
+    }
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructor.java b/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructor.java
new file mode 100644
index 0000000..9d2048b
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructor.java
@@ -0,0 +1,36 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.eclipse.xtend.lib.macro.Active;
+
+/**
+ * <p>Creates a constructor that takes a parameter for each final field of a class.</p>
+ * 
+ * Annotated on a class
+ * <p>
+ * Creates a constructor that takes all
+ * non-static, final fields of the class as an argument and assigns them to
+ * their corresponding fields. The order of arguments is the same as the order
+ * of the fields.
+ * </p>
+ * Annotated on a constructor
+ * <p>
+ * Turns that constructor into a final
+ * fields constructor as described above. This is useful for adding annotations
+ * to the constructor, e.g. for dependency injection frameworks.
+ * </p>
+ * 
+ * @since 2.7
+ */
+@Target({ ElementType.TYPE, ElementType.CONSTRUCTOR })
+@GwtCompatible
+@Beta
+@Active(FinalFieldsConstructorProcessor.class)
+@Documented
+@SuppressWarnings("all")
+public @interface FinalFieldsConstructor {
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructor.xtend b/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructor.xtend
new file mode 100644
index 0000000..95db307
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructor.xtend
@@ -0,0 +1,185 @@
+package org.eclipse.xtend.lib.annotations
+
+import com.google.common.annotations.Beta
+import com.google.common.annotations.GwtCompatible
+import java.lang.annotation.ElementType
+import java.lang.annotation.Target
+import java.util.List
+import java.util.regex.Pattern
+import org.eclipse.xtend.lib.macro.Active
+import org.eclipse.xtend.lib.macro.TransformationContext
+import org.eclipse.xtend.lib.macro.TransformationParticipant
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableConstructorDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableTypeDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableTypeParameterDeclarator
+import org.eclipse.xtend.lib.macro.declaration.TypeDeclaration
+import org.eclipse.xtend.lib.macro.declaration.TypeReference
+import java.lang.annotation.Documented
+
+/**
+ * <p>Creates a constructor that takes a parameter for each final field of a class.</p>
+ * 
+ * Annotated on a class 
+ * <p>
+ * Creates a constructor that takes all
+ * non-static, final fields of the class as an argument and assigns them to
+ * their corresponding fields. The order of arguments is the same as the order
+ * of the fields.
+ * </p>
+ * Annotated on a constructor
+ * <p>
+ * Turns that constructor into a final
+ * fields constructor as described above. This is useful for adding annotations
+ * to the constructor, e.g. for dependency injection frameworks.
+ * </p>
+ * 
+ * @since 2.7
+ */
+@Target(ElementType.TYPE, ElementType.CONSTRUCTOR)
+@GwtCompatible
+@Beta
+@Active(FinalFieldsConstructorProcessor)
+@Documented
+annotation FinalFieldsConstructor {
+}
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+class FinalFieldsConstructorProcessor implements TransformationParticipant<MutableTypeParameterDeclarator> {
+
+	override doTransform(List<? extends MutableTypeParameterDeclarator> elements,
+		extension TransformationContext context) {
+		elements.forEach[transform(context)]
+	}
+
+	def dispatch void transform(MutableClassDeclaration it, extension TransformationContext context) {
+		if (findAnnotation(Data.findTypeGlobally) !== null) {
+			return
+		}
+		if (findAnnotation(Accessors.findTypeGlobally) !== null) {
+			return
+		}
+		val extension util = new FinalFieldsConstructorProcessor.Util(context)
+		addFinalFieldsConstructor
+	}
+
+	def dispatch void transform(MutableConstructorDeclaration it, extension TransformationContext context) {
+		val extension util = new FinalFieldsConstructorProcessor.Util(context)
+		makeFinalFieldsConstructor
+	}
+
+	/**
+	 * @since 2.7
+	 * @noextend
+	 * @noreference
+	 */
+	@Beta
+	static class Util {
+		extension TransformationContext context
+
+		new(TransformationContext context) {
+			this.context = context
+		}
+
+		def getFinalFields(MutableTypeDeclaration it) {
+			declaredFields.filter[!static && final == true && initializer === null && thePrimaryGeneratedJavaElement]
+		}
+
+		def needsFinalFieldConstructor(MutableClassDeclaration it) {
+			!hasFinalFieldsConstructor
+			&& (primarySourceElement as ClassDeclaration).declaredConstructors.isEmpty
+		}
+
+		def hasFinalFieldsConstructor(MutableTypeDeclaration cls) {
+			val expectedTypes = cls.finalFieldsConstructorArgumentTypes
+			cls.declaredConstructors.exists [
+				parameters.map[type].toList == expectedTypes
+			]
+		}
+		
+		def getFinalFieldsConstructorArgumentTypes(MutableTypeDeclaration cls) {
+			val types = newArrayList
+			if (cls.superConstructor !== null) {
+				types += cls.superConstructor.resolvedParameters.map[resolvedType]
+			}
+			types += cls.finalFields.map[type]
+			types
+		}
+		
+		def String getConstructorAlreadyExistsMessage(MutableTypeDeclaration it) {
+			'''Cannot create FinalFieldsConstructor as a constructor with the signature "new(«finalFieldsConstructorArgumentTypes.join(",")»)" already exists.'''
+		}
+
+		def addFinalFieldsConstructor(MutableClassDeclaration it) {
+			if (finalFieldsConstructorArgumentTypes.empty) {
+				val anno = findAnnotation(FinalFieldsConstructor.findTypeGlobally)
+				anno.addWarning('''There are no final fields, this annotation has no effect''')
+				return
+			}
+			if (hasFinalFieldsConstructor) {
+				addError(constructorAlreadyExistsMessage)
+				return
+			}
+			addConstructor [
+				primarySourceElement = declaringType.primarySourceElement
+				makeFinalFieldsConstructor
+			]
+		}
+		
+		static val EMPTY_BODY = Pattern.compile("(\\{(\\s*\\})?)?")
+
+		def makeFinalFieldsConstructor(MutableConstructorDeclaration it) {
+			if (declaringType.finalFieldsConstructorArgumentTypes.empty) {
+				val anno = findAnnotation(FinalFieldsConstructor.findTypeGlobally)
+				anno.addWarning('''There are no final fields, this annotation has no effect''')
+				return
+			}
+			if (declaringType.hasFinalFieldsConstructor) {
+				addError(declaringType.constructorAlreadyExistsMessage)
+				return
+			}
+			if (!parameters.empty) {
+				addError("Parameter list must be empty")
+			}
+			if (body !== null && !EMPTY_BODY.matcher(body.toString).matches) {
+				addError("Body must be empty")
+			}
+			val superParameters = declaringType.superConstructor?.resolvedParameters ?: #[]
+			superParameters.forEach [ p |
+				addParameter(p.declaration.simpleName, p.resolvedType)
+			]
+			val fieldToParameter = newHashMap
+			declaringType.finalFields.forEach [ p |
+				p.markAsInitializedBy(it)
+				val param = addParameter(p.simpleName, p.type.orObject)
+				fieldToParameter.put(p, param)
+			]
+			body = '''
+				super(«superParameters.join(", ")[declaration.simpleName]»);
+				«FOR arg : declaringType.finalFields»
+					this.«arg.simpleName» = «fieldToParameter.get(arg).simpleName»;
+				«ENDFOR»
+			'''
+		}
+
+		def getSuperConstructor(TypeDeclaration it) {
+			if (it instanceof ClassDeclaration) {
+				if (extendedClass == object || extendedClass === null)
+					return null;
+				return extendedClass.declaredResolvedConstructors.head
+			} else {
+				return null
+			}
+		}
+		
+		private def orObject(TypeReference ref) {
+			if (ref === null) object else ref
+		}
+	}
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructorProcessor.java b/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructorProcessor.java
new file mode 100644
index 0000000..5f86438
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/FinalFieldsConstructorProcessor.java
@@ -0,0 +1,277 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import com.google.common.collect.Iterables;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.function.Consumer;
+import java.util.regex.Pattern;
+import org.eclipse.xtend.lib.macro.TransformationContext;
+import org.eclipse.xtend.lib.macro.TransformationParticipant;
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableConstructorDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableParameterDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableTypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableTypeParameterDeclarator;
+import org.eclipse.xtend.lib.macro.declaration.ResolvedConstructor;
+import org.eclipse.xtend.lib.macro.declaration.ResolvedParameter;
+import org.eclipse.xtend.lib.macro.declaration.TypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+@SuppressWarnings("all")
+public class FinalFieldsConstructorProcessor implements TransformationParticipant<MutableTypeParameterDeclarator> {
+  /**
+   * @since 2.7
+   * @noextend
+   * @noreference
+   */
+  @Beta
+  public static class Util {
+    @Extension
+    private TransformationContext context;
+    
+    public Util(final TransformationContext context) {
+      this.context = context;
+    }
+    
+    public Iterable<? extends MutableFieldDeclaration> getFinalFields(final MutableTypeDeclaration it) {
+      final Function1<MutableFieldDeclaration, Boolean> _function = (MutableFieldDeclaration it_1) -> {
+        return Boolean.valueOf(((((!it_1.isStatic()) && (it_1.isFinal() == true)) && (it_1.getInitializer() == null)) && this.context.isThePrimaryGeneratedJavaElement(it_1)));
+      };
+      return IterableExtensions.filter(it.getDeclaredFields(), _function);
+    }
+    
+    public boolean needsFinalFieldConstructor(final MutableClassDeclaration it) {
+      return ((!this.hasFinalFieldsConstructor(it)) && IterableExtensions.isEmpty(((ClassDeclaration) this.context.getPrimarySourceElement(it)).getDeclaredConstructors()));
+    }
+    
+    public boolean hasFinalFieldsConstructor(final MutableTypeDeclaration cls) {
+      boolean _xblockexpression = false;
+      {
+        final ArrayList<TypeReference> expectedTypes = this.getFinalFieldsConstructorArgumentTypes(cls);
+        final Function1<MutableConstructorDeclaration, Boolean> _function = (MutableConstructorDeclaration it) -> {
+          final Function1<MutableParameterDeclaration, TypeReference> _function_1 = (MutableParameterDeclaration it_1) -> {
+            return it_1.getType();
+          };
+          List<TypeReference> _list = IterableExtensions.<TypeReference>toList(IterableExtensions.map(it.getParameters(), _function_1));
+          return Boolean.valueOf(Objects.equal(_list, expectedTypes));
+        };
+        _xblockexpression = IterableExtensions.exists(cls.getDeclaredConstructors(), _function);
+      }
+      return _xblockexpression;
+    }
+    
+    public ArrayList<TypeReference> getFinalFieldsConstructorArgumentTypes(final MutableTypeDeclaration cls) {
+      ArrayList<TypeReference> _xblockexpression = null;
+      {
+        final ArrayList<TypeReference> types = CollectionLiterals.<TypeReference>newArrayList();
+        ResolvedConstructor _superConstructor = this.getSuperConstructor(cls);
+        boolean _tripleNotEquals = (_superConstructor != null);
+        if (_tripleNotEquals) {
+          final Function1<ResolvedParameter, TypeReference> _function = (ResolvedParameter it) -> {
+            return it.getResolvedType();
+          };
+          Iterable<TypeReference> _map = IterableExtensions.map(this.getSuperConstructor(cls).getResolvedParameters(), _function);
+          Iterables.<TypeReference>addAll(types, _map);
+        }
+        final Function1<MutableFieldDeclaration, TypeReference> _function_1 = (MutableFieldDeclaration it) -> {
+          return it.getType();
+        };
+        Iterable<TypeReference> _map_1 = IterableExtensions.map(this.getFinalFields(cls), _function_1);
+        Iterables.<TypeReference>addAll(types, _map_1);
+        _xblockexpression = types;
+      }
+      return _xblockexpression;
+    }
+    
+    public String getConstructorAlreadyExistsMessage(final MutableTypeDeclaration it) {
+      StringConcatenation _builder = new StringConcatenation();
+      _builder.append("Cannot create FinalFieldsConstructor as a constructor with the signature \"new(");
+      String _join = IterableExtensions.join(this.getFinalFieldsConstructorArgumentTypes(it), ",");
+      _builder.append(_join);
+      _builder.append(")\" already exists.");
+      return _builder.toString();
+    }
+    
+    public void addFinalFieldsConstructor(final MutableClassDeclaration it) {
+      boolean _isEmpty = this.getFinalFieldsConstructorArgumentTypes(it).isEmpty();
+      if (_isEmpty) {
+        final AnnotationReference anno = it.findAnnotation(this.context.findTypeGlobally(FinalFieldsConstructor.class));
+        StringConcatenation _builder = new StringConcatenation();
+        _builder.append("There are no final fields, this annotation has no effect");
+        this.context.addWarning(anno, _builder.toString());
+        return;
+      }
+      boolean _hasFinalFieldsConstructor = this.hasFinalFieldsConstructor(it);
+      if (_hasFinalFieldsConstructor) {
+        this.context.addError(it, this.getConstructorAlreadyExistsMessage(it));
+        return;
+      }
+      final Procedure1<MutableConstructorDeclaration> _function = (MutableConstructorDeclaration it_1) -> {
+        this.context.setPrimarySourceElement(it_1, this.context.getPrimarySourceElement(it_1.getDeclaringType()));
+        this.makeFinalFieldsConstructor(it_1);
+      };
+      it.addConstructor(_function);
+    }
+    
+    private static final Pattern EMPTY_BODY = Pattern.compile("(\\{(\\s*\\})?)?");
+    
+    public void makeFinalFieldsConstructor(final MutableConstructorDeclaration it) {
+      boolean _isEmpty = this.getFinalFieldsConstructorArgumentTypes(it.getDeclaringType()).isEmpty();
+      if (_isEmpty) {
+        final AnnotationReference anno = it.findAnnotation(this.context.findTypeGlobally(FinalFieldsConstructor.class));
+        StringConcatenation _builder = new StringConcatenation();
+        _builder.append("There are no final fields, this annotation has no effect");
+        this.context.addWarning(anno, _builder.toString());
+        return;
+      }
+      boolean _hasFinalFieldsConstructor = this.hasFinalFieldsConstructor(it.getDeclaringType());
+      if (_hasFinalFieldsConstructor) {
+        this.context.addError(it, this.getConstructorAlreadyExistsMessage(it.getDeclaringType()));
+        return;
+      }
+      boolean _isEmpty_1 = IterableExtensions.isEmpty(it.getParameters());
+      boolean _not = (!_isEmpty_1);
+      if (_not) {
+        this.context.addError(it, "Parameter list must be empty");
+      }
+      if (((it.getBody() != null) && (!FinalFieldsConstructorProcessor.Util.EMPTY_BODY.matcher(it.getBody().toString()).matches()))) {
+        this.context.addError(it, "Body must be empty");
+      }
+      Iterable<? extends ResolvedParameter> _elvis = null;
+      ResolvedConstructor _superConstructor = this.getSuperConstructor(it.getDeclaringType());
+      Iterable<? extends ResolvedParameter> _resolvedParameters = null;
+      if (_superConstructor!=null) {
+        _resolvedParameters=_superConstructor.getResolvedParameters();
+      }
+      if (_resolvedParameters != null) {
+        _elvis = _resolvedParameters;
+      } else {
+        _elvis = Collections.<ResolvedParameter>unmodifiableList(CollectionLiterals.<ResolvedParameter>newArrayList());
+      }
+      final Iterable<? extends ResolvedParameter> superParameters = _elvis;
+      final Consumer<ResolvedParameter> _function = (ResolvedParameter p) -> {
+        it.addParameter(p.getDeclaration().getSimpleName(), p.getResolvedType());
+      };
+      superParameters.forEach(_function);
+      final HashMap<MutableFieldDeclaration, MutableParameterDeclaration> fieldToParameter = CollectionLiterals.<MutableFieldDeclaration, MutableParameterDeclaration>newHashMap();
+      final Consumer<MutableFieldDeclaration> _function_1 = (MutableFieldDeclaration p) -> {
+        p.markAsInitializedBy(it);
+        final MutableParameterDeclaration param = it.addParameter(p.getSimpleName(), this.orObject(p.getType()));
+        fieldToParameter.put(p, param);
+      };
+      this.getFinalFields(it.getDeclaringType()).forEach(_function_1);
+      StringConcatenationClient _client = new StringConcatenationClient() {
+        @Override
+        protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+          _builder.append("super(");
+          final Function1<ResolvedParameter, CharSequence> _function = (ResolvedParameter it_1) -> {
+            return it_1.getDeclaration().getSimpleName();
+          };
+          String _join = IterableExtensions.join(superParameters, ", ", _function);
+          _builder.append(_join);
+          _builder.append(");");
+          _builder.newLineIfNotEmpty();
+          {
+            Iterable<? extends MutableFieldDeclaration> _finalFields = Util.this.getFinalFields(it.getDeclaringType());
+            for(final MutableFieldDeclaration arg : _finalFields) {
+              _builder.append("this.");
+              String _simpleName = arg.getSimpleName();
+              _builder.append(_simpleName);
+              _builder.append(" = ");
+              String _simpleName_1 = fieldToParameter.get(arg).getSimpleName();
+              _builder.append(_simpleName_1);
+              _builder.append(";");
+              _builder.newLineIfNotEmpty();
+            }
+          }
+        }
+      };
+      it.setBody(_client);
+    }
+    
+    public ResolvedConstructor getSuperConstructor(final TypeDeclaration it) {
+      if ((it instanceof ClassDeclaration)) {
+        if ((Objects.equal(((ClassDeclaration)it).getExtendedClass(), this.context.getObject()) || (((ClassDeclaration)it).getExtendedClass() == null))) {
+          return null;
+        }
+        return IterableExtensions.head(((ClassDeclaration)it).getExtendedClass().getDeclaredResolvedConstructors());
+      } else {
+        return null;
+      }
+    }
+    
+    private TypeReference orObject(final TypeReference ref) {
+      TypeReference _xifexpression = null;
+      if ((ref == null)) {
+        _xifexpression = this.context.getObject();
+      } else {
+        _xifexpression = ref;
+      }
+      return _xifexpression;
+    }
+  }
+  
+  @Override
+  public void doTransform(final List<? extends MutableTypeParameterDeclarator> elements, @Extension final TransformationContext context) {
+    final Consumer<MutableTypeParameterDeclarator> _function = (MutableTypeParameterDeclarator it) -> {
+      this.transform(it, context);
+    };
+    elements.forEach(_function);
+  }
+  
+  protected void _transform(final MutableClassDeclaration it, @Extension final TransformationContext context) {
+    AnnotationReference _findAnnotation = it.findAnnotation(context.findTypeGlobally(Data.class));
+    boolean _tripleNotEquals = (_findAnnotation != null);
+    if (_tripleNotEquals) {
+      return;
+    }
+    AnnotationReference _findAnnotation_1 = it.findAnnotation(context.findTypeGlobally(Accessors.class));
+    boolean _tripleNotEquals_1 = (_findAnnotation_1 != null);
+    if (_tripleNotEquals_1) {
+      return;
+    }
+    @Extension
+    final FinalFieldsConstructorProcessor.Util util = new FinalFieldsConstructorProcessor.Util(context);
+    util.addFinalFieldsConstructor(it);
+  }
+  
+  protected void _transform(final MutableConstructorDeclaration it, @Extension final TransformationContext context) {
+    @Extension
+    final FinalFieldsConstructorProcessor.Util util = new FinalFieldsConstructorProcessor.Util(context);
+    util.makeFinalFieldsConstructor(it);
+  }
+  
+  public void transform(final MutableTypeParameterDeclarator it, final TransformationContext context) {
+    if (it instanceof MutableConstructorDeclaration) {
+      _transform((MutableConstructorDeclaration)it, context);
+      return;
+    } else if (it instanceof MutableClassDeclaration) {
+      _transform((MutableClassDeclaration)it, context);
+      return;
+    } else {
+      throw new IllegalArgumentException("Unhandled parameter types: " +
+        Arrays.<Object>asList(it, context).toString());
+    }
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/ToString.java b/java/org/eclipse/xtend/lib/annotations/ToString.java
new file mode 100644
index 0000000..f6a96e9
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/ToString.java
@@ -0,0 +1,59 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import org.eclipse.xtend.lib.macro.Active;
+import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;
+
+/**
+ * Creates a default {@link Object#toString toString} implementation.
+ * 
+ * <p>
+ * All non-static fields of this class and all of its superclasses are used.
+ * Reflection is used to access all fields if this class has a superclass. This may not work in restrictive environments.
+ * For such cases use {@link ToStringBuilder} to write a non-reflective implementation.
+ * </p>
+ * The default format is:
+ * <pre>
+ *  ClassName [
+ *    field1 = "Foo"
+ *    field2 = 2
+ *    field3 = null
+ *  ]
+ * </pre>
+ * 
+ * The class name is hardcoded. Subclasses which inherit this class without overriding <code>toString</code> will show the same name.
+ * 
+ * </p>
+ * <p>
+ * For brevity there are options to hide field names, skip fields with null values and print everything on one line.
+ * </p>
+ * @since 2.7
+ */
+@Beta
+@Target(ElementType.TYPE)
+@Active(ToStringProcessor.class)
+@GwtCompatible
+@SuppressWarnings("all")
+public @interface ToString {
+  /**
+   * Fields with null values are not shown in the output.
+   */
+  public boolean skipNulls() default false;
+  /**
+   * Seperate fields with a comma and a single space
+   */
+  public boolean singleLine() default false;
+  /**
+   * Only list the values of the fields, not their names
+   */
+  public boolean hideFieldNames() default false;
+  /**
+   * By default, Iterables, Arrays and multiline Strings are pretty-printed.
+   * Switching to their normal representation makes the toString method significantly faster.
+   * @since 2.9
+   */
+  public boolean verbatimValues() default false;
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/ToString.xtend b/java/org/eclipse/xtend/lib/annotations/ToString.xtend
new file mode 100644
index 0000000..8a40140
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/ToString.xtend
@@ -0,0 +1,200 @@
+package org.eclipse.xtend.lib.annotations
+
+import com.google.common.annotations.Beta
+import com.google.common.annotations.GwtCompatible
+import java.lang.annotation.ElementType
+import java.lang.annotation.Target
+import org.eclipse.xtend.lib.macro.AbstractClassProcessor
+import org.eclipse.xtend.lib.macro.Active
+import org.eclipse.xtend.lib.macro.TransformationContext
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration
+import org.eclipse.xtext.xbase.lib.util.ToStringBuilder
+
+/**
+ * Creates a default {@link Object#toString toString} implementation. 
+ * 
+ * <p>
+ * All non-static fields of this class and all of its superclasses are used.
+ * Reflection is used to access all fields if this class has a superclass. This may not work in restrictive environments. 
+ * For such cases use {@link ToStringBuilder} to write a non-reflective implementation.
+ * </p>
+ * The default format is:
+ * <pre>
+ *  ClassName [
+ *    field1 = "Foo"
+ *    field2 = 2
+ *    field3 = null
+ *  ]
+ * </pre>
+ * 
+ * The class name is hardcoded. Subclasses which inherit this class without overriding <code>toString</code> will show the same name.
+ * 
+ * </p>
+ * <p>
+ * For brevity there are options to hide field names, skip fields with null values and print everything on one line.
+ * </p>
+ * @since 2.7
+ */
+@Beta
+@Target(ElementType.TYPE)
+@Active(ToStringProcessor)
+@GwtCompatible
+annotation ToString {
+	/**
+	 * Fields with null values are not shown in the output.
+	 */
+	val skipNulls = false
+	/**
+	 * Seperate fields with a comma and a single space
+	 */
+	val singleLine = false
+	/**
+	 * Only list the values of the fields, not their names
+	 */
+	val hideFieldNames = false
+
+	/**
+	 * By default, Iterables, Arrays and multiline Strings are pretty-printed.
+	 * Switching to their normal representation makes the toString method significantly faster.
+	 * @since 2.9
+	 */
+	val verbatimValues = false
+}
+
+/**
+ * @since 2.7
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noreference This class is not intended to be referenced by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@Beta
+class ToStringConfiguration {
+	val boolean skipNulls
+	val boolean singleLine
+	val boolean hideFieldNames
+	val boolean verbatimValues
+
+	new() {
+		this(false, false, false, false)
+	}
+
+	new(boolean skipNulls, boolean singleLine, boolean hideFieldNames, boolean verbatimValues) {
+		this.skipNulls = skipNulls
+		this.singleLine = singleLine
+		this.hideFieldNames = hideFieldNames
+		this.verbatimValues = verbatimValues
+	}
+
+	new(AnnotationReference annotation) {
+		this.skipNulls = annotation.getBooleanValue("skipNulls")
+		this.singleLine = annotation.getBooleanValue("singleLine")
+		this.hideFieldNames = annotation.getBooleanValue("hideFieldNames")
+		this.verbatimValues = annotation.getBooleanValue("verbatimValues")
+	}
+
+	def isSkipNulls() {
+		skipNulls
+	}
+
+	def isSingleLine() {
+		singleLine
+	}
+
+	def isHideFieldNames() {
+		hideFieldNames
+	}
+
+	def isVerbatimValues() {
+		verbatimValues
+	}
+}
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+class ToStringProcessor extends AbstractClassProcessor {
+
+	override doTransform(MutableClassDeclaration it, extension TransformationContext context) {
+		if (findAnnotation(Data.findTypeGlobally) !== null) {
+			return
+		}
+		val extension util = new ToStringProcessor.Util(context)
+		val annotation = findAnnotation(ToString.findTypeGlobally)
+		val configuration = new ToStringConfiguration(annotation)
+		if (hasToString) {
+			annotation.addWarning("toString is already defined, this annotation has no effect.")
+		} else if (extendedClass != object) {
+			addReflectiveToString(configuration)
+		} else {
+			addToString(declaredFields.filter[thePrimaryGeneratedJavaElement && ! static && !transient], configuration)
+		}
+	}
+
+	/**
+	 * @since 2.7
+	 * @noextend
+	 * @noreference
+	 */
+	@Beta
+	static class Util {
+		extension TransformationContext context
+
+		new(TransformationContext context) {
+			this.context = context
+		}
+
+		def hasToString(ClassDeclaration it) {
+			findDeclaredMethod("toString") !== null
+		}
+
+		def getToStringConfig(ClassDeclaration it) {
+			val anno = findAnnotation(ToString.findTypeGlobally)
+			if(anno === null) null else new ToStringConfiguration(anno)
+		}
+
+		def void addReflectiveToString(MutableClassDeclaration cls, ToStringConfiguration config) {
+			cls.addMethod("toString") [
+				primarySourceElement = cls.primarySourceElement
+				returnType = string
+				addAnnotation(newAnnotationReference(Override))
+				addAnnotation(newAnnotationReference(Pure))
+				body = '''
+					return new «ToStringBuilder»(this)
+						.addAllFields()
+						«IF config.skipNulls».skipNulls()«ENDIF»
+						«IF config.singleLine».singleLine()«ENDIF»
+						«IF config.hideFieldNames».hideFieldNames()«ENDIF»
+						«IF config.verbatimValues».verbatimValues()«ENDIF»
+						.toString();
+				'''
+			]
+		}
+
+		def void addToString(MutableClassDeclaration cls, Iterable<? extends FieldDeclaration> fields,
+			ToStringConfiguration config) {
+			cls.addMethod("toString") [
+				primarySourceElement = cls.primarySourceElement
+				returnType = string
+				addAnnotation(newAnnotationReference(Override))
+				addAnnotation(newAnnotationReference(Pure))
+				body = '''
+					«ToStringBuilder» b = new «ToStringBuilder»(this);
+					«IF config.skipNulls»b.skipNulls();«ENDIF»
+					«IF config.singleLine»b.singleLine();«ENDIF»
+					«IF config.hideFieldNames»b.hideFieldNames();«ENDIF»
+					«IF config.verbatimValues»b.verbatimValues();«ENDIF»
+					«FOR field : fields»
+						b.add("«field.simpleName»", this.«field.simpleName»);
+					«ENDFOR»
+					return b.toString();
+				'''
+			]
+		}
+	}
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/ToStringConfiguration.java b/java/org/eclipse/xtend/lib/annotations/ToStringConfiguration.java
new file mode 100644
index 0000000..36d3770
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/ToStringConfiguration.java
@@ -0,0 +1,56 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
+
+/**
+ * @since 2.7
+ * @noextend This class is not intended to be subclassed by clients.
+ * @noreference This class is not intended to be referenced by clients.
+ * @noinstantiate This class is not intended to be instantiated by clients.
+ */
+@Beta
+@SuppressWarnings("all")
+public class ToStringConfiguration {
+  private final boolean skipNulls;
+  
+  private final boolean singleLine;
+  
+  private final boolean hideFieldNames;
+  
+  private final boolean verbatimValues;
+  
+  public ToStringConfiguration() {
+    this(false, false, false, false);
+  }
+  
+  public ToStringConfiguration(final boolean skipNulls, final boolean singleLine, final boolean hideFieldNames, final boolean verbatimValues) {
+    this.skipNulls = skipNulls;
+    this.singleLine = singleLine;
+    this.hideFieldNames = hideFieldNames;
+    this.verbatimValues = verbatimValues;
+  }
+  
+  public ToStringConfiguration(final AnnotationReference annotation) {
+    this.skipNulls = annotation.getBooleanValue("skipNulls");
+    this.singleLine = annotation.getBooleanValue("singleLine");
+    this.hideFieldNames = annotation.getBooleanValue("hideFieldNames");
+    this.verbatimValues = annotation.getBooleanValue("verbatimValues");
+  }
+  
+  public boolean isSkipNulls() {
+    return this.skipNulls;
+  }
+  
+  public boolean isSingleLine() {
+    return this.singleLine;
+  }
+  
+  public boolean isHideFieldNames() {
+    return this.hideFieldNames;
+  }
+  
+  public boolean isVerbatimValues() {
+    return this.verbatimValues;
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/annotations/ToStringProcessor.java b/java/org/eclipse/xtend/lib/annotations/ToStringProcessor.java
new file mode 100644
index 0000000..0b6445c
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/annotations/ToStringProcessor.java
@@ -0,0 +1,215 @@
+package org.eclipse.xtend.lib.annotations;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.eclipse.xtend.lib.macro.AbstractClassProcessor;
+import org.eclipse.xtend.lib.macro.TransformationContext;
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableMethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+import org.eclipse.xtext.xbase.lib.Extension;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.lib.Pure;
+import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;
+
+/**
+ * @since 2.7
+ * @noextend
+ * @noreference
+ */
+@Beta
+@SuppressWarnings("all")
+public class ToStringProcessor extends AbstractClassProcessor {
+  /**
+   * @since 2.7
+   * @noextend
+   * @noreference
+   */
+  @Beta
+  public static class Util {
+    @Extension
+    private TransformationContext context;
+    
+    public Util(final TransformationContext context) {
+      this.context = context;
+    }
+    
+    public boolean hasToString(final ClassDeclaration it) {
+      MethodDeclaration _findDeclaredMethod = it.findDeclaredMethod("toString");
+      return (_findDeclaredMethod != null);
+    }
+    
+    public ToStringConfiguration getToStringConfig(final ClassDeclaration it) {
+      ToStringConfiguration _xblockexpression = null;
+      {
+        final AnnotationReference anno = it.findAnnotation(this.context.findTypeGlobally(ToString.class));
+        ToStringConfiguration _xifexpression = null;
+        if ((anno == null)) {
+          _xifexpression = null;
+        } else {
+          _xifexpression = new ToStringConfiguration(anno);
+        }
+        _xblockexpression = _xifexpression;
+      }
+      return _xblockexpression;
+    }
+    
+    public void addReflectiveToString(final MutableClassDeclaration cls, final ToStringConfiguration config) {
+      final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration it) -> {
+        this.context.setPrimarySourceElement(it, this.context.getPrimarySourceElement(cls));
+        it.setReturnType(this.context.getString());
+        it.addAnnotation(this.context.newAnnotationReference(Override.class));
+        it.addAnnotation(this.context.newAnnotationReference(Pure.class));
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append("return new ");
+            _builder.append(ToStringBuilder.class);
+            _builder.append("(this)");
+            _builder.newLineIfNotEmpty();
+            _builder.append("\t");
+            _builder.append(".addAllFields()");
+            _builder.newLine();
+            _builder.append("\t");
+            {
+              boolean _isSkipNulls = config.isSkipNulls();
+              if (_isSkipNulls) {
+                _builder.append(".skipNulls()");
+              }
+            }
+            _builder.newLineIfNotEmpty();
+            _builder.append("\t");
+            {
+              boolean _isSingleLine = config.isSingleLine();
+              if (_isSingleLine) {
+                _builder.append(".singleLine()");
+              }
+            }
+            _builder.newLineIfNotEmpty();
+            _builder.append("\t");
+            {
+              boolean _isHideFieldNames = config.isHideFieldNames();
+              if (_isHideFieldNames) {
+                _builder.append(".hideFieldNames()");
+              }
+            }
+            _builder.newLineIfNotEmpty();
+            _builder.append("\t");
+            {
+              boolean _isVerbatimValues = config.isVerbatimValues();
+              if (_isVerbatimValues) {
+                _builder.append(".verbatimValues()");
+              }
+            }
+            _builder.newLineIfNotEmpty();
+            _builder.append("\t");
+            _builder.append(".toString();");
+            _builder.newLine();
+          }
+        };
+        it.setBody(_client);
+      };
+      cls.addMethod("toString", _function);
+    }
+    
+    public void addToString(final MutableClassDeclaration cls, final Iterable<? extends FieldDeclaration> fields, final ToStringConfiguration config) {
+      final Procedure1<MutableMethodDeclaration> _function = (MutableMethodDeclaration it) -> {
+        this.context.setPrimarySourceElement(it, this.context.getPrimarySourceElement(cls));
+        it.setReturnType(this.context.getString());
+        it.addAnnotation(this.context.newAnnotationReference(Override.class));
+        it.addAnnotation(this.context.newAnnotationReference(Pure.class));
+        StringConcatenationClient _client = new StringConcatenationClient() {
+          @Override
+          protected void appendTo(StringConcatenationClient.TargetStringConcatenation _builder) {
+            _builder.append(ToStringBuilder.class);
+            _builder.append(" b = new ");
+            _builder.append(ToStringBuilder.class);
+            _builder.append("(this);");
+            _builder.newLineIfNotEmpty();
+            {
+              boolean _isSkipNulls = config.isSkipNulls();
+              if (_isSkipNulls) {
+                _builder.append("b.skipNulls();");
+              }
+            }
+            _builder.newLineIfNotEmpty();
+            {
+              boolean _isSingleLine = config.isSingleLine();
+              if (_isSingleLine) {
+                _builder.append("b.singleLine();");
+              }
+            }
+            _builder.newLineIfNotEmpty();
+            {
+              boolean _isHideFieldNames = config.isHideFieldNames();
+              if (_isHideFieldNames) {
+                _builder.append("b.hideFieldNames();");
+              }
+            }
+            _builder.newLineIfNotEmpty();
+            {
+              boolean _isVerbatimValues = config.isVerbatimValues();
+              if (_isVerbatimValues) {
+                _builder.append("b.verbatimValues();");
+              }
+            }
+            _builder.newLineIfNotEmpty();
+            {
+              for(final FieldDeclaration field : fields) {
+                _builder.append("b.add(\"");
+                String _simpleName = field.getSimpleName();
+                _builder.append(_simpleName);
+                _builder.append("\", this.");
+                String _simpleName_1 = field.getSimpleName();
+                _builder.append(_simpleName_1);
+                _builder.append(");");
+                _builder.newLineIfNotEmpty();
+              }
+            }
+            _builder.append("return b.toString();");
+            _builder.newLine();
+          }
+        };
+        it.setBody(_client);
+      };
+      cls.addMethod("toString", _function);
+    }
+  }
+  
+  @Override
+  public void doTransform(final MutableClassDeclaration it, @Extension final TransformationContext context) {
+    AnnotationReference _findAnnotation = it.findAnnotation(context.findTypeGlobally(Data.class));
+    boolean _tripleNotEquals = (_findAnnotation != null);
+    if (_tripleNotEquals) {
+      return;
+    }
+    @Extension
+    final ToStringProcessor.Util util = new ToStringProcessor.Util(context);
+    final AnnotationReference annotation = it.findAnnotation(context.findTypeGlobally(ToString.class));
+    final ToStringConfiguration configuration = new ToStringConfiguration(annotation);
+    boolean _hasToString = util.hasToString(it);
+    if (_hasToString) {
+      context.addWarning(annotation, "toString is already defined, this annotation has no effect.");
+    } else {
+      TypeReference _extendedClass = it.getExtendedClass();
+      TypeReference _object = context.getObject();
+      boolean _notEquals = (!Objects.equal(_extendedClass, _object));
+      if (_notEquals) {
+        util.addReflectiveToString(it, configuration);
+      } else {
+        final Function1<MutableFieldDeclaration, Boolean> _function = (MutableFieldDeclaration it_1) -> {
+          return Boolean.valueOf(((context.isThePrimaryGeneratedJavaElement(it_1) && (!it_1.isStatic())) && (!it_1.isTransient())));
+        };
+        util.addToString(it, IterableExtensions.filter(it.getDeclaredFields(), _function), configuration);
+      }
+    }
+  }
+}
diff --git a/java/org/eclipse/xtend/lib/macro/AbstractAnnotationTypeProcessor.java b/java/org/eclipse/xtend/lib/macro/AbstractAnnotationTypeProcessor.java
new file mode 100644
index 0000000..77980b8
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/AbstractAnnotationTypeProcessor.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.AnnotationTypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableAnnotationTypeDeclaration;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A convenient base class to process active annotations for annotation types.
+ */
+@Beta
+public abstract class AbstractAnnotationTypeProcessor implements RegisterGlobalsParticipant<AnnotationTypeDeclaration>, TransformationParticipant<MutableAnnotationTypeDeclaration>, CodeGenerationParticipant<AnnotationTypeDeclaration>, ValidationParticipant<AnnotationTypeDeclaration> {
+
+	public void doRegisterGlobals(List<? extends AnnotationTypeDeclaration> annotatedAnnotationTypes, @Extension RegisterGlobalsContext context) {
+		for (AnnotationTypeDeclaration annotatedAnnotationType : annotatedAnnotationTypes) {
+			doRegisterGlobals(annotatedAnnotationType, context);
+		}
+	}
+	
+	/**
+	 * Called during global symbol collecting.
+	 * 
+	 * @param annotatedAnnotationType a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doRegisterGlobals(AnnotationTypeDeclaration annotatedAnnotationType, @Extension RegisterGlobalsContext context) {}
+	
+	public void doTransform(List<? extends MutableAnnotationTypeDeclaration> annotatedAnnotationTypes, @Extension TransformationContext context) {
+		for (MutableAnnotationTypeDeclaration annotatedAnnotationType : annotatedAnnotationTypes) {
+			doTransform(annotatedAnnotationType, context);
+		}
+	}
+
+	/**
+	 * @param annotatedAnnotationType a mutable annotation type representation annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doTransform(MutableAnnotationTypeDeclaration annotatedAnnotationType, @Extension TransformationContext context) {}
+
+	public void doGenerateCode(List<? extends AnnotationTypeDeclaration> annotatedSourceElements, @Extension CodeGenerationContext context) {
+		for (AnnotationTypeDeclaration annotatedAnnotationType : annotatedSourceElements) {
+			doGenerateCode(annotatedAnnotationType, context);
+		}
+	}
+	
+	/**
+	 * Called during code generation. 
+	 * 
+	 * @param annotatedAnnotationType a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 * @see CodeGenerationParticipant#doGenerateCode(List, CodeGenerationContext)
+	 */
+	public void doGenerateCode(AnnotationTypeDeclaration annotatedAnnotationType, @Extension CodeGenerationContext context) {}
+	
+	public void doValidate(List<? extends AnnotationTypeDeclaration> annotatedAnnotationTypes, @Extension ValidationContext context) {
+		for (AnnotationTypeDeclaration annotatedAnnotationType : annotatedAnnotationTypes) {
+			doValidate(annotatedAnnotationType, context);
+		}
+	}
+
+	/**
+	 * Invoked by the validator
+	 * @param annotatedAnnotationType the generated annotation type that should be validated 
+	 * @param context 
+	 * @see #doValidate(List, ValidationContext)
+	 * @since 2.7
+	 */
+	public void doValidate(AnnotationTypeDeclaration annotatedAnnotationType, @Extension ValidationContext context) {}
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/AbstractClassProcessor.java b/java/org/eclipse/xtend/lib/macro/AbstractClassProcessor.java
new file mode 100644
index 0000000..543d9ae
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/AbstractClassProcessor.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A convenient base class to process active annotations for classes.
+ * 
+ * @author Sven Efftinge
+ */
+@Beta
+public abstract class AbstractClassProcessor implements RegisterGlobalsParticipant<ClassDeclaration>, TransformationParticipant<MutableClassDeclaration>, CodeGenerationParticipant<ClassDeclaration>, ValidationParticipant<ClassDeclaration> {
+
+	public void doRegisterGlobals(List<? extends ClassDeclaration> annotatedClasses, @Extension RegisterGlobalsContext context) {
+		for (ClassDeclaration annotatedClass : annotatedClasses) {
+			doRegisterGlobals(annotatedClass, context);
+		}
+	}
+	
+	/**
+	 * Called during global symbol collecting.
+	 * 
+	 * @param annotatedClass a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doRegisterGlobals(ClassDeclaration annotatedClass, @Extension RegisterGlobalsContext context) {}
+	
+	public void doTransform(List<? extends MutableClassDeclaration> annotatedClasses, @Extension TransformationContext context) {
+		for (MutableClassDeclaration annotatedClass : annotatedClasses) {
+			doTransform(annotatedClass, context);
+		}
+	}
+
+	/**
+	 * @param annotatedClass a mutable class representation annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doTransform(MutableClassDeclaration annotatedClass, @Extension TransformationContext context) {}
+
+	public void doGenerateCode(List<? extends ClassDeclaration> annotatedSourceElements, @Extension CodeGenerationContext context) {
+		for (ClassDeclaration annotatedClass : annotatedSourceElements) {
+			doGenerateCode(annotatedClass, context);
+		}
+	}
+	
+	/**
+	 * Called during code generation. 
+	 * 
+	 * @param annotatedClass a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 * @see CodeGenerationParticipant#doGenerateCode(List, CodeGenerationContext)
+	 */
+	public void doGenerateCode(ClassDeclaration annotatedClass, @Extension CodeGenerationContext context) {}
+	
+	public void doValidate(List<? extends ClassDeclaration> annotatedClasses, @Extension ValidationContext context) {
+		for (ClassDeclaration annotatedClass : annotatedClasses) {
+			doValidate(annotatedClass, context);
+		}
+	}
+
+	/**
+	 * Invoked by the validator
+	 * @param annotatedClass the generated class that should be validated 
+	 * @param context 
+	 * @see #doValidate(List, ValidationContext)
+	 * @since 2.7
+	 */
+	public void doValidate(ClassDeclaration annotatedClass, @Extension ValidationContext context) {}
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/AbstractConstructorProcessor.java b/java/org/eclipse/xtend/lib/macro/AbstractConstructorProcessor.java
new file mode 100644
index 0000000..eb25538
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/AbstractConstructorProcessor.java
@@ -0,0 +1,79 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.ConstructorDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableConstructorDeclaration;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A convenient base class to process active annotations for constructors.
+ * 
+ * @author Sven Efftinge
+ * @since 2.8
+ */
+@Beta
+public abstract class AbstractConstructorProcessor implements RegisterGlobalsParticipant<ConstructorDeclaration>, TransformationParticipant<MutableConstructorDeclaration>, CodeGenerationParticipant<ConstructorDeclaration>, ValidationParticipant<ConstructorDeclaration> {
+	
+	public void doRegisterGlobals(List<? extends ConstructorDeclaration> annotatedConstructors, RegisterGlobalsContext context) {
+		for (ConstructorDeclaration annotatedConstructor : annotatedConstructors) {
+			doRegisterGlobals(annotatedConstructor, context);
+		}
+	}
+	
+	/**
+	 * @param annotatedConstructor a source method annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doRegisterGlobals(ConstructorDeclaration annotatedConstructor, RegisterGlobalsContext context) {}
+
+	public void doTransform(List<? extends MutableConstructorDeclaration> annotatedConstructors, @Extension TransformationContext context) {
+		for (MutableConstructorDeclaration annotatedConstructor : annotatedConstructors) {
+			doTransform(annotatedConstructor, context);
+		}
+	}
+
+	/**
+	 * @param annotatedConstructor a mutable method representation annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doTransform(MutableConstructorDeclaration annotatedConstructor, @Extension TransformationContext context) {}
+
+	public void doGenerateCode(List<? extends ConstructorDeclaration> annotatedConstructors, @Extension CodeGenerationContext context) {
+		for (ConstructorDeclaration annotatedConstructor : annotatedConstructors) {
+			doGenerateCode(annotatedConstructor, context);
+		}
+	}
+	
+	/**
+	 * @param annotatedConstructor a source method annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doGenerateCode(ConstructorDeclaration annotatedConstructor, @Extension CodeGenerationContext context) {}
+
+	public void doValidate(List<? extends ConstructorDeclaration> annotatedConstructors, @Extension ValidationContext context) {
+		for (ConstructorDeclaration annotatedConstructor : annotatedConstructors) {
+			doValidate(annotatedConstructor, context);
+		}
+	}
+
+	/**
+	 * Invoked by the validator 
+	 * @param annotatedConstructor that generated method that should be validated
+	 * @param context
+	 * @see #doValidate(ConstructorDeclaration, ValidationContext)
+	 * @since 2.7
+	 */
+	public void doValidate(ConstructorDeclaration annotatedConstructor, ValidationContext context) {
+	}
+}
diff --git a/java/org/eclipse/xtend/lib/macro/AbstractEnumerationTypeProcessor.java b/java/org/eclipse/xtend/lib/macro/AbstractEnumerationTypeProcessor.java
new file mode 100644
index 0000000..369b209
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/AbstractEnumerationTypeProcessor.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.EnumerationTypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableEnumerationTypeDeclaration;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A convenient base class to process active annotations for enumeration types.
+ */
+@Beta
+public abstract class AbstractEnumerationTypeProcessor implements RegisterGlobalsParticipant<EnumerationTypeDeclaration>, TransformationParticipant<MutableEnumerationTypeDeclaration>, CodeGenerationParticipant<EnumerationTypeDeclaration>, ValidationParticipant<EnumerationTypeDeclaration> {
+
+	public void doRegisterGlobals(List<? extends EnumerationTypeDeclaration> annotatedEnumerationTypes, @Extension RegisterGlobalsContext context) {
+		for (EnumerationTypeDeclaration annotatedEnumerationType : annotatedEnumerationTypes) {
+			doRegisterGlobals(annotatedEnumerationType, context);
+		}
+	}
+	
+	/**
+	 * Called during global symbol collecting.
+	 * 
+	 * @param annotatedEnumerationType a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doRegisterGlobals(EnumerationTypeDeclaration annotatedEnumerationType, @Extension RegisterGlobalsContext context) {}
+	
+	public void doTransform(List<? extends MutableEnumerationTypeDeclaration> annotatedEnumerationTypes, @Extension TransformationContext context) {
+		for (MutableEnumerationTypeDeclaration annotatedEnumerationType : annotatedEnumerationTypes) {
+			doTransform(annotatedEnumerationType, context);
+		}
+	}
+
+	/**
+	 * @param annotatedEnumerationType a mutable enumeration type representation annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doTransform(MutableEnumerationTypeDeclaration annotatedEnumerationType, @Extension TransformationContext context) {}
+
+	public void doGenerateCode(List<? extends EnumerationTypeDeclaration> annotatedSourceElements, @Extension CodeGenerationContext context) {
+		for (EnumerationTypeDeclaration annotatedEnumerationType : annotatedSourceElements) {
+			doGenerateCode(annotatedEnumerationType, context);
+		}
+	}
+	
+	/**
+	 * Called during code generation. 
+	 * 
+	 * @param annotatedEnumerationType a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 * @see CodeGenerationParticipant#doGenerateCode(List, CodeGenerationContext)
+	 */
+	public void doGenerateCode(EnumerationTypeDeclaration annotatedEnumerationType, @Extension CodeGenerationContext context) {}
+	
+	public void doValidate(List<? extends EnumerationTypeDeclaration> annotatedEnumerationTypes, @Extension ValidationContext context) {
+		for (EnumerationTypeDeclaration annotatedEnumerationType : annotatedEnumerationTypes) {
+			doValidate(annotatedEnumerationType, context);
+		}
+	}
+
+	/**
+	 * Invoked by the validator
+	 * @param annotatedEnumerationType the generated enumeration type that should be validated 
+	 * @param context 
+	 * @see #doValidate(List, ValidationContext)
+	 * @since 2.7
+	 */
+	public void doValidate(EnumerationTypeDeclaration annotatedEnumerationType, @Extension ValidationContext context) {}
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/AbstractFieldProcessor.java b/java/org/eclipse/xtend/lib/macro/AbstractFieldProcessor.java
new file mode 100644
index 0000000..d52d0a6
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/AbstractFieldProcessor.java
@@ -0,0 +1,80 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.FieldDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableFieldDeclaration;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A convenient base class to process active annotations for fields.
+ * 
+ * @author Sven Efftinge
+ */
+@Beta
+public abstract class AbstractFieldProcessor implements RegisterGlobalsParticipant<FieldDeclaration>, TransformationParticipant<MutableFieldDeclaration>, CodeGenerationParticipant<FieldDeclaration>, ValidationParticipant<FieldDeclaration>{
+	
+	public void doRegisterGlobals(List<? extends FieldDeclaration> annotatedFields, @Extension RegisterGlobalsContext context) {
+		for (FieldDeclaration annotatedField : annotatedFields) {
+			doRegisterGlobals(annotatedField, context);
+		}
+	}
+	
+	/**
+	 * @param annotatedField a source field annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doRegisterGlobals(FieldDeclaration annotatedField, @Extension RegisterGlobalsContext context) {}
+
+	public void doTransform(List<? extends MutableFieldDeclaration> annotatedfields, @Extension TransformationContext context) {
+		for (MutableFieldDeclaration annotatedField : annotatedfields) {
+			doTransform(annotatedField, context);
+		}
+	}
+
+	/**
+	 * @param annotatedField a mutable field representation annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doTransform(MutableFieldDeclaration annotatedField, @Extension TransformationContext context) {}
+
+	public void doGenerateCode(List<? extends FieldDeclaration> annotatedFields, @Extension CodeGenerationContext context) {
+		for (FieldDeclaration annotatedField : annotatedFields) {
+			doGenerateCode(annotatedField, context);
+		}
+	}
+	
+	/**
+	 * Called during code generation. 
+	 * 
+	 * @param annotatedField a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 * @see CodeGenerationParticipant#doGenerateCode(List, CodeGenerationContext)
+	 */
+	public void doGenerateCode(FieldDeclaration annotatedField, @Extension CodeGenerationContext context) {}
+	
+	public void doValidate(List<? extends FieldDeclaration> annotatedFields, @Extension ValidationContext context) {
+		for (FieldDeclaration annotatedField : annotatedFields) {
+			doValidate(annotatedField, context);
+		}
+	}
+
+	/**
+	 * Invoked by the validator
+	 * @param annotatedField the generated field that should be validated 
+	 * @param context 
+	 * @see #doValidate(List, ValidationContext)
+	 * @since 2.7
+	 */
+	public void doValidate(FieldDeclaration annotatedField, @Extension ValidationContext context) {}
+}
diff --git a/java/org/eclipse/xtend/lib/macro/AbstractInterfaceProcessor.java b/java/org/eclipse/xtend/lib/macro/AbstractInterfaceProcessor.java
new file mode 100644
index 0000000..c1d87e8
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/AbstractInterfaceProcessor.java
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.InterfaceDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableInterfaceDeclaration;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A convenient base class to process active annotations for interfaces.
+ */
+@Beta
+public abstract class AbstractInterfaceProcessor implements RegisterGlobalsParticipant<InterfaceDeclaration>, TransformationParticipant<MutableInterfaceDeclaration>, CodeGenerationParticipant<InterfaceDeclaration>, ValidationParticipant<InterfaceDeclaration> {
+
+	public void doRegisterGlobals(List<? extends InterfaceDeclaration> annotatedInterfaces, @Extension RegisterGlobalsContext context) {
+		for (InterfaceDeclaration annotatedInterface : annotatedInterfaces) {
+			doRegisterGlobals(annotatedInterface, context);
+		}
+	}
+	
+	/**
+	 * Called during global symbol collecting.
+	 * 
+	 * @param annotatedInterface a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doRegisterGlobals(InterfaceDeclaration annotatedInterface, @Extension RegisterGlobalsContext context) {}
+	
+	public void doTransform(List<? extends MutableInterfaceDeclaration> annotatedInterfaces, @Extension TransformationContext context) {
+		for (MutableInterfaceDeclaration annotatedInterface : annotatedInterfaces) {
+			doTransform(annotatedInterface, context);
+		}
+	}
+
+	/**
+	 * @param annotatedInterface a mutable interface representation annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doTransform(MutableInterfaceDeclaration annotatedInterface, @Extension TransformationContext context) {}
+
+	public void doGenerateCode(List<? extends InterfaceDeclaration> annotatedSourceElements, @Extension CodeGenerationContext context) {
+		for (InterfaceDeclaration annotatedInterface : annotatedSourceElements) {
+			doGenerateCode(annotatedInterface, context);
+		}
+	}
+	
+	/**
+	 * Called during code generation. 
+	 * 
+	 * @param annotatedInterface a source element annotated with the annotation this processor is responsible for.
+	 * @param context
+	 * @see CodeGenerationParticipant#doGenerateCode(List, CodeGenerationContext)
+	 */
+	public void doGenerateCode(InterfaceDeclaration annotatedInterface, @Extension CodeGenerationContext context) {}
+	
+	public void doValidate(List<? extends InterfaceDeclaration> annotatedInterfaces, @Extension ValidationContext context) {
+		for (InterfaceDeclaration annotatedInterface : annotatedInterfaces) {
+			doValidate(annotatedInterface, context);
+		}
+	}
+
+	/**
+	 * Invoked by the validator
+	 * @param annotatedInterface the generated interface that should be validated 
+	 * @param context 
+	 * @see #doValidate(List, ValidationContext)
+	 * @since 2.7
+	 */
+	public void doValidate(InterfaceDeclaration annotatedInterface, @Extension ValidationContext context) {}
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/AbstractMethodProcessor.java b/java/org/eclipse/xtend/lib/macro/AbstractMethodProcessor.java
new file mode 100644
index 0000000..4eb82cc
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/AbstractMethodProcessor.java
@@ -0,0 +1,78 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.MethodDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableMethodDeclaration;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A convenient base class to process active annotations for methods.
+ * 
+ * @author Sven Efftinge
+ */
+@Beta
+public abstract class AbstractMethodProcessor implements RegisterGlobalsParticipant<MethodDeclaration>, TransformationParticipant<MutableMethodDeclaration>, CodeGenerationParticipant<MethodDeclaration>, ValidationParticipant<MethodDeclaration> {
+	
+	public void doRegisterGlobals(List<? extends MethodDeclaration> annotatedMethods, RegisterGlobalsContext context) {
+		for (MethodDeclaration annotatedMethod : annotatedMethods) {
+			doRegisterGlobals(annotatedMethod, context);
+		}
+	}
+	
+	/**
+	 * @param annotatedMethod a source method annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doRegisterGlobals(MethodDeclaration annotatedMethod, RegisterGlobalsContext context) {}
+
+	public void doTransform(List<? extends MutableMethodDeclaration> annotatedMethods, @Extension TransformationContext context) {
+		for (MutableMethodDeclaration annotatedMethod : annotatedMethods) {
+			doTransform(annotatedMethod, context);
+		}
+	}
+
+	/**
+	 * @param annotatedMethod a mutable method representation annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doTransform(MutableMethodDeclaration annotatedMethod, @Extension TransformationContext context) {}
+
+	public void doGenerateCode(List<? extends MethodDeclaration> annotatedMethods, @Extension CodeGenerationContext context) {
+		for (MethodDeclaration annotatedMethod : annotatedMethods) {
+			doGenerateCode(annotatedMethod, context);
+		}
+	}
+	
+	/**
+	 * @param annotatedMethod a source method annotated with the annotation this processor is responsible for.
+	 * @param context
+	 */
+	public void doGenerateCode(MethodDeclaration annotatedMethod, @Extension CodeGenerationContext context) {}
+
+	public void doValidate(List<? extends MethodDeclaration> annotatedMethods, @Extension ValidationContext context) {
+		for (MethodDeclaration annotatedMethod : annotatedMethods) {
+			doValidate(annotatedMethod, context);
+		}
+	}
+
+	/**
+	 * Invoked by the validator 
+	 * @param annotatedMethod that generated method that should be validated
+	 * @param context
+	 * @see #doValidate(MethodDeclaration, ValidationContext)
+	 * @since 2.7
+	 */
+	public void doValidate(MethodDeclaration annotatedMethod, ValidationContext context) {
+	}
+}
diff --git a/java/org/eclipse/xtend/lib/macro/Active.java b/java/org/eclipse/xtend/lib/macro/Active.java
new file mode 100644
index 0000000..1bb1df4
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/Active.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * The active annotation is used to register compilation participants
+ * with annotations. 
+ * 
+ *  They allow for enhancing and changing how Xtend code is translated to Java.
+ *  
+ *  There are four compiler phases in which an active annotation can participate, each with different possibilities and constraints:
+ *  <ul>
+ *  	<li>Phase 1: Register Globals {@link RegisterGlobalsParticipant}</li>
+ *  	<li>Phase 2: Transformation {@link TransformationParticipant}</li>
+ *  	<li>Phase 3: Validate Code {@link ValidationParticipant}</li>
+ *  	<li>Phase 4: Generate Code {@link CodeGenerationParticipant}</li>
+ *  </ul>
+ *  
+ *  Note, that in the IDE phase one, two and three are executed in the editor as you type, while phase 4 (code generation) only gets executed when 
+ *  the editor's contents gets saved to disk.
+ * 
+ * @author Sven Efftinge
+ */
+@Beta
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.ANNOTATION_TYPE)
+public @interface Active {
+
+	/**
+	 * @return the processor to call during compilation. should implement one or
+	 *         more of the processor interfaces {@link RegisterGlobalsParticipant},
+	 *         {@link TransformationParticipant}.
+	 */
+	Class<?> value();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/CodeGenerationContext.java b/java/org/eclipse/xtend/lib/macro/CodeGenerationContext.java
new file mode 100644
index 0000000..e824345
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/CodeGenerationContext.java
@@ -0,0 +1,29 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import org.eclipse.xtend.lib.macro.file.FileLocations;
+import org.eclipse.xtend.lib.macro.file.MutableFileSystemSupport;
+import org.eclipse.xtend.lib.macro.services.GlobalTypeLookup;
+import org.eclipse.xtend.lib.macro.services.Tracability;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Provides services for the code generation phase.
+ * 
+ * @see CodeGenerationParticipant
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface CodeGenerationContext extends MutableFileSystemSupport, FileLocations, GlobalTypeLookup, Tracability {
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/CodeGenerationParticipant.java b/java/org/eclipse/xtend/lib/macro/CodeGenerationParticipant.java
new file mode 100644
index 0000000..94fd26a
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/CodeGenerationParticipant.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.NamedElement;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Annotation processors implementing this interface will be called in the code generation phase, which is called 
+ * when Xtend's actual Java code is generated and written to the file system.
+ * 
+ * During this phase it is permitted to write to the file system.
+ * 
+ * @param <T> the type which this processor processes.
+ * 
+ * @author Sven Efftinge
+ * 
+ */
+@Beta
+public interface CodeGenerationParticipant<T extends NamedElement> {
+
+	/**
+	 * Invoked by the compiler during the code generation phase.
+	 * 
+	 * @param annotatedSourceElements the immutable source representation (i.e. the Xtend AST) of the annotated elements
+	 * @param context a {@link TransformationContext} providing useful services.
+	 */
+	void doGenerateCode(List<? extends T> annotatedSourceElements, @Extension CodeGenerationContext context);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/RegisterGlobalsContext.java b/java/org/eclipse/xtend/lib/macro/RegisterGlobalsContext.java
new file mode 100644
index 0000000..2f0aa72
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/RegisterGlobalsContext.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import org.eclipse.xtend.lib.macro.file.FileLocations;
+import org.eclipse.xtend.lib.macro.file.FileSystemSupport;
+import org.eclipse.xtend.lib.macro.services.SourceTypeLookup;
+import org.eclipse.xtend.lib.macro.services.UpstreamTypeLookup;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Provides services to be used during register-globals phase.
+ * 
+ * @author Sven Efftinge
+ * 
+ * @see RegisterGlobalsParticipant
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface RegisterGlobalsContext extends FileSystemSupport, FileLocations, UpstreamTypeLookup, SourceTypeLookup {
+	
+	/**
+	 * Registers and creates an empty Java class with given qualified name
+	 * 
+	 * If the name's namespace part refers to another derived Java type, this type will become a static member of that type.
+	 * 
+	 * For instance, given an 
+	 * <pre>
+	 *  // creates a type 'MyClass' in the package 'my.pack'
+	 *  registerClass("my.pack.MyClass") 
+	 * 
+	 *  // creates a type 'MyInnerClass' as a member of the type 'my.pack.MyClass'
+	 *  registerClass("my.pack.MyClass.MyInnerClass") 
+	 * </pre>
+	 * 
+	 * @param qualifiedName
+	 * @throws IllegalArgumentException if the qualifiedName conflicts with any existing types.
+	 * @exception IllegalArgumentException if the <code>qualifiedName</code> is not a valid qualified name
+	 */
+	void registerClass(String qualifiedName) throws IllegalArgumentException ;
+	
+	/**
+	 * Registers and creates an empty Java interface with given qualified name
+	 * 
+	 * If the name's namespace part refers to another derived Java type, this type will become a static member of that type.
+	 * 
+	 * For instance, given an 
+	 * <pre>
+	 *  // creates a type 'MyClass' in the package 'my.pack'
+	 *  registerClass("my.pack.MyClass") 
+	 * 
+	 *  // creates a type 'MyInnerClass' as a member of the type 'my.pack.MyClass'
+	 *  registerClass("my.pack.MyClass.MyInnerClass") 
+	 * </pre>
+	 * 
+	 * @param qualifiedName
+	 * @throws IllegalArgumentException if the qualifiedName conflicts with any existing types.
+	 * @exception IllegalArgumentException if the <code>qualifiedName</code> is not a valid qualified name
+	 */
+	void registerInterface(String qualifiedName) throws IllegalArgumentException ;
+	
+	/**
+	 * Registers and creates an empty Java annotation type with given qualified name
+	 * 
+	 * If the name's namespace part refers to another derived Java type, this type will become a static member of that type.
+	 * 
+	 * For instance, given an 
+	 * <pre>
+	 *  // creates a type 'MyClass' in the package 'my.pack'
+	 *  registerClass("my.pack.MyClass") 
+	 * 
+	 *  // creates a type 'MyInnerClass' as a member of the type 'my.pack.MyClass'
+	 *  registerClass("my.pack.MyClass.MyInnerClass") 
+	 * </pre>
+	 * 
+	 * @param qualifiedName
+	 * @throws IllegalArgumentException if the qualifiedName conflicts with any existing types.
+	 * @exception IllegalArgumentException if the <code>qualifiedName</code> is not a valid qualified name
+	 */
+	void registerAnnotationType(String qualifiedName) throws IllegalArgumentException ;
+	
+	/**
+	 * Registers and creates an empty Java enumeration type with given qualified name
+	 * 
+	 * If the name's namespace part refers to another derived Java type, this type will become a static member of that type.
+	 * 
+	 * For instance, given an 
+	 * <pre>
+	 *  // creates a type 'MyClass' in the package 'my.pack'
+	 *  registerClass("my.pack.MyClass") 
+	 * 
+	 *  // creates a type 'MyInnerClass' as a member of the type 'my.pack.MyClass'
+	 *  registerClass("my.pack.MyClass.MyInnerClass") 
+	 * </pre>
+	 * 
+	 * @param qualifiedName
+	 * @throws IllegalArgumentException if the qualifiedName conflicts with any existing types.
+	 * @exception IllegalArgumentException if the <code>qualifiedName</code> is not a valid qualified name
+	 */
+	void registerEnumerationType(String qualifiedName) throws IllegalArgumentException ;
+}
diff --git a/java/org/eclipse/xtend/lib/macro/RegisterGlobalsParticipant.java b/java/org/eclipse/xtend/lib/macro/RegisterGlobalsParticipant.java
new file mode 100644
index 0000000..038b888
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/RegisterGlobalsParticipant.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.NamedElement;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Call back to participate in the register-globals phase, where Java types are
+ * collected.
+ * 
+ * Clients should implement this to register and create new Java types.
+ * 
+ * @author Sven Efftinge
+ * 
+ * @param <T>
+ *            the type of the annotated elements
+ */
+@Beta
+public interface RegisterGlobalsParticipant<T extends NamedElement> {
+
+	/**
+	 * Called by the compiler during register-globals phase.
+	 * 
+	 * @param annotatedSourceElements
+	 *            the source elements from the currently processed compilation
+	 *            unit which are annotated with active annotation
+	 * @param context
+	 *            services to register new Java types
+	 * @see RegisterGlobalsContext
+	 */
+	void doRegisterGlobals(List<? extends T> annotatedSourceElements,
+			@Extension RegisterGlobalsContext context);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/TransformationContext.java b/java/org/eclipse/xtend/lib/macro/TransformationContext.java
new file mode 100644
index 0000000..1d92e59
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/TransformationContext.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import org.eclipse.xtend.lib.macro.file.FileLocations;
+import org.eclipse.xtend.lib.macro.file.FileSystemSupport;
+import org.eclipse.xtend.lib.macro.services.AnnotationReferenceProvider;
+import org.eclipse.xtend.lib.macro.services.Associator;
+import org.eclipse.xtend.lib.macro.services.ProblemSupport;
+import org.eclipse.xtend.lib.macro.services.Tracability;
+import org.eclipse.xtend.lib.macro.services.TypeLookup;
+import org.eclipse.xtend.lib.macro.services.TypeReferenceProvider;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Services provided during transformation phase
+ * 
+ * @author Sven Efftinge
+ * 
+ * @see TransformationParticipant
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface TransformationContext extends Tracability, ProblemSupport, TypeReferenceProvider, TypeLookup, FileSystemSupport, FileLocations, AnnotationReferenceProvider, Associator {
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/TransformationParticipant.java b/java/org/eclipse/xtend/lib/macro/TransformationParticipant.java
new file mode 100644
index 0000000..dd5c1c4
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/TransformationParticipant.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.MutableNamedElement;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A callback interface for the transformation phase, in which the Xtend AST is translated
+ * to the Java elements. This callback is invoked after the primary translation by the Xtend compiler is done.
+ * 
+ * It is safe to resolve any {@link TypeReference}s during this phase as long as they are not
+ * inferred from an expression. It's not allowed to resolve any expressions during this phase.
+ * 
+ * @param <T> the type which this processor processes.
+ * 
+ * @author Sven Efftinge
+ */
+@Beta
+public interface TransformationParticipant<T extends MutableNamedElement> {
+	
+	/**
+	 * Invoked by the compiler 
+	 * 
+	 * @param annotatedTargetElements the mutable java representation of the annotated elements
+	 * @param context a {@link TransformationContext} providing useful services.
+	 */
+	void doTransform(List<? extends T> annotatedTargetElements, @Extension TransformationContext context);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/ValidationContext.java b/java/org/eclipse/xtend/lib/macro/ValidationContext.java
new file mode 100644
index 0000000..abc17c7
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/ValidationContext.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import org.eclipse.xtend.lib.macro.file.FileLocations;
+import org.eclipse.xtend.lib.macro.file.FileSystemSupport;
+import org.eclipse.xtend.lib.macro.services.AnnotationReferenceProvider;
+import org.eclipse.xtend.lib.macro.services.ProblemSupport;
+import org.eclipse.xtend.lib.macro.services.Tracability;
+import org.eclipse.xtend.lib.macro.services.TypeLookup;
+import org.eclipse.xtend.lib.macro.services.TypeReferenceProvider;
+
+/**
+ * Services provided during the validation phase
+ *  
+ * @see ValidationParticipant
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface ValidationContext extends Tracability, ProblemSupport, TypeReferenceProvider, TypeLookup, FileSystemSupport, FileLocations, AnnotationReferenceProvider {
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/ValidationParticipant.java b/java/org/eclipse/xtend/lib/macro/ValidationParticipant.java
new file mode 100644
index 0000000..0900a9d
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/ValidationParticipant.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.NamedElement;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+import org.eclipse.xtext.xbase.lib.Extension;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A callback interface for the validation phase. This callback is invoked after all transformations are done.
+ * Inferred {@link TypeReference}s are resolved at that time, so it is safe to inspect them.
+ * 
+ * The AST is read-only in this phase.
+ * 
+ * @param <T> the type which this processor validates.
+ */
+@Beta
+public interface ValidationParticipant<T extends NamedElement> {
+	
+	/**
+	 * Invoked by the validator 
+	 * 
+	 * @param annotatedTargetElements the java representation of the annotated elements
+	 * @param context a {@link ValidationContext} providing useful services.
+	 */
+	void doValidate(List<? extends T> annotatedTargetElements, @Extension ValidationContext context);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/AnnotationReference.java b/java/org/eclipse/xtend/lib/macro/declaration/AnnotationReference.java
new file mode 100644
index 0000000..3da2db3
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/AnnotationReference.java
@@ -0,0 +1,331 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtend.lib.macro.expression.Expression;
+import org.eclipse.xtend.lib.macro.services.Tracability;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents an annotation.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface AnnotationReference extends Element {
+
+	/**
+	 * @return the annotation type
+	 */
+	AnnotationTypeDeclaration getAnnotationTypeDeclaration();
+
+	/**
+	 * Returns the value for the given property.
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned. 
+	 * 
+	 * Depending of the respective annotation type element, the following values are possibly returned:
+	 * <ul>
+	 * 	<li>Short or short[]</li>
+	 * 	<li>Integer or int[]</li>
+	 * 	<li>Long or long[]</li>
+	 * 	<li>Float or float[]</li>
+	 * 	<li>Double or double[]</li>
+	 * 	<li>Boolean or boolean[]</li>
+	 * 	<li>TypeReference or TypeReference[] - for elements of type Class&lt;?&gt;</li>
+	 * 	<li>AnnotationReference or AnnotationReference[] - for elements of an annotation type</li>
+	 * 	<li>EnumerationValueDeclaration or EnumerationValueDeclaration[] - for elements of an enum type</li>
+	 *  <li> <code>null</code> if no value is set and no default value on the original annotation type element is declared.</li>
+	 * </ul>
+	 * 
+	 * @param property the name of the property
+	 * @return the value set on this annotation reference, the default value of the annotation type element or <code>null</code>.
+	 */
+	Object getValue(String property);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	int getIntValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	int[] getIntArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	long getLongValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	long[] getLongArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	short getShortValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	short[] getShortArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	float getFloatValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	float[] getFloatArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	double getDoubleValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	double[] getDoubleArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	byte getByteValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	byte[] getByteArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	boolean getBooleanValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	boolean[] getBooleanArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	char getCharValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	char[] getCharArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	String getStringValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	String[] getStringArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	TypeReference getClassValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	TypeReference[] getClassArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	EnumerationValueDeclaration getEnumValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	EnumerationValueDeclaration[] getEnumArrayValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	AnnotationReference getAnnotationValue(String name);
+	
+	/**
+	 * Returns the value for the given property.
+	 * 
+	 * If no value was specified on the reference the default value of the corresponding {@link AnnotationTypeElementDeclaration}
+	 * will be returned.
+	 * 
+	 * @param name
+	 * @return the value set on this annotation reference or the default value of the annotation type element.
+	 */
+	AnnotationReference[] getAnnotationArrayValue(String name);
+	
+	/**
+	 * Returns the expression for the given annotation property.
+	 * 
+	 * Returns <code>null</code> if no expression is set, or this annotation reference is an external element
+	 * (i.e. {@link Tracability#isExternal(Element)} returns <code>true</code>). 
+	 * 
+	 * @param name
+	 * @return the expression
+	 */
+	Expression getExpression(String name);
+
+	
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTarget.java b/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTarget.java
new file mode 100644
index 0000000..b95c18c
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTarget.java
@@ -0,0 +1,33 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * An element that can be annotated
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface AnnotationTarget extends NamedElement {
+
+	/**
+	 * @return the annotations this element is annotated with
+	 */
+	Iterable<? extends AnnotationReference> getAnnotations();
+
+	/**
+	 * @param annotationType
+	 * @return the annotation reference for the given type, or <code>null</code>
+	 *         if this element is not annotated with the given annotation type
+	 */
+	AnnotationReference findAnnotation(Type annotationType);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTypeDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTypeDeclaration.java
new file mode 100644
index 0000000..84c6c10
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTypeDeclaration.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface AnnotationTypeDeclaration extends TypeDeclaration {
+	
+	/**
+	 * @param name the name of the annotation element
+	 * @return the annotation type element with the given name, declared by this annotation type declaration or <code>null</code> if no such annotation type element exists
+	 */
+	AnnotationTypeElementDeclaration findDeclaredAnnotationTypeElement(String name);
+	
+	/**
+	 * @return the annotation type elements declared by this annotation type declaration
+	 */
+	Iterable<? extends AnnotationTypeElementDeclaration> getDeclaredAnnotationTypeElements();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTypeElementDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTypeElementDeclaration.java
new file mode 100644
index 0000000..f967b92
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/AnnotationTypeElementDeclaration.java
@@ -0,0 +1,40 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtend.lib.macro.expression.Expression;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents an annotation property.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface AnnotationTypeElementDeclaration extends MemberDeclaration {
+
+	/**
+	 * @return the expression describing the default value, or <code>null</code>
+	 *         if there is no default value or this annotation element is
+	 *         declared in an external Java class.
+	 */
+	Expression getDefaultValueExpression();
+
+	/**
+	 * @return the value or <code>null</code> if the is no default value
+	 */
+	Object getDefaultValue();
+
+	/**
+	 * @return the type of this annotation element
+	 */
+	TypeReference getType();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ClassDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/ClassDeclaration.java
new file mode 100644
index 0000000..d0300cd
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ClassDeclaration.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface ClassDeclaration extends TypeDeclaration,
+		TypeParameterDeclarator {
+
+	/**
+	 * @return whether this class is marked <code>final</code>
+	 */
+	boolean isFinal();
+
+	/**
+	 * @return whether this class is marked <code>abstract</code>
+	 */
+	boolean isAbstract();
+
+	/**
+	 * @return whether this class is marked <code>static</code>
+	 */
+	boolean isStatic();
+
+	/**
+	 * @return whether this class is marked <code>strictfp</code>
+	 */
+	boolean isStrictFloatingPoint();
+
+	/**
+	 * @return the super class of this class. If this class declaration
+	 *         represents the source AST this method returns <code>null</code>
+	 *         if no explicit super class is specified.
+	 */
+	TypeReference getExtendedClass();
+
+	/**
+	 * @return the interfaces directly implemented by the class declaration
+	 */
+	Iterable<? extends TypeReference> getImplementedInterfaces();
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/CompilationStrategy.java b/java/org/eclipse/xtend/lib/macro/declaration/CompilationStrategy.java
new file mode 100644
index 0000000..3b1d9da
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/CompilationStrategy.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A compilation strategy can be assigned instead of an expression see {MutableExecutableDeclaration.
+ * It's used to take control over generating Java statements and expressions directly.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface CompilationStrategy {
+	
+	/**
+	 * call back method invoked during compliation
+	 * 
+	 * @param ctx - a compilation context, providing useful services.
+	 * @return the Java code
+	 */
+	CharSequence compile(CompilationContext ctx);
+	
+	/**
+	 * A strategy provided during compilation.
+	 */
+	public interface CompilationContext {
+		
+		/**
+		 * @param typeref the type reference to serialize
+		 * @return the serialized form of the type reference, taking imports into account.
+		 */
+		String toJavaCode(TypeReference typeref);
+		
+	}
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/CompilationUnit.java b/java/org/eclipse/xtend/lib/macro/declaration/CompilationUnit.java
new file mode 100644
index 0000000..f98512b
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/CompilationUnit.java
@@ -0,0 +1,48 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtend.lib.macro.file.Path;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * 
+ * Represents a single Xtend file and the root element of the AST.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface CompilationUnit extends AnnotationTarget {
+
+	/**
+	 * @return the package name of this compilation unit. 
+	 */
+	String getPackageName();
+
+	/**
+	 * @return the JavaDoc comment
+	 */
+	String getDocComment();
+
+	/**
+	 * @return the source view of the <code>TypeDeclaration</code>s directly contained in the compilation unit.
+	 */
+	Iterable<? extends TypeDeclaration> getSourceTypeDeclarations();
+	
+	/**
+	 * Returns the file handle for the given compilation unit.
+	 * 
+	 * @return the file handle for the given compilation unit.
+	 * @see Path
+	 */
+	Path getFilePath();
+	
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ConstructorDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/ConstructorDeclaration.java
new file mode 100644
index 0000000..47a75c2
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ConstructorDeclaration.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface ConstructorDeclaration extends ExecutableDeclaration {
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/Declaration.java b/java/org/eclipse/xtend/lib/macro/declaration/Declaration.java
new file mode 100644
index 0000000..11babae
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/Declaration.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface Declaration extends AnnotationTarget {
+
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/Element.java b/java/org/eclipse/xtend/lib/macro/declaration/Element.java
new file mode 100644
index 0000000..c5a013e
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/Element.java
@@ -0,0 +1,19 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+/**
+ * The super type of all AST elements used in this package
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface Element {
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/EnumerationTypeDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/EnumerationTypeDeclaration.java
new file mode 100644
index 0000000..70e9dd4
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/EnumerationTypeDeclaration.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface EnumerationTypeDeclaration extends TypeDeclaration {
+
+	/**
+	 * @return the values directly declared and contained in the enumeration type declaration
+	 */
+	Iterable<? extends EnumerationValueDeclaration> getDeclaredValues();
+	
+	/**
+	 * @param name of the feature
+	 * @return the declared value with the given name or <code>null</code> of no such value exists.
+	 */
+	EnumerationValueDeclaration findDeclaredValue(String name);
+	
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/EnumerationValueDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/EnumerationValueDeclaration.java
new file mode 100644
index 0000000..059d5c3
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/EnumerationValueDeclaration.java
@@ -0,0 +1,26 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface EnumerationValueDeclaration extends MemberDeclaration {
+	
+	/**
+	 * @return the enumeration type declaring this value
+	 */
+	public EnumerationTypeDeclaration getDeclaringType();
+
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ExecutableDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/ExecutableDeclaration.java
new file mode 100644
index 0000000..1d75444
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ExecutableDeclaration.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtend.lib.macro.expression.Expression;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A common super type for {@link MethodDeclaration} and {@link ConstructorDeclaration}
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface ExecutableDeclaration extends TypeParameterDeclarator {
+	
+	/**
+	 * @return whether this is a varArs declaration.
+	 */
+	boolean isVarArgs();
+	
+	/**
+	 * @return the body, might be null for external elements as well as abstract methods.
+	 */
+	Expression getBody();
+	
+	/**
+	 * @return the declared parameters
+	 */
+	Iterable<? extends ParameterDeclaration> getParameters();
+	
+	/**
+	 * @return the declared exceptions
+	 */
+	Iterable<? extends TypeReference> getExceptions();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/FieldDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/FieldDeclaration.java
new file mode 100644
index 0000000..6bad2f2
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/FieldDeclaration.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtend.lib.macro.expression.Expression;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface FieldDeclaration extends MemberDeclaration {
+	
+	/**
+	 * @return whether this field is declared 'final'
+	 */
+	boolean isFinal();
+
+	/**
+	 * @return whether this field is declared 'static'
+	 */
+	boolean isStatic();
+	
+	/**
+	 * @return whether this field is declared 'transient'
+	 */
+	boolean isTransient();
+	
+	/**
+	 * @return whether this field is declared 'volatile'
+	 */
+	boolean isVolatile();
+	
+	/**
+	 * @return the initializer. <code>null</code> if no initializer is present or this is an external element.
+	 */
+	Expression getInitializer();
+	
+	/**
+	 * @return the type of this expression. <code>null</code> if this is a source field declaration and the type is inferred from the initializer.
+	 */
+	TypeReference getType();
+	
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/InterfaceDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/InterfaceDeclaration.java
new file mode 100644
index 0000000..a4837b1
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/InterfaceDeclaration.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface InterfaceDeclaration extends TypeDeclaration, TypeParameterDeclarator {
+	
+	/**
+	 * @return whether this class is marked <code>strictfp</code>
+	 */
+	boolean isStrictFloatingPoint();
+	
+	/**
+	 * @return the extended interfaces
+	 */
+	Iterable<? extends TypeReference> getExtendedInterfaces();
+	
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MemberDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MemberDeclaration.java
new file mode 100644
index 0000000..886bca9
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MemberDeclaration.java
@@ -0,0 +1,58 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import java.util.Set;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MemberDeclaration extends Declaration {
+	
+	/**
+	 * @return the JavaDoc comment
+	 */
+	String getDocComment();
+
+	/**
+	 * @return the visibility of this member
+	 */
+	Visibility getVisibility();
+	
+	/**
+	 * @return the type declaring this member or <code>null</code> if this is a top level element
+	 */
+	TypeDeclaration getDeclaringType();
+	
+	/**
+	 * @return the modifiers of this Xtend element or an empty set of this is a Java element.
+	 * E.g. <code>public val foo = "foo"</code> has the modifiers {@link Modifier#VAL} and {@link Modifier#PUBLIC} 
+	 * @since 2.7
+	 */
+	Set<Modifier> getModifiers();
+	
+	/**
+	 * Returns {@code true} if this member is marked as deprecated.
+	 * @return {@code true} if this member is marked as deprecated.
+	 * @since 2.7
+	 */
+	boolean isDeprecated();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MethodDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MethodDeclaration.java
new file mode 100644
index 0000000..ab0b283
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MethodDeclaration.java
@@ -0,0 +1,77 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import java.util.Collections;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MethodDeclaration extends ExecutableDeclaration {
+	
+	/**
+	 * @return whether this method is declared <code>final</code>
+	 */
+	boolean isFinal();
+
+	/**
+	 * @return whether this method is declared <code>abstract</code>
+	 */
+	boolean isAbstract();
+
+	/**
+	 * @return whether this method is declared <code>static</code>
+	 */
+	boolean isStatic();
+	
+	/**
+	 * @return whether this method is declared <code>synchronized</code>
+	 */
+	boolean isSynchronized();
+	
+	/**
+	 * @return whether this method is declared <code>default</code>
+	 */
+	boolean isDefault();
+	
+	/**
+	 * @return whether this method is declared <code>strictfp</code>
+	 */
+	boolean isStrictFloatingPoint();
+
+	/**
+	 * @return whether this method is declared <code>native</code>
+	 */
+	boolean isNative();
+	
+	/**
+	 * @return the return type of this method
+	 */
+	TypeReference getReturnType();
+	
+	/**
+	 * @return the overridden or implemented methods
+	 * @since 2.23
+	 */
+	default Iterable<? extends MethodDeclaration> getOverriddenOrImplementedMethods() {
+		return Collections.emptyList();
+	}
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/Modifier.java b/java/org/eclipse/xtend/lib/macro/declaration/Modifier.java
new file mode 100644
index 0000000..1b97231
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/Modifier.java
@@ -0,0 +1,97 @@
+package org.eclipse.xtend.lib.macro.declaration;
+
+/**
+ * A list of all modifiers that are allowed on {@link MemberDeclaration}s in
+ * Xtend source code
+ */
+public enum Modifier {
+	/**
+	 * The public visibility modifier, can be present on
+	 * {@link FieldDeclaration fields}, {@link TypeDeclaration types} and
+	 * {@link ExecutableDeclaration executables}
+	 */
+	PUBLIC,
+	/**
+	 * The private visibility modifier, can be present on
+	 * {@link FieldDeclaration fields}, {@link TypeDeclaration types} and
+	 * {@link ExecutableDeclaration executables}
+	 */
+	PRIVATE,
+	/**
+	 * The protected visibility modifier, can be present on
+	 * {@link FieldDeclaration fields}, {@link TypeDeclaration types} and
+	 * {@link ExecutableDeclaration executables}
+	 */
+	PROTECTED,
+	/**
+	 * The package private visibility modifier, can be present on
+	 * {@link FieldDeclaration fields}, {@link TypeDeclaration types} and
+	 * {@link ExecutableDeclaration executables}
+	 */
+	PACKAGE,
+	/**
+	 * The abstract modifier, can be present on {@link ClassDeclaration classes}
+	 * and {@link MethodDeclaration methods}
+	 */
+	ABSTRACT,
+	/**
+	 * The static modifier, can be present on {@link TypeDeclaration types},
+	 * {@link FieldDeclaration fields} and {@link MethodDeclaration methods}
+	 */
+	STATIC,
+	/**
+	 * The dispatch modifier, can be present on {@link MethodDeclaration
+	 * methods}
+	 */
+	DISPATCH,
+	/**
+	 * The final modifier, can be present on {@link ClassDeclaration classes},
+	 * {@link FieldDeclaration fields} and {@link MethodDeclaration methods}
+	 */
+	FINAL,
+	/**
+	 * The strict floating point modifier, can be present on
+	 * {@link ClassDeclaration classes} and {@link MethodDeclaration methods}
+	 */
+	STRICTFP,
+	/**
+	 * The native modifier, can be present on {@link MethodDeclaration methods}
+	 */
+	NATIVE,
+	/**
+	 * The volatile modifier, can be present on {@link FieldDeclaration fields}
+	 */
+	VOLATILE,
+	/**
+	 * The synchronied modifier, can be present on {@link MethodDeclaration
+	 * methods}
+	 */
+	SYNCHRONIZED,
+	/**
+	 * The transient modifier, can be present on {@link FieldDeclaration fields}
+	 */
+	TRANSIENT,
+	/**
+	 * The val modifier, can be present on {@link FieldDeclaration fields}
+	 */
+	VAL,
+	/**
+	 * The var modifier, can be present on {@link FieldDeclaration fields}
+	 */
+	VAR,
+	/**
+	 * The def modifier, can be present on {@link MethodDeclaration methods}
+	 */
+	DEF,
+	/**
+	 * The override modifier, can be present on {@link MethodDeclaration
+	 * methods}
+	 */
+	OVERRIDE,
+	
+	/**
+	 * The extension modifier, can be present on {@link FieldDeclaration fields}
+	 * @since 2.8
+	 */
+	EXTENSION,
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTarget.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTarget.java
new file mode 100644
index 0000000..cde65c4
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTarget.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableAnnotationTarget extends MutableNamedElement, AnnotationTarget {
+
+	/**
+	 * Annotate this element with the given annotation reference.
+	 * 
+	 * @param annotationReference the annotation reference
+	 * @return a new annotation reference
+	 * @throws IllegalArgumentException if the given annotation reference is <code>null</code>
+	 * @since 2.6
+	 */
+	AnnotationReference addAnnotation(AnnotationReference annotationReference);
+	
+	/**
+	 * Remove the given annotation reference from this element.
+	 * 
+	 * @param annotationReference the annotation reference
+	 * @return <code>true</code> if this element contained the specified annotation
+	 * @since 2.6
+	 */
+	boolean removeAnnotation(AnnotationReference annotationReference);
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTypeDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTypeDeclaration.java
new file mode 100644
index 0000000..7f07a0a
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTypeDeclaration.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtext.xbase.lib.Procedures;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableAnnotationTypeDeclaration extends MutableTypeDeclaration, AnnotationTypeDeclaration {
+
+	MutableAnnotationTypeElementDeclaration findDeclaredAnnotationTypeElement(String name);
+	
+	Iterable<? extends MutableAnnotationTypeElementDeclaration> getDeclaredAnnotationTypeElements();
+	
+	/**
+	 * Adds a new annotation type element with the given name. 
+	 * 
+	 * @param name the name of the annotation type element to be added, must not be <code>null</code>
+	 * @param initializer a callback for further initialization of the created annotation type element, must not be <code>null</code>
+	 * 
+	 * @return the created annotation type element declaration
+	 * @throws UnsupportedOperationException if the underlying type declaration is not capable of containing an annotation type element.
+	 * @exception IllegalArgumentException if the <code>name</code> is not a valid java identifier or the <code>initializer</code> is <code>null</code>
+	 */
+	public MutableAnnotationTypeElementDeclaration addAnnotationTypeElement(String name,
+			Procedures.Procedure1<MutableAnnotationTypeElementDeclaration> initializer);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTypeElementDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTypeElementDeclaration.java
new file mode 100644
index 0000000..371bda4
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableAnnotationTypeElementDeclaration.java
@@ -0,0 +1,75 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2017 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtend.lib.macro.expression.Expression;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents an annotation property.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableAnnotationTypeElementDeclaration extends MutableMemberDeclaration, AnnotationTypeElementDeclaration {
+	
+	/**
+	 * Setting an expression will alter the scope of it accordingly.
+	 * Each expression can only be assigned to one element, if this {@link MutableExecutableDeclaration} has already set 
+	 * another expression or compilation strategy the old one will be detached.
+	 * 
+	 * If the given expression is already assigned to another {@link MutableExecutableDeclaration} or {@link MutableFieldDeclaration}
+	 * it will be automatically detached from it.
+	 * 
+	 * @param value the expression to set as the default value of this annotation property
+	 * 
+	 * @since 2.12
+	 */
+	void setDefaultValueExpression(Expression value);
+	
+	/**
+	 * Sets the given {@link CompilationStrategy} as the default value.
+	 * 
+	 * <b>The given {@link CompilationStrategy} will be executed later during code generation, not immediately.</b>
+	 * 
+	 * If this {@link MutableExecutableDeclaration} has already set another expression or compilation strategy the old one will be detached.
+	 * 
+	 * @param compilationStrategy the compilation strategy, must not be <code>null</code>
+	 * @exception IllegalArgumentException if <code>compilationStrategy</code> is <code>null</code>
+	 * 
+	 * @since 2.12
+	 */
+	void setDefaultValueExpression(CompilationStrategy compilationStrategy);
+	
+	/**
+	 * Sets the given {@link StringConcatenationClient} as the default value.
+	 * 
+	 * <b>The given {@link StringConcatenationClient} will be executed later during code generation, not immediately.</b>
+	 * 
+	 * If this {@link MutableExecutableDeclaration} has already set another expression or compilation strategy the old one will be detached.
+	 * 
+	 * @param compilationTemplate the compilation strategy, must not be <code>null</code>
+	 * @exception IllegalArgumentException if <code>compilationStrategy</code> is <code>null</code>
+	 * 
+	 * @since 2.12
+	 */
+	void setDefaultValueExpression(StringConcatenationClient compilationTemplate);
+	
+	/**
+	 * @param type the type of this annotation property, must be not <code>null</code>
+	 * @exception IllegalArgumentException if the <code>type</code> is <code>null</code>
+	 * 
+	 * @since 2.12
+	 */
+	void setType(TypeReference type);
+	
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableClassDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableClassDeclaration.java
new file mode 100644
index 0000000..96dd1e1
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableClassDeclaration.java
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableClassDeclaration extends MutableTypeParameterDeclarator, MutableTypeDeclaration, ClassDeclaration {
+	
+	/**
+	 * @param isFinal 
+	 */
+	void setFinal(boolean isFinal);
+	
+	/**
+	 * Sets the <code>abstract</code> property
+	 * 
+	 * @param isAbstract 
+	 */
+	void setAbstract(boolean isAbstract);
+	
+	/**
+	 * @param isStatic
+	 */
+	void setStatic(boolean isStatic);
+	
+	/**
+	 * @param isStrictFloatingPoint
+	 */
+	void setStrictFloatingPoint(boolean isStrictFloatingPoint);
+	
+	/**
+	 * @param superclass the type reference to the super type. <code>null</code> resets the extended class to java.lang.Object (the default).
+	 */
+	public void setExtendedClass(TypeReference superclass);
+	
+	/**
+	 * @param superinterfaces the interfaces this class implements
+	 * @exception IllegalArgumentException if <code>superinterfaces</code> is <code>null</code> or contains <code>null</code>
+	 */
+	public void setImplementedInterfaces(Iterable<? extends TypeReference> superinterfaces);
+	
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableConstructorDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableConstructorDeclaration.java
new file mode 100644
index 0000000..2bde019
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableConstructorDeclaration.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * 
+ * A mutable constructor declaration
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableConstructorDeclaration extends MutableExecutableDeclaration, ConstructorDeclaration {
+	
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableDeclaration.java
new file mode 100644
index 0000000..b3cd6d5
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableDeclaration.java
@@ -0,0 +1,27 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * 
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableDeclaration extends MutableAnnotationTarget, Declaration {
+
+	/**
+	 * Indicate that this declaration is being read locally by some synthetically generated member. It effectively suppresses
+	 * unused warnings.
+	 * @since 2.6
+	 */
+	void markAsRead();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableElement.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableElement.java
new file mode 100644
index 0000000..87bb29c
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableElement.java
@@ -0,0 +1,19 @@
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * 
+ * @author Anton Kosyakov
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableElement extends Element {
+
+	/**
+	 * Removes this element from its container and renders it invalid.
+	 * @throws IllegalStateException if this element has already been removed or it was not possible to remove
+	 */
+	public void remove();
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableEnumerationTypeDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableEnumerationTypeDeclaration.java
new file mode 100644
index 0000000..acd379d
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableEnumerationTypeDeclaration.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtext.xbase.lib.Procedures;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableEnumerationTypeDeclaration extends MutableTypeDeclaration, EnumerationTypeDeclaration {
+
+	Iterable<? extends MutableEnumerationValueDeclaration> getDeclaredValues();
+	
+	MutableEnumerationValueDeclaration findDeclaredValue(String name);
+	
+	/**
+	 * Adds a new value with the given name. 
+	 * 
+	 * @param name the name of the field to be added, must be not <code>null</code>
+	 * @param initializer a callback for further initialization of the created value, must be not <code>null</code>
+	 * @return the created value declaration
+	 * @exception IllegalArgumentException if the <code>name</code> is not a valid java identifier or the <code>initializer</code> is <code>null</code>
+	 */
+	MutableEnumerationValueDeclaration addValue(String name, Procedures.Procedure1<MutableEnumerationValueDeclaration> initializer);
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableEnumerationValueDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableEnumerationValueDeclaration.java
new file mode 100644
index 0000000..244103d
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableEnumerationValueDeclaration.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+/**
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableEnumerationValueDeclaration extends MutableMemberDeclaration, EnumerationValueDeclaration {
+	
+	/**
+	 * It is not possible to change visibility of enumeration value.
+	 * @exception UnsupportedOperationException always
+	 */
+	public void setVisibility(Visibility visibility);
+	
+	public MutableEnumerationTypeDeclaration getDeclaringType();
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableExecutableDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableExecutableDeclaration.java
new file mode 100644
index 0000000..cd2febc
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableExecutableDeclaration.java
@@ -0,0 +1,83 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtend.lib.macro.expression.Expression;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableExecutableDeclaration extends MutableTypeParameterDeclarator, ExecutableDeclaration {
+	
+	Iterable<? extends MutableParameterDeclaration> getParameters();
+	
+	/**
+	 * @param isVarArgs whether the last argument is a var arg.
+	 */
+	void setVarArgs(boolean isVarArgs);
+	
+	/**
+	 * Setting an expression will alter the scope of it accordingly.
+	 * Each expression can only be assigned to one element, if this {@link MutableExecutableDeclaration} has already set 
+	 * another expression or compilation strategy the old one will be detached.
+	 * 
+	 * If the given expression is already assigned to another {@link MutableExecutableDeclaration} or {@link MutableFieldDeclaration}
+	 * it will be automatically detached from it.
+	 * 
+	 * @param body the expression to set as the body of this executable
+	 */
+	void setBody(Expression body);
+	
+	/**
+	 * Sets the given {@link CompilationStrategy} as the body.
+	 * 
+	 * <b>The given {@link CompilationStrategy} will be executed later during code generation, not immediately.</b>
+	 * 
+	 * If this {@link MutableExecutableDeclaration} has already set another expression or compilation strategy the old one will be detached.
+	 * 
+	 * @param compilationStrategy the compilation strategy, must not be <code>null</code>
+	 * @exception IllegalArgumentException if <code>compilationStrategy</code> is <code>null</code>
+	 */
+	void setBody(CompilationStrategy compilationStrategy);
+	
+	/**
+	 * Sets the given {@link StringConcatenationClient} as the body.
+	 * 
+	 * <b>The given {@link StringConcatenationClient} will be executed later during code generation, not immediately.</b>
+	 * 
+	 * If this {@link MutableExecutableDeclaration} has already set another expression or compilation strategy the old one will be detached.
+	 * 
+	 * @param compilationTemplate the compilation strategy, must not be <code>null</code>
+	 * @exception IllegalArgumentException if <code>compilationStrategy</code> is <code>null</code>
+	 */
+	void setBody(StringConcatenationClient compilationTemplate);
+	
+	/**
+	 * Sets the declared exceptions.
+	 * 
+	 * @param exceptions the declared exceptions
+	 * @exception IllegalArgumentException if the <code>exceptions</code> is <code>null</code> or contains <code>null</code>
+	 */
+	void setExceptions(TypeReference... exceptions);
+	
+	/**
+	 * Adds a parameter
+	 * 
+	 * @param name the name of the parameter, must be a valid java identifier
+	 * @param type the type of the parameter, must not be <code>null</code>
+	 * @return the created parameter
+	 * @exception IllegalArgumentException if the name is not a valid java identifier or the type is <code>null</code>
+	 */
+	MutableParameterDeclaration addParameter(String name, TypeReference type);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableFieldDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableFieldDeclaration.java
new file mode 100644
index 0000000..4851574
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableFieldDeclaration.java
@@ -0,0 +1,199 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtend.lib.macro.expression.Expression;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * 
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableFieldDeclaration extends MutableMemberDeclaration, FieldDeclaration {
+	
+	/**
+	 * sets the 'final' property
+	 * 
+	 * @param isFinal
+	 */
+	void setFinal(boolean isFinal);
+
+	/**
+	 * sets the 'static' property
+	 * 
+	 * @param isStatic
+	 */
+	void setStatic(boolean isStatic);
+	
+	/**
+	 * sets the 'transient' property
+	 * 
+	 * @param isTransient
+	 */
+	void setTransient(boolean isTransient);
+	
+	/**
+	 * sets the 'volatile' property
+	 * 
+	 * @param isVolatile
+	 */
+	void setVolatile(boolean isVolatile);
+	
+	/**
+	 * sets the 'initializer' expression of this field declaration.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * 
+	 *  If the given expression is assigned to another {@link MutableExecutableDeclaration} or {@link MutableFieldDeclaration}, it
+	 *  will be detached from there as well.
+	 * 
+	 * @param initializer
+	 */
+	void setInitializer(Expression initializer);
+	
+	/**
+	 * sets the 'initializer' expression of this field declaration.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * 
+	 * <b>The given {@link CompilationStrategy} will be executed later during code generation, not immediately.</b>
+	 * 
+	 * @param initializer the compilation strategy, must not be <code>null</code>
+	 * @exception IllegalArgumentException if the <code>initializer</code> is <code>null</code>
+	 */
+	void setInitializer(CompilationStrategy initializer);
+
+	/**
+	 * sets the 'initializer' expression of this field declaration.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * 
+	 * <b>The given {@link StringConcatenationClient} will be executed later during code generation, not immediately.</b>
+	 * 
+	 * @param template the compilation template, must not be <code>null</code>
+	 * @exception IllegalArgumentException if the <code>initializer</code> is <code>null</code>
+	 */
+	void setInitializer(StringConcatenationClient template);
+	
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsLong(long value);
+
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsInt(int value);
+
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsShort(short value);
+
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsByte(byte value);
+
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsDouble(double value);
+
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsFloat(float value);
+
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsChar(char value);
+
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsBoolean(boolean value);
+
+	/**
+	 * sets the 'constant' value of this field.
+	 * Automatically detaches any previously assigned initializers from this field declaration.
+	 * Also marks this field as 'static' and 'final'
+	 * 
+	 * @param value the constant value, must not be <code>null</code>
+	 * @exception IllegalArgumentException if the <code>value</code> is <code>null</code>
+	 * 
+	 * @since 2.8
+	 */
+	void setConstantValueAsString(String value);
+	
+	/**
+	 * Indicate that this field is properly initialized by the given constructor.
+	 * @param constructorDeclaration a constructor that initializes this field
+	 * 
+	 * @since 2.7
+	 */
+	void markAsInitializedBy(ConstructorDeclaration constructorDeclaration);
+	
+	/**
+	 * sets the 'type' of this field declaration
+	 * @param type the type, must be not <code>null</code>
+	 * @exception IllegalArgumentException if the <code>type</code> is <code>null</code>l
+	 */
+	void setType(TypeReference type);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableInterfaceDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableInterfaceDeclaration.java
new file mode 100644
index 0000000..3a89682
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableInterfaceDeclaration.java
@@ -0,0 +1,28 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+/**
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+public interface MutableInterfaceDeclaration extends MutableTypeParameterDeclarator, MutableTypeDeclaration, InterfaceDeclaration {
+
+	/**
+	 * @param isStrictFloatingPoint
+	 */
+	void setStrictFloatingPoint(boolean isStrictFloatingPoint);
+
+	/**
+	 * @param superinterfaces the interfaces this class implements, must be not <code>null</code>
+	 * @exception IllegalArgumentException if <code>superinterfaces</code> is <code>null</code> or contains <code>null</code>
+	 */
+	public void setExtendedInterfaces(Iterable<? extends TypeReference> superinterfaces);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableMemberDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableMemberDeclaration.java
new file mode 100644
index 0000000..8c73856
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableMemberDeclaration.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableMemberDeclaration extends MutableDeclaration, MemberDeclaration {
+	
+	/**
+	 * Sets the JavaDoc comment for this member
+	 * @param docComment
+	 */
+	public void setDocComment(String docComment);
+	
+	/**
+	 * Sets the {@link Visibility} of this member.
+	 * 
+	 * @param visibility
+	 */
+	public void setVisibility(Visibility visibility);
+	
+	/**
+	 * @return the type declaring this member
+	 */
+	public MutableTypeDeclaration getDeclaringType();
+	
+	/**
+	 * Set the deprecated flag of this member. It will add or remove the {@link Deprecated} annotation
+	 * if appropriate.
+	 * @param deprecated {@code true} if this member should be marked as deprecated.
+	 * @since 2.7
+	 */
+	void setDeprecated(boolean deprecated);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableMethodDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableMethodDeclaration.java
new file mode 100644
index 0000000..8dcc3ef
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableMethodDeclaration.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableMethodDeclaration extends MutableExecutableDeclaration, MethodDeclaration {
+	
+	/**
+	 * @param type the return type of this method, must be not <code>null</code>
+	 * @exception IllegalArgumentException if the <code>type</code> is <code>null</code>
+	 */
+	void setReturnType(TypeReference type);
+	
+	/**
+	 * @param isStatic whether this method declaration is <code>static</code>
+	 */
+	void setStatic(boolean isStatic);
+	
+	/**
+	 * @param isFinal whether this method declaration is <code>final</code>
+	 */
+	void setFinal(boolean isFinal);
+	
+	/**
+	 * @param isStrictFloatingPoint whether this method declaration is <code>strictfp</code>
+	 */
+	void setStrictFloatingPoint(boolean isStrictFloatingPoint);
+
+	/**
+	 * @param isNative whether this method declaration is <code>native</code>
+	 */
+	void setNative(boolean isNative);
+
+	/**
+	 * @param isAbstract whether this method declaration is <code>abstract</code>
+	 */
+	void setAbstract(boolean isAbstract);
+	
+	/**
+	 * @param isSynchronized whether this method declaration is <code>synchronized</code>
+	 */
+	void setSynchronized(boolean isSynchronized);
+
+	/**
+	 * @param isDefault whether this method declaration is <code>default</code>
+	 */
+	void setDefault(boolean isDefault);
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableNamedElement.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableNamedElement.java
new file mode 100644
index 0000000..ce067da
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableNamedElement.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableNamedElement extends NamedElement, MutableElement {
+	
+	/**
+	 * @param simpleName the simple name of this element, must not be <code>null</code>
+	 * @exception IllegalArgumentException if the <code>simpleName</code> is <code>null</code>
+	 */
+	void setSimpleName(String simpleName);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableParameterDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableParameterDeclaration.java
new file mode 100644
index 0000000..39ebc98
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableParameterDeclaration.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableParameterDeclaration extends MutableDeclaration, ParameterDeclaration {
+	public MutableExecutableDeclaration getDeclaringExecutable();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeDeclaration.java
new file mode 100644
index 0000000..3251411
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeDeclaration.java
@@ -0,0 +1,106 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import org.eclipse.xtext.xbase.lib.Procedures;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A mutable type declaration.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableTypeDeclaration extends MutableMemberDeclaration, TypeDeclaration {
+	
+	Iterable<? extends MutableMemberDeclaration> getDeclaredMembers();
+	
+	Iterable<? extends MutableMethodDeclaration> getDeclaredMethods();
+	
+	Iterable<? extends MutableFieldDeclaration> getDeclaredFields();
+	
+	Iterable<? extends MutableConstructorDeclaration> getDeclaredConstructors();
+	
+	Iterable<? extends MutableClassDeclaration> getDeclaredClasses();
+	
+	Iterable<? extends MutableInterfaceDeclaration> getDeclaredInterfaces();
+	
+	/**
+	 * @since 2.8
+	 */
+	Iterable<? extends MutableEnumerationTypeDeclaration> getDeclaredEnumerationTypes();
+	
+	/**
+	 * @since 2.8
+	 */
+	Iterable<? extends MutableAnnotationTypeDeclaration> getDeclaredAnnotationTypes();
+	
+	/**
+	 * @since 2.8
+	 */
+	Iterable<? extends MutableTypeDeclaration> getDeclaredTypes();
+	
+	MutableFieldDeclaration findDeclaredField(String name);
+	
+	/**
+	 * @since 2.8
+	 */
+	MutableTypeDeclaration findDeclaredType(String name);
+
+	MutableMethodDeclaration findDeclaredMethod(String name, TypeReference... parameterTypes);
+
+	MutableConstructorDeclaration findDeclaredConstructor(TypeReference... parameterTypes);
+	
+	/**
+	 * Adds a new field with the given name. 
+	 * 
+	 * @param name the name of the field to be added, must be not <code>null</code>
+	 * @param initializer a callback for further initialization of the created field, must be not <code>null</code>
+	 * @return the created field declaration
+	 * @throws UnsupportedOperationException if the underlying type declaration is not capable of containing methods.
+	 * @exception IllegalArgumentException if the <code>name</code> is not a valid java identifier or the <code>initializer</code> is <code>null</code>
+	 */
+	MutableFieldDeclaration addField(String name, Procedures.Procedure1<MutableFieldDeclaration> initializer);
+
+	/**
+	 * Adds a new method with the given name to this type declaration.
+	 * 
+	 * @param name the name of the method
+	 * @param initializer a call back for further initialization of the method
+	 * @return the created method declaration
+	 * @throws UnsupportedOperationException if the underlying type declaration is not capable of containing methods.
+	 * @exception IllegalArgumentException if the <code>name</code> is not a valid java identifier or the <code>initializer</code> is <code>null</code>
+	 */
+	MutableMethodDeclaration addMethod(String name, Procedures.Procedure1<MutableMethodDeclaration> initializer);
+	
+	/**
+	 * Adds a new constructor to this type declaration.
+	 * 
+	 * @param initializer a call back for further initialization of the constructor
+	 * @return the created constructor declaration
+	 * @throws UnsupportedOperationException if the underlying type declaration is not capable of containing constructors.
+	 * @exception IllegalArgumentException if the <code>initializer</code> is <code>null</code>
+	 */
+	MutableConstructorDeclaration addConstructor(Procedures.Procedure1<MutableConstructorDeclaration> initializer);
+	
+	/**
+	 * It is not possible to rename a type. 
+	 * @exception UnsupportedOperationException always
+	 */
+	public void setSimpleName(String simpleName);
+	
+	/**
+	 * It is not possible to remove a type.
+	 * @throws UnsupportedOperationException always
+	 */
+	public void remove();
+	
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeParameterDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeParameterDeclaration.java
new file mode 100644
index 0000000..530a210
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeParameterDeclaration.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableTypeParameterDeclaration extends MutableDeclaration, TypeParameterDeclaration {
+	public MutableTypeParameterDeclarator getTypeParameterDeclarator();
+
+	/**
+	 * @param upperBounds - the upper bounds, must not be <code>null</code>
+	 * @exception IllegalArgumentException if <code>upperBounds</code> is <code>null</code> or contains <code>null</code>
+	 */
+	public void setUpperBounds(Iterable<? extends TypeReference> upperBounds);
+	
+	/**
+	 * This operation is not supported.
+	 * @exception UnsupportedOperationException always 
+	 */
+	public AnnotationReference addAnnotation(AnnotationReference annotationReference);
+	
+	/**
+	 * This operation is not supported.
+	 * @exception UnsupportedOperationException always 
+	 */
+	public boolean removeAnnotation(AnnotationReference annotationReference);
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeParameterDeclarator.java b/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeParameterDeclarator.java
new file mode 100644
index 0000000..e289ece
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/MutableTypeParameterDeclarator.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableTypeParameterDeclarator extends MutableMemberDeclaration, TypeParameterDeclarator {
+	
+	Iterable<? extends MutableTypeParameterDeclaration> getTypeParameters();
+
+	/**
+	 * Creates and adds a new {@link MutableTypeParameterDeclaration} to this
+	 * declarator.
+	 * 
+	 * @param name
+	 *            the name of the type parameter
+	 * @param upperBounds
+	 *            the upperbounds
+	 * @return the created and attached {@link MutableTypeParameterDeclaration}
+	 * @exception IllegalArgumentException
+	 *                <ol><li>if the <code>name</code> is not a valid java identifier</li>
+	 *                <li>if the <code>upperBounds</code> is <code>null</code> or contains <code>null</code></li></ol>
+	 */
+	MutableTypeParameterDeclaration addTypeParameter(String name, TypeReference... upperBounds);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/NamedElement.java b/java/org/eclipse/xtend/lib/macro/declaration/NamedElement.java
new file mode 100644
index 0000000..1d04f2e
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/NamedElement.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface NamedElement extends Element {
+	
+	/**
+	 * @return the name of this element
+	 */
+	String getSimpleName();
+	
+	/**
+	 * @return the currently processed compilation unit this element is contained in, or <code>null</code> if this element is not contained in the currently processed compilation unit.
+	 */
+	CompilationUnit getCompilationUnit();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ParameterDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/ParameterDeclaration.java
new file mode 100644
index 0000000..ae03fca
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ParameterDeclaration.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface ParameterDeclaration extends Declaration {
+	
+	/**
+	 * @return the type of the parameter
+	 */
+	TypeReference getType();
+	
+	/**
+	 * @return the {@link ExecutableDeclaration} this parameter is contained in
+	 */
+	ExecutableDeclaration getDeclaringExecutable();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/PrimitiveType.java b/java/org/eclipse/xtend/lib/macro/declaration/PrimitiveType.java
new file mode 100644
index 0000000..3d924f8
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/PrimitiveType.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface PrimitiveType extends Type {
+	/**
+	 * Returns the kind of primitive type that this object represents.
+	 * 
+	 * @return the kind of primitive type that this object represents
+	 */
+	Kind getKind();
+
+	/**
+	 * An enumeration of the different kinds of primitive types.
+	 */
+	enum Kind {
+		/** The primitive type <tt>boolean</tt> */
+		BOOLEAN,
+		/** The primitive type <tt>byte</tt> */
+		BYTE,
+		/** The primitive type <tt>short</tt> */
+		SHORT,
+		/** The primitive type <tt>int</tt> */
+		INT,
+		/** The primitive type <tt>long</tt> */
+		LONG,
+		/** The primitive type <tt>char</tt> */
+		CHAR,
+		/** The primitive type <tt>float</tt> */
+		FLOAT,
+		/** The primitive type <tt>double</tt> */
+		DOUBLE
+	}
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ResolvedConstructor.java b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedConstructor.java
new file mode 100644
index 0000000..bcd0d24
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedConstructor.java
@@ -0,0 +1,11 @@
+package org.eclipse.xtend.lib.macro.declaration;
+
+/**
+ * {@link ResolvedExecutable Resolved} representation of a
+ * {@link ConstructorDeclaration}.
+ * 
+ * @since 2.7
+ */
+public interface ResolvedConstructor extends ResolvedExecutable {
+	ConstructorDeclaration getDeclaration();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ResolvedExecutable.java b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedExecutable.java
new file mode 100644
index 0000000..a35c34f
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedExecutable.java
@@ -0,0 +1,50 @@
+package org.eclipse.xtend.lib.macro.declaration;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Resolved representation of an {@link ExecutableDeclaration}.
+ * 
+ * Parameter types and declared exceptions are put into the context of a
+ * specific declaring reference, e.g. {@link List#add(Object) List#add(Object)}
+ * becomes <code>List#add(String)</code> in the context of an {@link ArrayList
+ * ArrayList&lt;String&gt;}
+ * 
+ * @since 2.7
+ */
+public interface ResolvedExecutable {
+
+	/**
+	 * @return the executable that is {@link ResolvedExecutable resolved}
+	 */
+	ExecutableDeclaration getDeclaration();
+
+	/**
+	 * @return the {@link ResolvedExecutable resolved} parameters
+	 */
+	Iterable<? extends ResolvedParameter> getResolvedParameters();
+
+	/**
+	 * @return the {@link ResolvedExecutable resolved} exceptions
+	 */
+	Iterable<? extends TypeReference> getResolvedExceptionTypes();
+
+	/**
+	 * Returns the simple signature of this executable. The simple signature of
+	 * <code>List&lt;String&gt;.addAll(int, Collection&lt;E&gt;)</code> is
+	 * <code>addAll(int, Collection&lt;String&gt;)</code>.
+	 * @return the simple, human-readable signature
+	 */
+	String getSimpleSignature();
+
+	/**
+	 * Returns the resolved erased signature of this feature. The resolved representation of
+	 * <code>List&lt;String&gt;.addAll(int,java.util.Collection&lt;E&gt;)</code> is
+	 * <code>addAll(int,Collection)</code>.
+	 * 
+	 * @since 2.14
+	 * @return resolved erasure signature
+	 */
+	String getResolvedErasureSignature();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ResolvedMethod.java b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedMethod.java
new file mode 100644
index 0000000..95fe4fc
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedMethod.java
@@ -0,0 +1,22 @@
+package org.eclipse.xtend.lib.macro.declaration;
+
+/**
+ * {@link ResolvedExecutable Resolved} representation of a
+ * {@link MethodDeclaration}.
+ * 
+ * @since 2.7
+ */
+public interface ResolvedMethod extends ResolvedExecutable {
+
+	MethodDeclaration getDeclaration();
+
+	/**
+	 * @return the {@link ResolvedExecutable resolved} return type
+	 */
+	TypeReference getResolvedReturnType();
+
+	/**
+	 * @return the {@link ResolvedExecutable resolved} type parameters.
+	 */
+	Iterable<? extends ResolvedTypeParameter> getResolvedTypeParameters();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ResolvedParameter.java b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedParameter.java
new file mode 100644
index 0000000..c8b36e7
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedParameter.java
@@ -0,0 +1,28 @@
+package org.eclipse.xtend.lib.macro.declaration;
+
+/**
+ * The resolved representation of a parameter in the context of a type
+ * reference. Consider for instance this method
+ * 
+ * <pre>
+ * interface Foo&lt;T&gt; {
+ *  def void foo(T arg)
+ * }
+ * </pre>
+ * 
+ * In the context of the type reference <code>Foo&lt;String&gt;</code>, the
+ * parameter <code>arg</code> has the type <code>String</code>
+ * 
+ * @since 2.7
+ */
+public interface ResolvedParameter {
+	/**
+	 * @return the declaration being {@link ResolvedParameter resolved}
+	 */
+	ParameterDeclaration getDeclaration();
+
+	/**
+	 * @return the {@link ResolvedParameter resolved} type of the parameter
+	 */
+	TypeReference getResolvedType();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/ResolvedTypeParameter.java b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedTypeParameter.java
new file mode 100644
index 0000000..b0488e7
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/ResolvedTypeParameter.java
@@ -0,0 +1,26 @@
+package org.eclipse.xtend.lib.macro.declaration;
+
+/**
+ * The resolved representation of a type parameter in the context of a type
+ * reference. Consider for instance this method:
+ * 
+ * <pre>
+ * interface Foo&lt;T&gt; {
+ *  def &lt;U extends T&gt; void foo(U arg)
+ * }
+ * </pre>
+ * 
+ * For a <code>Foo&lt;CharSequence&gt;</code>, the type parameter <code>U</code>
+ * would have the upper bound <code>CharSequence</code>
+ */
+public interface ResolvedTypeParameter {
+	/**
+	 * @return the declaration that is {@link ResolvedTypeParameter resolved}
+	 */
+	TypeParameterDeclaration getDeclaration();
+
+	/**
+	 * @return the {@link ResolvedTypeParameter resolved} upper bounds
+	 */
+	Iterable<? extends TypeReference> getResolvedUpperBounds();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/Type.java b/java/org/eclipse/xtend/lib/macro/declaration/Type.java
new file mode 100644
index 0000000..06d85b0
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/Type.java
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface Type extends NamedElement {
+	
+	/**
+	 * Returns the qualified name of this type declaration. Nested types use the '.' char as the
+	 * inner class delimiter.
+	 * @return the qualified name of this type declaration.
+	 */
+	String getQualifiedName();
+	
+	/**
+     * Determines if the type represented by this
+     * <code>Type</code> object is either the same as, or is a supertype of, 
+     * the type represented by the specified <code>Type</code> parameter. 
+     * It returns <code>true</code> if so;
+     * otherwise it returns <code>false</code>. If this <code>Type</code>
+     * object represents a primitive type, this method returns
+     * <code>true</code> if the specified <code>Type</code> parameter is
+     * exactly this <code>Type</code> object; otherwise it returns
+     * <code>false</code>.
+     *
+     * @param otherType the <code>Type</code> object to be checked
+     * @return the <code>boolean</code> value indicating whether objects of the
+     * type <code>cls</code> can be assigned to objects of this type. The method returns false if
+     * the given parameter is <code>null</code>.
+     */
+	boolean isAssignableFrom(Type otherType);
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/TypeDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/TypeDeclaration.java
new file mode 100644
index 0000000..c945963
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/TypeDeclaration.java
@@ -0,0 +1,101 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface TypeDeclaration extends Type, MemberDeclaration {
+
+	/**
+	 * @return the members directly declared and contained in the type declaration
+	 */
+	Iterable<? extends MemberDeclaration> getDeclaredMembers();
+	
+	/**
+	 * @return the methods directly declared and contained in the type declaration
+	 */
+	Iterable<? extends MethodDeclaration> getDeclaredMethods();
+	
+	/**
+	 * @return the fields directly declared and contained in the type declaration
+	 */
+	Iterable<? extends FieldDeclaration> getDeclaredFields();
+	
+	/**
+	 * @return the constructors directly declared and contained in the type declaration
+	 */
+	Iterable<? extends ConstructorDeclaration> getDeclaredConstructors();
+	
+	/**
+	 * @return the classes directly declared and contained in the type declaration
+	 */
+	Iterable<? extends ClassDeclaration> getDeclaredClasses();
+	
+	/**
+	 * @return the interfaces directly declared and contained in the type declaration
+	 */
+	Iterable<? extends InterfaceDeclaration> getDeclaredInterfaces();
+	
+	/**
+	 * @return the enumeration types directly declared and contained in this type declaration
+	 * @since 2.8
+	 */
+	Iterable<? extends EnumerationTypeDeclaration> getDeclaredEnumerationTypes();
+	
+	/**
+	 * @return the annotation types directly declared and contained in this type declaration
+	 * @since 2.8
+	 */
+	Iterable<? extends AnnotationTypeDeclaration> getDeclaredAnnotationTypes();
+	
+	/**
+	 * @return the types directly declared and contained in this type declaration
+	 * @since 2.8
+	 */
+	Iterable<? extends TypeDeclaration> getDeclaredTypes();
+	
+	/**
+	 * @param name of the feature
+	 * @return the declared field with the given name or <code>null</code> of no such field exists.
+	 */
+	FieldDeclaration findDeclaredField(String name);
+	
+	/**
+	 * @param name of the nested type
+	 * @return the declared, nested type with the given name or <code>null</code> of no such type exists.
+	 * @since 2.8
+	 */
+	TypeDeclaration findDeclaredType(String name);
+	
+	/**
+	 * @param name of the method
+	 * @param parameterTypes - the types of the method
+	 * @return the declared method with the given name and the specified parameter types or <code>null</code> if no such method exists.
+	 */
+	MethodDeclaration findDeclaredMethod(String name, TypeReference... parameterTypes);
+	
+	/**
+	 * @param parameterTypes - the parameter types of the constructor
+	 * @return the declared constructor with the exact same parameter types or <code>null</code> if no such constructors exists.
+	 */
+	ConstructorDeclaration findDeclaredConstructor(TypeReference... parameterTypes);
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/TypeParameterDeclaration.java b/java/org/eclipse/xtend/lib/macro/declaration/TypeParameterDeclaration.java
new file mode 100644
index 0000000..6f6137f
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/TypeParameterDeclaration.java
@@ -0,0 +1,37 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface TypeParameterDeclaration extends Type, Declaration {
+	
+	/**
+	 * @return the upper bounds
+	 */
+	Iterable<? extends TypeReference> getUpperBounds();
+	
+	/**
+	 * @return the {@link TypeParameterDeclarator} declaring the type parameter
+	 */
+	TypeParameterDeclarator getTypeParameterDeclarator();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/TypeParameterDeclarator.java b/java/org/eclipse/xtend/lib/macro/declaration/TypeParameterDeclarator.java
new file mode 100644
index 0000000..0d8c111
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/TypeParameterDeclarator.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface TypeParameterDeclarator extends MemberDeclaration {
+	/**
+	 * @return the declared type parameters
+	 */
+	Iterable<? extends TypeParameterDeclaration> getTypeParameters();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/TypeReference.java b/java/org/eclipse/xtend/lib/macro/declaration/TypeReference.java
new file mode 100644
index 0000000..d74d94c
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/TypeReference.java
@@ -0,0 +1,212 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import java.util.List;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface TypeReference extends Element {
+	
+	/**
+	 * Returns a text representation using the simple names of the involved types.
+	 * 
+	 * I.e. for 
+	 * 
+	 *   'java.util.List&lt;? extends java.math.BigDecimal&gt;' this method returns
+	 *   'List&lt;? extends BigDecimal&gt;'
+	 * 
+	 * @return the simple name of this type reference
+	 */
+	String getSimpleName();
+	
+	/**
+	 * returns the text representation using the qualified names of the involved types.
+	 * 
+	 * @return the qualified name of this type reference
+	 */
+	String getName();
+
+	/**
+	 * @return the referenced type.
+	 */
+	Type getType();
+
+	/**
+	 * @return the type arguments
+	 */
+	List<TypeReference> getActualTypeArguments();
+
+	/**
+	 * @return whether this is a wildcard reference
+	 */
+	boolean isWildCard();
+
+	/**
+	 * @return the upper bounds
+	 */
+	TypeReference getUpperBound();
+
+	/**
+	 * @return the lower bounds
+	 */
+	TypeReference getLowerBound();
+
+	/**
+	 * @return whether this is an array
+	 */
+	boolean isArray();
+
+	/**
+	 * @return the component type if this tye reference is an array type reference, <code>null</code> otherwise.
+	 */
+	TypeReference getArrayComponentType();
+
+	/**
+	 * @return whether this is the any type, The any type is the subtype of every reference type and its only instance is <code>null</code>.
+	 */
+	boolean isAnyType();
+
+	/**
+	 * @return whether this is a primitive type (i.e. one of boolean, char, byte, short, int, long, float, double).
+	 */
+	boolean isPrimitive();
+
+	/**
+	 * @return the corresponding wrapper <code>TypeReference</code> if this type references is a primitive type. Returns <code>this</code> otherwise.
+	 */
+	TypeReference getWrapperIfPrimitive();
+
+	/**
+	 * Checks whether this type is one of the wrapper types for the primitive value types.
+	 * 
+	 * @return wither this is one of the wrapper types for the primitive value types.
+	 */
+	boolean isWrapper();
+
+	/**
+	 * @return the corresponding primitive <code>TypeReference</code> if this type references is a wrapper type. Returns <code>this</code> otherwise.
+	 */
+	TypeReference getPrimitiveIfWrapper();
+
+	/**
+	 * @return whether this type is 'void' (doesn't include 'java.lang.Void')
+	 */
+	boolean isVoid();
+
+	/**
+	 * Determines if the specified <code>TypeReference</code> parameter can be assigned to this 
+	 * <code>TypeReference</code>. It returns <code>true</code> if so;
+	 * otherwise it returns <code>false</code>.
+	 * 
+	 * @param typeReference
+	 * @return returns <code>true</code> is the specified type reference parameter can be assigned to this type reference.
+	 */
+	boolean isAssignableFrom(TypeReference typeReference);
+	
+	/**
+	 * Whether the given type reference is an inferred reference. 
+	 * That is the type is to be computed from some Expression, e.g. a method body or a field initializer.
+	 * 
+	 * Inferred type references can only be used as handles, and will through an {@link UnsupportedOperationException} on every method other than
+	 * 
+	 * <ul>
+	 *  <li>{@link #toString()}</li>
+	 *  <li>{@link #equals(Object)}</li>
+	 *  <li>{@link #hashCode()}</li>
+	 * </ul>
+	 * 
+	 * @return whether this type reference is an inferred type reference.
+	 */
+	boolean isInferred();
+	
+	/**
+	 * @return the supertypes (superclass and interfaces) directly implemented/extended by this type
+	 * @since 2.7
+	 */
+	Iterable<? extends TypeReference> getDeclaredSuperTypes();
+	
+	/**
+	 * @return the resolved methods directly declared by this type
+	 * @since 2.7
+	 */
+	Iterable<? extends ResolvedMethod> getDeclaredResolvedMethods();
+	
+	/**
+	 * @return the resolved constructors directly declared by this type
+	 * @since 2.7
+	 */
+	Iterable<? extends ResolvedConstructor> getDeclaredResolvedConstructors();
+	
+	/**
+	 * Computes all the resolved methods that can be called on this type, either because they were
+	 * declared directly by the type or by one of its supertypes.
+	 * For overloaded methods, the one declared closest to this type is used. E.g. when
+	 * called on the class <code>C</code> in this hierarchy:
+	 * 
+	 * <pre>
+	 * class A {
+	 *  def CharSequence foo()
+	 * }
+	 * class B extends A {
+	 *  override String foo()
+	 * }
+	 * class C extends B {}
+	 * <pre>
+	 * 
+	 * B#foo() would be contained, but not A#foo().
+	 * 
+	 * @return the resolved methods declared in this type and its supertypes. 
+	 * @since 2.7
+	 */
+	Iterable<? extends ResolvedMethod> getAllResolvedMethods();
+	
+//	/**
+//	 * Checks whether this {@link TypeReference} refers to the same type as the other one.
+//	 * @param other the type to test equivalence against
+//	 * @return true if this type and the given type are equivalent
+//	 * @since 2.7
+//	 */
+//	boolean is(TypeReference other);
+
+	/**
+	 * Checks whether this type reference equals the given type reference.
+	 * 
+	 * For type References where {@link #isInferred()} is <code>true</code>, the implementation is based on
+	 * identity of the underlying AST.
+	 *  
+	 * @param obj
+	 * @return whether the given obj is the same instance
+	 * @since 2.7
+	 */
+	public boolean equals(Object obj);
+	
+	/**
+	 * Value-based for all {@link TypeReference}s where {@link #isInferred()} is <code>false</code>.
+	 * @since 2.7
+	 */
+	public int hashCode();
+	
+	/**
+	 * A string representation for this type reference. If this reference is resolved, it will
+	 * return the simple name of this reference. Otherwise a technical information about the inferred type
+	 * reference.
+	 * 
+	 * @return a string representation
+	 * 
+	 * @since 2.8
+	 */
+	@Override
+	public String toString();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/Visibility.java b/java/org/eclipse/xtend/lib/macro/declaration/Visibility.java
new file mode 100644
index 0000000..5fa2632
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/Visibility.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ */
+@Beta
+public enum Visibility {
+	/**
+	 * default package-private
+	 */
+	DEFAULT, 
+	
+	/**
+	 * private visibility
+	 */
+	PRIVATE, 
+	
+	/**
+	 * protected visibility
+	 */
+	PROTECTED, 
+	
+	/**
+	 * public visibility
+	 */
+	PUBLIC
+}
diff --git a/java/org/eclipse/xtend/lib/macro/declaration/VoidType.java b/java/org/eclipse/xtend/lib/macro/declaration/VoidType.java
new file mode 100644
index 0000000..c2cffb9
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/declaration/VoidType.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+
+package org.eclipse.xtend.lib.macro.declaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface VoidType extends Type {
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/expression/Expression.java b/java/org/eclipse/xtend/lib/macro/expression/Expression.java
new file mode 100644
index 0000000..99f3522
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/expression/Expression.java
@@ -0,0 +1,22 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.expression;
+
+import org.eclipse.xtend.lib.macro.declaration.Element;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface Expression extends Element {
+	
+}
diff --git a/java/org/eclipse/xtend/lib/macro/file/FileLocations.java b/java/org/eclipse/xtend/lib/macro/file/FileLocations.java
new file mode 100644
index 0000000..4d50519
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/file/FileLocations.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.file;
+
+import java.util.Set;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A service which provides information about the location of a path.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface FileLocations {
+
+	/**
+	 * Returns the source folder the given handle is contained in or
+	 *         <code>null</code> if the given {@link Path} is not
+	 *         located in a source folder.
+	 *         
+	 * @param path an absolute path to a resource
+	 * @return the source folder the given handle is contained in or
+	 *         <code>null</code> if the given {@link Path} is not
+	 *         located in a source folder.
+	 * @see Path
+	 */
+	Path getSourceFolder(Path path);
+
+	/**
+	 * Returns the target folder for the given source folder or <code>null</code> if the given
+	 * folder is not a source folder or doesn't have a configured target folder.
+	 * 
+	 * @param sourceFolder the source folder to find the configured target folder for.
+	 * @return the target folder
+	 */
+	Path getTargetFolder(Path sourceFolder);
+
+	
+	/**
+	 * Returns the project root for the given resource handle.
+	 * 
+	 * @param path an absolute path 
+	 * @return the project's root
+	 */
+	Path getProjectFolder(Path path);
+	
+	/**
+	 * @param path an absolute path
+	 * @return the source folders of the project the given path is contained in
+	 * @since 2.8
+	 */
+	Set<Path> getProjectSourceFolders(Path path);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/file/FileSystemSupport.java b/java/org/eclipse/xtend/lib/macro/file/FileSystemSupport.java
new file mode 100644
index 0000000..70af18e
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/file/FileSystemSupport.java
@@ -0,0 +1,104 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.file;
+
+import java.io.InputStream;
+import java.net.URI;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * 
+ * Support for accessing the file system.
+ * 
+ * @author Anton Kosyakov
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface FileSystemSupport {
+
+	/**
+	 * @param path
+	 * @return the children of the folder the given path points to; 
+	 * 		   empty iterable if the path points to a non existent file or folder
+	 * @exception IllegalArgumentException if it is not possible to get children of a given path for some reason 
+	 */
+	Iterable<? extends Path> getChildren(Path path);
+	
+	/**
+	 * @param path the path
+	 * @return whether the given path points to an existent file.
+	 */
+	boolean exists(Path path);
+	
+	/**
+	 * @param path
+	 * @return whether the given path points to an existent folder
+	 */
+	boolean isFolder(Path path);
+	
+	/**
+	 * @param path
+	 * @return whether the given path points to an existent file
+	 */
+	boolean isFile(Path path);
+	
+	/**
+	 * @param path
+	 * @return  A <code>long</code> value representing the time the file was
+     *          last modified, measured in milliseconds since the epoch
+     *          (00:00:00 GMT, January 1, 1970), or <code>0L</code> if the
+     *          file does not exist.
+	 */
+	long getLastModification(Path path);
+	
+	/**
+	 * Returns the name of a charset to be used when decoding the contents of this 
+	 * file into characters. 
+	 * 
+	 * @param path the path
+	 * @return the name of a charset
+	 * @exception IllegalArgumentException if it is not possible to get charset of a given path for some reason
+	 */
+	String getCharset(Path path);
+
+	/**
+	 * Returns the contents of this file as a char sequence.
+	 * 
+	 * @param path the path
+	 * @return an input stream containing the contents of the file
+	 * @exception IllegalArgumentException if the path points to a non existent file
+	 */
+	CharSequence getContents(Path path);
+	
+	/**
+	 * Returns an open input stream on the contents of this file.
+	 * 
+	 * @param path the path
+	 * @return an input stream containing the contents of the file
+	 * @exception IllegalArgumentException if the path points to a non existent file
+	 */
+	InputStream getContentsAsStream(Path path);
+	
+	/**
+	 * <p>
+	 * Returns the URI representing the given path.
+	 * </p>
+	 * 
+	 * <p>
+	 * <b>Warning</b>: Don't use this method to get write access.
+	 * </p>
+	 * 
+	 * @param path
+	 *            the path
+	 * @return the URI representing the given path or <code>null</code> if the path points to a non existent file or a folder.
+	 */
+	URI toURI(Path path);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/file/MutableFileSystemSupport.java b/java/org/eclipse/xtend/lib/macro/file/MutableFileSystemSupport.java
new file mode 100644
index 0000000..f997528
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/file/MutableFileSystemSupport.java
@@ -0,0 +1,73 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.file;
+
+import java.io.InputStream;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Allows modifications on the file system.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface MutableFileSystemSupport extends FileSystemSupport {
+
+	/**
+	 * Writes the given contents to the given path.
+	 * It will create the file if it doesn't exist, and create folders for all parents if they don't exist.
+	 * 
+	 * Implementors may decide to perform this method asynchronously. Clients should not rely on invocation timing. 
+	 * 
+	 * @param path the path to write the contents to
+	 * @param contents the contents of the file
+	 */
+	void setContents(Path path, CharSequence contents);
+	
+	/**
+	 * Sets the contents of this file to the bytes in the given input stream.
+	 * The stream will be closed after the operation has finished.
+	 * 
+	 * Implementors may decide to perform this method asynchronously. Clients should not rely on invocation timing.
+	 *
+	 * @param path the path to the file
+	 * @param source an input stream containing the new contents of the file
+	 */
+	void setContentsAsStream(Path path, InputStream source);
+	
+	/**
+	 * <p>
+	 * This method will be removed in future versions.
+	 * Methods {@link #setContents} and {@link #setContentsAsStream(Path, InputStream)} create folders for all parents if they don't exist.
+	 * </p>
+	 * 
+	 * Creates a directory for the given path and all its parents if necessary.
+	 * 
+	 * Implementors may decide to perform this method asynchronously. Clients should not rely on invocation timing.
+	 * 
+	 * @param path the path to the file
+	 * @since 2.7
+	 */
+	@Deprecated
+	void mkdir(Path path);
+	
+	/**
+	 * Deletes the file or folder the given path points to. 
+	 * If path points to a folder this method will also delete all its contents.
+	 * 
+	 * Implementors may decide to perform this method asynchronously. Clients should not rely on invocation timing.
+	 * 
+	 * @param path
+	 * @since 2.7
+	 */
+	void delete(Path path);
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/file/Path.java b/java/org/eclipse/xtend/lib/macro/file/Path.java
new file mode 100644
index 0000000..4b7afa0
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/file/Path.java
@@ -0,0 +1,313 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.file;
+
+import static com.google.common.collect.Lists.newArrayList;
+
+import java.util.List;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Predicate;
+import com.google.common.base.Splitter;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+
+/**
+ * A path points to some file or folder within a {@link FileSystemSupport} and {@link MutableFileSystemSupport}.
+ * 
+ * A path either starts with a slash which denotes an absolute path or a segment which denotes a relative path.
+ * Note that this is an abstraction over different 'real' file systems and doesn't understand platform specific things like, e.g. 
+ * "c:/" on windows.
+ * 
+ * The path segment separator is '/'.
+ * 
+ * @author Sven Efftinge
+ */
+@Beta
+public final class Path {
+	
+	/**
+	 * the segment separator used.
+	 */
+	public static final char SEGMENT_SEPARATOR = '/';
+	private final static Splitter splitter = Splitter.on(SEGMENT_SEPARATOR );
+	/**
+	 * the root path
+	 */
+	public static final Path ROOT = new Path("/");
+	
+	private final ImmutableList<String> segments;
+	private final boolean absolute;
+
+	
+	/**
+	 * Constructs a new Path object from a given string.
+	 * 
+	 * the used file separator is '/' and a leading one indicates an absolute path.
+	 * 
+	 * @param pathAsString
+	 */
+	public Path(String pathAsString) {
+		if (pathAsString == null)
+			throw new NullPointerException();
+		if (pathAsString.trim().length() == 0)
+			throw new IllegalArgumentException("empty path");
+		pathAsString = pathAsString.replace('\\', SEGMENT_SEPARATOR ); //replace windows separators
+		Iterable<String> iterable = splitter.split(pathAsString);
+		
+		// if the first element is empty it has a leading separator;
+		this.absolute = iterable.iterator().next().length() == 0;
+		
+		Iterable<String> withoutEmptySegments = Iterables.filter(iterable, new Predicate<String>() {
+
+			public boolean apply(String input) {
+				return input != null && input.trim().length() > 0;
+			}
+		});
+		segments = ImmutableList.copyOf(normalize(withoutEmptySegments));
+	}
+	
+	private Path(List<String> segments, boolean isAbsolute) {
+		this.segments = ImmutableList.copyOf(normalize(segments));
+		this.absolute = isAbsolute;
+	}
+	
+	private Iterable<String> normalize(Iterable<String> segments) {
+		List<String> result = newArrayList();
+		boolean canRemoveSegment = false;
+		for (String seg : segments) {
+			String string = seg.trim();
+			if (canRemoveSegment && string.equals("..")) {
+				result.remove(result.size()-1);
+				canRemoveSegment = !result.isEmpty() && !result.get(0).equals("..");
+			} else if (string.equals(".")) {
+				// do nothing
+			} else {
+				result.add(string);
+				canRemoveSegment = !string.equals("..");
+			}
+		}
+		return result;
+	}
+
+	/**
+	 * @return whether this is an absolute path
+	 */
+	public boolean isAbsolute() {
+		return absolute;
+	}
+	
+	/**
+	 * @return the segments
+	 */
+	public List<String> getSegments() {
+		return segments;
+	}
+
+	/**
+	 * @return the trailing segment, i.e. the simple name of the underlying element.
+	 */
+	public String getLastSegment() {
+		return segments.isEmpty() ? null : segments.get(segments.size()-1);
+	}
+	
+	/**
+	 * Appends the given suffix to this path.
+	 * 
+	 * @param suffix the suffix to append to this path
+	 * @return a new Path with the given suffix appended to this path's segments.
+	 */
+	public Path append(String suffix) {
+		return new Path(toString()+ SEGMENT_SEPARATOR + suffix);
+	}
+	
+	/**
+	 * Returns the parent of this path or null if this path is the root path.
+	 * 
+	 * @return the parent of this path or null if this path is the root path.
+	 */
+	public Path getParent() {
+		if (!isAbsolute())
+			throw new IllegalStateException("path is not absolute: " + toString());
+		if (segments.isEmpty())
+			return null;
+		return new Path(segments.subList(0, segments.size()-1), true);
+	}
+	
+	/**
+	 * @return the file extension or <code>null</code> if this path's last segment doesn't have a file extension.
+	 */
+	public String getFileExtension() {
+		String lastSegment = getLastSegment();
+		int idx = lastSegment.lastIndexOf('.');
+		if (idx == -1) {
+			return null;
+		}
+		return lastSegment.substring(idx+1);
+	}
+	
+	/**
+	 * @param relativePath
+	 * @return the absolute path
+	 */
+	public Path getAbsolutePath(String relativePath) {
+		Path other = new Path(relativePath);
+		return getAbsolutePath(other);
+	}
+
+	/**
+	 * @param relativePath
+	 * @return the absolute path
+	 */
+	public Path getAbsolutePath(Path relativePath) {
+		if (relativePath.isAbsolute()) {
+			throw new IllegalArgumentException("The given path '"+relativePath+"' is not relative.");
+		}
+		List<String> result = newArrayList(getSegments());
+		for (String segment : relativePath.getSegments()) {
+			if (segment.equals("..")) {
+				// go up
+				result.remove(result.size()-1);
+			} else if (segment.equals(".")) {
+				// stay in current directory
+			} else {
+				result.add(segment);
+			}
+		}
+		return new Path(result, true);
+	}
+
+	/**
+	 * See {@link #relativize(Path)}
+	 * 
+	 * @param other a string representing a path
+	 * @return the resulting relative path or null if neither of the given paths is a prefix of the other
+	 */
+	public Path relativize(String other) {
+		return relativize(new Path(other));
+	}
+	
+	/**
+    * Constructs a relative path between this path and a given path.
+    *
+    * <p> Relativization is the inverse of {@link #getAbsolutePath(Path) resolution}.
+    * This method attempts to construct a {@link #isAbsolute relative} path
+    * that when {@link #getAbsolutePath(Path) resolved} against this path, yields a
+    * path that locates the same file as the given path. For example, on UNIX,
+    * if this path is {@code "/a/b"} and the given path is {@code "/a/b/c/d"}
+    * then the resulting relative path would be {@code "c/d"}. 
+ 	* Both paths must be absolute and and either this path or the given path must be a
+ 	* {@link #startsWith(Path) prefix} of the other.
+    *
+    * @param   other
+    *          the path to relativize against this path
+    *
+    * @return  the resulting relative path or null if neither of the given paths is a prefix of the other
+    *
+    * @throws  IllegalArgumentException
+    *          if this path and {@code other} are not both absolute or relative
+    */
+	public Path relativize(Path other) {
+		if (other.isAbsolute() != isAbsolute())
+			throw new IllegalArgumentException("This path and the given path are not both absolute or both relative: " + toString() + " | " + other.toString());
+		if (startsWith(other)) {
+			return internalRelativize(this, other);
+		} else if (other.startsWith(this)) {
+			return internalRelativize(other, this);
+		}
+		return null;
+	}
+	
+	private Path internalRelativize(Path path, Path prefix) {
+		return new Path(path.getSegments().subList(prefix.getSegments().size(), path.getSegments().size()), false);
+	}
+
+	/**
+	 * Returns whether this path starts with the same segments and
+	 * has the same {@link #isAbsolute()} value.
+	 * 
+	 * @param other the path, which might be a prefix of this path
+	 * @return whether the given path is a prefix of this path
+	 */
+	public boolean startsWith(Path other) {
+		if (isAbsolute() != other.isAbsolute())
+			return false;
+		List<String> otherSegments = other.getSegments();
+		List<String> thisSegments = getSegments();
+		int otherSegmentSize = otherSegments.size();
+		int thisSegmentSize = thisSegments.size();
+		if (otherSegmentSize > thisSegmentSize) {
+			return false;
+		}
+		for (int i = 0; i < otherSegmentSize; i++) {
+			String otherSeg = otherSegments.get(i);
+			String thisSeg = thisSegments.get(i);
+			if (!otherSeg.equals(thisSeg))
+				return false;
+		}
+		return true;
+	}
+
+	/* (non-Javadoc)
+	 * @see java.lang.Object#hashCode()
+	 */
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result + (absolute ? 1231 : 1237);
+		result = prime * result
+				+ ((segments == null) ? 0 : segments.hashCode());
+		return result;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#equals(java.lang.Object)
+	 */
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		Path other = (Path) obj;
+		if (absolute != other.absolute)
+			return false;
+		if (segments == null) {
+			if (other.segments != null)
+				return false;
+		} else if (!segments.equals(other.segments))
+			return false;
+		return true;
+	}
+	
+	/* (non-Javadoc)
+	 * @see java.lang.Object#toString()
+	 */
+	@Override
+	public String toString() {
+		StringBuilder result = new StringBuilder();
+		if (isAbsolute()) {
+			result.append(SEGMENT_SEPARATOR);
+		}
+		int size = segments.size();
+		for (int i = 0; i < size; i++) {
+			String segment = segments.get(i);
+			result.append(segment);
+			if (i < size-1) {
+				result.append(SEGMENT_SEPARATOR);
+			}
+		}
+		return result.toString();
+	}
+	
+
+}
diff --git a/java/org/eclipse/xtend/lib/macro/services/AnnotationReferenceBuildContext.java b/java/org/eclipse/xtend/lib/macro/services/AnnotationReferenceBuildContext.java
new file mode 100644
index 0000000..26f6042
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/AnnotationReferenceBuildContext.java
@@ -0,0 +1,187 @@
+/*******************************************************************************
+ * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
+import org.eclipse.xtend.lib.macro.declaration.EnumerationValueDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Services provided during an annotation reference initialization.  
+ * 
+ * @author Anton Kosyakov
+ * @since 2.6
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface AnnotationReferenceBuildContext {
+
+	/**
+	 * Sets the annotation property of the given name
+	 * 
+	 * Depending of the respective annotation type element, the following values
+	 * are permitted:
+	 * <ul>
+	 * <li>Short or short[]</li>
+	 * <li>Integer or int[]</li>
+	 * <li>Long or long[]</li>
+	 * <li>Float or float[]</li>
+	 * <li>Double or double[]</li>
+	 * <li>Boolean or boolean[]</li>
+	 * <li>TypeReference or TypeReference[] - for elements of type Class&lt;?&gt;</li>
+	 * <li>AnnotationReference or AnnotationReference[] - for elements of an annotation type</li>
+	 * <li>EnumerationValueDeclaration or EnumerationValueDeclaration[] - for elements of an enum type</li>
+	 * <li>Expression - for any element type that matches the given expression's type</li>
+	 * <li>null - will remove any existing value for the given element name</li>
+	 * </ul>
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value an annotation value or null if the annotation value should be removed.
+	 * @exception IllegalArgumentException
+	 *                if the value is not valid. See explanation above or if the
+	 *                name does not identify a method in the referenced
+	 *                annotation type.
+	 */
+	void set(String name, Object value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setIntValue(String name, int... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setLongValue(String name, long... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setShortValue(String name, short... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setDoubleValue(String name, double... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setFloatValue(String name, float... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setByteValue(String name, byte... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setBooleanValue(String name, boolean... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setCharValue(String name, char... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array without any null entries
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setStringValue(String name, String... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array without any null entries
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setClassValue(String name, TypeReference... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array without any null entries
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setEnumValue(String name, EnumerationValueDeclaration... value);
+
+	/**
+	 * Sets the given value for the given annotation element name.
+	 * 
+	 * @param name a valid name of a property of the annotation type.
+	 * @param value a non-null value array without any null entries
+	 * @throws IllegalArgumentException
+	 *             if the name does not point to a valid member of the
+	 *             referenced annotation type.
+	 */
+	void setAnnotationValue(String name, AnnotationReference... value);
+	
+}
diff --git a/java/org/eclipse/xtend/lib/macro/services/AnnotationReferenceProvider.java b/java/org/eclipse/xtend/lib/macro/services/AnnotationReferenceProvider.java
new file mode 100644
index 0000000..ff6d29e
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/AnnotationReferenceProvider.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import org.eclipse.xtend.lib.macro.declaration.AnnotationReference;
+import org.eclipse.xtend.lib.macro.declaration.Type;
+import org.eclipse.xtext.xbase.lib.Procedures;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Creates {@link AnnotationReference} instances.
+ * 
+ * @author Anton Kosyakov
+ * @since 2.6
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface AnnotationReferenceProvider {
+	
+	/**
+	 * Creates a new annotation reference for the given name.
+	 *  
+	 * @param annotationTypeName the name of the annotation type to point to, must be a valid java identifier
+	 * @return a {@link AnnotationReference} pointing to the type with the give name, or <code>null</code> if no such annotation type could be found.
+	 * @throws IllegalArgumentException if the <code>name</code> is not a valid java identifier
+	 */
+	AnnotationReference newAnnotationReference(String annotationTypeName);
+
+	/**
+	 * Creates a new annotation reference for the given type declaration.
+	 *  
+	 * @param annotationTypeDelcaration the annotation type to point to, must not be <code>null</code>.
+	 * @return a {@link AnnotationReference} pointing to the given type, or <code>null</code> if the given type is not an annotation type.
+	 * @throws IllegalArgumentException if the given type declaration is null
+	 */
+	AnnotationReference newAnnotationReference(Type annotationTypeDelcaration);
+
+	/**
+	 * Creates a new annotation reference for the given {@link Class}.
+	 *  
+	 * @param annotationClass the {@link Class} to point to, must not be <code>null</code>.
+	 * @return a {@link AnnotationReference} pointing to the given type, or <code>null</code> if the given type is not on the class path of the compiled project or an annotation type.
+	 * @throws IllegalArgumentException if the given {@link Class} is null
+	 */
+	AnnotationReference newAnnotationReference(Class<?> annotationClass);
+	
+	/**
+	 * Create a new annotation reference base on the given annotation reference.
+	 * 
+	 * @param annotationReference an annotation reference which is used as a base for a new annotation reference, must not be <code>null</code> or detached.  
+	 * @return a {@link AnnotationReference} constructed based on the given annotation reference, can be <code>null</code>
+	 * @throws IllegalArgumentException if the given annotation reference is <code>null</code> or detached
+	 */
+	AnnotationReference newAnnotationReference(AnnotationReference annotationReference);
+	
+	/**
+	 * Creates a new annotation reference for the given name.
+	 *  
+	 * @param annotationTypeName the name of the annotation type to point to
+	 * @param initializer a callback for further initialization of the create annotation reference, must not be <code>null</code>.
+	 * @return a {@link AnnotationReference} pointing to the type with the give name, or <code>null</code> if no such annotation type could be found.
+	 * @throws IllegalArgumentException if the <code>name</code> is not a valid java identifier or the <code>initializer</code> is <code>null</code>
+	 */
+	AnnotationReference newAnnotationReference(String annotationTypeName, Procedures.Procedure1<AnnotationReferenceBuildContext> initializer);
+	
+	/**
+	 * Creates a new annotation reference for the given type declaration.
+	 *  
+	 * @param annotationTypeDelcaration the annotation type to point to, must not be <code>null</code>.
+	 * @param initializer a callback for further initialization of the create annotation reference, must not be <code>null</code>.
+	 * @return a {@link AnnotationReference} pointing to the given type, or <code>null</code> if the given type is not an annotation type.
+	 * @throws IllegalArgumentException if the given type declaration is <code>null</code> or the <code>initializer</code> is <code>null</code>
+	 */
+	AnnotationReference newAnnotationReference(Type annotationTypeDelcaration, Procedures.Procedure1<AnnotationReferenceBuildContext> initializer);
+	
+	/**
+	 * Creates a new annotation reference for the given {@link Class}.
+	 *  
+	 * @param annotationClass the {@link Class} to point to, must not be <code>null</code>.
+	 * @param initializer a callback for further initialization of the create annotation reference, must not be <code>null</code>.
+	 * @return a {@link AnnotationReference} pointing to the given type, or <code>null</code> if the given type is not on the class path of the compiled project or an annotation type.
+	 * @throws IllegalArgumentException if the given {@link Class} is <code>null</code> or the <code>initializer</code> is <code>null</code>
+	 */
+	AnnotationReference newAnnotationReference(Class<?> annotationClass, Procedures.Procedure1<AnnotationReferenceBuildContext> initializer);
+	
+	/**
+	 * Create a new annotation reference base on the given annotation reference.
+	 * 
+	 * @param annotationReference an annotation reference which is used as a base for a new annotation reference, must not be <code>null</code> or detached. 
+	 * @param initializer a callback for further initialization of the create annotation reference, must not be <code>null</code>.
+	 * @return a {@link AnnotationReference} constructed based on the given annotation reference, can be <code>null</code> 
+	 * @throws IllegalArgumentException if the given annotation reference is <code>null</code> or detached; or the <code>initializer</code> is <code>null</code>
+	 */
+	AnnotationReference newAnnotationReference(AnnotationReference annotationReference, Procedures.Procedure1<AnnotationReferenceBuildContext> initializer);
+	
+}
diff --git a/java/org/eclipse/xtend/lib/macro/services/Associator.java b/java/org/eclipse/xtend/lib/macro/services/Associator.java
new file mode 100644
index 0000000..f2370d5
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/Associator.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import org.eclipse.xtend.lib.macro.declaration.Element;
+import org.eclipse.xtend.lib.macro.declaration.MutableElement;
+
+/**
+ * Associates generated Java elements with their source Xtend elements 
+ * @since 2.7
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @see Tracability
+ */
+public interface Associator {
+	/**
+	 * Associates the generate element with the Xtend source code. Every generated element should have
+	 * a source element. This information is used by features like "Go to Declaration" and the outline view.
+	 * A typical use case (generating a getter for a field) would look like this:
+	 * 
+	 * <pre>
+	 * myClass.declaredFields.forEach[field|
+	 *  myClass.addMethod("get" + field.simpleName.toFirstUpper) [
+	 *   primarySourceElement = field
+	 *   // return type, body etc...
+	 *  ]
+	 * ]
+	 * </pre>
+	 * 
+	 * This way, the getter generated in the active annotation above would be associated with the field in the Xtend source code.
+	 * Notice that we passed the field from the Java AST as a source element. This is a shortcut for
+	 * 
+	 * <pre>
+	 * primarySourceElement = field.primarySourceElement
+	 * </pre>
+	 * 
+	 * @param sourceElement the source element that the secondaryElement was derived from
+	 * @param javaElement the generated Java element 
+	 */
+	void setPrimarySourceElement(MutableElement javaElement, Element sourceElement);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/services/GlobalTypeLookup.java b/java/org/eclipse/xtend/lib/macro/services/GlobalTypeLookup.java
new file mode 100644
index 0000000..91a28c7
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/GlobalTypeLookup.java
@@ -0,0 +1,35 @@
+/*******************************************************************************
+ * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import org.eclipse.xtend.lib.macro.declaration.Type;
+
+/**
+ * @since 2.8
+ */
+public interface GlobalTypeLookup {
+
+	/**
+	 * @param clazz
+	 *            the clazz representing the type to look up
+	 * @return the type with the same qualified name as the given
+	 *         <code>Class</code> object, or <code>null</code> if that type
+	 *         couldn't be found on the compilation units classpath.
+	 */
+	Type findTypeGlobally(Class<?> clazz);
+
+	/**
+	 * @param typeName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the type with the given qualified name, or <code>null</code> if such a type
+	 *         couldn't be found on the compilation units classpath.
+	 */
+	Type findTypeGlobally(String typeName);
+
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/services/Problem.java b/java/org/eclipse/xtend/lib/macro/services/Problem.java
new file mode 100644
index 0000000..47bae21
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/Problem.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Represents a compiler problem or warning.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface Problem {
+	
+	/**
+	 * The severity of a problem 
+	 */
+	enum Severity {
+		ERROR, WARNING, INFO, IGNORE
+	}
+	
+	/**
+	 * @return the problem kind identifier.
+	 */
+	String getId();
+	
+	/**
+	 * @return the user message of the problem
+	 */
+	String getMessage();
+	
+	/**
+	 * @return the problem's severity
+	 */
+	Severity getSeverity();
+}
diff --git a/java/org/eclipse/xtend/lib/macro/services/ProblemSupport.java b/java/org/eclipse/xtend/lib/macro/services/ProblemSupport.java
new file mode 100644
index 0000000..63e3344
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/ProblemSupport.java
@@ -0,0 +1,57 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import java.util.List;
+
+import org.eclipse.xtend.lib.macro.declaration.Element;
+import org.eclipse.xtend.lib.macro.services.Problem.Severity;
+import org.eclipse.xtext.xbase.lib.Procedures;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Support for looking up and creating new {@link Problem} markers on {@link Element}s
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface ProblemSupport {
+	/**
+	 * @param element the element to look up problems
+	 * @return the problems associated with the given {@link Element}
+	 */
+	List<? extends Problem> getProblems(Element element);
+	
+	/**
+	 * Adds a problem marker with severity {@link Severity}#ERROR to the given element
+	 * 
+	 * @param element the element to which associate the new problem marker
+	 * @param message the message for the problem marker
+	 */
+	void addError(Element element, String message);
+	
+	/**
+	 * Adds a problem marker with severity {@link Severity}#WARNING to the given element
+	 * 
+	 * @param element the element to which associate the new problem marker
+	 * @param message the message for the problem marker
+	 */
+	void addWarning(Element element, String message);
+
+	/**
+	 * @param validationCallback
+	 *            a callback that will be executed in the validation phase, when
+	 *            all transformations have been done and types are inferred.
+	 * @since 2.7
+	 */
+	void validateLater(Procedures.Procedure0 validationCallback);
+}
+
diff --git a/java/org/eclipse/xtend/lib/macro/services/SourceTypeLookup.java b/java/org/eclipse/xtend/lib/macro/services/SourceTypeLookup.java
new file mode 100644
index 0000000..84ca389
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/SourceTypeLookup.java
@@ -0,0 +1,65 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import org.eclipse.xtend.lib.macro.declaration.AnnotationTypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.ClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.CompilationUnit;
+import org.eclipse.xtend.lib.macro.declaration.EnumerationTypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.InterfaceDeclaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Facilities to lookup Xtend type declarations declared within the currently
+ * processed {@link CompilationUnit}.
+ * 
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface SourceTypeLookup {
+
+	/**
+	 * @param qualifiedName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the <code>ClassDeclaration</code> with given qualified
+	 *         name, or <code>null</code> if no such class declaration is
+	 *         contained in the currently processed <code>CompilationUnit</code>
+	 */
+	ClassDeclaration findSourceClass(String qualifiedName);
+
+	/**
+	 * @param qualifiedName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the <code>InterfaceDeclaration</code> with given qualified
+	 *         name, or <code>null</code> if no such interface declaration is
+	 *         contained in the currently processed <code>CompilationUnit</code>
+	 */
+	InterfaceDeclaration findSourceInterface(String qualifiedName);
+
+	/**
+	 * @param qualifiedName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the <code>EnumerationTypeDeclaration</code> with given
+	 *         qualified name, or <code>null</code> if no such class declaration
+	 *         is contained in the currently processed
+	 *         <code>CompilationUnit</code>
+	 */
+	EnumerationTypeDeclaration findSourceEnumerationType(String qualifiedName);
+
+	/**
+	 * @param qualifiedName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the <code>AnnotationTypeDeclaration</code> with given
+	 *         qualified name, or <code>null</code> if no such class declaration
+	 *         is contained in the currently processed
+	 *         <code>CompilationUnit</code>
+	 */
+	AnnotationTypeDeclaration findSourceAnnotationType(String qualifiedName);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/services/Tracability.java b/java/org/eclipse/xtend/lib/macro/services/Tracability.java
new file mode 100644
index 0000000..c85bd4a
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/Tracability.java
@@ -0,0 +1,67 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import org.eclipse.xtend.lib.macro.declaration.CompilationUnit;
+import org.eclipse.xtend.lib.macro.declaration.Element;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * 
+ * Support for navigating between the primary AST structure representing the Xtend code
+ * and the corresponding Java elements derived from that.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @see Associator
+ */
+@Beta
+public interface Tracability {
+	/**
+	 * @param element
+	 * @return whether the given element is a source (i.e Xtend) element.
+	 * @since 2.7
+	 */
+	boolean isSource(Element element);
+	
+	/**
+	 * @param element
+	 * @return whether the given element is a Java element derived from the currently processed {@link CompilationUnit}
+	 * @since 2.7
+	 */
+	boolean isGenerated(Element element);
+	
+	/**
+	 * @param element
+	 * @return whether the given element is a Java element <b>not</b> derived from the currently processed {@link CompilationUnit}
+	 * @since 2.7
+	 */
+	boolean isExternal(Element element);
+	
+	/**
+	 * @param source
+	 * @return the primary generated element (Java) derived from the given source element (Xtend).
+	 * @since 2.7
+	 */
+	Element getPrimaryGeneratedJavaElement(Element source);
+	/**
+	 * @since 2.7
+	 * @param target
+	 * @return whether this element was already present in the Xtend source AST.
+	 */
+	boolean isThePrimaryGeneratedJavaElement(Element target);
+	
+	/**
+	 * @param target
+	 * @return the source element (Xtend) the given target (Java) element is derived from
+	 * @since 2.7
+	 */
+	Element getPrimarySourceElement(Element target);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/services/TypeLookup.java b/java/org/eclipse/xtend/lib/macro/services/TypeLookup.java
new file mode 100644
index 0000000..d49d63b
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/TypeLookup.java
@@ -0,0 +1,66 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import org.eclipse.xtend.lib.macro.declaration.CompilationUnit;
+import org.eclipse.xtend.lib.macro.declaration.MutableAnnotationTypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableClassDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableEnumerationTypeDeclaration;
+import org.eclipse.xtend.lib.macro.declaration.MutableInterfaceDeclaration;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Facilities to lookup Java type declarations generated within the currently
+ * processed {@link CompilationUnit} as well as on the classpath of that <code>CompilationUnit</code>.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface TypeLookup extends GlobalTypeLookup {
+
+	/**
+	 * @param qualifiedName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the <code>MutableClassDeclaration</code> with given qualified
+	 *         name, or <code>null</code> if no such class declaration is
+	 *         contained in the currently processed <code>CompilationUnit</code>
+	 */
+	MutableClassDeclaration findClass(String qualifiedName);
+
+	/**
+	 * @param qualifiedName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the <code>MutableInterfaceDeclaration</code> with given qualified
+	 *         name, or <code>null</code> if no such interface declaration is
+	 *         contained in the currently processed <code>CompilationUnit</code>
+	 */
+	MutableInterfaceDeclaration findInterface(String qualifiedName);
+
+	/**
+	 * @param qualifiedName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the <code>MutableEnumerationTypeDeclaration</code> with given
+	 *         qualified name, or <code>null</code> if no such class declaration
+	 *         is contained in the currently processed
+	 *         <code>CompilationUnit</code>
+	 */
+	MutableEnumerationTypeDeclaration findEnumerationType(String qualifiedName);
+
+	/**
+	 * @param qualifiedName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the <code>MutableAnnotationTypeDeclaration</code> with given
+	 *         qualified name, or <code>null</code> if no such class declaration
+	 *         is contained in the currently processed
+	 *         <code>CompilationUnit</code>
+	 */
+	MutableAnnotationTypeDeclaration findAnnotationType(String qualifiedName);
+}
diff --git a/java/org/eclipse/xtend/lib/macro/services/TypeReferenceProvider.java b/java/org/eclipse/xtend/lib/macro/services/TypeReferenceProvider.java
new file mode 100644
index 0000000..c02aa69
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/TypeReferenceProvider.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import java.util.List;
+import java.util.Set;
+
+import org.eclipse.xtend.lib.macro.declaration.Type;
+import org.eclipse.xtend.lib.macro.declaration.TypeReference;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Provides and creates {@link TypeReference} instances.
+ * 
+ * @author Sven Efftinge
+ * @noimplement This interface is not intended to be implemented by clients.
+ */
+@Beta
+public interface TypeReferenceProvider {
+	/**
+	 * Creates a new array type reference using the given component type.
+	 * If the component type is itself an array this method adds a dimension.
+	 * 
+	 * @param componentType the component type of the array type reference
+	 * @return an array type reference
+	 */
+	TypeReference newArrayTypeReference(TypeReference componentType);
+	
+	/**
+	 * Creates a new type reference for the given name and the given type arguments.
+	 * 
+	 * @param typeName the name of the type to point to
+	 * @param typeArguments the type arguments
+	 * @return a {@link TypeReference} pointing to the type with given name, or <code>null</code> if no such type could be found.
+	 */
+	TypeReference newTypeReference(String typeName, TypeReference... typeArguments);
+	
+	/**
+	 * Creates a new type reference for the given typeDeclaration and the type arguments.
+	 * 
+	 * @param typeDeclaration the type to point to
+	 * @param typeArguments the type arguments
+	 * @return a {@link TypeReference} pointing to the given type.
+	 */
+	TypeReference newTypeReference(Type typeDeclaration, TypeReference... typeArguments);
+	
+	/**
+	 * Returns a new self type reference for the given typeDeclaration, e.g. if you have a class like
+	 * 
+	 * <pre>
+	 *  class Foo&lt;T&gt; {}
+	 * </pre>
+	 * 
+	 * And you want to add a method that returns the instance itself, you would use the self type as the method's return type.
+	 * 
+	 * <pre>
+	 * class Foo&lt;T&gt; {
+	 *  def Foo&lt;T&gt; mySelf() {
+	 *   this
+	 *  }
+	 * }
+	 * </pre>
+	 * 
+	 * In contrast, {@link #newTypeReference(Type, TypeReference...)} without any arguments would return the raw type only and would result in code with warnings:
+	 * <pre>
+	 * class Foo&lt;T&gt; {
+	 *  def Foo mySelf() {
+	 *   this
+	 *  }
+	 * }
+	 * </pre>
+	 * 
+	 * @param typeDeclaration the raw type for the newly produced reference
+	 * @return a reference to the given type declaration
+	 * @since 2.7
+	 */
+	TypeReference newSelfTypeReference(Type typeDeclaration);
+	
+	/**
+	 * Creates a new type reference for the given <code>Class</code> and the type arguments.
+	 * 
+	 * @param clazz the clazz to point to
+	 * @param typeArguments the type arguments
+	 * @return a {@link TypeReference} pointing to the given type or <code>null</code> if the type is not on the class path of the compiled project.
+	 */
+	TypeReference newTypeReference(Class<?> clazz, TypeReference... typeArguments);
+	
+	/**
+	 * @return a wildcard type references with upperBound {@link Object}
+	 */
+	TypeReference newWildcardTypeReference();
+	
+	 /**
+	  * @param upperBound the upper bound of the wildcard type
+	  * @return a wildcard type references with the given upperBound.
+	  */
+	TypeReference newWildcardTypeReference(TypeReference upperBound);
+	
+	 /**
+	  * @param lowerBound the lower bound of the wildcard type
+	  * @return a wildcard type references with the given lowerBound.
+	  */
+	TypeReference newWildcardTypeReferenceWithLowerBound(TypeReference lowerBound);
+	
+	/**
+	 * @return a type reference pointing to {@link Object}
+	 */
+	TypeReference getObject();
+	
+	/**
+	 * @return a type reference pointing to {@link String}
+	 */
+	TypeReference getString();
+	
+	/**
+	 * @param param the type argument for the type reference
+	 * @return a type reference for {@link List} with the given type argument.
+	 */
+	TypeReference getList(TypeReference param);
+	
+	/**
+	 * @param param the type argument for the type reference
+	 * @return a type reference for {@link Set} with the given type argument.
+	 */
+	TypeReference getSet(TypeReference param);
+	
+	/**
+	 * The any type is the type of the null pointer and has no concrete
+	 * representation in Java. It is assignable to every reference type.
+	 * 
+	 * @return a type reference representing the "any type".
+	 */
+	TypeReference getAnyType();
+	
+	/**
+	 * @return a type reference representing 'void'
+	 */
+	TypeReference getPrimitiveVoid();
+	
+	/**
+	 * @return a type reference representing 'boolean'
+	 */
+	TypeReference getPrimitiveBoolean();
+	
+	/**
+	 * @return a type reference representing 'short'
+	 */
+	TypeReference getPrimitiveShort();
+	
+	/**
+	 * @return a type reference representing 'int'
+	 */
+	TypeReference getPrimitiveInt();
+	
+	/**
+	 * @return a type reference representing 'long'
+	 */
+	TypeReference getPrimitiveLong();
+	
+	/**
+	 * @return a type reference representing 'float'
+	 */
+	TypeReference getPrimitiveFloat();
+	
+	/**
+	 * @return a type reference representing 'double'
+	 */
+	TypeReference getPrimitiveDouble();
+	
+	/**
+	 * @return a type reference representing 'char'
+	 */
+	TypeReference getPrimitiveChar();
+	
+	/**
+	 * @return a type reference representing 'byte'
+	 */
+	TypeReference getPrimitiveByte();
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtend/lib/macro/services/UpstreamTypeLookup.java b/java/org/eclipse/xtend/lib/macro/services/UpstreamTypeLookup.java
new file mode 100644
index 0000000..5f2feb9
--- /dev/null
+++ b/java/org/eclipse/xtend/lib/macro/services/UpstreamTypeLookup.java
@@ -0,0 +1,42 @@
+/*******************************************************************************
+ * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend.lib.macro.services;
+
+import org.eclipse.xtend.lib.macro.declaration.CompilationUnit;
+import org.eclipse.xtend.lib.macro.declaration.Type;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Facilities to lookup of Java type declarations in upstream 
+ * dependencies of the current {@link CompilationUnit}. 
+ * This means that types defined in the same project will not be found.
+ * 
+ * @noimplement This interface is not intended to be implemented by clients.
+ * @since 2.7
+ */
+@Beta
+public interface UpstreamTypeLookup {
+	/**
+	 * @param clazz
+	 *            the clazz representing the type to look up
+	 * @return the type with the same qualified name as the given
+	 *         <code>Class</code> object, or <code>null</code> if that type
+	 *         couldn't be found on the compilation unit's upstream dependencies.
+	 */
+	Type findUpstreamType(Class<?> clazz);
+
+	/**
+	 * @param typeName
+	 *            the qualified name of the type to look up. Nested class delimiter is expected to be the '.' (dot).
+	 * @return the type with the given qualified name, or <code>null</code> if such a type
+	 *         couldn't be found on the compilation unit's upstream dependencies.
+	 */
+	Type findUpstreamType(String typeName);
+}
diff --git a/java/org/eclipse/xtend2/lib/DefaultLineDelimiter.java b/java/org/eclipse/xtend2/lib/DefaultLineDelimiter.java
new file mode 100644
index 0000000..3ba9480
--- /dev/null
+++ b/java/org/eclipse/xtend2/lib/DefaultLineDelimiter.java
@@ -0,0 +1,20 @@
+/*******************************************************************************
+ * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend2.lib;
+
+import com.google.common.annotations.GwtCompatible;
+/*
+ * Will be replaced with \n on GWT 
+ */
+@GwtCompatible(emulated = true)
+class DefaultLineDelimiter {
+	public static String get() {
+		return System.getProperty("line.separator");
+	}
+}
diff --git a/java/org/eclipse/xtend2/lib/Lib.gwt.xml b/java/org/eclipse/xtend2/lib/Lib.gwt.xml
new file mode 100644
index 0000000..7961395
--- /dev/null
+++ b/java/org/eclipse/xtend2/lib/Lib.gwt.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.4.0//EN" "http://google-web-toolkit.googlecode.com/svn/tags/2.4.0/distro-source/core/src/gwt-module.dtd">
+<module>
+	<source path=""/>
+	<super-source path="super"/>
+	<inherits name="com.google.gwt.user.User" />
+	<inherits name="com.google.common.collect.Collect" />
+</module>
\ No newline at end of file
diff --git a/java/org/eclipse/xtend2/lib/StringConcatenation.java b/java/org/eclipse/xtend2/lib/StringConcatenation.java
new file mode 100644
index 0000000..072b5fd
--- /dev/null
+++ b/java/org/eclipse/xtend2/lib/StringConcatenation.java
@@ -0,0 +1,747 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2016 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend2.lib;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.xtend2.lib.StringConcatenationClient.TargetStringConcatenation;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * <p>
+ * A {@link StringConcatenation} allows for efficient, indentation aware concatenation of character sequences.
+ * </p>
+ * <p>
+ * In addition to the methods that are specified by the implemented interface {@link CharSequence}, there are some other
+ * public operations that allow to modify the contents of this sequence. The string representation of arbitrary objects
+ * can be appended to an instance of {@link StringConcatenation}. There are overloaded variants of
+ * {@link #append(Object, String)} that allow to pass an indentation that should be applied to each line of the appended
+ * content. Each line break that is part of the new content will be replaced by the line delimiter that was configured
+ * for this {@link StringConcatenation}.
+ * </p>
+ * <p>
+ * The {@link #append(Object) append}-operation ignores <code>null</code> arguments. This is different to what
+ * {@link StringBuffer} or {@link StringBuilder} do and that's the reason why the {@link Appendable} interface is not
+ * fulfilled by a {@link StringConcatenation}.
+ * <p>
+ * <p>
+ * The object uses an internal {@link List} of {@link String Strings} that is concatenated on demand to a complete
+ * sequence. Use {@link #toString()} to get the joined version of a {@link StringConcatenation}.
+ * </p>
+ * <p>
+ * {@link #equals(Object)} and {@link #hashCode()} are not specialized for a {@link StringConcatenation}, that is, the
+ * semantics are based on identity similar to what {@link StringBuffer} and {@link StringBuilder} do.
+ * </p>
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @since 2.3
+ */
+@GwtCompatible
+public class StringConcatenation implements CharSequence {
+
+	/**
+	 * The default line delimiter that is used by instances of {@link StringConcatenation}. It uses
+	 * <code>System.getProperty("line.separator")</code>.
+	 * @since 2.3
+	 */
+	public static final String DEFAULT_LINE_DELIMITER = DefaultLineDelimiter.get();
+
+	/**
+	 * Number of elements to add to {@link #segments} array when we need to grow it. This should be a power-of-two
+	 * so we can perform efficient modulo operation.
+	 */
+	private static final int SEGMENTS_SIZE_INCREMENT = 16;
+
+	/**
+	 * Initial allocation size of the {@link #segments} array.
+	 */
+	private static final int SEGMENTS_INITIAL_SIZE = 3 * SEGMENTS_SIZE_INCREMENT;
+
+	/**
+	 * The complete content of this sequence. It may contain insignificant trailing parts that are not part of the final
+	 * string representation that can be obtained by {@link #toString()}. Insignificant parts will not be considered by
+	 * {@link #length()}, {@link #charAt(int)} or {@link #subSequence(int, int)}.
+	 */
+	private final ArrayList<String> segments = new ArrayList<String>(SEGMENTS_INITIAL_SIZE);
+
+	/**
+	 * Internal hint for the size of segments. We cache this value so we do not have to perform costly calculations. 
+	 */
+	private int lastSegmentsSize = SEGMENTS_INITIAL_SIZE;
+
+	/**
+	 * A cached string representation.
+	 */
+	private String cachedToString;
+
+	/**
+	 * The configured delimiter. It will be used to replace possibly existing delimiters of to-be-appended content.
+	 */
+	private final String lineDelimiter;
+
+	/**
+	 * Create a new concatenation that uses the system line delimiter.
+	 * 
+	 * @see System#getProperties()
+	 * @see System#getProperty(String)
+	 */
+	public StringConcatenation() {
+		this(DEFAULT_LINE_DELIMITER);
+	}
+
+	/**
+	 * Create a new concatenation with the specified delimiter.
+	 * 
+	 * @param lineDelimiter
+	 *            the used delimiter.
+	 * @throws IllegalArgumentException
+	 *             if the lineDelimiter is <code>null</code> or the empty String.
+	 * @since 2.3
+	 */
+	public StringConcatenation(String lineDelimiter) {
+		if (lineDelimiter == null || lineDelimiter.length() == 0)
+			throw new IllegalArgumentException("lineDelimiter must not be null or empty");
+		this.lineDelimiter = lineDelimiter;
+	}
+
+	private void growSegments(int increment) {
+		int targetSize = segments.size() + increment;
+		if (targetSize <= lastSegmentsSize) {
+			return;
+		}
+
+		int mod = targetSize % SEGMENTS_SIZE_INCREMENT;
+		if (mod != 0) {
+			targetSize += SEGMENTS_SIZE_INCREMENT - mod;
+		}
+
+		segments.ensureCapacity(targetSize);
+		lastSegmentsSize = targetSize;
+	}
+
+	/**
+	 * Append the string representation of the given object to this sequence. Does nothing if the object is
+	 * <code>null</code>.
+	 * 
+	 * @param object
+	 *            the to-be-appended object.
+	 */
+	public void append(Object object) {
+		append(object, segments.size());
+	}
+
+	/**
+	 * Append the given string to this sequence. Does nothing if the string is <code>null</code>.
+	 *
+	 * @param str
+	 *            the to-be-appended string.
+	 * @since 2.11
+	 */
+	public void append(String str) {
+		if (str != null)
+			append(str, segments.size());
+	}
+
+	/**
+	 * Append the contents of a given StringConcatenation to this sequence. Does nothing
+	 * if the concatenation is <code>null</code>.
+	 *
+	 * @param concat
+	 *            the to-be-appended StringConcatenation.
+	 * @since 2.11
+	 */
+	public void append(StringConcatenation concat) {
+		if (concat != null)
+			appendSegments(segments.size(), concat.getSignificantContent(), concat.lineDelimiter);
+	}
+
+	/**
+	 * Append the contents of a given StringConcatenationClient to this sequence. Does nothing
+	 * if the argument is <code>null</code>.
+	 *
+	 * @param client
+	 *            the to-be-appended StringConcatenationClient.
+	 * @since 2.11
+	 */
+	public void append(StringConcatenationClient client) {
+		if (client != null)
+			client.appendTo(new SimpleTarget(this, segments.size()));
+	}
+
+	/*
+	 * Add the string representation of the given object to this sequence at the given index. Does nothing if the object
+	 * is <code>null</code>.
+	 * 
+	 * @param object
+	 *            the to-be-appended object.
+	 * @param index
+	 *            the index in the list of segments.
+	 */
+	protected void append(Object object, int index) {
+		if (object == null)
+			return;
+		if (object instanceof String) {
+			append((String) object, index);
+		} else if (object instanceof StringConcatenation) {
+			StringConcatenation other = (StringConcatenation) object;
+			appendSegments(index, other.getSignificantContent(), other.lineDelimiter);
+		} else if (object instanceof StringConcatenationClient) {
+			StringConcatenationClient other = (StringConcatenationClient) object;
+			other.appendTo(new SimpleTarget(this, index));
+		} else {
+			final String text = getStringRepresentation(object);
+			if (text != null) {
+				append(text, index);
+			}
+		}
+	}
+
+	private void append(String text, int index) {
+		final int initial = initialSegmentSize(text);
+		if (initial == text.length()) {
+			appendSegment(index, text);
+		} else {
+			appendSegments(index, continueSplitting(text, initial));
+		}
+	}
+
+	/**
+	 * Add the string representation of the given object to this sequence. The given indentation will be prepended to
+	 * each line except the first one if the object has a multi-line string representation.
+	 * 
+	 * @param object
+	 *            the appended object.
+	 * @param indentation
+	 *            the indentation string that should be prepended. May not be <code>null</code>.
+	 */
+	public void append(Object object, String indentation) {
+		append(object, indentation, segments.size());
+	}
+
+	/**
+	 * Add the given string to this sequence. The given indentation will be prepended to
+	 * each line except the first one if the object has a multi-line string representation.
+	 *
+	 * @param str
+	 *            the appended string.
+	 * @param indentation
+	 *            the indentation string that should be prepended. May not be <code>null</code>.
+	 * @since 2.11
+	 */
+	public void append(String str, String indentation) {
+		if (indentation.isEmpty()) {
+			append(str);
+		} else if (str != null)
+			append(indentation, str, segments.size());
+	}
+
+	/**
+	 * Append the contents of a given StringConcatenation to this sequence. Does nothing
+	 * if the concatenation is <code>null</code>. The given indentation will be prepended to each line except
+	 * the first one.
+	 *
+	 * @param concat
+	 *            the to-be-appended StringConcatenation.
+	 * @param indentation
+	 *            the indentation string that should be prepended. May not be <code>null</code>.
+	 * @since 2.11
+	 */
+	public void append(StringConcatenation concat, String indentation) {
+		if (indentation.isEmpty()) {
+			append(concat);
+		} else if (concat != null)
+			appendSegments(indentation, segments.size(), concat.getSignificantContent(), concat.lineDelimiter);
+	}
+
+	/**
+	 * Append the contents of a given StringConcatenationClient to this sequence. Does nothing
+	 * if that argument is <code>null</code>. The given indentation will be prepended to each line except
+	 * the first one.
+	 *
+	 * @param client
+	 *            the to-be-appended StringConcatenationClient.
+	 * @param indentation
+	 *            the indentation string that should be prepended. May not be <code>null</code>.
+	 * @since 2.11
+	 */
+	public void append(StringConcatenationClient client, String indentation) {
+		if (indentation.isEmpty()) {
+			append(client);
+		} else if (client != null)
+			client.appendTo(new IndentedTarget(this, indentation, segments.size()));
+	}
+
+	/**
+	 * Add the string representation of the given object to this sequence at the given index. The given indentation will
+	 * be prepended to each line except the first one if the object has a multi-line string representation.
+	 * 
+	 * @param object
+	 *            the to-be-appended object.
+	 * @param indentation
+	 *            the indentation string that should be prepended. May not be <code>null</code>.
+	 * @param index
+	 *            the index in the list of segments.
+	 */
+	protected void append(Object object, String indentation, int index) {
+		if (indentation.length() == 0) {
+			append(object, index);
+			return;
+		}
+		if (object == null)
+			return;
+		if (object instanceof String) {
+			append(indentation, (String)object, index);
+		} else if (object instanceof StringConcatenation) {
+			StringConcatenation other = (StringConcatenation) object;
+			List<String> otherSegments = other.getSignificantContent();
+			appendSegments(indentation, index, otherSegments, other.lineDelimiter);
+		} else if (object instanceof StringConcatenationClient) {
+			StringConcatenationClient other = (StringConcatenationClient) object;
+			other.appendTo(new IndentedTarget(this, indentation, index));
+		} else {
+			final String text = getStringRepresentation(object);
+			if (text != null) {
+				append(indentation, text, index);
+			}
+		}
+	}
+
+	private void append(String indentation, String text, int index) {
+		final int initial = initialSegmentSize(text);
+		if (initial == text.length()) {
+			appendSegment(index, text);
+		} else {
+			appendSegments(indentation, index, continueSplitting(text, initial), lineDelimiter);
+		}
+	}
+
+	/**
+	 * Computes the string representation of the given object. The default implementation
+	 * will just invoke {@link Object#toString()} but clients may override and specialize
+	 * the logic.
+	 * 
+	 * @param object the object that shall be appended. Never <code>null</code>.
+	 * @return the string representation. May not be <code>null</code>.
+	 * @since 2.5
+	 */
+	protected String getStringRepresentation(Object object) {
+		return object.toString();
+	}
+
+	/**
+	 * Add the string representation of the given object to this sequence immediately. That is, all the trailing
+	 * whitespace of this sequence will be ignored and the string is appended directly after the last segment that
+	 * contains something besides whitespace. The given indentation will be prepended to each line except the first one
+	 * if the object has a multi-line string representation.
+	 * 
+	 * @param object
+	 *            the to-be-appended object.
+	 * @param indentation
+	 *            the indentation string that should be prepended. May not be <code>null</code>.
+	 */
+	public void appendImmediate(Object object, String indentation) {
+		for (int i = segments.size() - 1; i >= 0; i--) {
+			String segment = segments.get(i);
+			for (int j = 0; j < segment.length(); j++) {
+				if (!WhitespaceMatcher.isWhitespace(segment.charAt(j))) {
+					append(object, indentation, i + 1);
+					return;
+				}
+			}
+		}
+		append(object, indentation, 0);
+	}
+
+	/**
+	 * Add the list of segments to this sequence at the given index. The given indentation will be prepended to each
+	 * line except the first one if the object has a multi-line string representation.
+	 * 
+	 * @param indentation
+	 *            the indentation string that should be prepended. May not be <code>null</code>.
+	 * @param index
+	 *            the index in this instance's list of segments.
+	 * @param otherSegments
+	 *            the to-be-appended segments. May not be <code>null</code>.
+	 * @param otherDelimiter
+	 *            the line delimiter that was used in the otherSegments list.
+	 */
+	protected void appendSegments(String indentation, int index, List<String> otherSegments, String otherDelimiter) {
+		if (otherSegments.isEmpty()) {
+			return;
+		}
+
+		// This may not be accurate, but it's better than nothing
+		growSegments(otherSegments.size());
+		for (String otherSegment : otherSegments) {
+			if (otherDelimiter.equals(otherSegment)) {
+				segments.add(index++, lineDelimiter);
+				segments.add(index++, indentation);
+			} else {
+				segments.add(index++, otherSegment);
+			}
+		}
+		cachedToString = null;
+	}
+
+	/**
+	 * Add the list of segments to this sequence at the given index. The given indentation will be prepended to each
+	 * line except the first one if the object has a multi-line string representation.
+	 * 
+	 * @param index
+	 *            the index in this instance's list of segments.
+	 * @param otherSegments
+	 *            the to-be-appended segments. May not be <code>null</code>.
+	 * @param otherDelimiter
+	 *            the line delimiter that was used in the otherSegments list.
+	 * @since 2.5
+	 */
+	protected void appendSegments(int index, List<String> otherSegments, String otherDelimiter) {
+		if (otherDelimiter.equals(lineDelimiter)) {
+			appendSegments(index, otherSegments);
+		} else {
+			if (otherSegments.isEmpty()) {
+				return;
+			}
+			growSegments(otherSegments.size());
+			for (String otherSegment : otherSegments) {
+				if (otherDelimiter.equals(otherSegment)) {
+					segments.add(index++, lineDelimiter);
+				} else {
+					segments.add(index++, otherSegment);
+				}
+			}
+			cachedToString = null;
+		}
+	}
+
+	/**
+	 * Add the list of segments to this sequence at the given index. The given indentation will be prepended to each
+	 * line except the first one if the object has a multi-line string representation.
+	 * 
+	 * @param index
+	 *            the index in this instance's list of segments.
+	 * @param otherSegments
+	 *            the to-be-appended segments. May not be <code>null</code>.
+	 * @since 2.5
+	 */
+	protected void appendSegments(int index, List<String> otherSegments) {
+		growSegments(otherSegments.size());
+		if (segments.addAll(index, otherSegments)) {
+			cachedToString = null;
+		}
+	}
+
+	private void appendSegment(int index, String segment) {
+		growSegments(1);
+		segments.add(index, segment);
+		cachedToString = null;
+	}
+
+	/**
+	 * Add a newline to this sequence according to the configured lineDelimiter.
+	 */
+	public void newLine() {
+		growSegments(1);
+		segments.add(lineDelimiter);
+		cachedToString = null;
+	}
+
+	/**
+	 * Add a newline to this sequence according to the configured lineDelimiter if the last line contains
+	 * something besides whitespace.
+	 */
+	public void newLineIfNotEmpty() {
+		for (int i = segments.size() - 1; i >= 0; i--) {
+			String segment = segments.get(i);
+			if (lineDelimiter.equals(segment)) {
+				segments.subList(i + 1, segments.size()).clear();
+				cachedToString = null;
+				return;
+			}
+			for (int j = 0; j < segment.length(); j++) {
+				if (!WhitespaceMatcher.isWhitespace(segment.charAt(j))) {
+					newLine();
+					return;
+				}
+			}
+		}
+		segments.clear();
+		cachedToString = null;
+	}
+
+	@Override
+	public String toString() {
+		if (cachedToString != null) {
+			return cachedToString;
+		}
+		List<String> significantContent = getSignificantContent();
+		StringBuilder builder = new StringBuilder(significantContent.size() * 4);
+		for (String segment : significantContent)
+			builder.append(segment);
+		cachedToString = builder.toString();
+		return cachedToString;
+	}
+
+	/**
+	 * Return the actual content of this sequence, including all trailing whitespace. The return value is unsafe,
+	 * that is modification to this {@link StringConcatenation} will cause changes in a previously obtained
+	 * result and vice versa.
+	 * 
+	 * @return the actual content of this instance. Never <code>null</code>.
+	 * @since 2.8
+	 */
+	protected final List<String> getContent() {
+		return segments;
+	}
+
+	/**
+	 * Compute the significant content of this sequence. That is, trailing whitespace after the last line-break will be
+	 * ignored if the last line contains only whitespace. The return value is unsafe, that is modification to this
+	 * {@link StringConcatenation} will cause changes in a previously obtained result and vice versa.
+	 * 
+	 * @return the significant content of this instance. Never <code>null</code>.
+	 */
+	protected List<String> getSignificantContent() {
+		for (int i = segments.size() - 1; i >= 0; i--) {
+			String segment = segments.get(i);
+			if (lineDelimiter.equals(segment)) {
+				return segments.subList(0, i + 1);
+			}
+			for (int j = 0; j < segment.length(); j++) {
+				if (!WhitespaceMatcher.isWhitespace(segment.charAt(j))) {
+					return segments;
+				}
+			}
+		}
+		return segments;
+	}
+
+	/**
+	 * Allows subtypes to access the configured line delimiter.
+
+	 * @return the line delimiter
+	 * @since 2.5
+	 */
+	protected String getLineDelimiter() {
+		return lineDelimiter;
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * <p>
+	 * Only the significant content of this sequence is considered.
+	 * </p>
+	 */
+	@Override
+	public int length() {
+		return toString().length();
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * <p>
+	 * Only the significant content of this sequence is considered.
+	 * </p>
+	 */
+	@Override
+	public char charAt(int index) {
+		return toString().charAt(index);
+	}
+
+	/**
+	 * {@inheritDoc}
+	 * 
+	 * <p>
+	 * Only the significant content of this sequence is considered.
+	 * </p>
+	 */
+	@Override
+	public CharSequence subSequence(int start, int end) {
+		return toString().subSequence(start, end);
+	}
+
+	/**
+	 * Return a list of segments where each segment is either the content of a line in the given text or a line-break
+	 * according to the configured delimiter. Existing line-breaks in the text will be replaced by this's
+	 * instances delimiter.
+	 * 
+	 * @param text
+	 *            the to-be-splitted text. May be <code>null</code>.
+	 * @return a list of segments. Is never <code>null</code>.
+	 */
+	protected List<String> splitLinesAndNewLines(String text) {
+		if (text == null)
+			return Collections.emptyList();
+		int idx = initialSegmentSize(text);
+		if (idx == text.length()) {
+			return Collections.singletonList(text);
+		}
+
+		return continueSplitting(text, idx);
+	}
+
+	private static int initialSegmentSize(String text) {
+		final int length = text.length();
+			int idx = 0;
+			while (idx < length) {
+				char currentChar = text.charAt(idx);
+				if (currentChar == '\r' || currentChar == '\n') {
+					break;
+				}
+				idx++;
+			}
+
+		return idx;
+	}
+
+	private List<String> continueSplitting(String text, int idx) {
+		final int length = text.length();
+		int nextLineOffset = 0;
+
+		final List<String> result = new ArrayList<String>(5);
+		while (idx < length) {
+			char currentChar = text.charAt(idx);
+			// check for \r or \r\n
+			if (currentChar == '\r') {
+				int delimiterLength = 1;
+				if (idx + 1 < length && text.charAt(idx + 1) == '\n') {
+					delimiterLength++;
+					idx++;
+				}
+				int lineLength = idx - delimiterLength - nextLineOffset + 1;
+				result.add(text.substring(nextLineOffset, nextLineOffset + lineLength));
+				result.add(lineDelimiter);
+				nextLineOffset = idx + 1;
+			} else if (currentChar == '\n') {
+				int lineLength = idx - nextLineOffset;
+				result.add(text.substring(nextLineOffset, nextLineOffset + lineLength));
+				result.add(lineDelimiter);
+				nextLineOffset = idx + 1;
+			}
+			idx++;
+		}
+		if (nextLineOffset != length) {
+			int lineLength = length - nextLineOffset;
+			result.add(text.substring(nextLineOffset, nextLineOffset + lineLength));
+		}
+		return result;
+	}
+
+	/**
+	 * Decorates an existing {@link StringConcatenation} as a {@link TargetStringConcatenation}.
+	 * It maintains the index at which new elements should inserted into the existing concatenation.
+	 * 
+	 * @noextend This class is not intended to be subclassed by clients.
+	 * @noinstantiate This class is not intended to be instantiated by clients.
+	 */
+	private static class SimpleTarget implements StringConcatenationClient.TargetStringConcatenation {
+
+		private final StringConcatenation target;
+		private final int offsetFixup;
+
+		private SimpleTarget(StringConcatenation target, int index) {
+			this.target = target;
+			this.offsetFixup = target.segments.size() - index;
+		}
+
+		@Override
+		public int length() {
+			return target.length();
+		}
+
+		@Override
+		public char charAt(int index) {
+			return target.charAt(index);
+		}
+
+		@Override
+		public CharSequence subSequence(int start, int end) {
+			return target.subSequence(start, end);
+		}
+
+		@Override
+		public void newLineIfNotEmpty() {
+			target.newLineIfNotEmpty();
+		}
+
+		@Override
+		public void newLine() {
+			target.newLine();
+		}
+
+		@Override
+		public void appendImmediate(Object object, String indentation) {
+			target.appendImmediate(object, indentation);
+		}
+
+		@Override
+		public void append(Object object, String indentation) {
+			if (offsetFixup == 0)
+				target.append(object, indentation);
+			else
+				target.append(object, indentation, target.segments.size() - offsetFixup);
+		}
+
+		@Override
+		public void append(Object object) {
+			target.append(object, target.segments.size() - offsetFixup);
+		}
+
+	}
+
+	/**
+	 * Decorates an existing {@link StringConcatenation} as a {@link TargetStringConcatenation}.
+	 * This implementation keeps track of the current indentation at the position where
+	 * the clients should write into the decorated {@link StringConcatenation}.
+	 * 
+	 * @noextend This class is not intended to be subclassed by clients.
+	 * @noinstantiate This class is not intended to be instantiated by clients.
+	 */
+	private static class IndentedTarget extends SimpleTarget {
+
+		private final String indentation;
+
+		private IndentedTarget(StringConcatenation target, String indentation, int index) {
+			super(target, index);
+			this.indentation = indentation;
+		}
+
+		@Override
+		public void newLineIfNotEmpty() {
+			super.newLineIfNotEmpty();
+			super.append(indentation);
+		}
+
+		@Override
+		public void newLine() {
+			super.newLine();
+			super.append(indentation);
+		}
+
+		@Override
+		public void appendImmediate(Object object, String indentation) {
+			super.appendImmediate(object, this.indentation + indentation);
+		}
+
+		@Override
+		public void append(Object object, String indentation) {
+			super.append(object, this.indentation + indentation);
+		}
+
+		@Override
+		public void append(Object object) {
+			super.append(object, indentation);
+		}
+	}
+}
diff --git a/java/org/eclipse/xtend2/lib/StringConcatenationClient.java b/java/org/eclipse/xtend2/lib/StringConcatenationClient.java
new file mode 100644
index 0000000..3f24c2a
--- /dev/null
+++ b/java/org/eclipse/xtend2/lib/StringConcatenationClient.java
@@ -0,0 +1,108 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend2.lib;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * A callback object that allows to reuse an existing {@link StringConcatenation}
+ * to append content to it. This puts clients into the position that they can
+ * fully control the used instance, e.g. they can use a custom line delimiter
+ * or override {@link StringConcatenation#getStringRepresentation(Object)}.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @since 2.5
+ */
+/*
+ * This is deliberately modeled as an abstract class without abstract methods
+ * to allow for better interaction with overloaded methods that accept functional
+ * types.
+ */
+@GwtCompatible
+public abstract class StringConcatenationClient {
+	
+	/**
+	 * Implementors have to override this method and feed the given
+	 * target instance.
+	 * 
+	 * @param target the {@link TargetStringConcatenation} to-append-to. Never <code>null</code>.
+	 */
+	protected void appendTo(TargetStringConcatenation target) {
+		throw new UnsupportedOperationException("Clients have to override this.");
+	}
+	
+	/**
+	 * Delegates to {@link #appendTo(TargetStringConcatenation)} to make it publicly accessible.
+	 * 
+	 * @param client
+	 *            the {@link StringConcatenationClient} on which {@link #appendTo(TargetStringConcatenation)} is
+	 *            invoked.
+	 * @param target
+	 *            the {@link TargetStringConcatenation} to-append-to. Never <code>null</code>.
+	 * @since 2.10
+	 */
+	public static void appendTo(StringConcatenationClient client, TargetStringConcatenation target) {
+		client.appendTo(target);
+	}
+
+	/**
+	 * A {@link TargetStringConcatenation} models the public interface of a
+	 * {@link StringConcatenation} so implementations of the {@link StringConcatenationClient}
+	 * can append their content properly.
+	 * 
+	 * @since 2.5
+	 */
+	public interface TargetStringConcatenation extends CharSequence {
+
+		/**
+		 * Add a newline to this sequence according to the configured lineDelimiter if the last line contains
+		 * something besides whitespace.
+		 */
+		void newLineIfNotEmpty();
+
+		/**
+		 * Add a newline to this sequence according to the configured lineDelimiter.
+		 */
+		void newLine();
+
+		/**
+		 * Add the string representation of the given object to this sequence immediately. That is, all the trailing
+		 * whitespace of this sequence will be ignored and the string is appended directly after the last segment that
+		 * contains something besides whitespace. The given indentation will be prepended to each line except the first one
+		 * if the object has a multi-line string representation.
+		 * 
+		 * @param object
+		 *            the to-be-appended object.
+		 * @param indentation
+		 *            the indentation string that should be prepended. May not be <code>null</code>.
+		 */
+		void appendImmediate(Object object, String indentation);
+
+		/**
+		 * Add the string representation of the given object to this sequence. The given indentation will be prepended to
+		 * each line except the first one if the object has a multi-line string representation.
+		 * 
+		 * @param object
+		 *            the appended object.
+		 * @param indentation
+		 *            the indentation string that should be prepended. May not be <code>null</code>.
+		 */
+		void append(Object object, String indentation);
+
+		/**
+		 * Append the string representation of the given object to this sequence. Does nothing if the object is
+		 * <code>null</code>.
+		 * 
+		 * @param object
+		 *            the to-be-appended object.
+		 */
+		void append(Object object);
+
+	}
+}
diff --git a/java/org/eclipse/xtend2/lib/WhitespaceMatcher.java b/java/org/eclipse/xtend2/lib/WhitespaceMatcher.java
new file mode 100644
index 0000000..c26418d
--- /dev/null
+++ b/java/org/eclipse/xtend2/lib/WhitespaceMatcher.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * Copyright (c) 2014 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtend2.lib;
+
+import com.google.common.annotations.GwtCompatible;
+
+/*
+ * On GWT we use Character.isSpace instead
+ */
+@GwtCompatible(emulated = true)
+class WhitespaceMatcher {
+	public static boolean isWhitespace(char c) {
+		return Character.isWhitespace(c);
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ArrayExtensions.java b/java/org/eclipse/xtext/xbase/lib/ArrayExtensions.java
new file mode 100644
index 0000000..27f20aa
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ArrayExtensions.java
@@ -0,0 +1,1315 @@
+/*******************************************************************************
+ * Copyright (c) 2013, 2020 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtext.xbase.lib;
+
+import java.util.Objects;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+/**
+ * An extension library for arrays, to be used with Xtend. It allows to use an array without converting it to a list
+ * first.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * @author Stephane Galland - Add operations on 2-dimension arrays.
+ * @since 2.4
+ */
+@GwtCompatible
+public class ArrayExtensions {
+
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 * @since 2.4
+	 */
+	@Inline("$1[$2] = $3")
+	public static <T, E extends T> T set(T[] array, int index, E value) {
+		array[index] = value;
+		return value;
+	}
+
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static <T> T get(T[] array, int index) {
+		return array[index];
+	}
+
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static <T> T[] clone(T[] array) {
+		return array.clone();
+	}
+
+	// BEGIN generated code
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(Object[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(Object[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(Object[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Returns whether the array contains the given element.
+	 * 
+	 * More formally, returns <tt>true</tt> if and only if this array contains
+	 * at least one element <tt>e</tt> such that
+	 * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+	 *
+	 * @param array 
+	 * 			the array to test
+	 * @param o 
+	 * 			element whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(Object[] array, Object o) {
+		for (int i = 0; i < array.length; i++) {
+			if (Objects.equals(array[i], o)) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static boolean get(boolean[] array, int index) {
+		return array[index];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 */
+	@Inline("$1[$2] = $3")
+	public static boolean set(boolean[] array, int index, boolean value) {
+		array[index] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(boolean[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(boolean[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(boolean[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static boolean[] clone(boolean[] array) {
+		return array.clone();
+	}
+	
+	/**
+	 * Returns whether the array contains the given value. More formally,
+	 * returns <tt>true</tt> if and only if this array contains at least one
+	 * element <tt>e</tt> such that <tt>value==e</tt>.
+	 *
+	 * @param array 
+	 * 			the array to test
+	 * @param value 
+	 * 			value whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(boolean[] array, boolean value) {
+		for (int i = 0; i < array.length; i++) {
+			if (array[i] == value) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static double get(double[] array, int index) {
+		return array[index];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 */
+	@Inline("$1[$2] = $3")
+	public static double set(double[] array, int index, double value) {
+		array[index] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(double[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(double[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(double[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static double[] clone(double[] array) {
+		return array.clone();
+	}
+	
+	/**
+	 * Returns whether the array contains the given value.
+	 * 
+	 * More formally, returns <tt>true</tt> if and only if this array contains
+	 * at least one element <tt>e</tt> such that
+	 * <tt>java.lang.Double.compare(o,&nbsp;e)&nbsp;==&nbsp;0)</tt>.
+	 * 
+	 * @param array 
+	 * 			the array to test
+	 * @param value 
+	 * 			value whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(double[] array, double value) {
+		for (int i = 0; i < array.length; i++) {
+			if (Double.compare(array[i], value) == 0) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static float get(float[] array, int index) {
+		return array[index];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 */
+	@Inline("$1[$2] = $3")
+	public static float set(float[] array, int index, float value) {
+		array[index] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(float[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(float[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(float[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static float[] clone(float[] array) {
+		return array.clone();
+	}
+	
+	/**
+	 * Returns whether the array contains the given value.
+	 * 
+	 * More formally, returns <tt>true</tt> if and only if this array contains
+	 * at least one element <tt>e</tt> such that
+	 * <tt>java.lang.Float.compare(o,&nbsp;e)&nbsp;==&nbsp;0)</tt>.
+	 *
+	 * @param array 
+	 * 			the array to test
+	 * @param value 
+	 * 			value whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(float[] array, float value) {
+		for (int i = 0; i < array.length; i++) {
+			if (Float.compare(array[i], value) == 0) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static long get(long[] array, int index) {
+		return array[index];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 */
+	@Inline("$1[$2] = $3")
+	public static long set(long[] array, int index, long value) {
+		array[index] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(long[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(long[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(long[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static long[] clone(long[] array) {
+		return array.clone();
+	}
+	
+	/**
+	 * Returns whether the array contains the given value.
+	 * 
+	 * More formally, returns <tt>true</tt> if and only if this array contains
+	 * at least one element <tt>e</tt> such that
+	 * <tt>(value&nbsp;==&nbsp;e)</tt>.
+	 *
+	 * @param array 
+	 * 			the array to test
+	 * @param value 
+	 * 			element whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(long[] array, long value) {
+		for (int i = 0; i < array.length; i++) {
+			if (array[i] == value) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static int get(int[] array, int index) {
+		return array[index];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 */
+	@Inline("$1[$2] = $3")
+	public static int set(int[] array, int index, int value) {
+		array[index] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(int[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(int[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(int[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static int[] clone(int[] array) {
+		return array.clone();
+	}
+	
+	/**
+	 * Returns whether the array contains the given value.
+	 * 
+	 * More formally, returns <tt>true</tt> if and only if this array contains
+	 * at least one element <tt>e</tt> such that
+	 * <tt>(value&nbsp;==&nbsp;e)</tt>.
+	 *
+	 * @param array 
+	 * 			the array to test
+	 * @param value 
+	 * 			value whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(int[] array, int value) {
+		for (int i = 0; i < array.length; i++) {
+			if (array[i] == value) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static char get(char[] array, int index) {
+		return array[index];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 */
+	@Inline("$1[$2] = $3")
+	public static char set(char[] array, int index, char value) {
+		array[index] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(char[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(char[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(char[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static char[] clone(char[] array) {
+		return array.clone();
+	}
+	
+	/**
+	 * Returns whether the array contains the given value.
+	 * 
+	 * More formally, returns <tt>true</tt> if and only if this array contains
+	 * at least one element <tt>e</tt> such that
+	 * <tt>(value&nbsp;==&nbsp;e)</tt>.
+	 *
+	 * @param array 
+	 * 			the array to test
+	 * @param value 
+	 * 			value whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(char[] array, char value) {
+		for (int i = 0; i < array.length; i++) {
+			if (array[i] == value) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static short get(short[] array, int index) {
+		return array[index];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 */
+	@Inline("$1[$2] = $3")
+	public static short set(short[] array, int index, short value) {
+		array[index] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(short[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(short[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(short[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static short[] clone(short[] array) {
+		return array.clone();
+	}
+	
+	/**
+	 * Returns whether the array contains the given value.
+	 * 
+	 * More formally, returns <tt>true</tt> if and only if this array contains
+	 * at least one element <tt>e</tt> such that
+	 * <tt>(value&nbsp;==&nbsp;e)</tt>.
+	 *
+	 * @param array 
+	 * 			the array to test
+	 * @param value 
+	 * 			value whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(short[] array, short value) {
+		for (int i = 0; i < array.length; i++) {
+			if (array[i] == value) {
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index
+	 * @return the value at the given index
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static byte get(byte[] array, int index) {
+		return array[index];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index
+	 *            the index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 */
+	@Inline("$1[$2] = $3")
+	public static byte set(byte[] array, int index, byte value) {
+		array[index] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @return the length of the given array
+	 */
+	@Pure
+	@Inline("$1.length")
+	public static int length(byte[] array) {
+		return array.length;
+	}
+	
+	/**
+	 * Returns a hash code value for the given array.
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the hash code
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.hashCode()")
+	public static int hashCode(byte[] array) {
+		return array.hashCode();
+	}
+	
+	/**
+	 * Returns whether the array and the given other object are identical.
+	 *
+	 * Delegates to {@link Object#equals(Object)}
+	 * 
+	 * @param array
+	 *            the array
+	 * @param other
+	 *            the other element to compare to
+	 * @return whether the two given argument are identical 
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.equals($2)")
+	public static boolean equals(byte[] array, Object other) {
+		return array.equals(other);
+	}
+	
+	/**
+	 * Clones the array. @see {@link Object#clone}
+	 * 
+	 * @param array
+	 *            the array
+	 * @return the cloned array
+	 * @since 2.5
+	 */
+	@Pure
+	@Inline("$1.clone()")
+	@GwtIncompatible("clone")
+	public static byte[] clone(byte[] array) {
+		return array.clone();
+	}
+	
+	/**
+	 * Returns whether the array contains the given value.
+	 * 
+	 * More formally, returns <tt>true</tt> if and only if this array contains
+	 * at least one element <tt>e</tt> such that
+	 * <tt>(value&nbsp;==&nbsp;e)</tt>.
+	 *
+	 * @param array 
+	 * 			the array to test
+	 * @param value 
+	 * 			value whose presence in this array is to be tested
+	 * @return <tt>true</tt> if this array contains the specified element
+	 */
+	@Pure
+	public static boolean contains(byte[] array, byte value) {
+		for (int i = 0; i < array.length; i++) {
+			if (array[i] == value) {
+				return true;
+			}
+		}
+		return false;
+	}
+// END generated code
+
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the second index
+	 * @return the value at the given index
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2][$3]")
+	public static <T> T get(T[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given indexes
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static <T, E extends T> T set(T[][] array, int index0, int index1, E value) {
+		array[index0][index1] = value;
+		return value;
+	}
+
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the second index
+	 * @return the value at the given indexes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2][$3]")
+	public static boolean get(boolean[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given indexes
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static boolean set(boolean[][] array, int index0, int index1, boolean value) {
+		array[index0][index1] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the second index
+	 * @return the value at the given indexes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2][$3]")
+	public static double get(double[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given indexex
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static double set(double[][] array, int index0, int index1, double value) {
+		array[index0][index1] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the first index
+	 * @return the value at the given indexes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2][$3]")
+	public static float get(float[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given indexes
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static float set(float[][] array, int index0, int index1, float value) {
+		array[index0][index1] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the second index
+	 * @return the value at the given indexes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2][$3]")
+	public static long get(long[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given indexes
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static long set(long[][] array, int index0, int index1, long value) {
+		array[index0][index1] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the second index
+	 * @return the value at the given indexes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2]")
+	public static int get(int[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given index
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static int set(int[][] array, int index0, int index1, int value) {
+		array[index0][index1] = value;
+		return value;
+	}
+		
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the second index
+	 * @return the value at the given indexes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2][$3]")
+	public static char get(char[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given indexes
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static char set(char[][] array, int index0, int index1, char value) {
+		array[index0][index1] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the second index
+	 * @return the value at the given indexes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2][$3]")
+	public static short get(short[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given indexes
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static short set(short[][] array, int index0, int index1, short value) {
+		array[index0][index1] = value;
+		return value;
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index
+	 * @param index1
+	 *            the second index
+	 * @return the value at the given indexes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("$1[$2][$3]")
+	public static byte get(byte[][] array, int index0, int index1) {
+		return array[index0][index1];
+	}
+	
+	/**
+	 * @param array
+	 *            the array
+	 * @param index0
+	 *            the first index the value should be set at
+	 * @param index1
+	 *            the second index the value should be set at
+	 * @param value
+	 *            the value to set at the given indexes
+	 * @return the new value
+	 * @since 2.16
+	 */
+	@Inline("$1[$2][$3] = $4")
+	public static byte set(byte[][] array, int index0, int index1, byte value) {
+		array[index0][index1] = value;
+		return value;
+	}
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ArrayLiterals.java b/java/org/eclipse/xtext/xbase/lib/ArrayLiterals.java
new file mode 100644
index 0000000..f3d149f
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ArrayLiterals.java
@@ -0,0 +1,259 @@
+/*******************************************************************************
+ * Copyright (c) 2013 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtext.xbase.lib;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * Factory methods for arrays.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * @author Stephane Galland - Add operations on 2-dimension arrays.
+ * @since 2.4
+ */
+@GwtCompatible
+public class ArrayLiterals {
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new $4[$1][$2]")
+	public static <T> T[][] newArrayOfSize(int size0, int size1) {
+		throw new UnsupportedOperationException(
+				"This method relies on the inlined compilation (see @Inline annotation), and cannot be used from Java or with an uncustomized interpreter."); //$NON-NLS-1$
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new $3[$1]")
+	public static <T> T[] newArrayOfSize(int size) {
+		throw new UnsupportedOperationException(
+				"This method relies on the inlined compilation (see @Inline annotation), and cannot be used from Java or with an uncustomized interpreter.");
+	}
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new char[$1][$2]")
+	public static char[][] newCharArrayOfSize(int size0, int size1) {
+		return new char[size0][size1];
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new char[$1]")
+	public static char[] newCharArrayOfSize(int size) {
+		return new char[size];
+	}
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new int[$1][$2]")
+	public static int[][] newIntArrayOfSize(int size0, int size1) {
+		return new int[size0][size1];
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new int[$1]")
+	public static int[] newIntArrayOfSize(int size) {
+		return new int[size];
+	}
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new boolean[$1][$2]")
+	public static boolean[][] newBooleanArrayOfSize(int size0, int size1) {
+		return new boolean[size0][size1];
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new boolean[$1]")
+	public static boolean[] newBooleanArrayOfSize(int size) {
+		return new boolean[size];
+	}
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new short[$1][$2]")
+	public static short[][] newShortArrayOfSize(int size0, int size1) {
+		return new short[size0][size1];
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new short[$1]")
+	public static short[] newShortArrayOfSize(int size) {
+		return new short[size];
+	}
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new long[$1][$2]")
+	public static long[][] newLongArrayOfSize(int size0, int size1) {
+		return new long[size0][size1];
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new long[$1]")
+	public static long[] newLongArrayOfSize(int size) {
+		return new long[size];
+	}
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new float[$1][$2]")
+	public static float[][] newFloatArrayOfSize(int size0, int size1) {
+		return new float[size0][size1];
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new float[$1]")
+	public static float[] newFloatArrayOfSize(int size) {
+		return new float[size];
+	}
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new double[$1][$2]")
+	public static double[][] newDoubleArrayOfSize(int size0, int size1) {
+		return new double[size0][size1];
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new double[$1]")
+	public static double[] newDoubleArrayOfSize(int size) {
+		return new double[size];
+	}
+
+
+	/**
+	 * @param size0
+	 *            the first size for the array to be created
+	 * @param size1
+	 *            the second size for the array to be created
+	 * @return an array of the given sizes
+	 * @since 2.16
+	 */
+	@Pure
+	@Inline("new byte[$1][$2]")
+	public static byte[][] newByteArrayOfSize(int size0, int size1) {
+		return new byte[size0][size1];
+	}
+
+	/**
+	 * @param size
+	 *            the size for the array to be created
+	 * @return an array of the given size
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline("new byte[$1]")
+	public static byte[] newByteArrayOfSize(int size) {
+		return new byte[size];
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/BigDecimalExtensions.java b/java/org/eclipse/xtext/xbase/lib/BigDecimalExtensions.java
new file mode 100644
index 0000000..6ff3997
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/BigDecimalExtensions.java
@@ -0,0 +1,123 @@
+/*******************************************************************************
+ * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtext.xbase.lib;
+
+import java.math.BigDecimal;
+import java.math.MathContext;
+
+import com.google.common.annotations.GwtCompatible;
+
+
+/**
+ * This is an extension library for {@link BigDecimal big decimal numbers}.
+ * 
+ * @author Jan Koehnlein - Initial contribution and API
+ */
+@GwtCompatible public class BigDecimalExtensions {
+
+	/**
+	 * The unary <code>minus</code> operator. 
+	 * 
+	 * @param a
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @return <code>-a</code>
+	 * @throws NullPointerException
+	 *             if {@code a} is <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$1.negate()")
+	public static BigDecimal operator_minus(BigDecimal a) {
+		return a.negate();
+	}
+
+	/**
+	 * The binary <code>plus</code> operator. 
+	 * 
+	 * @param a
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @param b
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @return <code>a.add(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$1.add($2)")
+	public static BigDecimal operator_plus(BigDecimal a, BigDecimal b) {
+		return a.add(b);
+	}
+
+	/**
+	 * The binary <code>minus</code> operator.
+	 * 
+	 * @param a
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @param b
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @return <code>a.subtract(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$1.subtract($2)")
+	public static BigDecimal operator_minus(BigDecimal a, BigDecimal b) {
+		return a.subtract(b);
+	}
+
+	/**
+	 * The <code>power</code> operator.
+	 * 
+	 * @param a
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @param exponent
+	 *            the exponent.
+	 * @return <code>a.pow(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} is <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$1.pow($2)")
+	public static BigDecimal operator_power(BigDecimal a, int exponent) {
+		return a.pow(exponent);
+	}
+
+	/**
+	 * The binary <code>times</code> operator. 
+	 * 
+	 * @param a
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @param b
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @return <code>a.multiply(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$1.multiply($2)")
+	public static BigDecimal operator_multiply(BigDecimal a, BigDecimal b) {
+		return a.multiply(b);
+	}
+
+	/**
+	 * The binary <code>divide</code> operator. 
+	 * 
+	 * @param a
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @param b
+	 *            a BigDecimal. May not be <code>null</code>.
+	 * @return <code>a.divide(b, MathContext.DECIMAL128)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$1.divide($2, $3.DECIMAL128)", imported=MathContext.class)
+	public static BigDecimal operator_divide(BigDecimal a, BigDecimal b) {
+		return a.divide(b, MathContext.DECIMAL128);
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/BigIntegerExtensions.java b/java/org/eclipse/xtext/xbase/lib/BigIntegerExtensions.java
new file mode 100644
index 0000000..f45e1a1
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/BigIntegerExtensions.java
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtext.xbase.lib;
+
+import java.math.BigInteger;
+
+import com.google.common.annotations.GwtCompatible;
+
+
+/**
+ * This is an extension library for {@link BigInteger big integral numbers}.
+ * 
+ * @author Jan Koehnlein - Initial contribution and API
+ */
+@GwtCompatible public class BigIntegerExtensions {
+
+	/**
+	 * The unary <code>minus</code> operator.
+	 * 
+	 * @param a
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @return <code>-a</code>
+	 * @throws NullPointerException
+	 *             if {@code a} is <code>null</code>.
+	 */
+	@Inline(value="$1.negate()")
+	@Pure
+	public static BigInteger operator_minus(BigInteger a) {
+		return a.negate();
+	}
+
+	/**
+	 * The binary <code>plus</code> operator.
+	 * 
+	 * @param a
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @param b
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @return <code>a.add(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Inline(value="$1.add($2)")
+	@Pure
+	public static BigInteger operator_plus(BigInteger a, BigInteger b) {
+		return a.add(b);
+	}
+
+	/**
+	 * The binary <code>minus</code> operator.
+	 * 
+	 * @param a
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @param b
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @return <code>a.subtract(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Inline(value="$1.subtract($2)")
+	@Pure
+	public static BigInteger operator_minus(BigInteger a, BigInteger b) {
+		return a.subtract(b);
+	}
+
+	/**
+	 * The <code>power</code> operator.
+	 * 
+	 * @param a
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @param exponent
+	 *            the exponent.
+	 * @return <code>a.pow(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} <code>null</code>.
+	 */
+	@Inline(value="$1.pow($2)")
+	@Pure
+	public static BigInteger operator_power(BigInteger a, int exponent) {
+		return a.pow(exponent);
+	}
+
+	/**
+	 * The binary <code>times</code> operator.
+	 * 
+	 * @param a
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @param b
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @return <code>a.multiply(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Inline(value="$1.multiply($2)")
+	@Pure
+	public static BigInteger operator_multiply(BigInteger a, BigInteger b) {
+		return a.multiply(b);
+	}
+
+	/**
+	 * The binary <code>divide</code> operator. 
+	 * 
+	 * @param a
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @param b
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @return <code>a.divide(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Inline(value="$1.divide($2)")
+	@Pure
+	public static BigInteger operator_divide(BigInteger a, BigInteger b) {
+		return a.divide(b);
+	}
+
+	/**
+	 * The binary <code>modulo</code> operator. 
+	 * 
+	 * @param a
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @param b
+	 *            a BigInteger. May not be <code>null</code>.
+	 * @return <code>a.mod(b)</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Inline(value="$1.mod($2)")
+	@Pure
+	public static BigInteger operator_modulo(BigInteger a, BigInteger b) {
+		return a.mod(b);
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/BooleanExtensions.java b/java/org/eclipse/xtext/xbase/lib/BooleanExtensions.java
new file mode 100644
index 0000000..cb1f2ed
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/BooleanExtensions.java
@@ -0,0 +1,177 @@
+/*******************************************************************************
+ * Copyright (c) 2011 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtext.xbase.lib;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.primitives.Booleans;
+
+
+/**
+ * This is an extension library for {@link Boolean booleans}.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ */
+@GwtCompatible public class BooleanExtensions {
+
+	/**
+	 * The logical <code>and</code> (conjunction). This is the equivalent to the java <code>&amp;&amp;</code> operator.
+	 * 
+	 * @param a
+	 *            a boolean value.
+	 * @param b
+	 *            another boolean value.
+	 * @return <code>a &amp;&amp; b</code>
+	 */
+	@Pure
+	@Inline(value="($1 && $2)", constantExpression=true)
+	public static boolean operator_and(boolean a, boolean b) {
+		return a && b;
+	}
+
+	/**
+	 * A logical <code>or</code> (disjunction). This is the equivalent to the java <code>||</code> operator.
+	 * 
+	 * @param a
+	 *            a boolean value.
+	 * @param b
+	 *            another boolean value.
+	 * @return <code>a || b</code>
+	 */
+	@Pure
+	@Inline(value="($1 || $2)", constantExpression=true)
+	public static boolean operator_or(boolean a, boolean b) {
+		return a || b;
+	}
+
+	/**
+	 * The logical <code>not</code> (negation). This is the equivalent to the java <code>!</code> operator.
+	 * 
+	 * @param b
+	 *            a boolean value.
+	 * @return <code>!b</code>
+	 */
+	@Pure
+	@Inline(value="(!$1)", constantExpression=true)
+	public static boolean operator_not(boolean b) {
+		return !b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the java <code>==</code> operator.
+	 * 
+	 * @param a
+	 *            an boolean.
+	 * @param b
+	 *            an boolean.
+	 * @return <code>a==b</code>
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(boolean a, boolean b) {
+		return a == b;
+	}
+
+	/**
+	 * The binary <code>not equals</code> operator. This is the equivalent to the java <code>!=</code> operator.
+	 * 
+	 * @param a
+	 *            an boolean.
+	 * @param b
+	 *            an boolean.
+	 * @return <code>a!=b</code>
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(boolean a, boolean b) {
+		return a != b;
+	}
+
+	/**
+	 * A logical <code>xor</code>. This is the equivalent to the java <code>^</code> operator.
+	 * 
+	 * @param a
+	 *            a boolean value.
+	 * @param b
+	 *            another boolean value.
+	 * @return <code>a ^ b</code>
+	 */
+	@Pure
+	@Inline("($1 ^ $2)")
+	public static boolean xor(boolean a, boolean b) {
+		return a ^ b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator for boolean values.
+	 * {@code false} is considered less than {@code true}.
+	 * 
+	 * @see Boolean#compareTo(Boolean)
+	 * @see Booleans#compare(boolean, boolean)
+	 * @param a  a boolean.
+	 * @param b  another boolean.
+	 * @return   <code>Booleans.compare(a, b)&lt;0</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value = "($3.compare($1, $2) < 0)", imported = Booleans.class)
+	public static boolean operator_lessThan(boolean a, boolean b) {
+		return Booleans.compare(a, b) < 0;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator for boolean values.
+	 * {@code false} is considered less than {@code true}.
+	 * 
+	 * @see Boolean#compareTo(Boolean)
+	 * @see Booleans#compare(boolean, boolean)
+	 * @param a  a boolean.
+	 * @param b  another boolean.
+	 * @return   <code>Booleans.compare(a, b)&lt;=0</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value = "($3.compare($1, $2) <= 0)", imported = Booleans.class)
+	public static boolean operator_lessEqualsThan(boolean a, boolean b) {
+		return Booleans.compare(a, b) <= 0;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator for boolean values.
+	 * {@code false} is considered less than {@code true}.
+	 * 
+	 * @see Boolean#compareTo(Boolean)
+	 * @see Booleans#compare(boolean, boolean)
+	 * @param a  a boolean.
+	 * @param b  another boolean.
+	 * @return   <code>Booleans.compare(a, b)&gt;0</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value = "($3.compare($1, $2) > 0)", imported = Booleans.class)
+	public static boolean operator_greaterThan(boolean a, boolean b) {
+		return Booleans.compare(a, b) > 0;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator for boolean values.
+	 * {@code false} is considered less than {@code true}.
+	 * 
+	 * @see Boolean#compareTo(Boolean)
+	 * @see Booleans#compare(boolean, boolean)
+	 * @param a  a boolean.
+	 * @param b  another boolean.
+	 * @return   <code>Booleans.compare(a, b)&gt;=0</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value = "($3.compare($1, $2) >= 0)", imported = Booleans.class)
+	public static boolean operator_greaterEqualsThan(boolean a, boolean b) {
+		return Booleans.compare(a, b) >= 0;
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ByteExtensions.java b/java/org/eclipse/xtext/xbase/lib/ByteExtensions.java
new file mode 100644
index 0000000..f16d647
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ByteExtensions.java
@@ -0,0 +1,1469 @@
+/*******************************************************************************
+ * Copyright (c) 2012 itemis AG (http://www.itemis.eu) and others.
+ * This program and the accompanying materials are made available under the
+ * terms of the Eclipse Public License 2.0 which is available at
+ * http://www.eclipse.org/legal/epl-2.0.
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *******************************************************************************/
+package org.eclipse.xtext.xbase.lib;
+
+import com.google.common.annotations.GwtCompatible;
+
+
+/**
+ * This is an extension library for {@link Byte} numbers.
+ * 
+ * @author Jan Koehnlein - Code generator
+ * @since 2.3
+ */
+@GwtCompatible public class ByteExtensions {
+	// BEGIN generated code
+	/**
+	 * The unary <code>minus</code> operator. This is the equivalent to the Java's <code>-</code> function.
+	 * 
+	 * @param b  a byte.
+	 * @return   <code>-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="(-$1)", constantExpression=true)
+	public static int operator_minus(byte b) {
+		return -b;
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param b  a byte.
+	 * @return   <code>b--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static byte operator_minusMinus(byte b) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param b  a byte.
+	 * @return   <code>b--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static Byte operator_minusMinus(Byte b) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param b  a byte.
+	 * @return   <code>b++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static byte operator_plusPlus(byte b) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param b  a byte.
+	 * @return   <code>b++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static Byte operator_plusPlus(Byte b) {
+		throw new HardcodedInInterpreterException();
+	}
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(byte a, double b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(byte a, double b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(byte a, double b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(byte a, double b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(byte a, double b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(byte a, double b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(byte a, double b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(byte a, double b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(byte a, double b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(byte a, double b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(byte a, double b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>power</code> operator. This is the equivalent to the Java's <code>Math.pow()</code> function.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>Math.pow(a, b)</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="$3.pow($1, $2)", imported=Math.class)
+	public static double operator_power(byte a, double b) {
+		return Math.pow(a, b);
+	}
+	
+	/**
+	 * The <code>identity equals</code> operator. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(byte a, double b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a double.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(byte a, double b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(byte a, float b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(byte a, float b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(byte a, float b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(byte a, float b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(byte a, float b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(byte a, float b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(byte a, float b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(byte a, float b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(byte a, float b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(byte a, float b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(byte a, float b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>power</code> operator. This is the equivalent to the Java's <code>Math.pow()</code> function.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>Math.pow(a, b)</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="$3.pow($1, $2)", imported=Math.class)
+	public static double operator_power(byte a, float b) {
+		return Math.pow(a, b);
+	}
+	
+	/**
+	 * The <code>identity equals</code> operator. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(byte a, float b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a float.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(byte a, float b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(byte a, long b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(byte a, long b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(byte a, long b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(byte a, long b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(byte a, long b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(byte a, long b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(byte a, long b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(byte a, long b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(byte a, long b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(byte a, long b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(byte a, long b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>power</code> operator. This is the equivalent to the Java's <code>Math.pow()</code> function.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>Math.pow(a, b)</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="$3.pow($1, $2)", imported=Math.class)
+	public static double operator_power(byte a, long b) {
+		return Math.pow(a, b);
+	}
+	
+	/**
+	 * The <code>identity equals</code> operator. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(byte a, long b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a long.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(byte a, long b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(byte a, int b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(byte a, int b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(byte a, int b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(byte a, int b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(byte a, int b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(byte a, int b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(byte a, int b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(byte a, int b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(byte a, int b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(byte a, int b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(byte a, int b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>power</code> operator. This is the equivalent to the Java's <code>Math.pow()</code> function.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>Math.pow(a, b)</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="$3.pow($1, $2)", imported=Math.class)
+	public static double operator_power(byte a, int b) {
+		return Math.pow(a, b);
+	}
+	
+	/**
+	 * The <code>identity equals</code> operator. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(byte a, int b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  an integer.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(byte a, int b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(byte a, char b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(byte a, char b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(byte a, char b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(byte a, char b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(byte a, char b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(byte a, char b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(byte a, char b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(byte a, char b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(byte a, char b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(byte a, char b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(byte a, char b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>power</code> operator. This is the equivalent to the Java's <code>Math.pow()</code> function.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>Math.pow(a, b)</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="$3.pow($1, $2)", imported=Math.class)
+	public static double operator_power(byte a, char b) {
+		return Math.pow(a, b);
+	}
+	
+	/**
+	 * The <code>identity equals</code> operator. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(byte a, char b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a character.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(byte a, char b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(byte a, short b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(byte a, short b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(byte a, short b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(byte a, short b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(byte a, short b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(byte a, short b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(byte a, short b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(byte a, short b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(byte a, short b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(byte a, short b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(byte a, short b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>power</code> operator. This is the equivalent to the Java's <code>Math.pow()</code> function.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>Math.pow(a, b)</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="$3.pow($1, $2)", imported=Math.class)
+	public static double operator_power(byte a, short b) {
+		return Math.pow(a, b);
+	}
+	
+	/**
+	 * The <code>identity equals</code> operator. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(byte a, short b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a short.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(byte a, short b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a byte.
+	 * @param b  a byte.
+