/*
 * $Id$
 *
 * SARL is an general-purpose agent programming language.
 * More details on http://www.sarl.io
 *
 * Copyright (C) 2014-2026 SARL.io, the original authors and main authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.sarl.api.core.tests.bugs;

import static io.sarl.lang.validation.IssueCodes.ILLEGAL_PARAMETER_DEFAULT_VALUE_REDEFINITION;
import static io.sarl.lang.validation.IssueCodes.PARAMETER_DEFAULT_VALUE_REDFINITION;
import static io.sarl.tests.api.tools.TestEObjects.file;
import static io.sarl.tests.api.tools.TestUtils.multilineString;
import static io.sarl.tests.api.tools.TestUtils.multilineString2;
import static io.sarl.tests.api.tools.TestValidator.validate;
import static org.eclipse.xtext.xbase.validation.IssueCodes.FORBIDDEN_REFERENCE;
import static org.eclipse.xtext.xbase.validation.IssueCodes.STATIC_ACCESS_TO_INSTANCE_MEMBER;

import org.eclipse.xtext.xbase.XbasePackage;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

import io.sarl.lang.core.SARLVersion;
import io.sarl.lang.sarl.SarlPackage;
import io.sarl.lang.sarl.SarlScript;
import io.sarl.lang.tests.api.AbstractSarlTest;
import io.sarl.tests.api.tools.TestValidator.Validator;

/** Testing class for issue: Enable the use of instance-related
 * variables or functions within parameters default value.
 *
 * <p>https://github.com/sarl/sarl/issues/612
 *
 * @author $Author: sgalland$
 * @version $Name$ $Revision$ $Date$
 * @mavengroupid $GroupId$
 * @mavenartifactid $ArtifactId$
 * @see https://github.com/sarl/sarl/issues/612
 */
@DisplayName("Bug #612")
@SuppressWarnings("all")
@Tag("core")
public class Bug612Test {

	/** The container is a class. 
	 *
	 * @author $Author: sgalland$
	 * @version $Name$ $Revision$ $Date$
	 * @mavengroupid $GroupId$
	 * @mavenartifactid $ArtifactId$
	 */
	@DisplayName("Class Container")
	@Nested
	public class ClassContainer {

		/** Referencing a constant. 
		 *
		 * @author $Author: sgalland$
		 * @version $Name$ $Revision$ $Date$
		 * @mavengroupid $GroupId$
		 * @mavenartifactid $ArtifactId$
		 */
		@DisplayName("Constant reference from function")
		@Nested
		public class ConstantReference extends AbstractSarlTest {

			private final String CONSTANT = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  def fct(param : int = 5) { }",
					"}");


			@Test
			@DisplayName("Constant parsing")
			@Tag("sarlValidation")
			public void parsing_constant() throws Exception {
				SarlScript mas = file(getParseHelper(), CONSTANT);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Constant compiling")
			public void compiling_constant() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", CONSTANT, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"5\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return 5;",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

			private final String CONSTANT_EXPR = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  def fct(param : int = 5 * 6 + 5) { }",
					"}");

			@Test
			@DisplayName("Constant expression parsing")
			@Tag("sarlValidation")
			public void parsing_constantExpr() throws Exception {
				SarlScript mas = file(getParseHelper(), CONSTANT_EXPR);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Constant expression compiling")
			public void compiling_constantExpr() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", CONSTANT_EXPR, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"5 * 6 + 5\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return ((5 * 6) + 5);",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

		}

		/** Referencing a static field. 
		 *
		 * @author $Author: sgalland$
		 * @version $Name$ $Revision$ $Date$
		 * @mavengroupid $GroupId$
		 * @mavenartifactid $ArtifactId$
		 */
		@DisplayName("Static field reference from function")
		@Nested
		public class StaticFieldReference extends AbstractSarlTest {

			private final String LOCAL_STATIC_FIELD = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  static var SVAL : int = 5",
					"  def fct(param : int = SVAL) { }",
					"}");

