diff options
author | 2021-07-29 17:09:24 +0200 | |
---|---|---|
committer | 2021-07-29 17:09:24 +0200 | |
commit | 97ea34af2f8e5d0ca9da5dda331a9f54e580c4c6 (patch) | |
tree | 2f58b2e34609439b53e3a7ddd5337bb4733ce707 /language/src | |
parent | Appearance fixes (diff) | |
download | refinery-97ea34af2f8e5d0ca9da5dda331a9f54e580c4c6.tar.gz refinery-97ea34af2f8e5d0ca9da5dda331a9f54e580c4c6.tar.zst refinery-97ea34af2f8e5d0ca9da5dda331a9f54e580c4c6.zip |
Refactoring based on Sonar reports
Diffstat (limited to 'language/src')
13 files changed, 361 insertions, 316 deletions
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; | |||
9 | import com.google.inject.Injector; | 9 | import 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 | */ |
14 | public class ProblemStandaloneSetup extends ProblemStandaloneSetupGenerated { | 15 | public 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; | |||
16 | import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; | 16 | import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; |
17 | import org.eclipse.viatra.solver.language.model.problem.Relation; | 17 | import org.eclipse.viatra.solver.language.model.problem.Relation; |
18 | import org.eclipse.viatra.solver.language.model.problem.Variable; | 18 | import org.eclipse.viatra.solver.language.model.problem.Variable; |
19 | import org.eclipse.viatra.solver.language.naming.NamingUtil; | ||
19 | import org.eclipse.viatra.solver.language.scoping.ProblemGlobalScopeProvider; | 20 | import org.eclipse.viatra.solver.language.scoping.ProblemGlobalScopeProvider; |
20 | 21 | ||
21 | import com.google.common.collect.ImmutableList; | 22 | import com.google.common.collect.ImmutableList; |
22 | import com.google.inject.Singleton; | ||
23 | 23 | ||
24 | @Singleton | ||
25 | public final class ProblemUtil { | 24 | public 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; | |||
9 | public class ProblemValueConverterService extends DefaultTerminalConverters { | 9 | public 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 | */ | ||
4 | package org.eclipse.viatra.solver.language.generator; | ||
5 | |||
6 | import org.eclipse.emf.ecore.resource.Resource; | ||
7 | import org.eclipse.xtext.generator.AbstractGenerator; | ||
8 | import org.eclipse.xtext.generator.IFileSystemAccess2; | ||
9 | import 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 | */ | ||
16 | public 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 @@ | |||
1 | package org.eclipse.viatra.solver.language.naming; | ||
2 | |||
3 | import java.util.regex.Pattern; | ||
4 | |||
5 | public 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 @@ | |||
1 | package org.eclipse.viatra.solver.language.resource; | ||
2 | |||
3 | import java.util.HashSet; | ||
4 | import java.util.List; | ||
5 | import java.util.Set; | ||
6 | |||
7 | import org.eclipse.viatra.solver.language.model.problem.Argument; | ||
8 | import org.eclipse.viatra.solver.language.model.problem.Atom; | ||
9 | import org.eclipse.viatra.solver.language.model.problem.Conjunction; | ||
10 | import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier; | ||
11 | import org.eclipse.viatra.solver.language.model.problem.ImplicitVariable; | ||
12 | import org.eclipse.viatra.solver.language.model.problem.Literal; | ||
13 | import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral; | ||
14 | import org.eclipse.viatra.solver.language.model.problem.Parameter; | ||
15 | import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; | ||
16 | import org.eclipse.viatra.solver.language.model.problem.Problem; | ||
17 | import org.eclipse.viatra.solver.language.model.problem.ProblemFactory; | ||
18 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; | ||
19 | import org.eclipse.viatra.solver.language.model.problem.Statement; | ||
20 | import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; | ||
21 | import org.eclipse.viatra.solver.language.naming.NamingUtil; | ||
22 | import org.eclipse.xtext.linking.impl.LinkingHelper; | ||
23 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
24 | import org.eclipse.xtext.nodemodel.INode; | ||
25 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; | ||
26 | import org.eclipse.xtext.scoping.IScope; | ||
27 | import org.eclipse.xtext.scoping.IScopeProvider; | ||
28 | import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; | ||
29 | |||
30 | import com.google.inject.Inject; | ||
31 | import com.google.inject.Singleton; | ||
32 | import com.google.inject.name.Named; | ||
33 | |||
34 | @Singleton | ||
35 | public 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 @@ | |||
1 | package org.eclipse.viatra.solver.language.resource; | 1 | package org.eclipse.viatra.solver.language.resource; |
2 | 2 | ||
3 | import java.util.HashSet; | ||
4 | import java.util.List; | 3 | import java.util.List; |
5 | import java.util.Set; | 4 | import java.util.Set; |
6 | import java.util.function.Predicate; | 5 | import java.util.function.Predicate; |
@@ -21,15 +20,16 @@ import org.eclipse.viatra.solver.language.model.problem.Problem; | |||
21 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; | 20 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; |
22 | import org.eclipse.viatra.solver.language.model.problem.Statement; | 21 | import org.eclipse.viatra.solver.language.model.problem.Statement; |
23 | import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; | 22 | import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; |
23 | import org.eclipse.viatra.solver.language.naming.NamingUtil; | ||
24 | import org.eclipse.xtext.linking.impl.LinkingHelper; | 24 | import org.eclipse.xtext.linking.impl.LinkingHelper; |
25 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | 25 | import org.eclipse.xtext.naming.IQualifiedNameConverter; |
26 | import org.eclipse.xtext.naming.QualifiedName; | ||
27 | import org.eclipse.xtext.nodemodel.INode; | 26 | import org.eclipse.xtext.nodemodel.INode; |
28 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; | 27 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; |
29 | import org.eclipse.xtext.scoping.IScope; | 28 | import org.eclipse.xtext.scoping.IScope; |
30 | import org.eclipse.xtext.scoping.IScopeProvider; | 29 | import org.eclipse.xtext.scoping.IScopeProvider; |
31 | import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; | 30 | import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; |
32 | 31 | ||
32 | import com.google.common.collect.ImmutableSet; | ||
33 | import com.google.inject.Inject; | 33 | import com.google.inject.Inject; |
34 | import com.google.inject.name.Named; | 34 | import 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 @@ | |||
1 | package org.eclipse.viatra.solver.language.resource; | 1 | package org.eclipse.viatra.solver.language.resource; |
2 | 2 | ||
3 | import java.util.Collection; | ||
3 | import java.util.HashMap; | 4 | import java.util.HashMap; |
4 | import java.util.HashSet; | 5 | import java.util.HashSet; |
5 | import java.util.List; | 6 | import java.util.List; |
6 | import java.util.Map; | 7 | import java.util.Map; |
7 | import java.util.Set; | 8 | import java.util.Set; |
8 | import java.util.regex.Pattern; | 9 | import java.util.function.Function; |
9 | 10 | ||
10 | import org.eclipse.emf.common.notify.impl.AdapterImpl; | 11 | import org.eclipse.emf.common.notify.impl.AdapterImpl; |
11 | import org.eclipse.emf.ecore.EObject; | 12 | import org.eclipse.emf.ecore.EObject; |
12 | import org.eclipse.emf.ecore.resource.Resource; | 13 | import org.eclipse.emf.ecore.resource.Resource; |
13 | import org.eclipse.emf.ecore.util.EcoreUtil; | 14 | import org.eclipse.emf.ecore.util.EcoreUtil; |
14 | import org.eclipse.viatra.solver.language.ProblemUtil; | ||
15 | import org.eclipse.viatra.solver.language.model.problem.Argument; | ||
16 | import org.eclipse.viatra.solver.language.model.problem.Atom; | ||
17 | import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; | 15 | import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; |
18 | import org.eclipse.viatra.solver.language.model.problem.Conjunction; | ||
19 | import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier; | ||
20 | import org.eclipse.viatra.solver.language.model.problem.ImplicitVariable; | ||
21 | import org.eclipse.viatra.solver.language.model.problem.Literal; | ||
22 | import org.eclipse.viatra.solver.language.model.problem.NegativeLiteral; | ||
23 | import org.eclipse.viatra.solver.language.model.problem.Node; | 16 | import org.eclipse.viatra.solver.language.model.problem.Node; |
24 | import org.eclipse.viatra.solver.language.model.problem.Parameter; | ||
25 | import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; | ||
26 | import org.eclipse.viatra.solver.language.model.problem.Problem; | 17 | import org.eclipse.viatra.solver.language.model.problem.Problem; |
27 | import org.eclipse.viatra.solver.language.model.problem.ProblemFactory; | 18 | import org.eclipse.viatra.solver.language.model.problem.ProblemFactory; |
28 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; | ||
29 | import org.eclipse.viatra.solver.language.model.problem.Statement; | 19 | import org.eclipse.viatra.solver.language.model.problem.Statement; |
30 | import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; | ||
31 | import org.eclipse.xtext.Constants; | 20 | import org.eclipse.xtext.Constants; |
32 | import org.eclipse.xtext.linking.impl.LinkingHelper; | ||
33 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | ||
34 | import org.eclipse.xtext.naming.QualifiedName; | ||
35 | import org.eclipse.xtext.nodemodel.INode; | ||
36 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; | ||
37 | import org.eclipse.xtext.resource.DerivedStateAwareResource; | 21 | import org.eclipse.xtext.resource.DerivedStateAwareResource; |
38 | import org.eclipse.xtext.resource.IDerivedStateComputer; | 22 | import org.eclipse.xtext.resource.IDerivedStateComputer; |
39 | import org.eclipse.xtext.resource.XtextResource; | 23 | import org.eclipse.xtext.resource.XtextResource; |
40 | import org.eclipse.xtext.scoping.IScope; | ||
41 | import org.eclipse.xtext.scoping.IScopeProvider; | 24 | import org.eclipse.xtext.scoping.IScopeProvider; |
42 | import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; | 25 | import org.eclipse.xtext.scoping.impl.AbstractDeclarativeScopeProvider; |
43 | 26 | ||
@@ -50,32 +33,25 @@ import com.google.inject.name.Named; | |||
50 | public class ProblemDerivedStateComputer implements IDerivedStateComputer { | 33 | public 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; | |||
6 | import org.eclipse.viatra.solver.language.model.problem.Node; | 6 | import org.eclipse.viatra.solver.language.model.problem.Node; |
7 | import org.eclipse.viatra.solver.language.model.problem.Problem; | 7 | import org.eclipse.viatra.solver.language.model.problem.Problem; |
8 | import org.eclipse.viatra.solver.language.model.problem.Variable; | 8 | import org.eclipse.viatra.solver.language.model.problem.Variable; |
9 | import org.eclipse.viatra.solver.language.naming.NamingUtil; | ||
9 | import org.eclipse.xtext.EcoreUtil2; | 10 | import org.eclipse.xtext.EcoreUtil2; |
10 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | 11 | import org.eclipse.xtext.naming.IQualifiedNameConverter; |
11 | import org.eclipse.xtext.naming.QualifiedName; | 12 | import 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 @@ | |||
4 | package org.eclipse.viatra.solver.language.scoping; | 4 | package org.eclipse.viatra.solver.language.scoping; |
5 | 5 | ||
6 | import java.util.ArrayList; | 6 | import java.util.ArrayList; |
7 | import java.util.Collection; | ||
8 | import java.util.List; | 7 | import java.util.List; |
9 | 8 | ||
10 | import org.eclipse.emf.ecore.EObject; | 9 | import org.eclipse.emf.ecore.EObject; |
@@ -16,7 +15,6 @@ import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; | |||
16 | import org.eclipse.viatra.solver.language.model.problem.Problem; | 15 | import org.eclipse.viatra.solver.language.model.problem.Problem; |
17 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; | 16 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; |
18 | import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; | 17 | import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; |
19 | import org.eclipse.viatra.solver.language.model.problem.Relation; | ||
20 | import org.eclipse.viatra.solver.language.model.problem.Variable; | 18 | import org.eclipse.viatra.solver.language.model.problem.Variable; |
21 | import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; | 19 | import org.eclipse.viatra.solver.language.model.problem.VariableOrNodeArgument; |
22 | import org.eclipse.xtext.EcoreUtil2; | 20 | import 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 | */ |
4 | package org.eclipse.viatra.solver.language.validation; | 4 | package 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 | */ |
12 | public class ProblemValidator extends AbstractProblemValidator { | 12 | public 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 | } |