aboutsummaryrefslogtreecommitdiffstats
path: root/language
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-06-30 01:55:43 +0200
committerLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-06-30 02:04:32 +0200
commitadf4509525300f05334638d5d108dfd72ab7e65b (patch)
treedcd9a3910d37844f2e94c57a5c11a34a2cd2fd01 /language
parentTop level editorconfig (diff)
downloadrefinery-adf4509525300f05334638d5d108dfd72ab7e65b.tar.gz
refinery-adf4509525300f05334638d5d108dfd72ab7e65b.tar.zst
refinery-adf4509525300f05334638d5d108dfd72ab7e65b.zip
Node scoping fixes
Diffstat (limited to 'language')
-rw-r--r--language/build.gradle1
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/resource/NodeNameCollector.java140
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemDerivedStateComputer.java72
-rw-r--r--language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemScopingTest.xtend158
-rw-r--r--language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemTestUtil.xtend5
-rw-r--r--language/src/test/java/org/eclipse/viatra/solver/language/tests/scoping/NodeScopingTest.xtend262
6 files changed, 417 insertions, 221 deletions
diff --git a/language/build.gradle b/language/build.gradle
index 5b0ab20f..7e079f27 100644
--- a/language/build.gradle
+++ b/language/build.gradle
@@ -7,6 +7,7 @@ configurations {
7dependencies { 7dependencies {
8 testCompile "org.junit.jupiter:junit-jupiter-api:${junitVersion}" 8 testCompile "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
9 testRuntime "org.junit.jupiter:junit-jupiter-engine:${junitVersion}" 9 testRuntime "org.junit.jupiter:junit-jupiter-engine:${junitVersion}"
10 testCompile "org.junit.jupiter:junit-jupiter-params:${junitVersion}"
10 testCompile "org.eclipse.xtext:org.eclipse.xtext.testing:${xtextVersion}" 11 testCompile "org.eclipse.xtext:org.eclipse.xtext.testing:${xtextVersion}"
11 testCompile "org.eclipse.xtext:org.eclipse.xtext.xbase.testing:${xtextVersion}" 12 testCompile "org.eclipse.xtext:org.eclipse.xtext.xbase.testing:${xtextVersion}"
12 testCompile "org.hamcrest:hamcrest:${hamcrestVersion}" 13 testCompile "org.hamcrest:hamcrest:${hamcrestVersion}"
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/resource/NodeNameCollector.java b/language/src/main/java/org/eclipse/viatra/solver/language/resource/NodeNameCollector.java
new file mode 100644
index 00000000..4dee5434
--- /dev/null
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/resource/NodeNameCollector.java
@@ -0,0 +1,140 @@
1package org.eclipse.viatra.solver.language.resource;
2
3import java.util.HashSet;
4import java.util.List;
5import java.util.Set;
6import java.util.function.Predicate;
7
8import org.eclipse.emf.ecore.EObject;
9import org.eclipse.emf.ecore.EStructuralFeature;
10import org.eclipse.viatra.solver.language.model.problem.Argument;
11import org.eclipse.viatra.solver.language.model.problem.Assertion;
12import org.eclipse.viatra.solver.language.model.problem.AssertionArgument;
13import org.eclipse.viatra.solver.language.model.problem.Atom;
14import org.eclipse.viatra.solver.language.model.problem.Conjunction;
15import org.eclipse.viatra.solver.language.model.problem.EnumDeclaration;
16import org.eclipse.viatra.solver.language.model.problem.Literal;
17import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral;
18import org.eclipse.viatra.solver.language.model.problem.Node;
19import org.eclipse.viatra.solver.language.model.problem.NodeAssertionArgument;
20import org.eclipse.viatra.solver.language.model.problem.NodeValueAssertion;
21import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition;
22import org.eclipse.viatra.solver.language.model.problem.Problem;
23import org.eclipse.viatra.solver.language.model.problem.ProblemPackage;
24import org.eclipse.viatra.solver.language.model.problem.Statement;
25import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument;
26import org.eclipse.xtext.linking.impl.LinkingHelper;
27import org.eclipse.xtext.naming.IQualifiedNameConverter;
28import org.eclipse.xtext.naming.QualifiedName;
29import org.eclipse.xtext.nodemodel.INode;
30import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
31import org.eclipse.xtext.scoping.IScope;
32import org.eclipse.xtext.scoping.IScopeProvider;
33import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
34
35import com.google.inject.Inject;
36import com.google.inject.name.Named;
37
38public class NodeNameCollector {
39 @Inject
40 private LinkingHelper linkingHelper;
41
42 @Inject
43 private IQualifiedNameConverter qualifiedNameConverter;
44
45 @Inject
46 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)
47 private IScopeProvider scopeProvider;
48
49 private final Set<String> nodeNames = new HashSet<>();
50 private final Set<String> existingNodeNames = new HashSet<>();
51
52 private IScope nodeScope;
53
54 public Set<String> getNodeNames() {
55 return nodeNames;
56 }
57
58 public void collectNodeNames(Problem problem) {
59 nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__ARGUMENTS);
60 collectEnumLiteralNames(problem);
61 for (Statement statement : problem.getStatements()) {
62 collectStatementNodeNames(statement);
63 }
64 }
65
66 protected void collectEnumLiteralNames(Problem problem) {
67 for (Statement statement : problem.getStatements()) {
68 if (statement instanceof EnumDeclaration) {
69 EnumDeclaration enumDeclaration = (EnumDeclaration) statement;
70 for (Node literal : enumDeclaration.getLiterals()) {
71 String name = literal.getName();
72 if (ProblemDerivedStateComputer.validId(name)) {
73 existingNodeNames.add(name);
74 }
75 }
76 }
77 }
78 }
79
80 protected void collectStatementNodeNames(Statement statement) {
81 if (statement instanceof Assertion) {
82 collectAssertionNodeNames((Assertion) statement);
83 } else if (statement instanceof NodeValueAssertion) {
84 collectNodeValueAssertionNodeNames((NodeValueAssertion) statement);
85 } else if (statement instanceof PredicateDefinition) {
86 collectPredicateDefinitionNodeNames((PredicateDefinition) statement);
87 }
88 }
89
90 protected void collectAssertionNodeNames(Assertion assertion) {
91 for (AssertionArgument argument : assertion.getArguments()) {
92 if (argument instanceof NodeAssertionArgument) {
93 addNodeNames(argument, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE,
94 ProblemDerivedStateComputer::validNodeName);
95 }
96 }
97 }
98
99 protected void collectNodeValueAssertionNodeNames(NodeValueAssertion nodeValueAssertion) {
100 addNodeNames(nodeValueAssertion, ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE,
101 ProblemDerivedStateComputer::validNodeName);
102 }
103
104 protected void collectPredicateDefinitionNodeNames(PredicateDefinition predicateDefinition) {
105 for (Conjunction body : predicateDefinition.getBodies()) {
106 for (Literal literal : body.getLiterals()) {
107 Atom atom = null;
108 if (literal instanceof Atom) {
109 atom = (Atom) literal;
110 } else if (literal instanceof NegativeLiteral) {
111 NegativeLiteral negativeLiteral = (NegativeLiteral) literal;
112 atom = negativeLiteral.getAtom();
113 }
114 if (atom == null) {
115 continue;
116 }
117 for (Argument argument : atom.getArguments()) {
118 if (argument instanceof VariableOrNodeArgument) {
119 addNodeNames(argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE,
120 ProblemDerivedStateComputer::validQuotedId);
121 }
122 }
123 }
124 }
125 }
126
127 private void addNodeNames(EObject eObject, EStructuralFeature feature, Predicate<String> condition) {
128 List<INode> nodes = NodeModelUtils.findNodesForFeature(eObject, feature);
129 for (INode node : nodes) {
130 String nodeName = linkingHelper.getCrossRefNodeAsString(node, true);
131 if (!condition.test(nodeName)) {
132 continue;
133 }
134 QualifiedName qualifiedName = qualifiedNameConverter.toQualifiedName(nodeName);
135 if (!existingNodeNames.contains(nodeName) && nodeScope.getSingleElement(qualifiedName) == null) {
136 nodeNames.add(nodeName);
137 }
138 }
139 }
140} \ No newline at end of file
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemDerivedStateComputer.java b/language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemDerivedStateComputer.java
index 42e53534..81236afd 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemDerivedStateComputer.java
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemDerivedStateComputer.java
@@ -5,18 +5,14 @@ import java.util.HashSet;
5import java.util.List; 5import java.util.List;
6import java.util.Map; 6import java.util.Map;
7import java.util.Set; 7import java.util.Set;
8import java.util.function.Predicate;
9import java.util.regex.Pattern; 8import java.util.regex.Pattern;
10 9
11import org.eclipse.emf.common.notify.impl.AdapterImpl; 10import org.eclipse.emf.common.notify.impl.AdapterImpl;
12import org.eclipse.emf.ecore.EObject; 11import org.eclipse.emf.ecore.EObject;
13import org.eclipse.emf.ecore.EStructuralFeature;
14import org.eclipse.emf.ecore.resource.Resource; 12import org.eclipse.emf.ecore.resource.Resource;
15import org.eclipse.emf.ecore.util.EcoreUtil; 13import org.eclipse.emf.ecore.util.EcoreUtil;
16import org.eclipse.viatra.solver.language.ProblemUtil; 14import org.eclipse.viatra.solver.language.ProblemUtil;
17import org.eclipse.viatra.solver.language.model.problem.Argument; 15import org.eclipse.viatra.solver.language.model.problem.Argument;
18import org.eclipse.viatra.solver.language.model.problem.Assertion;
19import org.eclipse.viatra.solver.language.model.problem.AssertionArgument;
20import org.eclipse.viatra.solver.language.model.problem.Atom; 16import org.eclipse.viatra.solver.language.model.problem.Atom;
21import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; 17import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration;
22import org.eclipse.viatra.solver.language.model.problem.Conjunction; 18import org.eclipse.viatra.solver.language.model.problem.Conjunction;
@@ -25,8 +21,6 @@ import org.eclipse.viatra.solver.language.model.problem.ImplicitVariable;
25import org.eclipse.viatra.solver.language.model.problem.Literal; 21import org.eclipse.viatra.solver.language.model.problem.Literal;
26import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral; 22import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral;
27import org.eclipse.viatra.solver.language.model.problem.Node; 23import org.eclipse.viatra.solver.language.model.problem.Node;
28import org.eclipse.viatra.solver.language.model.problem.NodeAssertionArgument;
29import org.eclipse.viatra.solver.language.model.problem.NodeValueAssertion;
30import org.eclipse.viatra.solver.language.model.problem.Parameter; 24import org.eclipse.viatra.solver.language.model.problem.Parameter;
31import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; 25import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition;
32import org.eclipse.viatra.solver.language.model.problem.Problem; 26import org.eclipse.viatra.solver.language.model.problem.Problem;
@@ -48,6 +42,7 @@ import org.eclipse.xtext.scoping.IScopeProvider;
48import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; 42import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
49 43
50import com.google.inject.Inject; 44import com.google.inject.Inject;
45import com.google.inject.Provider;
51import com.google.inject.Singleton; 46import com.google.inject.Singleton;
52import com.google.inject.name.Named; 47import com.google.inject.name.Named;
53 48
@@ -73,6 +68,9 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
73 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE) 68 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)
74 private IScopeProvider scopeProvider; 69 private IScopeProvider scopeProvider;
75 70
71 @Inject
72 private Provider<NodeNameCollector> nodeNameCollectorProvider;
73
76 @Override 74 @Override
77 public void installDerivedState(DerivedStateAwareResource resource, boolean preLinkingPhase) { 75 public void installDerivedState(DerivedStateAwareResource resource, boolean preLinkingPhase) {
78 Problem problem = getProblem(resource); 76 Problem problem = getProblem(resource);
@@ -121,46 +119,9 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
121 } 119 }
122 120
123 protected Set<String> installDerivedNodes(Problem problem) { 121 protected Set<String> installDerivedNodes(Problem problem) {
124 IScope nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__ARGUMENTS); 122 NodeNameCollector collector = nodeNameCollectorProvider.get();
125 Set<String> nodeNames = new HashSet<>(); 123 collector.collectNodeNames(problem);
126 for (Statement statement : problem.getStatements()) { 124 Set<String> nodeNames = collector.getNodeNames();
127 if (statement instanceof Assertion) {
128 Assertion assertion = (Assertion) statement;
129 for (AssertionArgument argument : assertion.getArguments()) {
130 if (argument instanceof NodeAssertionArgument) {
131 addNodeNames(nodeNames, nodeScope, argument,
132 ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE,
133 ProblemDerivedStateComputer::validNodeName);
134 }
135 }
136 } else if (statement instanceof NodeValueAssertion) {
137 addNodeNames(nodeNames, nodeScope, statement, ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE,
138 ProblemDerivedStateComputer::validNodeName);
139 } else if (statement instanceof PredicateDefinition) {
140 PredicateDefinition predicateDefinition = (PredicateDefinition) statement;
141 for (Conjunction body : predicateDefinition.getBodies()) {
142 for (Literal literal : body.getLiterals()) {
143 Atom atom = null;
144 if (literal instanceof Atom) {
145 atom = (Atom) literal;
146 } else if (literal instanceof NegativeLiteral) {
147 NegativeLiteral negativeLiteral = (NegativeLiteral) literal;
148 atom = negativeLiteral.getAtom();
149 }
150 if (atom == null) {
151 continue;
152 }
153 for (Argument argument : atom.getArguments()) {
154 if (argument instanceof VariableOrNodeArgument) {
155 addNodeNames(nodeNames, nodeScope, argument,
156 ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE,
157 ProblemDerivedStateComputer::validQuotedId);
158 }
159 }
160 }
161 }
162 }
163 }
164 List<Node> grapNodes = problem.getNodes(); 125 List<Node> grapNodes = problem.getNodes();
165 for (String nodeName : nodeNames) { 126 for (String nodeName : nodeNames) {
166 Node graphNode = createNode(nodeName); 127 Node graphNode = createNode(nodeName);
@@ -169,21 +130,6 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
169 return nodeNames; 130 return nodeNames;
170 } 131 }
171 132
172 private void addNodeNames(Set<String> nodeNames, IScope nodeScope, EObject eObject, EStructuralFeature feature,
173 Predicate<String> condition) {
174 List<INode> nodes = NodeModelUtils.findNodesForFeature(eObject, feature);
175 for (INode node : nodes) {
176 String nodeName = linkingHelper.getCrossRefNodeAsString(node, true);
177 if (!condition.test(nodeName)) {
178 continue;
179 }
180 QualifiedName qualifiedName = qualifiedNameConverter.toQualifiedName(nodeName);
181 if (!nodeNames.contains(nodeName) && nodeScope.getSingleElement(qualifiedName) == null) {
182 nodeNames.add(nodeName);
183 }
184 }
185 }
186
187 protected Node createNode(String name) { 133 protected Node createNode(String name) {
188 Node node = ProblemFactory.eINSTANCE.createNode(); 134 Node node = ProblemFactory.eINSTANCE.createNode();
189 node.setName(name); 135 node.setName(name);
@@ -347,7 +293,7 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
347 return validId(name) || validQuotedId(name); 293 return validId(name) || validQuotedId(name);
348 } 294 }
349 295
350 public Adapter getOrInstallAdapter(Resource resource) { 296 protected Adapter getOrInstallAdapter(Resource resource) {
351 if (!(resource instanceof XtextResource)) { 297 if (!(resource instanceof XtextResource)) {
352 return new Adapter(); 298 return new Adapter();
353 } 299 }
@@ -363,7 +309,7 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
363 return adapter; 309 return adapter;
364 } 310 }
365 311
366 private static class Adapter extends AdapterImpl { 312 protected static class Adapter extends AdapterImpl {
367 public Map<ClassDeclaration, Node> newNodes = new HashMap<>(); 313 public Map<ClassDeclaration, Node> newNodes = new HashMap<>();
368 314
369 @Override 315 @Override
diff --git a/language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemScopingTest.xtend b/language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemScopingTest.xtend
deleted file mode 100644
index 7fc1c44d..00000000
--- a/language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemScopingTest.xtend
+++ /dev/null
@@ -1,158 +0,0 @@
1/*
2 * generated by Xtext 2.25.0
3 */
4package org.eclipse.viatra.solver.language.tests
5
6import com.google.inject.Inject
7import org.eclipse.viatra.solver.language.model.problem.Problem
8import org.eclipse.xtext.testing.InjectWith
9import org.eclipse.xtext.testing.extensions.InjectionExtension
10import org.eclipse.xtext.testing.util.ParseHelper
11import org.junit.jupiter.api.Test
12import org.junit.jupiter.api.^extension.ExtendWith
13
14import static org.hamcrest.MatcherAssert.assertThat
15import static org.hamcrest.Matchers.*
16
17@ExtendWith(InjectionExtension)
18@InjectWith(ProblemInjectorProvider)
19class ProblemScopingTest {
20 @Inject
21 ParseHelper<Problem> parseHelper
22
23 @Inject
24 extension ProblemTestUtil
25
26 @Test
27 def void builtInArgumentTypeTest() {
28 val it = parseHelper.parse('''
29 pred predicate(node a, data b, int c).
30 ''')
31 assertThat(errors, empty)
32 assertThat(pred('predicate').param(0).parameterType, equalTo(builtin.findClass('node')))
33 assertThat(pred('predicate').param(1).parameterType, equalTo(builtin.findClass('data')))
34 assertThat(pred('predicate').param(2).parameterType, equalTo(builtin.findClass('int')))
35 }
36
37 @Test
38 def void builtiQualifiedArgumentTypeTest() {
39 val it = parseHelper.parse('''
40 pred predicate(builtin::node a, builtin::data b, builtin::int c).
41 ''')
42 assertThat(errors, empty)
43 assertThat(pred('predicate').param(0).parameterType, equalTo(builtin.findClass('node')))
44 assertThat(pred('predicate').param(1).parameterType, equalTo(builtin.findClass('data')))
45 assertThat(pred('predicate').param(2).parameterType, equalTo(builtin.findClass('int')))
46 }
47
48 @Test
49 def void implicitNodeInAssertionTest() {
50 val it = parseHelper.parse('''
51 pred predicate(node a, node b).
52 predicate(a, a).
53 ?predicate(a, b).
54 ''')
55 assertThat(errors, empty)
56 assertThat(nodeNames, hasItems('a', 'b'))
57 assertThat(assertion(0).arg(0).node, equalTo(node('a')))
58 assertThat(assertion(0).arg(1).node, equalTo(node('a')))
59 assertThat(assertion(1).arg(0).node, equalTo(node('a')))
60 assertThat(assertion(1).arg(1).node, equalTo(node('b')))
61 }
62
63 @Test
64 def void quotedNodeInAssertionTest() {
65 val it = parseHelper.parse('''
66 pred predicate(node a, node b).
67 predicate('a', 'a').
68 ?predicate('a', 'b').
69 ''')
70 assertThat(errors, empty)
71 assertThat(nodeNames, hasItems("'a'", "'b'"))
72 assertThat(assertion(0).arg(0).node, equalTo(node("'a'")))
73 assertThat(assertion(0).arg(1).node, equalTo(node("'a'")))
74 assertThat(assertion(1).arg(0).node, equalTo(node("'a'")))
75 assertThat(assertion(1).arg(1).node, equalTo(node("'b'")))
76 }
77
78 @Test
79 def void builtInNodeInAssertionTest() {
80 val it = parseHelper.parse('''
81 pred predicate(node a).
82 predicate(int::new).
83 ''')
84 assertThat(errors, empty)
85 assertThat(nodes, empty)
86 assertThat(assertion(0).arg(0).node, equalTo(builtin.findClass('int').newNode))
87 }
88
89 @Test
90 def void qualifiedBuiltInNodeInAssertionTest() {
91 val it = parseHelper.parse('''
92 pred predicate(node a).
93 predicate(builtin::int::new).
94 ''')
95 assertThat(errors, empty)
96 assertThat(nodes, empty)
97 assertThat(assertion(0).arg(0).node, equalTo(builtin.findClass('int').newNode))
98 }
99
100 @Test
101 def void classNewNodeTest() {
102 val it = parseHelper.parse('''
103 class Foo.
104 pred predicate(node a).
105 predicate(Foo::new).
106 ''')
107 assertThat(errors, empty)
108 assertThat(nodes, empty)
109 assertThat(assertion(0).arg(0).node, equalTo(findClass('Foo').newNode))
110 }
111
112 @Test
113 def void qualifiedClassNewNodeTest() {
114 val it = parseHelper.parse('''
115 problem test.
116 class Foo.
117 pred predicate(node a).
118 predicate(test::Foo::new).
119 ''')
120 assertThat(errors, empty)
121 assertThat(nodes, empty)
122 assertThat(assertion(0).arg(0).node, equalTo(findClass('Foo').newNode))
123 }
124
125 @Test
126 def void newNodeIsNotSpecial() {
127 val it = parseHelper.parse('''
128 class Foo.
129 pred predicate(node a).
130 predicate(new).
131 ''')
132 assertThat(errors, empty)
133 assertThat(nodeNames, hasItem('new'))
134 assertThat(assertion(0).arg(0).node, not(equalTo(findClass('Foo').newNode)))
135 }
136
137 @Test
138 def void implicitNodeInPredicateTest() {
139 val it = parseHelper.parse('''
140 pred predicate(node a) :- node(b).
141 predicate(b).
142 ''')
143 assertThat(errors, empty)
144 assertThat(nodeNames, hasItem("b"))
145 assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(node("b")))
146 assertThat(assertion(0).arg(0).node, equalTo(node("b")))
147 }
148
149 @Test
150 def void quotedNodeInPredicateTest() {
151 val it = parseHelper.parse('''
152 pred predicate(node a) :- node('b').
153 ''')
154 assertThat(errors, empty)
155 assertThat(nodeNames, hasItem("'b'"))
156 assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(node("'b'")))
157 }
158}
diff --git a/language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemTestUtil.xtend b/language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemTestUtil.xtend
index b16de2b5..f2aedfd5 100644
--- a/language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemTestUtil.xtend
+++ b/language/src/test/java/org/eclipse/viatra/solver/language/tests/ProblemTestUtil.xtend
@@ -12,6 +12,7 @@ import org.eclipse.viatra.solver.language.model.problem.Literal
12import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral 12import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral
13import org.eclipse.viatra.solver.language.model.problem.Node 13import org.eclipse.viatra.solver.language.model.problem.Node
14import org.eclipse.viatra.solver.language.model.problem.NodeAssertionArgument 14import org.eclipse.viatra.solver.language.model.problem.NodeAssertionArgument
15import org.eclipse.viatra.solver.language.model.problem.NodeValueAssertion
15import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition 16import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition
16import org.eclipse.viatra.solver.language.model.problem.Problem 17import org.eclipse.viatra.solver.language.model.problem.Problem
17import org.eclipse.viatra.solver.language.model.problem.Variable 18import org.eclipse.viatra.solver.language.model.problem.Variable
@@ -74,6 +75,10 @@ class ProblemTestUtil {
74 statements.filter(Assertion).get(i) 75 statements.filter(Assertion).get(i)
75 } 76 }
76 77
78 def nodeValueAssertion(Problem it, int i) {
79 statements.filter(NodeValueAssertion).get(i)
80 }
81
77 def arg(Assertion it, int i) { 82 def arg(Assertion it, int i) {
78 arguments.get(i) 83 arguments.get(i)
79 } 84 }
diff --git a/language/src/test/java/org/eclipse/viatra/solver/language/tests/scoping/NodeScopingTest.xtend b/language/src/test/java/org/eclipse/viatra/solver/language/tests/scoping/NodeScopingTest.xtend
new file mode 100644
index 00000000..c92ad4c2
--- /dev/null
+++ b/language/src/test/java/org/eclipse/viatra/solver/language/tests/scoping/NodeScopingTest.xtend
@@ -0,0 +1,262 @@
1package org.eclipse.viatra.solver.language.tests.scoping
2
3import com.google.inject.Inject
4import java.util.stream.Stream
5import org.eclipse.viatra.solver.language.model.problem.Problem
6import org.eclipse.viatra.solver.language.tests.ProblemInjectorProvider
7import org.eclipse.viatra.solver.language.tests.ProblemTestUtil
8import org.eclipse.xtext.testing.InjectWith
9import org.eclipse.xtext.testing.extensions.InjectionExtension
10import org.eclipse.xtext.testing.util.ParseHelper
11import org.junit.jupiter.api.Test
12import org.junit.jupiter.api.^extension.ExtendWith
13import org.junit.jupiter.params.ParameterizedTest
14import org.junit.jupiter.params.provider.Arguments
15import org.junit.jupiter.params.provider.MethodSource
16import org.junit.jupiter.params.provider.ValueSource
17
18import static org.hamcrest.MatcherAssert.assertThat
19import static org.hamcrest.Matchers.*
20
21@ExtendWith(InjectionExtension)
22@InjectWith(ProblemInjectorProvider)
23class NodeScopingTest {
24 @Inject
25 ParseHelper<Problem> parseHelper
26
27 @Inject
28 extension ProblemTestUtil
29
30 @ParameterizedTest
31 @ValueSource(strings=#["", "builtin::"])
32 def void builtInArgumentTypeTest(String prefix) {
33 val it = parseHelper.parse('''
34 pred predicate(«prefix»node a, «prefix»data b, «prefix»int c).
35 ''')
36 assertThat(errors, empty)
37 assertThat(pred('predicate').param(0).parameterType, equalTo(builtin.findClass('node')))
38 assertThat(pred('predicate').param(1).parameterType, equalTo(builtin.findClass('data')))
39 assertThat(pred('predicate').param(2).parameterType, equalTo(builtin.findClass('int')))
40 }
41
42 @Test
43 def void implicitNodeInAssertionTest() {
44 val it = parseHelper.parse('''
45 pred predicate(node x, node y) :- node(x).
46 predicate(a, a).
47 ?predicate(a, b).
48 ''')
49 assertThat(errors, empty)
50 assertThat(nodeNames, hasItems('a', 'b'))
51 assertThat(assertion(0).arg(0).node, equalTo(node('a')))
52 assertThat(assertion(0).arg(1).node, equalTo(node('a')))
53 assertThat(assertion(1).arg(0).node, equalTo(node('a')))
54 assertThat(assertion(1).arg(1).node, equalTo(node('b')))
55 }
56
57 @Test
58 def void implicitNodeInNodeValueAssertionTest() {
59 val it = parseHelper.parse('''
60 a: 16.
61 ''')
62 assertThat(errors, empty)
63 assertThat(nodeNames, hasItems('a'))
64 assertThat(nodeValueAssertion(0).node, equalTo(node('a')))
65 }
66
67 def void implicitNodeInPredicateTest() {
68 val it = parseHelper.parse('''
69 pred predicate(node a) :- node(b).
70 predicate(b).
71 ''')
72 assertThat(errors, empty)
73 assertThat(nodeNames, hasItem("b"))
74 assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(node("b")))
75 assertThat(assertion(0).arg(0).node, equalTo(node("b")))
76 }
77
78 @Test
79 def void quotedNodeInAssertionTest() {
80 val it = parseHelper.parse('''
81 pred predicate(node x, node y) :- node(x).
82 predicate('a', 'a').
83 ?predicate('a', 'b').
84 ''')
85 assertThat(errors, empty)
86 assertThat(nodeNames, hasItems("'a'", "'b'"))
87 assertThat(assertion(0).arg(0).node, equalTo(node("'a'")))
88 assertThat(assertion(0).arg(1).node, equalTo(node("'a'")))
89 assertThat(assertion(1).arg(0).node, equalTo(node("'a'")))
90 assertThat(assertion(1).arg(1).node, equalTo(node("'b'")))
91 }
92
93 @Test
94 def void quotedNodeInNodeValueAssertionTest() {
95 val it = parseHelper.parse('''
96 'a': 16.
97 ''')
98 assertThat(errors, empty)
99 assertThat(nodeNames, hasItems("'a'"))
100 assertThat(nodeValueAssertion(0).node, equalTo(node("'a'")))
101 }
102
103 @Test
104 def void quotedNodeInPredicateTest() {
105 val it = parseHelper.parse('''
106 pred predicate(node a) :- node('b').
107 ''')
108 assertThat(errors, empty)
109 assertThat(nodeNames, hasItem("'b'"))
110 assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(node("'b'")))
111 }
112
113 @ParameterizedTest
114 @MethodSource("builtInNodeReferencesSource")
115 def void builtInNodeTest(String qualifiedName) {
116 val it = parseHelper.parse('''
117 pred predicate(node x) :- node(x).
118 predicate(«qualifiedName»).
119 ''')
120 assertThat(errors, empty)
121 assertThat(nodes, empty)
122 assertThat(assertion(0).arg(0).node, equalTo(builtin.findClass('int').newNode))
123 }
124
125 @ParameterizedTest
126 @MethodSource("builtInNodeReferencesSource")
127 def void builtInNodeInNodeValueAssertionTest(String qualifiedName) {
128 val it = parseHelper.parse('''
129 «qualifiedName»: 16.
130 ''')
131 assertThat(errors, empty)
132 assertThat(nodes, empty)
133 assertThat(nodeValueAssertion(0).node, equalTo(builtin.findClass('int').newNode))
134 }
135
136 @ParameterizedTest
137 @MethodSource("builtInNodeReferencesSource")
138 def void builtInNodeInPredicateTest(String qualifiedName) {
139 val it = parseHelper.parse('''
140 pred predicate(node x) :- node(«qualifiedName»).
141 ''')
142 assertThat(errors, empty)
143 assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(builtin.findClass('int').newNode))
144 }
145
146 static def builtInNodeReferencesSource() {
147 Stream.of(
148 Arguments.of("int::new"),
149 Arguments.of("builtin::int::new")
150 )
151 }
152
153 @ParameterizedTest(name="{0}, namedProblem={1}")
154 @MethodSource("classNewNodeReferencesSource")
155 def void classNewNodeTest(String qualifiedName, boolean namedProblem) {
156 val it = parseHelper.parse('''
157 «IF namedProblem»problem test.«ENDIF»
158 class Foo.
159 pred predicate(node x) :- node(x).
160 predicate(«qualifiedName»).
161 ''')
162 assertThat(errors, empty)
163 assertThat(nodes, empty)
164 assertThat(assertion(0).arg(0).node, equalTo(findClass('Foo').newNode))
165 }
166
167 @ParameterizedTest(name="{0}, namedProblem={1}")
168 @MethodSource("classNewNodeReferencesSource")
169 def void classNewNodeInNodeValueAssertionTest(String qualifiedName, boolean namedProblem) {
170 val it = parseHelper.parse('''
171 «IF namedProblem»problem test.«ENDIF»
172 class Foo.
173 «qualifiedName»: 16.
174 ''')
175 assertThat(errors, empty)
176 assertThat(nodes, empty)
177 assertThat(nodeValueAssertion(0).node, equalTo(findClass('Foo').newNode))
178 }
179
180 @ParameterizedTest(name="{0}, namedProblem={1}")
181 @MethodSource("classNewNodeReferencesSource")
182 def void classNewNodeInPredicateTest(String qualifiedName, boolean namedProblem) {
183 val it = parseHelper.parse('''
184 «IF namedProblem»problem test.«ENDIF»
185 class Foo.
186 pred predicate(node x) :- node(«qualifiedName»).
187 ''')
188 assertThat(errors, empty)
189 assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(findClass('Foo').newNode))
190 }
191
192 static def classNewNodeReferencesSource() {
193 Stream.of(
194 Arguments.of("Foo::new", false),
195 Arguments.of("Foo::new", true),
196 Arguments.of("test::Foo::new", true)
197 )
198 }
199
200 @Test
201 def void newNodeIsNotSpecial() {
202 val it = parseHelper.parse('''
203 class Foo.
204 pred predicate(node x) :- node(x).
205 predicate(new).
206 ''')
207 assertThat(errors, empty)
208 assertThat(nodeNames, hasItem('new'))
209 assertThat(assertion(0).arg(0).node, not(equalTo(findClass('Foo').newNode)))
210 }
211
212 @ParameterizedTest(name="{0}, namedProblem={1}")
213 @MethodSource("enumLiteralReferencesSource")
214 def void enumLiteralTest(String qualifiedName, boolean namedProblem) {
215 val it = parseHelper.parse('''
216 «IF namedProblem»problem test.«ENDIF»
217 enum Foo { alpha, beta }
218 pred predicate(Foo a) :- node(a).
219 predicate(«qualifiedName»).
220 ''')
221 assertThat(errors, empty)
222 assertThat(nodeNames, empty)
223 assertThat(assertion(0).arg(0).node, equalTo(findEnum("Foo").literal("alpha")))
224 }
225
226 @ParameterizedTest(name="{0}, namedProblem={1}")
227 @MethodSource("enumLiteralReferencesSource")
228 def void enumLiteralInNodeValueAssertionTest(String qualifiedName, boolean namedProblem) {
229 val it = parseHelper.parse('''
230 «IF namedProblem»problem test.«ENDIF»
231 enum Foo { alpha, beta }
232 «qualifiedName»: 16.
233 ''')
234 assertThat(errors, empty)
235 assertThat(nodeNames, empty)
236 assertThat(nodeValueAssertion(0).node, equalTo(findEnum("Foo").literal("alpha")))
237 }
238
239 @ParameterizedTest(name="{0}, namedProblem={1}")
240 @MethodSource("enumLiteralReferencesSource")
241 def void enumLiteralInPredicateTest(String qualifiedName, boolean namedProblem) {
242 val it = parseHelper.parse('''
243 «IF namedProblem»problem test.«ENDIF»
244 enum Foo { alpha, beta }
245 pred predicate(Foo a) :- node(«qualifiedName»).
246 ''')
247 assertThat(errors, empty)
248 assertThat(nodeNames, empty)
249 assertThat(pred("predicate").conj(0).lit(0).arg(0).node, equalTo(findEnum("Foo").literal("alpha")))
250 }
251
252 static def enumLiteralReferencesSource() {
253 Stream.of(
254 Arguments.of("alpha", false),
255 Arguments.of("alpha", true),
256 Arguments.of("Foo::alpha", false),
257 Arguments.of("Foo::alpha", true),
258 Arguments.of("test::alpha", true),
259 Arguments.of("test::Foo::alpha", true)
260 )
261 }
262}