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.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(byte a, byte 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 byte.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(byte a, byte 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 byte.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(byte a, byte 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 byte.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(byte a, byte 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 byte.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(byte a, byte 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 byte.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(byte a, byte 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 byte.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(byte a, byte 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 byte.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(byte a, byte 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 byte.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(byte a, byte 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 byte.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(byte a, byte 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 byte.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(byte a, byte 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 byte.
+	 * @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, byte 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 byte.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(byte a, byte 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 byte.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(byte a, byte b) {
+		return a != b;
+	}
+	
+	// END generated code
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/CharacterExtensions.java b/java/org/eclipse/xtext/xbase/lib/CharacterExtensions.java
new file mode 100644
index 0000000..1e47cc7
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/CharacterExtensions.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 Character} numbers.
+ * 
+ * @author Jan Koehnlein - Code generator
+ * @since 2.3
+ */
+@GwtCompatible public class CharacterExtensions {
+	// BEGIN generated code
+	/**
+	 * The unary <code>minus</code> operator. This is the equivalent to the Java's <code>-</code> function.
+	 * 
+	 * @param c  a character.
+	 * @return   <code>-c</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="(-$1)", constantExpression=true)
+	public static int operator_minus(char c) {
+		return -c;
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param c  a character.
+	 * @return   <code>c--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static char operator_minusMinus(char c) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param c  a character.
+	 * @return   <code>c--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static Character operator_minusMinus(Character c) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param c  a character.
+	 * @return   <code>c++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static char operator_plusPlus(char c) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param c  a character.
+	 * @return   <code>c++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static Character operator_plusPlus(Character c) {
+		throw new HardcodedInInterpreterException();
+	}
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a double.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(char 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 character.
+	 * @param b  a double.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(char 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 character.
+	 * @param b  a double.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(char 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 character.
+	 * @param b  a double.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(char 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 character.
+	 * @param b  a double.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a double.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(char 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 character.
+	 * @param b  a double.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a double.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(char 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 character.
+	 * @param b  a double.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(char 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 character.
+	 * @param b  a float.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(char 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 character.
+	 * @param b  a long.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(char 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 character.
+	 * @param b  an integer.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(char 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 character.
+	 * @param b  a character.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(char 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 character.
+	 * @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(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(char 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 character.
+	 * @param b  a short.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(char 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 character.
+	 * @param b  a byte.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(char a, byte b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(char a, byte b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(char a, byte b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(char a, byte b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(char a, byte b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(char a, byte b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(char a, byte b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(char a, byte b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(char a, byte b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(char a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(char a, byte 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 character.
+	 * @param b  a byte.
+	 * @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(char a, byte 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 character.
+	 * @param b  a byte.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(char a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a character.
+	 * @param b  a byte.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(char a, byte b) {
+		return a != b;
+	}
+	
+	// END generated code
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/CollectionExtensions.java b/java/org/eclipse/xtext/xbase/lib/CollectionExtensions.java
new file mode 100644
index 0000000..7bf01dd
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/CollectionExtensions.java
@@ -0,0 +1,320 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 2021 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.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.SortedSet;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedMap;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.Iterables;
+
+import static com.google.common.collect.Sets.*;
+
+/**
+ * This is an extension library for {@link Collection collections}.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * @author Sebastian Zarnekow
+ */
+@GwtCompatible public class CollectionExtensions {
+
+	/**
+	 * The operator mapping from {@code +=} to {@link Collection#add(Object)}. Returns <code>true</code> if the
+	 * collection changed due to this operation.
+	 * 
+	 * @param collection
+	 *            the to-be-changed collection. May not be <code>null</code>.
+	 * @param value
+	 *            the value that should be added to the collection.
+	 * @return <code>true</code> if the collection changed due to this operation.
+	 * @see Collection#add(Object)
+	 */
+	@Inline(value="$1.add($2)")
+	public static <E> boolean operator_add(Collection<? super E> collection, E value) {
+		return collection.add(value);
+	}
+
+	/**
+	 * The operator mapping from {@code +=} to {@link #addAll(Collection, Iterable)}. Returns <code>true</code> if the
+	 * collection changed due to this operation.
+	 * 
+	 * @param collection
+	 *            the to-be-changed collection. May not be <code>null</code>.
+	 * @param newElements
+	 *            elements to be inserted into the collection. May not be <code>null</code> but may contain
+	 *            <code>null</code> elements if the target collection supports <code>null</code> elements.
+	 * @return <code>true</code> if the collection changed due to this operation.
+	 * @see #addAll(Collection, Iterable)
+	 */
+	@Inline(value="$3.$4addAll($1, $2)", imported=Iterables.class)
+	public static <E> boolean operator_add(Collection<E> collection, Iterable<? extends E> newElements) {
+		return addAll(collection, newElements);
+	}
+
+	/**
+	 * The operator mapping from {@code -=} to {@link Collection#remove(Object)}. Returns <code>true</code> if the
+	 * collection changed due to this operation.
+	 * 
+	 * @param collection
+	 *            the to-be-changed collection. May not be <code>null</code>.
+	 * @param value
+	 *            the value that should be removed from the collection.
+	 * @return <code>true</code> if the collection changed due to this operation.
+	 * @see Collection#remove(Object)
+	 * @since 2.4
+	 */
+	@Inline(value="$1.remove($2)")
+	public static <E> boolean operator_remove(Collection<? super E> collection, E value) {
+		return collection.remove(value);
+	}
+
+	/**
+	 * The operator mapping from {@code -=} to {@link #removeAll(Collection, Collection)}. Returns <code>true</code> if the
+	 * collection changed due to this operation.
+	 * 
+	 * @param collection
+	 *            the to-be-changed collection. May not be <code>null</code>.
+	 * @param newElements
+	 *            elements to be removed from the collection. May not be <code>null</code> but may contain
+	 *            <code>null</code> elements if the target collection supports <code>null</code> elements.
+	 * @return <code>true</code> if the collection changed due to this operation.
+	 * @see #removeAll(Collection, Collection)
+	 * @since 2.4
+	 */
+	@Inline(value="$3.removeAll($1, $2)", imported=Iterables.class)
+	public static <E> boolean operator_remove(Collection<E> collection, Collection<? extends E> newElements) {
+		return removeAll(collection, newElements);
+	}
+
+	/**
+	 * Returns an unmodifiable view of the specified {@code list}.
+	 * 
+	 * @param list
+	 *            the list for which an unmodifiable view is to be returned. May not be <code>null</code>.
+	 * @return an unmodifiable view of the specified list.
+	 * @see Collections#unmodifiableList(List)
+	 */
+	@Inline(value="$2.$3unmodifiableList($1)", imported=Collections.class)
+	public static <T> List<T> unmodifiableView(List<? extends T> list) {
+		return Collections.unmodifiableList(list);
+	}
+
+	/**
+	 * Returns an unmodifiable view of the specified {@code collection}.
+	 * 
+	 * @param collection
+	 *            the collection for which an unmodifiable view is to be returned. May not be <code>null</code>.
+	 * @return an unmodifiable view of the specified collection.
+	 * @see Collections#unmodifiableCollection(Collection)
+	 */
+	@Inline(value="$2.$3unmodifiableCollection($1)", imported=Collections.class)
+	public static <T> Collection<T> unmodifiableView(Collection<? extends T> collection) {
+		return Collections.unmodifiableCollection(collection);
+	}
+
+	/**
+	 * Returns an unmodifiable view of the specified {@code set}.
+	 * 
+	 * @param set
+	 *            the set for which an unmodifiable view is to be returned. May not be <code>null</code>.
+	 * @return an unmodifiable view of the specified set.
+	 * @see Collections#unmodifiableSet(Set)
+	 */
+	@Inline(value="$2.$3unmodifiableSet($1)", imported=Collections.class)
+	public static <T> Set<T> unmodifiableView(Set<? extends T> set) {
+		return Collections.unmodifiableSet(set);
+	}
+
+	/**
+	 * Returns an unmodifiable view of the specified sorted {@code set}.
+	 * 
+	 * @param set
+	 *            the sorted set for which an unmodifiable view is to be returned. May not be <code>null</code>.
+	 * @return an unmodifiable view of the specified sorted set.
+	 * @see Collections#unmodifiableSortedSet(SortedSet)
+	 */
+	@Inline(value="$2.$3unmodifiableSortedSet($1)", imported=Collections.class)
+	public static <T> SortedSet<T> unmodifiableView(SortedSet<T> set) {
+		return Collections.unmodifiableSortedSet(set);
+	}
+
+	/**
+	 * Returns an unmodifiable view of the specified {@code map}.
+	 * 
+	 * @param map
+	 *            the map for which an unmodifiable view is to be returned. May not be <code>null</code>.
+	 * @return an unmodifiable view of the specified map.
+	 * @see Collections#unmodifiableMap(Map)
+	 */
+	@Inline(value="$2.$3unmodifiableMap($1)", imported=Collections.class)
+	public static <K, V> Map<K, V> unmodifiableView(Map<? extends K, ? extends V> map) {
+		return Collections.unmodifiableMap(map);
+	}
+
+	/**
+	 * Returns an unmodifiable view of the specified sorted {@code map}.
+	 * 
+	 * @param map
+	 *            the sorted map for which an unmodifiable view is to be returned. May not be <code>null</code>.
+	 * @return an unmodifiable view of the specified sorted map.
+	 * @see Collections#unmodifiableSortedMap(SortedMap)
+	 */
+	@Inline(value="$2.$3unmodifiableSortedMap($1)", imported=Collections.class)
+	public static <K, V> SortedMap<K, V> unmodifiableView(SortedMap<K, ? extends V> map) {
+		return Collections.unmodifiableSortedMap(map);
+	}
+
+	/**
+	 * Returns an immutable copy of the specified {@code list}.
+	 * 
+	 * @param list
+	 *            the list for which an immutable copy should be created. May not be <code>null</code>.
+	 * @return an immutable copy of the specified list.
+	 */
+	@Inline(value="$2.$3copyOf($1)", imported=ImmutableList.class)
+	public static <T> List<T> immutableCopy(List<? extends T> list) {
+		return ImmutableList.copyOf(list);
+	}
+
+	/**
+	 * Returns an immutable copy of the specified {@code set}.
+	 * 
+	 * @param set
+	 *            the set for which an immutable copy should be created. May not be <code>null</code>.
+	 * @return an immutable copy of the specified set.
+	 */
+	@Inline(value="$2.$3copyOf($1)", imported=ImmutableSet.class)
+	public static <T> Set<T> immutableCopy(Set<? extends T> set) {
+		return ImmutableSet.copyOf(set);
+	}
+
+	/**
+	 * Returns an immutable copy of the specified sorted {@code set}.
+	 * 
+	 * @param set
+	 *            the sorted set for which an immutable copy should be created. May not be <code>null</code>.
+	 * @return an immutable copy of the specified sorted set.
+	 */
+	@Inline(value="$2.$3copyOfSorted($1)", imported=ImmutableSortedSet.class)
+	public static <T> SortedSet<T> immutableCopy(SortedSet<T> set) {
+		return ImmutableSortedSet.copyOfSorted(set);
+	}
+
+	/**
+	 * Returns an immutable copy of the specified {@code map}.
+	 * 
+	 * @param map
+	 *            the map for which an immutable copy should be created. May not be <code>null</code>.
+	 * @return an immutable copy of the specified map.
+	 */
+	@Inline(value="$2.$3copyOf($1)", imported=ImmutableMap.class)
+	public static <K, V> Map<K, V> immutableCopy(Map<? extends K, ? extends V> map) {
+		return ImmutableMap.copyOf(map);
+	}
+
+	/**
+	 * Returns an immutable copy of the specified sorted {@code map}.
+	 * 
+	 * @param map
+	 *            the sorted map for which an immutable copy should be created. May not be <code>null</code>.
+	 * @return an immutable copy of the specified sorted map.
+	 */
+	@Inline(value="$2.$3copyOfSorted($1)", imported=ImmutableSortedMap.class)
+	public static <K, V> SortedMap<K, V> immutableCopy(SortedMap<K, ? extends V> map) {
+		return ImmutableSortedMap.copyOfSorted(map);
+	}
+
+	/**
+	 * Adds all of the specified elements to the specified collection.
+	 * 
+	 * @param collection
+	 *            the collection into which the {@code elements} are to be inserted. May not be <code>null</code>.
+	 * @param elements
+	 *            the elements to insert into the {@code collection}. May not be <code>null</code> but may contain
+	 *            <code>null</code> entries if the {@code collection} allows that.
+	 * @return <code>true</code> if the collection changed as a result of the call
+	 */
+	@SafeVarargs
+	public static <T> boolean addAll(Collection<? super T> collection, T... elements) {
+		return collection.addAll(Arrays.asList(elements));
+	}
+
+	/**
+	 * Adds all of the specified elements to the specified collection.
+	 * 
+	 * @param collection
+	 *            the collection into which the {@code elements} are to be inserted. May not be <code>null</code>.
+	 * @param elements
+	 *            the elements to insert into the {@code collection}. May not be <code>null</code> but may contain
+	 *            <code>null</code> entries if the {@code collection} allows that.
+	 * @return <code>true</code> if the collection changed as a result of the call
+	 */
+	@Inline(value="$3.$4addAll($1, $2)", imported=Iterables.class)
+	public static <T> boolean addAll(Collection<T> collection, Iterable<? extends T> elements) {
+		return Iterables.addAll(collection, elements);
+	}
+	
+	/**
+	 * Removes all of the specified elements from the specified collection.
+	 * 
+	 * @param collection
+	 *            the collection from which the {@code elements} are to be removed. May not be <code>null</code>.
+	 * @param elements
+	 *            the elements be remove from the {@code collection}. May not be <code>null</code> but may contain
+	 *            <code>null</code> entries if the {@code collection} allows that.
+	 * @return <code>true</code> if the collection changed as a result of the call
+	 * @since 2.4
+	 */
+	@SafeVarargs
+	public static <T> boolean removeAll(Collection<? super T> collection, T... elements) {
+		return collection.removeAll(Arrays.asList(elements));
+	}
+
+	/**
+	 * Removes all of the specified elements from the specified collection.
+	 *
+	 * @param collection
+	 *            the collection from which the {@code elements} are to be removed. May not be <code>null</code>.
+	 * @param elements
+	 *            the elements to remove from the {@code collection}. May not be <code>null</code> but may contain
+	 *            <code>null</code> entries if the {@code collection} allows that.
+	 * @return <code>true</code> if the collection changed as a result of the call
+	 * @since 2.4
+	 */
+	@Inline(value="$3.$4removeAll($1, $2)", imported=Iterables.class)
+	public static <T> boolean removeAll(Collection<T> collection, Collection<? extends T> elements) {
+		return Iterables.removeAll(collection, elements);
+	}
+
+	/**
+	 * Removes all of the specified elements from the specified collection.
+	 * 
+	 * @param collection
+	 *            the collection from which the {@code elements} are to be removed. May not be <code>null</code>.
+	 * @param elements
+	 *            the elements to remove from the {@code collection}. May not be <code>null</code> but may contain
+	 *            <code>null</code> entries if the {@code collection} allows that.
+	 * @return <code>true</code> if the collection changed as a result of the call
+	 * @since 2.4
+	 */
+	public static <T> boolean removeAll(Collection<T> collection, Iterable<? extends T> elements) {
+		return Iterables.removeAll(collection, newHashSet(elements));
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/CollectionLiterals.java b/java/org/eclipse/xtext/xbase/lib/CollectionLiterals.java
new file mode 100644
index 0000000..9a20632
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/CollectionLiterals.java
@@ -0,0 +1,402 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.xtext.xbase.lib;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.TreeSet;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.primitives.Ints;
+
+/**
+ * This is an extension library for {@link java.util.Collection collections}.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ */
+@GwtCompatible public class CollectionLiterals {
+
+	/**
+	 * Returns the empty, immutable list.
+	 * 
+	 * @return an empty, immutable list.
+	 * @see Collections#emptyList()
+	 */
+	@Pure
+	public static <T> List<T> emptyList() {
+		return Collections.emptyList();
+	}
+
+	/**
+	 * Returns the empty, immutable set.
+	 * 
+	 * @return an empty, immutable set.
+	 * @see Collections#emptySet()
+	 */
+	@Pure
+	public static <T> Set<T> emptySet() {
+		return Collections.emptySet();
+	}
+
+	/**
+	 * Returns the empty, immutable map.
+	 * 
+	 * @return an empty, immutable map.
+	 * @see Collections#emptyMap()
+	 */
+	@Pure
+	public static <K, V> Map<K, V> emptyMap() {
+		return Collections.emptyMap();
+	}
+
+	/**
+	 * Returns an immutable list containing the given elements, in order.
+	 * 
+	 * @param elements
+	 *            the elements that should be contained in the list. May not be <code>null</code> or contain any
+	 *            <code>null</code> values.
+	 * @return an immutable list containing the given elements.
+	 * @throws NullPointerException
+	 *             if {@code elements} or any of items in {@code elements} is <code>null</code>
+	 */
+	@Pure
+	@SafeVarargs
+	public static <T> List<T> newImmutableList(T... elements) {
+		return ImmutableList.copyOf(elements);
+	}
+
+	/**
+	 * Returns an immutable set containing the given elements. Repeated occurrences of an element (according to
+	 * {@link Object#equals}) after the first are ignored
+	 * 
+	 * @param elements
+	 *            the elements that should be contained in the set. May not be <code>null</code> or contain any
+	 *            <code>null</code> values.
+	 * @return an immutable set containing the given elements.
+	 * @throws NullPointerException
+	 *             if {@code elements} or any of items in {@code elements} is <code>null</code>
+	 */
+	@Pure
+	@SafeVarargs
+	public static <T> Set<T> newImmutableSet(T... elements) {
+		return ImmutableSet.copyOf(elements);
+	}
+
+	/**
+	 * Returns an immutable map containing the given entries. Repeated occurrences of a keys will cause an
+	 * {@link IllegalArgumentException}.
+	 * 
+	 * @param entries
+	 *            the entries that should be contained in the map. May not be <code>null</code> and may
+	 *            not contain any <code>null</code> keys or values.
+	 * @return an immutable map containing the given entries.
+	 * @throws NullPointerException
+	 *             if {@code entries} or any key or value in {@code entries} is <code>null</code>
+	 * @throws IllegalArgumentException
+	 *             if duplicate keys are contained in {@code entries}.
+	 */
+	@Pure
+	@SafeVarargs
+	public static <K, V> Map<K, V> newImmutableMap(Pair<? extends K, ? extends V>... entries) {
+		if (entries.length == 0)
+			return emptyMap();
+		ImmutableMap.Builder<K, V> builder = ImmutableMap.builder();
+		for (Pair<? extends K, ? extends V> entry : entries) {
+			builder.put(entry.getKey(), entry.getValue());
+		}
+		return builder.build();
+	}
+
+	/**
+	 * Creates an empty mutable {@link ArrayList} instance.
+	 * 
+	 * @return a new {@link ArrayList}
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <T> ArrayList<T> newArrayList() {
+		return new ArrayList<T>();
+	}
+
+	/**
+	 * Creates a mutable {@link ArrayList} instance containing the given initial elements.
+	 * 
+	 * @param initial
+	 *            the initial elements that the list should contain, in order. May not be <code>null</code> but may
+	 *            contain <code>null</code> values.
+	 * @return a new {@link ArrayList} containing those elements
+	 */
+	@SafeVarargs
+	@Pure
+	public static <T> ArrayList<T> newArrayList(T... initial) {
+		if (initial.length > 0)
+			return Lists.newArrayList(initial);
+		return newArrayList();
+	}
+
+	/**
+	 * Creates an empty mutable {@link LinkedList} instance.
+	 * 
+	 * @return a new {@link LinkedList}
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <T> LinkedList<T> newLinkedList() {
+		return new LinkedList<T>();
+	}
+
+	/**
+	 * Creates a mutable {@link LinkedList} instance containing the given initial elements.
+	 * 
+	 * @param initial
+	 *            the initial elements that the list should contain, in order. May not be <code>null</code> but may
+	 *            contain <code>null</code> values.
+	 * @return a new {@link LinkedList} containing those elements
+	 */
+	@SafeVarargs
+	@Pure
+	public static <T> LinkedList<T> newLinkedList(T... initial) {
+		if (initial.length > 0)
+			return Lists.newLinkedList(Arrays.asList(initial));
+		return newLinkedList();
+	}
+
+	/**
+	 * Creates an empty mutable {@link HashSet} instance.
+	 * 
+	 * @return a new {@link HashSet}
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <T> HashSet<T> newHashSet() {
+		return new HashSet<T>();
+	}
+
+	/**
+	 * Creates a mutable {@link HashSet} instance containing the given initial elements.
+	 * 
+	 * @param initial
+	 *            the initial elements that the set should contain, in order. May not be <code>null</code> but may
+	 *            contain <code>null</code> values.
+	 * @return a new {@link HashSet} containing those elements
+	 */
+	@SafeVarargs
+	@Pure
+	public static <T> HashSet<T> newHashSet(T... initial) {
+		if (initial.length > 0)
+			return Sets.newHashSet(initial);
+		return newHashSet();
+	}
+
+	/**
+	 * Creates an empty mutable {@link LinkedHashSet} instance.
+	 * 
+	 * @return a new {@link LinkedHashSet}
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <T> LinkedHashSet<T> newLinkedHashSet() {
+		return new LinkedHashSet<T>();
+	}
+
+	/**
+	 * Creates a mutable {@link LinkedHashSet} instance containing the given initial elements.
+	 * 
+	 * @param initial
+	 *            the initial elements that the set should contain, in order. May not be <code>null</code> but may
+	 *            contain <code>null</code> values.
+	 * @return a new {@link LinkedHashSet} containing those elements
+	 */
+	@SafeVarargs
+	@Pure
+	public static <T> LinkedHashSet<T> newLinkedHashSet(T... initial) {
+		if (initial.length > 0)
+			return Sets.newLinkedHashSet(Arrays.asList(initial));
+		return newLinkedHashSet();
+	}
+
+	/**
+	 * Creates an empty mutable {@link TreeSet} instance.
+	 * 
+	 * @param comparator
+	 *            the comparator that should be used. May be <code>null</code> which indicates that the natural ordering
+	 *            of the items should be used.
+	 * @return a new {@link TreeSet}
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <T> TreeSet<T> newTreeSet(Comparator<? super T> comparator) {
+		return new TreeSet<T>(comparator);
+	}
+
+	/**
+	 * Creates a mutable {@link TreeSet} instance containing the given initial elements.
+	 * 
+	 * @param initial
+	 *            the initial elements that the set should contain, in order. May not be <code>null</code> but may
+	 *            contain <code>null</code> values.
+	 * @param comparator
+	 *            the comparator that should be used. May be <code>null</code> which indicates that the natural ordering
+	 *            of the items should be used.
+	 * @return a new {@link TreeSet} containing those elements
+	 */
+	@SafeVarargs
+	@Pure
+	public static <T> TreeSet<T> newTreeSet(Comparator<? super T> comparator, T... initial) {
+		TreeSet<T> result = new TreeSet<T>(comparator);
+		if (initial.length > 0)
+			result.addAll(Arrays.asList(initial));
+		return result;
+	}
+
+	/**
+	 * Creates an empty mutable {@link HashMap} instance.
+	 * 
+	 * @return a new {@link HashMap}
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <K, V> HashMap<K, V> newHashMap() {
+		return new HashMap<K, V>();
+	}
+
+	/**
+	 * Creates a mutable {@link HashMap} instance containing the given initial entries. Repeated occurrences of a keys
+	 * will cause an {@link IllegalArgumentException}.
+	 * 
+	 * @param initial
+	 *            the entries that should be contained in the map. May not be <code>null</code> but may contain
+	 *            <code>null</code> keys or values.
+	 * @return a new {@link HashMap} containing those elements
+	 * @throws IllegalArgumentException
+	 *             if duplicate keys are contained the {@code initial} entries.
+	 */
+	@SafeVarargs
+	@Pure
+	public static <K, V> HashMap<K, V> newHashMap(Pair<? extends K, ? extends V>... initial) {
+		if (initial.length > 0) {
+			HashMap<K, V> result = new HashMap<K, V>(capacity(initial.length));
+			putAll(result, initial);
+			return result;
+		}
+		return newHashMap();
+	}
+
+	/**
+	 * Creates an empty mutable {@link LinkedHashMap} instance.
+	 * 
+	 * @return a new {@link LinkedHashMap}
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <K, V> LinkedHashMap<K, V> newLinkedHashMap() {
+		return new LinkedHashMap<K, V>();
+	}
+
+	/**
+	 * Creates a mutable {@link LinkedHashMap} instance containing the given initial entries. Repeated occurrences of a
+	 * keys will cause an {@link IllegalArgumentException}.
+	 * 
+	 * @param initial
+	 *            the entries that should be contained in the map. May not be <code>null</code> but may contain
+	 *            <code>null</code> keys or values.
+	 * @return a new {@link LinkedHashMap} containing those elements
+	 * @throws IllegalArgumentException
+	 *             if duplicate keys are contained the {@code initial} entries.
+	 */
+	@SafeVarargs
+	@Pure
+	public static <K, V> LinkedHashMap<K, V> newLinkedHashMap(Pair<? extends K, ? extends V>... initial) {
+		if (initial.length > 0) {
+			LinkedHashMap<K, V> result = new LinkedHashMap<K, V>(capacity(initial.length));
+			putAll(result, initial);
+			return result;
+		}
+		return newLinkedHashMap();
+	}
+	
+	private static int capacity(int initialSize) {
+		if (initialSize < 3)
+			return initialSize + 1;
+		else if (initialSize < Ints.MAX_POWER_OF_TWO)
+			return initialSize + initialSize / 3;
+		else
+			return Integer.MAX_VALUE;
+	}
+
+	/**
+	 * Creates an empty mutable {@link TreeMap} instance.
+	 * 
+	 * @param comparator
+	 *            the comparator that should be used. May be <code>null</code> which indicates that the natural ordering
+	 *            of the keys should be used.
+	 * @return a new {@link TreeMap}
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <K, V> TreeMap<K, V> newTreeMap(Comparator<? super K> comparator) {
+		return new TreeMap<K, V>(comparator);
+	}
+
+	/**
+	 * Creates a mutable {@link TreeMap} instance containing the given initial entries. Repeated occurrences of a keys
+	 * will cause an {@link IllegalArgumentException}.
+	 * 
+	 * @param initial
+	 *            the entries that should be contained in the map. May not be <code>null</code> but may contain
+	 *            <code>null</code> keys or values.
+	 * @param comparator
+	 *            the comparator that should be used. May be <code>null</code> which indicates that the natural ordering
+	 *            of the keys should be used.
+	 * @return a new {@link TreeMap} containing those elements
+	 * @throws IllegalArgumentException
+	 *             if duplicate keys are contained the {@code initial} entries.
+	 */
+	@SafeVarargs
+	@Pure
+	public static <K, V> TreeMap<K, V> newTreeMap(Comparator<? super K> comparator, Pair<? extends K, ? extends V>... initial) {
+		TreeMap<K, V> result = new TreeMap<K, V>(comparator);
+		putAll(result, initial);
+		return result;
+	}
+
+	@SafeVarargs
+	private static <K, V> void putAll(Map<K, V> result, Pair<? extends K, ? extends V>... entries) {
+		for (Pair<? extends K, ? extends V> entry : entries) {
+			if (result.containsKey(entry.getKey()))
+				throw new IllegalArgumentException("duplicate key: " + entry.getKey());
+			result.put(entry.getKey(), entry.getValue());
+		}
+	}
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ComparableExtensions.java b/java/org/eclipse/xtext/xbase/lib/ComparableExtensions.java
new file mode 100644
index 0000000..8a82c22
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ComparableExtensions.java
@@ -0,0 +1,96 @@
+/*******************************************************************************
+ * 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;
+
+
+/**
+ * This is an extension library for {@link Comparable comparables}.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ */
+@GwtCompatible public class ComparableExtensions {
+
+	/**
+	 * The comparison operator <code>less than</code>.
+	 * 
+	 * @param left
+	 *            a comparable
+	 * @param right
+	 *            the value to compare with
+	 * @return <code>left.compareTo(right) &lt; 0</code>
+	 */
+	@Pure /* not guaranteed, since compareTo() is invoked */
+	@Inline("($1.compareTo($2) < 0)")
+	public static <C> boolean operator_lessThan(Comparable<? super C> left, C right) {
+		return left.compareTo(right) < 0;
+	}
+
+	/**
+	 * The comparison operator <code>greater than</code>.
+	 * 
+	 * @param left
+	 *            a comparable
+	 * @param right
+	 *            the value to compare with
+	 * @return <code>left.compareTo(right) &gt; 0</code>
+	 */
+	@Pure /* not guaranteed, since compareTo() is invoked */
+	@Inline("($1.compareTo($2) > 0)")
+	public static <C> boolean operator_greaterThan(Comparable<? super C> left, C right) {
+		return left.compareTo(right) > 0;
+	}
+
+	/**
+	 * The comparison operator <code>less than or equals</code>.
+	 * 
+	 * @param left
+	 *            a comparable
+	 * @param right
+	 *            the value to compare with
+	 * @return <code>left.compareTo(right) &lt;= 0</code>
+	 */
+	@Pure /* not guaranteed, since compareTo() is invoked */
+	@Inline("($1.compareTo($2) <= 0)")
+	public static <C> boolean operator_lessEqualsThan(Comparable<? super C> left, C right) {
+		return left.compareTo(right) <= 0;
+	}
+
+	/**
+	 * The comparison operator <code>greater than or equals</code>.
+	 * 
+	 * @param left
+	 *            a comparable
+	 * @param right
+	 *            the value to compare with
+	 * @return <code>left.compareTo(right) &gt;= 0</code>
+	 */
+	@Pure /* not guaranteed, since compareTo() is invoked */
+	@Inline("($1.compareTo($2) >= 0)")
+	public static <C> boolean operator_greaterEqualsThan(Comparable<? super C> left, C right) {
+		return left.compareTo(right) >= 0;
+	}
+	
+	/**
+	 * The spaceship operator <code>&lt;=&gt;</code>.
+	 * 
+	 * @param left
+	 *            a comparable
+	 * @param right
+	 *            the value to compare with
+	 * @return <code>left.compareTo(right)</code>
+	 * @since 2.4
+	 */
+	@Pure /* not guaranteed, since compareTo() is invoked */
+	@Inline("($1.compareTo($2))")
+	public static <C> int operator_spaceship(Comparable<? super C> left, C right) {
+		return left.compareTo(right);
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Conversions.java b/java/org/eclipse/xtext/xbase/lib/Conversions.java
new file mode 100644
index 0000000..80f35f6
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Conversions.java
@@ -0,0 +1,1496 @@
+/*******************************************************************************
+ * Copyright (c) 2010, 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.xtext.xbase.lib;
+
+import java.lang.reflect.Array;
+import java.util.AbstractList;
+import java.util.List;
+import java.util.RandomAccess;
+
+import com.google.common.annotations.GwtIncompatible;
+import com.google.common.collect.Iterables;
+import com.google.common.primitives.Booleans;
+import com.google.common.primitives.Bytes;
+import com.google.common.primitives.Chars;
+import com.google.common.primitives.Doubles;
+import com.google.common.primitives.Floats;
+import com.google.common.primitives.Ints;
+import com.google.common.primitives.Longs;
+import com.google.common.primitives.Shorts;
+
+/**
+ * This is a library used to convert arrays to lists and vice versa in a way that keeps the identity of the
+ * to-be-converted object. That is, changes in the array will be reflected by the list and changes to the list will be
+ * reflected by the array for both kinds of conversion.
+ * 
+ * The utilities in this class should only be used by the Xbase compiler.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @author Sven Efftinge
+ * @author Facundo Etchezar - Initial implementation of the type-specific primitive array wrappers
+ */
+@GwtIncompatible("reflection")
+public final class Conversions {
+
+	private Conversions() {
+		throw new RuntimeException("Can't create instances of this class");
+	}
+
+	/**
+	 * Wraps {@code object} in a list if and only if {@code object} is an array. Works for primitive and
+	 * object-component types.
+	 * 
+	 * @param object
+	 *            the object to be wrapped. May be <code>null</code>.
+	 * @return a list if the given object was an array. Otherwise the unmodified given object. May return
+	 *         <code>null</code> if the object was <code>null</code>.
+	 */
+	@Pure
+	public static Object doWrapArray(Object object) {
+		if (object == null) {
+			// Nothing to wrap.
+			return null;
+		}
+
+		Class<?> arrayClass = object.getClass();
+
+		if (!arrayClass.isArray()) {
+			// Can't wrap something that isn't an array.
+			return object;
+		}
+
+		if (!arrayClass.getComponentType().isPrimitive()) {
+			// Not a primitive, return generic wrapped object array.
+			return WrappedArray.create((Object[]) object);
+		}
+
+		// Now check for each primitive type individually, and return the appropriate wrapper.
+
+		// These are probably the most used types, check for them first:
+		if (object instanceof int[]) {
+			return WrappedIntegerArray.create((int[]) object);
+		}
+
+		if (object instanceof long[]) {
+			return WrappedLongArray.create((long[]) object);
+		}
+
+		if (object instanceof float[]) {
+			return WrappedFloatArray.create((float[]) object);
+		}
+
+		if (object instanceof double[]) {
+			return WrappedDoubleArray.create((double[]) object);
+		}
+
+		// Now check for the slightly less used types:
+		if (object instanceof byte[]) {
+			return WrappedByteArray.create((byte[]) object);
+		}
+
+		if (object instanceof short[]) {
+			return WrappedShortArray.create((short[]) object);
+		}
+
+		if (object instanceof boolean[]) {
+			return WrappedBooleanArray.create((boolean[]) object);
+		}
+
+		if (object instanceof char[]) {
+			return WrappedCharacterArray.create((char[]) object);
+		}
+
+		// Unrecognized type.
+		throw new ArrayStoreException("Unrecognised type: " + arrayClass.getCanonicalName());
+	}
+
+	/**
+	 * Unwraps {@code object} to extract the original array if and only if {@code object} was previously created by
+	 * {@link #doWrapArray(Object)}. If the array's component type cannot be determined at runtime, {@link Object} is
+	 * used.
+	 * 
+	 * @param value
+	 *            the object to be unwrapped. May be <code>null</code>.
+	 * @return the previously wrapped array if the given value represents such. Otherwise returns the value unmodified.
+	 *         May return <code>null</code> if the value was <code>null</code>.
+	 */
+	@Pure
+	public static Object unwrapArray(Object value) {
+		return unwrapArray(value, Object.class);
+	}
+
+	/**
+	 * Unwraps {@code object} to extract the original array if and only if {@code object} was previously created by
+	 * {@link #doWrapArray(Object)}.
+	 * 
+	 * @param value
+	 *            the object to be unwrapped. May be <code>null</code>.
+	 * @param componentType
+	 *            the expected component type of the array. May not be <code>null</code>.
+	 * @return the previously wrapped array if the given value represents such. Otherwise returns the value unmodified.
+	 *         May return <code>null</code> if the value was <code>null</code>.
+	 * @throws ArrayStoreException
+	 *             if the expected runtime {@code componentType} does not match the actual runtime component type.
+	 */
+	@Pure
+	public static Object unwrapArray(Object value, Class<?> componentType) {
+		// This is the generic object array check.
+		if (value instanceof WrappedArray<?>) {
+			Object result = ((WrappedArray<?>) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+		// And now for the primitive arrays.
+		if (value instanceof WrappedIntegerArray) {
+			Object result = ((WrappedIntegerArray) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+
+		if (value instanceof WrappedLongArray) {
+			Object result = ((WrappedLongArray) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+
+		if (value instanceof WrappedFloatArray) {
+			Object result = ((WrappedFloatArray) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+
+		if (value instanceof WrappedDoubleArray) {
+			Object result = ((WrappedDoubleArray) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+
+		if (value instanceof WrappedByteArray) {
+			Object result = ((WrappedByteArray) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+
+		if (value instanceof WrappedShortArray) {
+			Object result = ((WrappedShortArray) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+
+		if (value instanceof WrappedBooleanArray) {
+			Object result = ((WrappedBooleanArray) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+
+		if (value instanceof WrappedCharacterArray) {
+			Object result = ((WrappedCharacterArray) value).internalToArray();
+			return checkComponentType(result, componentType);
+		}
+
+		if (!(value instanceof Iterable<?>)) {
+			// Nothing to unwrap.
+			return value;
+		}
+
+		if (!componentType.isPrimitive()) {
+			@SuppressWarnings({ "unchecked", "rawtypes" })
+			Object result = Iterables.toArray((Iterable) value, componentType);
+			return result;
+		}
+
+		try {
+			List<?> list = IterableExtensions.toList((Iterable<?>) value);
+			Object result = Array.newInstance(componentType, list.size());
+			for (int i = 0; i < list.size(); i++) {
+				Object element = list.get(i);
+				if (element == null) {
+					throw new ArrayStoreException("Cannot store <null> in primitive arrays.");
+				}
+				Array.set(result, i, element);
+			}
+			return result;
+		} catch (IllegalArgumentException iae) {
+			throw new ArrayStoreException("Primitive conversion failed: " + iae.getMessage());
+		}
+	}
+
+	/**
+	 * Checks the component type of the given array against the expected component type.
+	 * 
+	 * @param array
+	 *            the array to be checked. May not be <code>null</code>.
+	 * @param expectedComponentType
+	 *            the expected component type of the array. May not be <code>null</code>.
+	 * @return the unchanged array.
+	 * @throws ArrayStoreException
+	 *             if the expected runtime {@code componentType} does not match the actual runtime component type.
+	 */
+	private static Object checkComponentType(Object array, Class<?> expectedComponentType) {
+		Class<?> actualComponentType = array.getClass().getComponentType();
+		if (!expectedComponentType.isAssignableFrom(actualComponentType)) {
+			throw new ArrayStoreException(
+					String.format("The expected component type %s is not assignable from the actual type %s",
+							expectedComponentType.getCanonicalName(), actualComponentType.getCanonicalName()));
+		}
+		return array;
+	}
+
+	/**
+	 * A list that is completely backed by an array and that provides access to that array. Only for internal use.
+	 * 
+	 * @param <T>
+	 *            the type if the list elements.
+	 */
+	public static final class WrappedArray<T> extends AbstractList<T> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedArray} that is backed by the given {@code array}.
+		 * 
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the result object
+		 *            to fail with a {@link NullPointerException}.
+		 * @param <T>
+		 *            the element type of the created list.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		public static <T> WrappedArray<T> create(T[] array) {
+			return new WrappedArray<T>(array);
+		}
+
+		private T[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedArray}.
+		 * 
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedArray(T[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public T get(int index) {
+			return array[index];
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public T set(int index, T element) {
+			T old = array[index];
+			array[index] = element;
+			modCount++;
+			return old;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 * 
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		@Override
+		public Object[] toArray() {
+			return array.clone();
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 * 
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(Object[]) created} with
+		 *         a null argument.
+		 */
+		public T[] internalToArray() {
+			modCount++;
+			return array;
+		}
+
+	}
+
+	/**
+	 * A list that is completely backed by an array of primitives and that provides access to that array. Only for
+	 * internal use.
+	 */
+	public static final class WrappedByteArray extends AbstractList<Byte> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedByteArray} that is backed by the given primitive {@code array}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the resulting
+		 *            object to fail.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		@Pure
+		public static WrappedByteArray create(byte[] array) {
+			return new WrappedByteArray(array);
+		}
+
+		private final byte[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedByteArray}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedByteArray(byte[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Byte get(int index) {
+			return Byte.valueOf(array[index]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Byte set(int index, Byte element) {
+			modCount++;
+			byte old = array[index];
+			array[index] = element.byteValue();
+			return Byte.valueOf(old);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int indexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Byte) {
+				return Bytes.indexOf(array, ((Byte) o).byteValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int lastIndexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Byte) {
+				return Bytes.lastIndexOf(array, ((Byte) o).byteValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public boolean contains(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return false;
+			}
+			if (o instanceof Byte) {
+				return Bytes.contains(array, ((Byte) o).byteValue());
+			}
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 *
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(byte[]) created} with a
+		 *         null argument.
+		 */
+		public byte[] internalToArray() {
+			modCount++;
+			return array;
+		}
+	}
+
+	/**
+	 * A list that is completely backed by an array of primitives and that provides access to that array. Only for
+	 * internal use.
+	 */
+	public static final class WrappedShortArray extends AbstractList<Short> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedShortArray} that is backed by the given primitive {@code array}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the resulting
+		 *            object to fail.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		@Pure
+		public static WrappedShortArray create(short[] array) {
+			return new WrappedShortArray(array);
+		}
+
+		private final short[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedShortArray}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedShortArray(short[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Short get(int index) {
+			return Short.valueOf(array[index]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Short set(int index, Short element) {
+			modCount++;
+			short old = array[index];
+			array[index] = element.shortValue();
+			return Short.valueOf(old);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int indexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Short) {
+				return Shorts.indexOf(array, ((Short) o).shortValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int lastIndexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Short) {
+				return Shorts.lastIndexOf(array, ((Short) o).shortValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public boolean contains(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return false;
+			}
+			if (o instanceof Short) {
+				return Shorts.contains(array, ((Short) o).shortValue());
+			}
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 *
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(short[]) created} with
+		 *         a null argument.
+		 */
+		public short[] internalToArray() {
+			modCount++;
+			return array;
+		}
+	}
+
+	/**
+	 * A list that is completely backed by an array of primitives and that provides access to that array. Only for
+	 * internal use.
+	 */
+	public static final class WrappedIntegerArray extends AbstractList<Integer> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedIntegerArray} that is backed by the given primitive {@code array}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the resulting
+		 *            object to fail.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		@Pure
+		public static WrappedIntegerArray create(int[] array) {
+			return new WrappedIntegerArray(array);
+		}
+
+		private final int[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedIntegerArray}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedIntegerArray(int[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Integer get(int index) {
+			return Integer.valueOf(array[index]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Integer set(int index, Integer element) {
+			modCount++;
+			int old = array[index];
+			array[index] = element.intValue();
+			return Integer.valueOf(old);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int indexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Integer) {
+				return Ints.indexOf(array, ((Integer) o).intValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int lastIndexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Integer) {
+				return Ints.lastIndexOf(array, ((Integer) o).intValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public boolean contains(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return false;
+			}
+			if (o instanceof Integer) {
+				return Ints.contains(array, ((Integer) o).intValue());
+			}
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 *
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(int[]) created} with a
+		 *         null argument.
+		 */
+		public int[] internalToArray() {
+			modCount++;
+			return array;
+		}
+	}
+
+	/**
+	 * A list that is completely backed by an array of primitives and that provides access to that array. Only for
+	 * internal use.
+	 */
+	public static final class WrappedLongArray extends AbstractList<Long> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedLongArray} that is backed by the given primitive {@code array}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the resulting
+		 *            object to fail.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		@Pure
+		public static WrappedLongArray create(long[] array) {
+			return new WrappedLongArray(array);
+		}
+
+		private final long[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedLongArray}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedLongArray(long[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Long get(int index) {
+			return Long.valueOf(array[index]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Long set(int index, Long element) {
+			modCount++;
+			long old = array[index];
+			array[index] = element.longValue();
+			return Long.valueOf(old);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int indexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Long) {
+				return Longs.indexOf(array, ((Long) o).longValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int lastIndexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Long) {
+				return Longs.lastIndexOf(array, ((Long) o).longValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public boolean contains(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return false;
+			}
+			if (o instanceof Long) {
+				return Longs.contains(array, ((Long) o).longValue());
+			}
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 *
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(long[]) created} with a
+		 *         null argument.
+		 */
+		public long[] internalToArray() {
+			modCount++;
+			return array;
+		}
+	}
+
+	/**
+	 * A list that is completely backed by an array of primitives and that provides access to that array. Only for
+	 * internal use.
+	 */
+	public static final class WrappedFloatArray extends AbstractList<Float> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedFloatArray} that is backed by the given primitive {@code array}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the resulting
+		 *            object to fail.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		@Pure
+		public static WrappedFloatArray create(float[] array) {
+			return new WrappedFloatArray(array);
+		}
+
+		private final float[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedFloatArray}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedFloatArray(float[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Float get(int index) {
+			return Float.valueOf(array[index]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Float set(int index, Float element) {
+			modCount++;
+			float old = array[index];
+			array[index] = element.floatValue();
+			return Float.valueOf(old);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int indexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Float) {
+				return Floats.indexOf(array, ((Float) o).floatValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int lastIndexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Float) {
+				return Floats.lastIndexOf(array, ((Float) o).floatValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public boolean contains(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return false;
+			}
+			if (o instanceof Float) {
+				return Floats.contains(array, ((Float) o).floatValue());
+			}
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 *
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(float[]) created} with
+		 *         a null argument.
+		 */
+		public float[] internalToArray() {
+			modCount++;
+			return array;
+		}
+	}
+
+	/**
+	 * A list that is completely backed by an array of primitives and that provides access to that array. Only for
+	 * internal use.
+	 */
+	public static final class WrappedDoubleArray extends AbstractList<Double> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedDoubleArray} that is backed by the given primitive {@code array}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the resulting
+		 *            object to fail.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		@Pure
+		public static WrappedDoubleArray create(double[] array) {
+			return new WrappedDoubleArray(array);
+		}
+
+		private final double[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedDoubleArray}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedDoubleArray(double[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Double get(int index) {
+			return Double.valueOf(array[index]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Double set(int index, Double element) {
+			modCount++;
+			double old = array[index];
+			array[index] = element.doubleValue();
+			return Double.valueOf(old);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int indexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Double) {
+				return Doubles.indexOf(array, ((Double) o).doubleValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int lastIndexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Double) {
+				return Doubles.lastIndexOf(array, ((Double) o).doubleValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public boolean contains(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return false;
+			}
+			if (o instanceof Double) {
+				return Doubles.contains(array, ((Double) o).doubleValue());
+			}
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 *
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(double[]) created} with
+		 *         a null argument.
+		 */
+		public double[] internalToArray() {
+			modCount++;
+			return array;
+		}
+	}
+
+	/**
+	 * A list that is completely backed by an array of primitives and that provides access to that array. Only for
+	 * internal use.
+	 */
+	public static final class WrappedCharacterArray extends AbstractList<Character> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedCharacterArray} that is backed by the given primitive {@code array}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the resulting
+		 *            object to fail.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		@Pure
+		public static WrappedCharacterArray create(char[] array) {
+			return new WrappedCharacterArray(array);
+		}
+
+		private final char[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedCharacterArray}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedCharacterArray(char[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Character get(int index) {
+			return Character.valueOf(array[index]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Character set(int index, Character element) {
+			modCount++;
+			char old = array[index];
+			array[index] = element.charValue();
+			return Character.valueOf(old);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int indexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Character) {
+				return Chars.indexOf(array, ((Character) o).charValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int lastIndexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Character) {
+				return Chars.lastIndexOf(array, ((Character) o).charValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public boolean contains(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return false;
+			}
+			if (o instanceof Character) {
+				return Chars.contains(array, ((Character) o).charValue());
+			}
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 *
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(char[]) created} with a
+		 *         null argument.
+		 */
+		public char[] internalToArray() {
+			modCount++;
+			return array;
+		}
+	}
+
+	/**
+	 * A list that is completely backed by an array of primitives and that provides access to that array. Only for
+	 * internal use.
+	 */
+	public static final class WrappedBooleanArray extends AbstractList<Boolean> implements RandomAccess {
+
+		/**
+		 * Creates a new {@link WrappedBooleanArray} that is backed by the given primitive {@code array}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the resulting
+		 *            object to fail.
+		 * @return the wrapped array. Never <code>null</code>.
+		 */
+		@Pure
+		public static WrappedBooleanArray create(boolean[] array) {
+			return new WrappedBooleanArray(array);
+		}
+
+		private final boolean[] array;
+
+		/**
+		 * Internal constructor for {@link WrappedBooleanArray}.
+		 *
+		 * @param array
+		 *            the to-be-wrapped array. May be <code>null</code> which will cause any method on the created
+		 *            object to fail with a {@link NullPointerException}.
+		 */
+		protected WrappedBooleanArray(boolean[] array) {
+			this.array = array;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Boolean get(int index) {
+			return Boolean.valueOf(array[index]);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 * @throws ClassCastException
+		 *             {@inheritDoc}
+		 * @throws NullPointerException
+		 *             {@inheritDoc}
+		 * @throws IllegalArgumentException
+		 *             {@inheritDoc}
+		 * @throws IndexOutOfBoundsException
+		 *             {@inheritDoc}
+		 */
+		@Override
+		public Boolean set(int index, Boolean element) {
+			modCount++;
+			boolean old = array[index];
+			array[index] = element.booleanValue();
+			return Boolean.valueOf(old);
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int indexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Boolean) {
+				return Booleans.indexOf(array, ((Boolean) o).booleanValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int lastIndexOf(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return -1;
+			}
+			if (o instanceof Boolean) {
+				return Booleans.lastIndexOf(array, ((Boolean) o).booleanValue());
+			}
+			return -1;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public boolean contains(Object o) {
+			// Will make the method fail if array is null.
+			if (size() < 1) {
+				return false;
+			}
+			if (o instanceof Boolean) {
+				return Booleans.contains(array, ((Boolean) o).booleanValue());
+			}
+			return false;
+		}
+
+		/**
+		 * {@inheritDoc}
+		 *
+		 * @throws NullPointerException
+		 *             if the wrapped array was <code>null</code>.
+		 */
+		@Override
+		public int size() {
+			return array.length;
+		}
+
+		/**
+		 * Returns the underlying array in an unsafe manner. That is, modification of the array will be reflected by
+		 * this list and vice versa.
+		 *
+		 * @return the underlying array. May be <code>null</code> if the list was {@link #create(boolean[]) created}
+		 *         with a null argument.
+		 */
+		public boolean[] internalToArray() {
+			modCount++;
+			return array;
+		}
+	}
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtext/xbase/lib/DoubleExtensions.java b/java/org/eclipse/xtext/xbase/lib/DoubleExtensions.java
new file mode 100644
index 0000000..b1e140e
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/DoubleExtensions.java
@@ -0,0 +1,1565 @@
+/*******************************************************************************
+ * 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;
+
+
+/**
+ * This is an extension library for {@link Double floating point numbers}, e.g. <code>double</code> or <code>Double</code>.
+ * 
+ * @author Jan Koehnlein - Initial contribution and API
+ * @since 2.3
+ */
+@GwtCompatible public class DoubleExtensions {
+
+	/**
+	 * The unary <code>minus</code> operator. This is the equivalent to the unary java <code>-</code> operator.
+	 * 
+	 * @param a
+	 *            a double. May not be <code>null</code>.
+	 * @return <code>-a</code>
+	 * @throws NullPointerException
+	 *             if {@code a} is <code>null</code>.
+	 */
+	@Pure
+	public static double operator_minus(Double a) {
+		return -a;
+	}
+
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the java <code>+</code> operator.
+	 * 
+	 * @param a
+	 *            a double. May not be <code>null</code>.
+	 * @param b
+	 *            a number. May not be <code>null</code>.
+	 * @return <code>a+b</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Pure
+	public static double operator_plus(Double a, Number b) {
+		return a + b.doubleValue();
+	}
+
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the java <code>-</code> operator.
+	 * 
+	 * @param a
+	 *            a double. May not be <code>null</code>.
+	 * @param b
+	 *            a number. May not be <code>null</code>.
+	 * @return <code>a-b</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Pure
+	public static double operator_minus(Double a, Number b) {
+		return a - b.doubleValue();
+	}
+
+	/**
+	 * The <code>power</code> operator.
+	 * 
+	 * @param a
+	 *            a double. May not be <code>null</code>.
+	 * @param b
+	 *            a number. May not be <code>null</code>.
+	 * @return <code>a ** b</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Pure
+	public static double operator_power(Double a, Number b) {
+		return Math.pow(a, b.doubleValue());
+	}
+
+	/**
+	 * The binary <code>times</code> operator. This is the equivalent to the java <code>*</code> operator.
+	 * 
+	 * @param a
+	 *            a double. May not be <code>null</code>.
+	 * @param b
+	 *            a number. May not be <code>null</code>.
+	 * @return <code>a*b</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	public static double operator_multiply(Double a, Number b) {
+		return a * b.doubleValue();
+	}
+
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the java <code>/</code> operator. That is, the
+	 * result will be the integral result of the division, e.g. <code>operator_divide(1, 2)</code> yields <code>0</code>
+	 * .
+	 * 
+	 * @param a
+	 *            a double. May not be <code>null</code>.
+	 * @param b
+	 *            a number. May not be <code>null</code>.
+	 * @return <code>a/b</code>
+	 * @throws NullPointerException
+	 *             if {@code a} or {@code b} is <code>null</code>.
+	 */
+	@Pure
+	public static double operator_divide(Double a, Number b) {
+		return a / b.doubleValue();
+	}
+
+	// BEGIN generated code
+	/**
+	 * The unary <code>minus</code> operator. This is the equivalent to the Java's <code>-</code> function.
+	 * 
+	 * @param d  a double.
+	 * @return   <code>-d</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="(-$1)", constantExpression=true)
+	public static double operator_minus(double d) {
+		return -d;
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param d  a double.
+	 * @return   <code>d--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static double operator_minusMinus(double d) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param d  a double.
+	 * @return   <code>d--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static Double operator_minusMinus(Double d) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param d  a double.
+	 * @return   <code>d++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static double operator_plusPlus(double d) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param d  a double.
+	 * @return   <code>d++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static Double operator_plusPlus(Double d) {
+		throw new HardcodedInInterpreterException();
+	}
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a double.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(double 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 double.
+	 * @param b  a double.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(double 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 double.
+	 * @param b  a double.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(double 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 double.
+	 * @param b  a double.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(double 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 double.
+	 * @param b  a double.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a double.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(double 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 double.
+	 * @param b  a double.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a double.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(double 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 double.
+	 * @param b  a double.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(double 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 double.
+	 * @param b  a float.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(double 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 double.
+	 * @param b  a long.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(double 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 double.
+	 * @param b  an integer.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(double 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 double.
+	 * @param b  a character.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(double 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 double.
+	 * @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(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(double 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 double.
+	 * @param b  a short.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(double 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 double.
+	 * @param b  a byte.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(double a, byte b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(double a, byte b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(double a, byte b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(double a, byte b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(double a, byte b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(double a, byte b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(double a, byte b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(double a, byte b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(double a, byte b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(double a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(double a, byte 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 double.
+	 * @param b  a byte.
+	 * @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(double a, byte 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 double.
+	 * @param b  a byte.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(double a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a double.
+	 * @param b  a byte.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(double a, byte b) {
+		return a != b;
+	}
+	
+	// END generated code
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Exceptions.java b/java/org/eclipse/xtext/xbase/lib/Exceptions.java
new file mode 100644
index 0000000..33b6091
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Exceptions.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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;
+
+/**
+ * Useful helper methods when dealing with exceptions.
+ * @author Sven Efftinge - Initial contribution and API
+ */
+@GwtCompatible public class Exceptions {
+
+	/*
+	 * shamelessly taken from Project Lombok
+	 * https://github.com/rzwitserloot/lombok/blob/master/src/core/lombok/Lombok.java
+	 */
+	/**
+	 * Throws the given exception and sneaks it through any compiler checks. This
+	 * allows to throw checked exceptions without the need to declare it.
+	 * Clients should use the following idiom to trick static analysis and dead code checks:
+	 * <pre>
+	 * throw sneakyThrow(new CheckedException("Catch me if you can ;-)")).
+	 * </pre>
+	 * This method is heavily inspired by project
+	 * <a href="https://github.com/rzwitserloot/lombok/blob/master/src/core/lombok/Lombok.java">Lombok</a>.
+	 * @param t the throwable that should be sneaked through compiler checks. May not be <code>null</code>.
+	 * @return never returns anything since {@code t} is always thrown.
+	 * @throws NullPointerException if {@code t} is <code>null</code>.
+	 */
+	public static RuntimeException sneakyThrow(Throwable t) {
+		if (t == null)
+			throw new NullPointerException("t");
+		Exceptions.<RuntimeException> sneakyThrow0(t);
+		return null;
+	}
+
+	@SuppressWarnings("unchecked")
+	private static <T extends Throwable> void sneakyThrow0(Throwable t) throws T {
+		throw (T) t;
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ExclusiveRange.java b/java/org/eclipse/xtext/xbase/lib/ExclusiveRange.java
new file mode 100644
index 0000000..c306cfb
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ExclusiveRange.java
@@ -0,0 +1,237 @@
+/*******************************************************************************
+ * 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 java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * A sequence of integers starting from <code>start</code> to <code>end</code> counting up or down.
+ * It excludes the <code>end</code> value when counting up and the <code>start</code> value when counting down.   
+ * 
+ * Examples:
+ * <table>
+ * <tr><td><code>new ExclusiveRange(1, 5, true)</code></td><td>(1,2,3,4)</td></tr>
+ * <tr><td><code>new ExclusiveRange(0, 0, true)</code></td><td>()</td></tr>
+ * <tr><td><code>new ExclusiveRange(0, -1, true)</code></td><td>()</td></tr>
+ * <tr><td><code>new ExclusiveRange(-1, 0, true)</code></td><td>(-1)</td></tr>
+ * <tr><td><code>new ExclusiveRange(5, 1, false)</code></td><td>(4,3,2,1)</td></tr>
+ * <tr><td><code>new ExclusiveRange(0, 0, false)</code></td><td>()</td></tr>
+ * <tr><td><code>new ExclusiveRange(-1, 0, false)</code></td><td>()</td></tr>
+ * <tr><td><code>new ExclusiveRange(0, -1, false)</code></td><td>(-1)</td></tr>
+ * </table>
+ * 
+ * As opposed to {@link IntegerRange} this class meets the requirements to iterate arrays or lists without 
+ * the need for further guards, e.g.
+ * 
+ * <pre>
+ * for(i: new ExclusiveRange(0, list.size, true)) 
+ *   list.get(i)...
+ * 
+ * for(i: new ExclusiveRange(array.length, 0, false)) 
+ *   array.get(i)...
+ * 
+ * for(i: new ExclusiveRange(0, string.indexOf('x'), true)
+ *   string.charAt(i)...
+ * </pre>
+ * 
+ * @author Jan Koehnlein - Initial contribution and API
+ * @since 2.4
+ */
+@GwtCompatible 
+public class ExclusiveRange implements Iterable<Integer> {
+
+	private final int first;
+	private final int last;
+	private final int step;
+
+	private static final ListIterator<Integer> EMPTY_LIST_ITERATOR = new ListIterator<Integer>() {
+
+		@Override
+		public boolean hasNext() {
+			return false;
+		}
+
+		@Override
+		public Integer next() {
+			throw new NoSuchElementException();
+		}
+
+		@Override
+		public boolean hasPrevious() {
+			return false;
+		}
+
+		@Override
+		public Integer previous() {
+			throw new NoSuchElementException();
+		}
+
+		@Override
+		public int nextIndex() {
+			return -1;
+		}
+
+		@Override
+		public int previousIndex() {
+			return -1;
+		}
+
+		@Override
+		public void remove() {
+			throw new UnsupportedOperationException("Cannot remove elements from a Range");
+		}
+
+		@Override
+		public void set(Integer e) {
+			throw new UnsupportedOperationException("Cannot set elements in a Range");
+		}
+
+		@Override
+		public void add(Integer e) {
+			throw new UnsupportedOperationException("Cannot add elements to a Range");
+		}
+	};
+	
+	/**
+	 * @return a read-only {@link ListIterator} for this.
+	 */
+	@Override
+	@Pure
+	public ListIterator<Integer> iterator() {
+		return isEmpty() ? EMPTY_LIST_ITERATOR : new RangeIterator();
+	}
+
+	/**
+	 * Constructs a new ExclusiveRange object.
+	 * 
+	 * @param start the start value
+	 * @param end the end value
+	 * @param increment
+	 *            if true, the range goes from start up to end (exclusive)
+	 *            if false, the range goes from end down to start (exclusive)
+	 */
+	@Pure
+	public ExclusiveRange(int start, int end, boolean increment) {
+		if (increment) {
+			first = start;
+			last = end - 1;
+			step = 1;
+		} else {
+			first = start - 1;
+			last = end;
+			step = -1;
+		} 
+	}
+
+	/**
+	 * Returns the number of elements in this ExclusiveRange. 
+	 * 
+	 * @return the number of elements in this ExclusiveRange.
+	 */
+	@Pure
+	public int size() {
+		return (isEmpty()) ? 0 : Math.abs(last - first) + 1;
+	}
+
+
+	/** 
+	 * Returns whether this is range is empty.
+	 * 
+	 * @return true if this range is empty.
+	 */
+	@Pure 
+	public boolean isEmpty() {
+		return (last - first) * step < 0;
+	}
+	
+	/**
+	 * Checks whether this contains the given number, i.e. whether the iterator will yield the number. This is different
+	 * from interval containment: <code>0..2.by(2)</code> will <em>not</em> contain 1.
+	 * 
+	 * @param number
+	 *            the number to be checked for containment.
+	 * @return whether this sequence contains the given number or not.
+	 */
+	@Pure
+	public boolean contains(int number) {
+		if (isEmpty())
+			return false;
+		if(step == -1)
+			return number <= first && number >= last;
+		else
+			return number >= first && number <= last;
+	}
+
+	private class RangeIterator implements ListIterator<Integer> {
+
+		private int next = first;
+		private int nextIndex = 0;
+
+		@Override
+		public boolean hasNext() {
+			if (step < 0)
+				return next >= last;
+			else
+				return next <= last;
+		}
+
+		@Override
+		public Integer next() {
+			if (!hasNext()) {
+				throw new NoSuchElementException();
+			}
+			int value = next;
+			next += step;
+			++nextIndex;
+			return value;
+		}
+
+		@Override
+		public boolean hasPrevious() {
+			return nextIndex > 0;
+		}
+
+		@Override
+		public Integer previous() {
+			if (nextIndex <= 0)
+				throw new NoSuchElementException();
+			--nextIndex;
+			next -= step;
+			return next;
+		}
+
+		@Override
+		public int nextIndex() {
+			return nextIndex;
+		}
+
+		@Override
+		public int previousIndex() {
+			return nextIndex - 1;
+		}
+
+		@Override
+		public void remove() {
+			throw new UnsupportedOperationException("Cannot remove elements from a Range");
+		}
+
+		@Override
+		public void set(Integer e) {
+			throw new UnsupportedOperationException("Cannot set elements in a Range");
+		}
+
+		@Override
+		public void add(Integer e) {
+			throw new UnsupportedOperationException("Cannot add elements to a Range");
+		}
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Extension.java b/java/org/eclipse/xtext/xbase/lib/Extension.java
new file mode 100644
index 0000000..1db1c69
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Extension.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.xtext.xbase.lib;
+
+import java.lang.annotation.Documented;
+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;
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * Marks a field, parameter or local variable as extension provider.
+ * 
+ * Annotated extension fields are inherited if their visibility is set
+ * accordingly.
+ *  
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * 
+ * @since 2.4
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({
+    ElementType.FIELD,
+    ElementType.PARAMETER,
+    ElementType.LOCAL_VARIABLE
+})
+@Documented
+@Beta
+@GwtCompatible public @interface Extension {
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/FloatExtensions.java b/java/org/eclipse/xtext/xbase/lib/FloatExtensions.java
new file mode 100644
index 0000000..1a7c7f6
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/FloatExtensions.java
@@ -0,0 +1,1470 @@
+/*******************************************************************************
+ * 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 Float} numbers.
+ * 
+ * @author Jan Koehnlein - Code generator
+ * @since 2.3
+ */
+@GwtCompatible public class FloatExtensions {
+	// BEGIN generated code
+	/**
+	 * The unary <code>minus</code> operator. This is the equivalent to the Java's <code>-</code> function.
+	 * 
+	 * @param f  a float.
+	 * @return   <code>-f</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="(-$1)", constantExpression=true)
+	public static float operator_minus(float f) {
+		return -f;
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param f  a float.
+	 * @return   <code>f--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static float operator_minusMinus(float f) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param f  a float.
+	 * @return   <code>f--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static Float operator_minusMinus(Float f) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param f  a float.
+	 * @return   <code>f++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static float operator_plusPlus(float f) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param f  a float.
+	 * @return   <code>f++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static Float operator_plusPlus(Float f) {
+		throw new HardcodedInInterpreterException();
+	}
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a double.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(float 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 float.
+	 * @param b  a double.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(float 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 float.
+	 * @param b  a double.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(float 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 float.
+	 * @param b  a double.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(float 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 float.
+	 * @param b  a double.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a double.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(float 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 float.
+	 * @param b  a double.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a double.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(float 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 float.
+	 * @param b  a double.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(float 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 float.
+	 * @param b  a float.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(float 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 float.
+	 * @param b  a long.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(float 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 float.
+	 * @param b  an integer.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(float 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 float.
+	 * @param b  a character.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(float 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 float.
+	 * @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(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(float 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 float.
+	 * @param b  a short.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(float 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 float.
+	 * @param b  a byte.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(float a, byte b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(float a, byte b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(float a, byte b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(float a, byte b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(float a, byte b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(float a, byte b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(float a, byte b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(float a, byte b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(float a, byte b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(float a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(float a, byte 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 float.
+	 * @param b  a byte.
+	 * @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(float a, byte 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 float.
+	 * @param b  a byte.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(float a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a float.
+	 * @param b  a byte.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(float a, byte b) {
+		return a != b;
+	}
+	
+	// END generated code
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/FunctionExtensions.java b/java/org/eclipse/xtext/xbase/lib/FunctionExtensions.java
new file mode 100644
index 0000000..29274bd
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/FunctionExtensions.java
@@ -0,0 +1,309 @@
+/*******************************************************************************
+ * 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 org.eclipse.xtext.xbase.lib.Functions.Function0;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.Functions.Function2;
+import org.eclipse.xtext.xbase.lib.Functions.Function3;
+import org.eclipse.xtext.xbase.lib.Functions.Function4;
+import org.eclipse.xtext.xbase.lib.Functions.Function5;
+import org.eclipse.xtext.xbase.lib.Functions.Function6;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure0;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * This is an extension library for {@link Functions functions}, e.g. closures.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * @see Functions
+ */
+@GwtCompatible public class FunctionExtensions {
+
+	/**
+	 * Curries a function that takes one argument.
+	 * 
+	 * @param function
+	 *            the original function. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed argument.
+	 * @return a function that takes no arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, RESULT> Function0<RESULT> curry(final Function1<? super P1, ? extends RESULT> function, final P1 argument) {
+		if (function == null)
+			throw new NullPointerException("function");
+		return new Function0<RESULT>() {
+			@Override
+			public RESULT apply() {
+				return function.apply(argument);
+			}
+		};
+	}
+
+	/**
+	 * Curries a function that takes two arguments.
+	 * 
+	 * @param function
+	 *            the original function. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code function}.
+	 * @return a function that takes one argument. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, RESULT> Function1<P2, RESULT> curry(final Function2<? super P1, ? super P2, ? extends RESULT> function,
+			final P1 argument) {
+		if (function == null)
+			throw new NullPointerException("function");
+		return new Function1<P2, RESULT>() {
+			@Override
+			public RESULT apply(P2 p) {
+				return function.apply(argument, p);
+			}
+		};
+	}
+
+	/**
+	 * Curries a function that takes three arguments.
+	 * 
+	 * @param function
+	 *            the original function. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code function}.
+	 * @return a function that takes two arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, P3, RESULT> Function2<P2, P3, RESULT> curry(final Function3<? super P1, ? super P2, ? super P3, ? extends RESULT> function,
+			final P1 argument) {
+		if (function == null)
+			throw new NullPointerException("function");
+		return new Function2<P2, P3, RESULT>() {
+			@Override
+			public RESULT apply(P2 p2, P3 p3) {
+				return function.apply(argument, p2, p3);
+			}
+		};
+	}
+
+	/**
+	 * Curries a function that takes four arguments.
+	 * 
+	 * @param function
+	 *            the original function. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code function}.
+	 * @return a function that takes three arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, P3, P4, RESULT> Function3<P2, P3, P4, RESULT> curry(
+			final Function4<? super P1, ? super P2, ? super P3, ? super P4, ? extends RESULT> function, final P1 argument) {
+		if (function == null)
+			throw new NullPointerException("function");
+		return new Function3<P2, P3, P4, RESULT>() {
+			@Override
+			public RESULT apply(P2 p2, P3 p3, P4 p4) {
+				return function.apply(argument, p2, p3, p4);
+			}
+		};
+	}
+
+	/**
+	 * Curries a function that takes five arguments.
+	 * 
+	 * @param function
+	 *            the original function. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code function}.
+	 * @return a function that takes four arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, P3, P4, P5, RESULT> Function4<P2, P3, P4, P5, RESULT> curry(
+			final Function5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? extends RESULT> function, final P1 argument) {
+		if (function == null)
+			throw new NullPointerException("function");
+		return new Function4<P2, P3, P4, P5, RESULT>() {
+			@Override
+			public RESULT apply(P2 p2, P3 p3, P4 p4, P5 p5) {
+				return function.apply(argument, p2, p3, p4, p5);
+			}
+		};
+	}
+
+	/**
+	 * Curries a function that takes six arguments.
+	 * 
+	 * @param function
+	 *            the original function. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code function}.
+	 * @return a function that takes five arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, P3, P4, P5, P6, RESULT> Function5<P2, P3, P4, P5, P6, RESULT> curry(
+			final Function6<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? super P6, ? extends RESULT> function, final P1 argument) {
+		if (function == null)
+			throw new NullPointerException("function");
+		return new Function5<P2, P3, P4, P5, P6, RESULT>() {
+			@Override
+			public RESULT apply(P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
+				return function.apply(argument, p2, p3, p4, p5, p6);
+			}
+		};
+	}
+	
+	
+	/**
+	 * Returns a composed function that first applies the {@code before}
+	 * function to its input, and then applies the {@code after} function to the result.
+	 * If evaluation of either function throws an exception, it is relayed to
+	 * the caller of the composed function.
+	 *
+	 * @param <V> the type of input to the {@code before} function, and to the
+	 *        composed function
+	 * @param <T> the type of output of the {@code before} function, and input to the
+	 *        {@code after} function
+	 * @param <R> the type of output to the {@code after} function, and to the
+	 *        composed function
+	 * @param after the function to apply after the before function is applied
+	 * @param before the function to apply before the after function is applied
+	 * @return a composed function that first applies the {@code before}
+	 * function and then applies the {@code after} function
+	 * @throws NullPointerException if {@code before} or {@code after} is <code>null</code>
+	 *
+	 * @see #andThen(Functions.Function1, Functions.Function1)
+	 * @since 2.9
+	 */
+	public static <V,T,R> Function1<V, R> compose(final Function1<? super T, ? extends R> after, final Function1<? super V, ? extends T> before) {
+		if (after == null)
+			throw new NullPointerException("after");
+		if (before == null)
+			throw new NullPointerException("before");
+		return new Function1<V,R>() {
+			@Override
+			public R apply(V v) {
+				return after.apply(before.apply(v));
+			}
+		};
+	}
+	
+	/**
+	 * Returns a composed function that first applies the {@code before}
+	 * function to its input, and then applies the {@code after} function to the result.
+	 * If evaluation of either function throws an exception, it is relayed to
+	 * the caller of the composed function.
+	 *
+	 * @param <V> the type of input to the {@code before} function, and to the composed function
+	 * @param <T> the type of output of the {@code before} function, and input to the {@code after} function
+	 * @param <R> the type of output to the {@code after} function, and to the composed function
+	 * @param before the function to apply before the after function is applied
+	 * @param after the function to apply after the before function is applied
+	 * @return a composed function that first applies the {@code before}
+	 * function and then applies the {@code after} function
+	 * @throws NullPointerException if {@code before} or {@code after} is <code>null</code>
+	 *
+	 * @see #compose(Functions.Function1, Functions.Function1)
+	 * @since 2.9
+	 */
+	public static <V,T,R> Function1<V, R> andThen(final Function1<? super V, ? extends T> before, final Function1<? super T, ? extends R> after) {
+		return compose(after, before);
+	}
+	
+	/**
+	 * Returns a composed function that first applies the {@code before}
+	 * function to its input, and then applies the {@code after} function to the result.
+	 * If evaluation of either function throws an exception, it is relayed to
+	 * the caller of the composed function.
+	 *
+	 * @param <V1> the type of the first parameter to the {@code before} function, and to the composed function
+	 * @param <V2> the type of the second parameter to the {@code before} function, and to the composed function
+	 * @param <T> the type of output of the {@code before} function, and input to the {@code after} function
+	 * @param <R> the type of output to the {@code after} function, and to the composed function
+	 * @param before the function to apply before the {@code after} function is applied
+	 * @param after the function to apply after the {@code before} function is applied
+	 * @return a composed function that first applies the {@code before}
+	 * function and then applies the {@code after} function
+	 * @throws NullPointerException if {@code before} or {@code after} is null
+	 *
+	 * @see #compose(Functions.Function1, Functions.Function1)
+	 * @since 2.9
+	 */
+	public static <V1,V2,T,R> Function2<V1, V2, R> andThen(final Function2<? super V1,? super V2, ? extends T> before, final Function1<? super T, ? extends R> after) {
+		if (after == null)
+			throw new NullPointerException("after");
+		if (before == null)
+			throw new NullPointerException("before");
+		return new Function2<V1, V2, R>() {
+			@Override
+			public R apply(V1 v1, V2 v2) {
+				return after.apply(before.apply(v1, v2));
+			}
+		};
+	}
+	
+	
+	/**
+	 * Returns a composed {@code Procedure1} that performs, in sequence, the {@code before}
+	 * operation followed by the {@code after} operation. If performing either
+	 * operation throws an exception, it is relayed to the caller of the
+	 * composed operation. If performing the {@code before} operation throws an exception,
+	 * the {@code after} operation will not be performed.
+	 *
+	 * @param <T> the type of input for the {@code before} operation
+	 * @param before the operation to perform first
+	 * @param after the operation to perform afterwards
+	 * @return a composed {@code Procedure1} that performs in sequence the {@code before}
+	 * operation followed by the {@code after} operation
+	 * @throws NullPointerException if {@code before} or {@code after} is null
+	 * @since 2.9
+	 */
+	public static <T> Procedure1<T> andThen(final Procedure1<? super T> before, final Procedure1<? super T> after) {
+		if (after == null)
+			throw new NullPointerException("after");
+		if (before == null)
+			throw new NullPointerException("before");
+		return new Procedures.Procedure1<T>() {
+			@Override
+			public void apply(T p) {
+				before.apply(p);
+				after.apply(p);
+			}
+		};
+	}
+	
+	/**
+	 * Returns a composed {@code Procedure1} that performs, in sequence, the {@code before}
+	 * operation followed by the {@code after} operation. If performing either
+	 * operation throws an exception, it is relayed to the caller of the
+	 * composed operation. If performing the {@code before} operation throws an exception,
+	 * the {@code after} operation will not be performed.
+	 *
+	 * @param before the operation to perform first
+	 * @param after the operation to perform afterwards
+	 * @return a composed {@code Procedure1} that performs in sequence the {@code before}
+	 * operation followed by the {@code after} operation
+	 * @throws NullPointerException if {@code before} or {@code after} is null
+	 * @since 2.9
+	 */
+	public static Procedure0 andThen(final Procedure0 before, final Procedure0 after) {
+		if (after == null)
+			throw new NullPointerException("after");
+		if (before == null)
+			throw new NullPointerException("before");
+		return new Procedures.Procedure0() {
+			@Override
+			public void apply() {
+				before.apply();
+				after.apply();
+			}
+		};
+	}
+	
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Functions.java b/java/org/eclipse/xtext/xbase/lib/Functions.java
new file mode 100644
index 0000000..8bae150
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Functions.java
@@ -0,0 +1,161 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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 class serves as a container for the various function types that are used to implement the type of closures in
+ * Xbase.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @see FunctionExtensions
+ * @see Procedures
+ */
+@GwtCompatible public interface Functions {
+
+	/**
+	 * A function without any parameters.
+	 * 
+	 * @param <Result>
+	 *            the result of the single closure {@link #apply() method}.
+	 */
+	interface Function0<Result> {
+
+		Result apply();
+
+	}
+
+	/**
+	 * A function that takes one argument.
+	 * 
+	 * @param <Param>
+	 *            the only argument that is passed to the {@link #apply(Object) closure}
+	 * @param <Result>
+	 *            the result of the single closure {@link #apply(Object) method}.
+	 */
+	interface Function1<Param, Result> {
+
+		Result apply(Param p);
+
+	}
+
+	/**
+	 * A function that takes two arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the {@link #apply(Object, Object) closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the {@link #apply(Object, Object) closure}
+	 * @param <Result>
+	 *            the result of the single closure {@link #apply(Object, Object) method}.
+	 */
+	interface Function2<P1, P2, Result> {
+
+		Result apply(P1 p1, P2 p2);
+
+	}
+
+	/**
+	 * A function that takes three arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the {@link #apply(Object, Object, Object) closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the {@link #apply(Object, Object, Object) closure}
+	 * @param <P3>
+	 *            the third argument that is passed to the {@link #apply(Object, Object, Object) closure}
+	 * @param <Result>
+	 *            the result of the single closure {@link #apply(Object, Object, Object) method}.
+	 */
+	interface Function3<P1, P2, P3, Result> {
+
+		Result apply(P1 p1, P2 p2, P3 p3);
+
+	}
+
+	/**
+	 * A function that takes four arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the {@link #apply(Object, Object, Object, Object) closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the {@link #apply(Object, Object, Object, Object) closure}
+	 * @param <P3>
+	 *            the third argument that is passed to the {@link #apply(Object, Object, Object, Object) closure}
+	 * @param <P4>
+	 *            the fourth argument that is passed to the {@link #apply(Object, Object, Object, Object) closure}
+	 * @param <Result>
+	 *            the result of the single closure {@link #apply(Object, Object, Object, Object) method}.
+	 */
+	interface Function4<P1, P2, P3, P4, Result> {
+
+		Result apply(P1 p1, P2 p2, P3 p3, P4 p4);
+
+	}
+
+	/**
+	 * A function that takes five arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <P3>
+	 *            the third argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <P4>
+	 *            the fourth argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <P5>
+	 *            the fifth argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <Result>
+	 *            the result of the single closure {@link #apply(Object, Object, Object, Object, Object) method}.
+	 */
+	interface Function5<P1, P2, P3, P4, P5, Result> {
+
+		Result apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5);
+
+	}
+
+	/**
+	 * A function that takes six arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P3>
+	 *            the third argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P4>
+	 *            the fourth argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P5>
+	 *            the fifth argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P6>
+	 *            the sixth argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <Result>
+	 *            the result of the single closure {@link #apply(Object, Object, Object, Object, Object, Object) method}
+	 *            .
+	 */
+	interface Function6<P1, P2, P3, P4, P5, P6, Result> {
+
+		Result apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6);
+
+	}
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/HardcodedInInterpreterException.java b/java/org/eclipse/xtext/xbase/lib/HardcodedInInterpreterException.java
new file mode 100644
index 0000000..fab2367
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/HardcodedInInterpreterException.java
@@ -0,0 +1,25 @@
+/*******************************************************************************
+ * 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.xtext.xbase.lib;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * This exception is thrown if a method was invoked directly though it is usually inlined by the compiler by means of
+ * the {@link Inline @Inline annotation} and executed in a custom manner by the interpreter.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @since 2.6
+ */
+@GwtCompatible
+class HardcodedInInterpreterException extends RuntimeException {
+
+	private static final long serialVersionUID = 1L;
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Inline.java b/java/org/eclipse/xtext/xbase/lib/Inline.java
new file mode 100644
index 0000000..21ee0eb
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Inline.java
@@ -0,0 +1,86 @@
+/*******************************************************************************
+ * 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 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;
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * Allows to describe how a certain static function should be inlined by the Xbase compiler.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @since 2.3
+ */
+@Beta
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.METHOD })
+@GwtCompatible
+public @interface Inline {
+
+	/**
+	 * <p>
+	 * The inline format string. Placeholders like {@code $1, $2} etc can be used where the {@code 1..n} parameters of
+	 * the inlined method are used for {@code $1} to {@code $n} and the {@link #imported()} types are used for
+	 * subsequent indices. The next index {@code $n} can be used to insert all type parameters of the original
+	 * declaration. And finally the last indices refer to the upper bound substitute of the type parameters
+	 * individually.
+	 * </p>
+	 * <p>
+	 * So the order is arguments, imports, all type parameters at once incl. brackets and upper bounds of the individual
+	 * type parameters without brackets
+	 * </p>
+	 * <p>
+	 * For the following signature <br/>
+	 * {@code @Inline(value=".." imported = BigDecimal.class) public void <T1, T2> myMethod(String p1, String p2)}
+	 * </p>
+	 * <ul>
+	 * <li>
+	 * {@code $1} refers to {@code p1}</li>
+	 * <li>
+	 * {@code $2} refers to {@code p2}</li>
+	 * <li>
+	 * {@code $3} refers to {@code BigDecimal}</li>
+	 * <li>
+	 * {@code $4} refers to {@code <T1, T2>}</li>
+	 * <li>
+	 * {@code $5} refers to the upper bound of {@code T1}</li>
+	 * <li>
+	 * {@code $6} refers to the upper bound of {@code T2}</li>
+	 * </ul>
+	 * 
+	 */
+	String value();
+
+	/**
+	 * Types that should be imported to inline the operation.
+	 */
+	Class<?>[] imported() default {};
+
+	/**
+	 * Whether the inlined expression is a statement expression (see <a
+	 * href="http://docs.oracle.com/javase/specs/jls/se5.0/html/statements.html#14.8">14.8 - Statement Expressions in
+	 * Java Language Specification, Third Edition</a> )
+	 */
+	boolean statementExpression() default false;
+
+	/**
+	 * Whether the compiled Java is a constant expression operator. (see <a
+	 * href="http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28">15.28. Constant Expressions in Java
+	 * Language Specification, Third Edition</a>
+	 * 
+	 * @since 2.5
+	 */
+	boolean constantExpression() default false;
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/InputOutput.java b/java/org/eclipse/xtext/xbase/lib/InputOutput.java
new file mode 100644
index 0000000..4e051b8
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/InputOutput.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.xtext.xbase.lib;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * Utilities to print information to the console.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ */
+@GwtCompatible public class InputOutput {
+
+	/**
+	 * Prints a newline to standard out, by delegating directly to <code>System.out.println()</code>
+	 * @since 2.3
+	 */
+	public static void println() {
+		System.out.println();
+	}
+	/**
+	 * Prints the given {@code object} to {@link System#out System.out} and terminate the line. Useful to log partial
+	 * expressions to trap errors, e.g. the following is possible: <code>println(1 + println(2)) + 3</code>
+	 * 
+	 * @param object
+	 *            the to-be-printed object
+	 * @return the printed object.
+	 */
+	public static <T> T println(T object) {
+		System.out.println(object);
+		return object;
+	}
+
+	/**
+	 * Prints the given {@code object} to {@link System#out System.out}. Useful to log partial expressions to trap
+	 * errors, e.g. the following is possible: <code>1 + print(2) + 3</code>
+	 * 
+	 * @param o
+	 *            the to-be-printed object
+	 * @return the printed object.
+	 */
+	public static <T> T print(T o) {
+		System.out.print(o);
+		return o;
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/IntegerExtensions.java b/java/org/eclipse/xtext/xbase/lib/IntegerExtensions.java
new file mode 100644
index 0000000..f573d88
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/IntegerExtensions.java
@@ -0,0 +1,1680 @@
+/*******************************************************************************
+ * 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;
+
+
+
+/**
+ * This is an extension library for {@link Integer integral numbers}, e.g. <code>int</code> or <code>Integer</code>.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * @author Jan Koehnlein - Primitive versions
+ * @since 2.3
+ */
+@GwtCompatible public class IntegerExtensions {
+	
+	/**
+	 * The <code>..</code> operator yields an {@link IntegerRange}.
+	 * 
+	 * @param a the start of the range.
+	 * @param b the end of the range.
+	 * @return an {@link IntegerRange}. Never <code>null</code>.
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="new $3($1, $2)", imported=IntegerRange.class, statementExpression=false)
+	public static IntegerRange operator_upTo(final int a, final int b) {
+		return new IntegerRange(a, b);
+	}
+	
+	/**
+	 * The <code>..&lt;</code> operator yields an {@link ExclusiveRange} that increments from
+	 * a to b (exclusive).
+	 * 
+	 * @param a the start of the range.
+	 * @param b the end of the range (exclusive).
+	 * @return an incrementing {@link ExclusiveRange}. Never <code>null</code>.
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="new $3($1, $2, true)", imported=ExclusiveRange.class, statementExpression=false)
+	public static ExclusiveRange operator_doubleDotLessThan(final int a, final int b) {
+		return new ExclusiveRange(a, b, true);
+	}
+	
+	/**
+	 * The <code>&gt;..</code> operator yields an {@link ExclusiveRange} that decrements from a
+	 * (exclusive) down to b.
+	 * 
+	 * @param a the start of the range (exclusive).
+	 * @param b the end of the range.
+	 * @return a decrementing {@link ExclusiveRange}. Never <code>null</code>.
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="new $3($1, $2, false)", imported=ExclusiveRange.class, statementExpression=false)
+	public static ExclusiveRange operator_greaterThanDoubleDot(final int a, final int b) {
+		return new ExclusiveRange(a, b, false);
+	}
+	
+	/**
+	 * The bitwise inclusive <code>or</code> operation. This is the equivalent to the java <code>|</code> operator.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param b
+	 *            an integer.
+	 * @return <code>a|b</code>
+	 */
+	@Pure
+	@Inline(value="($1 | $2)", constantExpression=true)
+	public static int bitwiseOr(int a, int b) {
+		return a | b;
+	}
+
+	/**
+	 * The bitwise exclusive <code>or</code> operation. This is the equivalent to the java <code>^</code> operator.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param b
+	 *            an integer.
+	 * @return <code>a^b</code>
+	 */
+	@Pure
+	@Inline(value="($1 ^ $2)", constantExpression=true)
+	public static int bitwiseXor(int a, int b) {
+		return a ^ b;
+	}
+
+	/**
+	 * The bitwise <code>and</code> operation. This is the equivalent to the java <code>&amp;</code> operator.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param b
+	 *            an integer.
+	 * @return <code>a&amp;b</code>
+	 */
+	@Pure
+	@Inline(value="($1 & $2)", constantExpression=true)
+	public static int bitwiseAnd(int a, int b) {
+		return a & b;
+	}
+
+	/**
+	 * The bitwise complement operation. This is the equivalent to the java <code>~</code> operator.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @return the bitwise complement of <code>a</code>.
+	 */
+	@Pure
+	@Inline(value="(~$1)", constantExpression=true)
+	public static int bitwiseNot(int a) {
+		return ~a;
+	}
+
+	/**
+	 * The binary <code>signed left shift</code> operator. This is the equivalent to the java <code>&lt;&lt;</code> operator.
+	 * Fills in a zero as the least significant bit.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param distance 
+	 *            the number of times to shift.
+	 * @return <code>a&lt;&lt;distance</code>
+	 * @deprecated use {@link #operator_doubleLessThan(int, int)} instead
+	 */
+	@Pure
+	@Inline(value="($1 << $2)", constantExpression=true)
+	@Deprecated
+	public static int shiftLeft(int a, int distance) {
+		return a << distance;
+	}
+	
+	/**
+	 * The binary <code>signed left shift</code> operator. This is the equivalent to the java <code>&lt;&lt;</code> operator.
+	 * Fills in a zero as the least significant bit.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param distance 
+	 *            the number of times to shift.
+	 * @return <code>a&lt;&lt;distance</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 << $2)", constantExpression=true)
+	public static int operator_doubleLessThan(int a, int distance) {
+		return a << distance;
+	}
+
+	/**
+	 * The binary <code>signed right sift</code> operator. This is the equivalent to the java <code>&gt;&gt;</code> operator.
+	 * Shifts in the value of the sign bit as the leftmost bit, thus preserving the sign of the initial value.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param distance 
+	 *            the number of times to shift.
+	 * @return <code>a&gt;&gt;distance</code>
+	 * @deprecated use {@link #operator_doubleGreaterThan(int, int)} instead
+	 */
+	@Pure
+	@Inline(value="($1 >> $2)", constantExpression=true)
+	@Deprecated
+	public static int shiftRight(int a, int distance) {
+		return a >> distance;
+	}
+	
+	/**
+	 * The binary <code>signed right sift</code> operator. This is the equivalent to the java <code>&gt;&gt;</code> operator.
+	 * Shifts in the value of the sign bit as the leftmost bit, thus preserving the sign of the initial value.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param distance 
+	 *            the number of times to shift.
+	 * @return <code>a&gt;&gt;distance</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >> $2)", constantExpression=true)
+	public static int operator_doubleGreaterThan(int a, int distance) {
+		return a >> distance;
+	}
+
+	/**
+	 * The binary <code>unsigned right shift</code> operator. This is the equivalent to the java <code>&gt;&gt;&gt;</code> operator.
+	 * Shifts in zeros into as leftmost bits, thus always yielding a positive integer.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param distance
+	 *            the number of times to shift.
+	 * @return <code>a&gt;&gt;&gt;distance</code>
+	 * @deprecated use {@link #operator_tripleGreaterThan(int, int)} instead
+	 */
+	@Pure
+	@Inline(value="($1 >>> $2)", constantExpression=true)
+	@Deprecated
+	public static int shiftRightUnsigned(int a, int distance) {
+		return a >>> distance;
+	}
+	
+	/**
+	 * The binary <code>unsigned right shift</code> operator. This is the equivalent to the java <code>&gt;&gt;&gt;</code> operator.
+	 * Shifts in zeros into as leftmost bits, thus always yielding a positive integer.
+	 * 
+	 * @param a
+	 *            an integer.
+	 * @param distance
+	 *            the number of times to shift.
+	 * @return <code>a&gt;&gt;&gt;distance</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >>> $2)", constantExpression=true)
+	public static int operator_tripleGreaterThan(int a, int distance) {
+		return a >>> distance;
+	}
+
+	// BEGIN generated code
+	/**
+	 * The unary <code>minus</code> operator. This is the equivalent to the Java's <code>-</code> function.
+	 * 
+	 * @param i  an integer.
+	 * @return   <code>-i</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="(-$1)", constantExpression=true)
+	public static int operator_minus(int i) {
+		return -i;
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param i  an integer.
+	 * @return   <code>i--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static int operator_minusMinus(int i) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param i  an integer.
+	 * @return   <code>i--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static Integer operator_minusMinus(Integer i) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param i  an integer.
+	 * @return   <code>i++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static int operator_plusPlus(int i) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param i  an integer.
+	 * @return   <code>i++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static Integer operator_plusPlus(Integer i) {
+		throw new HardcodedInInterpreterException();
+	}
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a double.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(int a, double b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a double.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(int a, double b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a double.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(int a, double b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a double.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(int a, double b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a double.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int a, double b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a double.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(int a, double b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a double.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @param b  a double.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(int 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  an integer.
+	 * @param b  a double.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(int a, double b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a float.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(int a, float b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a float.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(int a, float b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a float.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(int a, float b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a float.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(int a, float b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a float.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int a, float b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a float.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(int a, float b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a float.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @param b  a float.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(int 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  an integer.
+	 * @param b  a float.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(int a, float b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a long.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(int a, long b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a long.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(int a, long b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a long.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(int a, long b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a long.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(int a, long b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a long.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int a, long b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a long.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(int a, long b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a long.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @param b  a long.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(int 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  an integer.
+	 * @param b  a long.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(int a, long b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(int a, int b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(int a, int b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(int a, int b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(int a, int b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int a, int b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(int a, int b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(int 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  an integer.
+	 * @param b  an integer.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(int a, int b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a character.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(int a, char b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a character.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(int a, char b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a character.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(int a, char b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a character.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(int a, char b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a character.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int a, char b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a character.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(int a, char b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a character.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @param b  a character.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(int 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  an integer.
+	 * @param b  a character.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(int a, char b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a short.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(int a, short b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a short.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(int a, short b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a short.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(int a, short b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a short.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(int a, short b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a short.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @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(int a, short b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a short.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(int a, short b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a short.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(int 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  an integer.
+	 * @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(int 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  an integer.
+	 * @param b  a short.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(int 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  an integer.
+	 * @param b  a short.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(int a, short b) {
+		return a != b;
+	}
+	
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(int a, byte b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(int a, byte b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(int a, byte b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(int a, byte b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(int a, byte b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(int a, byte b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(int a, byte b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(int a, byte b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(int a, byte b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(int a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(int a, byte 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  an integer.
+	 * @param b  a byte.
+	 * @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(int a, byte b) {
+		return Math.pow(a, b);
+	}
+	
+	/**
+	 * The <code>identity equals</code> operator. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(int a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  an integer.
+	 * @param b  a byte.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(int a, byte b) {
+		return a != b;
+	}
+	
+	// END generated code
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/IntegerRange.java b/java/org/eclipse/xtext/xbase/lib/IntegerRange.java
new file mode 100644
index 0000000..7574c66
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/IntegerRange.java
@@ -0,0 +1,202 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 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.xtext.xbase.lib;
+
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * A sequence of integers starting from <code>start</code> up to <code>end</code> with an increment of <code>step</code>. 
+ * The value of <code>start</code> is always included. 
+ * The value of <code>end</code> is included only if the difference between <code>end-start</code> is a multiple of <code>step</code>. 
+ * The <code>step</code> can be positive or negative, but never 0. It must have the same signum as of <code>end-start</code>.
+ * 
+ * @author Jan Koehnlein - Initial contribution and API
+ * @author Karsten Thoms - Bug#381140
+ * @since 2.3
+ */
+@GwtCompatible public class IntegerRange implements Iterable<Integer> {
+
+	private final int start;
+	private final int end;
+	private final int step;
+
+	/**
+	 * @return a read-only {@link ListIterator} for this.
+	 */
+	@Override
+	@Pure
+	public ListIterator<Integer> iterator() {
+		return new RangeIterator();
+	}
+
+	/**
+	 * Constructs a new IntegerRange object.
+	 * The step will be set to -1 if end&lt;start or to 1 otherwise.
+	 * 
+	 * @param start
+	 *            the start value (inclusive)
+	 * @param end
+	 *            the end value (inclusive)
+	 */
+	@Pure
+	public IntegerRange(int start, int end) {
+		this(start, end, end >= start ? 1 : -1);
+	}
+
+	/**
+	 * Constructs a new IntegerRange object.
+	 * 
+	 * @param start
+	 *            the start value (inclusive)
+	 * @param end
+	 *            the end value (inclusive if end-start%step == 0)
+	 * @param step
+	 *            the increment
+	 */
+	@Pure
+	public IntegerRange(int start, int end, int step) {
+		if ((start < end) && step < 0 || (start > end) && step > 0)
+			throw new IllegalArgumentException("The step of an IntegerRange must have the correct sign.");
+		if (step == 0)
+			throw new IllegalArgumentException("The step of an IntegerRange must not be 0");
+		this.start = start;
+		this.end = end;
+		this.step = step;
+	}
+
+	/**
+	 * @return the start value
+	 */
+	@Pure
+	public int getStart() {
+		return start;
+	}
+
+	/**
+	 * @return the step value
+	 */
+	@Pure
+	public int getStep() {
+		return step;
+	}
+
+	/**
+	 * @return the end value
+	 */
+	@Pure
+	public int getEnd() {
+		return end;
+	}
+
+	/**
+	 * Returns the number of elements in this IntegerRange. That is <em>not</em> the length of the interval,
+	 * but <code>(end-start)/step + 1</code>.
+	 * @return the number of elements in this IntegerRange.
+	 */
+	@Pure
+	public int getSize() {
+		return (end - start) / step + 1;
+	}
+
+	/**
+	 * @param step
+	 *            the step of the new range.
+	 * @return a new IntegerRange with the given step.
+	 */
+	@Pure
+	public IntegerRange withStep(int step) {
+		return new IntegerRange(start, end, step);
+	}
+
+	/**
+	 * Checks whether this contains the given number, i.e. whether the iterator will yield the number. This is different
+	 * from interval containment: <code>0..2.by(2)</code> will <em>not</em> contain 1.
+	 * 
+	 * @param number
+	 *            the number to be checked for containment.
+	 * @return whether this sequence contains the given number or not.
+	 */
+	@Pure
+	public boolean contains(int number) {
+		if (step < 0)
+			return number <= start && number >= end && (number - start) % step == 0;
+		else
+			return number >= start && number <= end && (number - start) % step == 0;
+	}
+
+	/**
+	 * @author Jan Koehnlein - Initial contribution and API
+	 */
+	private class RangeIterator implements ListIterator<Integer> {
+
+		private int next = start;
+		private int nextIndex = 0;
+
+		@Override
+		public boolean hasNext() {
+			if (step < 0)
+				return next >= end;
+			else
+				return next <= end;
+		}
+
+		@Override
+		public Integer next() {
+			if (!hasNext()) {
+				throw new NoSuchElementException();
+			}
+			int value = next;
+			next += step;
+			++nextIndex;
+			return value;
+		}
+
+		@Override
+		public boolean hasPrevious() {
+			return nextIndex > 0;
+		}
+
+		@Override
+		public Integer previous() {
+			if (nextIndex <= 0)
+				throw new NoSuchElementException();
+			--nextIndex;
+			next -= step;
+			return next;
+		}
+
+		@Override
+		public int nextIndex() {
+			return nextIndex;
+		}
+
+		@Override
+		public int previousIndex() {
+			return nextIndex - 1;
+		}
+
+		@Override
+		public void remove() {
+			throw new UnsupportedOperationException("Cannot remove elements from a Range");
+		}
+
+		@Override
+		public void set(Integer e) {
+			throw new UnsupportedOperationException("Cannot set elements in a Range");
+		}
+
+		@Override
+		public void add(Integer e) {
+			throw new UnsupportedOperationException("Cannot add elements to a Range");
+		}
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/IterableExtensions.java b/java/org/eclipse/xtext/xbase/lib/IterableExtensions.java
new file mode 100644
index 0000000..33eafb0
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/IterableExtensions.java
@@ -0,0 +1,1000 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.xtext.xbase.lib;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.Functions.Function2;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
+import org.eclipse.xtext.xbase.lib.internal.BooleanFunctionDelegate;
+import org.eclipse.xtext.xbase.lib.internal.FunctionDelegate;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * This is an extension library for {@link Iterable iterables}.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * @author Sebastian Zarnekow
+ */
+@GwtCompatible
+public class IterableExtensions {
+
+	/**
+	 * <p>
+	 * Concatenates two iterables into a single iterable. The returned iterable has an iterator that traverses the
+	 * elements in {@code a}, followed by the elements in {@code b}. The resulting iterable is effectivly a view on the
+	 * source iterables. That is, the source iterators are not polled until necessary and the result will reflect
+	 * changes in the sources.
+	 * </p>
+	 * <p>
+	 * The returned iterable's iterator supports {@code remove()} when the corresponding input iterator supports it.
+	 * </p>
+	 * 
+	 * @param a
+	 *            the first iterable. May not be <code>null</code>.
+	 * @param b
+	 *            the second iterable. May not be <code>null</code>.
+	 * @return a combined iterable. Never <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$3.$4concat($1, $2)", imported=Iterables.class)
+	public static <T> Iterable<T> operator_plus(Iterable<? extends T> a, Iterable<? extends T> b) {
+		return Iterables.concat(a, b);
+	}
+
+	/**
+	 * Finds the first element in the given iterable that fulfills the predicate. If none is found or the iterable is
+	 * empty, <code>null</code> is returned.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return the first element in the iterable for which the given predicate returns <code>true</code>, returns
+	 *         <code>null</code> if no element matches the predicate or the iterable is empty.
+	 */
+	public static <T> T findFirst(Iterable<T> iterable, Function1<? super T, Boolean> predicate) {
+		return IteratorExtensions.findFirst(iterable.iterator(), predicate);
+	}
+
+	/**
+	 * Finds the last element in the given iterable that fulfills the predicate. If none is found or the iterable is
+	 * empty, <code>null</code> is returned.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return the last element in the iterable for which the given predicate returns <code>true</code>, returns
+	 *         <code>null</code> if no element matches the predicate or the iterable is empty.
+	 */
+	public static <T> T findLast(Iterable<T> iterable, Functions.Function1<? super T, Boolean> predicate) {
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		if (iterable instanceof List<?>) {
+			List<T> list = (List<T>) iterable;
+			ListIterator<T> iterator = list.listIterator(list.size());
+			while (iterator.hasPrevious()) {
+				T t = iterator.previous();
+				if (predicate.apply(t))
+					return t;
+			}
+			return null;
+		} else {
+			return IteratorExtensions.findLast(iterable.iterator(), predicate);
+		}
+	}
+
+	/**
+	 * Returns the first element in the given iterable or <code>null</code> if empty.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @return the first element in the iterable or <code>null</code>.
+	 */
+	public static <T> T head(Iterable<T> iterable) {
+		return IteratorExtensions.head(iterable.iterator());
+	}
+
+	/**
+	 * Returns a view on this iterable that contains all the elements except the first.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @return an iterable with all elements except the first. Never <code>null</code>.
+	 * @see #drop(Iterable, int)
+	 */
+	public static <T> Iterable<T> tail(final Iterable<T> iterable) {
+		return drop(iterable, 1);
+	}
+
+	/**
+	 * Returns the last element in the given iterable or <code>null</code> if empty.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @return the last element in the iterable or <code>null</code>.
+	 */
+	public static <T> T last(Iterable<T> iterable) {
+		if (iterable instanceof List<?>) {
+			List<T> list = (List<T>) iterable;
+			if (list.isEmpty())
+				return null;
+			return list.get(list.size() - 1);
+		} else if (iterable instanceof SortedSet) {
+			SortedSet<T> sortedSet = (SortedSet<T>) iterable;
+			if (sortedSet.isEmpty())
+				return null;
+			return sortedSet.last();
+		} else {
+			return IteratorExtensions.last(iterable.iterator());
+		}
+	}
+
+	/**
+	 * Returns a view on this iterable that provides at most the first <code>count</code> entries.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param count
+	 *            the number of elements that should be returned at most.
+	 * @return an iterable with <code>count</code> elements. Never <code>null</code>.
+	 * @throws IllegalArgumentException
+	 *             if <code>count</code> is negative.
+	 */
+	public static <T> Iterable<T> take(final Iterable<T> iterable, final int count) {
+		if (iterable == null)
+			throw new NullPointerException("iterable");
+		if (count < 0)
+			throw new IllegalArgumentException("Cannot take a negative number of elements. Argument 'count' was: "
+					+ count);
+		if (count == 0)
+			return Collections.emptyList();
+		return new Iterable<T>() {
+			@Override
+			public Iterator<T> iterator() {
+				return IteratorExtensions.take(iterable.iterator(), count);
+			}
+		};
+	}
+
+	/**
+	 * Returns a view on this iterable that provides all elements except the first <code>count</code> entries.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param count
+	 *            the number of elements that should be dropped.
+	 * @return an iterable without the first <code>count</code> elements. Never <code>null</code>.
+	 * @throws IllegalArgumentException
+	 *             if <code>count</code> is negative.
+	 */
+	@Pure
+	public static <T> Iterable<T> drop(final Iterable<T> iterable, final int count) {
+		if (iterable == null)
+			throw new NullPointerException("iterable");
+		if (count == 0)
+			return iterable;
+		if (count < 0)
+			throw new IllegalArgumentException("Cannot drop a negative number of elements. Argument 'count' was: "
+					+ count);
+		return new Iterable<T>() {
+			@Override
+			public Iterator<T> iterator() {
+				return IteratorExtensions.drop(iterable.iterator(), count);
+			}
+		};
+	}
+
+	/**
+	 * Returns {@code true} if one or more elements in {@code iterable} satisfy the predicate.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return <code>true</code> if one or more elements in {@code iterable} satisfy the predicate.
+	 */
+	public static <T> boolean exists(Iterable<T> iterable, Function1<? super T, Boolean> predicate) {
+		return IteratorExtensions.exists(iterable.iterator(), predicate);
+	}
+
+	/**
+	 * Returns {@code true} if every element in {@code iterable} satisfies the predicate. If {@code iterable} is empty,
+	 * {@code true} is returned. In other words, <code>false</code> is returned if at least one element fails to fulfill
+	 * the predicate.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return <code>true</code> if every element in {@code iterable} satisfies the predicate and also if there is no element.
+	 */
+	public static <T> boolean forall(Iterable<T> iterable, Function1<? super T, Boolean> predicate) {
+		return IteratorExtensions.forall(iterable.iterator(), predicate);
+	}
+
+	/**
+	 * Returns the elements of {@code unfiltered} that satisfy a predicate. The resulting iterable's iterator does not
+	 * support {@code remove()}. The returned iterable is a view on the original elements. Changes in the unfiltered
+	 * original are reflected in the view.
+	 * 
+	 * @param unfiltered
+	 *            the unfiltered iterable. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return an iterable that contains only the elements that fulfill the predicate. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T> Iterable<T> filter(Iterable<T> unfiltered, Function1<? super T, Boolean> predicate) {
+		return Iterables.filter(unfiltered, new BooleanFunctionDelegate<T>(predicate));
+	}
+
+	/**
+	 * Returns the elements of {@code unfiltered} that do not satisfy a predicate. The resulting iterable's iterator does not
+	 * support {@code remove()}. The returned iterable is a view on the original elements. Changes in the unfiltered
+	 * original are reflected in the view.
+	 *
+	 * @param unfiltered
+	 *            the unfiltered iterable. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return an iterable that contains only the elements that do not fulfill the predicate. Never <code>null</code>.
+	 *
+	 * @since 2.11
+	 */
+	@Pure
+	public static <T> Iterable<T> reject(Iterable<T> unfiltered, Function1<? super T, Boolean> predicate) {
+		return Iterables.filter(unfiltered, Predicates.not(new BooleanFunctionDelegate<T>(predicate)));
+	}
+
+	/**
+	 * Returns the elements of {@code unfiltered} that are not instanceof {@code type}. The resulting iterable's iterator does not
+	 * support {@code remove()}. The returned iterable is a view on the original elements. Changes in the unfiltered
+	 * original are reflected in the view.
+	 *
+	 * @param unfiltered
+	 *            the unfiltered iterable. May not be <code>null</code>.
+	* @param type
+	 *            the type of elements undesired. May not be <code>null</code>.
+	 * @return an iterable that contains only the elements that are not instances of {@code type}. Never <code>null</code>.
+	 *         Note that the elements of the iterable can be null as null is an instance of nothing.
+	 *
+	 * @since 2.15
+	 */
+	@GwtIncompatible("Class.isInstance")
+	@Pure
+	public static <T> Iterable<T> reject(Iterable<T> unfiltered, Class<?> type) {
+		return filter(unfiltered, (t) -> !type.isInstance(t));
+	}
+
+	/**
+	 * Returns all instances of class {@code type} in {@code unfiltered}. The returned iterable has elements whose class
+	 * is {@code type} or a subclass of {@code type}. The returned iterable's iterator does not support {@code remove()}
+	 * . The returned iterable is a view on the original elements. Changes in the unfiltered original are reflected in
+	 * the view.
+	 * 
+	 * @param unfiltered
+	 *            the unfiltered iterable. May not be <code>null</code>.
+	 * @param type
+	 *            the type of elements desired
+	 * @return an unmodifiable iterable containing all elements of the original iterable that were of the requested
+	 *         type. Never <code>null</code>.
+	 */
+	@GwtIncompatible("Class.isInstance")
+	@Pure
+	@Inline(value="$3.$4filter($1, $2)", imported=Iterables.class)
+	public static <T> Iterable<T> filter(Iterable<?> unfiltered, Class<T> type) {
+		return Iterables.filter(unfiltered, type);
+	}
+	
+	/**
+	 * Returns a new iterable filtering any null references.
+	 * 
+	 * @param unfiltered
+	 *            the unfiltered iterable. May not be <code>null</code>.
+	 * @return an unmodifiable iterable containing all elements of the original iterable without any <code>null</code> references. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T> Iterable<T> filterNull(Iterable<T> unfiltered) {
+		return Iterables.filter(unfiltered, Predicates.notNull());
+	}
+
+	/**
+	 * Returns an iterable that performs the given {@code transformation} for each element of {@code original} when
+	 * requested. The mapping is done lazily. That is, subsequent iterations of the elements in the iterable will
+	 * repeatedly apply the transformation.
+	 * <p>
+	 * The returned iterable's iterator supports {@code remove()} if the provided iterator does. After a successful
+	 * {@code remove()} call, {@code original} no longer contains the corresponding element.
+	 * </p>
+	 * 
+	 * @param original
+	 *            the original iterable. May not be <code>null</code>.
+	 * @param transformation
+	 *            the transformation. May not be <code>null</code>.
+	 * @return an iterable that provides the result of the transformation. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T, R> Iterable<R> map(Iterable<T> original, Function1<? super T, ? extends R> transformation) {
+		return Iterables.transform(original, new FunctionDelegate<T, R>(transformation));
+	}
+
+	/**
+	 * Returns an iterable that performs the given {@code transformation} for each element of {@code original} when
+	 * requested. The mapping is done lazily. That is, subsequent iterations of the elements in the iterable will
+	 * repeatedly apply the transformation.
+	 * <p>
+	 * The transformation maps each element to an iterable, and all resulting iterables are combined to a single iterable.
+	 * Effectively a combination of {@link #map(Iterable, Functions.Function1)} and {@link #flatten(Iterable)} is performed.
+	 * </p>
+	 * <p>
+	 * The returned iterable's iterator <i>does not support {@code remove()}</i> in contrast to {@link #map(Iterable, Functions.Function1)}.
+	 * </p>
+	 * 
+	 * @param original
+	 *            the original iterable. May not be <code>null</code>.
+	 * @param transformation
+	 *            the transformation. May not be <code>null</code> and must not yield <code>null</code>.
+	 * @return an iterable that provides the result of the transformation. Never <code>null</code>.
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <T, R> Iterable<R> flatMap(Iterable<T> original, Function1<? super T, ? extends Iterable<R>> transformation) {
+		return flatten(map(original, transformation));
+	}
+
+	/**
+	 * Combines multiple iterables into a single iterable. The returned iterable has an iterator that traverses the
+	 * elements of each iterable in {@code inputs}. The input iterators are not polled until necessary.
+	 * 
+	 * <p>
+	 * The returned iterable's iterator supports {@code remove()} when the corresponding input iterator supports it. The
+	 * methods of the returned iterable may throw {@code NullPointerException} if any of the input iterators are null.
+	 * </p>
+	 * 
+	 * @param inputs
+	 *            the to be flattened iterables. May not be <code>null</code>.
+	 * @return an iterable that provides the concatenated values of the input elements. Never <code>null</code>.
+	 */
+	@Inline(value="$2.$3concat($1)", imported=Iterables.class)
+	public static <T> Iterable<T> flatten(Iterable<? extends Iterable<? extends T>> inputs) {
+		return Iterables.concat(inputs);
+	}
+
+	/**
+	 * Applies {@code procedure} for each element of the given iterable.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param procedure
+	 *            the procedure. May not be <code>null</code>.
+	 */
+	public static <T> void forEach(Iterable<T> iterable, Procedure1<? super T> procedure) {
+		IteratorExtensions.forEach(iterable.iterator(), procedure);
+	}
+	
+	/**
+	 * Applies {@code procedure} for each element of the given iterable.
+	 * The procedure takes the element and a loop counter. If the counter would overflow, {@link Integer#MAX_VALUE}
+	 * is returned for all subsequent elements. The first element is at index zero.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param procedure
+	 *            the procedure. May not be <code>null</code>.
+	 * @since 2.3
+	 */
+	public static <T> void forEach(Iterable<T> iterable, Procedure2<? super T, ? super Integer> procedure) {
+		IteratorExtensions.forEach(iterable.iterator(), procedure);
+	}
+
+	/**
+	 * Returns the concatenated string representation of the elements in the given iterable. No delimiter is used.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @return the string representation of the iterable's elements. Never <code>null</code>.
+	 * @see #join(Iterable, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1)
+	 */
+	public static String join(Iterable<?> iterable) {
+		return IteratorExtensions.join(iterable.iterator());
+	}
+
+	/**
+	 * Returns the concatenated string representation of the elements in the given iterable. The {@code separator} is
+	 * used to between each pair of entries in the input. The string <code>null</code> is used for <code>null</code>
+	 * entries in the input.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param separator
+	 *            the separator. May not be <code>null</code>.
+	 * @return the string representation of the iterable's elements. Never <code>null</code>.
+	 * @see #join(Iterable, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1)
+	 */
+	public static String join(Iterable<?> iterable, CharSequence separator) {
+		return IteratorExtensions.join(iterable.iterator(), separator);
+	}
+
+	/**
+	 * Returns the concatenated string representation of the elements in the given iterable. The {@code function} is
+	 * used to compute the string for each element. The {@code separator} is used to between each pair of entries in the
+	 * input. The string <code>null</code> is used if the function yields <code>null</code> as the string representation
+	 * for an entry.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param separator
+	 *            the separator. May not be <code>null</code>.
+	 * @param function
+	 *            the function that is used to compute the string representation of a single element. May not be
+	 *            <code>null</code>.
+	 * @return the string representation of the iterable's elements. Never <code>null</code>.
+	 */
+	public static <T> String join(Iterable<T> iterable, CharSequence separator,
+			Functions.Function1<? super T, ? extends CharSequence> function) {
+		return IteratorExtensions.join(iterable.iterator(), separator, function);
+	}
+	
+	/**
+	 * Returns the concatenated string representation of the elements in the given iterable. The {@code function} is
+	 * used to compute the string for each element. The {@code separator} is used to between each pair of entries in the
+	 * input. The string <code>null</code> is used if the function yields <code>null</code> as the string representation
+	 * for an entry.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @param before
+	 *            prepends the resulting string if the iterable contains at least one element. May be <code>null</code> which is equivalent to passing an empty string.
+	 * @param separator
+	 *            the separator. May be <code>null</code> which is equivalent to passing an empty string.
+	 * @param after
+	 *            appended to the resulting string if the iterable contain at least one element. May be <code>null</code> which is equivalent to passing an empty string.
+	 * @param function
+	 *            the function that is used to compute the string representation of a single element. May not be
+	 *            <code>null</code>.
+	 * @return the string representation of the iterable's elements. Never <code>null</code>.
+	 */
+	public static <T> String join(Iterable<T> iterable, CharSequence before, CharSequence separator, CharSequence after,
+			Functions.Function1<? super T, ? extends CharSequence> function) {
+		return IteratorExtensions.join(iterable.iterator(), before, separator, after, function);
+	}
+
+	/**
+	 * Determines whether two iterables contain equal elements in the same order. More specifically, this method returns
+	 * {@code true} if {@code iterable} and {@code other} contain the same number of elements and every element of
+	 * {@code iterable} is equal to the corresponding element of {@code other}.
+	 * 
+	 * @param iterable
+	 *            an iterable. May not be <code>null</code>.
+	 * @param other
+	 *            an iterable. May not be <code>null</code>.
+	 * @return <code>true</code> if the two iterables contain equal elements in the same order.
+	 */
+	public static boolean elementsEqual(Iterable<?> iterable, Iterable<?> other) {
+		return Iterables.elementsEqual(iterable, other);
+	}
+
+	/**
+	 * Determines if the given iterable is <code>null</code> or contains no elements.
+	 * 
+	 * @param iterable
+	 *            the to-be-queried iterable. May be <code>null</code>.
+	 * @return {@code true} if the iterable is <code>null</code> or contains no elements
+	 */
+	public static boolean isNullOrEmpty(Iterable<?> iterable) {
+		return iterable == null || isEmpty(iterable);
+	}
+
+	/**
+	 * Determines if the given iterable contains no elements.
+	 * 
+	 * @param iterable
+	 *            the to-be-queried iterable. May not be <code>null</code>.
+	 * @return {@code true} if the iterable contains no elements
+	 * @see #isNullOrEmpty(Iterable)
+	 */
+	public static boolean isEmpty(Iterable<?> iterable) {
+		if (iterable instanceof Collection<?>)
+			return ((Collection<?>) iterable).isEmpty();
+		return !iterable.iterator().hasNext();
+	}
+
+	/**
+	 * Returns the number of elements in {@code iterable}.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @return the number of elements in {@code iterable}.
+	 */
+	public static int size(Iterable<?> iterable) {
+		return Iterables.size(iterable);
+	}
+
+	/**
+	 * <p>
+	 * Applies the combinator {@code function} to all elements of the iterable in turn.
+	 * </p>
+	 * <p>
+	 * One of the function parameters is an element of the iterable, and the other is the result of previous application
+	 * of the function. The seed of the operation is the first element in the iterable. The second value is computed by
+	 * applying the function to the seed together with the second element of the iterable. The third value is computed
+	 * from the previous result together with the third element and so on. In other words, the previous result of each
+	 * step is taken and passed together with the next element to the combinator function.
+	 * </p>
+	 * <p>
+	 * If the iterable is empty, <code>null</code> is returned.
+	 * </p>
+	 * <p>
+	 * More formally, given an iterable {@code [a, b, c, d]} and a function {@code f}, the result of {@code reduce} is
+	 * <code>f(f(f(a, b), c), d)</code>
+	 * </p>
+	 * 
+	 * @param iterable
+	 *            the to-be-reduced iterable. May not be <code>null</code>.
+	 * @param function
+	 *            the combinator function. May not be <code>null</code>.
+	 * @return the last result of the applied combinator function or <code>null</code> for the empty input.
+	 */
+	public static <T> T reduce(Iterable<? extends T> iterable, Function2<? super T, ? super T, ? extends T> function) {
+		return IteratorExtensions.reduce(iterable.iterator(), function);
+	}
+
+	/**
+	 * <p>
+	 * Applies the combinator {@code function} to all elements of the iterable in turn and uses {@code seed} as the
+	 * start value.
+	 * </p>
+	 * <p>
+	 * One of the function parameters is an element of the iterable, and the other is the result of previous application
+	 * of the function. The seed of the operation is explicitly passed to
+	 * {@link #fold(Iterable, Object, org.eclipse.xtext.xbase.lib.Functions.Function2) fold}. The first computed value
+	 * is the result of the applied function for {@code seed} and the first element of the iterable. This intermediate
+	 * result together with the second element of the iterable produced the next result and so on.
+	 * </p>
+	 * <p>
+	 * {@link #fold(Iterable, Object, org.eclipse.xtext.xbase.lib.Functions.Function2) fold} is similar to
+	 * {@link #reduce(Iterable, org.eclipse.xtext.xbase.lib.Functions.Function2) reduce} but allows a {@code seed} value
+	 * and the combinator {@code function} may be asymmetric. It takes {@code T and R} and returns {@code R}.
+	 * <p>
+	 * If the iterable is empty, <code>seed</code> is returned.
+	 * </p>
+	 * <p>
+	 * More formally, given an iterable {@code [a, b, c, d]}, a seed {@code initial} and a function {@code f}, the
+	 * result of {@code fold} is <code>f(f(f(f(initial, a), b), c), d)</code>
+	 * </p>
+	 * 
+	 * @param iterable
+	 *            the to-be-folded iterable. May not be <code>null</code>.
+	 * @param seed
+	 *            the initial value. May be <code>null</code>.
+	 * @param function
+	 *            the combinator function. May not be <code>null</code>.
+	 * @return the last result of the applied combinator function or <code>seed</code> for the empty input.
+	 */
+	public static <T, R> R fold(Iterable<T> iterable, R seed, Function2<? super R, ? super T, ? extends R> function) {
+		return IteratorExtensions.fold(iterable.iterator(), seed, function);
+	}
+
+	/**
+	 * Returns a list that contains all the entries of the given iterable in the same order. If the iterable is of type
+	 * {@link List}, itself is returned. Therefore an unchecked cast is performed. 
+	 * In all other cases, the result list is a copy of the iterable.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @return a list with the same entries as the given iterable. May be the same as the given iterable iff it
+	 *         implements {@link List}, otherwise a copy is returned. Never <code>null</code>.
+	 */
+	@Beta
+	public static <T> List<T> toList(Iterable<T> iterable) {
+		if (iterable instanceof List<?>) {
+			List<T> result = (List<T>) iterable;
+			return result;
+		}
+		return Lists.newArrayList(iterable);
+	}
+
+	/**
+	 * Returns a set that contains all the unique entries of the given iterable in the order of their appearance. If the
+	 * iterable is of type {@link Set}, itself is returned. Therefore an unchecked cast is performed.
+	 * In all other cases, the result set is a copy of the iterable with stable order.
+	 * 
+	 * @param iterable
+	 *            the iterable. May not be <code>null</code>.
+	 * @return a set with the unique entries of the given iterable. May be the same as the given iterable iff it
+	 *         implements {@link Set}, otherwise a copy is returned. Never <code>null</code>.
+	 */
+	@Beta
+	public static <T> Set<T> toSet(Iterable<T> iterable) {
+		if (iterable instanceof Set<?>) {
+			Set<T> result = (Set<T>) iterable;
+			return result;
+		}
+		return Sets.newLinkedHashSet(iterable);
+	}
+
+	/**
+	 * Returns a map for which the {@link Map#values} are computed by the given function, and each key is an element in
+	 * the given {@code keys}. If the iterable contains equal keys more than once, the last one will be contained in the
+	 * map. The map is computed eagerly. That is, subsequent changes in the keys are not reflected by the map.
+	 * 
+	 * @param keys
+	 *            the keys to use when constructing the {@code Map}. May not be <code>null</code>.
+	 * @param computeValues
+	 *            the function used to produce the values for each key. May not be <code>null</code>.
+	 * @return a map mapping each entry in the given iterable to the corresponding result when evaluating the function
+	 *         {@code computeValues}.
+	 */
+	public static <K, V> Map<K, V> toInvertedMap(Iterable<? extends K> keys, Function1<? super K, V> computeValues) {
+		return IteratorExtensions.toInvertedMap(keys.iterator(), computeValues);
+	}
+
+	/**
+	 * Returns a map for which the {@link Map#values} are the given elements in the given order, and each key is the
+	 * product of invoking a supplied function {@code computeKeys} on its corresponding value. If the function produces
+	 * the same key for different values, the last one will be contained in the map.
+	 * 
+	 * @param values
+	 *            the values to use when constructing the {@code Map}. May not be <code>null</code>.
+	 * @param computeKeys
+	 *            the function used to produce the key for each value. May not be <code>null</code>.
+	 * @return a map mapping the result of evaluating the function {@code keyFunction} on each value in the input
+	 *         collection to that value
+	 */
+	public static <K, V> Map<K, V> toMap(Iterable<? extends V> values, Function1<? super V, K> computeKeys) {
+		return IteratorExtensions.toMap(values.iterator(), computeKeys);
+	}
+	
+	
+	/**
+	 * Returns a map for which the {@link Map#values} are the product of invoking supplied function {@code computeValues} 
+	 * on input iterable elements, and each key is the product of invoking a supplied function {@code computeKeys} on same elements. 
+	 * If the function produces the same key for different values, the last one will be contained in the map.
+	 * 
+	 * @param inputs
+	 *            the elements to use when constructing the {@code Map}. May not be <code>null</code>.
+	 * @param computeKeys
+	 *            the function used to produce the key for each value. May not be <code>null</code>.
+	 * @param computeValues
+	 *            the function used to produce the values for each key. May not be <code>null</code>.
+	 * @return a map mapping the result of evaluating the functions {@code keyFunction} and {@code computeValues} on each value in the input
+	 *         iterator to that value
+	 */
+	public static <T, K, V> Map<K, V> toMap(Iterable<? extends T> inputs, Function1<? super T, K> computeKeys, Function1<? super T, V> computeValues) {
+        return IteratorExtensions.toMap(inputs.iterator(),computeKeys,computeValues);
+    }
+
+	
+	/**
+	 * Returns a map for which the {@link Map#values} is a collection of lists, where the elements in the list will 
+	 * appear in the order as they appeared in the iterable. Each key is the product of invoking the supplied 
+	 * function {@code computeKeys} on its corresponding value. So a key of that map groups a list of values for 
+	 * which the function produced exactly that key.  
+	 * 
+	 * @param values
+	 *            the values to use when constructing the {@code Map}. May not be <code>null</code>.
+	 * @param computeKeys
+	 *            the function used to produce the key for each value. May not be <code>null</code>.
+	 * @return a map mapping the result of evaluating the function {@code keyFunction} on each value in the input
+	 *         iterable to that value. As there can be more than one value mapped by a key, the mapping result is is a
+	 *         list of values.
+	 * @since 2.7
+	 */
+	public static <K, V> Map<K, List<V>> groupBy(Iterable<? extends V> values,
+			Function1<? super V, ? extends K> computeKeys) {
+		return IteratorExtensions.groupBy(values.iterator(), computeKeys);
+   }
+
+	/**
+	 * Creates a sorted list that contains the items of the given iterable. The resulting list is in ascending order,
+	 * according to the natural ordering of the elements in the iterable.
+	 * 
+	 * @param iterable
+	 *            the items to be sorted. May not be <code>null</code>.
+	 * @return a sorted list as a shallow copy of the given iterable.
+	 * @see Collections#sort(List)
+	 * @see #sort(Iterable, Comparator)
+	 * @see #sortBy(Iterable, org.eclipse.xtext.xbase.lib.Functions.Function1)
+	 * @see ListExtensions#sortInplace(List)
+	 */
+	public static <T extends Comparable<? super T>> List<T> sort(Iterable<T> iterable) {
+		List<T> asList = Lists.newArrayList(iterable);
+		if (iterable instanceof SortedSet<?>) {
+			if (((SortedSet<T>) iterable).comparator() == null) {
+				return asList;
+			}
+		}
+		return ListExtensions.sortInplace(asList);
+	}
+
+	/**
+	 * This method is deprecated in favor of {@link #sortWith(Iterable, Comparator)}.
+	 * 
+	 * Creates a sorted list that contains the items of the given iterable. The resulting list is sorted according to
+	 * the order induced by the specified comparator.
+	 * 
+	 * @param iterable
+	 *            the items to be sorted. May not be <code>null</code>.
+	 * @param comparator
+	 *            the comparator to be used. May be <code>null</code> to indicate that the natural ordering of the
+	 *            elements should be used.
+	 * @return a sorted list as a shallow copy of the given iterable.
+	 * @see IterableExtensions#sortWith(Iterable, Comparator)
+	 * @deprecated Use {@link #sortWith(Iterable, Comparator)} instead.
+	 */
+	@Deprecated
+	@Inline(value="$3.$4sortWith($1, $2)", imported=IterableExtensions.class)
+	public static <T> List<T> sort(Iterable<T> iterable, Comparator<? super T> comparator) {
+		return sortWith(iterable, comparator);
+	}
+	
+	/**
+	 * Creates a sorted list that contains the items of the given iterable. The resulting list is sorted according to
+	 * the order induced by the specified comparator.
+	 * 
+	 * @param iterable
+	 *            the items to be sorted. May not be <code>null</code>.
+	 * @param comparator
+	 *            the comparator to be used. May be <code>null</code> to indicate that the natural ordering of the
+	 *            elements should be used.
+	 * @return a sorted list as a shallow copy of the given iterable.
+	 * @see Collections#sort(List, Comparator)
+	 * @see #sort(Iterable)
+	 * @see #sortBy(Iterable, org.eclipse.xtext.xbase.lib.Functions.Function1)
+	 * @see ListExtensions#sortInplace(List, Comparator)
+	 * @since 2.7
+	 */
+	public static <T> List<T> sortWith(Iterable<T> iterable, Comparator<? super T> comparator) {
+		return ListExtensions.sortInplace(Lists.newArrayList(iterable), comparator);
+	}
+
+	/**
+	 * Creates a sorted list that contains the items of the given iterable. The resulting list is sorted according to
+	 * the order induced by applying a key function to each element which yields a comparable criteria.
+	 * 
+	 * @param iterable
+	 *            the elements to be sorted. May not be <code>null</code>.
+	 * @param key
+	 *            the key function to-be-used. May not be <code>null</code>.
+	 * @return a sorted list as a shallow copy of the given iterable.
+	 * @see #sort(Iterable)
+	 * @see #sort(Iterable, Comparator)
+	 * @see ListExtensions#sortInplaceBy(List, org.eclipse.xtext.xbase.lib.Functions.Function1)
+	 */
+	public static <T, C extends Comparable<? super C>> List<T> sortBy(Iterable<T> iterable,
+			final Functions.Function1<? super T, C> key) {
+		return ListExtensions.sortInplaceBy(Lists.newArrayList(iterable), key);
+	}
+	
+
+
+	/**
+	 * Returns an Iterable containing all elements starting from the head of the source up to and excluding the first
+	 * element that violates the predicate The resulting Iterable is a lazily computed view, so any modifications to the
+	 * underlying Iterables will be reflected on subsequent iterations. The result's Iterator does not support
+	 * {@link Iterator#remove()}
+	 * 
+	 * @param iterable
+	 *            the elements from which to take. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate which decides whether to keep taking elements. May not be <code>null</code>.
+	 * @return the taken elements
+	 * @since 2.7
+	 */
+	public static <T> Iterable<T> takeWhile(final Iterable<? extends T> iterable, final Function1<? super T, Boolean> predicate) {
+		if (iterable == null)
+			throw new NullPointerException("iterable");
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		return new Iterable<T>() {
+			@Override
+			public Iterator<T> iterator() {
+				return IteratorExtensions.takeWhile(iterable.iterator(), predicate);
+			}
+		};
+	}
+
+	/**
+	 * Returns an Iterable containing all elements starting from the first element for which the drop-predicate returned
+	 * false. The resulting Iterable is a lazily computed view, so any modifications to the underlying Iterables will be
+	 * reflected on subsequent iterations. The result's Iterator does not support {@link Iterator#remove()}
+	 * 
+	 * @param iterable
+	 *            the elements from which to drop. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate which decides whether to keep dropping elements. May not be <code>null</code>.
+	 * @return the remaining elements after dropping
+	 * @since 2.7
+	 */
+	public static <T> Iterable<T> dropWhile(final Iterable<? extends T> iterable, final Function1<? super T, Boolean> predicate) {
+		if (iterable == null)
+			throw new NullPointerException("iterable");
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		return new Iterable<T>() {
+			@Override
+			public Iterator<T> iterator() {
+				return IteratorExtensions.dropWhile(iterable.iterator(), predicate);
+			}
+		};
+	}
+
+	/**
+	 * Returns an Iterable of Pairs where the nth pair is created by taking the nth element of the source as the value
+	 * its 0-based index as the key. E.g. <code>zipWitIndex(#["a", "b", "c"]) == #[(0, "a"), (1, "b"), (2, "c")]</code>
+	 * 
+	 * If the index would overflow, {@link Integer#MAX_VALUE} is returned for all subsequent elements.
+	 * 
+	 * The resulting Iterable is a lazily computed view, so any modifications to the underlying Iterable will be
+	 * reflected on iteration. The result's Iterator does not support {@link Iterator#remove()}
+	 * 
+	 * @param iterable
+	 *            the elements. May not be <code>null</code>.
+	 * @return the zipped result
+	 * @since 2.7
+	 */
+	public static <A> Iterable<Pair<Integer, A>> indexed(final Iterable<? extends A> iterable) {
+		if (iterable == null)
+			throw new NullPointerException("iterable");
+		return new Iterable<Pair<Integer, A>>() {
+			@Override
+			public Iterator<Pair<Integer, A>> iterator() {
+				return IteratorExtensions.indexed(iterable.iterator());
+			}
+		};
+	}
+
+	/**
+	 * Finds the minimum of the given elements according to their natural ordering. If there are several mimina, the
+	 * first one will be returned.
+	 * 
+	 * @param iterable
+	 *            the mutually comparable elements. May not be <code>null</code>.
+	 * @return the minimum
+	 * @throws NoSuchElementException
+	 *             if the iterable is empty
+	 * @since 2.7
+	 */
+	public static <T extends Comparable<? super T>> T min(final Iterable<T> iterable) {
+		if (iterable instanceof SortedSet<?>) {
+			SortedSet<T> asSet = (SortedSet<T>) iterable;
+			// only use the set-semantic if we can be absolutely sure that the set uses the natural order
+			if (asSet.comparator() == null)
+				return asSet.first();
+		}
+		return IteratorExtensions.min(iterable.iterator());
+	}
+
+	/**
+	 * Finds the element that yields the minimum value when passed to <code>compareBy</code>. If there are several
+	 * minima, the first one will be returned.
+	 * 
+	 * @param iterable
+	 *            the elements to find the minimum of. May not be <code>null</code>.
+	 * @param compareBy
+	 *            a function that returns a comparable characteristic to compare the elements by. May not be <code>null</code>.
+	 * @return the minimum
+	 * @throws NoSuchElementException
+	 *             if the iterable is empty
+	 * @since 2.7
+	 */
+	public static <T, C extends Comparable<? super C>> T minBy(final Iterable<T> iterable,
+			final Function1<? super T, C> compareBy) {
+		return IteratorExtensions.minBy(iterable.iterator(), compareBy);
+	}
+
+	/**
+	 * Finds the mininmum element according to <code>comparator</code>. If there are several minima, the first one will
+	 * be returned.
+	 * 
+	 * @param iterable
+	 *            the elements to find the minimum of. May not be <code>null</code>.
+	 * @param comparator
+	 *            the comparison function. May not be <code>null</code>.
+	 * @return the minimum
+	 * @throws NoSuchElementException
+	 *             if the iterable is empty
+	 * @since 2.7
+	 */
+	public static <T> T min(final Iterable<T> iterable, Comparator<? super T> comparator) {
+		return IteratorExtensions.min(iterable.iterator(), comparator);
+	}
+
+	/**
+	 * Finds the maximum of the elements according to their natural ordering. If there are several maxima, the first one
+	 * will be returned.
+	 * 
+	 * @param iterable
+	 *            the mutually comparable elements. May not be <code>null</code>.
+	 * @return the maximum
+	 * @throws NoSuchElementException
+	 *             if the iterable is empty
+	 * @since 2.7
+	 */
+	public static <T extends Comparable<? super T>> T max(final Iterable<T> iterable) {
+		// cannot special-case for SortedSet since we want to find the first one that is a maximum
+		// where Set.last would return the last of the seemingly equal maximum elements
+		return IteratorExtensions.max(iterable.iterator());
+	}
+
+	/**
+	 * Finds the element that yields the maximum value when passed to <code>compareBy</code> If there are several
+	 * maxima, the first one will be returned.
+	 * 
+	 * @param iterable
+	 *            the elements to find the maximum of. May not be <code>null</code>.
+	 * @param compareBy
+	 *            a function that returns a comparable characteristic to compare the elements by. May not be <code>null</code>.
+	 * @return the maximum
+	 * @throws NoSuchElementException
+	 *             if the iterable is empty
+	 * @since 2.7
+	 */
+	public static <T, C extends Comparable<? super C>> T maxBy(final Iterable<T> iterable,
+			final Function1<? super T, C> compareBy) {
+		return IteratorExtensions.maxBy(iterable.iterator(), compareBy);
+	}
+
+	/**
+	 * Finds the maximum element according to <code>comparator</code>. If there are several maxima, the first one will
+	 * be returned.
+	 * 
+	 * @param iterable
+	 *            the elements to find the maximum of. May not be <code>null</code>.
+	 * @param comparator
+	 *            the comparison function. May not be <code>null</code>.
+	 * @return the maximum
+	 * @throws NoSuchElementException
+	 *             if the iterable is empty
+	 * @since 2.7
+	 */
+	public static <T> T max(final Iterable<T> iterable, Comparator<? super T> comparator) {
+		return IteratorExtensions.max(iterable.iterator(), comparator);
+	}
+
+    /**
+     * Returns <tt>true</tt> if this Iterable contains the specified element.
+     * More formally, returns <tt>true</tt> if and only if this Iterable contains
+     * at least one element <tt>e</tt> such that
+     * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+     *
+     * @param iterable 
+     * 			the elements to test
+     * @param o 
+     * 			element whose presence in the Iterable is to be tested
+     * @return <tt>true</tt> if this Iterable contains the specified element
+     */
+	public static boolean contains(Iterable<?> iterable, Object o) {
+		if (iterable instanceof Collection<?>) {
+			return ((Collection<?>) iterable).contains(o);
+		}
+		return IteratorExtensions.contains(iterable.iterator(), o);
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/IteratorExtensions.java b/java/org/eclipse/xtext/xbase/lib/IteratorExtensions.java
new file mode 100644
index 0000000..beac936
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/IteratorExtensions.java
@@ -0,0 +1,1091 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+import java.util.Objects;
+import java.util.Set;
+
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.Functions.Function2;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
+import org.eclipse.xtext.xbase.lib.internal.BooleanFunctionDelegate;
+import org.eclipse.xtext.xbase.lib.internal.FunctionDelegate;
+import org.eclipse.xtext.xbase.lib.internal.KeyComparator;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+import com.google.common.base.Joiner;
+import com.google.common.base.Predicates;
+import com.google.common.collect.AbstractIterator;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Iterators;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Ordering;
+import com.google.common.collect.Sets;
+
+/**
+ * This is an extension library for {@link Iterator iterators}.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * @author Sebastian Zarnekow
+ */
+@GwtCompatible public class IteratorExtensions {
+
+	/**
+	 * Wraps an {@link Iterator} in an {@link Iterable}. WARNING: The resulting
+	 * {@link Iterable} may be used (e.g. calling
+	 * {@link IterableExtensions#isEmpty(Iterable)}) / iterated (e.g. in a for
+	 * loop) only once. If you want to create a reusable {@link Iterable} call
+	 * {@link IterableExtensions#toList(Iterable)} or
+	 * {@link IterableExtensions#toSet(Iterable)} on the result and reuse the
+	 * resulting {@link List} / {@link Set}
+	 * @param iterator the {@link Iterator} to wrap in an {@link Iterable}. May not be <code>null</code>.
+	 * @return an {@link Iterable} providing the given {@link Iterator}. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T> Iterable<T> toIterable(final Iterator<T> iterator) {
+		if (iterator == null)
+			throw new NullPointerException("iterator");
+		return new Iterable<T>() {
+			@Override
+			public Iterator<T> iterator() {
+				return iterator;
+			}
+		};
+	}
+	
+	/**
+	 * <p>
+	 * Concatenates two iterators into a single iterator. The returned iterator traverses the
+	 * elements in {@code a}, followed by the elements in {@code b}. The resulting iterator is effectivly a view on the
+	 * source iterators. That is, the source iterators are not polled until necessary and the result will reflect
+	 * changes in the sources.
+	 * </p>
+	 * <p>
+	 * The returned iterator supports {@code remove()} when the corresponding input iterator supports it.
+	 * </p>
+	 * 
+	 * @param a
+	 *            the first iterator. May not be <code>null</code>.
+	 * @param b
+	 *            the second iterator. May not be <code>null</code>.
+	 * @return a combined iterator. Never <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$3.$4concat($1, $2)", imported=Iterators.class)
+	public static <T> Iterator<T> operator_plus(Iterator<? extends T> a, Iterator<? extends T> b) {
+		return Iterators.concat(a, b);
+	}
+
+	/**
+	 * Finds the first element in the given iterator that fulfills the predicate. If none is found or the iterator is
+	 * empty, <code>null</code> is returned.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return the first element in the iterator for which the given predicate returns <code>true</code>, returns
+	 *         <code>null</code> if no element matches the predicate or the iterator is empty.
+	 */
+	public static <T> T findFirst(Iterator<T> iterator, Function1<? super T, Boolean> predicate) {
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		while(iterator.hasNext()) {
+			T t = iterator.next();
+			if (predicate.apply(t))
+				return t;
+		}
+		return null;
+	}
+
+	/**
+	 * Finds the last element in the given iterator that fulfills the predicate. If none is found or the iterator is
+	 * empty, <code>null</code> is returned.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return the last element in the iterator for which the given predicate returns <code>true</code>, returns
+	 *         <code>null</code> if no element matches the predicate or the iterator is empty.
+	 */
+	public static <T> T findLast(Iterator<T> iterator, Functions.Function1<? super T, Boolean> predicate) {
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		T result = null;
+		while(iterator.hasNext()) {
+			T t = iterator.next();
+			if (predicate.apply(t))
+				result = t;
+		}
+		return result;
+	}
+
+	/**
+	 * Returns the first element in the given iterator or <code>null</code> if empty.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @return the first element in the iterator or <code>null</code>.
+	 */
+	public static <T> T head(Iterator<T> iterator) {
+		if (iterator.hasNext())
+			return iterator.next();
+		return null;
+	}
+
+	/**
+	 * Returns a view on this iterator that contains all the elements except the first.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @return an iterator with all elements except the first. Never <code>null</code>.
+	 * @see #drop(Iterator, int)
+	 */
+	public static <T> Iterator<T> tail(final Iterator<T> iterator) {
+		return drop(iterator, 1);
+	}
+
+	/**
+	 * Returns the last element in the given iterator or <code>null</code> if empty.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @return the last element in the iterator or <code>null</code>.
+	 */
+	public static <T> T last(Iterator<T> iterator) {
+		T result = null;
+		while(iterator.hasNext()) {
+			result = iterator.next();
+		}
+		return result;
+	}
+
+	/**
+	 * Returns a view on this iterator that provides at most the first <code>count</code> entries.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param count
+	 *            the number of elements that should be returned at most.
+	 * @return an iterator with <code>count</code> elements. Never <code>null</code>.
+	 * @throws IllegalArgumentException
+	 *             if <code>count</code> is negative.
+	 */
+	@Pure
+	public static <T> Iterator<T> take(final Iterator<T> iterator, final int count) {
+		if (iterator == null)
+			throw new NullPointerException("iterator");
+		if (count < 0)
+			throw new IllegalArgumentException("Cannot take a negative number of elements. Argument 'count' was: "
+					+ count);
+		if (count == 0)
+			return ImmutableSet.<T>of().iterator();
+		return new AbstractIterator<T>() {
+
+			private int remaining = count;
+
+			@Override
+			protected T computeNext() {
+				if (remaining <= 0)
+					return endOfData();
+				if (!iterator.hasNext())
+					return endOfData();
+				remaining--;
+				return iterator.next();
+			}
+		};
+	}
+
+	/**
+	 * Returns a view on this iterator that provides all elements except the first <code>count</code> entries.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param count
+	 *            the number of elements that should be dropped.
+	 * @return an iterator without the first <code>count</code> elements. Never <code>null</code>.
+	 * @throws IllegalArgumentException
+	 *             if <code>count</code> is negative.
+	 */
+	public static <T> Iterator<T> drop(final Iterator<T> iterator, final int count) {
+		if (iterator == null)
+			throw new NullPointerException("iterator");
+		if (count == 0)
+			return iterator;
+		if (count < 0)
+			throw new IllegalArgumentException("Cannot drop a negative number of elements. Argument 'count' was: "
+					+ count);
+		return new AbstractIterator<T>() {
+			{
+				int i = count;
+				while (i > 0 && iterator.hasNext()) {
+					iterator.next();
+					i--;
+				}
+			}
+
+			@Override
+			protected T computeNext() {
+				if (!iterator.hasNext())
+					return endOfData();
+				return iterator.next();
+			}
+		};
+	}
+
+	/**
+	 * Returns {@code true} if one or more elements in {@code iterator} satisfy the predicate.
+	 * 
+     * <p>Note that this will advance or even exhaust the given iterator.</p>
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return <code>true</code> if one or more elements in {@code iterator} satisfy the predicate.
+	 */
+	public static <T> boolean exists(Iterator<T> iterator, Function1<? super T, Boolean> predicate) {
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		while(iterator.hasNext()) {
+			if (predicate.apply(iterator.next()))
+				return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Returns {@code true} if every element in {@code iterator} satisfies the predicate. If {@code iterator} is empty,
+	 * {@code true} is returned. In other words, <code>false</code> is returned if at least one element fails to fulfill
+	 * the predicate.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return <code>true</code> if every element in {@code iterator} satisfies the predicate and also if there is no element.
+	 */
+	public static <T> boolean forall(Iterator<T> iterator, Function1<? super T, Boolean> predicate) {
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		while(iterator.hasNext()) {
+			if (!predicate.apply(iterator.next()))
+				return false;
+		}
+		return true;
+	}
+
+	/**
+	 * Returns the elements of {@code unfiltered} that satisfy a predicate. The resulting iterator does not
+	 * support {@code remove()}. The returned iterator is a view on the original elements. Changes in the unfiltered
+	 * original are reflected in the view.
+	 * 
+	 * @param unfiltered
+	 *            the unfiltered iterator. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return an iterator that contains only the elements that fulfill the predicate. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T> Iterator<T> filter(Iterator<T> unfiltered, Function1<? super T, Boolean> predicate) {
+		return Iterators.filter(unfiltered, new BooleanFunctionDelegate<T>(predicate));
+	}
+
+	/**
+	 * Returns the elements of {@code unfiltered} that do not satisfy a predicate. The resulting iterator does not
+	 * support {@code remove()}. The returned iterator is a view on the original elements. Changes in the unfiltered
+	 * original are reflected in the view.
+	 *
+	 * @param unfiltered
+	 *            the unfiltered iterator. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return an iterator that contains only the elements that do not fulfill the predicate. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T> Iterator<T> reject(Iterator<T> unfiltered, Function1<? super T, Boolean> predicate) {
+		return Iterators.filter(unfiltered, Predicates.not(new BooleanFunctionDelegate<T>(predicate)));
+	}
+
+	/**
+	 * Returns all instances of class {@code type} in {@code unfiltered}. The returned iterator has elements whose class
+	 * is {@code type} or a subclass of {@code type}. The returned iterator does not support {@code remove()}.
+	 * The returned iterator is a view on the original elements. Changes in the unfiltered original are reflected in
+	 * the view.
+	 * 
+	 * @param unfiltered
+	 *            the unfiltered iterator. May not be <code>null</code>.
+	 * @param type
+	 *            the type of elements desired
+	 * @return an unmodifiable iterator containing all elements of the original iterator that were of the requested
+	 *         type. Never <code>null</code>.
+	 */
+	@Pure
+	@GwtIncompatible("Class.isInstance")
+	@Inline(value="$3.$4filter($1, $2)", imported=Iterators.class)
+	public static <T> Iterator<T> filter(Iterator<?> unfiltered, Class<T> type) {
+		return Iterators.filter(unfiltered, type);
+	}
+	
+	/**
+	 * Returns a new iterator filtering any null references.
+	 * 
+	 * @param unfiltered
+	 *            the unfiltered iterator. May not be <code>null</code>.
+	 * @return an unmodifiable iterator containing all elements of the original iterator without any <code>null</code>
+	 *         references. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T> Iterator<T> filterNull(Iterator<T> unfiltered) {
+		return Iterators.filter(unfiltered, Predicates.notNull());
+	}
+
+	/**
+	 * Returns an iterator that performs the given {@code transformation} for each element of {@code original} when
+	 * requested. The mapping is done lazily. 
+	 * 
+	 * The returned iterator's iterator supports {@code remove()} if the provided iterator does. After a successful
+	 * {@code remove()} call, {@code original} no longer contains the corresponding element.
+	 * 
+	 * @param original
+	 *            the original iterator. May not be <code>null</code>.
+	 * @param transformation
+	 *            the transformation. May not be <code>null</code>.
+	 * @return an iterator that provides the result of the transformation. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T, R> Iterator<R> map(Iterator<T> original, Function1<? super T, ? extends R> transformation) {
+		return Iterators.transform(original, new FunctionDelegate<T, R>(transformation));
+	}
+
+	/**
+	 * Returns an iterable that performs the given {@code transformation} for each element of {@code original} when
+	 * requested. The mapping is done lazily. That is, subsequent iterations of the elements in the iterable will
+	 * repeatedly apply the transformation.
+	 * <p>
+	 * The transformation maps each element to an iterable, and all resulting iterables are combined to a single iterable.
+	 * Effectively a combination of {@link #map(Iterator, Functions.Function1)} and {@link #flatten(Iterator)} is performed.
+	 * </p>
+	 * <p>
+	 * The returned iterable's iterator <i>does not support {@code remove()}</i> in contrast to {@link #map(Iterator, Functions.Function1)}.
+	 * </p>
+	 * 
+	 * @param original
+	 *            the original iterable. May not be <code>null</code>.
+	 * @param transformation
+	 *            the transformation. May not be <code>null</code> and must not yield <code>null</code>.
+	 * @return an iterable that provides the result of the transformation. Never <code>null</code>.
+	 * 
+	 * @since 2.13
+	 */
+	@Pure
+	public static <T, R> Iterator<R> flatMap(Iterator<T> original, Function1<? super T, ? extends Iterator<R>> transformation) {
+		return flatten(map(original, transformation));
+	}
+
+
+	/**
+	 * Combines multiple iterators into a single iterator. The returned iterator traverses the
+	 * elements of each iterator in {@code inputs}. The input iterators are not polled until necessary.
+	 * 
+	 * @param inputs
+	 *            the to be flattened iterators. May not be <code>null</code>.
+	 * @return an iterator that provides the concatenated values of the input elements. Never <code>null</code>.
+	 * 
+	 * @since 2.13
+	 */
+	@Inline(value="$2.$3concat($1)", imported=Iterators.class)
+	public static <T> Iterator<T> flatten(Iterator<? extends Iterator<? extends T>> inputs) {
+		return Iterators.concat(inputs);
+	}
+
+	/**
+	 * Applies {@code procedure} for each element of the given iterator.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param procedure
+	 *            the procedure. May not be <code>null</code>.
+	 */
+	public static <T> void forEach(Iterator<T> iterator, Procedure1<? super T> procedure) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		while(iterator.hasNext()) {
+			procedure.apply(iterator.next());
+		}
+	}
+	
+	/**
+	 * Applies {@code procedure} for each element of the given iterator.
+	 * The procedure takes the element and a loop counter. If the counter would overflow, {@link Integer#MAX_VALUE}
+	 * is returned for all subsequent elements. The first element is at index zero.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param procedure
+	 *            the procedure. May not be <code>null</code>.
+	 */
+	public static <T> void forEach(Iterator<T> iterator, Procedure2<? super T, ? super Integer> procedure) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		int i = 0;
+		while(iterator.hasNext()) {
+			procedure.apply(iterator.next(), i);
+			if (i != Integer.MAX_VALUE)
+				i++;
+		}
+	}
+
+	/**
+	 * Returns the concatenated string representation of the elements in the given iterator. No delimiter is used.
+	 * The given iterator is left exhausted.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @return the string representation of the iterator's elements. Never <code>null</code>.
+	 * @see #join(Iterator, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1)
+	 */
+	public static String join(Iterator<?> iterator) {
+		return join(iterator, "");
+	}
+
+	/**
+	 * Returns the concatenated string representation of the elements in the given iterator. The {@code separator} is
+	 * used to between each pair of entries in the input. The string <code>null</code> is used for <code>null</code>
+	 * entries in the input. The given iterator is left exhausted.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param separator
+	 *            the separator. May not be <code>null</code>.
+	 * @return the string representation of the iterator's elements. Never <code>null</code>.
+	 * @see #join(Iterator, CharSequence, org.eclipse.xtext.xbase.lib.Functions.Function1)
+	 */
+	public static String join(Iterator<?> iterator, CharSequence separator) {
+		return Joiner.on(separator.toString()).useForNull("null").join(toIterable(iterator));
+	}
+
+	/**
+	 * Returns the concatenated string representation of the elements in the given iterator. The {@code function} is
+	 * used to compute the string for each element. The {@code separator} is used to between each pair of entries in the
+	 * input. The string <code>null</code> is used if the function yields <code>null</code> as the string representation
+	 * for an entry. The given iterator is left exhausted.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param separator
+	 *            the separator. May not be <code>null</code>.
+	 * @param function
+	 *            the function that is used to compute the string representation of a single element. May not be
+	 *            <code>null</code>.
+	 * @return the string representation of the iterator's elements. Never <code>null</code>.
+	 */
+	public static <T> String join(Iterator<T> iterator, CharSequence separator,
+			Functions.Function1<? super T, ? extends CharSequence> function) {
+		if (separator == null)
+			throw new NullPointerException("separator");
+		if (function == null)
+			throw new NullPointerException("function");
+		StringBuilder result = new StringBuilder();
+		while (iterator.hasNext()) {
+			T next = iterator.next();
+			CharSequence elementToString = function.apply(next);
+			result.append(elementToString);
+			if (iterator.hasNext())
+				result.append(separator);
+		}
+		return result.toString();
+	}
+	
+	/**
+	 * Returns the concatenated string representation of the elements in the given iterator. The {@code function} is
+	 * used to compute the string for each element. The {@code separator} is used to between each pair of entries in the
+	 * input. The string <code>null</code> is used if the function yields <code>null</code> as the string representation
+	 * for an entry. The given iterator is left exhausted.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @param before
+	 *            prepends the resulting string if the iterator contains at least one element. May be <code>null</code> which is equivalent to passing an empty string.
+	 * @param separator
+	 *            the separator. May be <code>null</code> which is equivalent to passing an empty string.
+	 * @param after
+	 *            appended to the resulting string if the iterator contain at least one element. May be <code>null</code> which is equivalent to passing an empty string.
+	 * @param function
+	 *            the function that is used to compute the string representation of a single element. May not be
+	 *            <code>null</code>.
+	 * @return the string representation of the iterator's elements. Never <code>null</code>.
+	 */
+	public static <T> String join(Iterator<T> iterator, CharSequence before, CharSequence separator, CharSequence after,
+			Functions.Function1<? super T, ? extends CharSequence> function) {
+		if (function == null)
+			throw new NullPointerException("function");
+		StringBuilder result = new StringBuilder();
+		boolean notEmpty = iterator.hasNext(); 
+		if (notEmpty && before != null)
+			result.append(before);
+		while (iterator.hasNext()) {
+			T next = iterator.next();
+			CharSequence elementToString = function.apply(next);
+			result.append(elementToString);
+			if (iterator.hasNext() && separator != null)
+				result.append(separator);
+		}
+		if (notEmpty && after != null)
+			result.append(after);
+		return result.toString();
+	}
+
+	/**
+	 * Determines whether two iterators contain equal elements in the same order. More specifically, this method returns
+	 * {@code true} if {@code iterator} and {@code other} contain the same number of elements and every element of
+	 * {@code iterator} is equal to the corresponding element of {@code other}.
+	 * 
+	 * <p>Note that this will advance or even exhaust the given iterators.</p>
+	 * 
+	 * @param iterator
+	 *            an iterator. May not be <code>null</code>.
+	 * @param other
+	 *            an iterator. May not be <code>null</code>.
+	 * @return <code>true</code> if the two iterators contain equal elements in the same order.
+	 */
+	public static boolean elementsEqual(Iterator<?> iterator, Iterator<?> other) {
+		return Iterators.elementsEqual(iterator, other);
+	}
+	
+	/**
+	 * Determines whether two iterators contain equal elements in the same order. More specifically, this method returns
+	 * {@code true} if {@code iterator} and {@code iterable} contain the same number of elements and every element of
+	 * {@code iterator} is equal to the corresponding element of {@code iterable}.
+	 * 
+	 * <p>Note that this will advance or even exhaust the given iterators.</p>
+	 * 
+	 * @param iterator
+	 *            an iterator. May not be <code>null</code>.
+	 * @param iterable
+	 *            an iterable. May not be <code>null</code>.
+	 * @return <code>true</code> if the two iterators contain equal elements in the same order.
+	 */
+	public static boolean elementsEqual(Iterator<?> iterator, Iterable<?> iterable) {
+		return Iterators.elementsEqual(iterator, iterable.iterator());
+	}
+
+	/**
+	 * Determines if the given iterator is <code>null</code> or contains no elements.
+	 * 
+	 * @param iterator
+	 *            the to-be-queried iterator. May be <code>null</code>.
+	 * @return {@code true} if the iterator is <code>null</code> or contains no elements
+	 */
+	public static boolean isNullOrEmpty(Iterator<?> iterator) {
+		return iterator == null || isEmpty(iterator);
+	}
+
+	/**
+	 * Determines if the given iterator contains no elements.
+	 * 
+	 * @param iterator
+	 *            the to-be-queried iterator. May not be <code>null</code>.
+	 * @return {@code true} if the iterator contains no elements
+	 * @see #isNullOrEmpty(Iterator)
+	 */
+	public static boolean isEmpty(Iterator<?> iterator) {
+		return !iterator.hasNext();
+	}
+
+	/**
+	 * Returns the number of elements in {@code iterator}.
+	 * The given iterator is left exhausted.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @return the number of elements in {@code iterator}.
+	 */
+	public static int size(Iterator<?> iterator) {
+		return Iterators.size(iterator);
+	}
+
+	/**
+	 * <p>
+	 * Applies the combinator {@code function} to all elements of the iterator in turn.
+	 * </p>
+	 * <p>
+	 * One of the function parameters is an element of the iterator, and the other is the result of previous application
+	 * of the function. The seed of the operation is the first element in the iterator. The second value is computed by
+	 * applying the function to the seed together with the second element of the iterator. The third value is computed
+	 * from the previous result together with the third element and so on. In other words, the previous result of each
+	 * step is taken and passed together with the next element to the combinator function.
+	 * </p>
+	 * <p>
+	 * If the iterator is empty, <code>null</code> is returned.
+	 * </p>
+	 * <p>
+	 * More formally, given an iterator {@code [a, b, c, d]} and a function {@code f}, the result of {@code reduce} is
+	 * <code>f(f(f(a, b), c), d)</code>
+	 * </p>
+	 * 
+	 * @param iterator
+	 *            the to-be-reduced iterator. May not be <code>null</code>.
+	 * @param function
+	 *            the combinator function. May not be <code>null</code>.
+	 * @return the last result of the applied combinator function or <code>null</code> for the empty input.
+	 */
+	public static <T> T reduce(Iterator<? extends T> iterator, Function2<? super T, ? super T, ? extends T> function) {
+		if (function == null)
+			throw new NullPointerException("function");
+		if (iterator.hasNext()) {
+			T result = iterator.next();
+			while (iterator.hasNext()) {
+				result = function.apply(result, iterator.next());
+			}
+			return result;
+		} else {
+			return null;
+		}
+	}
+
+	/**
+	 * <p>
+	 * Applies the combinator {@code function} to all elements of the iterator in turn and uses {@code seed} as the
+	 * start value.
+	 * </p>
+	 * <p>
+	 * One of the function parameters is an element of the iterator, and the other is the result of previous application
+	 * of the function. The seed of the operation is explicitly passed to {@link #fold(Iterator, Object, org.eclipse.xtext.xbase.lib.Functions.Function2)
+	 * fold}. The first computed value is the result of the applied function for {@code seed} and the first element of
+	 * the iterator. This intermediate result together with the second element of the iterator produced the next result
+	 * and so on.
+	 * </p>
+	 * <p>
+	 * {@link #fold(Iterator, Object, org.eclipse.xtext.xbase.lib.Functions.Function2) fold} is similar to {@link #reduce(Iterator, org.eclipse.xtext.xbase.lib.Functions.Function2) reduce} but
+	 * allows a {@code seed} value and the combinator {@code function} may be asymmetric. It takes {@code T and R} and
+	 * returns {@code R}.
+	 * <p>
+	 * If the iterator is empty, <code>seed</code> is returned.
+	 * </p>
+	 * <p>
+	 * More formally, given an iterator {@code [a, b, c, d]}, a seed {@code initial} and a function {@code f}, the
+	 * result of {@code fold} is <code>f(f(f(f(initial, a), b), c), d)</code>
+	 * </p>
+	 * 
+	 * @param iterator
+	 *            the to-be-folded iterator. May not be <code>null</code>.
+	 * @param seed
+	 *            the initial value. May be <code>null</code>.
+	 * @param function
+	 *            the combinator function. May not be <code>null</code>.
+	 * @return the last result of the applied combinator function or <code>seed</code> for the empty input.
+	 */
+	public static <T, R> R fold(Iterator<T> iterator, R seed, Function2<? super R, ? super T, ? extends R> function) {
+		R result = seed;
+		while (iterator.hasNext()) {
+			result = function.apply(result, iterator.next());
+		}
+		return result;
+	}
+
+	/**
+	 * Returns a list that contains all the entries of the given iterator in the same order. 
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @return a list with the same entries as the given iterator. Never <code>null</code>.
+	 */
+	public static <T> List<T> toList(Iterator<? extends T> iterator) {
+		return Lists.newArrayList(iterator);
+	}
+
+	/**
+	 * Returns a set that contains all the unique entries of the given iterator in the order of their appearance. 
+	 * The result set is a copy of the iterator with stable order.
+	 * 
+	 * @param iterator
+	 *            the iterator. May not be <code>null</code>.
+	 * @return a set with the unique entries of the given iterator. Never <code>null</code>.
+	 */
+	public static <T> Set<T> toSet(Iterator<? extends T> iterator) {
+		return Sets.newLinkedHashSet(toIterable(iterator));
+	}
+
+	/**
+	 * Returns a map for which the {@link Map#values} are computed by the given function, and each key is an element in
+	 * the given {@code keys}. If the iterator contains equal keys more than once, the last one will be contained in the
+	 * map. The map is computed eagerly. That is, subsequent changes in the keys are not reflected by the map.
+	 * The key iterator is left exhausted.
+	 * 
+	 * @param keys
+	 *            the keys to use when constructing the {@code Map}. May not be <code>null</code>.
+	 * @param computeValues
+	 *            the function used to produce the values for each key. May not be <code>null</code>.
+	 * @return a map mapping each entry in the given iterator to the corresponding result when evaluating the function
+	 *         {@code computeValues}.
+	 */
+	public static <K, V> Map<K, V> toInvertedMap(Iterator<? extends K> keys, Function1<? super K, V> computeValues) {
+		Map<K, V> result = Maps.newLinkedHashMap();
+		while(keys.hasNext()) {
+			K k = keys.next();
+			result.put(k, computeValues.apply(k));
+		}
+		return result;
+	}
+
+	/**
+	 * Returns a map for which the {@link Map#values} are the given elements in the given order, and each key is the
+	 * product of invoking a supplied function {@code computeKeys} on its corresponding value. If the function produces
+	 * the same key for different values, the last one will be contained in the map. The value iterator is left exhausted.
+	 * 
+	 * @param values
+	 *            the values to use when constructing the {@code Map}. May not be <code>null</code>.
+	 * @param computeKeys
+	 *            the function used to produce the key for each value. May not be <code>null</code>.
+	 * @return a map mapping the result of evaluating the function {@code keyFunction} on each value in the input
+	 *         iterator to that value
+	 */
+	public static <K, V> Map<K, V> toMap(Iterator<? extends V> values, Function1<? super V, K> computeKeys) {
+		if (computeKeys == null)
+			throw new NullPointerException("computeKeys");
+		Map<K, V> result = Maps.newLinkedHashMap();
+		while(values.hasNext()) {
+			V v = values.next();
+			result.put(computeKeys.apply(v), v);
+		}
+		return result;
+	}
+	
+	/**
+	 * Returns a map for which the {@link Map#values} are the product of invoking supplied function {@code computeValues} 
+	 * on input iterable elements, and each key is the product of invoking a supplied function {@code computeKeys} on same elements. 
+	 * If the function produces the same key for different values, the last one will be contained in the map. The input iterator is left exhausted.
+	 * 
+	 * @param inputs
+	 *            the elements to use when constructing the {@code Map}. May not be <code>null</code>.
+	 * @param computeKeys
+	 *            the function used to produce the key for each value. May not be <code>null</code>.
+	 * @param computeValues
+	 *            the function used to produce the values for each key. May not be <code>null</code>.
+	 * @return a map mapping the result of evaluating the functions {@code keyFunction} and {@code computeValues} on each value in the input
+	 *         iterator to that value
+	 */
+	public static <T, K, V> Map<K, V> toMap(Iterator<? extends T> inputs, Function1<? super T, K> computeKeys, Function1<? super T, V> computeValues) {
+        if (computeKeys == null)
+            throw new NullPointerException("computeKeys");
+        if (computeValues == null)
+            throw new NullPointerException("computeValues");
+        Map<K, V> result = Maps.newLinkedHashMap();
+        while(inputs.hasNext()) {
+            T t = inputs.next();
+            result.put(computeKeys.apply(t), computeValues.apply(t));
+        }
+        return result;
+    }
+	
+	
+	
+	/**
+	 * Returns a map for which the {@link Map#values} is a collection of lists, where the elements in the list will 
+	 * appear in the order as they appeared in the iterator. Each key is the product of invoking the supplied 
+	 * function {@code computeKeys} on its corresponding value. So a key of that map groups a list of values for 
+	 * which the function produced exactly that key. The value iterator is left exhausted.
+	 * 
+	 * @param values
+	 *            the values to use when constructing the {@code Map}. May not be <code>null</code>.
+	 * @param computeKeys
+	 *            the function used to produce the key for each value. May not be <code>null</code>.
+	 * @return a map mapping the result of evaluating the function {@code keyFunction} on each value in the input
+	 *         iterator to that value. As there can be more than one value mapped by a key, the mapping result is is a
+	 *         list of values.
+	 * @since 2.7
+	 */
+	public static <K, V> Map<K, List<V>> groupBy(Iterator<? extends V> values,
+			Function1<? super V, ? extends K> computeKeys) {
+		if (computeKeys == null)
+			throw new NullPointerException("computeKeys");
+		Map<K, List<V>> result = Maps.newLinkedHashMap();
+		while(values.hasNext()) {
+			V v = values.next();
+			K key = computeKeys.apply(v);
+			List<V> grouped = result.get(key);
+			if (grouped == null) {
+				grouped = new ArrayList<V>();
+				result.put(key, grouped);
+			}
+			grouped.add(v);
+		}
+		return result;
+	}	
+
+	/**
+	 * Returns an Iterator containing all elements starting from the head of the source up to and excluding the first
+	 * element that violates the predicate. The resulting Iterator is a lazily computed view, so any modifications to the
+	 * underlying Iterators will be reflected on iteration. The result does not support {@link Iterator#remove()}
+	 * 
+	 * @param iterator
+	 *            the elements from which to take. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate which decides whether to keep taking elements. May not be <code>null</code>.
+	 * @return the taken elements
+	 * @since 2.7
+	 */
+	public static <T> Iterator<T> takeWhile(final Iterator<? extends T> iterator, final Function1<? super T, Boolean> predicate) {
+		if (iterator == null)
+			throw new NullPointerException("iterator");
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		return new AbstractIterator<T>() {
+			@Override
+			protected T computeNext() {
+				if (!iterator.hasNext())
+					return endOfData();
+				T next = iterator.next();
+				if (predicate.apply(next)) {
+					return next;
+				} else {
+					return endOfData();
+				}
+			}
+		};
+	}
+
+	/**
+	 * Returns an Iterator containing all elements starting from the first element for which the drop-predicate returned
+	 * false. The resulting Iterator is a lazily computed view, so any modifications to the
+	 * underlying Iterators will be reflected on iteration. The result does not support {@link Iterator#remove()}
+	 * 
+	 * @param iterator
+	 *            the elements from which to drop. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate which decides whether to keep dropping elements. May not be <code>null</code>.
+	 * @return the remaining elements after dropping
+	 * @since 2.7
+	 */
+	public static <T> Iterator<T> dropWhile(final Iterator<? extends T> iterator, final Function1<? super T, Boolean> predicate) {
+		if (iterator == null)
+			throw new NullPointerException("iterator");
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		return new AbstractIterator<T>() {
+			private boolean headFound = false;
+
+			@Override
+			protected T computeNext() {
+				while (!headFound) {
+					if (!iterator.hasNext())
+						return endOfData();
+					T next = iterator.next();
+					if (!predicate.apply(next)) {
+						headFound = true;
+						return next;
+					}
+				}
+				if (iterator.hasNext()) {
+					return iterator.next();
+				} else {
+					return endOfData();
+				}
+			}
+		};
+	}
+
+	/**
+	 * Returns an Iterator of Pairs where the nth pair is created by taking the nth element of the source as the value
+	 * and its 0-based index as the key. E.g.
+	 * <code>zipWitIndex(#["a", "b", "c"]) == #[(0, "a"), (1, "b"), (2, "c")]</code>
+	 * 
+	 * If the index would overflow, {@link Integer#MAX_VALUE} is returned for all subsequent elements.
+	 * 
+	 * The resulting Iterator is a lazily computed view, so any modifications to the underlying Iterator will be
+	 * reflected on iteration. The result does not support {@link Iterator#remove()}
+	 * 
+	 * @param iterator
+	 *            the elements. May not be <code>null</code>.
+	 * @return the zipped result
+	 * @since 2.7
+	 */
+	public static <A> Iterator<Pair<Integer, A>> indexed(final Iterator<? extends A> iterator) {
+		if (iterator == null)
+			throw new NullPointerException("iterator");
+		return new AbstractIterator<Pair<Integer, A>>() {
+			int i = 0;
+			@Override
+			protected Pair<Integer, A> computeNext() {
+				if (iterator.hasNext()) {
+					Pair<Integer, A> next = new Pair<Integer, A>(i, iterator.next());
+					if (i != Integer.MAX_VALUE)
+						i++;
+					return next;
+				} else {
+					return endOfData();
+				}
+			}
+		};
+	}
+
+	/**
+	 * Finds the minimum of the given elements according to their natural ordering. If there are several mimina, the
+	 * first one will be returned.
+	 * 
+	 * <p>Note that this will advance or even exhaust the given iterator.</p>
+	 * 
+	 * @param iterator
+	 *            the mutually comparable elements. May not be <code>null</code>.
+	 * @return the minimum
+	 * @throws NoSuchElementException
+	 *             if the iterator is empty
+	 * @since 2.7
+	 */
+	public static <T extends Comparable<? super T>> T min(final Iterator<T> iterator) {
+		return min(iterator, Ordering.natural());
+	}
+
+	/**
+	 * Finds the element that yields the minimum value when passed to <code>compareBy</code>. If there are several
+	 * maxima, the first one will be returned.
+	 * 
+	 * <p>Note that this will advance or even exhaust the given iterator.</p>
+	 * 
+	 * @param iterator
+	 *            the elements to find the minimum of. May not be <code>null</code>.
+	 * @param compareBy
+	 *            a function that returns a comparable characteristic to compare the elements by. May not be <code>null</code>.
+	 * @return the minimum
+	 * @throws NoSuchElementException
+	 *             if the iterator is empty
+	 * @since 2.7
+	 */
+	public static <T, C extends Comparable<? super C>> T minBy(final Iterator<T> iterator, final Function1<? super T, C> compareBy) {
+		if (compareBy == null)
+			throw new NullPointerException("compareBy");
+		return min(iterator, new KeyComparator<T, C>(compareBy));
+	}
+	
+	/**
+	 * Finds the mininmum element according to <code>comparator</code>. If there are several minima, the first one will
+	 * be returned.
+	 * 
+	 * <p>Note that this will advance or even exhaust the given iterator.</p>
+	 * 
+	 * @param iterator
+	 *            the elements to find the minimum of. May not be <code>null</code>.
+	 * @param comparator
+	 *            the comparison function. May not be <code>null</code>.
+	 * @return the minimum
+	 * @throws NoSuchElementException
+	 *             if the iterator is empty
+	 * @since 2.7
+	 */
+	public static <T> T min(final Iterator<T> iterator, Comparator<? super T> comparator) {
+		if (comparator == null)
+			throw new NullPointerException("comparator");
+		T min = iterator.next();
+		while (iterator.hasNext()) {
+			T element = iterator.next();
+			min = comparator.compare(min, element) <= 0 ? min : element;
+		}
+		return min;
+	}
+
+	/**
+	 * Finds the maximum of the elements according to their natural ordering. If there are several maxima, the first one
+	 * will be returned.
+	 * 
+     * <p>Note that this will advance or even exhaust the given iterator.</p>
+     * 
+	 * @param iterator
+	 *            the mutually comparable elements. May not be <code>null</code>.
+	 * @return the maximum
+	 * @throws NoSuchElementException
+	 *             if the iterator is empty
+	 * @since 2.7
+	 */
+	public static <T extends Comparable<? super T>> T max(final Iterator<T> iterator) {
+		return max(iterator, Ordering.natural());
+	}
+
+	/**
+	 * Finds the element that yields the maximum value when passed to <code>compareBy</code> If there are several
+	 * maxima, the first one will be returned.
+	 * 
+	 * <p>Note that this will advance or even exhaust the given iterator.</p>
+	 * 
+	 * @param iterator
+	 *            the elements to find the maximum of. May not be <code>null</code>.
+	 * @param compareBy
+	 *            a function that returns a comparable characteristic to compare the elements by. May not be <code>null</code>.
+	 * @return the maximum
+	 * @throws NoSuchElementException
+	 *             if the iterator is empty
+	 * @since 2.7
+	 */
+	public static <T, C extends Comparable<? super C>> T maxBy(final Iterator<T> iterator, final Function1<? super T, C> compareBy) {
+		if (compareBy == null)
+			throw new NullPointerException("compareBy");
+		return max(iterator, new KeyComparator<T, C>(compareBy));
+	}
+
+	/**
+	 * Finds the maximum element according to <code>comparator</code>. If there are several maxima, the first one will
+	 * be returned.
+	 * 
+	 * <p>Note that this will advance or even exhaust the given iterator.</p>
+	 * 
+	 * @param iterator
+	 *            the elements to find the maximum of. May not be <code>null</code>.
+	 * @param comparator
+	 *            the comparison function. May not be <code>null</code>.
+	 * @return the maximum
+	 * @throws NoSuchElementException
+	 *             if the iterator is empty
+	 * @since 2.7
+	 */
+	public static <T> T max(final Iterator<T> iterator, Comparator<? super T> comparator) {
+		if (comparator == null)
+			throw new NullPointerException("comparator");
+		T max = iterator.next();
+		while (iterator.hasNext()) {
+			T element = iterator.next();
+			max = comparator.compare(max, element) >= 0 ? max : element;
+		}
+		return max;
+	}
+
+	/**
+	 * Returns <tt>true</tt> if this Iterator contains the specified element.
+	 * More formally, returns <tt>true</tt> if and only if this Iterator
+	 * contains at least one element <tt>e</tt> such that
+	 * <tt>(o==null&nbsp;?&nbsp;e==null&nbsp;:&nbsp;o.equals(e))</tt>.
+	 * 
+	 * <p>
+	 * Note that this will advance or even exhaust the given iterator.
+	 * </p>
+	 *
+	 * @param iterator 
+	 * 			the elements to test
+	 * @param o 
+	 * 			element whose presence in this Iterator is to be tested
+	 * @return <tt>true</tt> if this Iterator contains the specified element
+	 */
+	public static boolean contains(Iterator<?> iterator, Object o) {
+		while (iterator.hasNext()) {
+			if (Objects.equals(o, iterator.next())) {
+				return true;
+			}
+		}
+		return false;
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Lib.gwt.xml b/java/org/eclipse/xtext/xbase/lib/Lib.gwt.xml
new file mode 100644
index 0000000..2e68e5f
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Lib.gwt.xml
@@ -0,0 +1,9 @@
+<?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>
+	<inherits name="com.google.gwt.user.User" />
+	<inherits name="com.google.common.collect.Collect" />
+	<inherits name="org.eclipse.xtend2.lib.Lib" />
+	<source path=""/>
+	<super-source path="super"/>
+</module>
\ No newline at end of file
diff --git a/java/org/eclipse/xtext/xbase/lib/ListExtensions.java b/java/org/eclipse/xtext/xbase/lib/ListExtensions.java
new file mode 100644
index 0000000..be1ff3b
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ListExtensions.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * 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.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.internal.FunctionDelegate;
+import org.eclipse.xtext.xbase.lib.internal.KeyComparator;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.collect.Lists;
+
+/**
+ * This is an extension library for {@link List lists}.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ */
+/* To be discussed:
+ * List#binarySearch(Comparator<T>)
+ * List#binarySearchBy(T->Comparable<?>)
+ * List#reverseView should return a list and not an iterable
+ * List#tail -> List
+ * List#take -> List
+ * List#drop -> List
+ */
+@GwtCompatible public class ListExtensions {
+
+	/**
+	 * Sorts the specified list itself into ascending order, according to the natural ordering of its elements.
+	 * 
+	 * @param list
+	 *            the list to be sorted. May not be <code>null</code>.
+	 * @return the sorted list itself.
+	 * @see Collections#sort(List)
+	 */
+	public static <T extends Comparable<? super T>> List<T> sortInplace(List<T> list) {
+		Collections.sort(list);
+		return list;
+	}
+
+	/**
+	 * Sorts the specified list itself according to the order induced by the specified comparator.
+	 * 
+	 * @param list
+	 *            the list to be sorted. May not be <code>null</code>.
+	 * @param comparator
+	 *            the comparator to be used. May be <code>null</code> to indicate that the natural ordering of the
+	 *            elements should be used.
+	 * @return the sorted list itself.
+	 * @see Collections#sort(List, Comparator)
+	 * @see #sortInplace(List)
+	 * @see #sortInplaceBy(List, org.eclipse.xtext.xbase.lib.Functions.Function1)
+	 */
+	public static <T> List<T> sortInplace(List<T> list, Comparator<? super T> comparator) {
+		Collections.sort(list, comparator);
+		return list;
+	}
+
+	/**
+	 * Sorts the specified list itself according to the order induced by applying a key function to each element which
+	 * yields a comparable criteria.
+	 * 
+	 * @param list
+	 *            the list to be sorted. May not be <code>null</code>.
+	 * @param key
+	 *            the key function to-be-used. May not be <code>null</code>.
+	 * @return the sorted list itself.
+	 * @see Collections#sort(List)
+	 */
+	public static <T, C extends Comparable<? super C>> List<T> sortInplaceBy(List<T> list,
+			final Functions.Function1<? super T, C> key) {
+		if (key == null)
+			throw new NullPointerException("key");
+		Collections.sort(list, new KeyComparator<T, C>(key));
+		return list;
+	}
+
+	/**
+	 * Provides a reverse view on the given list which is especially useful to traverse a list backwards in a for-each
+	 * loop. The list itself is not modified by calling this method.
+	 * 
+	 * @param list
+	 *            the list whose elements should be traversed in reverse. May not be <code>null</code>.
+	 * @return a list with the same elements as the given list, in reverse
+	 */
+	@Pure
+	public static <T> List<T> reverseView(List<T> list) {
+		return Lists.reverse(list);
+	}
+
+	/**
+	 * Reverses the order of the elements in the specified list. The list itself will be modified.
+	 * 
+	 * @param list
+	 *            the list whose elements are to be reversed.
+	 * @return the list itself
+	 * @throws UnsupportedOperationException
+	 *             if the specified list or its list-iterator does not support the <tt>set</tt> method.
+	 */
+	public static <T> List<T> reverse(List<T> list) {
+		Collections.reverse(list);
+		return list;
+	}
+
+	/**
+	 * Returns a list that performs the given {@code transformation} for each element of {@code original} when
+	 * requested. The mapping is done lazily. That is, subsequent iterations of the elements in the list will
+	 * repeatedly apply the transformation. The returned list is a transformed view of {@code original}; changes to
+	 * {@code original} will be reflected in the returned list and vice versa (e.g. invocations of {@link List#remove(int)}).
+	 * 
+	 * 
+	 * @param original
+	 *            the original list. May not be <code>null</code>.
+	 * @param transformation
+	 *            the transformation. May not be <code>null</code>.
+	 * @return a list that effectively contains the results of the transformation. Never <code>null</code>.
+	 */
+	@Pure
+	public static <T, R> List<R> map(List<T> original, Function1<? super T, ? extends R> transformation) {
+		return Lists.transform(original, new FunctionDelegate<T, R>(transformation));
+	}
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/LongExtensions.java b/java/org/eclipse/xtext/xbase/lib/LongExtensions.java
new file mode 100644
index 0000000..ec29335
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/LongExtensions.java
@@ -0,0 +1,1631 @@
+/*******************************************************************************
+ * 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 Long} numbers.
+ * 
+ * @author Jan Koehnlein - Code generator
+ * @since 2.3
+ */
+@GwtCompatible public class LongExtensions {
+	
+	/**
+	 * The bitwise inclusive <code>or</code> operation. This is the equivalent to the java <code>|</code> operator.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param b
+	 *            a long
+	 * @return <code>a|b</code>
+	 */
+	@Pure
+	@Inline(value="($1 | $2)", constantExpression=true)
+	public static long bitwiseOr(long a, long b) {
+		return a | b;
+	}
+
+	/**
+	 * The bitwise exclusive <code>or</code> operation. This is the equivalent to the java <code>^</code> operator.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param b
+	 *            a long.
+	 * @return <code>a^b</code>
+	 */
+	@Pure
+	@Inline(value="($1 ^ $2)", constantExpression=true)
+	public static long bitwiseXor(long a, long b) {
+		return a ^ b;
+	}
+
+	/**
+	 * The bitwise <code>and</code> operation. This is the equivalent to the java <code>&amp;</code> operator.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param b
+	 *            a long.
+	 * @return <code>a&amp;b</code>
+	 */
+	@Pure
+	@Inline(value="($1 & $2)", constantExpression=true)
+	public static long bitwiseAnd(long a, long b) {
+		return a & b;
+	}
+
+	/**
+	 * The bitwise complement operation. This is the equivalent to the java <code>~</code> operator.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @return the bitwise complement of <code>a</code>.
+	 */
+	@Pure
+	@Inline(value="(~$1)", constantExpression=true)
+	public static long bitwiseNot(long a) {
+		return ~a;
+	}
+
+	/**
+	 * The binary <code>signed left shift</code> operator. This is the equivalent to the java <code>&lt;&lt;</code> operator.
+	 * Fills in a zero as the least significant bit.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param distance 
+	 *            the number of times to shift.
+	 * @return <code>a&lt;&lt;distance</code>
+	 * @deprecated use {@link #operator_doubleLessThan(long, int)} instead.
+	 */
+	@Deprecated
+	@Pure
+	@Inline(value="($1 << $2)", constantExpression=true)
+	public static long shiftLeft(long a, int distance) {
+		return a << distance;
+	}
+
+	/**
+	 * The binary <code>signed left shift</code> operator. This is the equivalent to the java <code>&lt;&lt;</code> operator.
+	 * Fills in a zero as the least significant bit.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param distance 
+	 *            the number of times to shift.
+	 * @return <code>a&lt;&lt;distance</code>
+	 */
+	@Pure
+	@Inline(value="($1 << $2)", constantExpression=true)
+	public static long operator_doubleLessThan(long a, int distance) {
+		return a << distance;
+	}
+
+	/**
+	 * The binary <code>signed right sift</code> operator. This is the equivalent to the java <code>&gt;&gt;</code> operator.
+	 * Shifts in the value of the sign bit as the leftmost bit, thus preserving the sign of the initial value.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param distance 
+	 *            the number of times to shift.
+	 * @return <code>a&gt;&gt;distance</code>
+	 * @deprecated use {@link #operator_doubleGreaterThan(long, int)} instead.
+	 */
+	@Deprecated
+	@Pure
+	@Inline(value="($1 >> $2)", constantExpression=true)
+	public static long shiftRight(long a, int distance) {
+		return a >> distance;
+	}
+
+	/**
+	 * The binary <code>signed right sift</code> operator. This is the equivalent to the java <code>&gt;&gt;</code> operator.
+	 * Shifts in the value of the sign bit as the leftmost bit, thus preserving the sign of the initial value.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param distance 
+	 *            the number of times to shift.
+	 * @return <code>a&gt;&gt;distance</code>
+	 */
+	@Pure
+	@Inline(value="($1 >> $2)", constantExpression=true)
+	public static long operator_doubleGreaterThan(long a, int distance) {
+		return a >> distance;
+	}
+
+	/**
+	 * The binary <code>unsigned right shift</code> operator. This is the equivalent to the java <code>&gt;&gt;&gt;</code> operator.
+	 * Shifts in zeros into as leftmost bits, thus always yielding a positive integer.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param distance
+	 *            the number of times to shift.
+	 * @return <code>a&gt;&gt;&gt;distance</code>
+	 * @deprecated use {@link #operator_tripleGreaterThan(long, int)} instead.
+	 */
+	@Deprecated
+	@Pure
+	@Inline(value="($1 >>> $2)", constantExpression=true)
+	public static long shiftRightUnsigned(long a, int distance) {
+		return a >>> distance;
+	}
+
+	/**
+	 * The binary <code>unsigned right shift</code> operator. This is the equivalent to the java <code>&gt;&gt;&gt;</code> operator.
+	 * Shifts in zeros into as leftmost bits, thus always yielding a positive integer.
+	 * 
+	 * @param a
+	 *            a long.
+	 * @param distance
+	 *            the number of times to shift.
+	 * @return <code>a&gt;&gt;&gt;distance</code>
+	 */
+	@Pure
+	@Inline(value="($1 >>> $2)", constantExpression=true)
+	public static long operator_tripleGreaterThan(long a, int distance) {
+		return a >>> distance;
+	}
+
+	// BEGIN generated code
+	/**
+	 * The unary <code>minus</code> operator. This is the equivalent to the Java's <code>-</code> function.
+	 * 
+	 * @param l  a long.
+	 * @return   <code>-l</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="(-$1)", constantExpression=true)
+	public static long operator_minus(long l) {
+		return -l;
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param l  a long.
+	 * @return   <code>l--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static long operator_minusMinus(long l) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param l  a long.
+	 * @return   <code>l--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static Long operator_minusMinus(Long l) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param l  a long.
+	 * @return   <code>l++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static long operator_plusPlus(long l) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param l  a long.
+	 * @return   <code>l++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static Long operator_plusPlus(Long l) {
+		throw new HardcodedInInterpreterException();
+	}
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a double.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(long 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 long.
+	 * @param b  a double.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(long 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 long.
+	 * @param b  a double.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(long 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 long.
+	 * @param b  a double.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(long 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 long.
+	 * @param b  a double.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a double.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(long 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 long.
+	 * @param b  a double.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a double.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(long 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 long.
+	 * @param b  a double.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(long 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 long.
+	 * @param b  a float.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(long 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 long.
+	 * @param b  a long.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(long 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 long.
+	 * @param b  an integer.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(long 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 long.
+	 * @param b  a character.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(long 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 long.
+	 * @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(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(long 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 long.
+	 * @param b  a short.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(long 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 long.
+	 * @param b  a byte.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(long a, byte b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(long a, byte b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(long a, byte b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(long a, byte b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(long a, byte b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(long a, byte b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(long a, byte b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(long a, byte b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(long a, byte b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(long a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(long a, byte 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 long.
+	 * @param b  a byte.
+	 * @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(long a, byte 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 long.
+	 * @param b  a byte.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(long a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a long.
+	 * @param b  a byte.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(long a, byte b) {
+		return a != b;
+	}
+	
+	// END generated code
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/MapExtensions.java b/java/org/eclipse/xtext/xbase/lib/MapExtensions.java
new file mode 100644
index 0000000..ff809d8
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/MapExtensions.java
@@ -0,0 +1,422 @@
+/*******************************************************************************
+ * 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.util.Collections;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.Functions.Function2;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure3;
+import org.eclipse.xtext.xbase.lib.internal.FunctionDelegate;
+import org.eclipse.xtext.xbase.lib.internal.UnmodifiableMergingMapView;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Objects;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+
+
+/**
+ * This is an extension library for {@link Map maps}.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @author Stephane Galland - Add operators on map structures.
+ */
+@GwtCompatible public class MapExtensions {
+
+	/**
+	 * Applies the given {@code procedure} for each {@link java.util.Map.Entry key value pair} of the given {@code map}. 
+	 * 
+	 * @param map
+	 *            the map. May not be <code>null</code>.
+	 * @param procedure
+	 *            the procedure. May not be <code>null</code>.
+	 */
+	public static <K, V> void forEach(Map<K, V> map, Procedure2<? super K, ? super V> procedure) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		for (Map.Entry<K, V> entry : map.entrySet()) {
+			procedure.apply(entry.getKey(), entry.getValue());
+		}
+	}
+	
+	/**
+	 * Applies the given {@code procedure} for each {@link java.util.Map.Entry key value pair} of the given {@code map}. 
+	 * The procedure takes the key, the value and a loop counter. If the counter would overflow, {@link Integer#MAX_VALUE}
+	 * is returned for all subsequent pairs. The first pair is at index zero.
+	 * 
+	 * @param map
+	 *            the map. May not be <code>null</code>.
+	 * @param procedure
+	 *            the procedure. May not be <code>null</code>.
+	 */
+	public static <K, V> void forEach(Map<K, V> map, Procedure3<? super K, ? super V, ? super Integer> procedure) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		int i = 0;
+		for (Map.Entry<K, V> entry : map.entrySet()) {
+			procedure.apply(entry.getKey(), entry.getValue(), i);
+			if (i != Integer.MAX_VALUE)
+				i++;
+		}
+	}
+	
+	/**
+	 * <p>
+	 * Returns a filtered live view on top of the original map. Changes to one affect the other.
+	 * </p>
+	 * 
+	 * <p>
+	 * The mapping is done lazily. That is, subsequent access of the values in the map will repeatedly apply the
+	 * transformation. Characteristics of the original map, such as iteration order, are left intact. Changes in the
+	 * original map are reflected in the result map. The results supports removal if the original map supports removal.
+	 * </p>
+	 * 
+	 * @param original
+	 *            the original map. May not be <code>null</code>.
+	 * @param predicate
+	 *            the predicate. May not be <code>null</code>.
+	 * @return a filtered view on top of the original map. Never <code>null</code>.
+	 */
+	public static <K, V> Map<K, V> filter(Map<K, V> original, final Function2<? super K, ? super V, Boolean> predicate) {
+		if (predicate == null)
+			throw new NullPointerException("predicate");
+		return Maps.filterEntries(original, new Predicate<Map.Entry<K, V>>() {
+			@Override
+			public boolean apply(Map.Entry<K, V> input) {
+				Boolean result = predicate.apply(input.getKey(), input.getValue());
+				return result.booleanValue();
+			}
+		});
+	}
+	
+	/**
+	 * Add the given pair into the map.
+	 *
+	 * <p>
+	 * If the pair key already exists in the map, its value is replaced
+	 * by the value in the pair, and the old value in the map is returned.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param map the map to update.
+	 * @param entry the entry (key, value) to add into the map.
+	 * @return the value previously associated to the key, or <code>null</code>
+	 *     if the key was not present in the map before the addition.
+	 * @since 2.15
+	 */
+	@Inline(value = "$1.put($2.getKey(), $2.getValue())", statementExpression = true)
+	public static <K, V> V operator_add(Map<K, V> map, Pair<? extends K, ? extends V> entry) {
+		return map.put(entry.getKey(), entry.getValue());
+	}
+
+	/**
+	 * Add the given entries of the input map into the output map.
+	 *
+	 * <p>
+	 * If a key in the inputMap already exists in the outputMap, its value is
+	 * replaced in the outputMap by the value from the inputMap.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param outputMap the map to update.
+	 * @param inputMap the entries to add.
+	 * @since 2.15
+	 */
+	@Inline(value = "$1.putAll($2)", statementExpression = true)
+	public static <K, V> void operator_add(Map<K, V> outputMap, Map<? extends K, ? extends V> inputMap) {
+		outputMap.putAll(inputMap);
+	}
+
+	/**
+	 * Add the given pair to a given map for obtaining a new map.
+	 *
+	 * <p>
+	 * The replied map is a view on the given map. It means that any change
+	 * in the original map is reflected to the result of this operation.
+	 * </p>
+	 *
+	 * <p>
+	 * Even if the key of the right operand exists in the left operand, the value in the right operand is preferred.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param left the map to consider.
+	 * @param right the entry (key, value) to add into the map.
+	 * @return an immutable map with the content of the map and with the given entry.
+	 * @throws IllegalArgumentException - when the right operand key exists in the left operand.
+	 * @since 2.15
+	 */
+	@Pure
+	@Inline(value = "$3.union($1, $4.singletonMap($2.getKey(), $2.getValue()))",
+			imported = { MapExtensions.class, Collections.class })
+	public static <K, V> Map<K, V> operator_plus(Map<K, V> left, final Pair<? extends K, ? extends V> right) {
+		return union(left, Collections.singletonMap(right.getKey(), right.getValue()));
+	}
+
+	/**
+	 * Merge the two maps.
+	 *
+	 * <p>
+	 * The replied map is a view on the given map. It means that any change
+	 * in the original map is reflected to the result of this operation.
+	 * </p>
+	 *
+	 * <p>
+	 * If a key exists in the left and right operands, the value in the right operand is preferred.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param left the left map.
+	 * @param right the right map.
+	 * @return a map with the merged contents from the two maps.
+	 * @throws IllegalArgumentException - when a right operand key exists in the left operand.
+	 * @since 2.15
+	 */
+	@Pure
+	@Inline(value = "$3.union($1, $2)", imported = MapExtensions.class)
+	public static <K, V> Map<K, V> operator_plus(Map<K, V> left, Map<? extends K, ? extends V> right) {
+		return union(left, right);
+	}
+
+	/**
+	 * Remove a key from the given map.
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param map the map to update.
+	 * @param key the key to remove.
+	 * @return the removed value, or <code>null</code> if the key was not
+	 *     present in the map.
+	 * @since 2.15
+	 */
+	@Inline(value = "$1.remove($2)", statementExpression = true)
+	public static <K, V> V operator_remove(Map<K, V> map, K key) {
+		return map.remove(key);
+	}
+
+	/**
+	 * Remove the given pair into the map.
+	 *
+	 * <p>
+	 * If the given key is inside the map, but is not mapped to the given value, the
+	 * map will not be changed.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param map the map to update.
+	 * @param entry the entry (key, value) to remove from the map.
+	 * @return {@code true} if the pair was removed.
+	 * @since 2.15
+	 */
+	@Inline(value = "$1.remove($2.getKey(), $2.getValue())", statementExpression = true)
+	public static <K, V> boolean operator_remove(Map<K, V> map, Pair<? extends K, ? extends V> entry) {
+		//TODO use the JRE 1.8 API: map.remove(entry.getKey(), entry.getValue());
+		final K key = entry.getKey();
+		final V storedValue = map.get(entry.getKey());
+	        if (!Objects.equal(storedValue, entry.getValue())
+			|| (storedValue == null && !map.containsKey(key))) {
+	            return false;
+        	}
+        	map.remove(key);
+	        return true;
+	}
+
+	/**
+	 * Remove pairs with the given keys from the map.
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param map the map to update.
+	 * @param keysToRemove the keys of the pairs to remove.
+	 * @since 2.15
+	 */
+	public static <K, V> void operator_remove(Map<K, V> map, Iterable<? super K> keysToRemove) {
+		for (final Object key : keysToRemove) {
+			map.remove(key);
+		}
+	}
+
+	/**
+	 * Remove the given pair from a given map for obtaining a new map.
+	 *
+	 * <p>
+	 * If the given key is inside the map, but is not mapped to the given value, the
+	 * map will not be changed.
+	 * </p>
+	 *
+	 * <p>
+	 * The replied map is a view on the given map. It means that any change
+	 * in the original map is reflected to the result of this operation.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param left the map to consider.
+	 * @param right the entry (key, value) to remove from the map.
+	 * @return an immutable map with the content of the map and with the given entry.
+	 * @throws IllegalArgumentException - when the right operand key exists in the left operand.
+	 * @since 2.15
+	 */
+	@Pure
+	public static <K, V> Map<K, V> operator_minus(Map<K, V> left, final Pair<? extends K, ? extends V> right) {
+		return Maps.filterEntries(left, new Predicate<Entry<K, V>>() {
+			@Override
+			public boolean apply(Entry<K, V> input) {
+				return !Objects.equal(input.getKey(), right.getKey()) || !Objects.equal(input.getValue(), right.getValue());
+			}
+		});
+	}
+
+	/**
+	 * Replies the elements of the given map except the pair with the given key.
+	 *
+	 * <p>
+	 * The replied map is a view on the given map. It means that any change
+	 * in the original map is reflected to the result of this operation.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param map the map to update.
+	 * @param key the key to remove.
+	 * @return the map with the content of the map except the key.
+	 * @since 2.15
+	 */
+	@Pure
+	public static <K, V> Map<K, V> operator_minus(Map<K, V> map, final K key) {
+		return Maps.filterKeys(map, new Predicate<K>() {
+			@Override
+			public boolean apply(K input) {
+				return !Objects.equal(input, key);
+			}
+		});
+	}
+
+	/**
+	 * Replies the elements of the left map without the pairs in the right map.
+	 * If the pair's values differ from
+	 * the value within the map, the map entry is not removed.
+	 *
+	 * <p>
+	 * The difference is an immutable
+	 * snapshot of the state of the maps at the time this method is called. It
+	 * will never change, even if the maps change at a later time.
+	 * </p>
+	 *
+	 * <p>
+	 * Since this method uses {@code HashMap} instances internally, the keys of
+	 * the supplied maps must be well-behaved with respect to
+	 * {@link Object#equals} and {@link Object#hashCode}.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param left the map to update.
+	 * @param right the pairs to remove.
+	 * @return the map with the content of the left map except the pairs of the right map.
+	 * @since 2.15
+	 */
+	@Pure
+	public static <K, V> Map<K, V> operator_minus(Map<K, V> left, final Map<? extends K, ? extends V> right) {
+		return Maps.filterEntries(left, new Predicate<Entry<K, V>>() {
+			@Override
+			public boolean apply(Entry<K, V> input) {
+				final V value = right.get(input.getKey());
+				if (value == null) {
+					return input.getValue() == null && right.containsKey(input.getKey());
+				}
+				return !Objects.equal(input.getValue(), value);
+			}
+		});
+	}
+
+	/**
+	 * Replies the elements of the given map except the pairs with the given keys.
+	 *
+	 * <p>
+	 * The replied map is a view on the given map. It means that any change
+	 * in the original map is reflected to the result of this operation.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param map the map to update.
+	 * @param keys the keys of the pairs to remove.
+	 * @return the map with the content of the map except the pairs.
+	 * @since 2.15
+	 */
+	@Pure
+	public static <K, V> Map<K, V> operator_minus(Map<K, V> map, final Iterable<?> keys) {
+		return Maps.filterKeys(map, new Predicate<K>() {
+			@Override
+			public boolean apply(K input) {
+				return !Iterables.contains(keys, input);
+			}
+		});
+	}
+
+	/**
+	 * Merge the given maps.
+	 *
+	 * <p>
+	 * The replied map is a view on the given two maps.
+	 * If a key exists in the two maps, the replied value is the value of the right operand.
+	 * </p>
+	 *
+	 * <p>
+	 * Even if the key of the right operand exists in the left operand, the value in the right operand is preferred.
+	 * </p>
+	 *
+	 * <p>
+	 * The replied map is unmodifiable.
+	 * </p>
+	 *
+	 * @param <K> type of the map keys.
+	 * @param <V> type of the map values.
+	 * @param left the left map.
+	 * @param right the right map.
+	 * @return a map with the merged contents from the two maps.
+	 * @since 2.15
+	 */
+	@Pure
+	@Inline(value = "(new $3<$5, $6>($1, $2))", imported = UnmodifiableMergingMapView.class, constantExpression = true)
+	public static <K, V> Map<K, V> union(Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) {
+		return new UnmodifiableMergingMapView<K, V>(left, right);
+	}
+
+	/**
+	 * <p>Returns a map that performs the given {@code transformation} for each value of {@code original} when requested.</p>
+	 * 
+	 * <p>The mapping is done lazily. That is, subsequent access of the values in the map will repeatedly apply the
+	 * transformation. Characteristics of the original map, such as iteration order, are left intact. Changes in the
+	 * original map are reflected in the result map. The results supports removal if the original map supports removal.</p>
+	 * 
+	 * @param original
+	 *            the original map. May not be <code>null</code>.
+	 * @param transformation
+	 *            the transformation. May not be <code>null</code>.
+	 * @return a map with equal keys but transformed values. Never <code>null</code>.
+	 * @since 2.4
+	 */
+	@Pure
+	public static <K, V1, V2> Map<K, V2> mapValues(Map<K, V1> original, Function1<? super V1, ? extends V2> transformation) {
+		return Maps.transformValues(original, new FunctionDelegate<V1, V2>(transformation));
+	}
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ObjectExtensions.java b/java/org/eclipse/xtext/xbase/lib/ObjectExtensions.java
new file mode 100644
index 0000000..1436352
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ObjectExtensions.java
@@ -0,0 +1,186 @@
+/*******************************************************************************
+ * 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 org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Objects;
+
+/**
+ * This is an extension library for all {@link Object objects}.
+ */
+@GwtCompatible public class ObjectExtensions {
+
+	/**
+	 * The <code>equals not</code> operator. This is the equivalent to a negated, null-safe
+	 * {@link Object#equals(Object)} method.
+	 * 
+	 * @param a
+	 *            an object.
+	 * @param b
+	 *            another object.
+	 * @return <code>true</code> if {@code a} and {@code b} are not equal.
+	 */
+	@Pure
+	@Inline(value="(!$3.equal($1, $2))", imported=Objects.class)
+	public static boolean operator_notEquals(Object a, Object b) {
+		return !Objects.equal(a, b);
+	}
+
+	/**
+	 * The <code>equals</code> operator. This is the equivalent to a null-safe invocation of
+	 * {@link Object#equals(Object)}.
+	 * 
+	 * @param a
+	 *            an object.
+	 * @param b
+	 *            another object.
+	 * @return <code>true</code> if {@code a} and {@code b} are equal.
+	 */
+	@Pure
+	@Inline(value="$3.equal($1, $2)", imported=Objects.class)
+	public static boolean operator_equals(Object a, Object b) {
+		return Objects.equal(a, b);
+	}
+
+	/**
+	 * Returns <code>true</code> if {@code a} and {@code b} are identical (the same instance)
+	 * or both <code>null</code>. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a
+	 *            an object.
+	 * @param b
+	 *            another object.
+	 * @return Java's <code>a == b</code>
+	 */
+	@Pure
+	@Inline(value = "($1 == $2)", constantExpression = true)
+	public static boolean identityEquals(Object a, Object b) {
+		return a == b;
+	}
+
+	/**
+	 * The <code>identity equals</code> operator. This is the equivalent to Java's <code>==</code>
+	 * operator.
+	 * 
+	 * @param a
+	 *            an object.
+	 * @param b
+	 *            another object.
+	 * @return Java's <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value = "($1 == $2)", constantExpression = true)
+	public static boolean operator_tripleEquals(Object a, Object b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a
+	 *            an object.
+	 * @param b
+	 *            another object.
+	 * @return Java's <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value = "($1 != $2)", constantExpression = true)
+	public static boolean operator_tripleNotEquals(Object a, Object b) {
+		return a != b;
+	}
+
+	/**
+	 * The <code>mappedTo</code> operator yields a {@link Pair} with {@code a} as the {@link Pair#getKey() key} and
+	 * {@code b} as its {@link Pair#getValue() value}.
+	 * 
+	 * @param a
+	 *            an object.
+	 * @param b
+	 *            another object.
+	 * @return a {@link Pair}. Never <code>null</code>.
+	 */
+	@Pure
+	@Inline(value="$3.$4of($1, $2)", imported=Pair.class)
+	public static <A, B> Pair<A, B> operator_mappedTo(A a, B b) {
+		return Pair.of(a, b);
+	}
+	
+	/**
+	 * The <code>doubleArrow</code> operator is used as a 'with'- or 'let'-operation.
+	 * It allows to bind an object to a local scope in order to do something on it.
+	 * 
+	 * Example:
+	 * <code>
+	 *   new Person =&gt; [
+	 *     firstName = 'Han'
+	 *     lastName = 'Solo'
+	 *   ]
+	 * </code>
+	 * 
+	 * @param object
+	 *            an object. Can be <code>null</code>.
+	 * @param block
+	 *            the block to execute with the given object. Must not be <code>null</code>.
+	 * @return the reference to object.
+	 * @since 2.3
+	 */
+	public static <T> T operator_doubleArrow(T object, Procedure1<? super T> block) {
+		block.apply(object);
+		return object;
+	}
+	
+	/**
+	 * The binary <code>+</code> operator that concatenates two strings.
+	 * 
+	 * @param a
+	 *            an {@link Object}.
+	 * @param b
+	 *            a {@link String}.
+	 * @return <code>a + b</code>
+	 * @since 2.3
+	 */
+	@Pure /* not guaranteed pure , since toString() is invoked on the argument a*/
+	@Inline("($1 + $2)")
+	public static String operator_plus(Object a, String b) {
+		return a + b;
+	}
+	
+	/**
+	 * The elvis operator <code>?:</code> is a short hand notation for
+	 * providing default value in case an expression evaluates to <code>null</code>.
+	 * 
+	 * Not that the Xtend compiler will inline calls to this not call this method with a short-circuit semantic.
+	 * That is the second argument is only evaluated if the first one evaluates to <code>null</code>.
+	 * 
+	 * Example:
+	 * <code>person.name?:'Hans'</code>
+	 * 
+	 * @param first
+	 *            an {@link Object}. Might be <code>null</code>.
+	 * @param second
+	 *            an {@link Object}. Might be <code>null</code>.
+	 * 
+	 * @return a reference to <code>first</code> if <code>first != null </code>, <code>second<code> otherwise, 
+	 * @since 2.3
+	 */
+	@Pure
+	public static <T> T operator_elvis(T first, T second) {
+		if (first != null)
+			return first;
+		return second;
+	}
+	
+	
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Pair.java b/java/org/eclipse/xtext/xbase/lib/Pair.java
new file mode 100644
index 0000000..d64220b
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Pair.java
@@ -0,0 +1,103 @@
+/*******************************************************************************
+ * 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.io.Serializable;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Objects;
+
+/**
+ * An immutable pair of {@link #getKey() key} and {@link #getValue() value}. A pair is considered to be
+ * {@link #equals(Object) equal} to another pair if both the key and the value are equal.
+ * 
+ * @param <K>
+ *            the key-type of the pair.
+ * @param <V>
+ *            the value-type of the pair.
+ * @author Sebastian Zarnekow - Initial contribution and API
+ */
+@GwtCompatible public final class Pair<K, V> implements Serializable {
+
+	private static final long serialVersionUID = 736548906251305939L;
+	private final K k;
+	private final V v;
+	
+	/**
+	 * Creates a new instance with the given key and value.
+	 * May be used instead of the constructor for convenience reasons.
+	 * 
+	 * @param k
+	 *            the key. May be <code>null</code>.
+	 * @param v
+	 *            the value. May be <code>null</code>.
+	 * @return a newly created pair. Never <code>null</code>.
+	 * @since 2.3
+	 */
+	@Pure
+	public static <K, V> Pair<K, V> of(K k, V v) {
+		return new Pair<K, V>(k, v);
+	}
+
+	/**
+	 * Creates a new instance with the given key and value.
+	 * 
+	 * @param k
+	 *            the key. May be <code>null</code>.
+	 * @param v
+	 *            the value. May be <code>null</code>.
+	 * 
+	 */
+	@Pure
+	public Pair(K k, V v) {
+		this.k = k;
+		this.v = v;
+	}
+
+	/**
+	 * Returns the key.
+	 * 
+	 * @return the key.
+	 */
+	@Pure
+	public K getKey() {
+		return k;
+	}
+
+	/**
+	 * Returns the value.
+	 * 
+	 * @return the value.
+	 */
+	@Pure
+	public V getValue() {
+		return v;
+	}
+
+	@Override
+	public boolean equals(Object o) {
+		if (o == this)
+			return true;
+		if (!(o instanceof Pair))
+			return false;
+		Pair<?, ?> e = (Pair<?, ?>) o;
+		return Objects.equal(k, e.getKey()) && Objects.equal(v, e.getValue());
+	}
+
+	@Override
+	public int hashCode() {
+		return ((k == null) ? 0 : k.hashCode()) ^ ((v == null) ? 0 : v.hashCode());
+	}
+
+	@Override
+	public String toString() {
+		return k + "->" + v;
+	}
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ProcedureExtensions.java b/java/org/eclipse/xtext/xbase/lib/ProcedureExtensions.java
new file mode 100644
index 0000000..e048d25
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ProcedureExtensions.java
@@ -0,0 +1,157 @@
+/*******************************************************************************
+ * 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 org.eclipse.xtext.xbase.lib.Procedures.Procedure0;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure3;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure4;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure5;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure6;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * This is an extension library for {@link Procedures procedures}, e.g. side-effect only-closures.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @see Procedures
+ */
+@GwtCompatible public class ProcedureExtensions {
+
+	/**
+	 * Curries a procedure that takes one argument.
+	 * 
+	 * @param procedure
+	 *            the original procedure. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed argument.
+	 * @return a procedure that takes no arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1> Procedure0 curry(final Procedure1<? super P1> procedure, final P1 argument) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		return new Procedure0() {
+			@Override
+			public void apply() {
+				procedure.apply(argument);
+			}
+		};
+	}
+
+	/**
+	 * Curries a procedure that takes two arguments.
+	 * 
+	 * @param procedure
+	 *            the original procedure. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code procedure}.
+	 * @return a procedure that takes one argument. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2> Procedure1<P2> curry(final Procedure2<? super P1, ? super P2> procedure, final P1 argument) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		return new Procedure1<P2>() {
+			@Override
+			public void apply(P2 p) {
+				procedure.apply(argument, p);
+			}
+		};
+	}
+
+	/**
+	 * Curries a procedure that takes three arguments.
+	 * 
+	 * @param procedure
+	 *            the original procedure. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code procedure}.
+	 * @return a procedure that takes two arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, P3> Procedure2<P2, P3> curry(final Procedure3<? super P1, ? super P2, ? super P3> procedure, final P1 argument) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		return new Procedure2<P2, P3>() {
+			@Override
+			public void apply(P2 p2, P3 p3) {
+				procedure.apply(argument, p2, p3);
+			}
+		};
+	}
+
+	/**
+	 * Curries a procedure that takes four arguments.
+	 * 
+	 * @param procedure
+	 *            the original procedure. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code procedure}.
+	 * @return a procedure that takes three arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, P3, P4> Procedure3<P2, P3, P4> curry(final Procedure4<? super P1, ? super P2, ? super P3, ? super P4> procedure,
+			final P1 argument) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		return new Procedure3<P2, P3, P4>() {
+			@Override
+			public void apply(P2 p2, P3 p3, P4 p4) {
+				procedure.apply(argument, p2, p3, p4);
+			}
+		};
+	}
+
+	/**
+	 * Curries a procedure that takes five arguments.
+	 * 
+	 * @param procedure
+	 *            the original procedure. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code procedure}.
+	 * @return a procedure that takes four arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, P3, P4, P5> Procedure4<P2, P3, P4, P5> curry(final Procedure5<? super P1, ? super P2, ? super P3, ? super P4, ? super P5> procedure,
+			final P1 argument) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		return new Procedure4<P2, P3, P4, P5>() {
+			@Override
+			public void apply(P2 p2, P3 p3, P4 p4, P5 p5) {
+				procedure.apply(argument, p2, p3, p4, p5);
+			}
+		};
+	}
+
+	/**
+	 * Curries a procedure that takes six arguments.
+	 * 
+	 * @param procedure
+	 *            the original procedure. May not be <code>null</code>.
+	 * @param argument
+	 *            the fixed first argument of {@code procedure}.
+	 * @return a procedure that takes five arguments. Never <code>null</code>.
+	 */
+	@Pure
+	public static <P1, P2, P3, P4, P5, P6> Procedure5<P2, P3, P4, P5, P6> curry(
+			final Procedure6<? super P1, ? super P2, ? super P3, ? super P4, ? super P5, ? super P6> procedure, final P1 argument) {
+		if (procedure == null)
+			throw new NullPointerException("procedure");
+		return new Procedure5<P2, P3, P4, P5, P6>() {
+			@Override
+			public void apply(P2 p2, P3 p3, P4 p4, P5 p5, P6 p6) {
+				procedure.apply(argument, p2, p3, p4, p5, p6);
+			}
+		};
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Procedures.java b/java/org/eclipse/xtext/xbase/lib/Procedures.java
new file mode 100644
index 0000000..7fa5008
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Procedures.java
@@ -0,0 +1,145 @@
+/*******************************************************************************
+ * Copyright (c) 2010 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 class serves as a container for the various procedure types that are used to implement the type of closures in
+ * Xbase that do not return any results but a meant to cause side-effects.
+ * 
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @see ProcedureExtensions
+ * @see Functions
+ */
+@GwtCompatible public interface Procedures {
+
+	/**
+	 * A procedure without any parameters, e.g. a {@link Runnable}.
+	 */
+	interface Procedure0 {
+
+		void apply();
+
+	}
+
+	/**
+	 * A procedure that takes one argument.
+	 * 
+	 * @param <Param>
+	 *            the only argument that is passed to the {@link #apply(Object) closure}
+	 */
+	interface Procedure1<Param> {
+
+		void apply(Param p);
+
+	}
+
+	/**
+	 * A procedure that takes two arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the {@link #apply(Object, Object) closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the {@link #apply(Object, Object) closure}
+	 */
+	interface Procedure2<P1, P2> {
+
+		void apply(P1 p1, P2 p2);
+
+	}
+
+	/**
+	 * A procedure that takes three arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the {@link #apply(Object, Object, Object) closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the {@link #apply(Object, Object, Object) closure}
+	 * @param <P3>
+	 *            the third argument that is passed to the {@link #apply(Object, Object, Object) closure}
+	 */
+	interface Procedure3<P1, P2, P3> {
+
+		void apply(P1 p1, P2 p2, P3 p3);
+
+	}
+
+	/**
+	 * A procedure that takes four arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the {@link #apply(Object, Object, Object, Object) closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the {@link #apply(Object, Object, Object, Object) closure}
+	 * @param <P3>
+	 *            the third argument that is passed to the {@link #apply(Object, Object, Object, Object) closure}
+	 * @param <P4>
+	 *            the fourth argument that is passed to the {@link #apply(Object, Object, Object, Object) closure}
+	 */
+	interface Procedure4<P1, P2, P3, P4> {
+
+		void apply(P1 p1, P2 p2, P3 p3, P4 p4);
+
+	}
+
+	/**
+	 * A procedure that takes five arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <P3>
+	 *            the third argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <P4>
+	 *            the fourth argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 * @param <P5>
+	 *            the fifth argument that is passed to the {@link #apply(Object, Object, Object, Object, Object)
+	 *            closure}
+	 */
+	interface Procedure5<P1, P2, P3, P4, P5> {
+
+		void apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5);
+
+	}
+
+	/**
+	 * A procedure that takes six arguments.
+	 * 
+	 * @param <P1>
+	 *            the first argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P2>
+	 *            the second argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P3>
+	 *            the third argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P4>
+	 *            the fourth argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P5>
+	 *            the fifth argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 * @param <P6>
+	 *            the sixth argument that is passed to the
+	 *            {@link #apply(Object, Object, Object, Object, Object, Object) closure}
+	 */
+	interface Procedure6<P1, P2, P3, P4, P5, P6> {
+
+		void apply(P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6);
+
+	}
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/Pure.java b/java/org/eclipse/xtext/xbase/lib/Pure.java
new file mode 100644
index 0000000..1f72c5b
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/Pure.java
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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 java.lang.annotation.Documented;
+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;
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * The annotated constructor or method causes no externally visible side-effects and 
+ * does not mutate non-local state. 
+ * 
+ * In other words: if the result of a pure function or constructor is not used, it 
+ * is dead code and is supposed to be removeable without changing the behavior of the 
+ * program.
+ * 
+ * On {@link Inline}d methods this means the compiler cannot use the resulting Java
+ * expression as a statement. 
+ *  
+ * @author Sven Efftinge - Initial contribution and API
+ * 
+ * @since 2.3
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({
+    ElementType.CONSTRUCTOR,
+    ElementType.METHOD})
+@Documented
+@Beta
+@GwtCompatible public @interface Pure {
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ReassignFirstArgument.java b/java/org/eclipse/xtext/xbase/lib/ReassignFirstArgument.java
new file mode 100644
index 0000000..b8f888d
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ReassignFirstArgument.java
@@ -0,0 +1,36 @@
+/*******************************************************************************
+ * 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.xtext.xbase.lib;
+
+import java.lang.annotation.Documented;
+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;
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * The annotated function assigns the returned value to the first argument.
+ * 
+ * That is, it is required that the first argument is a reference to an assignable
+ * variable or field.
+ * 
+ * @author Anton Kosyakov - Initial contribution and API
+ * @since 2.6
+ */
+@Beta
+@Retention(RetentionPolicy.RUNTIME)
+@Target(value = { ElementType.METHOD })
+@Documented
+@GwtCompatible
+public @interface ReassignFirstArgument {
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/ShortExtensions.java b/java/org/eclipse/xtext/xbase/lib/ShortExtensions.java
new file mode 100644
index 0000000..270d562
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/ShortExtensions.java
@@ -0,0 +1,1470 @@
+/*******************************************************************************
+ * 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 Short} numbers.
+ * 
+ * @author Jan Koehnlein - Code generator
+ * @since 2.3
+ */
+@GwtCompatible public class ShortExtensions {
+	// BEGIN generated code
+	/**
+	 * The unary <code>minus</code> operator. This is the equivalent to the Java's <code>-</code> function.
+	 * 
+	 * @param s  a short.
+	 * @return   <code>-s</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="(-$1)", constantExpression=true)
+	public static int operator_minus(short s) {
+		return -s;
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param s  a short.
+	 * @return   <code>s--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static short operator_minusMinus(short s) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>decrement</code> operator. This is the equivalent to the Java's <code>--</code> postfix function.
+	 * 
+	 * @param s  a short.
+	 * @return   <code>s--</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1--")
+	public static Short operator_minusMinus(Short s) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param s  a short.
+	 * @return   <code>s++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static short operator_plusPlus(short s) {
+		throw new HardcodedInInterpreterException();
+	}
+	
+	/**
+	 * The postfix <code>increment</code> operator. This is the equivalent to the Java's <code>++</code> postfix function.
+	 * 
+	 * @param s  a short.
+	 * @return   <code>s++</code>
+	 * @since 2.6
+	 */
+	@Inline(value="$1++")
+	public static Short operator_plusPlus(Short s) {
+		throw new HardcodedInInterpreterException();
+	}
+	/**
+	 * The binary <code>plus</code> operator. This is the equivalent to the Java <code>+</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a double.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static double operator_plus(short 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 short.
+	 * @param b  a double.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static double operator_minus(short 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 short.
+	 * @param b  a double.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static double operator_multiply(short 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 short.
+	 * @param b  a double.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static double operator_divide(short 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 short.
+	 * @param b  a double.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static double operator_modulo(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a double.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(short 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 short.
+	 * @param b  a double.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a double.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(short 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 short.
+	 * @param b  a double.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static float operator_plus(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static float operator_minus(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static float operator_multiply(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static float operator_divide(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static float operator_modulo(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(short 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 short.
+	 * @param b  a float.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static long operator_plus(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static long operator_minus(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static long operator_multiply(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static long operator_divide(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static long operator_modulo(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(short 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 short.
+	 * @param b  a long.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(short 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 short.
+	 * @param b  an integer.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(short 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 short.
+	 * @param b  a character.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(short 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 short.
+	 * @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(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(short 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 short.
+	 * @param b  a short.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(short 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 short.
+	 * @param b  a byte.
+	 * @return   <code>a+b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static int operator_plus(short a, byte b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>minus</code> operator. This is the equivalent to the Java <code>-</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a-b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 - $2)", constantExpression=true)
+	public static int operator_minus(short a, byte b) {
+		return a - b;
+	}
+	
+	/**
+	 * The binary <code>multiply</code> operator. This is the equivalent to the Java <code>*</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a*b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 * $2)", constantExpression=true)
+	public static int operator_multiply(short a, byte b) {
+		return a * b;
+	}
+	
+	/**
+	 * The binary <code>divide</code> operator. This is the equivalent to the Java <code>/</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a/b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 / $2)", constantExpression=true)
+	public static int operator_divide(short a, byte b) {
+		return a / b;
+	}
+	
+	/**
+	 * The binary <code>modulo</code> operator. This is the equivalent to the Java <code>%</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a%b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 % $2)", constantExpression=true)
+	public static int operator_modulo(short a, byte b) {
+		return a % b;
+	}
+	
+	/**
+	 * The binary <code>lessThan</code> operator. This is the equivalent to the Java <code>&lt;</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 < $2)", constantExpression=true)
+	public static boolean operator_lessThan(short a, byte b) {
+		return a < b;
+	}
+	
+	/**
+	 * The binary <code>lessEqualsThan</code> operator. This is the equivalent to the Java <code>&lt;=</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a&lt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 <= $2)", constantExpression=true)
+	public static boolean operator_lessEqualsThan(short a, byte b) {
+		return a <= b;
+	}
+	
+	/**
+	 * The binary <code>greaterThan</code> operator. This is the equivalent to the Java <code>&gt;</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 > $2)", constantExpression=true)
+	public static boolean operator_greaterThan(short a, byte b) {
+		return a > b;
+	}
+	
+	/**
+	 * The binary <code>greaterEqualsThan</code> operator. This is the equivalent to the Java <code>&gt;=</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a&gt;=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 >= $2)", constantExpression=true)
+	public static boolean operator_greaterEqualsThan(short a, byte b) {
+		return a >= b;
+	}
+	
+	/**
+	 * The binary <code>equals</code> operator. This is the equivalent to the Java <code>==</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a==b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_equals(short a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The binary <code>notEquals</code> operator. This is the equivalent to the Java <code>!=</code> operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a!=b</code>
+	 * @since 2.3
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_notEquals(short a, byte 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 short.
+	 * @param b  a byte.
+	 * @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(short a, byte 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 short.
+	 * @param b  a byte.
+	 * @return   <code>a == b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 == $2)", constantExpression=true)
+	public static boolean operator_tripleEquals(short a, byte b) {
+		return a == b;
+	}
+	
+	/**
+	 * The <code>identity not equals</code> operator. This is the equivalent to Java's <code>!=</code>
+	 * operator.
+	 * 
+	 * @param a  a short.
+	 * @param b  a byte.
+	 * @return   <code>a != b</code>
+	 * @since 2.4
+	 */
+	@Pure
+	@Inline(value="($1 != $2)", constantExpression=true)
+	public static boolean operator_tripleNotEquals(short a, byte b) {
+		return a != b;
+	}
+	
+	// END generated code
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/StringExtensions.java b/java/org/eclipse/xtext/xbase/lib/StringExtensions.java
new file mode 100644
index 0000000..3a917a7
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/StringExtensions.java
@@ -0,0 +1,105 @@
+/*******************************************************************************
+ * 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;
+
+
+/**
+ * This is an extension library for {@link String strings}.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ */
+@GwtCompatible public class StringExtensions {
+
+	/**
+	 * The binary <code>+</code> operator that concatenates a string and the string
+	 * reprentation of an object.
+	 * 
+	 * @param a
+	 *            a string.
+	 * @param b
+	 *            an object.
+	 * @return <code>a + b</code>
+	 */
+	@Pure /* not guaranteed, since toString() is invoked */
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static String operator_plus(String a, Object b) {
+		return a + b;
+	}
+	
+	/**
+	 * The binary <code>+</code> operator that concatenates two strings.
+	 * 
+	 * @param a
+	 *            a string.
+	 * @param b
+	 *            another string.
+	 * @return <code>a + b</code>
+	 * 
+	 * @since 2.5
+	 */
+	@Pure /* not guaranteed, since toString() is invoked */
+	@Inline(value="($1 + $2)", constantExpression=true)
+	public static String operator_plus(String a, String b) {
+		return a + b;
+	}
+
+	/**
+	 * Returns <code>true</code> if {@code s} is <code>null</code> or equal to the empty {@link String} <code>""</code>.
+	 * 
+	 * @param s
+	 *            the string
+	 * @return <code>true</code> if {@code s} is <code>null</code> or equal to the empty {@link String} <code>""</code>
+	 */
+	@Pure
+	public static boolean isNullOrEmpty(String s) {
+		return s == null || s.length() == 0;
+	}
+
+	/**
+	 * Returns the {@link String} {@code s} with an {@link Character#isUpperCase(char) upper case} first character. This
+	 * function is null-safe.
+	 * 
+	 * @param s
+	 *            the string that should get an upper case first character. May be <code>null</code>.
+	 * @return the {@link String} {@code s} with an upper case first character or <code>null</code> if the input
+	 *         {@link String} {@code s} was <code>null</code>.
+	 */
+	@Pure
+	public static String toFirstUpper(String s) {
+		if (s == null || s.length() == 0)
+			return s;
+		if (Character.isUpperCase(s.charAt(0)))
+			return s;
+		if (s.length() == 1)
+			return s.toUpperCase();
+		return s.substring(0, 1).toUpperCase() + s.substring(1);
+	}
+
+	/**
+	 * Returns the {@link String} {@code s} with an {@link Character#isLowerCase(char) lower case} first character. This
+	 * function is null-safe.
+	 * 
+	 * @param s
+	 *            the string that should get an lower case first character. May be <code>null</code>.
+	 * @return the {@link String} {@code s} with an lower case first character or <code>null</code> if the input
+	 *         {@link String} {@code s} was <code>null</code>.
+	 */
+	@Pure
+	public static String toFirstLower(String s) {
+		if (s == null || s.length() == 0)
+			return s;
+		if (Character.isLowerCase(s.charAt(0)))
+			return s;
+		if (s.length() == 1)
+			return s.toLowerCase();
+		return s.substring(0, 1).toLowerCase() + s.substring(1);
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/internal/BooleanFunctionDelegate.java b/java/org/eclipse/xtext/xbase/lib/internal/BooleanFunctionDelegate.java
new file mode 100644
index 0000000..630b72d
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/internal/BooleanFunctionDelegate.java
@@ -0,0 +1,46 @@
+/*******************************************************************************
+ * 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.internal;
+
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Predicate;
+
+/**
+ * Internal wrapper to look like a google.collect predicate
+ * 
+ * @param <T>
+ *            the type of the objects that can be used by this predicate.
+ */
+@GwtCompatible public class BooleanFunctionDelegate<T> implements Predicate<T> {
+
+	private final Function1<? super T, Boolean> delegate;
+
+	/**
+	 * Creates a new {@link BooleanFunctionDelegate} that wraps the given delegate function. This implementation will
+	 * throw a {@link NullPointerException} if the delegate's {@link Function1#apply(Object) implementation} returns
+	 * <code>null</code> for a given object.
+	 * 
+	 * @param delegate
+	 *            the delegate function. May not be <code>null</code>.
+	 */
+	public BooleanFunctionDelegate(Function1<? super T, Boolean> delegate) {
+		if (delegate == null)
+			throw new NullPointerException("delegate");
+		this.delegate = delegate;
+	}
+
+	@Override
+	public boolean apply(T input) {
+		Boolean result = delegate.apply(input);
+		return result.booleanValue();
+	}
+
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtext/xbase/lib/internal/FunctionDelegate.java b/java/org/eclipse/xtext/xbase/lib/internal/FunctionDelegate.java
new file mode 100644
index 0000000..9b6d4e1
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/internal/FunctionDelegate.java
@@ -0,0 +1,47 @@
+/*******************************************************************************
+ * 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.internal;
+
+import org.eclipse.xtext.xbase.lib.Functions;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Function;
+
+/**
+ * Internal wrapper to look like a google.collect function
+ * 
+ * @param <P>
+ *            the type of the arguments that can be passed to this function.
+ * @param <R>
+ *            the type of the result instances of this function.
+ * @author Sebastian Zarnekow - Initial contribution and API
+ */
+@GwtCompatible public class FunctionDelegate<P, R> implements Function<P, R> {
+
+	private final Functions.Function1<? super P, ? extends R> delegate;
+
+	/**
+	 * Creates a new {@link FunctionDelegate} that wraps the given delegate function.
+	 * 
+	 * @param delegate
+	 *            the delegate function. May not be <code>null</code>.
+	 */
+	public FunctionDelegate(Functions.Function1<? super P, ? extends R> delegate) {
+		if (delegate == null)
+			throw new NullPointerException("delegate");
+		this.delegate = delegate;
+	}
+
+	@Override
+	public R apply(P input) {
+		R result = delegate.apply(input);
+		return result;
+	}
+
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtext/xbase/lib/internal/KeyComparator.java b/java/org/eclipse/xtext/xbase/lib/internal/KeyComparator.java
new file mode 100644
index 0000000..8a0993e
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/internal/KeyComparator.java
@@ -0,0 +1,52 @@
+/*******************************************************************************
+ * 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.xtext.xbase.lib.internal;
+
+import static com.google.common.base.Preconditions.*;
+
+import java.util.Comparator;
+
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+
+import com.google.common.annotations.GwtCompatible;
+
+/**
+ * A comparator that compares objects by calling the supplied key function on them and then comparing the resulting
+ * keys. It is null-safe if the key's compareTo method is null-safe.
+ * 
+ * @param <T>
+ *            the type to compare
+ * @param <C>
+ *            the type of the comparable key
+ */
+@GwtCompatible
+public final class KeyComparator<T, C extends Comparable<? super C>> implements Comparator<T> {
+	private final Function1<? super T, C> keyFunction;
+
+	/**
+	 * @param keyFunction
+	 *            the key function to use for comparing objects. May not be <code>null</code>
+	 */
+	public KeyComparator(Function1<? super T, C> keyFunction) {
+		this.keyFunction = checkNotNull(keyFunction, "keyFunction");
+	}
+
+	@Override
+	public int compare(T a, T b) {
+		C c1 = keyFunction.apply(a);
+		C c2 = keyFunction.apply(b);
+		if (c1 == c2) {
+			return 0;
+		} else if (c1 != null) {
+			return c1.compareTo(c2);
+		} else {
+			return -c2.compareTo(c1);
+		}
+	}
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtext/xbase/lib/internal/ToStringHelper.java b/java/org/eclipse/xtext/xbase/lib/internal/ToStringHelper.java
new file mode 100644
index 0000000..99f84cf
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/internal/ToStringHelper.java
@@ -0,0 +1,18 @@
+/*******************************************************************************
+ * 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.internal;
+
+
+/**
+ * @author Sven Efftinge - Initial contribution and API
+ */
+@Deprecated
+public class ToStringHelper extends org.eclipse.xtext.xbase.lib.util.ToStringHelper {
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/internal/UnmodifiableMergingMapView.java b/java/org/eclipse/xtext/xbase/lib/internal/UnmodifiableMergingMapView.java
new file mode 100644
index 0000000..5ae872d
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/internal/UnmodifiableMergingMapView.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Universite de Technologie de Belfort-Montbeliard (http://www.utbm.fr) 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.internal;
+
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.function.BiFunction;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterators;
+
+/**
+ * Map implementation that is merging two maps.
+ *
+ * <p>If a key exists within the two merged maps, then the retained value is the one of the right map.
+ *
+ * @author Stephane Galland - Initial contribution and API
+ * @since 2.15
+ * @param <K> the type of the keys.
+ * @param <V> the type of the values in the maps.
+ */
+@GwtCompatible
+public class UnmodifiableMergingMapView<K, V> extends AbstractMap<K, V> {
+
+	private final Map<? extends K, ? extends V> left;
+
+	private final Map<? extends K, ? extends V> right;
+
+	/** Construct the wrapping map.
+	 *
+	 * @param left the left operand to merge.
+	 * @param right the right operand to merge.
+	 */
+	public UnmodifiableMergingMapView(Map<? extends K, ? extends V> left, Map<? extends K, ? extends V> right) {
+		assert left != null : "left must not be null"; //$NON-NLS-1$
+		assert right != null : "right must not be null"; //$NON-NLS-1$
+		this.left = left;
+		this.right = right;
+	}
+
+	@Override
+	public Set<Entry<K, V>> entrySet() {
+		// A call to "Sets.union(ks1, ks2)" does not work because of the equals() definition on Map.Entry.
+		// This equality test breaks the unicity of the keys over the resulting Set.
+		// In other words, "Sets.union(ks1, ks2)" replies all the entries that
+		// are different on their keys or values.
+
+		final Set<Entry<K, V>> diff =  difference(this.left, this.right);
+		return new AbstractEarlyFailingSet<Entry<K, V>>() {
+			@SuppressWarnings({ "unchecked", "rawtypes", "synthetic-access" })
+			@Override
+			public Iterator<Entry<K, V>> iterator() {
+				return Iterators.unmodifiableIterator((Iterator) Iterators.concat(
+						UnmodifiableMergingMapView.this.right.entrySet().iterator(), diff.iterator()));
+			}
+
+			@Override
+			public int size() {
+				return Iterators.size(iterator());
+			}
+		};
+	}
+
+	private static <K, V> Set<Entry<K, V>> difference(final Map<? extends K, ? extends V> left, final Map<? extends K, ? extends V> right) {
+		final Predicate<Entry<? extends K, ? extends V>> notInSet = new Predicate<Map.Entry<? extends K, ? extends V>>() {
+			@Override
+			public boolean apply(Entry<? extends K, ? extends V> it) {
+				if (it == null) {
+					return false;
+				}
+				return !right.containsKey(it.getKey());
+			}
+		};
+
+		return new AbstractEarlyFailingSet<Entry<K, V>>() {
+			@SuppressWarnings({ "unchecked", "rawtypes" })
+			@Override
+			public Iterator<Entry<K, V>> iterator() {
+				return Iterators.unmodifiableIterator((Iterator) Iterators.filter(left.entrySet().iterator(), notInSet));
+			}
+
+			@Override
+			public int size() {
+				return Iterators.size(iterator());
+			}
+		};
+	}
+
+	@Override
+	public void clear() {
+		// Fail even if the set is empty.
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public V put(K key, V value) {
+		// Fail even if the set is empty.
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public V remove(Object key) {
+		// Fail even if the set is empty.
+		throw new UnsupportedOperationException();
+	}
+
+	@Override
+	public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
+		// Fail even if the set is empty.
+		throw new UnsupportedOperationException();
+	}
+
+	/**
+	 * Abstract implements of a set that is failing as soon as possible
+	 * when modifiers are called.
+	 *
+	 * @param <T> the type of the set elements.
+	 * @author $Author: sgalland$
+	 * @version $FullVersion$
+	 * @mavengroupid $GroupId$
+	 * @mavenartifactid $ArtifactId$
+	 */
+	@GwtCompatible
+	private abstract static class AbstractEarlyFailingSet<T> extends AbstractSet<T> {
+
+		AbstractEarlyFailingSet() {
+			//
+		}
+
+		@Override
+		public void clear() {
+			// Fail even if the set is empty.
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public boolean add(T entry) {
+			// Fail even if the set is empty.
+			throw new UnsupportedOperationException();
+		}
+
+		@Override
+		public boolean remove(Object element) {
+			// Fail even if the set is empty.
+			throw new UnsupportedOperationException();
+		}
+
+	}
+
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/util/ReflectExtensions.java b/java/org/eclipse/xtext/xbase/lib/util/ReflectExtensions.java
new file mode 100644
index 0000000..1b12ba3
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/util/ReflectExtensions.java
@@ -0,0 +1,165 @@
+/*******************************************************************************
+ * 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.util;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Preconditions;
+
+/**
+ * Extension methods to simplify reflective invocation of methods and fields.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * @since 2.3
+ */
+@Beta
+public class ReflectExtensions {
+
+	/**
+	 * Sets the given value on an the receivers's accessible field with the given name.
+	 * 
+	 * @param receiver the receiver, never <code>null</code>
+	 * @param fieldName the field's name, never <code>null</code>
+	 * @param value the value to set
+	 * 
+	 * @throws NoSuchFieldException see {@link Class#getField(String)}
+	 * @throws SecurityException see {@link Class#getField(String)}
+	 * @throws IllegalAccessException see {@link Field#set(Object, Object)}
+	 * @throws IllegalArgumentException see {@link Field#set(Object, Object)}
+	 */
+	public void set(Object receiver, String fieldName, /* @Nullable */ Object value) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
+		Preconditions.checkNotNull(receiver,"receiver");
+		Preconditions.checkNotNull(fieldName,"fieldName");
+		Class<? extends Object> clazz = receiver.getClass();
+		Field f = getDeclaredField(clazz, fieldName);
+		if (!f.isAccessible())
+			f.setAccessible(true);
+		f.set(receiver, value);
+	}
+	
+	/**
+	 * Retrieves the value of the given accessible field of the given receiver.
+	 * 
+	 * @param receiver the container of the field, not <code>null</code>
+	 * @param fieldName the field's name, not <code>null</code>
+	 * @return the value of the field
+	 * 
+	 * @throws NoSuchFieldException see {@link Class#getField(String)}
+	 * @throws SecurityException see {@link Class#getField(String)}
+	 * @throws IllegalAccessException see {@link Field#get(Object)}
+	 * @throws IllegalArgumentException see {@link Field#get(Object)}
+	 */
+	@SuppressWarnings("unchecked")
+	/* @Nullable */
+	public <T> T get(Object receiver, String fieldName) throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
+		Preconditions.checkNotNull(receiver,"receiver");
+		Preconditions.checkNotNull(fieldName,"fieldName");
+		
+		Class<? extends Object> clazz = receiver.getClass();
+		Field f = getDeclaredField(clazz, fieldName);
+		if (!f.isAccessible())
+			f.setAccessible(true);
+		return (T) f.get(receiver);
+	}
+	
+	private Field getDeclaredField(Class<?> clazz, String name) throws NoSuchFieldException {
+		NoSuchFieldException initialException = null;
+		do {
+			try {
+				Field f = clazz.getDeclaredField(name);
+				return f;
+			} catch(NoSuchFieldException noSuchField) {
+				if (initialException == null) {
+					initialException = noSuchField;
+				}
+			}
+		} while((clazz = clazz.getSuperclass()) != null);
+		throw initialException;
+	}
+	
+	/**
+	 * Invokes the first accessible method defined on the receiver'c class with the given name and
+	 * a parameter list compatible to the given arguments.
+	 * 
+	 * @param receiver the method call receiver, not <code>null</code>
+	 * @param methodName the method name, not <code>null</code>
+	 * @param args the arguments for the method invocation
+	 * @return the result of the method invocation. <code>null</code> if the method was of type void.
+	 * 
+	 * @throws SecurityException see {@link Class#getMethod(String, Class...)}
+	 * @throws NoSuchMethodException see {@link Class#getMethod(String, Class...)}
+	 * @throws IllegalAccessException see {@link Method#invoke(Object, Object...)}
+	 * @throws IllegalArgumentException see {@link Method#invoke(Object, Object...)}
+	 * @throws InvocationTargetException see {@link Method#invoke(Object, Object...)}
+	 */
+	/* @Nullable */
+	public Object invoke(Object receiver, String methodName, /* @Nullable */ Object...args) throws SecurityException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
+		Preconditions.checkNotNull(receiver,"receiver");
+		Preconditions.checkNotNull(methodName,"methodName");
+		final Object[] arguments = args==null ? new Object[]{null}:args;
+		
+		Class<? extends Object> clazz = receiver.getClass();
+		Method compatible = null;
+		do {
+			for (Method candidate : clazz.getDeclaredMethods()) {
+				if (candidate != null && !candidate.isBridge() && isCompatible(candidate, methodName, arguments)) {
+					if (compatible != null) 
+						throw new IllegalStateException("Ambiguous methods to invoke. Both "+compatible+" and  "+candidate+" would be compatible choices.");
+					compatible = candidate;
+				}
+			}
+		} while(compatible == null && (clazz = clazz.getSuperclass()) != null);
+		if (compatible != null) {
+			if (!compatible.isAccessible())
+				compatible.setAccessible(true);
+			return compatible.invoke(receiver, arguments);
+		}
+		// not found provoke method not found exception
+		Class<?>[] paramTypes = new Class<?>[arguments.length];
+		for (int i = 0; i< arguments.length ; i++) {
+			paramTypes[i] = arguments[i] == null ? Object.class : arguments[i].getClass();
+		}
+		Method method = receiver.getClass().getMethod(methodName, paramTypes);
+		return method.invoke(receiver, arguments);
+	}
+	
+	private boolean isCompatible(Method candidate, String featureName, Object... args) {
+		if (!candidate.getName().equals(featureName))
+			return false;
+		if (candidate.getParameterTypes().length != args.length)
+			return false;
+		for (int i = 0; i< candidate.getParameterTypes().length; i++) {
+			Object param = args[i];
+			Class<?> class1 = candidate.getParameterTypes()[i];
+			if (class1.isPrimitive())
+				class1 = wrapperTypeFor(class1);
+			if (param != null && !class1.isInstance(param))
+				return false;
+		}
+		return true;
+	}
+	
+	private Class<?> wrapperTypeFor(Class<?> primitive) {
+		Preconditions.checkNotNull(primitive);
+        if (primitive == Boolean.TYPE) return Boolean.class;
+        if (primitive == Byte.TYPE) return Byte.class;
+        if (primitive == Character.TYPE) return Character.class;
+        if (primitive == Short.TYPE) return Short.class;
+        if (primitive == Integer.TYPE) return Integer.class;
+        if (primitive == Long.TYPE) return Long.class;
+        if (primitive == Float.TYPE) return Float.class;
+        if (primitive == Double.TYPE) return Double.class;
+        if (primitive == Void.TYPE) return Void.class;
+        throw new IllegalArgumentException(primitive+ " is not a primitive");
+    }
+	
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/util/ToStringBuilder.java b/java/org/eclipse/xtext/xbase/lib/util/ToStringBuilder.java
new file mode 100644
index 0000000..8871d92
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/util/ToStringBuilder.java
@@ -0,0 +1,367 @@
+/**
+ * Copyright (c) 2014, 2018 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.util;
+
+import com.google.common.annotations.Beta;
+import com.google.common.annotations.GwtCompatible;
+import com.google.common.annotations.GwtIncompatible;
+import com.google.common.base.Objects;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.function.Consumer;
+import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.Conversions;
+import org.eclipse.xtext.xbase.lib.Exceptions;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.util.ToStringContext;
+
+/**
+ * Helps with the construction of good {@link Object#toString()} representations.
+ * <p>You can customize the output using the builder-style methods {@link ToStringBuilder#singleLine()} {@link ToStringBuilder#skipNulls()} and {@link ToStringBuilder#hideFieldNames()}.</p>
+ * <p>You can either directly list fields to include via {@link ToStringBuilder#add(String, Object)} and {@link ToStringBuilder#add(Object)}
+ * or you can let the builder do it automatically using reflection, either including the fields declared in this class or including all superclasses.</p>
+ * <p>The builder will automatically handle cycles in the object tree. It also pretty prints arrays and Iterables.</p>
+ *
+ * This class is not thread safe.
+ * @since 2.7
+ */
+@Beta
+@GwtCompatible
+@SuppressWarnings("all")
+public final class ToStringBuilder {
+	
+	private static ToStringContext toStringContext = ToStringContext.INSTANCE;
+	
+	private final Object instance;
+
+	private final String typeName;
+
+	private boolean multiLine = true;
+
+	private boolean skipNulls = false;
+
+	private boolean showFieldNames = true;
+
+	private boolean prettyPrint = true;
+
+	private final List<Part> parts = new ArrayList<Part>();
+
+	/**
+	 * Creates a new ToStringBuilder for the given object. If you don't use reflection, then this instance
+	 * is only used for obtaining its classes' simple name.
+	 *
+	 * @param instance the object to convert to a String
+	 */
+	public ToStringBuilder(final Object instance) {
+		this.instance = instance;
+		this.typeName = instance.getClass().getSimpleName();
+	}
+
+	/**
+	 * Fields are printed on a single line, separated by commas instead of newlines
+	 * @return this
+	 */
+	public ToStringBuilder singleLine() {
+		this.multiLine = false;
+		return this;
+	}
+
+	/**
+	 * Fields with null values will be excluded from the output
+	 * @return this
+	 */
+	public ToStringBuilder skipNulls() {
+		this.skipNulls = true;
+		return this;
+	}
+
+	/**
+	 * Field names will not be included in the output. Useful for small classes.
+	 * @return this
+	 */
+	public ToStringBuilder hideFieldNames() {
+		this.showFieldNames = false;
+		return this;
+	}
+
+	/**
+	 * By default, Iterables, Arrays and multiline Strings are pretty-printed.
+	 * Switching to their normal representation makes the toString method significantly faster.
+	 * @since 2.9
+	 * @return this
+	 */
+	public ToStringBuilder verbatimValues() {
+		this.prettyPrint = false;
+		return this;
+	}
+
+	/**
+	 * Adds all fields declared directly in the object's class to the output
+	 * @return this
+	 */
+	@GwtIncompatible("Class.getDeclaredFields")
+	public ToStringBuilder addDeclaredFields() {
+		Field[] fields = instance.getClass().getDeclaredFields();
+		for(Field field : fields) {
+			addField(field);
+		}
+		return this;
+	}
+
+	/**
+	 * Adds all fields declared in the object's class and its superclasses to the output.
+	 * @return this
+	 */
+	@GwtIncompatible("Class.getDeclaredFields")
+	public ToStringBuilder addAllFields() {
+		List<Field> fields = getAllDeclaredFields(instance.getClass());
+		for(Field field : fields) {
+			addField(field);
+		}
+		return this;
+	}
+
+	/**
+	 * @param fieldName the name of the field to add to the output using reflection
+	 * @return this
+	 */
+	@GwtIncompatible("Class.getDeclaredField(String)")
+	public ToStringBuilder addField(final String fieldName) {
+		List<Field> fields = getAllDeclaredFields(instance.getClass());
+		for(Field field : fields) {
+			if(fieldName.equals(field.getName())) {
+				addField(field);
+				break;
+			}
+		}
+		return this;
+	}
+
+	@GwtIncompatible("java.lang.reflect.Field")
+	private ToStringBuilder addField(final Field field) {
+		if (!Modifier.isStatic(field.getModifiers())) {
+			field.setAccessible(true);
+			try {
+				add(field.getName(), field.get(instance));
+			} catch(IllegalAccessException e) {
+				throw Exceptions.sneakyThrow(e);
+			}
+		}
+		return this;
+	}
+
+	/**
+	 * @param value the value to add to the output
+	 * @param fieldName the field name to list the value under
+	 * @return this
+	 */
+	public ToStringBuilder add(final String fieldName, final Object value) {
+		return addPart(fieldName, value);
+	}
+
+	/**
+	 * @param value the value to add to the output without a field name
+	 * @return this
+	 */
+	public ToStringBuilder add(final Object value) {
+		return addPart(value);
+	}
+
+	private Part addPart() {
+		final Part p = new Part();
+		this.parts.add(p);
+		return p;
+	}
+
+	private ToStringBuilder addPart(final Object value) {
+		final Part p = this.addPart();
+		p.value = value;
+		return this;
+	}
+
+	private ToStringBuilder addPart(final String fieldName, final Object value) {
+		final Part p = this.addPart();
+		p.fieldName = fieldName;
+		p.value = value;
+		return this;
+	}
+
+	/**
+	 * @return the String representation of the processed object
+	 */
+	@Override
+	public String toString() {
+		boolean startProcessing = ToStringBuilder.toStringContext.startProcessing(this.instance);
+		if (!startProcessing) {
+			return this.toSimpleReferenceString(this.instance);
+		}
+		try {
+			final IndentationAwareStringBuilder builder = new IndentationAwareStringBuilder();
+			builder.append(typeName).append(" ");
+			builder.append("[");
+			String nextSeparator = "";
+			if (multiLine) {
+				builder.increaseIndent();
+			}
+			for (Part part : parts) {
+				if (!skipNulls || part.value != null) {
+					if (multiLine) {
+						builder.newLine();
+					} else {
+						builder.append(nextSeparator);
+						nextSeparator = ", ";
+					}
+					if (part.fieldName != null && this.showFieldNames) {
+						builder.append(part.fieldName).append(" = ");
+					}
+					this.internalToString(part.value, builder);
+				}
+			}
+			if (multiLine) {
+				builder.decreaseIndent().newLine();
+			}
+			builder.append("]");
+			return builder.toString();
+		} finally {
+			ToStringBuilder.toStringContext.endProcessing(this.instance);
+		}
+	}
+
+	private void internalToString(final Object object, final IndentationAwareStringBuilder sb) {
+		if (prettyPrint) {
+			if (object instanceof Iterable<?>) {
+				serializeIterable((Iterable<?>)object, sb);
+			} else if (object instanceof Object[]) {
+				sb.append(Arrays.toString((Object[])object));
+			} else if (object instanceof byte[]) {
+				sb.append(Arrays.toString((byte[])object));
+			} else if (object instanceof char[]) {
+				sb.append(Arrays.toString((char[])object));
+			} else if (object instanceof int[]) {
+				sb.append(Arrays.toString((int[])object));
+			} else if (object instanceof boolean[]) {
+				sb.append(Arrays.toString((boolean[])object));
+			} else if (object instanceof long[]) {
+				sb.append(Arrays.toString((long[])object));
+			} else if (object instanceof float[]) {
+				sb.append(Arrays.toString((float[])object));
+			} else if (object instanceof double[]) {
+				sb.append(Arrays.toString((double[])object));
+			} else if (object instanceof CharSequence) {
+				sb.append("\"").append(((CharSequence)object).toString().replace("\n", "\\n").replace("\r", "\\r")).append("\"");
+			} else if (object instanceof Enum<?>) {
+				sb.append(((Enum<?>)object).name());
+			} else {
+				sb.append(String.valueOf(object));
+			}
+		} else {
+			sb.append(String.valueOf(object));
+		}
+	}
+
+	private void serializeIterable(final Iterable<?> object, final IndentationAwareStringBuilder sb) {
+		final Iterator<?> iterator = object.iterator();
+		sb.append(object.getClass().getSimpleName()).append(" (");
+		if (multiLine) {
+			sb.increaseIndent();
+		}
+		boolean wasEmpty = true;
+		while (iterator.hasNext()) {
+			wasEmpty = false;
+			if (multiLine) {
+				sb.newLine();
+			}
+			this.internalToString(iterator.next(), sb);
+			if (iterator.hasNext()) {
+				sb.append(",");
+			}
+		}
+		if (multiLine) {
+			sb.decreaseIndent();
+		}
+		if (!wasEmpty && this.multiLine) {
+			sb.newLine();
+		}
+		sb.append(")");
+	}
+
+	private String toSimpleReferenceString(final Object obj) {
+		String simpleName = obj.getClass().getSimpleName();
+		int identityHashCode = System.identityHashCode(obj);
+		return simpleName + "@" + Integer.valueOf(identityHashCode);
+	}
+
+	@GwtIncompatible("java.lang.reflect.Field")
+	private List<Field> getAllDeclaredFields(final Class<?> clazz) {
+		final ArrayList<Field> result = new ArrayList();
+
+		for(Class<?> current = clazz; current != null; current = current.getSuperclass()) {
+			Field[] declaredFields = current.getDeclaredFields();
+			result.addAll(Arrays.asList(declaredFields));
+			
+		}
+		return result;
+	}
+
+	private static final class Part {
+		private String fieldName;
+		private Object value;
+	}
+
+	private static class IndentationAwareStringBuilder {
+		private final StringBuilder builder = new StringBuilder();
+
+		private final String indentationString = "  ";
+
+		private final String newLineString = "\n";
+
+		private int indentation = 0;
+
+		public IndentationAwareStringBuilder increaseIndent() {
+			indentation++;
+			return this;
+		}
+
+		public IndentationAwareStringBuilder decreaseIndent() {
+			indentation--;
+			return this;
+		}
+
+		public IndentationAwareStringBuilder append(final CharSequence string) {
+			if (indentation > 0) {
+				String indented = string.toString().replace(
+					newLineString,
+					newLineString + Strings.repeat(indentationString, indentation)
+				);
+				builder.append(indented);
+			} else {
+				builder.append(string);
+			}
+			return this;
+		}
+
+		public IndentationAwareStringBuilder newLine() {
+			builder.append(newLineString).
+			append(Strings.repeat(this.indentationString, this.indentation));
+			return this;
+		}
+
+		@Override
+		public String toString() {
+			return this.builder.toString();
+		}
+	}
+}
diff --git a/java/org/eclipse/xtext/xbase/lib/util/ToStringContext.java b/java/org/eclipse/xtext/xbase/lib/util/ToStringContext.java
new file mode 100644
index 0000000..44af7c9
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/util/ToStringContext.java
@@ -0,0 +1,37 @@
+/**
+ * Copyright (c) 2014, 2018 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.util;
+
+import com.google.common.annotations.GwtCompatible;
+import java.util.IdentityHashMap;
+
+/**
+ * On GWT we just use a static variable instead of a ThreadLocal
+ */
+@GwtCompatible(emulated = true)
+@SuppressWarnings("all")
+class ToStringContext {
+
+	public final static ToStringContext INSTANCE = new ToStringContext();
+
+	private final static ThreadLocal<IdentityHashMap<Object, Boolean>> currentlyProcessed = new ThreadLocal<IdentityHashMap<Object, Boolean>>() {
+		@Override
+		public IdentityHashMap<Object, Boolean> initialValue() {
+			return new IdentityHashMap<Object, Boolean>();
+		}
+	};
+
+	public boolean startProcessing(final Object obj) {
+		return ToStringContext.currentlyProcessed.get().put(obj, Boolean.TRUE) == null;
+	}
+
+	public void endProcessing(final Object obj) {
+		ToStringContext.currentlyProcessed.get().remove(obj);
+	}
+}
\ No newline at end of file
diff --git a/java/org/eclipse/xtext/xbase/lib/util/ToStringHelper.java b/java/org/eclipse/xtext/xbase/lib/util/ToStringHelper.java
new file mode 100644
index 0000000..2113d33
--- /dev/null
+++ b/java/org/eclipse/xtext/xbase/lib/util/ToStringHelper.java
@@ -0,0 +1,45 @@
+/*******************************************************************************
+ * 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.util;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * A helper class to assist construction of proper {@link Object#toString()} implementation for value objects.
+ * 
+ * @author Sven Efftinge - Initial contribution and API
+ * 
+ * @since 2.3
+ * @deprecated use {@link ToStringBuilder}
+ */
+@Beta
+@Deprecated
+public class ToStringHelper {
+
+	/**
+	 * @deprecated use {@link ToStringBuilder}
+	 */
+	@Deprecated
+	public ToStringHelper() {
+	}
+
+	/**
+	 * Creates a string representation of the given object by listing the internal state of all fields.
+	 * 
+	 * @param obj
+	 *            the object that should be printed.
+	 * @return the string representation. Never <code>null</code>.
+	 * @deprecated use <code>new ToStringBuilder().addAllFields().toString()</code>
+	 */
+	@Deprecated
+	public String toString(Object obj) {
+		return new ToStringBuilder(obj).addAllFields().toString();
+	}
+
+}
diff --git a/javatests/org/eclipse/xtend/lib/annotations/DataTest.java b/javatests/org/eclipse/xtend/lib/annotations/DataTest.java
new file mode 100644
index 0000000..e222ca5
--- /dev/null
+++ b/javatests/org/eclipse/xtend/lib/annotations/DataTest.java
@@ -0,0 +1,91 @@
+package org.eclipse.xtend.lib.annotations;
+
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtext.xbase.lib.Pure;
+import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;
+import org.junit.Assert;
+import org.junit.Test;
+
+@SuppressWarnings("all")
+public class DataTest {
+  @Data
+  public static class MyDataClass {
+    private final String arg;
+    
+    private final boolean foo = false;
+    
+    public MyDataClass(final String arg) {
+      super();
+      this.arg = arg;
+    }
+    
+    @Override
+    @Pure
+    public int hashCode() {
+      final int prime = 31;
+      int result = 1;
+      result = prime * result + ((this.arg== null) ? 0 : this.arg.hashCode());
+      return prime * result + (this.foo ? 1231 : 1237);
+    }
+    
+    @Override
+    @Pure
+    public boolean equals(final Object obj) {
+      if (this == obj)
+        return true;
+      if (obj == null)
+        return false;
+      if (getClass() != obj.getClass())
+        return false;
+      DataTest.MyDataClass other = (DataTest.MyDataClass) obj;
+      if (this.arg == null) {
+        if (other.arg != null)
+          return false;
+      } else if (!this.arg.equals(other.arg))
+        return false;
+      if (other.foo != this.foo)
+        return false;
+      return true;
+    }
+    
+    @Override
+    @Pure
+    public String toString() {
+      ToStringBuilder b = new ToStringBuilder(this);
+      b.add("arg", this.arg);
+      b.add("foo", this.foo);
+      return b.toString();
+    }
+    
+    @Pure
+    public String getArg() {
+      return this.arg;
+    }
+    
+    @Pure
+    public boolean isFoo() {
+      return this.foo;
+    }
+  }
+  
+  @Test
+  public void testData() {
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("MyDataClass [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("arg = \"foo\"");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("foo = false");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(DataTest.toUnix(_builder.toString()), new DataTest.MyDataClass("foo").toString());
+  }
+  
+  public static String toUnix(final String s) {
+    StringConcatenation result = new StringConcatenation("\n");
+    result.append(s);
+    return result.toString();
+  }
+}
diff --git a/javatests/org/eclipse/xtend/lib/annotations/DataTest.xtend b/javatests/org/eclipse/xtend/lib/annotations/DataTest.xtend
new file mode 100644
index 0000000..45e7821
--- /dev/null
+++ b/javatests/org/eclipse/xtend/lib/annotations/DataTest.xtend
@@ -0,0 +1,27 @@
+package org.eclipse.xtend.lib.annotations
+
+import org.junit.Test
+import org.junit.Assert
+import org.eclipse.xtend2.lib.StringConcatenation
+
+class DataTest {
+	
+	@Test def void testData() {
+		Assert.assertEquals(toUnix('''
+			MyDataClass [
+			  arg = "foo"
+			  foo = false
+			]'''), new MyDataClass("foo").toString)
+	}
+	
+	@Data static class MyDataClass {
+		String arg
+		boolean foo = false
+	} 
+
+	def static String toUnix(String s) {
+		var StringConcatenation result = new StringConcatenation("\n")
+		result.append(s)
+		return result.toString()
+	}
+}
\ No newline at end of file
diff --git a/javatests/org/eclipse/xtend/lib/test/Test.gwt.xml b/javatests/org/eclipse/xtend/lib/test/Test.gwt.xml
new file mode 100644
index 0000000..7da5f50
--- /dev/null
+++ b/javatests/org/eclipse/xtend/lib/test/Test.gwt.xml
@@ -0,0 +1,8 @@
+<!DOCTYPE module PUBLIC "-//Google Inc.//DTD Google Web Toolkit 2.8.2//EN" "http://www.gwtproject.org/doctype/2.8.2/gwt-module.dtd">
+<module>
+  <inherits name="org.eclipse.xtend.lib.Lib" />
+  <source path="">
+    <include name="TestEntryPoint.java" />
+  </source>
+  <entry-point class="org.eclipse.xtend.lib.test.TestEntryPoint" />
+</module>
\ No newline at end of file
diff --git a/javatests/org/eclipse/xtend/lib/test/TestEntryPoint.java b/javatests/org/eclipse/xtend/lib/test/TestEntryPoint.java
new file mode 100644
index 0000000..a2ec90f
--- /dev/null
+++ b/javatests/org/eclipse/xtend/lib/test/TestEntryPoint.java
@@ -0,0 +1,12 @@
+package org.eclipse.xtend.lib.test;
+
+import org.eclipse.xtend2.lib.StringConcatenation;
+
+import com.google.gwt.core.client.EntryPoint;
+
+public class TestEntryPoint implements EntryPoint {
+  public void onModuleLoad() {
+	  StringConcatenation demo = null;
+	  assert demo == null;
+  }
+}
\ No newline at end of file
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsBooleanTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsBooleanTest.java
new file mode 100644
index 0000000..f20ded3
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsBooleanTest.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsBooleanTest {
+  private boolean[] data;
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private boolean[] createData() {
+    final boolean[] array = new boolean[3];
+    array[0] = true;
+    array[1] = false;
+    array[2] = true;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__boolean() {
+    Assert.assertTrue(this.data[0]);
+    Assert.assertFalse(this.data[1]);
+    Assert.assertTrue(this.data[2]);
+  }
+  
+  @Test
+  public void testClone__boolean() {
+    final boolean[] clonedData = this.data.clone();
+    Assert.assertTrue(clonedData[0]);
+    Assert.assertFalse(clonedData[1]);
+    Assert.assertTrue(clonedData[2]);
+  }
+  
+  @Test
+  public void testLength__boolean() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__boolean() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__boolean() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    boolean[] _createData = this.createData();
+    final Procedure1<boolean[]> _function = (boolean[] it) -> {
+      it[1] = true;
+    };
+    final boolean[] newData = ObjectExtensions.<boolean[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__boolean() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, true));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, false));
+    boolean[] _newBooleanArrayOfSize = new boolean[2];
+    final Procedure1<boolean[]> _function = (boolean[] it) -> {
+      it[0] = false;
+      it[1] = false;
+    };
+    final boolean[] onlyFalse = ObjectExtensions.<boolean[]>operator_doubleArrow(_newBooleanArrayOfSize, _function);
+    Assert.assertFalse(ArrayExtensions.contains(onlyFalse, true));
+    Assert.assertTrue(ArrayExtensions.contains(onlyFalse, false));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsBooleanTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsBooleanTest.xtend
new file mode 100644
index 0000000..60d697a
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsBooleanTest.xtend
@@ -0,0 +1,89 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import java.util.Objects
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsBooleanTest {
+
+	var boolean[] data
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def boolean[] createData() {
+		val boolean[] array = newBooleanArrayOfSize(3)
+		array.set(0, true)
+		array.set(1, false)
+		array.set(2, true)
+		return array
+	}
+
+	@Test
+	def void testSetGet__boolean() {
+		assertTrue(data.get(0))
+		assertFalse(data.get(1))
+		assertTrue(data.get(2))
+	}
+
+	@Test
+	def void testClone__boolean() {
+		val clonedData = data.clone();
+
+		assertTrue(clonedData.get(0))
+		assertFalse(clonedData.get(1))
+		assertTrue(clonedData.get(2))
+	}
+
+	@Test
+	def void testLength__boolean() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__boolean() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__boolean() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, true)]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test
+	def void testContains__boolean() {
+		assertTrue(data.contains(true))
+		assertTrue(data.contains(false))
+		
+		val onlyFalse = newBooleanArrayOfSize(2) => [
+			set(0, false)
+			set(1, false)
+		]
+
+		assertFalse(onlyFalse.contains(true))
+		assertTrue(onlyFalse.contains(false))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsByteTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsByteTest.java
new file mode 100644
index 0000000..db29a56
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsByteTest.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsByteTest {
+  private byte[] data;
+  
+  private final byte _10 = ((byte) 10);
+  
+  private final byte _20 = ((byte) 20);
+  
+  private final byte _30 = ((byte) 30);
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private byte[] createData() {
+    final byte[] array = new byte[3];
+    array[0] = this._10;
+    array[1] = this._20;
+    array[2] = this._30;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__byte() {
+    Assert.assertEquals(this._10, this.data[0]);
+    Assert.assertEquals(this._20, this.data[1]);
+    Assert.assertEquals(this._30, this.data[2]);
+  }
+  
+  @Test
+  public void testClone__byte() {
+    final byte[] clonedData = this.data.clone();
+    Assert.assertEquals(this._10, clonedData[0]);
+    Assert.assertEquals(this._20, clonedData[1]);
+    Assert.assertEquals(this._30, clonedData[2]);
+  }
+  
+  @Test
+  public void testLength__byte() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__byte() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__byte() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    byte[] _createData = this.createData();
+    final Procedure1<byte[]> _function = (byte[] it) -> {
+      it[1] = ((byte) 0);
+    };
+    final byte[] newData = ObjectExtensions.<byte[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__byte() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, ((byte) 10)));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, ((byte) 20)));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, ((byte) 30)));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, ((byte) 40)));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsByteTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsByteTest.xtend
new file mode 100644
index 0000000..456a1f4
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsByteTest.xtend
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+import java.util.Objects
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsByteTest {
+
+	var byte[] data
+
+	val byte _10 = 10 as byte
+	val byte _20 = 20 as byte
+	val byte _30 = 30 as byte
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def byte[] createData() {
+		val byte[] array = newByteArrayOfSize(3)
+		array.set(0, _10)
+		array.set(1, _20)
+		array.set(2, _30)
+		return array
+	}
+
+	@Test
+	def void testSetGet__byte() {
+		assertEquals(_10, data.get(0))
+		assertEquals(_20, data.get(1))
+		assertEquals(_30, data.get(2))
+	}
+
+	@Test
+	def void testClone__byte() {
+		val clonedData = data.clone();
+
+		assertEquals(_10, clonedData.get(0))
+		assertEquals(_20, clonedData.get(1))
+		assertEquals(_30, clonedData.get(2))
+	}
+
+	@Test
+	def void testLength__byte() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__byte() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__byte() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, 0 as byte)]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test 
+	def void testContains__byte() {
+		assertTrue(data.contains(10 as byte))
+		assertTrue(data.contains(20 as byte)) 
+		assertTrue(data.contains(30 as byte))
+		
+		assertFalse(data.contains(40 as byte))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsCharTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsCharTest.java
new file mode 100644
index 0000000..c6b8bda
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsCharTest.java
@@ -0,0 +1,93 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsCharTest {
+  private char[] data;
+  
+  private final char a = 'a';
+  
+  private final char b = 'b';
+  
+  private final char c = 'c';
+  
+  private final char x = 'x';
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private char[] createData() {
+    final char[] array = new char[3];
+    array[0] = this.a;
+    array[1] = this.b;
+    array[2] = this.c;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__char() {
+    Assert.assertEquals(this.a, this.data[0]);
+    Assert.assertEquals(this.b, this.data[1]);
+    Assert.assertEquals(this.c, this.data[2]);
+  }
+  
+  @Test
+  public void testClone__char() {
+    final char[] clonedData = this.data.clone();
+    Assert.assertEquals(this.a, clonedData[0]);
+    Assert.assertEquals(this.b, clonedData[1]);
+    Assert.assertEquals(this.c, clonedData[2]);
+  }
+  
+  @Test
+  public void testLength__char() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__char() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__char() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    char[] _createData = this.createData();
+    final Procedure1<char[]> _function = (char[] it) -> {
+      it[1] = this.a;
+    };
+    final char[] newData = ObjectExtensions.<char[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__char() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, this.a));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, this.b));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, this.c));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, this.x));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsCharTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsCharTest.xtend
new file mode 100644
index 0000000..f66ec1f
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsCharTest.xtend
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+import java.util.Objects
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsCharTest {
+
+	var char[] data
+	
+	val char a = 'a'
+	val char b = 'b'
+	val char c = 'c'
+	
+	val char x = 'x'
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def char[] createData() {
+		val char[] array = newCharArrayOfSize(3)
+		array.set(0, a) 
+		array.set(1, b)
+		array.set(2, c)
+		return array
+	}
+
+	@Test
+	def void testSetGet__char() {
+		assertEquals(a, data.get(0))
+		assertEquals(b, data.get(1))
+		assertEquals(c, data.get(2))
+	}
+
+	@Test
+	def void testClone__char() {
+		val clonedData = data.clone();
+
+		assertEquals(a, clonedData.get(0))
+		assertEquals(b, clonedData.get(1))
+		assertEquals(c, clonedData.get(2))
+	}
+
+	@Test
+	def void testLength__char() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__char() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__char() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, a)]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test 
+	def void testContains__char() {
+		assertTrue(data.contains(a))
+		assertTrue(data.contains(b))
+		assertTrue(data.contains(c))
+		
+		assertFalse(data.contains(x))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsDoubleTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsDoubleTest.java
new file mode 100644
index 0000000..fb6c84f
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsDoubleTest.java
@@ -0,0 +1,117 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsDoubleTest {
+  private double[] data;
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private double[] createData() {
+    final double[] array = new double[3];
+    array[0] = 10.0;
+    array[1] = 20.0;
+    array[2] = 30.0;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__double() {
+    Assert.assertEquals(10.0, this.data[0], 0.001);
+    Assert.assertEquals(20.0, this.data[1], 0.001);
+    Assert.assertEquals(30.0, this.data[2], 0.001);
+  }
+  
+  @Test
+  public void testClone__double() {
+    final double[] clonedData = this.data.clone();
+    Assert.assertEquals(10.0, clonedData[0], 0.001);
+    Assert.assertEquals(20.0, clonedData[1], 0.001);
+    Assert.assertEquals(30.0, clonedData[2], 0.001);
+  }
+  
+  @Test
+  public void testLength__double() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__double() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__double() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    double[] _createData = this.createData();
+    final Procedure1<double[]> _function = (double[] it) -> {
+      it[1] = 0.0;
+    };
+    final double[] newData = ObjectExtensions.<double[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__double() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 10.0));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 20.0));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 30.0));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, 40.0));
+  }
+  
+  @Test
+  public void testContains__float_NaN() {
+    final double[] nanData = { 1.0, Double.NaN };
+    Assert.assertTrue(ArrayExtensions.contains(nanData, Double.NaN));
+    Assert.assertTrue(ArrayExtensions.contains(nanData, (0f / 0f)));
+    Assert.assertTrue(ArrayExtensions.contains(nanData, Math.log((-1))));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Double.NEGATIVE_INFINITY));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Double.POSITIVE_INFINITY));
+  }
+  
+  @Test
+  public void testContains__double_posInfinity() {
+    final double[] nanData = { 1.0f, Double.POSITIVE_INFINITY };
+    Assert.assertTrue(ArrayExtensions.contains(nanData, Double.POSITIVE_INFINITY));
+    Assert.assertTrue(ArrayExtensions.contains(nanData, (Double.POSITIVE_INFINITY + 7.2f)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Double.NaN));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, (0f / 0f)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Math.log((-1))));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Double.NEGATIVE_INFINITY));
+  }
+  
+  @Test
+  public void testContains__double_negInfinity() {
+    final double[] nanData = { 1.0f, Double.NEGATIVE_INFINITY };
+    Assert.assertTrue(ArrayExtensions.contains(nanData, Double.NEGATIVE_INFINITY));
+    Assert.assertTrue(ArrayExtensions.contains(nanData, (Double.NEGATIVE_INFINITY + 7.2f)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Double.NaN));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, (0f / 0f)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Math.log((-1))));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Double.POSITIVE_INFINITY));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsDoubleTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsDoubleTest.xtend
new file mode 100644
index 0000000..7d37551
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsDoubleTest.xtend
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import java.util.Objects
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsDoubleTest {
+
+	var double[] data
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def double[] createData() {
+		val double[] array = newDoubleArrayOfSize(3)
+		array.set(0, 10.0)
+		array.set(1, 20.0)
+		array.set(2, 30.0)
+		return array
+	}
+
+	@Test
+	def void testSetGet__double() {
+		assertEquals(10.0, data.get(0), 0.001)
+		assertEquals(20.0, data.get(1), 0.001)
+		assertEquals(30.0, data.get(2), 0.001)
+	}
+
+	@Test
+	def void testClone__double() {
+		val clonedData = data.clone();
+
+		assertEquals(10.0, clonedData.get(0), 0.001)
+		assertEquals(20.0, clonedData.get(1), 0.001)
+		assertEquals(30.0, clonedData.get(2), 0.001)
+	}
+
+	@Test
+	def void testLength__double() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__double() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__double() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, 0.0)]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test
+	def void testContains__double() {
+		assertTrue(data.contains(10.0))
+		assertTrue(data.contains(20.0))
+		assertTrue(data.contains(30.0))
+		
+		assertFalse(data.contains(40.0))
+	}
+	
+	@Test
+	def void testContains__float_NaN() {
+		val double[] nanData = #[1.0, Double.NaN]
+		
+		assertTrue(nanData.contains(Double.NaN))
+		assertTrue(nanData.contains(0f / 0f))
+		assertTrue(nanData.contains(Math.log(-1)))
+		
+		assertFalse(nanData.contains(Double.NEGATIVE_INFINITY))
+		assertFalse(nanData.contains(Double.POSITIVE_INFINITY))
+	}
+	
+	@Test
+	def void testContains__double_posInfinity() {
+		val double[] nanData = #[1.0f, Double.POSITIVE_INFINITY]
+		
+		assertTrue(nanData.contains(Double.POSITIVE_INFINITY))
+		assertTrue(nanData.contains(Double.POSITIVE_INFINITY + 7.2f))
+		
+		assertFalse(nanData.contains(Double.NaN))
+		assertFalse(nanData.contains(0f / 0f))
+		assertFalse(nanData.contains(Math.log(-1)))
+		assertFalse(nanData.contains(Double.NEGATIVE_INFINITY))
+	}
+
+	@Test
+	def void testContains__double_negInfinity() {
+		val double[] nanData = #[1.0f, Double.NEGATIVE_INFINITY]
+		
+		assertTrue(nanData.contains(Double.NEGATIVE_INFINITY))
+		assertTrue(nanData.contains(Double.NEGATIVE_INFINITY + 7.2f))
+		
+		assertFalse(nanData.contains(Double.NaN))
+		assertFalse(nanData.contains(0f / 0f))
+		assertFalse(nanData.contains(Math.log(-1)))
+		assertFalse(nanData.contains(Double.POSITIVE_INFINITY))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsFloatTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsFloatTest.java
new file mode 100644
index 0000000..f79f1bd
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsFloatTest.java
@@ -0,0 +1,120 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsFloatTest {
+  private float[] data;
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private float[] createData() {
+    final float[] array = new float[3];
+    array[0] = 10.0f;
+    array[1] = 20.0f;
+    array[2] = 30.0f;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__float() {
+    Assert.assertEquals(10.0f, this.data[0], 0.001f);
+    Assert.assertEquals(20.0f, this.data[1], 0.001f);
+    Assert.assertEquals(30.0f, this.data[2], 0.001f);
+  }
+  
+  @Test
+  public void testClone__float() {
+    final float[] clonedData = this.data.clone();
+    Assert.assertEquals(10.0f, clonedData[0], 0.001f);
+    Assert.assertEquals(20.0f, clonedData[1], 0.001f);
+    Assert.assertEquals(30.0f, clonedData[2], 0.001f);
+  }
+  
+  @Test
+  public void testLength__float() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__float() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__float() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    float[] _createData = this.createData();
+    final Procedure1<float[]> _function = (float[] it) -> {
+      it[1] = 0.0f;
+    };
+    final float[] newData = ObjectExtensions.<float[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__float() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 10.0f));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 20.0f));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 30.0f));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, 40.0f));
+  }
+  
+  @Test
+  public void testContains__float_NaN() {
+    final float[] nanData = { 1.0f, Float.NaN };
+    Assert.assertTrue(ArrayExtensions.contains(nanData, Float.NaN));
+    Assert.assertTrue(ArrayExtensions.contains(nanData, (0f / 0f)));
+    double _log = Math.log((-1));
+    Assert.assertTrue(ArrayExtensions.contains(nanData, ((float) _log)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Float.NEGATIVE_INFINITY));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Float.POSITIVE_INFINITY));
+  }
+  
+  @Test
+  public void testContains__float_posInfinity() {
+    final float[] nanData = { 1.0f, Float.POSITIVE_INFINITY };
+    Assert.assertTrue(ArrayExtensions.contains(nanData, Float.POSITIVE_INFINITY));
+    Assert.assertTrue(ArrayExtensions.contains(nanData, (Float.POSITIVE_INFINITY + 7.2f)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Float.NaN));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, (0f / 0f)));
+    double _log = Math.log((-1));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, ((float) _log)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Float.NEGATIVE_INFINITY));
+  }
+  
+  @Test
+  public void testContains__float_negInfinity() {
+    final float[] nanData = { 1.0f, Float.NEGATIVE_INFINITY };
+    Assert.assertTrue(ArrayExtensions.contains(nanData, Float.NEGATIVE_INFINITY));
+    Assert.assertTrue(ArrayExtensions.contains(nanData, (Float.NEGATIVE_INFINITY + 7.2f)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Float.NaN));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, (0f / 0f)));
+    double _log = Math.log((-1));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, ((float) _log)));
+    Assert.assertFalse(ArrayExtensions.contains(nanData, Float.POSITIVE_INFINITY));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsFloatTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsFloatTest.xtend
new file mode 100644
index 0000000..f6a9afd
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsFloatTest.xtend
@@ -0,0 +1,122 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import java.util.Objects
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsFloatTest {
+
+	var float[] data
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def float[] createData() {
+		val float[] array = newFloatArrayOfSize(3)
+		array.set(0, 10.0f)
+		array.set(1, 20.0f)
+		array.set(2, 30.0f)
+		return array
+	}
+
+	@Test
+	def void testSetGet__float() {
+		assertEquals(10.0f, data.get(0), 0.001f)
+		assertEquals(20.0f, data.get(1), 0.001f)
+		assertEquals(30.0f, data.get(2), 0.001f)
+	}
+
+	@Test
+	def void testClone__float() {
+		val clonedData = data.clone();
+
+		assertEquals(10.0f, clonedData.get(0), 0.001f)
+		assertEquals(20.0f, clonedData.get(1), 0.001f)
+		assertEquals(30.0f, clonedData.get(2), 0.001f)
+	}
+
+	@Test
+	def void testLength__float() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__float() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__float() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, 0.0f)]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test 
+	def void testContains__float() {
+		assertTrue(data.contains(10.0f))
+		assertTrue(data.contains(20.0f))
+		assertTrue(data.contains(30.0f))
+		
+		assertFalse(data.contains(40.0f))
+	}
+	
+	@Test
+	def void testContains__float_NaN() {
+		val float[] nanData = #[1.0f, Float.NaN]
+		
+		assertTrue(nanData.contains(Float.NaN))
+		assertTrue(nanData.contains(0f / 0f))
+		assertTrue(nanData.contains(Math.log(-1) as float))
+		
+		assertFalse(nanData.contains(Float.NEGATIVE_INFINITY))
+		assertFalse(nanData.contains(Float.POSITIVE_INFINITY))
+	}
+	
+	@Test
+	def void testContains__float_posInfinity() {
+		val float[] nanData = #[1.0f, Float.POSITIVE_INFINITY]
+		
+		assertTrue(nanData.contains(Float.POSITIVE_INFINITY))
+		assertTrue(nanData.contains(Float.POSITIVE_INFINITY + 7.2f))
+		
+		assertFalse(nanData.contains(Float.NaN))
+		assertFalse(nanData.contains(0f / 0f))
+		assertFalse(nanData.contains(Math.log(-1) as float))
+		assertFalse(nanData.contains(Float.NEGATIVE_INFINITY))
+	}
+
+	@Test
+	def void testContains__float_negInfinity() {
+		val float[] nanData = #[1.0f, Float.NEGATIVE_INFINITY]
+		
+		assertTrue(nanData.contains(Float.NEGATIVE_INFINITY))
+		assertTrue(nanData.contains(Float.NEGATIVE_INFINITY + 7.2f))
+		
+		assertFalse(nanData.contains(Float.NaN))
+		assertFalse(nanData.contains(0f / 0f))
+		assertFalse(nanData.contains(Math.log(-1) as float))
+		assertFalse(nanData.contains(Float.POSITIVE_INFINITY))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsIntTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsIntTest.java
new file mode 100644
index 0000000..59e5f92
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsIntTest.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsIntTest {
+  private int[] data;
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private int[] createData() {
+    final int[] array = new int[3];
+    array[0] = 10;
+    array[1] = 20;
+    array[2] = 30;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__int() {
+    Assert.assertEquals(10, this.data[0]);
+    Assert.assertEquals(20, this.data[1]);
+    Assert.assertEquals(30, this.data[2]);
+  }
+  
+  @Test
+  public void testClone__int() {
+    final int[] clonedData = this.data.clone();
+    Assert.assertEquals(10, clonedData[0]);
+    Assert.assertEquals(20, clonedData[1]);
+    Assert.assertEquals(30, clonedData[2]);
+  }
+  
+  @Test
+  public void testLength__int() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__int() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__int() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    int[] _createData = this.createData();
+    final Procedure1<int[]> _function = (int[] it) -> {
+      it[1] = 0;
+    };
+    final int[] newData = ObjectExtensions.<int[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__int() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 10));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 20));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 30));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, 40));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsIntTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsIntTest.xtend
new file mode 100644
index 0000000..12bc15a
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsIntTest.xtend
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+import java.util.Objects
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsIntTest {
+
+	var int[] data
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def int[] createData() {
+		val int[] array = newIntArrayOfSize(3)
+		array.set(0, 10)
+		array.set(1, 20)
+		array.set(2, 30)
+		return array
+	}
+
+	@Test
+	def void testSetGet__int() {
+		assertEquals(10, data.get(0))
+		assertEquals(20, data.get(1))
+		assertEquals(30, data.get(2))
+	}
+
+	@Test
+	def void testClone__int() {
+		val clonedData = data.clone();
+
+		assertEquals(10, clonedData.get(0))
+		assertEquals(20, clonedData.get(1))
+		assertEquals(30, clonedData.get(2))
+	}
+
+	@Test
+	def void testLength__int() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__int() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__int() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, 0)]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test 
+	def void testContains__int() {
+		assertTrue(data.contains(10))
+		assertTrue(data.contains(20))
+		assertTrue(data.contains(30))
+		
+		assertFalse(data.contains(40))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsLongTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsLongTest.java
new file mode 100644
index 0000000..a3d8425
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsLongTest.java
@@ -0,0 +1,85 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsLongTest {
+  private long[] data;
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private long[] createData() {
+    final long[] array = new long[3];
+    array[0] = 10l;
+    array[1] = 20l;
+    array[2] = 30l;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__long() {
+    Assert.assertEquals(10l, this.data[0]);
+    Assert.assertEquals(20l, this.data[1]);
+    Assert.assertEquals(30l, this.data[2]);
+  }
+  
+  @Test
+  public void testClone__long() {
+    final long[] clonedData = this.data.clone();
+    Assert.assertEquals(10l, clonedData[0]);
+    Assert.assertEquals(20l, clonedData[1]);
+    Assert.assertEquals(30l, clonedData[2]);
+  }
+  
+  @Test
+  public void testLength__long() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__long() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__long() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    long[] _createData = this.createData();
+    final Procedure1<long[]> _function = (long[] it) -> {
+      it[1] = 0l;
+    };
+    final long[] newData = ObjectExtensions.<long[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__long() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 10l));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 20l));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, 30l));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, 40l));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsLongTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsLongTest.xtend
new file mode 100644
index 0000000..d2e3786
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsLongTest.xtend
@@ -0,0 +1,84 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+import java.util.Objects
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsLongTest {
+
+	var long[] data
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def long[] createData() {
+		val long[] array = newLongArrayOfSize(3)
+		array.set(0, 10l)
+		array.set(1, 20l)
+		array.set(2, 30l)
+		return array
+	}
+
+	@Test
+	def void testSetGet__long() {
+		assertEquals(10l, data.get(0))
+		assertEquals(20l, data.get(1))
+		assertEquals(30l, data.get(2))
+	}
+
+	@Test
+	def void testClone__long() {
+		val clonedData = data.clone();
+
+		assertEquals(10l, clonedData.get(0))
+		assertEquals(20l, clonedData.get(1))
+		assertEquals(30l, clonedData.get(2))
+	}
+
+	@Test
+	def void testLength__long() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__long() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__long() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, 0l)]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test 
+	def void testContains__long() {
+		assertTrue(data.contains(10l))
+		assertTrue(data.contains(20l))
+		assertTrue(data.contains(30l))
+		
+		assertFalse(data.contains(40l))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsObjectTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsObjectTest.java
new file mode 100644
index 0000000..3dae089
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsObjectTest.java
@@ -0,0 +1,86 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsObjectTest {
+  private Object[] data;
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private Object[] createData() {
+    final Object[] array = new Object[3];
+    array[0] = Integer.valueOf(0);
+    array[1] = Integer.valueOf(1);
+    array[2] = null;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__Object() {
+    Assert.assertSame(Integer.valueOf(0), this.data[0]);
+    Assert.assertSame(Integer.valueOf(1), this.data[1]);
+    Assert.assertNull(null, this.data[2]);
+  }
+  
+  @Test
+  public void testClone__Object() {
+    final Object[] clonedData = this.data.clone();
+    Assert.assertSame(Integer.valueOf(0), clonedData[0]);
+    Assert.assertSame(Integer.valueOf(1), clonedData[1]);
+    Assert.assertNull(null, this.data[2]);
+  }
+  
+  @Test
+  public void testLength__Object() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__Object() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__Object() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    Object[] _createData = this.createData();
+    final Procedure1<Object[]> _function = (Object[] it) -> {
+      it[1] = "Hello World";
+    };
+    final Object[] newData = ObjectExtensions.<Object[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__Object() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, Integer.valueOf(0)));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, Integer.valueOf(1)));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, null));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, Integer.valueOf(3)));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, Integer.valueOf(4)));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsObjectTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsObjectTest.xtend
new file mode 100644
index 0000000..461e8cd
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsObjectTest.xtend
@@ -0,0 +1,85 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import java.util.Objects
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsObjectTest {
+
+	var Object[] data
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def Object[] createData() {
+		val Object[] array = newArrayOfSize(3)
+		array.set(0, Integer.valueOf(0))
+		array.set(1, Integer.valueOf(1))
+		array.set(2, null)
+		return array
+	}
+
+	@Test
+	def void testSetGet__Object() {
+		assertSame(Integer.valueOf(0), data.get(0))
+		assertSame(Integer.valueOf(1), data.get(1))
+		assertNull(null, data.get(2))
+	}
+
+	@Test
+	def void testClone__Object() {
+		val clonedData = data.clone();
+
+		assertSame(Integer.valueOf(0), clonedData.get(0))
+		assertSame(Integer.valueOf(1), clonedData.get(1))
+		assertNull(null, data.get(2))
+	}
+
+	@Test
+	def void testLength__Object() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__Object() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__Object() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, "Hello World")]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test
+	def void testContains__Object() {
+		assertTrue(data.contains(Integer.valueOf(0)))
+		assertTrue(data.contains(Integer.valueOf(1)))
+		assertTrue(data.contains(null))
+
+		assertFalse(data.contains(Integer.valueOf(3)))
+		assertFalse(data.contains(Integer.valueOf(4)))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsShortTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsShortTest.java
new file mode 100644
index 0000000..0252f5a
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsShortTest.java
@@ -0,0 +1,91 @@
+/**
+ * Copyright (c) 2019 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.tests.lib;
+
+import java.util.Objects;
+import org.eclipse.xtext.xbase.lib.ArrayExtensions;
+import org.eclipse.xtext.xbase.lib.ObjectExtensions;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ArrayExtensionsShortTest {
+  private short[] data;
+  
+  private final short _10 = ((short) 10);
+  
+  private final short _20 = ((short) 20);
+  
+  private final short _30 = ((short) 30);
+  
+  @Before
+  public void init() {
+    this.data = this.createData();
+  }
+  
+  private short[] createData() {
+    final short[] array = new short[3];
+    array[0] = this._10;
+    array[1] = this._20;
+    array[2] = this._30;
+    return array;
+  }
+  
+  @Test
+  public void testSetGet__short() {
+    Assert.assertEquals(this._10, this.data[0]);
+    Assert.assertEquals(this._20, this.data[1]);
+    Assert.assertEquals(this._30, this.data[2]);
+  }
+  
+  @Test
+  public void testClone__short() {
+    final short[] clonedData = this.data.clone();
+    Assert.assertEquals(this._10, clonedData[0]);
+    Assert.assertEquals(this._20, clonedData[1]);
+    Assert.assertEquals(this._30, clonedData[2]);
+  }
+  
+  @Test
+  public void testLength__short() {
+    Assert.assertEquals(3, this.data.length);
+  }
+  
+  @Test
+  public void testHashCode__short() {
+    Assert.assertEquals(Objects.hashCode(this.data), this.data.hashCode());
+  }
+  
+  @Test
+  public void testEquals__short() {
+    Assert.assertTrue(this.data.equals(this.data));
+    Assert.assertFalse(this.data.equals(this.createData()));
+    Assert.assertFalse(this.data.equals(new Object[3]));
+    Assert.assertFalse(this.data.equals(null));
+    short[] _createData = this.createData();
+    final Procedure1<short[]> _function = (short[] it) -> {
+      it[1] = ((short) 0);
+    };
+    final short[] newData = ObjectExtensions.<short[]>operator_doubleArrow(_createData, _function);
+    Assert.assertFalse(this.data.equals(newData));
+  }
+  
+  @Test
+  public void testContains__short() {
+    Assert.assertTrue(ArrayExtensions.contains(this.data, ((short) 10)));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, ((short) 20)));
+    Assert.assertTrue(ArrayExtensions.contains(this.data, ((short) 30)));
+    Assert.assertFalse(ArrayExtensions.contains(this.data, ((short) 40)));
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsShortTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsShortTest.xtend
new file mode 100644
index 0000000..261538d
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ArrayExtensionsShortTest.xtend
@@ -0,0 +1,88 @@
+/*******************************************************************************
+ * Copyright (c) 2019 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.tests.lib
+
+import org.junit.Before
+import org.junit.Test
+
+import static org.junit.Assert.*
+import java.util.Objects
+
+/**
+ * @author Mathias Rieder - Initial contribution and API
+ */
+class ArrayExtensionsShortTest {
+
+	var short[] data
+
+	val short _10 = 10 as short
+	val short _20 = 20 as short
+	val short _30 = 30 as short
+
+	@Before
+	def void init() {
+		data = createData()
+	}
+
+	private def short[] createData() {
+		val short[] array = newShortArrayOfSize(3)
+		array.set(0, _10)
+		array.set(1, _20)
+		array.set(2, _30)
+		return array
+	}
+
+	@Test
+	def void testSetGet__short() {
+		assertEquals(_10, data.get(0))
+		assertEquals(_20, data.get(1))
+		assertEquals(_30, data.get(2))
+	}
+
+	@Test
+	def void testClone__short() {
+		val clonedData = data.clone();
+
+		assertEquals(_10, clonedData.get(0))
+		assertEquals(_20, clonedData.get(1))
+		assertEquals(_30, clonedData.get(2))
+	}
+
+	@Test
+	def void testLength__short() {
+		assertEquals(3, data.length)
+	}
+
+	@Test
+	def void testHashCode__short() {
+		assertEquals(Objects.hashCode(data), data.hashCode)
+	}
+
+	@Test
+	def void testEquals__short() {
+		assertTrue(data.equals(data))
+
+		assertFalse(data.equals(createData()))
+		assertFalse(data.equals(newArrayOfSize(3)))
+		assertFalse(data.equals(null))
+
+		val newData = createData() => [it.set(1, 0 as short)]
+		assertFalse(data.equals(newData))
+	}
+
+	@Test 
+	def void testContains__short() {
+		assertTrue(data.contains(10 as short))
+		assertTrue(data.contains(20 as short))
+		assertTrue(data.contains(30 as short))
+		
+		assertFalse(data.contains(40 as short))
+	}
+
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/BaseIterablesIteratorsTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/BaseIterablesIteratorsTest.java
new file mode 100644
index 0000000..4ed18e0
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/BaseIterablesIteratorsTest.java
@@ -0,0 +1,548 @@
+/*******************************************************************************
+ * 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.tests.lib;
+
+import java.util.Comparator;
+import java.util.NoSuchElementException;
+
+import org.eclipse.xtext.xbase.lib.Functions;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.Procedures;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.google.common.collect.Ordering;
+
+/**
+ * @author Sebastian Zarnekow - Initial contribution and API
+ */
+public abstract class BaseIterablesIteratorsTest<IterableOrIterator> extends Assert {
+
+	protected Integer first = Integer.valueOf(1);
+	protected Integer second = Integer.valueOf(2);
+	protected Integer third = Integer.valueOf(3);
+	protected Integer forth = Integer.valueOf(4);
+	protected Integer fifth = Integer.valueOf(5);
+	
+	protected abstract IterableOrIterator[] testData(Integer... elements);
+	protected abstract IterableOrIterator[] nullableTestData(Integer... elements);
+	protected abstract IterableOrIterator dummy();
+	protected abstract boolean is(IterableOrIterator input, Integer... elements);
+
+	protected abstract IterableOrIterator operator_plus(IterableOrIterator first, IterableOrIterator second);
+	protected boolean canIterateTwice() {
+		return true;
+	}
+	
+	@Test public void testOperatorPlus_Same() {
+		IterableOrIterator[] data = testData(first, second);
+		for(int i = 0;i < data.length; i++) {
+			if (canIterateTwice())
+				assertTrue(is(operator_plus(data[i], data[i]), first, second, first, second));
+			else
+				assertTrue(is(operator_plus(data[i], data[i]), first, second));
+		}
+	}
+	
+	@Test public void testOperatorPlus() {
+		IterableOrIterator[] firstData = testData(first, second);
+		IterableOrIterator[] secondData = testData(third, forth);
+		for(int i = 0;i < firstData.length; i++) {
+			assertTrue(is(operator_plus(firstData[i], secondData[i]), first, second, third, forth));
+		}
+	}
+	
+	@Test public void testOperatorPlus_NPE_left() {
+		try {
+			operator_plus(null, dummy());
+			fail("expected NullPointerException");
+		} catch(NullPointerException npe) {
+			// expected
+		}
+	}
+	
+	@Test public void testOperatorPlus_NPE_right() {
+		try {
+			operator_plus(dummy(), null);
+			fail("expected NullPointerException");
+		} catch(NullPointerException npe) {
+			// expected
+		}
+	}
+	
+	protected abstract Integer findFirst(IterableOrIterator input, Functions.Function1<Integer, Boolean> filter);
+	
+	@Test public void testFindFirst_empty() {
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return true;
+			}
+		};
+		for(IterableOrIterator testMe: testData()) {
+			Integer last = findFirst(testMe, filter);
+			assertNull("empty input yields null", last);
+		}
+	}
+	
+	@Test public void testFindFirst_noMatch() {
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return false;
+			}
+		};
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			Integer last = findFirst(testMe, filter);
+			assertNull("unmatched input yields null", last);
+		}
+	}
+	
+	@Test public void testFindFirst_allMatches() {
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return true;
+			}
+		};
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			Integer last = findFirst(testMe, filter);
+			assertEquals(first, last);
+		}
+	}
+	
+	@Test public void testFindFirst_oneMatch() {
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return second.equals(p);
+			}
+		};
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			Integer last = findFirst(testMe, filter);
+			assertEquals(second, last);
+		}
+	}
+
+	@Test public void testFindFirst_exceptionInFilter() {
+		final RuntimeException expectedException = new RuntimeException();
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				throw expectedException;
+			}
+		};
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			try {
+				findFirst(testMe, filter);
+				fail("expected exception");
+			} catch(RuntimeException e) {
+				assertSame(expectedException, e);
+			}
+		}
+	}
+	
+	@Test public void testFindFirst_exceptionInFilter_emptyInput() {
+		final RuntimeException expectedException = new RuntimeException();
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				throw expectedException;
+			}
+		};
+		for(IterableOrIterator testMe: testData()) {
+			assertNull(findFirst(testMe, filter));
+		}
+	}
+	
+	@Test public void testFindFirst_NPE_noFilter() {
+		for(IterableOrIterator testMe: testData()) {
+			try {
+				findFirst(testMe, null);
+				fail("Expected NPE");
+			} catch(NullPointerException npe) {
+				// expected
+			}
+		}
+	}
+	
+	@Test public void testFindFirst_NPE_noInput() {
+		try {
+			findLast(null, new Functions.Function1<Integer, Boolean>() {
+				@Override
+				public Boolean apply(Integer p) {
+					return true;
+				}
+			});
+			fail("Expected NPE");
+		} catch(NullPointerException npe) {
+			// expected
+		}
+	}
+	
+	protected abstract Integer findLast(IterableOrIterator input, Functions.Function1<Integer, Boolean> filter);
+	
+	@Test public void testFindLast_empty() {
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return true;
+			}
+		};
+		for(IterableOrIterator testMe: testData()) {
+			Integer last = findLast(testMe, filter);
+			assertNull("empty input yields null", last);
+		}
+	}
+	
+	@Test public void testFindLast_noMatch() {
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return false;
+			}
+		};
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			Integer last = findLast(testMe, filter);
+			assertNull("unmatched input yields null", last);
+		}
+	}
+	
+	@Test public void testFindLast_allMatches() {
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return true;
+			}
+		};
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			Integer last = findLast(testMe, filter);
+			assertEquals(third, last);
+		}
+	}
+	
+	@Test public void testFindLast_oneMatch() {
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return second.equals(p);
+			}
+		};
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			Integer last = findLast(testMe, filter);
+			assertEquals(second, last);
+		}
+	}
+
+	@Test public void testFindLast_exceptionInFilter() {
+		final RuntimeException expectedException = new RuntimeException();
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				throw expectedException;
+			}
+		};
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			try {
+				findLast(testMe, filter);
+				fail("expected exception");
+			} catch(RuntimeException e) {
+				assertSame(expectedException, e);
+			}
+		}
+	}
+	
+	@Test public void testFindLast_exceptionInFilter_emptyInput() {
+		final RuntimeException expectedException = new RuntimeException();
+		Function1<Integer, Boolean> filter = new Functions.Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				throw expectedException;
+			}
+		};
+		for(IterableOrIterator testMe: testData()) {
+			Integer last = findLast(testMe, filter);
+			assertEquals(null, last);
+		}
+	}
+	
+	@Test public void testFindLast_NPE_noFilter() {
+		for(IterableOrIterator testMe: testData()) {
+			try {
+				findLast(testMe, null);
+				fail("Expected NPE");
+			} catch(NullPointerException npe) {
+				// expected
+			}
+		}
+	}
+	
+	@Test public void testFindLast_NPE_noInput() {
+		try {
+			findLast(null, new Functions.Function1<Integer, Boolean>() {
+				@Override
+				public Boolean apply(Integer p) {
+					return true;
+				}
+			});
+			fail("Expected NPE");
+		} catch(NullPointerException npe) {
+			// expected
+		}
+	}
+	
+	protected abstract Integer last(IterableOrIterator input);
+	
+	@Test public void testLast_empty() {
+		for(IterableOrIterator testMe: testData()) {
+			Integer last = last(testMe);
+			assertNull("empty input yields null", last);
+		}
+	}
+	
+	@Test public void testLast_oneEntry() {
+		for(IterableOrIterator testMe: testData(first)) {
+			Integer last = last(testMe);
+			assertEquals(first, last);
+		}
+	}
+	
+	@Test public void testLast_entryIsNull() {
+		for(IterableOrIterator testMe: nullableTestData((Integer)null)) {
+			Integer last = last(testMe);
+			assertEquals(null, last);
+		}
+	}
+	
+	@Test public void testLast_moreEntries() {
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			Integer last = last(testMe);
+			assertEquals(third, last);
+		}
+	}
+	
+	@Test public void testLast_NPE() {
+		try {
+			last(null);
+			fail("expeced NPE");
+		} catch(NullPointerException npe) {
+			// expected
+		}
+	}
+	
+	protected abstract Integer head(IterableOrIterator input);
+	
+	@Test public void testHead_empty() {
+		for(IterableOrIterator testMe: testData()) {
+			Integer head = head(testMe);
+			assertNull("empty input yields null", head);
+		}
+	}
+	
+	@Test public void testHead_oneEntry() {
+		for(IterableOrIterator testMe: testData(first)) {
+			Integer head = head(testMe);
+			assertEquals(first, head);
+		}
+	}
+	
+	@Test public void testHead_entryIsNull() {
+		for(IterableOrIterator testMe: nullableTestData((Integer)null)) {
+			Integer head = head(testMe);
+			assertEquals(null, head);
+		}
+	}
+	
+	@Test public void testHead_moreEntries() {
+		for(IterableOrIterator testMe: testData(first, second, third)) {
+			Integer head = head(testMe);
+			assertEquals(first, head);
+		}
+	}
+	
+	@Test public void testHead_NPE() {
+		try {
+			head(null);
+			fail("expeced NPE");
+		} catch(NullPointerException npe) {
+			// expected
+		}
+	}
+	
+	protected abstract void forEach(IterableOrIterator input, Procedures.Procedure2<Integer, Integer> proc);
+	
+	static class ForEachLoopCounter implements Procedures.Procedure2<Integer, Integer> {
+
+		private int expectedIndex = 0;
+		private final Integer[] values;
+		
+		ForEachLoopCounter(Integer... values) {
+			this.values = values;
+		}
+		
+		@Override
+		public void apply(Integer value, Integer index) {
+			assertEquals(expectedIndex, index.intValue());
+			assertEquals(values[expectedIndex], value);
+			expectedIndex++;
+		}
+		
+	}
+	
+	@Test public void testForEachWithIndex_empty() {
+		for(IterableOrIterator testMe: testData()) {
+			ForEachLoopCounter counter = new ForEachLoopCounter();
+			forEach(testMe, counter);
+			assertEquals(0, counter.expectedIndex);
+		}
+	}
+	
+	@Test public void testForEachWithIndex_empty_noProcedure() {
+		for(IterableOrIterator testMe: testData()) {
+			try {
+				forEach(testMe, null);
+				fail("expeced NPE");
+			} catch(NullPointerException e) {
+				// expected
+			}
+		}
+	}
+	
+	@Test public void testForEachWithIndex_oneEntry() {
+		for(IterableOrIterator testMe: testData(first)) {
+			ForEachLoopCounter counter = new ForEachLoopCounter(first);
+			forEach(testMe, counter);
+			assertEquals(1, counter.expectedIndex);
+		}
+	}
+	
+	@Test public void testForEachWithIndex_entryIsNull() {
+		for(IterableOrIterator testMe: nullableTestData((Integer)null)) {
+			ForEachLoopCounter counter = new ForEachLoopCounter((Integer)null);
+			forEach(testMe, counter);
+			assertEquals(1, counter.expectedIndex);
+		}
+	}
+	
+	@Test public void testForEachWithIndex_moreEntries() {
+		for(IterableOrIterator testMe: testData(first, second, forth)) {
+			ForEachLoopCounter counter = new ForEachLoopCounter(first, second, forth);
+			forEach(testMe, counter);
+			assertEquals(3, counter.expectedIndex);
+		}
+	}
+	
+	@Test public void testForEachWithIndex_NPE() {
+		try {
+			forEach(null, new ForEachLoopCounter());
+			fail("expeced NPE");
+		} catch(NullPointerException npe) {
+			// expected
+		}
+	}
+	
+	protected abstract IterableOrIterator takeWhile(IterableOrIterator input, Functions.Function1<Integer, Boolean> filter);
+	protected abstract IterableOrIterator dropWhile(IterableOrIterator input, Functions.Function1<Integer, Boolean> filter);
+	protected abstract Integer min(IterableOrIterator input);
+	protected abstract Integer max(IterableOrIterator input);
+	protected abstract Integer min(IterableOrIterator input, Comparator<? super Integer> comparator);
+	protected abstract Integer max(IterableOrIterator input, Comparator<? super Integer> comparator);
+	protected abstract Integer minBy(IterableOrIterator input, Functions.Function1<? super Integer, String> compareBy);
+	protected abstract Integer maxBy(IterableOrIterator input, Functions.Function1<? super Integer, String> compareBy);
+	
+	@Test public void testTakeWhile() {
+		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
+			IterableOrIterator taken = takeWhile(testMe, new Function1<Integer, Boolean>() {
+				@Override
+				public Boolean apply(Integer p) {
+					return p <= 3;
+				}
+			});
+			assertTrue(is(taken, first, second, third));
+		}
+	}
+	
+	@Test public void testDropWhile() {
+		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
+			IterableOrIterator tail = dropWhile(testMe, new Function1<Integer, Boolean>() {
+				@Override
+				public Boolean apply(Integer p) {
+					return p <= 3;
+				}
+			});
+			assertTrue(is(tail, forth, fifth));
+		}
+	}
+	
+	@Test public void testMinComparable() {
+		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
+			Integer min = min(testMe);
+			assertEquals(first, min);
+		}
+	}
+	
+	@Test public void testMaxComparable() {
+		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
+			Integer max = max(testMe);
+			assertEquals(fifth, max);
+		}
+	}
+	
+	@Test(expected = NoSuchElementException.class) 
+	public void testMinEmpty() {
+		for (IterableOrIterator testMe : testData()) {
+			min(testMe);
+		}
+	}
+	
+	@Test(expected = NoSuchElementException.class)
+	public void testMaxEmpty() {
+		for (IterableOrIterator testMe : testData()) {
+			max(testMe);
+		}
+	}
+	
+	@Test public void testMinComparator() {
+		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
+			Integer min = min(testMe, Ordering.natural().reverse());
+			assertEquals(fifth, min);
+		}
+	}
+	
+	@Test public void testMaxComparator() {
+		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
+			Integer max = max(testMe, Ordering.natural().reverse());
+			assertEquals(first, max);
+		}
+	}
+	
+	@Test public void testMinBy() {
+		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
+			Integer min = minBy(testMe, new Function1<Integer, String>() {
+				@Override
+				public String apply(Integer p) {
+					return Integer.toBinaryString(p);
+				}
+			});
+			assertEquals(first, min);
+		}
+	}
+	
+	@Test public void testMaxBy() {
+		for (IterableOrIterator testMe : testData(first, second, third, forth, fifth)) {
+			Integer max = maxBy(testMe, new Function1<Integer, String>() {
+				@Override
+				public String apply(Integer p) {
+					return Integer.toBinaryString(p);
+				}
+			});
+			assertEquals(third, max);
+		}
+	}
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/ExclusiveRangeTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/ExclusiveRangeTest.java
new file mode 100644
index 0000000..205fc36
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/ExclusiveRangeTest.java
@@ -0,0 +1,94 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2018 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.tests.lib;
+
+import org.eclipse.xtext.xbase.lib.ExclusiveRange;
+import org.junit.Test;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertFalse;
+import static org.eclipse.xtext.xbase.lib.IterableExtensions.join;
+
+/**
+ * @author Jan Koehnlein
+ */
+public class ExclusiveRangeTest {
+
+	@Test
+	public void testContent() {
+		assertEquals("1,2,3,4", join(new ExclusiveRange(1, 5, true), ","));
+		assertEquals("", join(new ExclusiveRange(0, 0, true), ","));
+		assertEquals("", join(new ExclusiveRange(0, -1, true), ","));
+		assertEquals("-1", join(new ExclusiveRange(-1, 0, true), ","));
+		assertEquals("4,3,2,1", join(new ExclusiveRange(5, 1, false), ","));
+		assertEquals("", join(new ExclusiveRange(0, 0, false), ","));
+		assertEquals("", join(new ExclusiveRange(-1, 0, false), ","));
+		assertEquals("-1", join(new ExclusiveRange(0, -1, false), ","));
+	}
+
+	@Test
+	public void testSize() {
+		assertEquals(4, new ExclusiveRange(1, 5, true).size());
+		assertEquals(0, new ExclusiveRange(0, 0, true).size());
+		assertEquals(0, new ExclusiveRange(0, -1, true).size());
+		assertEquals(1, new ExclusiveRange(-1, 0, true).size());
+		assertEquals(4, new ExclusiveRange(5, 1, false).size());
+		assertEquals(0, new ExclusiveRange(0, 0, false).size());
+		assertEquals(0, new ExclusiveRange(-1, 0, false).size());
+		assertEquals(1, new ExclusiveRange(0, -1, false).size());
+	}
+
+	@Test
+	public void testIsEmpty() {
+		assertFalse(new ExclusiveRange(1, 5, true).isEmpty());
+		assertTrue(new ExclusiveRange(0, 0, true).isEmpty());
+		assertTrue(new ExclusiveRange(0, -1, true).isEmpty());
+		assertFalse(new ExclusiveRange(-1, 0, true).isEmpty());
+		assertFalse(new ExclusiveRange(5, 1, false).isEmpty());
+		assertTrue(new ExclusiveRange(0, 0, false).isEmpty());
+		assertTrue(new ExclusiveRange(-1, 0, false).isEmpty());
+		assertFalse(new ExclusiveRange(0, -1, false).isEmpty());
+	}
+
+	@Test
+	public void testContains() {
+		assertFalse(new ExclusiveRange(1, 5, true).contains(0));
+		assertTrue(new ExclusiveRange(1, 5, true).contains(1));
+		assertTrue(new ExclusiveRange(1, 5, true).contains(2));
+		assertTrue(new ExclusiveRange(1, 5, true).contains(3));
+		assertTrue(new ExclusiveRange(1, 5, true).contains(4));
+		assertFalse(new ExclusiveRange(1, 5, true).contains(5));
+
+		assertFalse(new ExclusiveRange(0, 0, true).contains(0));
+
+		assertFalse(new ExclusiveRange(0, -1, true).contains(0));
+		assertFalse(new ExclusiveRange(0, -1, true).contains(-1));
+
+		assertFalse(new ExclusiveRange(-1, 0, true).contains(-2));
+		assertTrue(new ExclusiveRange(-1, 0, true).contains(-1));
+		assertFalse(new ExclusiveRange(-1, 0, true).contains(-0));
+
+		assertFalse(new ExclusiveRange(5, 1, false).contains(0));
+		assertTrue(new ExclusiveRange(5, 1, false).contains(1));
+		assertTrue(new ExclusiveRange(5, 1, false).contains(2));
+		assertTrue(new ExclusiveRange(5, 1, false).contains(3));
+		assertTrue(new ExclusiveRange(5, 1, false).contains(4));
+		assertFalse(new ExclusiveRange(5, 1, false).contains(5));
+
+		assertFalse(new ExclusiveRange(0, 0, false).contains(0));
+
+		assertFalse(new ExclusiveRange(-1, 0, false).contains(0));
+		assertFalse(new ExclusiveRange(-1, 0, false).contains(-1));
+
+		assertFalse(new ExclusiveRange(0, -1, false).contains(-2));
+		assertTrue(new ExclusiveRange(0, -1, false).contains(-1));
+		assertFalse(new ExclusiveRange(0, -1, false).contains(-0));
+	}
+	
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/FunctionCompositionTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/FunctionCompositionTest.java
new file mode 100644
index 0000000..9ae3071
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/FunctionCompositionTest.java
@@ -0,0 +1,71 @@
+/**
+ * Copyright (c) 2015, 2018 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.tests.lib;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.eclipse.xtext.xbase.lib.FunctionExtensions;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.Functions.Function2;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author efftinge - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class FunctionCompositionTest {
+	
+	private Function2<Integer, Integer, Integer> binaryFun = (Integer e, Integer e2) -> {
+		return e * e2;
+	};
+
+	private Function1<Integer, Integer> times2 = (Integer e) -> {
+		return e * 2;
+	};
+
+	private Function1<Integer, Integer> squared = (Integer e) -> {
+		return e * e;
+	};
+
+	@Test
+	public void testCompose() {
+		int actual = FunctionExtensions.compose(times2, squared).apply(4);
+		Assert.assertEquals(32, actual);
+	}
+
+	@Test
+	public void testAndThen() {
+		int actual = FunctionExtensions.andThen(times2, squared).apply(4);
+		Assert.assertEquals(64, actual);
+	}
+
+	@Test
+	public void testAndThen2() {
+		int actual = FunctionExtensions.andThen(binaryFun, squared).apply(2, 1);
+		Assert.assertEquals(4, actual);
+	}
+
+	@Test
+	public void testAndThenProcedure() {
+		Procedure1<AtomicInteger> incrementer = (AtomicInteger it) -> {
+			it.incrementAndGet();
+		};
+		
+		Procedure1<AtomicInteger> function = (AtomicInteger it) -> {
+			Assert.assertEquals(2, it.incrementAndGet());
+		};
+		
+		AtomicInteger counter = new AtomicInteger();
+		FunctionExtensions.andThen(incrementer, function).apply(counter);
+		
+		Assert.assertEquals(3, counter.incrementAndGet());
+	}
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/IntegerExtensionsTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/IntegerExtensionsTest.java
new file mode 100644
index 0000000..9829550
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/IntegerExtensionsTest.java
@@ -0,0 +1,56 @@
+/*******************************************************************************
+ * 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.tests.lib;
+
+import java.util.Iterator;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Sven Efftinge - Initial contribution and API
+ */
+public class IntegerExtensionsTest {
+	
+	@Test
+	public void testOperator_upTo_01() throws Exception {
+		Iterator<Integer> iterator = org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_upTo(0, 0).iterator();
+		Assert.assertEquals(0, iterator.next().intValue());
+		Assert.assertFalse(iterator.hasNext());
+	}
+	
+	@Test
+	public void testOperator_upTo_02() throws Exception {
+		Iterator<Integer> iterator = org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_upTo(4, 6).iterator();
+		Assert.assertEquals(4, iterator.next().intValue());
+		Assert.assertEquals(5, iterator.next().intValue());
+		Assert.assertEquals(6, iterator.next().intValue());
+		Assert.assertFalse(iterator.hasNext());
+	}
+	
+	@Test
+	public void testOperator_upTo_03() throws Exception {
+		Iterator<Integer> iterator = org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_upTo(12, 9).iterator();
+		Assert.assertEquals(12, iterator.next().intValue());
+		Assert.assertEquals(11, iterator.next().intValue());
+		Assert.assertEquals(10, iterator.next().intValue());
+		Assert.assertEquals(9, iterator.next().intValue());
+		Assert.assertFalse(iterator.hasNext());
+	}
+	
+	@Test
+	public void testOperator_upTo_04() throws Exception {
+		Iterator<Integer> iterator = org.eclipse.xtext.xbase.lib.IntegerExtensions.operator_upTo(-12, -9).iterator();
+		Assert.assertEquals(-12, iterator.next().intValue());
+		Assert.assertEquals(-11, iterator.next().intValue());
+		Assert.assertEquals(-10, iterator.next().intValue());
+		Assert.assertEquals(-9, iterator.next().intValue());
+		Assert.assertFalse(iterator.hasNext());
+	}
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/IntegerRangeTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/IntegerRangeTest.java
new file mode 100644
index 0000000..065ed37
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/IntegerRangeTest.java
@@ -0,0 +1,160 @@
+/*******************************************************************************
+ * Copyright (c) 2012, 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.xtext.xbase.tests.lib;
+
+import static org.junit.Assert.*;
+
+import java.util.ListIterator;
+import java.util.NoSuchElementException;
+
+import org.eclipse.xtext.xbase.lib.IntegerRange;
+import org.junit.Test;
+
+/**
+ * @author Jan Koehnlein - Initial contribution and API
+ * @author Karsten Thoms - Bug#381140
+ */
+public class IntegerRangeTest {
+
+	@Test
+	public void testValidity() {
+		new IntegerRange(0, 0, 1);
+		new IntegerRange(0, 0, -1);
+		new IntegerRange(0, 2, 1);
+		new IntegerRange(-1, 2, 1);
+		new IntegerRange(-2, -1, 1);
+		new IntegerRange(2, 0, -1);
+		new IntegerRange(2, -1, -1);
+		new IntegerRange(-1, -2, -1);
+		new IntegerRange(-2, 0, 1);
+		new IntegerRange(Integer.MIN_VALUE, 0, 1);
+		new IntegerRange(Integer.MAX_VALUE, 0, -1);
+
+		assertInvalid(0, 1, 0);
+		assertInvalid(0, 2, -1);
+		assertInvalid(-1, 2, -1);
+		assertInvalid(-2, -1, -1);
+		assertInvalid(2, 0, 1);
+		assertInvalid(2, -1, 1);
+		assertInvalid(-1, -2, 1);
+	}
+
+	protected void assertInvalid(int start, int end, int step) {
+		try {
+			new IntegerRange(start, end, step);
+			fail("Invalid step not detected");
+		} catch (IllegalArgumentException e) {
+			// expected exception
+		}
+	}
+
+	@Test
+	public void testDefaultStep() {
+		assertEquals(1, new IntegerRange(0, 10).getStep());
+		assertEquals(-1, new IntegerRange(10, 0).getStep());
+		assertEquals(1, new IntegerRange(10, 10).getStep());
+	}
+
+	@Test
+	public void testContains_0() {
+		IntegerRange range = new IntegerRange(-1, 1, 2);
+		assertFalse(range.contains(-2));
+		assertTrue(range.contains(-1));
+		assertFalse(range.contains(0));
+		assertTrue(range.contains(1));
+		assertFalse(range.contains(2));
+	}
+
+	@Test
+	public void testContains_1() {
+		IntegerRange range = new IntegerRange(-1, 2, 2);
+		assertFalse(range.contains(-2));
+		assertTrue(range.contains(-1));
+		assertFalse(range.contains(0));
+		assertTrue(range.contains(1));
+		assertFalse(range.contains(2));
+	}
+
+	@Test
+	public void testSize() {
+		final IntegerRange myRange = new IntegerRange(-1, 1);
+		assertEquals(3, myRange.getSize());
+		assertEquals(2, myRange.withStep(2).getSize());
+		assertEquals(1, myRange.withStep(3).getSize());
+		
+		final IntegerRange myRange2 = new IntegerRange(1, -1);
+		assertEquals(3, myRange2.getSize());
+		assertEquals(2, myRange2.withStep(-2).getSize());
+		assertEquals(1, myRange2.withStep(-3).getSize());
+	}
+
+	@Test
+	public void testIterator() {
+		ListIterator<Integer> iterator = new IntegerRange(-2, 2, 2).iterator();
+		assertFalse(iterator.hasPrevious());
+		assertTrue(iterator.hasNext());
+		assertEquals(0, iterator.nextIndex());
+		assertEquals(-1, iterator.previousIndex());
+		try {
+			iterator.previous();
+			fail("Expected NoSuchElementException");
+		} catch(NoSuchElementException e) {
+			// expected exception;
+		}
+		
+		assertEquals(-2, iterator.next().intValue());
+		assertTrue(iterator.hasPrevious());
+		assertTrue(iterator.hasNext());
+		assertEquals(1, iterator.nextIndex());
+		assertEquals(0, iterator.previousIndex());
+
+		assertEquals(0, iterator.next().intValue());
+		assertTrue(iterator.hasPrevious());
+		assertTrue(iterator.hasNext());
+		assertEquals(2, iterator.nextIndex());
+		assertEquals(1, iterator.previousIndex());
+
+		assertEquals(2, iterator.next().intValue());
+		assertTrue(iterator.hasPrevious());
+		assertFalse(iterator.hasNext());
+		assertEquals(3, iterator.nextIndex());
+		assertEquals(2, iterator.previousIndex());
+		try {
+			iterator.next();
+			fail("Expected NoSuchElementException");
+		} catch(NoSuchElementException e) {
+			// expected exception;
+		}
+
+		assertEquals(2, iterator.previous().intValue());
+		assertTrue(iterator.hasPrevious());
+		assertTrue(iterator.hasNext());
+		assertEquals(2, iterator.nextIndex());
+		assertEquals(1, iterator.previousIndex());
+
+		assertEquals(0, iterator.previous().intValue());
+		assertTrue(iterator.hasPrevious());
+		assertTrue(iterator.hasNext());
+		assertEquals(1, iterator.nextIndex());
+		assertEquals(0, iterator.previousIndex());
+
+		assertEquals(-2, iterator.previous().intValue());
+		assertFalse(iterator.hasPrevious());
+		assertTrue(iterator.hasNext());
+		assertEquals(0, iterator.nextIndex());
+		assertEquals(-1, iterator.previousIndex());
+
+		try {
+			iterator.previous();
+			fail("Expected NoSuchElementException");
+		} catch(NoSuchElementException e) {
+			// expected exception;
+		}
+	}
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/IterableExtensionsTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/IterableExtensionsTest.java
new file mode 100644
index 0000000..226628c
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/IterableExtensionsTest.java
@@ -0,0 +1,363 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.xtext.xbase.tests.lib;
+
+import static com.google.common.collect.Lists.*;
+import static com.google.common.collect.Sets.*;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import org.eclipse.xtext.xbase.lib.Functions;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IterableExtensions;
+import org.eclipse.xtext.xbase.lib.Pair;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
+import org.junit.Test;
+
+import com.google.common.collect.ForwardingCollection;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+
+/**
+ * @author Sebastian Zarnekow - Initial contribution and API
+ * @author Karsten Thoms - testMap, testFlatMap
+ */
+public class IterableExtensionsTest extends BaseIterablesIteratorsTest<Iterable<Integer>> {
+
+	@Override
+	protected Iterable<Integer>[] testData(Integer... elements) {
+		@SuppressWarnings("unchecked")
+		Iterable<Integer>[] result = new Iterable[] {
+			Lists.newArrayList(elements),
+			Lists.newLinkedList(Lists.newArrayList(elements)),
+			Sets.newLinkedHashSet(Lists.newArrayList(elements)),
+			Sets.newTreeSet(Lists.newArrayList(elements))
+		};
+		return result;
+	}
+	
+	@Override
+	protected Iterable<Integer>[] nullableTestData(Integer... elements) {
+		@SuppressWarnings("unchecked")
+		Iterable<Integer>[] result = new Iterable[] {
+			Lists.newArrayList(elements),
+			Lists.newLinkedList(Lists.newArrayList(elements)),
+			Sets.newLinkedHashSet(Lists.newArrayList(elements)),
+//			Sets.newTreeSet(Lists.newArrayList(elements)) null is not allowed
+		};
+		return result;
+	}
+
+	@Override
+	protected Iterable<Integer> dummy() {
+		return Collections.emptyList();
+	}
+
+	@Override
+	protected boolean is(Iterable<Integer> input, Integer... elements) {
+		return Iterables.elementsEqual(input, Lists.newArrayList(elements));
+	}
+
+	@Override
+	protected Iterable<Integer> operator_plus(Iterable<Integer> first, Iterable<Integer> second) {
+		return IterableExtensions.operator_plus(first, second);
+	}
+
+	@Override
+	protected Integer findFirst(Iterable<Integer> input, Function1<Integer, Boolean> filter) {
+		return IterableExtensions.findFirst(input, filter);
+	}
+
+	@Override
+	protected Integer findLast(Iterable<Integer> input, Function1<Integer, Boolean> filter) {
+		return IterableExtensions.findLast(input, filter);
+	}
+
+	@Override
+	protected Integer last(Iterable<Integer> input) {
+		return IterableExtensions.last(input);
+	}
+
+	@Override
+	protected Integer head(Iterable<Integer> input) {
+		return IterableExtensions.head(input);
+	}
+	
+	@Override
+	protected void forEach(Iterable<Integer> input, Procedure2<Integer, Integer> proc) {
+		IterableExtensions.forEach(input, proc);
+	}
+	
+	@Override
+	protected Iterable<Integer> takeWhile(Iterable<Integer> input, Function1<Integer, Boolean> filter) {
+		return IterableExtensions.takeWhile(input, filter);
+	}
+	
+	@Override
+	protected Iterable<Integer> dropWhile(Iterable<Integer> input, Function1<Integer, Boolean> filter) {
+		return IterableExtensions.dropWhile(input, filter);
+	}
+	
+	@Override
+	protected Integer max(Iterable<Integer> input) {
+		return IterableExtensions.max(input);
+	}
+	
+	@Override
+	protected Integer max(Iterable<Integer> input, Comparator<? super Integer> comparator) {
+		return IterableExtensions.max(input, comparator);
+	}
+	
+	@Override
+	protected Integer maxBy(Iterable<Integer> input, Function1<? super Integer, String> compareBy) {
+		return IterableExtensions.maxBy(input, compareBy);
+	}
+	
+	@Override
+	protected Integer min(Iterable<Integer> input) {
+		return IterableExtensions.min(input);
+	}
+	
+	@Override
+	protected Integer min(Iterable<Integer> input, Comparator<? super Integer> comparator) {
+		return IterableExtensions.min(input, comparator);
+	}
+	
+	@Override
+	protected Integer minBy(Iterable<Integer> input, Function1<? super Integer, String> compareBy) {
+		return IterableExtensions.minBy(input, compareBy);
+	}
+	
+	@Test public void testJoinWithNull() {
+		List<String> list = Lists.newArrayList("a", null, "c");
+		String string = IterableExtensions.join(list, ",");
+		assertEquals("a,null,c", string);
+	}
+	
+	@Test public void testSortBy() throws Exception {
+		List<? extends CharSequence> list = newArrayList("foo","bar","baz");
+		List<? extends CharSequence> sorted = IterableExtensions.sortBy(list, new Functions.Function1<CharSequence, String>() {
+			@Override
+			public String apply(CharSequence p) {
+				return p.toString();
+			}
+		});
+		assertNotSame(list, sorted);
+		assertEquals(sorted, newArrayList("bar","baz","foo"));
+	}
+	
+	@Test public void testFilterNull() throws Exception {
+		Iterator<String> iter = IterableExtensions.filterNull(newArrayList("foo", null, "bar")).iterator();
+		assertEquals("foo", iter.next());
+		assertEquals("bar", iter.next());
+		assertFalse(iter.hasNext());
+	}
+	
+	@Test public void testJoinWithBeforeAndAfter() throws Exception {
+		ArrayList<String> list = newArrayList("foo", "bar");
+		ArrayList<String> singletonList = newArrayList("foo");
+		ArrayList<String> emptylist = new ArrayList<String>();
+		
+		final Functions.Function1<String, String> function = new Functions.Function1<String, String>() {
+			@Override
+			public String apply(String p) {
+				return p;
+			}
+		};
+		assertEquals("<foo,bar>", IterableExtensions.join(list, "<", ",", ">", function));
+		assertEquals("<foo>", IterableExtensions.join(singletonList, "<", ",", ">", function));
+		assertEquals("", IterableExtensions.join(emptylist, "<", ",", ">", function));
+		
+		assertEquals("foo,bar>", IterableExtensions.join(list, null, ",", ">", function));
+		assertEquals("foo>", IterableExtensions.join(singletonList, null, ",", ">", function));
+		assertEquals("", IterableExtensions.join(emptylist, null, ",", ">", function));
+		
+		assertEquals("<foobar>", IterableExtensions.join(list, "<", null, ">", function));
+		assertEquals("<foo>", IterableExtensions.join(singletonList, "<", null, ">", function));
+		assertEquals("", IterableExtensions.join(emptylist, "<", null, ">", function));
+		
+		assertEquals("<foo,bar", IterableExtensions.join(list, "<", ",", null, function));
+		assertEquals("<foo", IterableExtensions.join(singletonList, "<", ",", null, function));
+		assertEquals("", IterableExtensions.join(emptylist, "<", ",", null, function));
+	}
+	
+	@Test public void testIndexed() {
+		Iterator<Pair<Integer, String>> result = IterableExtensions.indexed(newArrayList("foo", "bar")).iterator();
+		assertEquals(new Pair<Integer, String>(0, "foo"), result.next());
+		assertEquals(new Pair<Integer, String>(1, "bar"), result.next());
+		assertFalse(result.hasNext());
+	}
+
+	class A {}
+	interface C {}
+	class B extends A implements C {}
+	class D extends A {}
+
+	@Test public void testReject() {
+		List<Integer> nullList = new ArrayList<>();
+		nullList.add(null);
+		List<Object> objects = newArrayList(1, 2, null, 4l, "String");
+		assertEquals(newArrayList(1, 2, null, 4l), newArrayList(IterableExtensions.reject(objects, String.class)));
+		assertEquals(nullList, newArrayList(IterableExtensions.reject(objects, Object.class)));
+		
+		List<Integer> integerObjects = newArrayList(1, 2, null, 4);
+		assertEquals(nullList, newArrayList(IterableExtensions.reject(integerObjects, Integer.class)));
+		
+		List<A> bObjects = newArrayList(new B(), new B(), new D());
+		assertEquals(0, IterableExtensions.size(IterableExtensions.reject(bObjects, A.class)));
+		assertEquals(1, IterableExtensions.size(IterableExtensions.reject(bObjects, B.class)));
+		assertEquals(1, IterableExtensions.size(IterableExtensions.reject(bObjects, C.class)));
+		assertEquals(2, IterableExtensions.size(IterableExtensions.reject(bObjects, D.class)));
+		
+		Function1<Integer, Boolean> function = new Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return p % 2 == 0;
+			}
+		};
+		assertEquals(newArrayList(1,3,5),newArrayList(IterableExtensions.reject(newArrayList(1,2,3,4,5), function)));
+		Function1<Integer, Boolean> functionNullSafe = new Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return p == null || p % 2 == 0;
+			}
+		};
+		assertEquals(newArrayList(1,5),newArrayList(IterableExtensions.reject(newArrayList(1,2,null,4,5), functionNullSafe)));
+		try {
+			newArrayList(IterableExtensions.reject(null, function));
+			fail("NullPointerException expected");
+		} catch (NullPointerException e) {
+			// expected NPE
+		}
+		try {
+			Function1<? super Integer, Boolean> nullFn = null;
+			newArrayList(IterableExtensions.reject(newArrayList(1,2,3), nullFn));
+			fail("NullPointerException expected");
+		} catch (NullPointerException e) {
+			// expected NPE
+		}
+		try {
+			Class<Integer> nullClass = null;
+			newArrayList(IterableExtensions.reject(newArrayList(1,2,3), nullClass));
+			fail("NullPointerException expected");
+		} catch (NullPointerException e) {
+			// expected NPE
+		}
+		Function1<Integer, Boolean> brokenFunction = new Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return null;
+			}
+		};
+		try {
+			newArrayList(IterableExtensions.reject(newArrayList(1,2,3), brokenFunction));
+			fail("NullPointerException expected");
+		} catch (NullPointerException e) {
+			// expected NPE
+		}
+	}
+
+	@Test public void testMap () {
+		ArrayList<String> list = newArrayList("foo", "bar");
+		
+		final Functions.Function1<String, String> function = new Functions.Function1<String, String>() {
+			@Override
+			public String apply(String p) {
+				return "Hello "+p;
+			}
+		};
+		
+		assertEquals(newArrayList("Hello foo", "Hello bar"), newArrayList(IterableExtensions.map(list, function)));
+	
+		// test that the returned iterator supports remove on the underyling list
+		// therefore we need a function that maps to the same object contained in the list
+		final Functions.Function1<String, String> functionForRemove = new Functions.Function1<String, String>() {
+			@Override
+			public String apply(String p) {
+				return "foo".equals(p) ? p : "Hello "+p;
+			}
+		};
+
+		assertTrue(list.contains("foo"));
+		assertEquals(2, list.size());
+		assertEquals(newArrayList("foo", "Hello bar"), newArrayList(IterableExtensions.map(list, functionForRemove)));
+		Iterator<String> iterator = IterableExtensions.map(list, functionForRemove).iterator();
+		iterator.next();
+		iterator.remove();
+		
+		assertTrue(!list.contains("foo"));
+		assertEquals(1, list.size());
+	}
+
+	@Test public void testFlatMap () {
+		ArrayList<String> list = newArrayList("foo", "bar");
+		
+		final Functions.Function1<String, Iterable<String>> function = new Functions.Function1<String, Iterable<String>>() {
+			@Override
+			public Iterable<String> apply(String p) {
+				return newArrayList("Hello", p);
+			}
+		};
+		assertEquals(newArrayList("Hello", "foo", "Hello", "bar"), newArrayList(IterableExtensions.flatMap(list, function)));
+	}
+	
+	@Test public void testContains() {
+		ArrayList<String> list = newArrayList("element1", "element2", "element3", null);
+		
+		assertTrue(IterableExtensions.contains(list, "element3"));
+		assertTrue(IterableExtensions.contains(list, new String("element3")));
+		assertTrue(IterableExtensions.contains(list, null));
+		
+		assertFalse(IterableExtensions.contains(list, "element4"));
+		assertFalse(IterableExtensions.contains(list, new String("element4")));
+	}
+	
+	private static class TestableCollection<T> extends ForwardingCollection<T> {
+
+		private Collection<T> original;
+		boolean containsWasCalled;
+		Object containsParameter;
+		
+		public TestableCollection(Collection<T> original) {
+			super();
+			this.original = original;
+		}
+
+		@Override
+		protected Collection<T> delegate() {
+			return original;
+		}
+		
+		@Override
+		public boolean contains(Object object) {
+			containsWasCalled = true;
+			containsParameter = object;
+			return super.contains(object);
+		}
+	}
+	
+	@Test public void testContainsOnCollection() {
+		//GIVEN a collection, declared as an iterable
+		TestableCollection<String> collection = new TestableCollection<String>(newHashSet("element1", "element2", "element3"));
+		
+		//WHEN we call the contains method via the IterableExtensions
+		IterableExtensions.contains(collection, "element1");
+		
+		//THEN we expect that the collection's native contains method was used
+		assertTrue("IterableExtensions.contains didn't use the collection's native contains method",
+					collection.containsWasCalled);
+		assertEquals("element1", collection.containsParameter);
+	}
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/IteratorExtensionsTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/IteratorExtensionsTest.java
new file mode 100644
index 0000000..cd6c74a
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/IteratorExtensionsTest.java
@@ -0,0 +1,417 @@
+/*******************************************************************************
+ * Copyright (c) 2011, 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.xtext.xbase.tests.lib;
+
+import static com.google.common.collect.Lists.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.xtext.xbase.lib.Functions;
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.IteratorExtensions;
+import org.eclipse.xtext.xbase.lib.Pair;
+import org.eclipse.xtext.xbase.lib.Procedures.Procedure2;
+import org.junit.Assert;
+import org.junit.Test;
+
+import com.google.common.collect.Iterators;
+
+/**
+ * @author Sven Efftinge - Initial contribution and API
+ * @author Karsten Thoms - testMap, testFlatMap
+ */
+public class IteratorExtensionsTest extends BaseIterablesIteratorsTest<Iterator<Integer>> {
+	
+	@Test public void testToIterable() throws Exception {
+		ArrayList<String> list = newArrayList("A","B");
+		for (String s : IteratorExtensions.toIterable(list.iterator())) {
+			assertTrue(list.contains(s));
+		}
+	}
+	
+	@Override
+	protected boolean canIterateTwice() {
+		return false;
+	}
+
+	@SuppressWarnings("unchecked")
+	@Override
+	protected Iterator<Integer>[] testData(Integer... elements) {
+		return new Iterator[] { Iterators.forArray(elements) };
+	}
+	
+	@SuppressWarnings("unchecked")
+	@Override
+	protected Iterator<Integer>[] nullableTestData(Integer... elements) {
+		return new Iterator[] { Iterators.forArray(elements) };
+	}
+
+	@Override
+	protected Iterator<Integer> dummy() {
+		return Collections.<Integer>emptyList().iterator();
+	}
+
+	@Override
+	protected boolean is(Iterator<Integer> input, Integer... elements) {
+		return Iterators.elementsEqual(input, Iterators.forArray(elements));
+	}
+
+	@Override
+	protected Iterator<Integer> operator_plus(Iterator<Integer> first, Iterator<Integer> second) {
+		return IteratorExtensions.operator_plus(first, second);
+	}
+
+	@Override
+	protected Integer findFirst(Iterator<Integer> input, Function1<Integer, Boolean> filter) {
+		return IteratorExtensions.findFirst(input, filter);
+	}
+
+	@Override
+	protected Integer findLast(Iterator<Integer> input, Function1<Integer, Boolean> filter) {
+		return IteratorExtensions.findLast(input, filter);
+	}
+
+	@Override
+	protected Integer last(Iterator<Integer> input) {
+		return IteratorExtensions.last(input);
+	}
+
+	@Override
+	protected Integer head(Iterator<Integer> input) {
+		return IteratorExtensions.head(input);
+	}
+	
+	@Override
+	protected void forEach(Iterator<Integer> input, Procedure2<Integer, Integer> proc) {
+		IteratorExtensions.forEach(input, proc);
+	}
+	
+	@Override
+	protected Iterator<Integer> takeWhile(Iterator<Integer> input, Function1<Integer, Boolean> filter) {
+		return IteratorExtensions.takeWhile(input, filter);
+	}
+	
+	@Override
+	protected Iterator<Integer> dropWhile(Iterator<Integer> input, Function1<Integer, Boolean> filter) {
+		return IteratorExtensions.dropWhile(input, filter);
+	}
+	
+	@Override
+	protected Integer max(Iterator<Integer> input) {
+		return IteratorExtensions.max(input);
+	}
+	
+	@Override
+	protected Integer max(Iterator<Integer> input, Comparator<? super Integer> comparator) {
+		return IteratorExtensions.max(input, comparator);
+	}
+	
+	@Override
+	protected Integer maxBy(Iterator<Integer> input, Function1<? super Integer, String> compareBy) {
+		return IteratorExtensions.maxBy(input, compareBy);
+	}
+	
+	@Override
+	protected Integer min(Iterator<Integer> input) {
+		return IteratorExtensions.min(input);
+	}
+	
+	@Override
+	protected Integer min(Iterator<Integer> input, Comparator<? super Integer> comparator) {
+		return IteratorExtensions.min(input, comparator);
+	}
+	
+	@Override
+	protected Integer minBy(Iterator<Integer> input, Function1<? super Integer, String> compareBy) {
+		return IteratorExtensions.minBy(input, compareBy);
+	}
+	
+	@Test public void testIndexed() {
+		Iterator<Pair<Integer, String>> result = IteratorExtensions.indexed(newArrayList("foo", "bar").iterator());
+		assertEquals(new Pair<Integer, String>(0, "foo"), result.next());
+		assertEquals(new Pair<Integer, String>(1, "bar"), result.next());
+		assertFalse(result.hasNext());
+	}
+	
+	@Test
+	public void testToMap() {
+		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
+		pairs.add(new Pair<Integer, String>(1, "A"));
+		pairs.add(new Pair<Integer, String>(1, "a"));
+		pairs.add(new Pair<Integer, String>(2, "B"));
+		pairs.add(new Pair<Integer, String>(2, "b"));
+		Function1<Pair<Integer, String>, Integer> computeKeys = new Function1<Pair<Integer, String>, Integer>() {
+
+			@Override
+			public Integer apply(Pair<Integer, String> p) {
+				return p.getKey();
+			}
+		};
+		Map<Integer, Pair<Integer, String>> map = IteratorExtensions.toMap(pairs.iterator(), computeKeys);
+		Assert.assertEquals("Expected grouped map size", 2, map.size());
+		Assert.assertTrue("Contains 1 as key", map.keySet().contains(1));
+		Assert.assertEquals("Contains entry 1->a for key 1", map.get(1), new Pair<Integer, String>(1, "a"));
+		Assert.assertTrue("Contains 2 as key", map.keySet().contains(2));
+		Assert.assertEquals("Contains entry 2->b for key 2", map.get(2), new Pair<Integer, String>(2, "b"));
+	}
+
+	@Test
+	public void testToMap__WhenEmptyList() {
+		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
+		Function1<Pair<Integer, String>, Integer> computeKeys = new Function1<Pair<Integer, String>, Integer>() {
+
+			@Override
+			public Integer apply(Pair<Integer, String> p) {
+				return p.getKey();
+			}
+		};
+		Map<Integer, Pair<Integer, String>> map = IteratorExtensions.toMap(pairs.iterator(), computeKeys);
+		Assert.assertEquals("Expected grouped map size", 0, map.size());
+	}
+
+	@Test
+	public void testToMap__WhenCalculatedKeyNull() {
+		List<String> names = new ArrayList<String>();
+		names.add("Mueller");
+		names.add("Schneider");
+		names.add("Schmidt");
+		names.add("Koch");
+		Function1<String, String> computeKeys = new Function1<String, String>() {
+
+			@Override
+			public String apply(String p) {
+				return p.contains("y") ? "y" : null;
+			}
+		};
+		Map<String, String> map = IteratorExtensions.toMap(names.iterator(), computeKeys);
+		Assert.assertEquals("Expected grouped map size", 1, map.size());
+		Assert.assertTrue("Contains null as key", map.keySet().contains(null));
+		Assert.assertEquals("Contains entry Koch for key null", "Koch", map.get(null));
+	}
+
+	@Test
+	public void testToMap__WhenNoValuesForKey() {
+		List<String> names = new ArrayList<String>();
+		names.add("Mueller");
+		names.add("Schneider");
+		names.add("Schmidt");
+		names.add("Koch");
+		Function1<String, Boolean> computeKeys = new Function1<String, Boolean>() {
+
+			@Override
+			public Boolean apply(String p) {
+				return p.contains("y");
+			}
+		};
+		Map<Boolean, String> map = IteratorExtensions.toMap(names.iterator(), computeKeys);
+		Assert.assertEquals("Expected grouped map size", 1, map.size());
+		Assert.assertTrue("Contains FALSE as key", map.keySet().contains(Boolean.FALSE));
+		Assert.assertTrue("Contains entry Mueller for key FALSE", map.get(Boolean.FALSE).equals("Koch"));
+		Assert.assertNull("Contains no entry for key Boolean.TRUE", map.get(Boolean.TRUE));
+	}
+
+	@Test(expected = NullPointerException.class)
+	public void testToMap__WhenFunctionNull() {
+		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
+		Function1<Pair<Integer, String>, Integer> computeKeys = null;
+		IteratorExtensions.toMap(pairs.iterator(), computeKeys);
+	}	
+	
+	@Test
+	public void testGroupBy() {
+		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
+		pairs.add(new Pair<Integer, String>(1, "A"));
+		pairs.add(new Pair<Integer, String>(1, "a"));
+		pairs.add(new Pair<Integer, String>(2, "B"));
+		pairs.add(new Pair<Integer, String>(2, "b"));
+		Function1<Pair<Integer, String>, Integer> computeKeys = new Function1<Pair<Integer, String>, Integer>() {
+
+			@Override
+			public Integer apply(Pair<Integer, String> p) {
+				return p.getKey();
+			}
+		};
+		Map<Integer, List<Pair<Integer, String>>> map = IteratorExtensions.groupBy(pairs.iterator(), computeKeys);
+		Assert.assertEquals("Expected grouped map size", 2, map.size());
+		Assert.assertTrue("Contains 1 as key", map.keySet().contains(1));
+		Assert.assertEquals("Contains 2 entries for key 1", 2, map.get(1).size());
+		Assert.assertEquals("Contains entry 1->A for key 1", new Pair<Integer, String>(1, "A"), map.get(1).get(0));
+		Assert.assertEquals("Contains entry 1->a for key 1", new Pair<Integer, String>(1, "a"), map.get(1).get(1));
+		Assert.assertTrue("Contains 2 as key", map.keySet().contains(2));
+		Assert.assertEquals("Contains 2 entries for key 2", 2, map.get(2).size());
+		Assert.assertEquals("Contains entry 2->B for key 2", new Pair<Integer, String>(2, "B"), map.get(2).get(0));
+		Assert.assertEquals("Contains entry 2->b for key 2", new Pair<Integer, String>(2, "b"), map.get(2).get(1));
+	}
+
+	@Test
+	public void testGroupBy__WhenEmptyList() {
+		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
+		Function1<Pair<Integer, String>, Integer> computeKeys = new Function1<Pair<Integer, String>, Integer>() {
+
+			@Override
+			public Integer apply(Pair<Integer, String> p) {
+				return p.getKey();
+			}
+		};
+		Map<Integer, List<Pair<Integer, String>>> map = IteratorExtensions.groupBy(pairs.iterator(), computeKeys);
+		Assert.assertEquals("Expected grouped map size", 0, map.size());
+	}
+
+	@Test
+	public void testGroupBy__WhenCalculatedKeyNull() {
+		List<String> names = new ArrayList<String>();
+		names.add("Mueller");
+		names.add("Schneider");
+		names.add("Schmidt");
+		names.add("Koch");
+		Function1<String, String> computeKeys = new Function1<String, String>() {
+
+			@Override
+			public String apply(String p) {
+				return p.contains("y") ? "y" : null;
+			}
+		};
+		Map<String, List<String>> map = IteratorExtensions.groupBy(names.iterator(), computeKeys);
+		Assert.assertEquals("Expected grouped map size", 1, map.size());
+		Assert.assertTrue("Contains null as key", map.keySet().contains(null));
+		Assert.assertEquals("Contains 4 entries for key null", 4, map.get(null).size());
+	}
+
+	@Test
+	public void testGroupBy__WhenNoValuesForKey() {
+		List<String> names = new ArrayList<String>();
+		names.add("Mueller");
+		names.add("Schneider");
+		names.add("Schmidt");
+		names.add("Koch");
+		Function1<String, Boolean> computeKeys = new Function1<String, Boolean>() {
+
+			@Override
+			public Boolean apply(String p) {
+				return p.contains("y");
+			}
+		};
+		Map<Boolean, List<String>> map = IteratorExtensions.groupBy(names.iterator(), computeKeys);
+		Assert.assertEquals("Expected grouped map size", 1, map.size());
+		Assert.assertTrue("Contains FALSE as key", map.keySet().contains(Boolean.FALSE));
+		Assert.assertEquals("Contains 4 entries for key Boolean.FALSE", 4, map.get(Boolean.FALSE).size());
+		Assert.assertTrue("Contains entry Mueller for key FALSE", map.get(Boolean.FALSE).contains("Mueller"));
+		Assert.assertNull("Contains no entry for key Boolean.TRUE", map.get(Boolean.TRUE));
+	}
+
+	@Test(expected = NullPointerException.class)
+	public void testGroupBy__WhenFunctionNull() {
+		List<Pair<Integer, String>> pairs = new ArrayList<Pair<Integer, String>>();
+		Function1<Pair<Integer, String>, Integer> computeKeys = null;
+		IteratorExtensions.groupBy(pairs.iterator(), computeKeys);
+	}
+
+	@Test public void testReject() {
+		Function1<Integer, Boolean> function = new Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return p % 2 == 0;
+			}
+		};
+		assertEquals(newArrayList(1,3,5),newArrayList(IteratorExtensions.reject(newArrayList(1,2,3,4,5).iterator(), function)));
+		Function1<Integer, Boolean> functionNullSafe = new Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return p == null || p % 2 == 0;
+			}
+		};
+		assertEquals(newArrayList(1,5),newArrayList(IteratorExtensions.reject(newArrayList(1,2,null,4,5).iterator(), functionNullSafe)));
+		try {
+			newArrayList(IteratorExtensions.reject(null, function));
+			fail("NullPointerException expected");
+		} catch (NullPointerException e) {
+			// expected NPE
+		}
+		try {
+			newArrayList(IteratorExtensions.reject(newArrayList(1,2,3).iterator(), null));
+			fail("NullPointerException expected");
+		} catch (NullPointerException e) {
+			// expected NPE
+		}
+		Function1<Integer, Boolean> brokenFunction = new Function1<Integer, Boolean>() {
+			@Override
+			public Boolean apply(Integer p) {
+				return null;
+			}
+		};
+		try {
+			newArrayList(IteratorExtensions.reject(newArrayList(1,2,3).iterator(), brokenFunction));
+			fail("NullPointerException expected");
+		} catch (NullPointerException e) {
+			// expected NPE
+		}
+	}
+
+	@Test public void testMap () {
+		ArrayList<String> list = newArrayList("foo", "bar");
+		
+		final Functions.Function1<String, String> function = new Functions.Function1<String, String>() {
+			@Override
+			public String apply(String p) {
+				return "Hello "+p;
+			}
+		};
+		
+		assertEquals(newArrayList("Hello foo", "Hello bar"), newArrayList(IteratorExtensions.map(list.iterator(), function)));
+
+	
+		// test that the returned iterator supports remove on the underyling list
+		// therefore we need a function that maps to the same object contained in the list
+		final Functions.Function1<String, String> functionForRemove = new Functions.Function1<String, String>() {
+			@Override
+			public String apply(String p) {
+				return "foo".equals(p) ? p : "Hello "+p;
+			}
+		};
+
+		assertTrue(list.contains("foo"));
+		assertEquals(2, list.size());
+		assertEquals(newArrayList("foo", "Hello bar"), newArrayList(IteratorExtensions.map(list.iterator(), functionForRemove)));
+		Iterator<String> iterator = IteratorExtensions.map(list.iterator(), functionForRemove);
+		iterator.next();
+		iterator.remove();
+		
+		assertTrue(!list.contains("foo"));
+		assertEquals(1, list.size());
+	}
+
+	@Test public void testFlatMap () {
+		ArrayList<String> list = newArrayList("foo", "bar");
+		
+		final Functions.Function1<String, Iterator<String>> function = new Functions.Function1<String, Iterator<String>>() {
+			@Override
+			public Iterator<String> apply(String p) {
+				return newArrayList("Hello", p).iterator();
+			}
+		};
+		assertEquals(newArrayList("Hello", "foo", "Hello", "bar"), newArrayList(IteratorExtensions.flatMap(list.iterator(), function)));
+	}
+	
+	@Test public void testContains() {
+		ArrayList<String> list = newArrayList("element1", "element2", "element3", null);
+		
+		assertTrue(IteratorExtensions.contains(list.iterator(), "element3"));
+		assertTrue(IteratorExtensions.contains(list.iterator(), new String("element3")));
+		
+		assertTrue(IteratorExtensions.contains(list.iterator(), null));
+		
+		assertFalse(IteratorExtensions.contains(list.iterator(), "element4"));
+		assertFalse(IteratorExtensions.contains(list.iterator(), new String("element4")));
+	}
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/MapExtensionsTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/MapExtensionsTest.java
new file mode 100644
index 0000000..9e91794
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/MapExtensionsTest.java
@@ -0,0 +1,471 @@
+/*******************************************************************************
+ * Copyright (c) 2017 Universite de Technologie de Belfort-Montbeliard (http://www.utbm.fr) 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.tests.lib;
+
+import static org.eclipse.xtext.xbase.lib.MapExtensions.*;
+import static org.junit.Assert.*;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+import java.util.Map.Entry;
+
+import com.google.common.collect.Maps;
+import com.google.common.collect.testing.MapTestSuiteBuilder;
+import com.google.common.collect.testing.TestStringMapGenerator;
+import com.google.common.collect.testing.features.CollectionFeature;
+import com.google.common.collect.testing.features.CollectionSize;
+import com.google.common.collect.testing.features.MapFeature;
+import junit.framework.TestSuite;
+import org.eclipse.xtext.xbase.lib.Pair;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+import org.eclipse.xtext.xbase.lib.internal.UnmodifiableMergingMapView;
+
+/**
+ * @author Stephane Galland - Initial contribution and API
+ * @since 2.15
+ */
+@SuppressWarnings("all")
+@RunWith(Suite.class)
+@SuiteClasses({
+	MapExtensionsTest.ManualTest.class,
+	MapExtensionsTest.GuavaTest.class,
+})
+public class MapExtensionsTest {
+
+	public static class GuavaTest {
+		public static TestSuite suite() {
+			return MapTestSuiteBuilder
+					// The create method is called with an array of elements
+					// that should populate the collection.
+					.using(new TestStringMapGenerator() {
+						@Override
+						protected Map<String, String> create(Entry<String, String>[] source) {
+							Map<String, String> left = Maps.newHashMap();
+							Map<String, String> right = Maps.newHashMap();
+							for(int i = 0; i < source.length; i++) {
+								Entry<String, String> entry = source[i];
+								if (right.containsKey(entry.getKey())) {
+									left.put(entry.getKey(), right.get(entry.getKey()));
+									right.put(entry.getKey(), entry.getValue());
+								} else if (i % 2 != 0) {
+									left.put(entry.getKey(), entry.getValue());	
+								} else {
+									right.put(entry.getKey(), entry.getValue());
+									if (i % 4 != 0) {
+										left.put(entry.getKey(), "will be ignored");
+									}
+								}
+							}
+							return new UnmodifiableMergingMapView(left, right);
+						}
+					}).named("Guava-based UnmodifiableMergingMapView tests")
+					.withFeatures(
+							MapFeature.ALLOWS_NULL_KEYS,
+							MapFeature.ALLOWS_NULL_VALUES,
+							MapFeature.ALLOWS_ANY_NULL_QUERIES,
+							MapFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
+							CollectionFeature.ALLOWS_NULL_QUERIES,
+							CollectionFeature.FAILS_FAST_ON_CONCURRENT_MODIFICATION,
+							CollectionSize.ANY)
+					.createTestSuite();
+		}
+	}
+
+	public static class ManualTest {
+
+		private Map<String, String> map;
+		private String key1;
+		private String key2;
+		private String value1;
+		private String value2;
+	
+		@Before
+		public void setUp() {
+			this.map = new HashMap<String, String>();
+			this.key1 = "k1"; //$NON-NLS-1$
+			this.key2 = "k2"; //$NON-NLS-1$
+			this.value1 = UUID.randomUUID().toString();
+			this.value2 = UUID.randomUUID().toString();
+			this.map.put(this.key1, this.value1);
+			this.map.put(this.key2, this.value2);
+		}
+	
+		@After
+		public void tearDown() {
+			this.key1 = this.value1 = null;
+			this.key2 = this.value2 = null;
+			this.map = null;
+		}
+	
+		@Test
+		public void operator_add_MapPair_0() {
+			String v = UUID.randomUUID().toString();
+			String o;
+	
+			o = operator_add(this.map, new Pair<String, String>("k3", v));
+			assertNull(o);
+			assertEquals(3, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertEquals(v, this.map.get("k3"));
+		}
+	
+		@Test
+		public void operator_add_MapPair_1() {
+			String v = UUID.randomUUID().toString();
+			String o;
+	
+			o = operator_add(this.map, new Pair<String, String>("k2", v));
+			assertEquals(this.value2, o);
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(v, this.map.get("k2"));
+		}
+	
+		@Test
+		public void operator_remove_MapPair_0() {
+			String v = UUID.randomUUID().toString();
+			boolean o;
+	
+			o = operator_remove(this.map, new Pair<String, String>("k3", v));
+			assertFalse(o);
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+		}
+	
+		@Test
+		public void operator_remove_MapPair_1() {
+			String v = UUID.randomUUID().toString();
+			boolean o;
+	
+			o = operator_remove(this.map, new Pair<String, String>("k2", v));
+			assertFalse(o);
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+		}
+	
+		@Test
+		public void operator_remove_MapPair_2() {
+			String v = UUID.randomUUID().toString();
+			boolean o;
+	
+			o = operator_remove(this.map, new Pair<String, String>("k2", new String(this.value2)));
+			assertTrue(o);
+			assertEquals(1, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertNull(this.map.get("k2"));
+		}
+	
+		@Test
+		public void operator_plus_MapPair_0() {
+			String v = UUID.randomUUID().toString();
+			Map<String, String> o;
+	
+			o = operator_plus(this.map, new Pair<String, String>("k3", v));
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertEquals(3, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertEquals(this.value2, o.get("k2"));
+			assertEquals(v, o.get("k3"));
+		}
+	
+		@Test
+		public void operator_plus_MapPair_1() {
+			String v = UUID.randomUUID().toString();
+			Map<String, String> o = operator_plus(this.map, new Pair<String, String>("k2", v));
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertNull(this.map.get("k3"));
+			assertEquals(2, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertEquals(v, o.get("k2"));
+			assertNull(o.get("k3"));
+		}
+	
+		@Test
+		public void operator_minus_MapPair_0() {
+			String v = UUID.randomUUID().toString();
+			Map<String, String> o;
+	
+			o = operator_minus(this.map, new Pair<String, String>("k3", v));
+	
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertNull(this.map.get("k3"));
+			
+			assertEquals(2, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertEquals(this.value2, o.get("k2"));
+			assertNull(o.get("k3"));
+		}
+	
+		@Test
+		public void operator_minus_MapPair_1() {
+			String v = UUID.randomUUID().toString();
+			Map<String, String> o = operator_minus(this.map, new Pair<String, String>("k2", v));
+			
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertNull(this.map.get("k3"));
+			
+			assertEquals(2, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertEquals(this.value2, o.get("k2"));
+			assertNull(o.get("k3"));
+		}
+	
+		@Test
+		public void operator_minus_MapPair_2() {
+			String v = UUID.randomUUID().toString();
+			Map<String, String> o = operator_minus(this.map, new Pair<String, String>("k2", new String(this.value2)));
+			
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertNull(this.map.get("k3"));
+			
+			assertEquals(1, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertNull(o.get("k2"));
+			assertNull(o.get("k3"));
+		}
+	
+		@Test
+		public void operator_plus_MapMap_0() {
+			String v1 = UUID.randomUUID().toString();
+			String v2 = UUID.randomUUID().toString();
+			String v3 = UUID.randomUUID().toString();
+			Map<String, String> o;
+	
+			Map<String, String> tmp = new HashMap<String, String>();
+			tmp.put("k3", v1);
+			tmp.put("k4", v2);
+			tmp.put("k5", v3);
+	
+			o = operator_plus(this.map, tmp);
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			assertNotSame(tmp, o);
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertEquals(3, tmp.size());
+			assertEquals(v1, tmp.get("k3"));
+			assertEquals(v2, tmp.get("k4"));
+			assertEquals(v3, tmp.get("k5"));
+			assertEquals(5, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertEquals(this.value2, o.get("k2"));
+			assertEquals(v1, o.get("k3"));
+			assertEquals(v2, o.get("k4"));
+			assertEquals(v3, o.get("k5"));
+		}
+	
+		@Test
+		public void operator_plus_MapMap_1() {
+			String v1 = UUID.randomUUID().toString();
+			String v2 = UUID.randomUUID().toString();
+			String v3 = UUID.randomUUID().toString();
+			Map<String, String> o;
+	
+			Map<String, String> tmp = new HashMap<String, String>();
+			tmp.put("k3", v1);
+			tmp.put("k4", v2);
+			tmp.put("k5", v3);
+	
+			o = operator_plus(tmp, this.map);
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			assertNotSame(tmp, o);
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertEquals(3, tmp.size());
+			assertEquals(v1, tmp.get("k3"));
+			assertEquals(v2, tmp.get("k4"));
+			assertEquals(v3, tmp.get("k5"));
+			assertEquals(5, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertEquals(this.value2, o.get("k2"));
+			assertEquals(v1, o.get("k3"));
+			assertEquals(v2, o.get("k4"));
+			assertEquals(v3, o.get("k5"));
+		}
+	
+		@Test
+		public void operator_plus_MapMap_2() {
+			String v1 = UUID.randomUUID().toString();
+			String v2 = UUID.randomUUID().toString();
+			String v3 = UUID.randomUUID().toString();
+			Map<String, String> o;
+	
+			Map<String, String> tmp = new HashMap<String, String>();
+			tmp.put("k3", v1);
+			tmp.put("k1", v2);
+			tmp.put("k5", v3);
+	
+			o = operator_plus(this.map, tmp);
+			assertNotNull(o);
+			assertEquals(4, o.size());
+			assertEquals(v2, o.get("k1"));
+			assertEquals(this.value2, o.get("k2"));
+			assertEquals(v1, o.get("k3"));
+			assertNull(o.get("k4"));
+			assertEquals(v3, o.get("k5"));
+		}
+	
+		@Test
+		public void operator_plus_MapMap_3() {
+			String v1 = UUID.randomUUID().toString();
+			String v2 = UUID.randomUUID().toString();
+			String v3 = UUID.randomUUID().toString();
+			Map<String, String> o;
+	
+			Map<String, String> tmp = new HashMap<String, String>();
+			tmp.put("k3", v1);
+			tmp.put("k1", v2);
+			tmp.put("k5", v3);
+	
+			o = operator_plus(tmp, this.map);
+			assertNotNull(o);
+			assertEquals(4, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertEquals(this.value2, o.get("k2"));
+			assertEquals(v1, o.get("k3"));
+			assertNull(o.get("k4"));
+			assertEquals(v3, o.get("k5"));
+		}
+	
+		@Test
+		public void operator_remove_MapK_0() {
+			String o = operator_remove(this.map, "k0");
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertNull(o);
+		}
+	
+		@Test
+		public void operator_remove_MapK_1() {
+			String o = operator_remove(this.map, "k1");
+			assertEquals(1, this.map.size());
+			assertNull(this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertEquals(this.value1, o);
+		}
+	
+		@Test
+		public void operator_remove_MapK_2() {
+			String o = operator_remove(this.map, "k2");
+			assertEquals(1, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertNull(this.map.get("k2"));
+			assertEquals(this.value2, o);
+		}
+	
+		@Test
+		public void operator_remove_MapK_3() {
+			String o1 = operator_remove(this.map, "k2");
+			String o2 = operator_remove(this.map, "k1");
+			assertEquals(0, this.map.size());
+			assertNull(this.map.get("k1"));
+			assertNull(this.map.get("k2"));
+			assertEquals(this.value2, o1);
+			assertEquals(this.value1, o2);
+		}
+	
+		@Test
+		public void operator_remove_MapIterable() {
+			List<String> m = new ArrayList<String>();
+			m.add("k0");
+			m.add("k1");
+			operator_remove(this.map, m);
+			assertEquals(1, this.map.size());
+			assertNull(this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+		}
+	
+		@Test
+		public void operator_minus_MapK_0() {
+			Map<String, String> o = operator_minus(this.map, "k0");
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			assertEquals(2, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertEquals(this.value2, o.get("k2"));
+		}
+	
+		@Test
+		public void operator_minus_MapK_1() {
+			Map<String, String> o = operator_minus(this.map, "k2");
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertNotNull(o);
+			assertNotSame(this.map, o);
+			assertEquals(1, o.size());
+			assertEquals(this.value1, o.get("k1"));
+			assertNull(o.get("k2"));
+		}
+	
+		@Test
+		public void operator_minus_MapK_2() {
+			Map<String, String> o1 = operator_minus(this.map, "k2");
+			Map<String, String> o2 = operator_minus(o1, "k1");
+			assertEquals(2, this.map.size());
+			assertEquals(this.value1, this.map.get("k1"));
+			assertEquals(this.value2, this.map.get("k2"));
+			assertNotNull(o1);
+			assertNotSame(this.map, o1);
+			assertEquals(1, o1.size());
+			assertEquals(this.value1, o1.get("k1"));
+			assertNull(o1.get("k2"));
+			assertNotNull(o2);
+			assertNotSame(this.map, o2);
+			assertEquals(0, o2.size());
+			assertNull(o2.get("k1"));
+			assertNull(o2.get("k2"));
+		}
+
+	}
+
+}
+
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/StringConcatenationTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/StringConcatenationTest.java
new file mode 100644
index 0000000..ac06803
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/StringConcatenationTest.java
@@ -0,0 +1,333 @@
+/*******************************************************************************
+ * Copyright (c) 2016, 2017 Pantheon Technologies, s.r.o. 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.tests.lib;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertTrue;
+
+import java.lang.reflect.Field;
+
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtend2.lib.StringConcatenationClient;
+import org.junit.Test;
+
+public class StringConcatenationTest {
+    // Utility class wrapping a String
+    private static final class StringObject extends Object {
+        final String string;
+
+        StringObject(final String string) {
+            this.string = string;
+        }
+
+        @Override
+        public String toString() {
+            return string;
+        }
+    }
+
+    @Test
+    public void testEmpty() {
+        assertEquals("", new StringConcatenation().toString());
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testNullDelimiter() {
+        new StringConcatenation(null);
+    }
+
+    @Test(expected=IllegalArgumentException.class)
+    public void testEmptyDelimiter() {
+        new StringConcatenation("");
+    }
+
+    @Test
+    public void testAppendObjectNull() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append((Object)null);
+        c.append((Object)null, "");
+        c.append((Object)null, " ");
+        assertEquals("", c.toString());
+    }
+
+    @Test
+    public void testAppendStringNull() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append((String)null);
+        c.append((String)null, "");
+        c.append((String)null, " ");
+        assertEquals("", c.toString());
+    }
+
+    @Test
+    public void testAppendStringConcatNull() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append((StringConcatenation)null);
+        c.append((StringConcatenation)null, "");
+        c.append((StringConcatenation)null, " ");
+        assertEquals("", c.toString());
+    }
+
+    @Test
+    public void testAppendStringConcatClientNull() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append((StringConcatenationClient)null);
+        c.append((StringConcatenationClient)null, "");
+        c.append((StringConcatenationClient)null, " ");
+        assertEquals("", c.toString());
+    }
+
+    @Test
+    public void testAppendNullToString() {
+        final Object o = new StringObject(null);
+        final StringConcatenation c = new StringConcatenation();
+        c.append(o);
+        c.append(o, "");
+        assertEquals("", new StringConcatenation().toString());
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void testAppendWithNullIndent() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append("a", null);
+    }
+
+    @Test(expected=NullPointerException.class)
+    public void testAppendNullWithNullIndent() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append((Object)null, null);
+    }
+
+    @Test
+    public void testStringConcat() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append("a");
+        c.append("b");
+        c.append("c");
+        assertEquals("abc", c.toString());
+    }
+
+    @Test
+    public void testMaskedStringConcat() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append((Object)"a");
+        c.append((Object)"b");
+        c.append((Object)"c");
+        assertEquals("abc", c.toString());
+    }
+
+    @Test
+    public void testMixedConcat() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append("a");
+        c.append(Character.valueOf('b'));
+        c.append(new StringObject("c"));
+        assertEquals("abc", c.toString());
+    }
+
+    @Test
+    public void testCharSequenceMethods() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append("a");
+        c.append("b");
+        c.append("c");
+
+        assertEquals(3, c.length());
+        assertEquals('a', c.charAt(0));
+        assertEquals('b', c.charAt(1));
+        assertEquals("ab", c.subSequence(0, 2));
+        assertEquals("bc", c.subSequence(1, 3));
+    }
+
+    @Test
+    public void testNoindentConcat() {
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.append("a\n");
+        c.append("b\r");
+        c.append("c\n");
+        assertEquals("a\nb\nc\n", c.toString());
+    }
+
+    @Test
+    public void testIndentConcat() {
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.append("a\n", " ");
+        c.append("b\r", "  ");
+        c.append("c\nd", "   ");
+        assertEquals("a\n b\n  c\n   d", c.toString());
+    }
+
+    @Test
+    public void testMaskedIndentConcat() {
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.append((Object)"a\n", " ");
+        c.append((Object)"b\r", "  ");
+        c.append((Object)"c\nd", "   ");
+        assertEquals("a\n b\n  c\n   d", c.toString());
+    }
+
+    @Test
+    public void testObjectIndentConcat() {
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.append(new StringObject("a\n"), " ");
+        c.append(new StringObject("b\r"), "  ");
+        c.append(new StringObject("c\nd"), "   ");
+        assertEquals("a\n b\n  c\n   d", c.toString());
+    }
+
+    @Test
+    public void testNewLine() {
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.newLine();
+        c.append("a");
+        c.newLine();
+        assertEquals("\na\n", c.toString());
+    }
+
+    @Test
+    public void testNewLineIfNotEmpty() {
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.newLineIfNotEmpty();
+        c.append("a");
+        c.newLineIfNotEmpty();
+        c.append("b\n");
+        c.newLineIfNotEmpty();
+        c.append("  ");
+        c.newLineIfNotEmpty();
+        assertEquals("a\nb\n", c.toString());
+    }
+
+    @Test
+    public void testCachedToString() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append("a");
+        c.append("b\n");
+
+        final String str = c.toString();
+        assertSame(str, c.toString());
+    }
+
+    @Test
+    public void testAppendEmptyConcat() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append(new StringConcatenation());
+        assertEquals("", c.toString());
+        c.append(new StringConcatenation(), "  ");
+        assertEquals("", c.toString());
+    }
+
+    @Test
+    public void testAppendConcat() {
+        final StringConcatenation toAppend = new StringConcatenation("\n");
+        toAppend.append("a\n");
+        toAppend.append("b");
+
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.append(toAppend);
+        assertEquals("a\nb", c.toString());
+    }
+
+    @Test
+    public void testAppendConcatSeparator() {
+        final StringConcatenation toAppend = new StringConcatenation("\t");
+        toAppend.append("a\t");
+        toAppend.append("b");
+
+        final StringConcatenation c = new StringConcatenation();
+        c.append(toAppend);
+        assertEquals("a\tb", c.toString());
+    }
+
+    @Test
+    public void testAppendEmptyConcatSeparator() {
+        final StringConcatenation c = new StringConcatenation();
+        c.append(new StringConcatenation("\t"));
+        assertEquals("", c.toString());
+    }
+
+    @Test
+    public void testAppendMaskedConcat() {
+        final StringConcatenation toAppend = new StringConcatenation("\n");
+        toAppend.append("a\n");
+        toAppend.append("b");
+
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.append((Object)toAppend);
+        assertEquals("a\nb", c.toString());
+    }
+
+    @Test
+    public void testAppendMaskedIndentConcat() {
+        final StringConcatenation toAppend = new StringConcatenation("\n");
+        toAppend.append("a\n");
+        toAppend.append("b");
+
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.append((Object)toAppend, " ");
+        assertEquals("a\n b", c.toString());
+    }
+
+    @Test
+    public void testAppendImmediateSimple() {
+        final StringConcatenation c = new StringConcatenation();
+        c.appendImmediate("a", "  ");
+        assertEquals("a", c.toString());
+    }
+
+    @Test
+    public void testAppendImmediateComplex() {
+        final StringConcatenation c = new StringConcatenation("\n");
+        c.append("a\n");
+        c.append(" b   ");
+        c.newLineIfNotEmpty();
+        c.append("    ");
+        c.appendImmediate("c\nd", "  ");
+        assertEquals("a\n b   c\n  d\n", c.toString());
+    }
+
+    @Test
+    public void testGrowInChunks() throws Exception {
+        // This is rather ugly, but gets the job done. It would be much cleaner if this test were in the same
+        // package as the class being tested...
+        final Field lss = StringConcatenation.class.getDeclaredField("lastSegmentsSize");
+        lss.setAccessible(true);
+
+        final StringConcatenation c = new StringConcatenation();
+        final int initialSize = lss.getInt(c);
+        assertTrue(initialSize >= 0);
+
+        for (int i = 0; i < initialSize; ++i) {
+            c.append("a");
+        }
+
+        // No reallocation should happen
+        assertEquals(initialSize, lss.getInt(c));
+
+        // This should trigger pre-allocation
+        c.append("b");
+        final int firstGrown = lss.getInt(c);
+        assertTrue(firstGrown > initialSize);
+
+        // The delta needs to be a power-of-two
+        final int deltaSize = firstGrown - initialSize;
+        assertEquals(1, Integer.bitCount(deltaSize));
+
+        // Now just to make sure, append another set
+        final StringConcatenation batch = new StringConcatenation();
+        for (int i = 1; i < deltaSize * 2; ++i) {
+            batch.newLine();
+        }
+        c.append(batch);
+
+        final int secondGrown = lss.getInt(c);
+        assertTrue(firstGrown < secondGrown);
+        assertEquals(deltaSize, secondGrown - firstGrown);
+    }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringBuilderTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringBuilderTest.java
new file mode 100644
index 0000000..dff34e2
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringBuilderTest.java
@@ -0,0 +1,271 @@
+/**
+ * Copyright (c) 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.xtext.xbase.tests.lib.internal;
+
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import org.eclipse.xtend.lib.annotations.Accessors;
+import org.eclipse.xtend.lib.annotations.ToString;
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.Pure;
+import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * @author Karsten Thoms - Initial contribution and API
+ */
+@SuppressWarnings("all")
+public class ToStringBuilderTest {
+  public static class OtherClass {
+    public ToStringBuilderTest.OtherClass other;
+    
+    public String name;
+  }
+  
+  @Accessors
+  @ToString
+  public static class DataClass {
+    public ToStringBuilderTest.DataClass other;
+    
+    public String name;
+    
+    @Pure
+    public ToStringBuilderTest.DataClass getOther() {
+      return this.other;
+    }
+    
+    public void setOther(final ToStringBuilderTest.DataClass other) {
+      this.other = other;
+    }
+    
+    @Pure
+    public String getName() {
+      return this.name;
+    }
+    
+    public void setName(final String name) {
+      this.name = name;
+    }
+    
+    @Override
+    @Pure
+    public String toString() {
+      ToStringBuilder b = new ToStringBuilder(this);
+      b.add("other", this.other);
+      b.add("name", this.name);
+      return b.toString();
+    }
+  }
+  
+  public static class MyEntity {
+    private final boolean boolProp = true;
+    
+    private final int intProp = 42;
+    
+    private final ArrayList<String> myList = CollectionLiterals.<String>newArrayList("foo", "bar", "baz");
+    
+    private final ToStringBuilderTest.MyEntity friend;
+    
+    private final RetentionPolicy policy = RetentionPolicy.CLASS;
+    
+    public MyEntity() {
+      this.friend = null;
+    }
+    
+    public MyEntity(final ToStringBuilderTest.MyEntity friend) {
+      this.friend = friend;
+    }
+    
+    @Override
+    public String toString() {
+      String _plus = (Boolean.valueOf(this.boolProp) + "\n");
+      String _plus_1 = (_plus + Integer.valueOf(this.intProp));
+      String _plus_2 = (_plus_1 + "\n");
+      String _plus_3 = (_plus_2 + this.myList);
+      String _plus_4 = (_plus_3 + "\n");
+      String _plus_5 = (_plus_4 + this.friend);
+      String _plus_6 = (_plus_5 + "\n");
+      return (_plus_6 + this.policy);
+    }
+  }
+  
+  @Test
+  public void testToString() {
+    ToStringBuilderTest.MyEntity _myEntity = new ToStringBuilderTest.MyEntity();
+    ToStringBuilderTest.MyEntity _myEntity_1 = new ToStringBuilderTest.MyEntity(_myEntity);
+    final ToStringBuilder builder = new ToStringBuilder(_myEntity_1).addAllFields();
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("MyEntity [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("boolProp = true");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("intProp = 42");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("myList = ArrayList (");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"foo\",");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"bar\",");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"baz\"");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append(")");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("friend = true");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("42");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("[foo, bar, baz]");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("null");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("CLASS");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("policy = CLASS");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringBuilderTest.toUnix(_builder.toString()), builder.toString());
+  }
+  
+  @Test
+  public void testSingleLine() {
+    ToStringBuilderTest.MyEntity _myEntity = new ToStringBuilderTest.MyEntity();
+    final ToStringBuilder builder = new ToStringBuilder(_myEntity).singleLine().addAllFields();
+    Assert.assertEquals(
+      "MyEntity [boolProp = true, intProp = 42, myList = ArrayList (\"foo\",\"bar\",\"baz\"), friend = null, policy = CLASS]", 
+      builder.toString());
+  }
+  
+  @Test
+  public void testHideFieldNames() {
+    ToStringBuilderTest.MyEntity _myEntity = new ToStringBuilderTest.MyEntity();
+    final ToStringBuilder builder = new ToStringBuilder(_myEntity).singleLine().hideFieldNames().addAllFields();
+    Assert.assertEquals("MyEntity [true, 42, ArrayList (\"foo\",\"bar\",\"baz\"), null, CLASS]", builder.toString());
+  }
+  
+  @Test
+  public void testSkipNulls() {
+    ToStringBuilderTest.MyEntity _myEntity = new ToStringBuilderTest.MyEntity();
+    final ToStringBuilder builder = new ToStringBuilder(_myEntity).skipNulls().addAllFields();
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("MyEntity [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("boolProp = true");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("intProp = 42");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("myList = ArrayList (");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"foo\",");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"bar\",");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"baz\"");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append(")");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("policy = CLASS");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringBuilderTest.toUnix(_builder.toString()), builder.toString());
+  }
+  
+  @Test
+  public void testExplicitFieldListing() {
+    ToStringBuilderTest.MyEntity _myEntity = new ToStringBuilderTest.MyEntity();
+    final ToStringBuilder builder = new ToStringBuilder(_myEntity).add("boolProp", Boolean.valueOf(false)).addField("intProp");
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("MyEntity [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("boolProp = false");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("intProp = 42");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringBuilderTest.toUnix(_builder.toString()), builder.toString());
+  }
+  
+  @Test
+  public void recursionHandling() {
+    final ToStringBuilderTest.OtherClass obj = new ToStringBuilderTest.OtherClass();
+    obj.name = "foo";
+    obj.other = obj;
+    final ToStringBuilder builder = new ToStringBuilder(obj).addDeclaredFields();
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("OtherClass [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("other = ");
+    String _string = obj.toString();
+    _builder.append(_string, "  ");
+    _builder.newLineIfNotEmpty();
+    _builder.append("  ");
+    _builder.append("name = \"foo\"");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringBuilderTest.toUnix(_builder.toString()), builder.toString());
+  }
+  
+  @Test
+  public void recursionHandling_02() {
+    final ToStringBuilderTest.DataClass obj = new ToStringBuilderTest.DataClass();
+    obj.other = obj;
+    obj.name = "test";
+    final ToStringBuilder builder = new ToStringBuilder(obj).addDeclaredFields();
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("DataClass [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("other = DataClass@");
+    int _identityHashCode = System.identityHashCode(obj);
+    _builder.append(_identityHashCode, "  ");
+    _builder.newLineIfNotEmpty();
+    _builder.append("  ");
+    _builder.append("name = \"test\"");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringBuilderTest.toUnix(_builder.toString()), builder.toString());
+  }
+  
+  public static String toUnix(final String s) {
+    StringConcatenation result = new StringConcatenation("\n");
+    result.append(s);
+    return result.toString();
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringBuilderTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringBuilderTest.xtend
new file mode 100644
index 0000000..bc0b910
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringBuilderTest.xtend
@@ -0,0 +1,150 @@
+/*******************************************************************************
+ * Copyright (c) 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.xtext.xbase.tests.lib.internal
+
+import java.lang.annotation.RetentionPolicy
+import org.eclipse.xtend.lib.annotations.Accessors
+import org.eclipse.xtend2.lib.StringConcatenation
+import org.eclipse.xtext.xbase.lib.util.ToStringBuilder
+import org.junit.Test
+
+import static org.junit.Assert.*
+import org.eclipse.xtend.lib.annotations.ToString
+
+/**
+ * @author Karsten Thoms - Initial contribution and API
+ */
+class ToStringBuilderTest {
+
+	@Test def void testToString() {
+		val builder = new ToStringBuilder(new MyEntity(new MyEntity)).addAllFields
+		assertEquals(toUnix(
+				'''
+		MyEntity [
+		  boolProp = true
+		  intProp = 42
+		  myList = ArrayList (
+		    "foo",
+		    "bar",
+		    "baz"
+		  )
+		  friend = true
+		  42
+		  [foo, bar, baz]
+		  null
+		  CLASS
+		  policy = CLASS
+		]'''), builder.toString())
+	}
+
+	@Test def void testSingleLine() {
+		val builder = new ToStringBuilder(new MyEntity).singleLine.addAllFields
+
+		assertEquals(
+			'MyEntity [boolProp = true, intProp = 42, myList = ArrayList ("foo","bar","baz"), friend = null, policy = CLASS]',
+			builder.toString())
+	}
+
+	@Test def void testHideFieldNames() {
+		val builder = new ToStringBuilder(new MyEntity).singleLine.hideFieldNames.addAllFields
+
+		assertEquals('MyEntity [true, 42, ArrayList ("foo","bar","baz"), null, CLASS]', builder.toString())
+	}
+
+	@Test def void testSkipNulls() {
+		val builder = new ToStringBuilder(new MyEntity).skipNulls.addAllFields
+
+		assertEquals(toUnix(
+				'''
+		MyEntity [
+		  boolProp = true
+		  intProp = 42
+		  myList = ArrayList (
+		    "foo",
+		    "bar",
+		    "baz"
+		  )
+		  policy = CLASS
+		]'''), builder.toString)
+	}
+
+	@Test def void testExplicitFieldListing() {
+		val builder = new ToStringBuilder(new MyEntity).add("boolProp", false).addField("intProp")
+
+		assertEquals(toUnix(
+				'''
+		MyEntity [
+		  boolProp = false
+		  intProp = 42
+		]'''), builder.toString)
+	}
+
+	@Test def void recursionHandling() {
+		val obj = new OtherClass
+		obj.name = 'foo'
+		obj.other = obj
+		val builder = new ToStringBuilder(obj).addDeclaredFields
+
+		assertEquals(toUnix(
+				'''
+		OtherClass [
+		  other = «obj.toString»
+		  name = "foo"
+		]'''), builder.toString)
+	}
+
+	@Test def void recursionHandling_02() {
+		val obj = new DataClass()
+		obj.other = obj
+		obj.name = "test"
+		val builder = new ToStringBuilder(obj).addDeclaredFields
+		assertEquals(toUnix(
+				'''
+		DataClass [
+		  other = DataClass@«System::identityHashCode(obj)»
+		  name = "test"
+		]'''), builder.toString)
+	}
+
+	static class OtherClass {
+		public OtherClass other
+		public String name
+	}
+
+	@Accessors @ToString static class DataClass {
+		public DataClass other
+		public String name
+	}
+
+	static class MyEntity {
+		val boolProp = true
+		val intProp = 42
+		val myList = newArrayList('foo', 'bar', 'baz')
+		val MyEntity friend
+		val RetentionPolicy policy = RetentionPolicy::CLASS
+
+		new() {
+			this.friend = null
+		}
+
+		new(MyEntity friend) {
+			this.friend = friend;
+		}
+
+		override toString() {
+			return boolProp + '\n' + intProp + '\n' + myList + '\n' + friend + '\n' + policy
+		}
+	}
+
+	def static String toUnix(String s) {
+		var StringConcatenation result = new StringConcatenation("\n")
+		result.append(s)
+		return result.toString()
+	}
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringHelperTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringHelperTest.java
new file mode 100644
index 0000000..af95adb
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringHelperTest.java
@@ -0,0 +1,262 @@
+package org.eclipse.xtext.xbase.tests.lib.internal;
+
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import org.eclipse.xtend.lib.annotations.Accessors;
+import org.eclipse.xtend.lib.annotations.ToString;
+import org.eclipse.xtend2.lib.StringConcatenation;
+import org.eclipse.xtext.xbase.lib.CollectionLiterals;
+import org.eclipse.xtext.xbase.lib.Pure;
+import org.eclipse.xtext.xbase.lib.util.ToStringBuilder;
+import org.eclipse.xtext.xbase.lib.util.ToStringHelper;
+import org.junit.Assert;
+import org.junit.Test;
+
+@Deprecated
+@SuppressWarnings("all")
+public class ToStringHelperTest {
+  public static class OtherClass {
+    public ToStringHelperTest.OtherClass other;
+    
+    public String name;
+  }
+  
+  @Accessors
+  @ToString
+  public static class DataClass {
+    public ToStringHelperTest.DataClass other;
+    
+    public String name;
+    
+    @Pure
+    public ToStringHelperTest.DataClass getOther() {
+      return this.other;
+    }
+    
+    public void setOther(final ToStringHelperTest.DataClass other) {
+      this.other = other;
+    }
+    
+    @Pure
+    public String getName() {
+      return this.name;
+    }
+    
+    public void setName(final String name) {
+      this.name = name;
+    }
+    
+    @Override
+    @Pure
+    public String toString() {
+      ToStringBuilder b = new ToStringBuilder(this);
+      b.add("other", this.other);
+      b.add("name", this.name);
+      return b.toString();
+    }
+  }
+  
+  public static class MyEntity {
+    private final boolean boolProp = true;
+    
+    private final int intProp = 42;
+    
+    private final ArrayList<String> myList = CollectionLiterals.<String>newArrayList("foo", "bar", "baz");
+    
+    private final ToStringHelperTest.MyEntity friend;
+    
+    private final RetentionPolicy policy = RetentionPolicy.CLASS;
+    
+    public MyEntity() {
+      this.friend = null;
+    }
+    
+    public MyEntity(final ToStringHelperTest.MyEntity friend) {
+      this.friend = friend;
+    }
+    
+    @Override
+    public String toString() {
+      String _plus = (Boolean.valueOf(this.boolProp) + "\n");
+      String _plus_1 = (_plus + Integer.valueOf(this.intProp));
+      String _plus_2 = (_plus_1 + "\n");
+      String _plus_3 = (_plus_2 + this.myList);
+      String _plus_4 = (_plus_3 + "\n");
+      String _plus_5 = (_plus_4 + this.friend);
+      String _plus_6 = (_plus_5 + "\n");
+      return (_plus_6 + this.policy);
+    }
+  }
+  
+  @Test
+  public void testToString() {
+    final ToStringHelper helper = new ToStringHelper();
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("MyEntity [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("boolProp = true");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("intProp = 42");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("myList = ArrayList (");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"foo\",");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"bar\",");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"baz\"");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append(")");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("friend = true");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("42");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("[foo, bar, baz]");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("null");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("CLASS");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("policy = CLASS");
+    _builder.newLine();
+    _builder.append("]");
+    ToStringHelperTest.MyEntity _myEntity = new ToStringHelperTest.MyEntity();
+    ToStringHelperTest.MyEntity _myEntity_1 = new ToStringHelperTest.MyEntity(_myEntity);
+    Assert.assertEquals(
+      ToStringHelperTest.toUnix(_builder.toString()), helper.toString(_myEntity_1));
+  }
+  
+  @Test
+  public void testSingleLine() {
+    ToStringHelperTest.MyEntity _myEntity = new ToStringHelperTest.MyEntity();
+    final ToStringBuilder helper = new ToStringBuilder(_myEntity).singleLine().addAllFields();
+    Assert.assertEquals(
+      "MyEntity [boolProp = true, intProp = 42, myList = ArrayList (\"foo\",\"bar\",\"baz\"), friend = null, policy = CLASS]", 
+      helper.toString());
+  }
+  
+  @Test
+  public void testHideFieldNames() {
+    ToStringHelperTest.MyEntity _myEntity = new ToStringHelperTest.MyEntity();
+    final ToStringBuilder helper = new ToStringBuilder(_myEntity).singleLine().hideFieldNames().addAllFields();
+    Assert.assertEquals("MyEntity [true, 42, ArrayList (\"foo\",\"bar\",\"baz\"), null, CLASS]", helper.toString());
+  }
+  
+  @Test
+  public void testSkipNulls() {
+    ToStringHelperTest.MyEntity _myEntity = new ToStringHelperTest.MyEntity();
+    final ToStringBuilder helper = new ToStringBuilder(_myEntity).skipNulls().addAllFields();
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("MyEntity [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("boolProp = true");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("intProp = 42");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("myList = ArrayList (");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"foo\",");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"bar\",");
+    _builder.newLine();
+    _builder.append("    ");
+    _builder.append("\"baz\"");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append(")");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("policy = CLASS");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringHelperTest.toUnix(_builder.toString()), helper.toString());
+  }
+  
+  @Test
+  public void testExplicitFieldListing() {
+    ToStringHelperTest.MyEntity _myEntity = new ToStringHelperTest.MyEntity();
+    final ToStringBuilder helper = new ToStringBuilder(_myEntity).add("boolProp", Boolean.valueOf(false)).addField("intProp");
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("MyEntity [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("boolProp = false");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("intProp = 42");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringHelperTest.toUnix(_builder.toString()), helper.toString());
+  }
+  
+  @Test
+  public void recursionHandling() {
+    final ToStringHelper helper = new ToStringHelper();
+    final ToStringHelperTest.OtherClass obj = new ToStringHelperTest.OtherClass();
+    obj.name = "foo";
+    obj.other = obj;
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("OtherClass [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("other = ");
+    String _string = obj.toString();
+    _builder.append(_string, "  ");
+    _builder.newLineIfNotEmpty();
+    _builder.append("  ");
+    _builder.append("name = \"foo\"");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringHelperTest.toUnix(_builder.toString()), helper.toString(obj));
+  }
+  
+  @Test
+  public void recursionHandling_02() {
+    final ToStringHelper helper = new ToStringHelper();
+    final ToStringHelperTest.DataClass obj = new ToStringHelperTest.DataClass();
+    obj.other = obj;
+    obj.name = "test";
+    StringConcatenation _builder = new StringConcatenation();
+    _builder.append("DataClass [");
+    _builder.newLine();
+    _builder.append("  ");
+    _builder.append("other = DataClass@");
+    int _identityHashCode = System.identityHashCode(obj);
+    _builder.append(_identityHashCode, "  ");
+    _builder.newLineIfNotEmpty();
+    _builder.append("  ");
+    _builder.append("name = \"test\"");
+    _builder.newLine();
+    _builder.append("]");
+    Assert.assertEquals(
+      ToStringHelperTest.toUnix(_builder.toString()), helper.toString(obj));
+  }
+  
+  public static String toUnix(final String s) {
+    StringConcatenation result = new StringConcatenation("\n");
+    result.append(s);
+    return result.toString();
+  }
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringHelperTest.xtend b/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringHelperTest.xtend
new file mode 100644
index 0000000..dba2751
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/internal/ToStringHelperTest.xtend
@@ -0,0 +1,140 @@
+package org.eclipse.xtext.xbase.tests.lib.internal
+
+import java.lang.annotation.RetentionPolicy
+import org.eclipse.xtend.lib.annotations.Accessors
+import org.eclipse.xtend.lib.annotations.ToString
+import org.eclipse.xtend2.lib.StringConcatenation
+import org.eclipse.xtext.xbase.lib.util.ToStringBuilder
+import org.junit.Test
+
+import static org.junit.Assert.*
+
+@Deprecated
+class ToStringHelperTest {
+
+	@Test def void testToString() {
+		val helper = new org.eclipse.xtext.xbase.lib.util.ToStringHelper
+		assertEquals(toUnix(
+				'''
+		MyEntity [
+		  boolProp = true
+		  intProp = 42
+		  myList = ArrayList (
+		    "foo",
+		    "bar",
+		    "baz"
+		  )
+		  friend = true
+		  42
+		  [foo, bar, baz]
+		  null
+		  CLASS
+		  policy = CLASS
+		]'''), helper.toString(new MyEntity(new MyEntity)))
+	}
+
+	@Test def void testSingleLine() {
+		val helper = new ToStringBuilder(new MyEntity).singleLine.addAllFields
+
+		assertEquals(
+			'MyEntity [boolProp = true, intProp = 42, myList = ArrayList ("foo","bar","baz"), friend = null, policy = CLASS]',
+			helper.toString())
+	}
+
+	@Test def void testHideFieldNames() {
+		val helper = new ToStringBuilder(new MyEntity).singleLine.hideFieldNames.addAllFields
+
+		assertEquals('MyEntity [true, 42, ArrayList ("foo","bar","baz"), null, CLASS]', helper.toString())
+	}
+
+	@Test def void testSkipNulls() {
+		val helper = new ToStringBuilder(new MyEntity).skipNulls.addAllFields
+
+		assertEquals(toUnix(
+				'''
+		MyEntity [
+		  boolProp = true
+		  intProp = 42
+		  myList = ArrayList (
+		    "foo",
+		    "bar",
+		    "baz"
+		  )
+		  policy = CLASS
+		]'''), helper.toString())
+	}
+
+	@Test def void testExplicitFieldListing() {
+		val helper = new ToStringBuilder(new MyEntity).add("boolProp", false).addField("intProp")
+
+		assertEquals(toUnix(
+				'''
+		MyEntity [
+		  boolProp = false
+		  intProp = 42
+		]'''), helper.toString())
+	}
+
+	@Test def void recursionHandling() {
+		val helper = new org.eclipse.xtext.xbase.lib.util.ToStringHelper
+		val obj = new OtherClass
+		obj.name = 'foo'
+		obj.other = obj
+
+		assertEquals(toUnix(
+				'''
+		OtherClass [
+		  other = «obj.toString»
+		  name = "foo"
+		]'''), helper.toString(obj))
+	}
+
+	@Test def void recursionHandling_02() {
+		val helper = new org.eclipse.xtext.xbase.lib.util.ToStringHelper
+		val obj = new DataClass()
+		obj.other = obj
+		obj.name = "test"
+		assertEquals(toUnix(
+				'''
+		DataClass [
+		  other = DataClass@«System::identityHashCode(obj)»
+		  name = "test"
+		]'''), helper.toString(obj))
+	}
+
+	static class OtherClass {
+		public OtherClass other
+		public String name
+	}
+
+	@Accessors @ToString static class DataClass {
+		public DataClass other
+		public String name
+	}
+
+	static class MyEntity {
+		val boolProp = true
+		val intProp = 42
+		val myList = newArrayList('foo', 'bar', 'baz')
+		val MyEntity friend
+		val RetentionPolicy policy = RetentionPolicy::CLASS
+
+		new() {
+			this.friend = null
+		}
+
+		new(MyEntity friend) {
+			this.friend = friend;
+		}
+
+		override toString() {
+			return boolProp + '\n' + intProp + '\n' + myList + '\n' + friend + '\n' + policy
+		}
+	}
+
+	def static String toUnix(String s) {
+		var StringConcatenation result = new StringConcatenation("\n")
+		result.append(s)
+		return result.toString()
+	}
+}
diff --git a/javatests/org/eclipse/xtext/xbase/tests/lib/util/ReflectExtensionsTest.java b/javatests/org/eclipse/xtext/xbase/tests/lib/util/ReflectExtensionsTest.java
new file mode 100644
index 0000000..465d0d6
--- /dev/null
+++ b/javatests/org/eclipse/xtext/xbase/tests/lib/util/ReflectExtensionsTest.java
@@ -0,0 +1,91 @@
+package org.eclipse.xtext.xbase.tests.lib.util;
+
+import org.eclipse.xtext.xbase.lib.Functions.Function1;
+import org.eclipse.xtext.xbase.lib.util.ReflectExtensions;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ReflectExtensionsTest {
+
+	public ReflectExtensions ext = new ReflectExtensions();
+	private ReflectExtensions privateExt = new ReflectExtensions();
+
+	@Test
+	public void testInvoke_01() throws Exception {
+		String x = "foo";
+		Assert.assertEquals(3, ext.invoke(x, "length"));
+	}
+
+	@Test(expected=NoSuchMethodException.class)
+	public void testInvoke_02() throws Exception {
+		String x = "foo";
+		ext.invoke(x, "foo");
+	}
+
+	@Test(expected=NoSuchMethodException.class)
+	public void testInvoke_03() throws Exception {
+		String x = "foo";
+		ext.invoke(x, "length", 24);
+	}
+
+	@Test(expected=IllegalStateException.class)
+	public void testInvokeWithOverloadedMethods() throws Exception {
+		StringBuilder x = new StringBuilder();
+		ext.invoke(x, "append", "foo");
+	}
+
+	@Test
+	public void testInvokeWithNull() throws Exception {
+		final Function1<String, String> x = (String s) -> {
+			return s;
+		};
+		Object[] args = null;
+		Assert.assertNull(ext.invoke(x, "apply", args));
+		Assert.assertEquals("foo", ext.invoke(x, "apply", "foo"));
+	}
+
+	@Test
+	public void testInvokeWithPrimitives() throws Exception {
+		String x = "foo";
+		Assert.assertEquals("o", ext.invoke(x, "substring", 1, 2));
+	}
+
+	@Test
+	public void testGet_01() throws Exception {
+		ReflectExtensionsTest x = new ReflectExtensionsTest();
+		Assert.assertNotNull(ext.get(x, "ext"));
+	}
+
+	@Test(expected=NoSuchFieldException.class)
+	public void testGet_02() throws Exception {
+		ReflectExtensionsTest x = new ReflectExtensionsTest();
+		Assert.assertNotNull(ext.get(x, "foo"));
+	}
+
+	@Test
+	public void testGet_03() throws Exception {
+		ReflectExtensionsTest x = new ReflectExtensionsTest();
+		Assert.assertSame(x.privateExt, ext.get(x, "privateExt"));
+	}
+
+	@Test
+	public void testSet_01() throws Exception {
+		ReflectExtensionsTest x = new ReflectExtensionsTest();
+		ext.set(x, "ext", null);
+		Assert.assertNull(x.ext);
+	}
+
+	@Test(expected=NoSuchFieldException.class)
+	public void testSet_02() throws Exception {
+		ReflectExtensionsTest x = new ReflectExtensionsTest();
+		ext.set(x, "foo", "bar");
+	}
+
+	@Test
+	public void testSet_03() throws Exception {
+		ReflectExtensionsTest x = new ReflectExtensionsTest();
+		ext.set(x, "privateExt", null);
+		Assert.assertNull(x.privateExt);
+	}
+
+}
\ No newline at end of file