			@Test
			@DisplayName("Local static field parsing")
			@Tag("sarlValidation")
			public void parsing_localStaticField() throws Exception {
				SarlScript mas = file(getParseHelper(), LOCAL_STATIC_FIELD);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Local static field compiling")
			public void compiling_localStaticField() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", LOCAL_STATIC_FIELD, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  private static int SVAL = 5;",
						"  ",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"SVAL\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return XXX.SVAL;",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

			private final String LOCAL_STATIC_FINAL_FIELD = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  static val SVAL : int = 5",
					"  def fct(param : int = SVAL) { }",
					"}");

			@Test
			@DisplayName("Local static final field parsing")
			@Tag("sarlValidation")
			public void parsing_localStaticFinalField() throws Exception {
				SarlScript mas = file(getParseHelper(), LOCAL_STATIC_FINAL_FIELD);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Local static final field compiling")
			public void compiling_localStaticFinalField() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", LOCAL_STATIC_FINAL_FIELD, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  private static final int SVAL = 5;",
						"  ",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"SVAL\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return XXX.SVAL;",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

			private final String LOCAL_STATIC_FIELD_EXPR = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  static val SVAL : int = 5",
					"  def fct(param : int = SVAL + 7) { }",
					"}");

			@Test
			@DisplayName("Local static field expression parsing")
			@Tag("sarlValidation")
			public void parsing_localStaticFieldExpr() throws Exception {
				SarlScript mas = file(getParseHelper(), LOCAL_STATIC_FIELD_EXPR);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Local static field expression compiling")
			public void compiling_localStaticFieldExpr() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", LOCAL_STATIC_FIELD_EXPR, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  private static final int SVAL = 5;",
						"  ",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"SVAL + 7\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return (XXX.SVAL + 7);",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

		}

		/** Referencing a static function.
		 *
		 * @author $Author: sgalland$
		 * @version $Name$ $Revision$ $Date$
		 * @mavengroupid $GroupId$
		 * @mavenartifactid $ArtifactId$
		 */
		@DisplayName("Static function reference from function")
		@Nested
		public class StaticFunctionReference extends AbstractSarlTest {

			private final String PURE_FUNCTION = multilineString(
					"package io.sarl.lang.tests.bug612",
					"import org.eclipse.xtext.xbase.lib.Pure",
					"class XXX {",
					"  @Pure static def pureFunction : int {5}",
					"  def fct(param : int = pureFunction) { }",
					"}");

			@Test
			@DisplayName("Pure function parsing")
			@Tag("sarlValidation")
			public void parsing_pureFunction() throws Exception {
				SarlScript mas = file(getParseHelper(), PURE_FUNCTION);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Pure function compiling")
			public void compiling_pureFunction() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", PURE_FUNCTION, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  @Pure",
						"  public static int pureFunction() {",
						"    return 5;",
						"  }",
						"  ",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"pureFunction\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    int _pureFunction = XXX.pureFunction();",
						"    return _pureFunction;",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

			private final String NOT_PURE_FUNCTION = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  static var field : int",
					"  static def getX : int {field}",
					"  static def notPureFunction : int {field = 5; return 5}",
					"  def fct(param : int = notPureFunction) { }",
					"}");

			@Test
			@DisplayName("Not pure function parsing")
			@Tag("sarlValidation")
			public void parsing_notPureFunction() throws Exception {
				SarlScript mas = file(getParseHelper(), NOT_PURE_FUNCTION);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertError(
						XbasePackage.eINSTANCE.getXFeatureCall(),
						FORBIDDEN_REFERENCE,
						"Default value's expression cannot reference the not-pure operation: notPureFunction() : int");
			}

		}

		/** Referencing an instance field.
		 *
		 * @author $Author: sgalland$
		 * @version $Name$ $Revision$ $Date$
		 * @mavengroupid $GroupId$
		 * @mavenartifactid $ArtifactId$
		 */
		@DisplayName("Field reference from function")
		@Nested
		public class FieldReference extends AbstractSarlTest {

