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()
+ * @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()
+ * @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<?></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<String>}
+ *
+ * @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<String>.addAll(int, Collection<E>)</code> is
+ * <code>addAll(int, Collection<String>)</code>.
+ * @return the simple, human-readable signature
+ */
+ String getSimpleSignature();
+
+ /**
+ * Returns the resolved erased signature of this feature. The resolved representation of
+ * <code>List<String>.addAll(int,java.util.Collection<E>)</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<T> {
+ * def void foo(T arg)
+ * }
+ * </pre>
+ *
+ * In the context of the type reference <code>Foo<String></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<T> {
+ * def <U extends T> void foo(U arg)
+ * }
+ * </pre>
+ *
+ * For a <code>Foo<CharSequence></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<? extends java.math.BigDecimal>' this method returns
+ * 'List<? extends BigDecimal>'
+ *
+ * @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<?></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<T> {}
+ * </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<T> {
+ * def Foo<T> 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<T> {
+ * 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 ? e==null : 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, e) == 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, e) == 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 == 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 == 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 == 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 == 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 == 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>&&</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_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)<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)<=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)>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)>=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><</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_lessThan(byte a, double b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(byte a, double b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(byte a, double b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(byte a, float b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(byte a, float b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(byte a, float b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(byte a, long b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(byte a, long b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(byte a, long b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(byte a, int b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(byte a, int b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(byte a, int b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(byte a, char b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(byte a, char b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(byte a, char b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(byte a, short b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(byte a, short b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(byte a, short b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(byte a, byte b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(byte a, byte b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(byte a, byte b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(char a, double b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(char a, double b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(char a, double b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(char a, float b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(char a, float b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(char a, float b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(char a, long b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(char a, long b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(char a, long b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(char a, int b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(char a, int b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(char a, int b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(char a, char b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(char a, char b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(char a, char b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(char a, short b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(char a, short b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(char a, short b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(char a, byte b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(char a, byte b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(char a, byte b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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) < 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) > 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) <= 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) >= 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><=></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><</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_lessThan(double a, double b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(double a, double b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(double a, double b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(double a, float b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(double a, float b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(double a, float b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(double a, long b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(double a, long b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(double a, long b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(double a, int b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(double a, int b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(double a, int b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(double a, char b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(double a, char b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(double a, char b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(double a, short b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(double a, short b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(double a, short b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(double a, byte b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(double a, byte b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(double a, byte b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(float a, double b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(float a, double b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(float a, double b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(float a, float b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(float a, float b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(float a, float b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(float a, long b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(float a, long b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(float a, long b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(float a, int b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(float a, int b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(float a, int b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(float a, char b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(float a, char b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(float a, char b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(float a, short b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(float a, short b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(float a, short b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(float a, byte b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(float a, byte b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(float a, byte b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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>..<</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>>..</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>&</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 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><<</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<<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><<</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<<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>>></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>>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>>></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>>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>>>></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>>>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>>>></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>>>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><</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_lessThan(int a, double b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(int a, double b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(int a, double b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(int a, float b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(int a, float b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(int a, float b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(int a, long b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(int a, long b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(int a, long b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(int a, int b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(int a, int b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(int a, int b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(int a, char b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(int a, char b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(int a, char b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(int a, short b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(int a, short b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(int a, short b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(int a, byte b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(int a, byte b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(int a, byte b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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<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 ? e==null : 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 ? e==null : 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>&</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 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><<</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<<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><<</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<<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>>></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>>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>>></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>>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>>>></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>>>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>>>></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>>>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><</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_lessThan(long a, double b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(long a, double b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(long a, double b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(long a, float b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(long a, float b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(long a, float b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(long a, long b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(long a, long b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(long a, long b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(long a, int b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(long a, int b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(long a, int b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(long a, char b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(long a, char b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(long a, char b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(long a, short b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(long a, short b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(long a, short b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(long a, byte b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(long a, byte b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(long a, byte b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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 => [
+ * 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><</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_lessThan(short a, double b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(short a, double b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(short a, double b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(short a, float b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(short a, float b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(short a, float b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(short a, long b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(short a, long b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(short a, long b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(short a, int b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(short a, int b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(short a, int b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(short a, char b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(short a, char b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(short a, char b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(short a, short b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(short a, short b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(short a, short b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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><</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_lessThan(short a, byte b) {
+ return a < b;
+ }
+
+ /**
+ * The binary <code>lessEqualsThan</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_lessEqualsThan(short a, byte b) {
+ return a <= b;
+ }
+
+ /**
+ * The binary <code>greaterThan</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_greaterThan(short a, byte b) {
+ return a > b;
+ }
+
+ /**
+ * The binary <code>greaterEqualsThan</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_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