aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2024-06-17 01:33:53 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2024-06-17 01:33:53 +0200
commit9c6eb852e9277537bf1a771bb337eb5e23f4f81c (patch)
treed162aa24f92953f792d5e4f5437cf8303510ebb5 /subprojects
parentrefactor(language): allow rules without preconditions (diff)
downloadrefinery-9c6eb852e9277537bf1a771bb337eb5e23f4f81c.tar.gz
refinery-9c6eb852e9277537bf1a771bb337eb5e23f4f81c.tar.zst
refinery-9c6eb852e9277537bf1a771bb337eb5e23f4f81c.zip
feat(language): warn about partial references
Diffstat (limited to 'subprojects')
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/validation/ActionTargetCollector.java73
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java15
2 files changed, 88 insertions, 0 deletions
diff --git a/subprojects/language/src/main/java/tools/refinery/language/validation/ActionTargetCollector.java b/subprojects/language/src/main/java/tools/refinery/language/validation/ActionTargetCollector.java
new file mode 100644
index 00000000..67cd5777
--- /dev/null
+++ b/subprojects/language/src/main/java/tools/refinery/language/validation/ActionTargetCollector.java
@@ -0,0 +1,73 @@
1/*
2 * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/>
3 *
4 * SPDX-License-Identifier: EPL-2.0
5 */
6package tools.refinery.language.validation;
7
8import com.google.inject.Inject;
9import com.google.inject.Singleton;
10import org.eclipse.xtext.EcoreUtil2;
11import org.eclipse.xtext.util.IResourceScopeCache;
12import org.eclipse.xtext.util.Tuples;
13import tools.refinery.language.model.problem.*;
14
15import java.util.HashSet;
16import java.util.Set;
17
18@Singleton
19public class ActionTargetCollector {
20 private static final String ACTION_TARGETS =
21 "tools.refinery.language.validation.ActionTargetCollector.ACTION_TARGETS";
22
23 @Inject
24 private IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE;
25
26 public boolean isActionTarget(Relation relation) {
27 var problem = EcoreUtil2.getContainerOfType(relation, Problem.class);
28 return problem != null && isActionTarget(problem, relation);
29 }
30
31 public boolean isActionTarget(Problem problem, Relation relation) {
32 var targets = getActionTargets(problem);
33 if (targets.contains(relation)) {
34 return true;
35 }
36 if (relation instanceof ReferenceDeclaration referenceDeclaration) {
37 var opposite = referenceDeclaration.getOpposite();
38 return opposite != null && targets.contains(opposite);
39 }
40 return false;
41 }
42
43 protected Set<Relation> getActionTargets(Problem problem) {
44 var resource = problem.eResource();
45 if (resource == null) {
46 return doGetActionTargets(problem);
47 }
48 return cache.get(Tuples.create(problem, ACTION_TARGETS), resource, () -> doGetActionTargets(problem));
49 }
50
51 protected Set<Relation> doGetActionTargets(Problem problem) {
52 var targets = new HashSet<Relation>();
53 for (var statement : problem.getStatements()) {
54 if (statement instanceof RuleDefinition ruleDefinition) {
55 collectTargets(ruleDefinition, targets);
56 }
57 }
58 return targets;
59 }
60
61 private static void collectTargets(RuleDefinition ruleDefinition, HashSet<Relation> targets) {
62 for (var consequent : ruleDefinition.getConsequents()) {
63 for (var action : consequent.getActions()) {
64 if (action instanceof AssertionAction assertionAction) {
65 var target = assertionAction.getRelation();
66 if (target != null) {
67 targets.add(target);
68 }
69 }
70 }
71 }
72 }
73}
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 36a77ac7..84218f17 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
@@ -54,6 +54,7 @@ public class ProblemValidator extends AbstractProblemValidator {
54 public static final String INVALID_ASSIGNMENT_ISSUE = ISSUE_PREFIX + "INVALID_ASSIGNMENT"; 54 public static final String INVALID_ASSIGNMENT_ISSUE = ISSUE_PREFIX + "INVALID_ASSIGNMENT";
55 public static final String TYPE_ERROR = ISSUE_PREFIX + "TYPE_ERROR"; 55 public static final String TYPE_ERROR = ISSUE_PREFIX + "TYPE_ERROR";
56 public static final String VARIABLE_WITHOUT_EXISTS = ISSUE_PREFIX + "VARIABLE_WITHOUT_EXISTS"; 56 public static final String VARIABLE_WITHOUT_EXISTS = ISSUE_PREFIX + "VARIABLE_WITHOUT_EXISTS";
57 public static final String UNUSED_PARTIAL_RELATION = ISSUE_PREFIX + "UNUSED_PARTIAL_RELATION";
57 58
58 @Inject 59 @Inject
59 private ReferenceCounter referenceCounter; 60 private ReferenceCounter referenceCounter;
@@ -62,6 +63,9 @@ public class ProblemValidator extends AbstractProblemValidator {
62 private ExistsVariableCollector existsVariableCollector; 63 private ExistsVariableCollector existsVariableCollector;
63 64
64 @Inject 65 @Inject
66 private ActionTargetCollector actionTargetCollector;
67
68 @Inject
65 private IQualifiedNameConverter qualifiedNameConverter; 69 private IQualifiedNameConverter qualifiedNameConverter;
66 70
67 @Inject 71 @Inject
@@ -336,6 +340,17 @@ public class ProblemValidator extends AbstractProblemValidator {
336 } 340 }
337 341
338 @Check 342 @Check
343 public void checkPartialReference(ReferenceDeclaration referenceDeclaration) {
344 if (referenceDeclaration.getKind() == ReferenceKind.PARTIAL &&
345 !actionTargetCollector.isActionTarget(referenceDeclaration)) {
346 var message = "Add decision or propagation rules to refine partial relation '%s'."
347 .formatted(referenceDeclaration.getName());
348 acceptWarning(message, referenceDeclaration, ProblemPackage.Literals.REFERENCE_DECLARATION__KIND, 0,
349 UNUSED_PARTIAL_RELATION);
350 }
351 }
352
353 @Check
339 public void checkSupertypes(ClassDeclaration classDeclaration) { 354 public void checkSupertypes(ClassDeclaration classDeclaration) {
340 var supertypes = classDeclaration.getSuperTypes(); 355 var supertypes = classDeclaration.getSuperTypes();
341 int supertypeCount = supertypes.size(); 356 int supertypeCount = supertypes.size();