			private final String THIS_FIELD = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  var field : int = 5",
					"  def fct(param : int = this.field) { }",
					"}");

			@Test
			@DisplayName("this.field parsing")
			@Tag("sarlValidation")
			public void parsing_thisField() throws Exception {
				SarlScript mas = file(getParseHelper(), THIS_FIELD);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("this.field compiling")
			public void compiling_thisField() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", THIS_FIELD, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  private int field = 5;",
						"  ",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"this.field\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return this.field;",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @Override",
						"  @Pure",
						"  @SyntheticMember",
						"  public boolean equals(final Object obj) {",
						"    if (this == obj)",
						"      return true;",
						"    if (obj == null)",
						"      return false;",
						"    if (getClass() != obj.getClass())",
						"      return false;",
						"    XXX other = (XXX) obj;",
						"    if (other.field != this.field)",
						"      return false;",
						"    return super.equals(obj);",
						"  }",
						"  ",
						"  @Override",
						"  @Pure",
						"  @SyntheticMember",
						"  public int hashCode() {",
						"    int result = super.hashCode();",
						"    final int prime = 31;",
						"    result = prime * result + Integer.hashCode(this.field);",
						"    return result;",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

			private final String IMPLICIT_THIS_FIELD = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  var field : int = 5",
					"  def fct(param : int = field) { }",
					"}");

			@Test
			@DisplayName("Field parsing without this")
			@Tag("sarlValidation")
			public void parsing_fieldDirect() throws Exception {
				SarlScript mas = file(getParseHelper(), IMPLICIT_THIS_FIELD);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Field compiling without this")
			public void compiling_fieldDirect() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", IMPLICIT_THIS_FIELD, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  private int field = 5;",
						"  ",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"field\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return this.field;",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @Override",
						"  @Pure",
						"  @SyntheticMember",
						"  public boolean equals(final Object obj) {",
						"    if (this == obj)",
						"      return true;",
						"    if (obj == null)",
						"      return false;",
						"    if (getClass() != obj.getClass())",
						"      return false;",
						"    XXX other = (XXX) obj;",
						"    if (other.field != this.field)",
						"      return false;",
						"    return super.equals(obj);",
						"  }",
						"  ",
						"  @Override",
						"  @Pure",
						"  @SyntheticMember",
						"  public int hashCode() {",
						"    int result = super.hashCode();",
						"    final int prime = 31;",
						"    result = prime * result + Integer.hashCode(this.field);",
						"    return result;",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

			private final String THIS_FINAL_FIELD = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  val field : int = 5",
					"  def fct(param : int = this.field) { }",
					"}");

			@Test
			@DisplayName("Final this.field parsing")
			@Tag("sarlValidation")
			public void parsing_finalThisField() throws Exception {
				SarlScript mas = file(getParseHelper(), THIS_FINAL_FIELD);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Final this.field compiling")
			public void compiling_finalThisField() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", THIS_FINAL_FIELD, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  private final int field = 5;",
						"  ",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"this.field\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return this.field;",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @Override",
						"  @Pure",
						"  @SyntheticMember",
						"  public boolean equals(final Object obj) {",
						"    if (this == obj)",
						"      return true;",
						"    if (obj == null)",
						"      return false;",
						"    if (getClass() != obj.getClass())",
						"      return false;",
						"    XXX other = (XXX) obj;",
						"    if (other.field != this.field)",
						"      return false;",
						"    return super.equals(obj);",
						"  }",
						"  ",
						"  @Override",
						"  @Pure",
						"  @SyntheticMember",
						"  public int hashCode() {",
						"    int result = super.hashCode();",
						"    final int prime = 31;",
						"    result = prime * result + Integer.hashCode(this.field);",
						"    return result;",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

			private final String IMPLICIT_THIS_FINAL_FIELD = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  val field : int = 5",
					"  def fct(param : int = field) { }",
					"}");

