aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-11-05 21:20:58 +0100
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-11-17 12:41:34 +0100
commit3564713078409adea416b24515a55d7eff666013 (patch)
treec72325c9dfb8f4a8ae8e1d4ed4bea83ef1035c95
parentfeat(langugage): detect ambiguous references (diff)
downloadrefinery-3564713078409adea416b24515a55d7eff666013.tar.gz
refinery-3564713078409adea416b24515a55d7eff666013.tar.zst
refinery-3564713078409adea416b24515a55d7eff666013.zip
feat(language): validate unique names
-rw-r--r--subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java2
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/validation/ProblemValidator.java66
-rw-r--r--subprojects/language/src/main/java/tools/refinery/language/validation/ReferenceCounter.java (renamed from subprojects/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java)2
3 files changed, 60 insertions, 10 deletions
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java
index ea90a82e..9bbce54b 100644
--- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java
+++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java
@@ -18,7 +18,7 @@ import org.eclipse.xtext.resource.IEObjectDescription;
18import org.eclipse.xtext.scoping.IScope; 18import org.eclipse.xtext.scoping.IScope;
19import tools.refinery.language.model.problem.Problem; 19import tools.refinery.language.model.problem.Problem;
20import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; 20import tools.refinery.language.resource.ProblemResourceDescriptionStrategy;
21import tools.refinery.language.resource.ReferenceCounter; 21import tools.refinery.language.validation.ReferenceCounter;
22import tools.refinery.language.utils.ProblemUtil; 22import tools.refinery.language.utils.ProblemUtil;
23 23
24import java.util.ArrayList; 24import java.util.ArrayList;
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 56a934cf..ef04726b 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
@@ -9,15 +9,17 @@
9 */ 9 */
10package tools.refinery.language.validation; 10package tools.refinery.language.validation;
11 11
12import com.google.inject.Inject;
12import org.eclipse.xtext.EcoreUtil2; 13import org.eclipse.xtext.EcoreUtil2;
13import org.eclipse.xtext.validation.Check; 14import org.eclipse.xtext.validation.Check;
14
15import com.google.inject.Inject;
16
17import tools.refinery.language.model.problem.*; 15import tools.refinery.language.model.problem.*;
18import tools.refinery.language.resource.ReferenceCounter;
19import tools.refinery.language.utils.ProblemUtil; 16import tools.refinery.language.utils.ProblemUtil;
20 17
18import java.util.ArrayList;
19import java.util.LinkedHashMap;
20import java.util.LinkedHashSet;
21import java.util.Set;
22
21/** 23/**
22 * This class contains custom validation rules. 24 * This class contains custom validation rules.
23 * <p> 25 * <p>
@@ -29,13 +31,15 @@ public class ProblemValidator extends AbstractProblemValidator {
29 31
30 public static final String SINGLETON_VARIABLE_ISSUE = ISSUE_PREFIX + "SINGLETON_VARIABLE"; 32 public static final String SINGLETON_VARIABLE_ISSUE = ISSUE_PREFIX + "SINGLETON_VARIABLE";
31 33
32 public static final String NON_INDIVIDUAL_NODE_ISSUE = ISSUE_PREFIX + "NON_INDIVIDUAL_NODE"; 34 public static final String NODE_CONSTANT_ISSUE = ISSUE_PREFIX + "NODE_CONSTANT_ISSUE";
35
36 public static final String DUPLICATE_NAME_ISSUE = ISSUE_PREFIX + "DUPLICATE_NAME";
33 37
34 @Inject 38 @Inject
35 private ReferenceCounter referenceCounter; 39 private ReferenceCounter referenceCounter;
36 40
37 @Check 41 @Check
38 public void checkUniqueVariable(VariableOrNodeExpr expr) { 42 public void checkSingletonVariable(VariableOrNodeExpr expr) {
39 var variableOrNode = expr.getVariableOrNode(); 43 var variableOrNode = expr.getVariableOrNode();
40 if (variableOrNode instanceof Variable variable && ProblemUtil.isImplicitVariable(variable) 44 if (variableOrNode instanceof Variable variable && ProblemUtil.isImplicitVariable(variable)
41 && !ProblemUtil.isSingletonVariable(variable)) { 45 && !ProblemUtil.isSingletonVariable(variable)) {
@@ -51,14 +55,60 @@ public class ProblemValidator extends AbstractProblemValidator {
51 } 55 }
52 56
53 @Check 57 @Check
54 public void checkNonUniqueNode(VariableOrNodeExpr expr) { 58 public void checkNodeConstants(VariableOrNodeExpr expr) {
55 var variableOrNode = expr.getVariableOrNode(); 59 var variableOrNode = expr.getVariableOrNode();
56 if (variableOrNode instanceof Node node && !ProblemUtil.isIndividualNode(node)) { 60 if (variableOrNode instanceof Node node && !ProblemUtil.isIndividualNode(node)) {
57 var name = node.getName(); 61 var name = node.getName();
58 var message = ("Only individuals can be referenced in predicates. " + 62 var message = ("Only individuals can be referenced in predicates. " +
59 "Mark '%s' as individual with the declaration 'indiv %s.'").formatted(name, name); 63 "Mark '%s' as individual with the declaration 'indiv %s.'").formatted(name, name);
60 error(message, expr, ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE, 64 error(message, expr, ProblemPackage.Literals.VARIABLE_OR_NODE_EXPR__VARIABLE_OR_NODE,
61 INSIGNIFICANT_INDEX, NON_INDIVIDUAL_NODE_ISSUE); 65 INSIGNIFICANT_INDEX, NODE_CONSTANT_ISSUE);
66 }
67 }
68
69 @Check
70 public void checkUniqueDeclarations(Problem problem) {
71 var relations = new ArrayList<Relation>();
72 var individuals = new ArrayList<Node>();
73 for (var statement : problem.getStatements()) {
74 if (statement instanceof Relation relation) {
75 relations.add(relation);
76 } else if (statement instanceof IndividualDeclaration individualDeclaration) {
77 individuals.addAll(individualDeclaration.getNodes());
78 }
79 }
80 checkUniqueSimpleNames(relations);
81 checkUniqueSimpleNames(individuals);
82 }
83
84 @Check
85 public void checkUniqueFeatures(ClassDeclaration classDeclaration) {
86 checkUniqueSimpleNames(classDeclaration.getFeatureDeclarations());
87 }
88
89 @Check
90 public void checkUniqueLiterals(EnumDeclaration enumDeclaration) {
91 checkUniqueSimpleNames(enumDeclaration.getLiterals());
92 }
93
94 protected void checkUniqueSimpleNames(Iterable<? extends NamedElement> namedElements) {
95 var names = new LinkedHashMap<String, Set<NamedElement>>();
96 for (var namedElement : namedElements) {
97 var name = namedElement.getName();
98 var objectsWithName = names.computeIfAbsent(name, ignored -> new LinkedHashSet<>());
99 objectsWithName.add(namedElement);
100 }
101 for (var entry : names.entrySet()) {
102 var objectsWithName = entry.getValue();
103 if (objectsWithName.size() <= 1) {
104 continue;
105 }
106 var name = entry.getKey();
107 var message = "Duplicate name '%s'.".formatted(name);
108 for (var namedElement : objectsWithName) {
109 acceptError(message, namedElement, ProblemPackage.Literals.NAMED_ELEMENT__NAME, 0,
110 DUPLICATE_NAME_ISSUE);
111 }
62 } 112 }
63 } 113 }
64} 114}
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java b/subprojects/language/src/main/java/tools/refinery/language/validation/ReferenceCounter.java
index f1be55ee..55cbd71d 100644
--- a/subprojects/language/src/main/java/tools/refinery/language/resource/ReferenceCounter.java
+++ b/subprojects/language/src/main/java/tools/refinery/language/validation/ReferenceCounter.java
@@ -3,7 +3,7 @@
3 * 3 *
4 * SPDX-License-Identifier: EPL-2.0 4 * SPDX-License-Identifier: EPL-2.0
5 */ 5 */
6package tools.refinery.language.resource; 6package tools.refinery.language.validation;
7 7
8import java.util.HashMap; 8import java.util.HashMap;
9import java.util.Map; 9import java.util.Map;