docs: private JvmOperation toEqualsMethod(
  			XtendTypeDeclaration sarlElement,
  			final JvmDeclaredType declaredType,
  			final Iterable<JvmField> jvmFields,
  			boolean generatePureAnnotation) {
  		if (sarlElement == null || declaredType == null) {
  			return null;
  		}
  
  		final JvmOperation result = this.typeBuilder.toMethod(sarlElement, EQUALS_FUNCTION_NAME,
  				this._typeReferenceBuilder.typeRef(boolean.class), null);
  		if (result == null) {
  			return null;
  		}
  		addAnnotationSafe(result, Override.class);
  		if (generatePureAnnotation) {
  			addAnnotationSafe(result, Pure.class);
  		}
  
  		final JvmFormalParameter param = this.typesFactory.createJvmFormalParameter();
  		param.setName("obj"); //$NON-NLS-1$
  		param.setParameterType(this._typeReferenceBuilder.typeRef(Object.class));
  		this.associator.associate(sarlElement, param);
  		result.getParameters().add(param);
  		setBody(result, new Procedures.Procedure1<ITreeAppendable>() {
  			@SuppressWarnings("synthetic-access")
  			@Override
  			public void apply(ITreeAppendable it) {
  				boolean firstAttr = true;
  				for (final JvmField field : jvmFields) {
  					if (isEqualityTestValidField(field.getType())) {
  						if (firstAttr) {
  							firstAttr = false;
  							it.append("if (this == obj)").increaseIndentation(); //$NON-NLS-1$
  							it.newLine().append("return true;").decreaseIndentation(); //$NON-NLS-1$
  							it.newLine().append("if (obj == null)").increaseIndentation(); //$NON-NLS-1$
  							it.newLine().append("return false;").decreaseIndentation(); //$NON-NLS-1$
  							it.newLine().append("if (getClass() != obj.getClass())").increaseIndentation(); //$NON-NLS-1$
  							it.newLine().append("return false;").decreaseIndentation(); //$NON-NLS-1$
  							final StringBuilder currentTypeName = new StringBuilder();
  							currentTypeName.append(declaredType.getSimpleName());
  							final List<JvmTypeParameter> typeParameters = getTypeParametersFor(sarlElement);
  							if (!typeParameters.isEmpty()) {
  								currentTypeName.append("<"); //$NON-NLS-1$
  								boolean first = true;
  								for (final JvmTypeParameter typeParameter : typeParameters) {
  									if (first) {
  										first = false;
  									} else {
  										currentTypeName.append(", "); //$NON-NLS-1$
  									}
  									currentTypeName.append(typeParameter.getName());
  								}
  								currentTypeName.append(">"); //$NON-NLS-1$
  							}
  							it.newLine().append(currentTypeName).append(" other = ("); //$NON-NLS-1$
  							it.append(currentTypeName).append(") obj;").newLine(); //$NON-NLS-1$
  						}
  						generateToEqualForField(it, field);
  					}
  				}
  				it.append("return super.").append(EQUALS_FUNCTION_NAME); //$NON-NLS-1$
  				it.append("(obj);"); //$NON-NLS-1$
  			}
  
  			@SuppressWarnings({"checkstyle:booleanexpressioncomplexity", "checkstyle:cyclomaticcomplexity", "synthetic-access"})
  			private void generateToEqualForField(ITreeAppendable it, JvmField field) {
  				final TypeReferences refs = SARLJvmModelInferrer.this.typeReferences;
  				final JvmTypeReference type = field.getType();
  				if (refs.is(type, Boolean.TYPE) || refs.is(type, Boolean.class)
  					|| refs.is(type, Integer.TYPE) || refs.is(type, Integer.class)
  					|| refs.is(type, Long.TYPE) || refs.is(type, Long.class)
  					|| refs.is(type, Character.TYPE) || refs.is(type, Character.class)
  					|| refs.is(type, Byte.TYPE) || refs.is(type, Byte.class)
  					|| refs.is(type, Short.TYPE) || refs.is(type, Short.class)) {
  					it.append("if (other.").append(field.getSimpleName()); //$NON-NLS-1$
  					it.append(" != this.").append(field.getSimpleName()).append(")").increaseIndentation(); //$NON-NLS-1$ //$NON-NLS-2$
  					it.newLine().append("return false;").decreaseIndentation(); //$NON-NLS-1$
  				} else if (refs.is(type, Double.TYPE) || refs.is(type, Double.class)) {
  					it.append("if (Double.doubleToLongBits(other.").append(field.getSimpleName()); //$NON-NLS-1$
  					it.append(") != Double.doubleToLongBits(this.").append(field.getSimpleName()); //$NON-NLS-1$
  					it.append("))").increaseIndentation(); //$NON-NLS-1$
  					it.newLine().append("return false;").decreaseIndentation(); //$NON-NLS-1$
  				} else if (refs.is(type, Float.TYPE) || refs.is(type, Float.class)) {
  					it.append("if (Float.floatToIntBits(other.").append(field.getSimpleName()); //$NON-NLS-1$
  					it.append(") != Float.floatToIntBits(this.").append(field.getSimpleName()); //$NON-NLS-1$
  					it.append("))").increaseIndentation(); //$NON-NLS-1$
  					it.newLine().append("return false;").decreaseIndentation(); //$NON-NLS-1$
  				} else {
  					it.append("if (!").append(java.util.Objects.class); //$NON-NLS-1$
  					it.append(".equals(this.").append(field.getSimpleName()); //$NON-NLS-1$
  					it.append(", other.").append(field.getSimpleName()); //$NON-NLS-1$
  					it.append(")) {").increaseIndentation(); //$NON-NLS-1$
  					it.newLine().append("return false;").decreaseIndentation(); //$NON-NLS-1$
  					it.newLine().append("}"); //$NON-NLS-1$
  				}
  				it.newLine();
  			}
  		});
  
  		return result;
  	}