From 23b0925f419894cf3f4699fa49dd91fb2ee4f4a5 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Thu, 29 Feb 2024 16:33:59 +0100 Subject: feat(language): validate assignment expressions --- .../language/validation/ProblemValidator.java | 32 ++++++++++++ .../tests/validation/AssignmentValidationTest.java | 61 ++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 subprojects/language/src/test/java/tools/refinery/language/tests/validation/AssignmentValidationTest.java (limited to 'subprojects') diff --git a/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java b/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java index 560f612a..7f45bc20 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java +++ b/subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java @@ -63,6 +63,8 @@ public class ProblemValidator extends AbstractProblemValidator { public static final String UNSUPPORTED_ASSERTION_ISSUE = ISSUE_PREFIX + "UNSUPPORTED_ASSERTION"; + public static final String INVALID_ASSIGNMENT_ISSUE = ISSUE_PREFIX + "INVALID_ASSIGNMENT"; + @Inject private ReferenceCounter referenceCounter; @@ -493,4 +495,34 @@ public class ProblemValidator extends AbstractProblemValidator { } } } + + @Check + private void checkAssignmentExpr(AssignmentExpr assignmentExpr) { + var left = assignmentExpr.getLeft(); + if (left == null) { + // Syntactically invalid, so we already emit an error. + return; + } + if (!(left instanceof VariableOrNodeExpr variableOrNodeExpr)) { + var message = "Left side of an assignment must be variable."; + acceptError(message, assignmentExpr, ProblemPackage.Literals.BINARY_EXPR__LEFT, + 0, INVALID_ASSIGNMENT_ISSUE); + return; + } + var target = variableOrNodeExpr.getVariableOrNode(); + if (target == null) { + // Syntactically invalid, so we already emit an error. + return; + } + if (target instanceof Parameter) { + var message = "Parameters cannot be assigned."; + acceptError(message, variableOrNodeExpr, ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE, + 0, INVALID_ASSIGNMENT_ISSUE); + } + if (target instanceof Node) { + var message = "Nodes cannot be assigned."; + acceptError(message, variableOrNodeExpr, ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE, + 0, INVALID_ASSIGNMENT_ISSUE); + } + } } diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/validation/AssignmentValidationTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/validation/AssignmentValidationTest.java new file mode 100644 index 00000000..a9e0e311 --- /dev/null +++ b/subprojects/language/src/test/java/tools/refinery/language/tests/validation/AssignmentValidationTest.java @@ -0,0 +1,61 @@ +/* + * SPDX-FileCopyrightText: 2024 The Refinery Authors + * + * SPDX-License-Identifier: EPL-2.0 + */ +package tools.refinery.language.tests.validation; + + +import com.google.inject.Inject; +import org.eclipse.xtext.testing.InjectWith; +import org.eclipse.xtext.testing.extensions.InjectionExtension; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; +import tools.refinery.language.model.tests.utils.ProblemParseHelper; +import tools.refinery.language.tests.ProblemInjectorProvider; +import tools.refinery.language.validation.ProblemValidator; + +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.*; + +@ExtendWith(InjectionExtension.class) +@InjectWith(ProblemInjectorProvider.class) +class AssignmentValidationTest { + @Inject + private ProblemParseHelper parseHelper; + + @ParameterizedTest + @ValueSource(strings = {""" + pred foo(node a) <-> 5 is 5. + """, """ + pred foo(node a) <-> b + 2 is 5. + """, """ + pred foo(node a) <-> a is 5. + """, """ + node(n). + pred foo(node a) <-> n is 5. + """, """ + enum E { A, B } + pred foo(node a) <-> B is 5. + """}) + void invalidAssignmentTest(String text) { + var problem = parseHelper.parse(text); + var issues = problem.validate(); + assertThat(issues, hasItem(hasProperty("issueCode", is( + ProblemValidator.INVALID_ASSIGNMENT_ISSUE + )))); + } + + @Test + void validAssignmentTest() { + var problem = parseHelper.parse(""" + pred foo(node a) <-> b is 5. + """); + var issues = problem.validate(); + assertThat(issues, not(hasItem(hasProperty("issueCode", is( + ProblemValidator.INVALID_ASSIGNMENT_ISSUE + ))))); + } +} -- cgit v1.2.3-54-g00ecf