			@Test
			@DisplayName("Final field parsing without this")
			@Tag("sarlValidation")
			public void parsing_finalFieldDirect() throws Exception {
				SarlScript mas = file(getParseHelper(), IMPLICIT_THIS_FINAL_FIELD);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Final field compiling without this")
			public void compiling_finalFieldDirect() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", IMPLICIT_THIS_FINAL_FIELD, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
						"import io.sarl.lang.core.annotation.DefaultValueUse;",
						"import io.sarl.lang.core.annotation.SarlElementType;",
						"import io.sarl.lang.core.annotation.SarlSourceCode;",
						"import io.sarl.lang.core.annotation.SarlSpecification;",
						"import io.sarl.lang.core.annotation.SyntheticMember;",
						"import org.eclipse.xtext.xbase.lib.Pure;",
						"import org.eclipse.xtext.xbase.lib.XbaseGenerated;",
						"",
						"@SarlSpecification(\"" + SARLVersion.SPECIFICATION_RELEASE_VERSION_STRING + "\")",
						"@SarlElementType(" + SarlPackage.SARL_CLASS + ")",
						"@XbaseGenerated",
						"@SuppressWarnings(\"all\")",
						"public class XXX {",
						"  private final int field = 5;",
						"  ",
						"  @DefaultValueSource",
						"  public void fct(@DefaultValue(\"io.sarl.lang.tests.bug612.XXX#FCT_0\") final int param) {",
						"  }",
						"  ",
						"  /**",
						"   * Default value for the parameter param",
						"   */",
						"  @Pure",
						"  @SyntheticMember",
						"  @SarlSourceCode(\"field\")",
						"  private final int $DEFAULT_VALUE$FCT_0() {",
						"    return this.field;",
						"  }",
						"  ",
						"  @DefaultValueUse(\"int\")",
						"  @SyntheticMember",
						"  public final void fct() {",
						"    fct($DEFAULT_VALUE$FCT_0());",
						"  }",
						"  ",
						"  @Override",
						"  @Pure",
						"  @SyntheticMember",
						"  public boolean equals(final Object obj) {",
						"    if (this == obj)",
						"      return true;",
						"    if (obj == null)",
						"      return false;",
						"    if (getClass() != obj.getClass())",
						"      return false;",
						"    XXX other = (XXX) obj;",
						"    if (other.field != this.field)",
						"      return false;",
						"    return super.equals(obj);",
						"  }",
						"  ",
						"  @Override",
						"  @Pure",
						"  @SyntheticMember",
						"  public int hashCode() {",
						"    int result = super.hashCode();",
						"    final int prime = 31;",
						"    result = prime * result + Integer.hashCode(this.field);",
						"    return result;",
						"  }",
						"  ",
						"  @SyntheticMember",
						"  public XXX() {",
						"    super();",
						"  }",
						"}",
						""));
			}

			private final String EXPRESSION = multilineString(
					"package io.sarl.lang.tests.bug612",
					"class XXX {",
					"  var field : int = 5",
					"  def fct(param : int = field * 7) { }",
					"}");

			@Test
			@DisplayName("Expression parsing")
			@Tag("sarlValidation")
			public void parsing_fieldExpr() throws Exception {
				SarlScript mas = file(getParseHelper(), EXPRESSION);
				final Validator validator = validate(getValidationHelper(), getInjector(), mas);
				validator.assertNoIssues();
			}

			@Test
			@Tag("compileToJava")
			@DisplayName("Expression compiling")
			public void compiling_fieldExpr() throws Exception {
				getCompileHelper().assertCompilesTo("io.sarl.lang.tests.bug612.XXX", EXPRESSION, multilineString(
						"package io.sarl.lang.tests.bug612;",
						"",
						"import io.sarl.lang.core.annotation.DefaultValue;",
						"import io.sarl.lang.core.annotation.DefaultValueSource;",
