diff options
Diffstat (limited to 'language')
-rw-r--r-- | language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java | 10 | ||||
-rw-r--r-- | language/src/main/java/tools/refinery/language/validation/ProblemValidator.java | 49 |
2 files changed, 58 insertions, 1 deletions
diff --git a/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java b/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java index 56186bc9..7525dfc6 100644 --- a/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java +++ b/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java | |||
@@ -16,7 +16,15 @@ public class ReferenceCounter { | |||
16 | @Inject | 16 | @Inject |
17 | private IResourceScopeCache cache; | 17 | private IResourceScopeCache cache; |
18 | 18 | ||
19 | public Map<EObject, Integer> getReferenceCounts(Problem problem) { | 19 | public int countReferences(Problem problem, EObject eObject) { |
20 | var count = getReferenceCounts(problem).get(eObject); | ||
21 | if (count == null) { | ||
22 | return 0; | ||
23 | } | ||
24 | return count; | ||
25 | } | ||
26 | |||
27 | protected Map<EObject, Integer> getReferenceCounts(Problem problem) { | ||
20 | var resource = problem.eResource(); | 28 | var resource = problem.eResource(); |
21 | if (resource == null) { | 29 | if (resource == null) { |
22 | return doGetReferenceCounts(problem); | 30 | return doGetReferenceCounts(problem); |
diff --git a/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java b/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java index f2378df6..dfd386f5 100644 --- a/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java +++ b/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java | |||
@@ -3,6 +3,19 @@ | |||
3 | */ | 3 | */ |
4 | package tools.refinery.language.validation; | 4 | package tools.refinery.language.validation; |
5 | 5 | ||
6 | import org.eclipse.xtext.EcoreUtil2; | ||
7 | import org.eclipse.xtext.validation.Check; | ||
8 | |||
9 | import com.google.inject.Inject; | ||
10 | |||
11 | import tools.refinery.language.model.ProblemUtil; | ||
12 | import tools.refinery.language.model.problem.Node; | ||
13 | import tools.refinery.language.model.problem.Problem; | ||
14 | import tools.refinery.language.model.problem.ProblemPackage; | ||
15 | import tools.refinery.language.model.problem.Variable; | ||
16 | import tools.refinery.language.model.problem.VariableOrNodeArgument; | ||
17 | import tools.refinery.language.resource.ReferenceCounter; | ||
18 | |||
6 | /** | 19 | /** |
7 | * This class contains custom validation rules. | 20 | * This class contains custom validation rules. |
8 | * | 21 | * |
@@ -10,4 +23,40 @@ package tools.refinery.language.validation; | |||
10 | * https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation | 23 | * https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation |
11 | */ | 24 | */ |
12 | public class ProblemValidator extends AbstractProblemValidator { | 25 | public class ProblemValidator extends AbstractProblemValidator { |
26 | private static final String ISSUE_PREFIX = "tools.refinery.language.validation.ProblemValidator."; | ||
27 | |||
28 | public static final String SINGLETON_VARIABLE_ISSUE = ISSUE_PREFIX + "SINGLETON_VARIABLE"; | ||
29 | |||
30 | public static final String NON_UNIQUE_NODE_ISSUE = ISSUE_PREFIX + "NON_UNIQUE_NODE"; | ||
31 | |||
32 | @Inject | ||
33 | private ReferenceCounter referenceCounter; | ||
34 | |||
35 | @Check | ||
36 | public void checkUniqueVariable(VariableOrNodeArgument argument) { | ||
37 | var variableOrNode = argument.getVariableOrNode(); | ||
38 | if (variableOrNode instanceof Variable variable && ProblemUtil.isImplicitVariable(variable) | ||
39 | && !ProblemUtil.isSingletonVariable(variable)) { | ||
40 | var problem = EcoreUtil2.getContainerOfType(variable, Problem.class); | ||
41 | if (problem != null && referenceCounter.countReferences(problem, variable) <= 1) { | ||
42 | var name = variable.getName(); | ||
43 | var message = "Variable '%s' has only a single reference. Add another reference or mark is as a singleton variable: '_%s'" | ||
44 | .formatted(name, name); | ||
45 | warning(message, argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE, | ||
46 | INSIGNIFICANT_INDEX, SINGLETON_VARIABLE_ISSUE); | ||
47 | } | ||
48 | } | ||
49 | } | ||
50 | |||
51 | @Check | ||
52 | public void checkNonUniqueNode(VariableOrNodeArgument argument) { | ||
53 | var variableOrNode = argument.getVariableOrNode(); | ||
54 | if (variableOrNode instanceof Node node && !ProblemUtil.isUniqueNode(node)) { | ||
55 | var name = node.getName(); | ||
56 | var message = "Only unique nodes can be referenced in predicates. Mark '%s' as unique with the declaration 'unique %s.'" | ||
57 | .formatted(name, name); | ||
58 | error(message, argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE, | ||
59 | INSIGNIFICANT_INDEX, NON_UNIQUE_NODE_ISSUE); | ||
60 | } | ||
61 | } | ||
13 | } | 62 | } |