From f4708c52194d0b3b2185aa7620ba98c3274d2af1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?St=C3=A9phane=20Galland?= Date: Sun, 18 Feb 2018 09:21:59 +0100 Subject: [PATCH] [lang] Adding tests on field read accesses for prepare Xtext PR. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Galland --- .../sarl/lang/validation/SARLValidator.java | 71 +- .../{Bug208.java => Bug208And810.java} | 7 +- .../sarl/lang/tests/bugs/to00699/Bug483.java | 4 +- .../sarl/lang/tests/bugs/to00699/Bug505.java | 12 +- .../parsing/general/ReadWriteAccessTest.java | 677 ++++++++++++++++++ 5 files changed, 725 insertions(+), 46 deletions(-) rename tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00399/{Bug208.java => Bug208And810.java} (98%) create mode 100644 tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/general/parsing/general/ReadWriteAccessTest.java 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 dcef069e59..77c3d6c5ea 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 @@ -162,7 +162,6 @@ import org.eclipse.xtext.xbase.XExpression; import org.eclipse.xtext.xbase.XFeatureCall; import org.eclipse.xtext.xbase.XForLoopExpression; -import org.eclipse.xtext.xbase.XMemberFeatureCall; import org.eclipse.xtext.xbase.XSynchronizedExpression; import org.eclipse.xtext.xbase.XTypeLiteral; import org.eclipse.xtext.xbase.XVariableDeclaration; @@ -2570,38 +2569,6 @@ private static EObject getOutermostType(XtendMember member) { return result; } - /** Replies if the given object is locally assigned. - * - *

An object is locally assigned when it is the left operand of an assignment operation. - * - * @param target the object to test. - * @param containerToFindUsage the container in which the usages should be find. - * @return {@code true} if the given object is assigned. - * @since 0.7 - */ - protected boolean isLocallyAssigned(EObject target, EObject containerToFindUsage) { - if (this.readAndWriteTracking.isAssigned(target)) { - return true; - } - final Collection usages = XbaseUsageCrossReferencer.find(target, containerToFindUsage); - // field are assigned when they are not used as the left operand of an assignment operator. - for (final Setting usage : usages) { - EObject object = usage.getEObject(); - while (object instanceof XMemberFeatureCall) { - object = ((XMemberFeatureCall) object).eContainer(); - } - if (object instanceof XAssignment) { - final XAssignment assignment = (XAssignment) object; - if (assignment.getFeature() == target) { - // Mark the field as assigned in order to be faster during the next assignment test. - this.readAndWriteTracking.markAssignmentAccess(target); - return true; - } - } - } - return false; - } - @Override protected boolean isInitialized(JvmField input) { if (super.isInitialized(input)) { @@ -2631,6 +2598,35 @@ protected boolean isInitialized(JvmField input) { return false; } + /** Replies if the given object is locally assigned. + * + *

An object is locally assigned when it is the left operand of an assignment operation. + * + * @param target the object to test. + * @param containerToFindUsage the container in which the usages should be find. + * @return {@code true} if the given object is assigned. + * @since 0.7 + */ + protected boolean isLocallyAssigned(EObject target, EObject containerToFindUsage) { + if (this.readAndWriteTracking.isAssigned(target)) { + return true; + } + final Collection usages = XbaseUsageCrossReferencer.find(target, containerToFindUsage); + // field are assigned when they are not used as the left operand of an assignment operator. + for (final Setting usage : usages) { + final EObject object = usage.getEObject(); + if (object instanceof XAssignment) { + final XAssignment assignment = (XAssignment) object; + if (assignment.getFeature() == target) { + // Mark the field as assigned in order to be faster during the next assignment test. + this.readAndWriteTracking.markAssignmentAccess(target); + return true; + } + } + } + return false; + } + @SuppressWarnings("checkstyle:npathcomplexity") @Override protected boolean isLocallyUsed(EObject target, EObject containerToFindUsage) { @@ -2639,13 +2635,10 @@ protected boolean isLocallyUsed(EObject target, EObject containerToFindUsage) { return true; } final Collection usages = XbaseUsageCrossReferencer.find(target, containerToFindUsage); - // field are used when they are not used as the left operand of an assignment operator. - if (target instanceof JvmField) { + // field and local variables are used when they are not used as the left operand of an assignment operator. + if (target instanceof XVariableDeclaration || target instanceof JvmField) { for (final Setting usage : usages) { - EObject object = usage.getEObject(); - while (object instanceof XMemberFeatureCall) { - object = ((XMemberFeatureCall) object).eContainer(); - } + final EObject object = usage.getEObject(); if (object instanceof XAssignment) { final XAssignment assignment = (XAssignment) object; if (assignment.getFeature() != target) { diff --git a/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00399/Bug208.java b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00399/Bug208And810.java similarity index 98% rename from tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00399/Bug208.java rename to tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00399/Bug208And810.java index b80774aa06..73b30350ee 100644 --- a/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00399/Bug208.java +++ b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00399/Bug208And810.java @@ -33,14 +33,15 @@ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ * @see "https://github.com/sarl/sarl/issues/208" + * @see "https://github.com/sarl/sarl/issues/810" */ @RunWith(Suite.class) @SuiteClasses({ - Bug208.WithProblem.class, - Bug208.WithoutProblem.class, + Bug208And810.WithProblem.class, + Bug208And810.WithoutProblem.class, }) @SuppressWarnings("all") -public class Bug208 { +public class Bug208And810 { public static class WithProblem extends AbstractSarlTest { diff --git a/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00699/Bug483.java b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00699/Bug483.java index 615333d386..b7847b5999 100644 --- a/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00699/Bug483.java +++ b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00699/Bug483.java @@ -421,7 +421,9 @@ public void copyInLocalVariable_02() throws Exception { " x = 1", " }", "}")); - validate(mas).assertNoIssues(); + validate(mas).assertWarning( + XbasePackage.eINSTANCE.getXVariableDeclaration(), + org.eclipse.xtext.xbase.validation.IssueCodes.UNUSED_LOCAL_VARIABLE); } @Test diff --git a/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00699/Bug505.java b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00699/Bug505.java index 1a929e8ee3..f168b18279 100644 --- a/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00699/Bug505.java +++ b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/bugs/to00699/Bug505.java @@ -16,19 +16,23 @@ package io.sarl.lang.tests.bugs.to00699; import com.google.inject.Inject; +import org.eclipse.xtext.xbase.XbasePackage; 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.lang.validation.IssueCodes; import io.sarl.tests.api.AbstractSarlTest; -/** +/** Text for issue 505: Reference instance methods or fields in abstract class. + * * @author $Author: sgalland$ * @version $Name$ $Revision$ $Date$ * @mavengroupid $GroupId$ * @mavenartifactid $ArtifactId$ + * @see "https://github.com/sarl/sarl/issues/505" */ @SuppressWarnings("all") public class Bug505 extends AbstractSarlTest { @@ -94,7 +98,7 @@ public class Bug505 extends AbstractSarlTest { @Test public void snipset1() throws Exception { SarlScript mas = file(snippet1); - validate(mas).assertNoIssues(); + validate(mas).assertNoErrors(); } @Test @@ -288,7 +292,9 @@ public void snipset4Compilation() throws Exception { @Test public void snipset5() throws Exception { SarlScript mas = file(snippet5); - validate(mas).assertNoIssues(); + validate(mas).assertWarning( + XbasePackage.eINSTANCE.getXAssignment(), + IssueCodes.POTENTIAL_FIELD_SYNCHRONIZATION_PROBLEM); } @Test diff --git a/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/general/parsing/general/ReadWriteAccessTest.java b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/general/parsing/general/ReadWriteAccessTest.java new file mode 100644 index 0000000000..c155aa84d0 --- /dev/null +++ b/tests/io.sarl.lang.tests/src/test/java/io/sarl/lang/tests/general/parsing/general/ReadWriteAccessTest.java @@ -0,0 +1,677 @@ +/* + * 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.general.parsing.general; + +import org.eclipse.xtend.core.validation.IssueCodes; +import org.eclipse.xtext.xbase.XbasePackage; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.junit.runners.Suite.SuiteClasses; + +import io.sarl.lang.sarl.SarlPackage; +import io.sarl.lang.sarl.SarlScript; +import io.sarl.tests.api.AbstractSarlTest; + +/** Test the read/write accesses. + * + * FIXME: See issue #809. Remove when Xtext PR is merged: https://github.com/eclipse/xtext-extras/pull/232. + * + * @author $Author: sgalland$ + * @version $Name$ $Revision$ $Date$ + * @mavengroupid $GroupId$ + * @mavenartifactid $ArtifactId$ + * @since 0.7 + * @see "https://github.com/eclipse/xtext-extras/pull/232" + */ +@RunWith(Suite.class) +@SuiteClasses({ + ReadWriteAccessTest.FieldReadTest.class, + ReadWriteAccessTest.VariableReadTest.class, +}) +@SuppressWarnings("all") +public class ReadWriteAccessTest { + + public static class FieldReadTest extends AbstractSarlTest { + + @Test + public void test000() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " val f = 1", + "}" + )); + validate(mas).assertWarning( + SarlPackage.eINSTANCE.getSarlField(), + IssueCodes.UNUSED_PRIVATE_MEMBER, + "field C1.f"); + } + + @Test + public void test001() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + "}" + )); + validate(mas).assertWarning( + SarlPackage.eINSTANCE.getSarlField(), + IssueCodes.UNUSED_PRIVATE_MEMBER, + "field C1.f"); + } + + @Test + public void test002() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + " def fct : void {", + " f = 2", + " }", + "}" + )); + validate(mas).assertWarning( + SarlPackage.eINSTANCE.getSarlField(), + IssueCodes.UNUSED_PRIVATE_MEMBER, + "field C1.f"); + } + + @Test + public void test003() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + " def fct : int {", + " var x = f", + " return x", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test004() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + " def fct : void {", + " f = f + 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test005() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + " def fct : void {", + " this.f = 2", + " }", + "}" + )); + validate(mas).assertWarning( + SarlPackage.eINSTANCE.getSarlField(), + IssueCodes.UNUSED_PRIVATE_MEMBER, + "field C1.f"); + } + + @Test + public void test006() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + " def fct : int {", + " var x = this.f", + " return x", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test007() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + " def fct : void {", + " this.f = this.f + 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test008() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + " def fct : void {", + " fct2(this.f)", + " }", + " def fct2(p : int) : void {", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test009() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var f = 1", + " def fct : void {", + " for (i : 1..f) { }", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test010() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct : C11 {", + " return this.x", + " }", + " static class C11 {", + " var f = 1", + " }", + "}" + )); + validate(mas).assertWarning( + SarlPackage.eINSTANCE.getSarlField(), + IssueCodes.UNUSED_PRIVATE_MEMBER, + "field C11.f"); + } + + @Test + public void test011() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct : void {", + " this.x.f = 4", + " }", + " static class C11 {", + " var f = 1", + " }", + "}" + )); + validate(mas).assertWarning( + SarlPackage.eINSTANCE.getSarlField(), + IssueCodes.UNUSED_PRIVATE_MEMBER, + "field C11.f"); + } + + @Test + public void test012() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct : int {", + " return this.x.f", + " }", + " static class C11 {", + " var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test013() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct : int {", + " this.x.f = (this.x.f ** 3) as int", + " }", + " static class C11 {", + " var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test014() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct(p : int) : int {", + " if (this.x !== null) {", + " switch (p) {", + " case 1 : { return this.x.f }", + " default: { }", + " }", + " }", + " return 0", + " }", + " static class C11 {", + " var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test015() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : int {", + " return xx().f", + " }", + " def xx : C11 {", + " null", + " }", + " static class C11 {", + " var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test016() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct(x : String) : int {", + " return (x + 35).f", + " }", + " def operator_plus(a : String, b : int) : C11 {", + " null", + " }", + " static class C11 {", + " var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test017() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected val f = 1", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test018() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test019() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + " def fct : void {", + " f = 2", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test020() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + " def fct : int {", + " var x = f", + " return x", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test021() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + " def fct : void {", + " f = f + 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test022() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + " def fct : void {", + " this.f = 2", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test023() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + " def fct : int {", + " var x = this.f", + " return x", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test024() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + " def fct : void {", + " this.f = this.f + 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test025() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + " def fct : void {", + " fct2(this.f)", + " }", + " def fct2(p : int) : void {", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test026() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " protected var f = 1", + " def fct : void {", + " for (i : 1..f) { }", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test027() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct : C11 {", + " return this.x", + " }", + " static class C11 {", + " protected var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test028() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct : void {", + " this.x.f = 4", + " }", + " static class C11 {", + " protected var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test029() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct : int {", + " return this.x.f", + " }", + " static class C11 {", + " protected var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test0130() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct : int {", + " this.x.f = (this.x.f ** 3) as int", + " }", + " static class C11 {", + " protected var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test031() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " var x : C11", + " def fct(p : int) : int {", + " if (this.x !== null) {", + " switch (p) {", + " case 1 : { return this.x.f }", + " default: { }", + " }", + " }", + " return 0", + " }", + " static class C11 {", + " protected var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test032() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : int {", + " return xx().f", + " }", + " def xx : C11 {", + " null", + " }", + " static class C11 {", + " protected var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test033() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct(x : String) : int {", + " return (x + 35).f", + " }", + " def operator_plus(a : String, b : int) : C11 {", + " null", + " }", + " static class C11 {", + " protected var f = 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + } + + public static class VariableReadTest extends AbstractSarlTest { + + @Test + public void test000() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : int {", + " val f = 1", + " 1", + " }", + "}" + )); + validate(mas).assertWarning( + XbasePackage.eINSTANCE.getXVariableDeclaration(), + org.eclipse.xtext.xbase.validation.IssueCodes.UNUSED_LOCAL_VARIABLE, + "variable f"); + } + + @Test + public void test001() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : int {", + " var f = 1", + " 1", + " }", + "}" + )); + validate(mas).assertWarning( + XbasePackage.eINSTANCE.getXVariableDeclaration(), + org.eclipse.xtext.xbase.validation.IssueCodes.UNUSED_LOCAL_VARIABLE, + "variable f"); + } + + @Test + public void test002() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : void {", + " var f : int", + " f = 2", + " }", + "}" + )); + validate(mas).assertWarning( + XbasePackage.eINSTANCE.getXVariableDeclaration(), + org.eclipse.xtext.xbase.validation.IssueCodes.UNUSED_LOCAL_VARIABLE, + "variable f"); + } + + @Test + public void test003() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : int {", + " var f = 1", + " var x = f", + " return x", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test004() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : void {", + " var f = 1", + " f = f + 1", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test005() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : void {", + " var f = 1", + " fct2(f)", + " }", + " def fct2(p : int) : void {", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + @Test + public void test006() throws Exception { + SarlScript mas = file(multilineString( + "class C1 {", + " def fct : void {", + " var f = 1", + " for (i : 1..f) { }", + " }", + "}" + )); + validate(mas).assertNoIssues(); + } + + } + +}