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