docs: @Override
  	@SuppressWarnings({"checkstyle:methodlength", "checkstyle:cyclomaticcomplexity",
  			"checkstyle:npathcomplexity", "checkstyle:booleanexpressioncomplexity"})
  	protected void transform(final XtendFunction source, final JvmGenericType container, boolean allowDispatch) {
  		final GenerationContext context = getContext(container);
  
  		// Compute the operation name
  		// Issue #355: null or empty name is possible.
  		final String originalFunctionName = source.getName();
  		if (!Strings.isNullOrEmpty(originalFunctionName)) {
  			final StringBuilder sourceNameBuffer = new StringBuilder(originalFunctionName);
  			if (allowDispatch && source.isDispatch()) {
  				sourceNameBuffer.insert(0, "_"); //$NON-NLS-1$
  			}
  			final String sourceName = sourceNameBuffer.toString();
  
  			// Create the main function
  			final JvmOperation operation = this.typesFactory.createJvmOperation();
  			container.getMembers().add(operation);
  			operation.setSimpleName(sourceName);
  			setVisibility(operation, source);
  			operation.setStrictFloatingPoint(source.isStrictFloatingPoint());
  			operation.setStatic(source.isStatic());
  			operation.setSynchronized(source.isSynchonized());
  			operation.setNative(source.isNative());
  			boolean enableFunctionBody;
  			if (container.isInterface()) {
  				enableFunctionBody = false;
  				if (context != null && context.isAtLeastJava8()
  						&& !Utils.toLightweightTypeReference(container, this.services).isSubtypeOf(Capacity.class)) {
  					if (operation.isStatic()) {
  						enableFunctionBody = true;
  					} else if (source.getExpression() != null && !operation.isAbstract()) {
  						enableFunctionBody = true;
  					}
  				}
  				operation.setDefault(enableFunctionBody && !operation.isStatic());
  				operation.setAbstract(!enableFunctionBody);
  				operation.setFinal(false);
  			} else {
  				operation.setDefault(false);
  				enableFunctionBody = context != null && !source.isAbstract();
  				operation.setAbstract(!enableFunctionBody);
  				operation.setFinal(enableFunctionBody && source.isFinal());
  			}
  			this.associator.associatePrimary(source, operation);
  
  			// Type parameters
  			copyAndFixTypeParameters(source.getTypeParameters(), operation);
  
  			// Compute the identifier of the action.
  			final QualifiedActionName actionKey = this.sarlSignatureProvider.createQualifiedActionName(
  					container, sourceName);
  
  			// Compute the different action prototypes associated to the action to create.
  			final boolean isVarArgs = Utils.isVarArg(source.getParameters());
  			final InferredPrototype actionSignatures = this.sarlSignatureProvider.createPrototypeFromSarlModel(
  					actionKey,
  					isVarArgs, source.getParameters());
  
  			// Compute the action prototype of the action without optional parameter
  			final ActionPrototype actSigKey = this.sarlSignatureProvider.createActionPrototype(
  					sourceName,
  					actionSignatures.getFormalParameterTypes());
  
  			// Generate the parameters
  			final List<InferredStandardParameter> paramList = actionSignatures.getOriginalParameterTypes();
  			translateSarlFormalParameters(
  					context,
  					operation, container, isVarArgs,
  					source.getParameters(),
  					container.isInterface(), paramList);
  
  			// Get the super function
  			final JvmOperation inheritedOperation;
  			if (context != null) {
  				JvmOperation tmpInheritedOperation = context.getInheritedFinalOperations().get(actSigKey);
  				if (tmpInheritedOperation == null) {
  					tmpInheritedOperation = context.getInheritedOverridableOperations().get(actSigKey);
  				}
  				if (tmpInheritedOperation == null) {
  					tmpInheritedOperation = context.getInheritedOperationsToImplement().get(actSigKey);
  				}
  				inheritedOperation = tmpInheritedOperation;
  			} else {
  				inheritedOperation = null;
  			}
  
  			// Infer the return type
  			final JvmTypeReference selectedReturnType = inferFunctionReturnType(source, operation, inheritedOperation);
  			operation.setReturnType(selectedReturnType);
  
  			// Exceptions
  			for (final JvmTypeReference exception : source.getExceptions()) {
  				operation.getExceptions().add(this.typeBuilder.cloneWithProxies(exception));
  			}
  
  			// Add the body
  			if (enableFunctionBody) {
  				setBody(operation, source.getExpression());
  			}
  
  			// User Annotations
  			translateAnnotationsTo(source.getAnnotations(), operation);
  
  			// Add @Inline annotation
  			if (context != null && context.isAtLeastJava8()
  					&& context.getGeneratorConfig2().isGenerateInlineAnnotation()
  					&& !source.isAbstract() && !container.isInterface()
  					&& (source.isStatic() || source.isFinal() || container.isFinal())
  					&& context.getParentContext() == null
  					&& this.annotationFinder.findAnnotation(operation, Inline.class) == null) {
  				context.getPostFinalizationElements().add(
  						() -> this.inlineExpressionCompiler.appendInlineAnnotation(operation, source));
  			}
  
  			// Add @Override annotation
  			if (source.isOverride()
  					&& this.annotationFinder.findAnnotation(operation, Override.class) == null
  					&& this.typeReferences.findDeclaredType(Override.class, source) != null) {
  				addAnnotationSafe(operation, Override.class);
  			}
  
  			// Add @Pure annotation
  			final boolean addDynamicPureAnnotationGenerator;
  			final boolean hasExplicitPureAnnotation = this.annotationFinder.findAnnotation(operation, Pure.class) != null;
  			if (context != null && context.getGeneratorConfig2().isGeneratePureAnnotation()
  					&& !hasExplicitPureAnnotation && this.typeReferences.findDeclaredType(Pure.class, source) != null) {
  				addDynamicPureAnnotationGenerator = inheritedOperation == null;
  				if (addDynamicPureAnnotationGenerator) {
  					this.operationHelper.attachPureAnnotationAdapter(operation, (op, helper) -> {
  						return helper.isPurableOperation(source);
  					});
  				} else {
  					this.operationHelper.attachPureAnnotationAdapter(operation, (op, helper) -> {
  						return helper.isPureOperation(inheritedOperation);
  					});
  				}
  			} else {
  				addDynamicPureAnnotationGenerator = false;
  			}
  
  			// Detecting if the action is an early-exit action.
  			// If true, the Java code is annotated to be usable by the SARL validator.
  			final List<JvmTypeReference> firedEvents;
  			final boolean isEarlyExit;
  			if (source instanceof SarlAction) {
  				final SarlAction action = (SarlAction) source;
  				firedEvents = action.getFiredEvents();
  				isEarlyExit = this.earlyExitComputer.isEarlyExitOperation(action);
  				if (isEarlyExit) {
  					addAnnotationSafe(operation, EarlyExit.class);
  				}
  			} else {
  				firedEvents = Collections.emptyList();
  				isEarlyExit = false;
  			}
  
  			// Put the fired SARL events as Java annotations for being usable by the SARL validator.
  			if (!firedEvents.isEmpty()) {
  				operation.getAnnotations().add(annotationClassRef(FiredEvent.class, firedEvents));
  			}
  
  			// 1. Ensure that the Java annotations related to the default value are really present.
  			//    They may be not present if the generated action is a specific version of an inherited
  			//    action with default values for parameters.
  			// 2. Update the two collections that describes the implemented and implementable operations.
  			if (context != null) {
  				final JvmOperation implementedOperation = context.getInheritedOperationsToImplement().remove(actSigKey);
  				// Put the annotations that were defined in the implemented operation
  				if (implementedOperation != null) {
  					if (this.annotationFinder.findAnnotation(implementedOperation, DefaultValueSource.class) != null
  							&& this.annotationFinder.findAnnotation(operation, DefaultValueSource.class) == null) {
  						addAnnotationSafe(operation, DefaultValueSource.class);
  					}
  					// Reinject the @DefaultValue annotations
  					final List<JvmFormalParameter> oparams = implementedOperation.getParameters();
  					final List<JvmFormalParameter> cparams = operation.getParameters();
  					assert oparams.size() == cparams.size();
  					for (int i = 0; i < oparams.size(); ++i) {
  						final JvmFormalParameter op = oparams.get(i);
  						final JvmFormalParameter cp = cparams.get(i);
  						final String ovalue = this.annotationUtils.findStringValue(op, DefaultValue.class);
  						if (ovalue != null
  								&& this.annotationFinder.findAnnotation(cp, DefaultValue.class) == null) {
  							addAnnotationSafe(cp,
  									DefaultValue.class,
  									this.sarlSignatureProvider.qualifyDefaultValueID(
  											implementedOperation.getDeclaringType().getIdentifier(),
  											ovalue));
  						}
  					}
  				}
  				// Add the main operation into the list of overridable operations
  				context.getInheritedOverridableOperations().put(actSigKey, operation);
  			}
  
  			copyAndCleanDocumentationTo(source, operation);
  
  			@SuppressWarnings("checkstyle:anoninnerlength")
  			final Runnable differedGeneration = () -> {
  				// Generate the Java functions that correspond to the action with the parameter default values applied.
  				for (final Entry<ActionParameterTypes, List<InferredStandardParameter>> otherSignature
  						: actionSignatures.getInferredParameterTypes().entrySet()) {
  					final ActionPrototype ak = SARLJvmModelInferrer.this.sarlSignatureProvider.createActionPrototype(
  							sourceName,
  							otherSignature.getKey());
  					if (ak != null
  							&& (context == null
  							|| (!context.getInheritedFinalOperations().containsKey(ak)
  									&& !context.getInheritedOverridableOperations().containsKey(ak)))) {
  
  						// Generate the additional constructor that is invoke the main constructor previously generated.
  						final JvmOperation operation2 = SARLJvmModelInferrer.this.typesFactory.createJvmOperation();
  						container.getMembers().add(operation2);
  						operation2.setSimpleName(operation.getSimpleName());
  						operation2.setVisibility(operation.getVisibility());
  						operation2.setVarArgs(operation.isVarArgs());
  						operation2.setAbstract(operation.isAbstract());
  						operation2.setDeprecated(operation.isDeprecated());
  						operation2.setStatic(operation.isStatic());
  						operation2.setFinal(!operation.isStatic() && !container.isInterface());
  						operation2.setNative(false);
  						operation2.setStrictFloatingPoint(false);
  						operation2.setSynchronized(false);
  						this.associator.associate(source, operation2);
  
  						copyTypeParametersFromJvmOperation(operation, operation2);
  
  						for (final JvmTypeReference exception : operation.getExceptions()) {
  							operation2.getExceptions().add(SARLJvmModelInferrer.this.typeBuilder
  									.cloneWithProxies(exception));
  						}
  
  						if (selectedReturnType instanceof XComputedTypeReference) {
  							operation2.setReturnType(this.typeReferences.createDelegateTypeReference(selectedReturnType));
  						} else {
  							operation2.setReturnType(cloneWithTypeParametersAndProxies(selectedReturnType, operation2));
  						}
  
  						final List<String> args = translateSarlFormalParametersForSyntheticOperation(
  								operation2, container, isVarArgs, otherSignature.getValue());
  
  						if (context != null && context.isAtLeastJava8()) {
  							operation2.setDefault(container.isInterface());
  							operation2.setAbstract(false);
  							setBody(operation2, it -> {
  								final JvmTypeReference type = operation2.getReturnType();
  								if (!SARLJvmModelInferrer.this.typeReferences.is(type, void.class)) {
  									it.append("return "); //$NON-NLS-1$
  								}
  								it.append(sourceName);
  								it.append("("); //$NON-NLS-1$
  								it.append(IterableExtensions.join(args, ", ")); //$NON-NLS-1$
  								it.append(");"); //$NON-NLS-1$
  							});
  						} else {
  							operation2.setDefault(false);
  							operation2.setAbstract(true);
  						}
  
  						// @Override annotation
  						if (source.isOverride()
  								&& SARLJvmModelInferrer.this.annotationFinder.findAnnotation(operation,
  								Override.class) == null
  								&& SARLJvmModelInferrer.this.typeReferences.findDeclaredType(
  										Override.class, source) != null) {
  							addAnnotationSafe(
  									operation, Override.class);
  						}
  
  						// @DefaultValueUse annotation
  						addAnnotationSafe(
  								operation2, DefaultValueUse.class,
  								actionSignatures.getFormalParameterTypes().toString());
  						appendGeneratedAnnotation(operation2, context);
  
  						// @EarlyExit annotation
  						// If the main action is an early-exit action, the additional operation
  						// is also an early-exit operation.
  						if (isEarlyExit) {
  							addAnnotationSafe(
  									operation2, EarlyExit.class);
  						}
  
  						// @FiredEvent annotation
  						// Put the fired SARL events as Java annotations for being usable by the SARL validator.
  						if (!firedEvents.isEmpty()) {
  							operation2.getAnnotations().add(
  									annotationClassRef(FiredEvent.class, firedEvents));
  						}
  
  						// @Pure annotation
  						if (addDynamicPureAnnotationGenerator) {
  							this.operationHelper.attachPureAnnotationAdapter(operation2, (op, helper) -> {
  								return helper.isPureOperation(operation);
  							});
  						} else if (hasExplicitPureAnnotation) {
  							addAnnotationSafe(
  									operation2, Pure.class);
  						}
  
  						// Copy the annotations from the original operations, and that are not overridden above
  						for (final JvmAnnotationReference annotation : operation.getAnnotations()) {
  							final String id = annotation.getAnnotation().getIdentifier();
  							if (!DefaultValueSource.class.getName().equals(id)
  									&& !DefaultValueUse.class.getName().equals(id)
  									&& !Pure.class.getName().equals(id)
  									&& !EarlyExit.class.getName().equals(id)
  									&& !FiredEvent.class.getName().equals(id)
  									&& !Inline.class.getName().equals(id)
  									&& !Generated.class.getName().equals(id)) {
  								try {
  									final JvmAnnotationReference clone = SARLJvmModelInferrer.this._annotationTypesBuilder
  											.annotationRef(id);
  									for (final JvmAnnotationValue annotationValue : annotation.getExplicitValues()) {
  										clone.getExplicitValues().add(EcoreUtil.copy(annotationValue));
  									}
  									operation2.getAnnotations().add(clone);
  								} catch (IllegalArgumentException exception) {
  									// ignore
  								}
  							}
  						}
  
  						// Copy and clean the documentation
  						copyAndCleanDocumentationTo(operation, operation2);
  
  						// Update the two collections that describes the implemented and implementable operations.
  						if (context != null) {
  							context.getInheritedOperationsToImplement().remove(ak);
  							context.getInheritedOverridableOperations().put(ak, operation2);
  						}
  					}
  				}
  			};
  
  			if (context != null) {
  				context.getPreFinalizationElements().add(differedGeneration);
  				context.setActionIndex(context.getActionIndex() + 1);
  				context.incrementSerial(actSigKey.hashCode());
  			} else {
  				differedGeneration.run();
  			}
  		}
  	}