diff --git a/main/coreplugins/io.sarl.lang/src/io/sarl/lang/jvmmodel/SARLJvmModelInferrer.java b/main/coreplugins/io.sarl.lang/src/io/sarl/lang/jvmmodel/SARLJvmModelInferrer.java index 1953d60bf0..48ce1118f1 100644 --- a/main/coreplugins/io.sarl.lang/src/io/sarl/lang/jvmmodel/SARLJvmModelInferrer.java +++ b/main/coreplugins/io.sarl.lang/src/io/sarl/lang/jvmmodel/SARLJvmModelInferrer.java @@ -1801,6 +1801,7 @@ protected void transform(final XtendFunction source, final JvmGenericType contai operation2.setNative(false); operation2.setStrictFloatingPoint(false); operation2.setSynchronized(false); + this.associator.associate(source, operation2); copyTypeParametersFromJvmOperation(operation, operation2); diff --git a/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/Messages.java b/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/Messages.java index e0fec70a39..ab0434717c 100644 --- a/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/Messages.java +++ b/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/Messages.java @@ -130,6 +130,7 @@ private Messages() { public static String SARLValidator_91; public static String SARLValidator_92; public static String SARLValidator_93; + public static String SARLValidator_94; public static String SARLSyntaxErrorMessageProvider_0; public static String SARLSyntaxErrorMessageProvider_1; } diff --git a/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/SARLValidator.java b/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/SARLValidator.java index fbe48222ce..08b7402567 100644 --- a/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/SARLValidator.java +++ b/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/SARLValidator.java @@ -61,6 +61,7 @@ import static org.eclipse.xtend.core.validation.IssueCodes.OBSOLETE_OVERRIDE; import static org.eclipse.xtend.core.validation.IssueCodes.OVERRIDDEN_FINAL; import static org.eclipse.xtend.core.validation.IssueCodes.OVERRIDE_REDUCES_VISIBILITY; +import static org.eclipse.xtend.core.validation.IssueCodes.UNUSED_PRIVATE_MEMBER; import static org.eclipse.xtend.core.validation.IssueCodes.XBASE_LIB_NOT_ON_CLASSPATH; import static org.eclipse.xtend.core.xtend.XtendPackage.Literals.XTEND_CLASS__IMPLEMENTS; import static org.eclipse.xtend.core.xtend.XtendPackage.Literals.XTEND_FIELD__NAME; @@ -123,6 +124,7 @@ import org.eclipse.xtend.core.xtend.XtendInterface; import org.eclipse.xtend.core.xtend.XtendMember; import org.eclipse.xtend.core.xtend.XtendPackage; +import org.eclipse.xtend.core.xtend.XtendParameter; import org.eclipse.xtend.core.xtend.XtendTypeDeclaration; import org.eclipse.xtend.lib.annotations.Accessors; import org.eclipse.xtend.lib.annotations.Data; @@ -184,6 +186,7 @@ import org.eclipse.xtext.xbase.typesystem.references.StandardTypeReferenceOwner; import org.eclipse.xtext.xbase.util.XbaseUsageCrossReferencer; import org.eclipse.xtext.xbase.validation.FeatureNameValidator; +import org.eclipse.xtext.xbase.validation.UIStrings; import io.sarl.lang.SARLVersion; import io.sarl.lang.annotation.EarlyExit; @@ -404,6 +407,9 @@ public class SARLValidator extends AbstractSARLValidator { @Inject private IImmutableTypeValidator immutableTypeValidator; + @Inject + private UIStrings uiStrings; + // Update the annotation target information { final ImmutableMultimap.Builder, ElementType> result = ImmutableMultimap.builder(); @@ -969,8 +975,7 @@ public void checkFinalFieldInitialization(SarlAgent agent) { * @param feature the syntactic feature related to the supertypes. * @param defaultSignatures the signatures of the default constructors for the given container. */ - @SuppressWarnings({"checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity", - "checkstyle:nestedifdepth"}) + @SuppressWarnings({"checkstyle:cyclomaticcomplexity", "checkstyle:npathcomplexity", "checkstyle:nestedifdepth"}) protected void checkSuperConstructor( XtendTypeDeclaration container, EStructuralFeature feature, @@ -2890,6 +2895,56 @@ public void checkTopElementsAreUnique(SarlScript script) { } } + /** Replies if the given function has a default value for one of its parameters. + * + * @param function the function to test. + * @return {@code true} if one parameter has a default value. + */ + @SuppressWarnings("static-method") + protected boolean isDefaultValuedParameterFunction(XtendFunction function) { + for (final XtendParameter parameter : function.getParameters()) { + if (parameter instanceof SarlFormalParameter) { + final SarlFormalParameter sarlParameter = (SarlFormalParameter) parameter; + if (sarlParameter.getDefaultValue() != null) { + return true; + } + } + } + return false; + } + + @Check + @Override + public void checkLocalUsageOfDeclaredXtendFunction(XtendFunction function) { + if (doCheckValidMemberName(function) && !isIgnored(UNUSED_PRIVATE_MEMBER)) { + final JvmOperation mainOperation; + if (function.isDispatch()) { + mainOperation = this.associations.getDispatchOperation(function); + } else { + mainOperation = this.associations.getDirectlyInferredOperation(function); + } + if (mainOperation != null && mainOperation.getVisibility() == JvmVisibility.PRIVATE) { + final EObject outerType = getOutermostType(function); + boolean isUsed = isLocallyUsed(mainOperation, outerType); + if (!isUsed && isDefaultValuedParameterFunction(function)) { + for (final EObject jvmElement : this.associations.getJvmElements(function)) { + if (jvmElement != mainOperation && jvmElement instanceof JvmOperation + && isLocallyUsed(jvmElement, outerType)) { + isUsed = true; + // break the loop + break; + } + } + } + if (!isUsed) { + final String message = MessageFormat.format(Messages.SARLValidator_94, + mainOperation.getSimpleName(), this.uiStrings.parameters(mainOperation), getDeclaratorName(mainOperation)); + addIssueToState(UNUSED_PRIVATE_MEMBER, message, XtendPackage.Literals.XTEND_FUNCTION__NAME); + } + } + } + } + /** The modifier validator for constructors. * * @author $Author: sgalland$ diff --git a/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/messages.properties b/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/messages.properties index 0e421c7338..fd06cdd6ae 100644 --- a/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/messages.properties +++ b/main/coreplugins/io.sarl.lang/src/io/sarl/lang/validation/messages.properties @@ -87,6 +87,7 @@ SARLValidator_90=Forbidden annotation to the agent-oriented feature of type {0}. SARLValidator_91=The field {0} should be synchronized for avoiding value inconsistency due to parallel execution. SARLValidator_92=Discouraged use of the feature ''{0}'. You should not use the feature ''{0}'', or one of its member as argument of an action because it may be change by a border effect. SARLValidator_93=Duplicate type {0}. +SARLValidator_94=The method {0}{1} from the type {2} is never used locally. SARLSyntaxErrorMessageProvider_0=''{0}'' is a reserved keyword which is not allowed as identifier. Please choose another word or alternatively confuse your co-workers by escaping it like this: "{1}". SARLSyntaxErrorMessageProvider_1=''{0}'' is a reserved keyword which is not allowed as identifier. Please choose another word. diff --git a/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00999/Bug895.java b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00999/Bug895.java new file mode 100644 index 0000000000..e0b3340f94 --- /dev/null +++ b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00999/Bug895.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2014-2018 the original authors or 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.lang.tests.bugs.to00999; + +import com.google.inject.Inject; +import org.eclipse.xtend.core.validation.IssueCodes; +import org.eclipse.xtext.xbase.testing.CompilationTestHelper; +import org.junit.Test; + +import io.sarl.lang.SARLVersion; +import io.sarl.lang.sarl.SarlPackage; +import io.sarl.lang.sarl.SarlScript; +import io.sarl.tests.api.AbstractSarlTest; +import io.sarl.tests.api.AbstractSarlTest.Validator; + +/** Testing class for issue: Invalid "function not used" warning for functions with default valued parameter. + * + *

https://github.com/sarl/sarl/issues/895 + * + * @author $Author: sgalland$ + * @author $Author: alombard$ + * @version $Name$ $Revision$ $Date$ + * @mavengroupid $GroupId$ + * @mavenartifactid $ArtifactId$ + * @see "https://github.com/sarl/sarl/issues/895" + */ +@SuppressWarnings("all") +public class Bug895 extends AbstractSarlTest { + + private static final String CALL_WITH_DEFAULT_VALUE = multilineString( + "package io.sarl.lang.tests.bug895", + "class X {", + " private def f1(param : int = 0) : void {", + " }", + " def f {", + " f1", + " }", + "}"); + + + @Test + public void callWithDefaultValue() throws Exception { + SarlScript mas = file(CALL_WITH_DEFAULT_VALUE); + final Validator validator = validate(mas); + validator.assertNoWarnings( + SarlPackage.eINSTANCE.getSarlAction(), + IssueCodes.UNUSED_PRIVATE_MEMBER); + } + + private static final String CALL_WITH_EXPLICIT_VALUE = multilineString( + "package io.sarl.lang.tests.bug895", + "class X {", + " private def f1(param : int = 0) : void {", + " }", + " def f {", + " f1(4)", + " }", + "}"); + + + @Test + public void callWithExplicitValue() throws Exception { + SarlScript mas = file(CALL_WITH_EXPLICIT_VALUE); + final Validator validator = validate(mas); + validator.assertNoWarnings( + SarlPackage.eINSTANCE.getSarlAction(), + IssueCodes.UNUSED_PRIVATE_MEMBER); + } + + private static final String CALL_WITH_CLASSIC_ARGUMENT = multilineString( + "package io.sarl.lang.tests.bug895", + "class X {", + " private def f1(param : int) : void {", + " }", + " def f {", + " f1(4)", + " }", + "}"); + + + @Test + public void callWithClassicArgument() throws Exception { + SarlScript mas = file(CALL_WITH_CLASSIC_ARGUMENT); + final Validator validator = validate(mas); + validator.assertNoWarnings( + SarlPackage.eINSTANCE.getSarlAction(), + IssueCodes.UNUSED_PRIVATE_MEMBER); + } + + private static final String NO_CALL_WITH_CLASSIC_ARGUMENT = multilineString( + "package io.sarl.lang.tests.bug895", + "class X {", + " private def f1(param : int) : void {", + " }", + " private def f2 : void {", + " }", + " def f {", + " f2", + " }", + "}"); + + + @Test + public void noCallWithClassicArgument() throws Exception { + SarlScript mas = file(NO_CALL_WITH_CLASSIC_ARGUMENT); + final Validator validator = validate(mas); + validator.assertWarning( + SarlPackage.eINSTANCE.getSarlAction(), + IssueCodes.UNUSED_PRIVATE_MEMBER, + "f1(int)"); + } + +}