aboutsummaryrefslogtreecommitdiffstats
path: root/language
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-07-29 17:09:24 +0200
committerLibravatar Kristóf Marussy <marussy@mit.bme.hu>2021-07-29 17:09:24 +0200
commit97ea34af2f8e5d0ca9da5dda331a9f54e580c4c6 (patch)
tree2f58b2e34609439b53e3a7ddd5337bb4733ce707 /language
parentAppearance fixes (diff)
downloadrefinery-97ea34af2f8e5d0ca9da5dda331a9f54e580c4c6.tar.gz
refinery-97ea34af2f8e5d0ca9da5dda331a9f54e580c4c6.tar.zst
refinery-97ea34af2f8e5d0ca9da5dda331a9f54e580c4c6.zip
Refactoring based on Sonar reports
Diffstat (limited to 'language')
-rw-r--r--language/build.gradle16
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe24
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/ProblemRuntimeModule.java3
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/ProblemStandaloneSetup.java13
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java26
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/conversion/ProblemValueConverterService.java4
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/generator/ProblemGenerator.java30
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/naming/NamingUtil.java35
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java195
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/resource/NodeNameCollector.java52
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemDerivedStateComputer.java213
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemResourceDescriptionStrategy.java67
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java17
-rw-r--r--language/src/main/java/org/eclipse/viatra/solver/language/validation/ProblemValidator.java18
14 files changed, 369 insertions, 324 deletions
diff --git a/language/build.gradle b/language/build.gradle
index 7e079f27..5ad5ab1f 100644
--- a/language/build.gradle
+++ b/language/build.gradle
@@ -1,8 +1,5 @@
1configurations { 1apply from: "${rootDir}/gradle/xtext-common.gradle"
2 mwe2 { 2apply from: "${rootDir}/gradle/mwe2.gradle"
3 extendsFrom compile
4 }
5}
6 3
7dependencies { 4dependencies {
8 testCompile "org.junit.jupiter:junit-jupiter-api:${junitVersion}" 5 testCompile "org.junit.jupiter:junit-jupiter-api:${junitVersion}"
@@ -15,13 +12,18 @@ dependencies {
15 compile "org.eclipse.xtext:org.eclipse.xtext.xbase:${xtextVersion}" 12 compile "org.eclipse.xtext:org.eclipse.xtext.xbase:${xtextVersion}"
16 compile "org.eclipse.emf:org.eclipse.emf.ecore:${ecoreVersion}" 13 compile "org.eclipse.emf:org.eclipse.emf.ecore:${ecoreVersion}"
17 compile project(':language-model') 14 compile project(':language-model')
18 mwe2 "org.eclipse.emf:org.eclipse.emf.mwe2.launch:${mwe2Version}"
19 mwe2 "org.eclipse.xtext:org.eclipse.xtext.common.types:${xtextVersion}" 15 mwe2 "org.eclipse.xtext:org.eclipse.xtext.common.types:${xtextVersion}"
20 mwe2 "org.eclipse.xtext:org.eclipse.xtext.xtext.generator:${xtextVersion}" 16 mwe2 "org.eclipse.xtext:org.eclipse.xtext.xtext.generator:${xtextVersion}"
21 mwe2 "org.eclipse.xtext:xtext-antlr-generator:${xtextAntlrGeneratorVersion}" 17 mwe2 "org.eclipse.xtext:xtext-antlr-generator:${xtextAntlrGeneratorVersion}"
22 mwe2 project(':language-mwe2') 18 mwe2 project(':language-mwe2')
23} 19}
24 20
21jar {
22 from(sourceSets.main.allSource) {
23 include '**/*.xtext'
24 }
25}
26
25task generateXtextLanguage(type: JavaExec) { 27task generateXtextLanguage(type: JavaExec) {
26 main = 'org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher' 28 main = 'org.eclipse.emf.mwe2.launch.runtime.Mwe2Launcher'
27 classpath = configurations.mwe2 29 classpath = configurations.mwe2
@@ -43,5 +45,3 @@ test {
43 45
44generateXtext.dependsOn(generateXtextLanguage) 46generateXtext.dependsOn(generateXtextLanguage)
45clean.dependsOn(cleanGenerateXtextLanguage) 47clean.dependsOn(cleanGenerateXtextLanguage)
46
47eclipse.classpath.plusConfigurations += [configurations.mwe2]
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2 b/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2
index 18f70080..ca3e2665 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2
@@ -44,7 +44,9 @@ Workflow {
44 validator = { 44 validator = {
45 generateDeprecationValidation = true 45 generateDeprecationValidation = true
46 } 46 }
47 generator = null 47 generator = {
48 generateStub = false
49 }
48 junitSupport = { 50 junitSupport = {
49 junitVersion = "5" 51 junitVersion = "5"
50 } 52 }
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/ProblemRuntimeModule.java b/language/src/main/java/org/eclipse/viatra/solver/language/ProblemRuntimeModule.java
index eb9ddd77..9fec7d75 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/ProblemRuntimeModule.java
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/ProblemRuntimeModule.java
@@ -62,6 +62,8 @@ public class ProblemRuntimeModule extends AbstractProblemRuntimeModule {
62 return DerivedStateAwareResource.class; 62 return DerivedStateAwareResource.class;
63 } 63 }
64 64
65 // Method name follows Xtext convention.
66 @SuppressWarnings("squid:S100")
65 public Class<? extends IResourceDescription.Manager> bindIResourceDescription$Manager() { 67 public Class<? extends IResourceDescription.Manager> bindIResourceDescription$Manager() {
66 return DerivedStateAwareResourceDescriptionManager.class; 68 return DerivedStateAwareResourceDescriptionManager.class;
67 } 69 }
@@ -74,6 +76,7 @@ public class ProblemRuntimeModule extends AbstractProblemRuntimeModule {
74 return ProblemDerivedStateComputer.class; 76 return ProblemDerivedStateComputer.class;
75 } 77 }
76 78
79 @Override
77 public Class<? extends ILocationInFileProvider> bindILocationInFileProvider() { 80 public Class<? extends ILocationInFileProvider> bindILocationInFileProvider() {
78 return ProblemLocationInFileProvider.class; 81 return ProblemLocationInFileProvider.class;
79 } 82 }
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/ProblemStandaloneSetup.java b/language/src/main/java/org/eclipse/viatra/solver/language/ProblemStandaloneSetup.java
index 5652f859..11e5ad8a 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/ProblemStandaloneSetup.java
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/ProblemStandaloneSetup.java
@@ -9,18 +9,25 @@ import org.eclipse.viatra.solver.language.model.problem.ProblemPackage;
9import com.google.inject.Injector; 9import com.google.inject.Injector;
10 10
11/** 11/**
12 * Initialization support for running Xtext languages without Equinox extension registry. 12 * Initialization support for running Xtext languages without Equinox extension
13 * registry.
13 */ 14 */
14public class ProblemStandaloneSetup extends ProblemStandaloneSetupGenerated { 15public class ProblemStandaloneSetup extends ProblemStandaloneSetupGenerated {
15 16
16 public static void doSetup() { 17 public static void doSetup() {
17 new ProblemStandaloneSetup().createInjectorAndDoEMFRegistration(); 18 new ProblemStandaloneSetup().createInjectorAndDoEMFRegistration();
18 } 19 }
19 20
20 @Override 21 @Override
22 // Here we can't rely on java.util.HashMap#computeIfAbsent, because
23 // org.eclipse.emf.ecore.impl.EPackageRegistryImpl#containsKey is overridden
24 // without also overriding computeIfAbsent. We must make sure to call the
25 // overridden containsKey implementation.
26 @SuppressWarnings("squid:S3824")
21 public Injector createInjectorAndDoEMFRegistration() { 27 public Injector createInjectorAndDoEMFRegistration() {
22 if (!EPackage.Registry.INSTANCE.containsKey(ProblemPackage.eNS_URI)) 28 if (!EPackage.Registry.INSTANCE.containsKey(ProblemPackage.eNS_URI)) {
23 EPackage.Registry.INSTANCE.put(ProblemPackage.eNS_URI, ProblemPackage.eINSTANCE); 29 EPackage.Registry.INSTANCE.put(ProblemPackage.eNS_URI, ProblemPackage.eINSTANCE);
30 }
24 return super.createInjectorAndDoEMFRegistration(); 31 return super.createInjectorAndDoEMFRegistration();
25 } 32 }
26} 33}
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java b/language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java
index e0a72687..2d7fede6 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/ProblemUtil.java
@@ -16,27 +16,18 @@ import org.eclipse.viatra.solver.language.model.problem.ProblemPackage;
16import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; 16import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration;
17import org.eclipse.viatra.solver.language.model.problem.Relation; 17import org.eclipse.viatra.solver.language.model.problem.Relation;
18import org.eclipse.viatra.solver.language.model.problem.Variable; 18import org.eclipse.viatra.solver.language.model.problem.Variable;
19import org.eclipse.viatra.solver.language.naming.NamingUtil;
19import org.eclipse.viatra.solver.language.scoping.ProblemGlobalScopeProvider; 20import org.eclipse.viatra.solver.language.scoping.ProblemGlobalScopeProvider;
20 21
21import com.google.common.collect.ImmutableList; 22import com.google.common.collect.ImmutableList;
22import com.google.inject.Singleton;
23 23
24@Singleton
25public final class ProblemUtil { 24public final class ProblemUtil {
26 private ProblemUtil() { 25 private ProblemUtil() {
27 throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); 26 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
28 } 27 }
29 28
30 public static final String SINGLETON_VARIABLE_PREFIX = "_";
31
32 public static final String ENUM_NODE_NAME_QUOTE = "'";
33
34 public static final String NODE_CLASS_NAME = "node"; 29 public static final String NODE_CLASS_NAME = "node";
35 30
36 public static boolean isSingletonVariableName(String name) {
37 return name != null && name.startsWith(SINGLETON_VARIABLE_PREFIX);
38 }
39
40 public static boolean isSingletonVariable(Variable variable) { 31 public static boolean isSingletonVariable(Variable variable) {
41 return variable.eContainingFeature() == ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__SINGLETON_VARIABLE; 32 return variable.eContainingFeature() == ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__SINGLETON_VARIABLE;
42 } 33 }
@@ -46,10 +37,7 @@ public final class ProblemUtil {
46 } 37 }
47 38
48 public static boolean isEnumNode(Node node) { 39 public static boolean isEnumNode(Node node) {
49 String name = node.getName(); 40 return NamingUtil.isQuotedName(node.getName()) || isEnumLiteral(node);
50 boolean isNameQuoted = name != null && name.startsWith(ENUM_NODE_NAME_QUOTE)
51 && name.endsWith(ENUM_NODE_NAME_QUOTE);
52 return isNameQuoted || isEnumLiteral(node);
53 } 41 }
54 42
55 public static boolean isNewNode(Node node) { 43 public static boolean isNewNode(Node node) {
@@ -63,6 +51,16 @@ public final class ProblemUtil {
63 .filter(Problem.class::isInstance).map(Problem.class::cast); 51 .filter(Problem.class::isInstance).map(Problem.class::cast);
64 } 52 }
65 53
54 public static boolean isBuiltIn(EObject eObject) {
55 if (eObject != null) {
56 var eResource = eObject.eResource();
57 if (eResource != null) {
58 return ProblemGlobalScopeProvider.BULTIN_LIBRARY_URI.equals(eResource.getURI());
59 }
60 }
61 return false;
62 }
63
66 public static Optional<ClassDeclaration> getNodeClassDeclaration(EObject context) { 64 public static Optional<ClassDeclaration> getNodeClassDeclaration(EObject context) {
67 return getBuiltInLibrary(context).flatMap(problem -> problem.getStatements().stream() 65 return getBuiltInLibrary(context).flatMap(problem -> problem.getStatements().stream()
68 .filter(ClassDeclaration.class::isInstance).map(ClassDeclaration.class::cast) 66 .filter(ClassDeclaration.class::isInstance).map(ClassDeclaration.class::cast)
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/conversion/ProblemValueConverterService.java b/language/src/main/java/org/eclipse/viatra/solver/language/conversion/ProblemValueConverterService.java
index 4f5fd069..1c665e6f 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/conversion/ProblemValueConverterService.java
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/conversion/ProblemValueConverterService.java
@@ -9,8 +9,10 @@ import com.google.inject.Inject;
9public class ProblemValueConverterService extends DefaultTerminalConverters { 9public class ProblemValueConverterService extends DefaultTerminalConverters {
10 @Inject 10 @Inject
11 private UpperBoundValueConverter upperBoundValueConverter; 11 private UpperBoundValueConverter upperBoundValueConverter;
12 12
13 @ValueConverter(rule = "UpperBound") 13 @ValueConverter(rule = "UpperBound")
14 // Method name follows Xtext convention.
15 @SuppressWarnings("squid:S100")
14 public IValueConverter<Integer> UpperBound() { 16 public IValueConverter<Integer> UpperBound() {
15 return upperBoundValueConverter; 17 return upperBoundValueConverter;
16 } 18 }
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/generator/ProblemGenerator.java b/language/src/main/java/org/eclipse/viatra/solver/language/generator/ProblemGenerator.java
deleted file mode 100644
index b6ea3553..00000000
--- a/language/src/main/java/org/eclipse/viatra/solver/language/generator/ProblemGenerator.java
+++ /dev/null
@@ -1,30 +0,0 @@
1/*
2 * generated by Xtext 2.26.0.M1
3 */
4package org.eclipse.viatra.solver.language.generator;
5
6import org.eclipse.emf.ecore.resource.Resource;
7import org.eclipse.xtext.generator.AbstractGenerator;
8import org.eclipse.xtext.generator.IFileSystemAccess2;
9import org.eclipse.xtext.generator.IGeneratorContext;
10
11/**
12 * Generates code from your model files on save.
13 *
14 * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#code-generation
15 */
16public class ProblemGenerator extends AbstractGenerator {
17
18 @Override
19 public void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) {
20// Iterator<Greeting> filtered = Iterators.filter(resource.getAllContents(), Greeting.class);
21// Iterator<String> names = Iterators.transform(filtered, new Function<Greeting, String>() {
22//
23// @Override
24// public String apply(Greeting greeting) {
25// return greeting.getName();
26// }
27// });
28// fsa.generateFile("greetings.txt", "People to greet: " + IteratorExtensions.join(names, ", "));
29 }
30}
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/naming/NamingUtil.java b/language/src/main/java/org/eclipse/viatra/solver/language/naming/NamingUtil.java
new file mode 100644
index 00000000..decc014a
--- /dev/null
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/naming/NamingUtil.java
@@ -0,0 +1,35 @@
1package org.eclipse.viatra.solver.language.naming;
2
3import java.util.regex.Pattern;
4
5public final class NamingUtil {
6 private static final String SINGLETON_VARIABLE_PREFIX = "_";
7
8 private static final String ENUM_NODE_NAME_QUOTE = "'";
9
10 private static final Pattern ID_REGEX = Pattern.compile("[_a-zA-Z][_0-9a-zA-Z]*");
11
12 private NamingUtil() {
13 throw new IllegalStateException("This is a static utility class and should not be instantiated directly");
14 }
15
16 public static boolean isNullOrEmpty(String name) {
17 return name == null || name.isEmpty();
18 }
19
20 public static boolean isSingletonVariableName(String name) {
21 return name != null && name.startsWith(SINGLETON_VARIABLE_PREFIX);
22 }
23
24 public static boolean isQuotedName(String name) {
25 return name != null && name.startsWith(ENUM_NODE_NAME_QUOTE) && name.endsWith(ENUM_NODE_NAME_QUOTE);
26 }
27
28 public static boolean isValidId(String name) {
29 return name != null && ID_REGEX.matcher(name).matches();
30 }
31
32 public static boolean isValidNodeName(String name) {
33 return isValidId(name) || isQuotedName(name);
34 }
35}
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java b/language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java
new file mode 100644
index 00000000..1b0146b6
--- /dev/null
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/resource/DerivedVariableComputer.java
@@ -0,0 +1,195 @@
1package org.eclipse.viatra.solver.language.resource;
2
3import java.util.HashSet;
4import java.util.List;
5import java.util.Set;
6
7import org.eclipse.viatra.solver.language.model.problem.Argument;
8import org.eclipse.viatra.solver.language.model.problem.Atom;
9import org.eclipse.viatra.solver.language.model.problem.Conjunction;
10import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier;
11import org.eclipse.viatra.solver.language.model.problem.ImplicitVariable;
12import org.eclipse.viatra.solver.language.model.problem.Literal;
13import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral;
14import org.eclipse.viatra.solver.language.model.problem.Parameter;
15import 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.ProblemFactory;
18import org.eclipse.viatra.solver.language.model.problem.ProblemPackage;
19import org.eclipse.viatra.solver.language.model.problem.Statement;
20import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument;
21import org.eclipse.viatra.solver.language.naming.NamingUtil;
22import org.eclipse.xtext.linking.impl.LinkingHelper;
23import org.eclipse.xtext.naming.IQualifiedNameConverter;
24import org.eclipse.xtext.nodemodel.INode;
25import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
26import org.eclipse.xtext.scoping.IScope;
27import org.eclipse.xtext.scoping.IScopeProvider;
28import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
29
30import com.google.inject.Inject;
31import com.google.inject.Singleton;
32import com.google.inject.name.Named;
33
34@Singleton
35public class DerivedVariableComputer {
36 @Inject
37 private LinkingHelper linkingHelper;
38
39 @Inject
40 private IQualifiedNameConverter qualifiedNameConverter;
41
42 @Inject
43 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)
44 private IScopeProvider scopeProvider;
45
46 public void installDerivedVariables(Problem problem, Set<String> nodeNames) {
47 for (Statement statement : problem.getStatements()) {
48 if (statement instanceof PredicateDefinition) {
49 PredicateDefinition definition = (PredicateDefinition) statement;
50 installDerivedPredicateDefinitionState(definition, nodeNames);
51 }
52 }
53 }
54
55 protected void installDerivedPredicateDefinitionState(PredicateDefinition definition, Set<String> nodeNames) {
56 Set<String> knownVariables = new HashSet<>();
57 knownVariables.addAll(nodeNames);
58 for (Parameter parameter : definition.getParameters()) {
59 String name = parameter.getName();
60 if (name != null) {
61 knownVariables.add(name);
62 }
63 }
64 for (Conjunction body : definition.getBodies()) {
65 installDeriveConjunctionState(body, knownVariables);
66 }
67 }
68
69 protected void installDeriveConjunctionState(Conjunction conjunction, Set<String> knownVariables) {
70 Set<String> newVariables = new HashSet<>();
71 for (Literal literal : conjunction.getLiterals()) {
72 if (literal instanceof Atom) {
73 var atom = (Atom) literal;
74 createSigletonVariablesAndCollectVariables(atom, knownVariables, newVariables);
75 }
76 }
77 createVariables(conjunction, newVariables);
78 newVariables.addAll(knownVariables);
79 for (Literal literal : conjunction.getLiterals()) {
80 if (literal instanceof NegativeLiteral) {
81 var negativeLiteral = (NegativeLiteral) literal;
82 installDeriveNegativeLiteralState(negativeLiteral, newVariables);
83 }
84 }
85 }
86
87 protected void installDeriveNegativeLiteralState(NegativeLiteral negativeLiteral, Set<String> knownVariables) {
88 Set<String> newVariables = new HashSet<>();
89 createSigletonVariablesAndCollectVariables(negativeLiteral.getAtom(), knownVariables, newVariables);
90 createVariables(negativeLiteral, newVariables);
91 }
92
93 protected void createSigletonVariablesAndCollectVariables(Atom atom, Set<String> knownVariables,
94 Set<String> newVariables) {
95 for (Argument argument : atom.getArguments()) {
96 if (argument instanceof VariableOrNodeArgument) {
97 var variableOrNodeArgument = (VariableOrNodeArgument) argument;
98 IScope scope = scopeProvider.getScope(variableOrNodeArgument,
99 ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE);
100 List<INode> nodes = NodeModelUtils.findNodesForFeature(variableOrNodeArgument,
101 ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE);
102 for (INode node : nodes) {
103 var variableName = linkingHelper.getCrossRefNodeAsString(node, true);
104 var created = tryCreateVariableForArgument(variableOrNodeArgument, variableName, scope,
105 knownVariables, newVariables);
106 if (created) {
107 break;
108 }
109 }
110 }
111 }
112 }
113
114 protected boolean tryCreateVariableForArgument(VariableOrNodeArgument variableOrNodeArgument, String variableName,
115 IScope scope, Set<String> knownVariables, Set<String> newVariables) {
116 if (!NamingUtil.isValidId(variableName)) {
117 return false;
118 }
119 var qualifiedName = qualifiedNameConverter.toQualifiedName(variableName);
120 if (scope.getSingleElement(qualifiedName) != null) {
121 return false;
122 }
123 if (NamingUtil.isSingletonVariableName(variableName)) {
124 createSingletonVariable(variableOrNodeArgument, variableName);
125 return true;
126 }
127 if (!knownVariables.contains(variableName)) {
128 newVariables.add(variableName);
129 return true;
130 }
131 return false;
132 }
133
134 protected void createVariables(ExistentialQuantifier quantifier, Set<String> newVariables) {
135 for (String variableName : newVariables) {
136 createVariable(quantifier, variableName);
137 }
138 }
139
140 protected void createVariable(ExistentialQuantifier quantifier, String variableName) {
141 if (NamingUtil.isValidId(variableName)) {
142 ImplicitVariable variable = createNamedVariable(variableName);
143 quantifier.getImplicitVariables().add(variable);
144 }
145 }
146
147 protected void createSingletonVariable(VariableOrNodeArgument argument, String variableName) {
148 if (NamingUtil.isValidId(variableName)) {
149 ImplicitVariable variable = createNamedVariable(variableName);
150 argument.setSingletonVariable(variable);
151 }
152 }
153
154 protected ImplicitVariable createNamedVariable(String variableName) {
155 var variable = ProblemFactory.eINSTANCE.createImplicitVariable();
156 variable.setName(variableName);
157 return variable;
158 }
159
160 public void discardDerivedVariables(Problem problem) {
161 for (Statement statement : problem.getStatements()) {
162 if (statement instanceof PredicateDefinition) {
163 discardPredicateDefinitionState((PredicateDefinition) statement);
164 }
165 }
166 }
167
168 protected void discardPredicateDefinitionState(PredicateDefinition definition) {
169 for (Conjunction body : definition.getBodies()) {
170 body.getImplicitVariables().clear();
171 for (Literal literal : body.getLiterals()) {
172 if (literal instanceof Atom) {
173 discardDerivedAtomState((Atom) literal);
174 }
175 if (literal instanceof NegativeLiteral) {
176 var negativeLiteral = (NegativeLiteral) literal;
177 negativeLiteral.getImplicitVariables().clear();
178 discardDerivedAtomState(negativeLiteral.getAtom());
179 }
180 }
181 }
182 }
183
184 protected void discardDerivedAtomState(Atom atom) {
185 if (atom == null) {
186 return;
187 }
188 for (Argument argument : atom.getArguments()) {
189 if (argument instanceof VariableOrNodeArgument) {
190 var variableOrNodeArgument = (VariableOrNodeArgument) argument;
191 variableOrNodeArgument.setSingletonVariable(null);
192 }
193 }
194 }
195}
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
index 79d7ffbb..597dd92d 100644
--- 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
@@ -1,6 +1,5 @@
1package org.eclipse.viatra.solver.language.resource; 1package org.eclipse.viatra.solver.language.resource;
2 2
3import java.util.HashSet;
4import java.util.List; 3import java.util.List;
5import java.util.Set; 4import java.util.Set;
6import java.util.function.Predicate; 5import java.util.function.Predicate;
@@ -21,15 +20,16 @@ import org.eclipse.viatra.solver.language.model.problem.Problem;
21import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; 20import org.eclipse.viatra.solver.language.model.problem.ProblemPackage;
22import org.eclipse.viatra.solver.language.model.problem.Statement; 21import org.eclipse.viatra.solver.language.model.problem.Statement;
23import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; 22import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument;
23import org.eclipse.viatra.solver.language.naming.NamingUtil;
24import org.eclipse.xtext.linking.impl.LinkingHelper; 24import org.eclipse.xtext.linking.impl.LinkingHelper;
25import org.eclipse.xtext.naming.IQualifiedNameConverter; 25import org.eclipse.xtext.naming.IQualifiedNameConverter;
26import org.eclipse.xtext.naming.QualifiedName;
27import org.eclipse.xtext.nodemodel.INode; 26import org.eclipse.xtext.nodemodel.INode;
28import org.eclipse.xtext.nodemodel.util.NodeModelUtils; 27import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
29import org.eclipse.xtext.scoping.IScope; 28import org.eclipse.xtext.scoping.IScope;
30import org.eclipse.xtext.scoping.IScopeProvider; 29import org.eclipse.xtext.scoping.IScopeProvider;
31import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; 30import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
32 31
32import com.google.common.collect.ImmutableSet;
33import com.google.inject.Inject; 33import com.google.inject.Inject;
34import com.google.inject.name.Named; 34import com.google.inject.name.Named;
35 35
@@ -44,12 +44,12 @@ public class NodeNameCollector {
44 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE) 44 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)
45 private IScopeProvider scopeProvider; 45 private IScopeProvider scopeProvider;
46 46
47 private final Set<String> nodeNames = new HashSet<>(); 47 private final ImmutableSet.Builder<String> nodeNames = ImmutableSet.builder();
48 48
49 private IScope nodeScope; 49 private IScope nodeScope;
50 50
51 public Set<String> getNodeNames() { 51 public Set<String> getNodeNames() {
52 return nodeNames; 52 return nodeNames.build();
53 } 53 }
54 54
55 public void collectNodeNames(Problem problem) { 55 public void collectNodeNames(Problem problem) {
@@ -73,35 +73,39 @@ public class NodeNameCollector {
73 for (AssertionArgument argument : assertion.getArguments()) { 73 for (AssertionArgument argument : assertion.getArguments()) {
74 if (argument instanceof NodeAssertionArgument) { 74 if (argument instanceof NodeAssertionArgument) {
75 collectNodeNames(argument, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE, 75 collectNodeNames(argument, ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE,
76 ProblemDerivedStateComputer::validNodeName); 76 NamingUtil::isValidNodeName);
77 } 77 }
78 } 78 }
79 } 79 }
80 80
81 protected void collectNodeValueAssertionNodeNames(NodeValueAssertion nodeValueAssertion) { 81 protected void collectNodeValueAssertionNodeNames(NodeValueAssertion nodeValueAssertion) {
82 collectNodeNames(nodeValueAssertion, ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE, 82 collectNodeNames(nodeValueAssertion, ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE,
83 ProblemDerivedStateComputer::validNodeName); 83 NamingUtil::isValidNodeName);
84 } 84 }
85 85
86 protected void collectPredicateDefinitionNodeNames(PredicateDefinition predicateDefinition) { 86 protected void collectPredicateDefinitionNodeNames(PredicateDefinition predicateDefinition) {
87 for (Conjunction body : predicateDefinition.getBodies()) { 87 for (Conjunction body : predicateDefinition.getBodies()) {
88 for (Literal literal : body.getLiterals()) { 88 for (Literal literal : body.getLiterals()) {
89 Atom atom = null; 89 collectLiteralNodeNames(literal);
90 if (literal instanceof Atom) { 90 }
91 atom = (Atom) literal; 91 }
92 } else if (literal instanceof NegativeLiteral) { 92 }
93 NegativeLiteral negativeLiteral = (NegativeLiteral) literal; 93
94 atom = negativeLiteral.getAtom(); 94 protected void collectLiteralNodeNames(Literal literal) {
95 } 95 Atom atom = null;
96 if (atom == null) { 96 if (literal instanceof Atom) {
97 continue; 97 atom = (Atom) literal;
98 } 98 } else if (literal instanceof NegativeLiteral) {
99 for (Argument argument : atom.getArguments()) { 99 var negativeLiteral = (NegativeLiteral) literal;
100 if (argument instanceof VariableOrNodeArgument) { 100 atom = negativeLiteral.getAtom();
101 collectNodeNames(argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE, 101 }
102 ProblemDerivedStateComputer::validQuotedId); 102 if (atom == null) {
103 } 103 return;
104 } 104 }
105 for (Argument argument : atom.getArguments()) {
106 if (argument instanceof VariableOrNodeArgument) {
107 collectNodeNames(argument, ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE,
108 NamingUtil::isQuotedName);
105 } 109 }
106 } 110 }
107 } 111 }
@@ -109,11 +113,11 @@ public class NodeNameCollector {
109 private void collectNodeNames(EObject eObject, EStructuralFeature feature, Predicate<String> condition) { 113 private void collectNodeNames(EObject eObject, EStructuralFeature feature, Predicate<String> condition) {
110 List<INode> nodes = NodeModelUtils.findNodesForFeature(eObject, feature); 114 List<INode> nodes = NodeModelUtils.findNodesForFeature(eObject, feature);
111 for (INode node : nodes) { 115 for (INode node : nodes) {
112 String nodeName = linkingHelper.getCrossRefNodeAsString(node, true); 116 var nodeName = linkingHelper.getCrossRefNodeAsString(node, true);
113 if (!condition.test(nodeName)) { 117 if (!condition.test(nodeName)) {
114 continue; 118 continue;
115 } 119 }
116 QualifiedName qualifiedName = qualifiedNameConverter.toQualifiedName(nodeName); 120 var qualifiedName = qualifiedNameConverter.toQualifiedName(nodeName);
117 if (nodeScope.getSingleElement(qualifiedName) == null) { 121 if (nodeScope.getSingleElement(qualifiedName) == null) {
118 nodeNames.add(nodeName); 122 nodeNames.add(nodeName);
119 } 123 }
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 81236afd..a2d0eef6 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
@@ -1,43 +1,26 @@
1package org.eclipse.viatra.solver.language.resource; 1package org.eclipse.viatra.solver.language.resource;
2 2
3import java.util.Collection;
3import java.util.HashMap; 4import java.util.HashMap;
4import java.util.HashSet; 5import java.util.HashSet;
5import java.util.List; 6import java.util.List;
6import java.util.Map; 7import java.util.Map;
7import java.util.Set; 8import java.util.Set;
8import java.util.regex.Pattern; 9import java.util.function.Function;
9 10
10import org.eclipse.emf.common.notify.impl.AdapterImpl; 11import org.eclipse.emf.common.notify.impl.AdapterImpl;
11import org.eclipse.emf.ecore.EObject; 12import org.eclipse.emf.ecore.EObject;
12import org.eclipse.emf.ecore.resource.Resource; 13import org.eclipse.emf.ecore.resource.Resource;
13import org.eclipse.emf.ecore.util.EcoreUtil; 14import org.eclipse.emf.ecore.util.EcoreUtil;
14import org.eclipse.viatra.solver.language.ProblemUtil;
15import org.eclipse.viatra.solver.language.model.problem.Argument;
16import org.eclipse.viatra.solver.language.model.problem.Atom;
17import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; 15import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration;
18import org.eclipse.viatra.solver.language.model.problem.Conjunction;
19import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier;
20import org.eclipse.viatra.solver.language.model.problem.ImplicitVariable;
21import org.eclipse.viatra.solver.language.model.problem.Literal;
22import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral;
23import org.eclipse.viatra.solver.language.model.problem.Node; 16import org.eclipse.viatra.solver.language.model.problem.Node;
24import org.eclipse.viatra.solver.language.model.problem.Parameter;
25import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition;
26import org.eclipse.viatra.solver.language.model.problem.Problem; 17import org.eclipse.viatra.solver.language.model.problem.Problem;
27import org.eclipse.viatra.solver.language.model.problem.ProblemFactory; 18import org.eclipse.viatra.solver.language.model.problem.ProblemFactory;
28import org.eclipse.viatra.solver.language.model.problem.ProblemPackage;
29import org.eclipse.viatra.solver.language.model.problem.Statement; 19import org.eclipse.viatra.solver.language.model.problem.Statement;
30import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument;
31import org.eclipse.xtext.Constants; 20import org.eclipse.xtext.Constants;
32import org.eclipse.xtext.linking.impl.LinkingHelper;
33import org.eclipse.xtext.naming.IQualifiedNameConverter;
34import org.eclipse.xtext.naming.QualifiedName;
35import org.eclipse.xtext.nodemodel.INode;
36import org.eclipse.xtext.nodemodel.util.NodeModelUtils;
37import org.eclipse.xtext.resource.DerivedStateAwareResource; 21import org.eclipse.xtext.resource.DerivedStateAwareResource;
38import org.eclipse.xtext.resource.IDerivedStateComputer; 22import org.eclipse.xtext.resource.IDerivedStateComputer;
39import org.eclipse.xtext.resource.XtextResource; 23import org.eclipse.xtext.resource.XtextResource;
40import org.eclipse.xtext.scoping.IScope;
41import org.eclipse.xtext.scoping.IScopeProvider; 24import org.eclipse.xtext.scoping.IScopeProvider;
42import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; 25import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider;
43 26
@@ -50,32 +33,25 @@ import com.google.inject.name.Named;
50public class ProblemDerivedStateComputer implements IDerivedStateComputer { 33public class ProblemDerivedStateComputer implements IDerivedStateComputer {
51 public static final String NEW_NODE = "new"; 34 public static final String NEW_NODE = "new";
52 35
53 private static final Pattern ID_REGEX = Pattern.compile("[_a-zA-Z][_0-9a-zA-Z]*");
54
55 private static final Pattern QUOTED_ID_REGEX = Pattern.compile("'(\\\\.|[^\\'])*'");
56
57 @Inject 36 @Inject
58 @Named(Constants.LANGUAGE_NAME) 37 @Named(Constants.LANGUAGE_NAME)
59 private String languageName; 38 private String languageName;
60 39
61 @Inject 40 @Inject
62 private LinkingHelper linkingHelper;
63
64 @Inject
65 private IQualifiedNameConverter qualifiedNameConverter;
66
67 @Inject
68 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE) 41 @Named(AbstractDeclarativeScopeProvider.NAMED_DELEGATE)
69 private IScopeProvider scopeProvider; 42 private IScopeProvider scopeProvider;
70 43
71 @Inject 44 @Inject
72 private Provider<NodeNameCollector> nodeNameCollectorProvider; 45 private Provider<NodeNameCollector> nodeNameCollectorProvider;
73 46
47 @Inject
48 private DerivedVariableComputer derivedVariableComputer;
49
74 @Override 50 @Override
75 public void installDerivedState(DerivedStateAwareResource resource, boolean preLinkingPhase) { 51 public void installDerivedState(DerivedStateAwareResource resource, boolean preLinkingPhase) {
76 Problem problem = getProblem(resource); 52 var problem = getProblem(resource);
77 if (problem != null) { 53 if (problem != null) {
78 Adapter adapter = getOrInstallAdapter(resource); 54 var adapter = getOrInstallAdapter(resource);
79 installDerivedProblemState(problem, adapter, preLinkingPhase); 55 installDerivedProblemState(problem, adapter, preLinkingPhase);
80 } 56 }
81 } 57 }
@@ -98,20 +74,15 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
98 return; 74 return;
99 } 75 }
100 Set<String> nodeNames = installDerivedNodes(problem); 76 Set<String> nodeNames = installDerivedNodes(problem);
101 for (Statement statement : problem.getStatements()) { 77 derivedVariableComputer.installDerivedVariables(problem, nodeNames);
102 if (statement instanceof PredicateDefinition) {
103 PredicateDefinition definition = (PredicateDefinition) statement;
104 installDerivedPredicateDefinitionState(definition, nodeNames);
105 }
106 }
107 } 78 }
108 79
109 protected void installNewNodes(Problem problem, Adapter adapter) { 80 protected void installNewNodes(Problem problem, Adapter adapter) {
110 for (Statement statement : problem.getStatements()) { 81 for (Statement statement : problem.getStatements()) {
111 if (statement instanceof ClassDeclaration) { 82 if (statement instanceof ClassDeclaration) {
112 ClassDeclaration declaration = (ClassDeclaration) statement; 83 var declaration = (ClassDeclaration) statement;
113 if (!declaration.isAbstract() && declaration.getNewNode() == null) { 84 if (!declaration.isAbstract() && declaration.getNewNode() == null) {
114 Node newNode = adapter.newNodes.computeIfAbsent(declaration, key -> createNode(NEW_NODE)); 85 var newNode = adapter.createNodeIfAbsent(declaration, key -> createNode(NEW_NODE));
115 declaration.setNewNode(newNode); 86 declaration.setNewNode(newNode);
116 } 87 }
117 } 88 }
@@ -119,123 +90,28 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
119 } 90 }
120 91
121 protected Set<String> installDerivedNodes(Problem problem) { 92 protected Set<String> installDerivedNodes(Problem problem) {
122 NodeNameCollector collector = nodeNameCollectorProvider.get(); 93 var collector = nodeNameCollectorProvider.get();
123 collector.collectNodeNames(problem); 94 collector.collectNodeNames(problem);
124 Set<String> nodeNames = collector.getNodeNames(); 95 Set<String> nodeNames = collector.getNodeNames();
125 List<Node> grapNodes = problem.getNodes(); 96 List<Node> grapNodes = problem.getNodes();
126 for (String nodeName : nodeNames) { 97 for (String nodeName : nodeNames) {
127 Node graphNode = createNode(nodeName); 98 var graphNode = createNode(nodeName);
128 grapNodes.add(graphNode); 99 grapNodes.add(graphNode);
129 } 100 }
130 return nodeNames; 101 return nodeNames;
131 } 102 }
132 103
133 protected Node createNode(String name) { 104 protected Node createNode(String name) {
134 Node node = ProblemFactory.eINSTANCE.createNode(); 105 var node = ProblemFactory.eINSTANCE.createNode();
135 node.setName(name); 106 node.setName(name);
136 return node; 107 return node;
137 } 108 }
138 109
139 protected void installDerivedPredicateDefinitionState(PredicateDefinition definition, Set<String> nodeNames) {
140 Set<String> knownVariables = new HashSet<>();
141 knownVariables.addAll(nodeNames);
142 for (Parameter parameter : definition.getParameters()) {
143 String name = parameter.getName();
144 if (name != null) {
145 knownVariables.add(name);
146 }
147 }
148 for (Conjunction body : definition.getBodies()) {
149 installDeriveConjunctionState(body, knownVariables);
150 }
151 }
152
153 protected void installDeriveConjunctionState(Conjunction conjunction, Set<String> knownVariables) {
154 Set<String> newVariables = new HashSet<>();
155 for (Literal literal : conjunction.getLiterals()) {
156 if (literal instanceof Atom) {
157 Atom atom = (Atom) literal;
158 createSigletonVariablesAndCollectVariables(atom, knownVariables, newVariables);
159 }
160 }
161 createVariables(conjunction, newVariables);
162 newVariables.addAll(knownVariables);
163 for (Literal literal : conjunction.getLiterals()) {
164 if (literal instanceof NegativeLiteral) {
165 NegativeLiteral negativeLiteral = (NegativeLiteral) literal;
166 installDeriveNegativeLiteralState(negativeLiteral, newVariables);
167 }
168 }
169 }
170
171 protected void installDeriveNegativeLiteralState(NegativeLiteral negativeLiteral, Set<String> knownVariables) {
172 Set<String> newVariables = new HashSet<>();
173 createSigletonVariablesAndCollectVariables(negativeLiteral.getAtom(), knownVariables, newVariables);
174 createVariables(negativeLiteral, newVariables);
175 }
176
177 protected void createSigletonVariablesAndCollectVariables(Atom atom, Set<String> knownVariables,
178 Set<String> newVariables) {
179 for (Argument argument : atom.getArguments()) {
180 if (argument instanceof VariableOrNodeArgument) {
181 VariableOrNodeArgument variableOrNodeArgument = (VariableOrNodeArgument) argument;
182 IScope scope = scopeProvider.getScope(variableOrNodeArgument,
183 ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE);
184 List<INode> nodes = NodeModelUtils.findNodesForFeature(variableOrNodeArgument,
185 ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE);
186 for (INode node : nodes) {
187 String variableName = linkingHelper.getCrossRefNodeAsString(node, true);
188 if (!validId(variableName)) {
189 continue;
190 }
191 QualifiedName qualifiedName = qualifiedNameConverter.toQualifiedName(variableName);
192 if (scope.getSingleElement(qualifiedName) != null) {
193 continue;
194 }
195 if (ProblemUtil.isSingletonVariableName(variableName)) {
196 createSingletonVariable(variableOrNodeArgument, variableName);
197 break;
198 }
199 if (!knownVariables.contains(variableName)) {
200 newVariables.add(variableName);
201 break;
202 }
203 }
204 }
205 }
206 }
207
208 protected void createVariables(ExistentialQuantifier quantifier, Set<String> newVariables) {
209 for (String variableName : newVariables) {
210 createVariable(quantifier, variableName);
211 }
212 }
213
214 protected void createVariable(ExistentialQuantifier quantifier, String variableName) {
215 if (validId(variableName)) {
216 ImplicitVariable variable = createNamedVariable(variableName);
217 quantifier.getImplicitVariables().add(variable);
218 }
219 }
220
221 protected void createSingletonVariable(VariableOrNodeArgument argument, String variableName) {
222 if (validId(variableName)) {
223 ImplicitVariable variable = createNamedVariable(variableName);
224 argument.setSingletonVariable(variable);
225 }
226 }
227
228 protected ImplicitVariable createNamedVariable(String variableName) {
229 ImplicitVariable variable = ProblemFactory.eINSTANCE.createImplicitVariable();
230 variable.setName(variableName);
231 return variable;
232 }
233
234 @Override 110 @Override
235 public void discardDerivedState(DerivedStateAwareResource resource) { 111 public void discardDerivedState(DerivedStateAwareResource resource) {
236 Problem problem = getProblem(resource); 112 var problem = getProblem(resource);
237 if (problem != null) { 113 if (problem != null) {
238 Adapter adapter = getOrInstallAdapter(resource); 114 var adapter = getOrInstallAdapter(resource);
239 discardDerivedProblemState(problem, adapter); 115 discardDerivedProblemState(problem, adapter);
240 } 116 }
241 } 117 }
@@ -245,52 +121,13 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
245 problem.getNodes().clear(); 121 problem.getNodes().clear();
246 for (Statement statement : problem.getStatements()) { 122 for (Statement statement : problem.getStatements()) {
247 if (statement instanceof ClassDeclaration) { 123 if (statement instanceof ClassDeclaration) {
248 ClassDeclaration classDeclaration = (ClassDeclaration) statement; 124 var classDeclaration = (ClassDeclaration) statement;
249 classDeclaration.setNewNode(null); 125 classDeclaration.setNewNode(null);
250 classDeclarations.add(classDeclaration); 126 classDeclarations.add(classDeclaration);
251 } 127 }
252 if (statement instanceof PredicateDefinition) {
253 PredicateDefinition definition = (PredicateDefinition) statement;
254 for (Conjunction body : definition.getBodies()) {
255 body.getImplicitVariables().clear();
256 for (Literal literal : body.getLiterals()) {
257 if (literal instanceof Atom) {
258 discardDerivedAtomState((Atom) literal);
259 }
260 if (literal instanceof NegativeLiteral) {
261 NegativeLiteral negativeLiteral = (NegativeLiteral) literal;
262 negativeLiteral.getImplicitVariables().clear();
263 discardDerivedAtomState(negativeLiteral.getAtom());
264 }
265 }
266 }
267 }
268 } 128 }
269 adapter.newNodes.keySet().retainAll(classDeclarations); 129 adapter.retainAll(classDeclarations);
270 } 130 derivedVariableComputer.discardDerivedVariables(problem);
271
272 protected void discardDerivedAtomState(Atom atom) {
273 if (atom == null) {
274 return;
275 }
276 for (Argument argument : atom.getArguments()) {
277 if (argument instanceof VariableOrNodeArgument) {
278 VariableOrNodeArgument variableOrNodeArgument = (VariableOrNodeArgument) argument;
279 variableOrNodeArgument.setSingletonVariable(null);
280 }
281 }
282 }
283
284 protected static boolean validId(String name) {
285 return name != null && ID_REGEX.matcher(name).matches();
286 }
287
288 protected static boolean validQuotedId(String name) {
289 return name != null && QUOTED_ID_REGEX.matcher(name).matches();
290 }
291
292 protected static boolean validNodeName(String name) {
293 return validId(name) || validQuotedId(name);
294 } 131 }
295 132
296 protected Adapter getOrInstallAdapter(Resource resource) { 133 protected Adapter getOrInstallAdapter(Resource resource) {
@@ -301,7 +138,7 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
301 if (!languageName.equals(resourceLanguageName)) { 138 if (!languageName.equals(resourceLanguageName)) {
302 return new Adapter(); 139 return new Adapter();
303 } 140 }
304 Adapter adapter = (Adapter) EcoreUtil.getAdapter(resource.eAdapters(), Adapter.class); 141 var adapter = (Adapter) EcoreUtil.getAdapter(resource.eAdapters(), Adapter.class);
305 if (adapter == null) { 142 if (adapter == null) {
306 adapter = new Adapter(); 143 adapter = new Adapter();
307 resource.eAdapters().add(adapter); 144 resource.eAdapters().add(adapter);
@@ -310,7 +147,15 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer {
310 } 147 }
311 148
312 protected static class Adapter extends AdapterImpl { 149 protected static class Adapter extends AdapterImpl {
313 public Map<ClassDeclaration, Node> newNodes = new HashMap<>(); 150 private Map<ClassDeclaration, Node> newNodes = new HashMap<>();
151
152 public Node createNodeIfAbsent(ClassDeclaration classDeclaration, Function<ClassDeclaration, Node> createNode) {
153 return newNodes.computeIfAbsent(classDeclaration, createNode);
154 }
155
156 public void retainAll(Collection<ClassDeclaration> classDeclarations) {
157 newNodes.keySet().retainAll(classDeclarations);
158 }
314 159
315 @Override 160 @Override
316 public boolean isAdapterForType(Object type) { 161 public boolean isAdapterForType(Object type) {
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemResourceDescriptionStrategy.java b/language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemResourceDescriptionStrategy.java
index 686e54df..da737e3d 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemResourceDescriptionStrategy.java
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/resource/ProblemResourceDescriptionStrategy.java
@@ -6,6 +6,7 @@ import org.eclipse.viatra.solver.language.model.problem.NamedElement;
6import org.eclipse.viatra.solver.language.model.problem.Node; 6import org.eclipse.viatra.solver.language.model.problem.Node;
7import org.eclipse.viatra.solver.language.model.problem.Problem; 7import org.eclipse.viatra.solver.language.model.problem.Problem;
8import org.eclipse.viatra.solver.language.model.problem.Variable; 8import org.eclipse.viatra.solver.language.model.problem.Variable;
9import org.eclipse.viatra.solver.language.naming.NamingUtil;
9import org.eclipse.xtext.EcoreUtil2; 10import org.eclipse.xtext.EcoreUtil2;
10import org.eclipse.xtext.naming.IQualifiedNameConverter; 11import org.eclipse.xtext.naming.IQualifiedNameConverter;
11import org.eclipse.xtext.naming.QualifiedName; 12import org.eclipse.xtext.naming.QualifiedName;
@@ -27,61 +28,59 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti
27 if (!shouldExport(eObject)) { 28 if (!shouldExport(eObject)) {
28 return false; 29 return false;
29 } 30 }
30 if (!(eObject instanceof NamedElement)) { 31 var qualifiedName = getNameAsQualifiedName(eObject);
31 return true; 32 if (qualifiedName == null) {
32 }
33 NamedElement namedElement = (NamedElement) eObject;
34 String name = namedElement.getName();
35 if (name == null || name.isEmpty()) {
36 return true; 33 return true;
37 } 34 }
38 Problem problem = EcoreUtil2.getContainerOfType(namedElement, Problem.class); 35 var problem = EcoreUtil2.getContainerOfType(eObject, Problem.class);
39 QualifiedName problemQualifiedName = null; 36 var problemQualifiedName = getNameAsQualifiedName(problem);
40 if (problem != null) {
41 String problemName = problem.getName();
42 if (problemName != null && !problemName.isEmpty()) {
43 problemQualifiedName = qualifiedNameConverter.toQualifiedName(problemName);
44 }
45 }
46 QualifiedName qualifiedName = qualifiedNameConverter.toQualifiedName(namedElement.getName());
47 boolean nameExported; 37 boolean nameExported;
48 if (shouldExportSimpleName(namedElement)) { 38 if (shouldExportSimpleName(eObject)) {
49 acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); 39 acceptEObjectDescription(eObject, problemQualifiedName, qualifiedName, acceptor);
50 nameExported = true; 40 nameExported = true;
51 } else { 41 } else {
52 nameExported = false; 42 nameExported = false;
53 } 43 }
54 EObject parent = namedElement.eContainer(); 44 var parent = eObject.eContainer();
55 while (parent != null && parent != problem) { 45 while (parent != null && parent != problem) {
56 if (parent instanceof NamedElement) { 46 var parentQualifiedName = getNameAsQualifiedName(parent);
57 NamedElement namedParent = (NamedElement) parent; 47 if (parentQualifiedName == null) {
58 String parentName = namedParent.getName(); 48 continue;
59 if (parentName != null || !name.isEmpty()) { 49 }
60 QualifiedName parentQualifiedName = qualifiedNameConverter.toQualifiedName(parentName); 50 qualifiedName = parentQualifiedName.append(qualifiedName);
61 qualifiedName = parentQualifiedName.append(qualifiedName); 51 if (shouldExportSimpleName(parent)) {
62 if (shouldExportSimpleName(namedParent)) { 52 acceptEObjectDescription(eObject, problemQualifiedName, qualifiedName, acceptor);
63 acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); 53 nameExported = true;
64 nameExported = true; 54 } else {
65 } else { 55 nameExported = false;
66 nameExported = false;
67 }
68 }
69 } 56 }
70 parent = parent.eContainer(); 57 parent = parent.eContainer();
71 } 58 }
72 if (!nameExported) { 59 if (!nameExported) {
73 acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); 60 acceptEObjectDescription(eObject, problemQualifiedName, qualifiedName, acceptor);
74 } 61 }
75 return true; 62 return true;
76 } 63 }
77 64
65 protected QualifiedName getNameAsQualifiedName(EObject eObject) {
66 if (!(eObject instanceof NamedElement)) {
67 return null;
68 }
69 var namedElement = (NamedElement) eObject;
70 var name = namedElement.getName();
71 if (NamingUtil.isNullOrEmpty(name)) {
72 return null;
73 }
74 return qualifiedNameConverter.toQualifiedName(name);
75 }
76
78 protected boolean shouldExport(EObject eObject) { 77 protected boolean shouldExport(EObject eObject) {
79 if (eObject instanceof Variable) { 78 if (eObject instanceof Variable) {
80 // Variables are always private to the containing predicate definition. 79 // Variables are always private to the containing predicate definition.
81 return false; 80 return false;
82 } 81 }
83 if (eObject instanceof Node) { 82 if (eObject instanceof Node) {
84 Node node = (Node) eObject; 83 var node = (Node) eObject;
85 // Only enum literals and new nodes are visible across problem files. 84 // Only enum literals and new nodes are visible across problem files.
86 return ProblemUtil.isEnumLiteral(node) || ProblemUtil.isNewNode(node); 85 return ProblemUtil.isEnumLiteral(node) || ProblemUtil.isNewNode(node);
87 } 86 }
@@ -97,7 +96,7 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti
97 96
98 private void acceptEObjectDescription(EObject eObject, QualifiedName prefix, QualifiedName qualifiedName, 97 private void acceptEObjectDescription(EObject eObject, QualifiedName prefix, QualifiedName qualifiedName,
99 IAcceptor<IEObjectDescription> acceptor) { 98 IAcceptor<IEObjectDescription> acceptor) {
100 QualifiedName qualifiedNameWithPrefix = prefix == null ? qualifiedName : prefix.append(qualifiedName); 99 var qualifiedNameWithPrefix = prefix == null ? qualifiedName : prefix.append(qualifiedName);
101 acceptor.accept(EObjectDescription.create(qualifiedNameWithPrefix, eObject)); 100 acceptor.accept(EObjectDescription.create(qualifiedNameWithPrefix, eObject));
102 } 101 }
103} 102}
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java b/language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java
index 597085a8..33f8c50f 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/scoping/ProblemScopeProvider.java
@@ -4,7 +4,6 @@
4package org.eclipse.viatra.solver.language.scoping; 4package org.eclipse.viatra.solver.language.scoping;
5 5
6import java.util.ArrayList; 6import java.util.ArrayList;
7import java.util.Collection;
8import java.util.List; 7import java.util.List;
9 8
10import org.eclipse.emf.ecore.EObject; 9import org.eclipse.emf.ecore.EObject;
@@ -16,7 +15,6 @@ import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition;
16import org.eclipse.viatra.solver.language.model.problem.Problem; 15import org.eclipse.viatra.solver.language.model.problem.Problem;
17import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; 16import org.eclipse.viatra.solver.language.model.problem.ProblemPackage;
18import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; 17import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration;
19import org.eclipse.viatra.solver.language.model.problem.Relation;
20import org.eclipse.viatra.solver.language.model.problem.Variable; 18import org.eclipse.viatra.solver.language.model.problem.Variable;
21import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; 19import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument;
22import org.eclipse.xtext.EcoreUtil2; 20import org.eclipse.xtext.EcoreUtil2;
@@ -34,7 +32,7 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider {
34 32
35 @Override 33 @Override
36 public IScope getScope(EObject context, EReference reference) { 34 public IScope getScope(EObject context, EReference reference) {
37 IScope scope = super.getScope(context, reference); 35 var scope = super.getScope(context, reference);
38 if (reference == ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE 36 if (reference == ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE
39 || reference == ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE) { 37 || reference == ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE) {
40 return getNodesScope(context, scope); 38 return getNodesScope(context, scope);
@@ -49,7 +47,7 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider {
49 } 47 }
50 48
51 protected IScope getNodesScope(EObject context, IScope delegateScope) { 49 protected IScope getNodesScope(EObject context, IScope delegateScope) {
52 Problem problem = EcoreUtil2.getContainerOfType(context, Problem.class); 50 var problem = EcoreUtil2.getContainerOfType(context, Problem.class);
53 if (problem == null) { 51 if (problem == null) {
54 return delegateScope; 52 return delegateScope;
55 } 53 }
@@ -73,7 +71,7 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider {
73 } 71 }
74 currentContext = currentContext.eContainer(); 72 currentContext = currentContext.eContainer();
75 } 73 }
76 if (currentContext instanceof PredicateDefinition) { 74 if (currentContext != null) {
77 PredicateDefinition definition = (PredicateDefinition) currentContext; 75 PredicateDefinition definition = (PredicateDefinition) currentContext;
78 variables.addAll(definition.getParameters()); 76 variables.addAll(definition.getParameters());
79 } 77 }
@@ -81,17 +79,16 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider {
81 } 79 }
82 80
83 protected IScope getOppositeScope(EObject context, IScope delegateScope) { 81 protected IScope getOppositeScope(EObject context, IScope delegateScope) {
84 ReferenceDeclaration referenceDeclaration = EcoreUtil2.getContainerOfType(context, ReferenceDeclaration.class); 82 var referenceDeclaration = EcoreUtil2.getContainerOfType(context, ReferenceDeclaration.class);
85 if (referenceDeclaration == null) { 83 if (referenceDeclaration == null) {
86 return delegateScope; 84 return delegateScope;
87 } 85 }
88 Relation relation = referenceDeclaration.getReferenceType(); 86 var relation = referenceDeclaration.getReferenceType();
89 if (!(relation instanceof ClassDeclaration)) { 87 if (!(relation instanceof ClassDeclaration)) {
90 return delegateScope; 88 return delegateScope;
91 } 89 }
92 ClassDeclaration classDeclaration = (ClassDeclaration) relation; 90 var classDeclaration = (ClassDeclaration) relation;
93 Collection<ReferenceDeclaration> referenceDeclarations = ProblemUtil 91 var referenceDeclarations = ProblemUtil.getAllReferenceDeclarations(classDeclaration);
94 .getAllReferenceDeclarations(classDeclaration);
95 return Scopes.scopeFor(referenceDeclarations, delegateScope); 92 return Scopes.scopeFor(referenceDeclarations, delegateScope);
96 } 93 }
97} 94}
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/validation/ProblemValidator.java b/language/src/main/java/org/eclipse/viatra/solver/language/validation/ProblemValidator.java
index 2b17e222..96b656a3 100644
--- a/language/src/main/java/org/eclipse/viatra/solver/language/validation/ProblemValidator.java
+++ b/language/src/main/java/org/eclipse/viatra/solver/language/validation/ProblemValidator.java
@@ -3,23 +3,11 @@
3 */ 3 */
4package org.eclipse.viatra.solver.language.validation; 4package org.eclipse.viatra.solver.language.validation;
5 5
6
7/** 6/**
8 * This class contains custom validation rules. 7 * This class contains custom validation rules.
9 * 8 *
10 * See https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation 9 * See
10 * https://www.eclipse.org/Xtext/documentation/303_runtime_concepts.html#validation
11 */ 11 */
12public class ProblemValidator extends AbstractProblemValidator { 12public class ProblemValidator extends AbstractProblemValidator {
13
14// public static final String INVALID_NAME = "invalidName";
15//
16// @Check
17// public void checkGreetingStartsWithCapital(Greeting greeting) {
18// if (!Character.isUpperCase(greeting.getName().charAt(0))) {
19// warning("Name should start with a capital",
20// ProblemPackage.Literals.GREETING__NAME,
21// INVALID_NAME);
22// }
23// }
24
25} 13}