aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/language
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2024-06-01 18:37:20 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2024-06-01 20:17:47 +0200
commit07b4048828d9ef8126282c4626dd3f0729213d91 (patch)
tree4523d01e7802585ae3a3c7ec622d1b0a1e3dfa91 /subprojects/language
parentfix(reasoning): candidate count literal rewriting (diff)
downloadrefinery-07b4048828d9ef8126282c4626dd3f0729213d91.tar.gz
refinery-07b4048828d9ef8126282c4626dd3f0729213d91.tar.zst
refinery-07b4048828d9ef8126282c4626dd3f0729213d91.zip
feat: partial references
References marked as partial are not concretized during model generation. The should be managed by the user manually using propagation rules instead.
Diffstat (limited to 'subprojects/language')
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/Problem.xtext2
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java14
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java5
-rw-r--r--subprojects/language/src/test/java/tools/refinery/language/tests/validation/OppositeValidationTest.java36
4 files changed, 46 insertions, 11 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext
index ebb5bf71..10e994a0 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext
+++ b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext
@@ -45,7 +45,7 @@ AggregatorDeclaration:
45 "extern" "aggregator" name=Identifier "."; 45 "extern" "aggregator" name=Identifier ".";
46 46
47enum ReferenceKind: 47enum ReferenceKind:
48 REFERENCE="refers" | CONTAINMENT="contains" | CONTAINER="container"; 48 REFERENCE="refers" | CONTAINMENT="contains" | CONTAINER="container" | PARTIAL="partial";
49 49
50ReferenceDeclaration: 50ReferenceDeclaration:
51 (referenceType=[Relation|NonContainmentQualifiedName] | 51 (referenceType=[Relation|NonContainmentQualifiedName] |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java b/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java
index 9daa8f61..e1820261 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/utils/ProblemUtil.java
@@ -42,13 +42,11 @@ public final class ProblemUtil {
42 } 42 }
43 43
44 public static boolean isImplicit(EObject eObject) { 44 public static boolean isImplicit(EObject eObject) {
45 if (eObject instanceof Node node) { 45 return switch (eObject) {
46 return isImplicitNode(node); 46 case Node node -> isImplicitNode(node);
47 } else if (eObject instanceof Variable variable) { 47 case Variable variable -> isImplicitVariable(variable);
48 return isImplicitVariable(variable); 48 default -> false;
49 } else { 49 };
50 return false;
51 }
52 } 50 }
53 51
54 public static boolean isError(EObject eObject) { 52 public static boolean isError(EObject eObject) {
@@ -119,7 +117,7 @@ public final class ProblemUtil {
119 return false; 117 return false;
120 } 118 }
121 return switch (kind) { 119 return switch (kind) {
122 case CONTAINMENT -> false; 120 case CONTAINMENT, PARTIAL -> false;
123 case CONTAINER -> true; 121 case CONTAINER -> true;
124 case DEFAULT, REFERENCE -> { 122 case DEFAULT, REFERENCE -> {
125 var opposite = referenceDeclaration.getOpposite(); 123 var opposite = referenceDeclaration.getOpposite();
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 9f5fdeae..754572d1 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
@@ -318,6 +318,11 @@ public class ProblemValidator extends AbstractProblemValidator {
318 referenceDeclaration, ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE, 0, 318 referenceDeclaration, ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE, 0,
319 INVALID_OPPOSITE_ISSUE); 319 INVALID_OPPOSITE_ISSUE);
320 } 320 }
321 } else if (kind == ReferenceKind.PARTIAL && opposite != null && opposite.getKind() != ReferenceKind.PARTIAL) {
322 acceptError("Opposite '%s' of partial reference '%s' is not a partial reference."
323 .formatted(opposite.getName(), referenceDeclaration.getName()),
324 referenceDeclaration, ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE, 0,
325 INVALID_OPPOSITE_ISSUE);
321 } 326 }
322 } 327 }
323 328
diff --git a/subprojects/language/src/test/java/tools/refinery/language/tests/validation/OppositeValidationTest.java b/subprojects/language/src/test/java/tools/refinery/language/tests/validation/OppositeValidationTest.java
index 57602377..d73ef8e7 100644
--- a/subprojects/language/src/test/java/tools/refinery/language/tests/validation/OppositeValidationTest.java
+++ b/subprojects/language/src/test/java/tools/refinery/language/tests/validation/OppositeValidationTest.java
@@ -57,6 +57,18 @@ class OppositeValidationTest {
57 class Foo { 57 class Foo {
58 Foo foo[] opposite foo 58 Foo foo[] opposite foo
59 } 59 }
60 """, """
61 class Foo {
62 partial Bar bar opposite foo
63 }
64
65 class Bar {
66 partial Foo foo opposite bar
67 }
68 """, """
69 class Foo {
70 partial Foo foo[] opposite foo
71 }
60 """}) 72 """})
61 void validOppositeTest(String text) { 73 void validOppositeTest(String text) {
62 var problem = parseHelper.parse(text); 74 var problem = parseHelper.parse(text);
@@ -188,7 +200,7 @@ class OppositeValidationTest {
188 } 200 }
189 201
190 @ParameterizedTest 202 @ParameterizedTest
191 @ValueSource(strings = {"Foo foo", "container Foo foo"}) 203 @ValueSource(strings = {"Foo foo", "container Foo foo", "partial Foo foo"})
192 void containerInvalidOppositeTest(String reference) { 204 void containerInvalidOppositeTest(String reference) {
193 var problem = parseHelper.parse(""" 205 var problem = parseHelper.parse("""
194 class Foo { 206 class Foo {
@@ -203,7 +215,27 @@ class OppositeValidationTest {
203 assertThat(issues, hasItem(allOf( 215 assertThat(issues, hasItem(allOf(
204 hasProperty("severity", is(Diagnostic.ERROR)), 216 hasProperty("severity", is(Diagnostic.ERROR)),
205 hasProperty("issueCode", is(ProblemValidator.INVALID_OPPOSITE_ISSUE)), 217 hasProperty("issueCode", is(ProblemValidator.INVALID_OPPOSITE_ISSUE)),
206 hasProperty("message", stringContainsInOrder("foo", "bar")) 218 hasProperty("message", stringContainsInOrder("foo", "container", "bar"))
219 )));
220 }
221
222 @ParameterizedTest
223 @ValueSource(strings = {"Foo foo", "contains Foo foo", "container Foo foo"})
224 void partialWithConcreteOppositeTest(String reference) {
225 var problem = parseHelper.parse("""
226 class Foo {
227 partial Bar bar opposite foo
228 }
229
230 class Bar {
231 %s opposite bar
232 }
233 """.formatted(reference));
234 var issues = problem.validate();
235 assertThat(issues, hasItem(allOf(
236 hasProperty("severity", is(Diagnostic.ERROR)),
237 hasProperty("issueCode", is(ProblemValidator.INVALID_OPPOSITE_ISSUE)),
238 hasProperty("message", stringContainsInOrder("foo", "partial", "bar"))
207 ))); 239 )));
208 } 240 }
209} 241}