diff options
27 files changed, 551 insertions, 498 deletions
diff --git a/build.gradle b/build.gradle index e1d31ecc..1736d644 100644 --- a/build.gradle +++ b/build.gradle | |||
@@ -12,35 +12,7 @@ plugins { | |||
12 | id 'com.moowork.node' version "1.3.1" apply false | 12 | id 'com.moowork.node' version "1.3.1" apply false |
13 | } | 13 | } |
14 | 14 | ||
15 | subprojects { | 15 | allprojects { |
16 | repositories { | ||
17 | mavenCentral() | ||
18 | } | ||
19 | |||
20 | apply plugin: 'java' | ||
21 | dependencies { | ||
22 | compile platform("org.eclipse.xtext:xtext-dev-bom:${xtextVersion}") | ||
23 | } | ||
24 | |||
25 | apply plugin: 'org.xtext.xtend' | ||
26 | apply from: "${rootDir}/gradle/source-layout.gradle" | ||
27 | apply plugin: 'eclipse' | ||
28 | |||
29 | group = 'org.eclipse.viatra.solver' | 16 | group = 'org.eclipse.viatra.solver' |
30 | version = '1.0.0-SNAPSHOT' | 17 | version = '1.0.0-SNAPSHOT' |
31 | |||
32 | sourceCompatibility = '11' | ||
33 | targetCompatibility = '11' | ||
34 | |||
35 | configurations.all { | ||
36 | exclude group: 'asm' | ||
37 | } | ||
38 | |||
39 | eclipse.classpath.file.whenMerged { | ||
40 | for (entry in entries) { | ||
41 | if (entry.path.endsWith('xtext-gen')) { | ||
42 | entry.entryAttributes['ignore_optional_problems'] = true | ||
43 | } | ||
44 | } | ||
45 | } | ||
46 | } | 18 | } |
diff --git a/gradle/java-common.gradle b/gradle/java-common.gradle new file mode 100644 index 00000000..0cc09a4f --- /dev/null +++ b/gradle/java-common.gradle | |||
@@ -0,0 +1,50 @@ | |||
1 | repositories { | ||
2 | mavenCentral() | ||
3 | } | ||
4 | |||
5 | apply plugin: 'java' | ||
6 | apply plugin: 'org.xtext.xtend' | ||
7 | |||
8 | sourceCompatibility = '11' | ||
9 | targetCompatibility = '11' | ||
10 | |||
11 | sourceSets { | ||
12 | main { | ||
13 | xtendOutputDir = 'src/main/xtend-gen' | ||
14 | } | ||
15 | test { | ||
16 | xtendOutputDir = 'src/test/xtend-gen' | ||
17 | } | ||
18 | } | ||
19 | |||
20 | configurations.all { | ||
21 | exclude group: 'asm' | ||
22 | } | ||
23 | |||
24 | jar { | ||
25 | manifest { | ||
26 | attributes 'Bundle-SymbolicName': project.name | ||
27 | } | ||
28 | } | ||
29 | |||
30 | clean.doLast { | ||
31 | delete 'src/main/xtend-gen' | ||
32 | delete 'src/test/xtend-gen' | ||
33 | } | ||
34 | |||
35 | apply plugin: 'eclipse' | ||
36 | |||
37 | eclipse { | ||
38 | classpath.file.whenMerged { | ||
39 | for (entry in entries) { | ||
40 | if (entry.path.endsWith('-gen')) { | ||
41 | entry.entryAttributes['ignore_optional_problems'] = true | ||
42 | } | ||
43 | } | ||
44 | } | ||
45 | |||
46 | jdt.file.whenMerged { properties -> | ||
47 | // Allow @SupperessWarnings to suppress SonalLint warnings | ||
48 | properties['org.eclipse.jdt.core.compiler.problem.unhandledWarningToken'] = 'ignore' | ||
49 | } | ||
50 | } | ||
diff --git a/gradle/mwe2.gradle b/gradle/mwe2.gradle new file mode 100644 index 00000000..5fd53126 --- /dev/null +++ b/gradle/mwe2.gradle | |||
@@ -0,0 +1,11 @@ | |||
1 | configurations { | ||
2 | mwe2 { | ||
3 | extendsFrom compile | ||
4 | } | ||
5 | } | ||
6 | |||
7 | dependencies { | ||
8 | mwe2 "org.eclipse.emf:org.eclipse.emf.mwe2.launch:${mwe2Version}" | ||
9 | } | ||
10 | |||
11 | eclipse.classpath.plusConfigurations += [configurations.mwe2] | ||
diff --git a/gradle/source-layout.gradle b/gradle/source-layout.gradle deleted file mode 100644 index 254798f1..00000000 --- a/gradle/source-layout.gradle +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | sourceSets { | ||
2 | main { | ||
3 | java.srcDirs = ['src/main/java', 'src/main/xtext-gen'] | ||
4 | resources.srcDirs = ['src/main/resources', 'src/main/xtext-gen'] | ||
5 | xtendOutputDir = 'src/main/xtend-gen' | ||
6 | } | ||
7 | test { | ||
8 | java.srcDirs = ['src/test/java', 'src/test/xtext-gen'] | ||
9 | resources.srcDirs = ['src/test/resources', 'src/test/xtext-gen'] | ||
10 | xtendOutputDir = 'src/test/xtend-gen' | ||
11 | } | ||
12 | } | ||
13 | |||
14 | jar { | ||
15 | from(sourceSets.main.allSource) { | ||
16 | include '**/*.xtext' | ||
17 | } | ||
18 | manifest { | ||
19 | attributes 'Bundle-SymbolicName': project.name | ||
20 | } | ||
21 | } | ||
22 | |||
23 | clean.doLast { | ||
24 | delete 'src/main/xtend-gen' | ||
25 | delete 'src/main/xtext-gen' | ||
26 | delete 'src/test/xtend-gen' | ||
27 | delete 'src/test/xtext-gen' | ||
28 | } | ||
diff --git a/gradle/xtext-common.gradle b/gradle/xtext-common.gradle new file mode 100644 index 00000000..cf6a5831 --- /dev/null +++ b/gradle/xtext-common.gradle | |||
@@ -0,0 +1,21 @@ | |||
1 | apply from: "${rootDir}/gradle/java-common.gradle" | ||
2 | |||
3 | dependencies { | ||
4 | compile platform("org.eclipse.xtext:xtext-dev-bom:${xtextVersion}") | ||
5 | } | ||
6 | |||
7 | sourceSets { | ||
8 | main { | ||
9 | java.srcDirs += ['src/main/xtext-gen'] | ||
10 | resources.srcDirs += ['src/main/xtext-gen'] | ||
11 | } | ||
12 | test { | ||
13 | java.srcDirs = ['src/test/xtext-gen'] | ||
14 | resources.srcDirs = ['src/test/xtext-gen'] | ||
15 | } | ||
16 | } | ||
17 | |||
18 | clean.doLast { | ||
19 | delete 'src/main/xtext-gen' | ||
20 | delete 'src/test/xtext-gen' | ||
21 | } | ||
diff --git a/language-ide/build.gradle b/language-ide/build.gradle index 396f63bd..1731cc59 100644 --- a/language-ide/build.gradle +++ b/language-ide/build.gradle | |||
@@ -1,3 +1,5 @@ | |||
1 | apply from: "${rootDir}/gradle/xtext-common.gradle" | ||
2 | |||
1 | dependencies { | 3 | dependencies { |
2 | compile project(':language') | 4 | compile project(':language') |
3 | compile "org.eclipse.xtext:org.eclipse.xtext.ide:${xtextVersion}" | 5 | compile "org.eclipse.xtext:org.eclipse.xtext.ide:${xtextVersion}" |
diff --git a/language-ide/src/main/java/org/eclipse/viatra/solver/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java b/language-ide/src/main/java/org/eclipse/viatra/solver/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java index eee5070b..b1a69e9d 100644 --- a/language-ide/src/main/java/org/eclipse/viatra/solver/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java +++ b/language-ide/src/main/java/org/eclipse/viatra/solver/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java | |||
@@ -3,26 +3,24 @@ package org.eclipse.viatra.solver.language.ide.syntaxcoloring; | |||
3 | import java.util.List; | 3 | import java.util.List; |
4 | 4 | ||
5 | import org.eclipse.emf.common.util.EList; | 5 | import org.eclipse.emf.common.util.EList; |
6 | import org.eclipse.emf.ecore.EAttribute; | ||
7 | import org.eclipse.emf.ecore.EObject; | 6 | import org.eclipse.emf.ecore.EObject; |
8 | import org.eclipse.emf.ecore.EReference; | 7 | import org.eclipse.emf.ecore.EReference; |
9 | import org.eclipse.emf.ecore.resource.Resource; | ||
10 | import org.eclipse.viatra.solver.language.ProblemUtil; | 8 | import org.eclipse.viatra.solver.language.ProblemUtil; |
11 | import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; | 9 | import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; |
12 | import org.eclipse.viatra.solver.language.model.problem.EnumDeclaration; | 10 | import org.eclipse.viatra.solver.language.model.problem.EnumDeclaration; |
11 | import org.eclipse.viatra.solver.language.model.problem.NamedElement; | ||
13 | import org.eclipse.viatra.solver.language.model.problem.Node; | 12 | import org.eclipse.viatra.solver.language.model.problem.Node; |
14 | import org.eclipse.viatra.solver.language.model.problem.Parameter; | 13 | import org.eclipse.viatra.solver.language.model.problem.Parameter; |
15 | import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; | 14 | import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; |
15 | 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.Variable; | 17 | import org.eclipse.viatra.solver.language.model.problem.Variable; |
18 | import org.eclipse.viatra.solver.language.scoping.ProblemGlobalScopeProvider; | ||
19 | import org.eclipse.xtext.ide.editor.syntaxcoloring.DefaultSemanticHighlightingCalculator; | 18 | import org.eclipse.xtext.ide.editor.syntaxcoloring.DefaultSemanticHighlightingCalculator; |
20 | import org.eclipse.xtext.ide.editor.syntaxcoloring.IHighlightedPositionAcceptor; | 19 | import org.eclipse.xtext.ide.editor.syntaxcoloring.IHighlightedPositionAcceptor; |
21 | import org.eclipse.xtext.nodemodel.INode; | 20 | import org.eclipse.xtext.nodemodel.INode; |
22 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; | 21 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; |
23 | import org.eclipse.xtext.service.OperationCanceledManager; | 22 | import org.eclipse.xtext.service.OperationCanceledManager; |
24 | import org.eclipse.xtext.util.CancelIndicator; | 23 | import org.eclipse.xtext.util.CancelIndicator; |
25 | import org.eclipse.xtext.util.SimpleAttributeResolver; | ||
26 | 24 | ||
27 | import com.google.common.collect.ImmutableList; | 25 | import com.google.common.collect.ImmutableList; |
28 | import com.google.inject.Inject; | 26 | import com.google.inject.Inject; |
@@ -49,19 +47,18 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
49 | @Override | 47 | @Override |
50 | protected boolean highlightElement(EObject object, IHighlightedPositionAcceptor acceptor, | 48 | protected boolean highlightElement(EObject object, IHighlightedPositionAcceptor acceptor, |
51 | CancelIndicator cancelIndicator) { | 49 | CancelIndicator cancelIndicator) { |
52 | highlightName(object, acceptor, cancelIndicator); | 50 | highlightName(object, acceptor); |
53 | highlightCrossReferences(object, acceptor, cancelIndicator); | 51 | highlightCrossReferences(object, acceptor, cancelIndicator); |
54 | return false; | 52 | return false; |
55 | } | 53 | } |
56 | 54 | ||
57 | protected void highlightName(EObject object, IHighlightedPositionAcceptor acceptor, | 55 | protected void highlightName(EObject object, IHighlightedPositionAcceptor acceptor) { |
58 | CancelIndicator cancelIndicator) { | 56 | if (!(object instanceof NamedElement)) { |
57 | return; | ||
58 | } | ||
59 | String[] highlightClass = getHighlightClass(object); | 59 | String[] highlightClass = getHighlightClass(object); |
60 | if (highlightClass.length > 0) { | 60 | if (highlightClass.length > 0) { |
61 | EAttribute nameAttribute = SimpleAttributeResolver.NAME_RESOLVER.getAttribute(object); | 61 | highlightFeature(acceptor, object, ProblemPackage.Literals.NAMED_ELEMENT__NAME, highlightClass); |
62 | if (nameAttribute != null) { | ||
63 | highlightFeature(acceptor, object, nameAttribute, highlightClass); | ||
64 | } | ||
65 | } | 62 | } |
66 | } | 63 | } |
67 | 64 | ||
@@ -73,36 +70,44 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
73 | } | 70 | } |
74 | operationCanceledManager.checkCanceled(cancelIndicator); | 71 | operationCanceledManager.checkCanceled(cancelIndicator); |
75 | if (reference.isMany()) { | 72 | if (reference.isMany()) { |
76 | @SuppressWarnings("unchecked") | 73 | highlightManyValues(object, reference, acceptor); |
77 | EList<? extends EObject> values = (EList<? extends EObject>) object.eGet(reference); | ||
78 | List<INode> nodes = NodeModelUtils.findNodesForFeature(object, reference); | ||
79 | int size = Math.min(values.size(), nodes.size()); | ||
80 | for (int i = 0; i < size; i++) { | ||
81 | EObject valueInList = values.get(i); | ||
82 | INode node = nodes.get(i); | ||
83 | String[] highlightClass = getHighlightClass(valueInList); | ||
84 | if (highlightClass.length > 0) { | ||
85 | highlightNode(acceptor, node, highlightClass); | ||
86 | } | ||
87 | } | ||
88 | } else { | 74 | } else { |
89 | EObject valueObj = (EObject) object.eGet(reference); | 75 | highlightSingleValue(object, reference, acceptor); |
90 | String[] highlightClass = getHighlightClass(valueObj); | 76 | } |
91 | if (highlightClass.length > 0) { | 77 | } |
92 | highlightFeature(acceptor, object, reference, highlightClass); | 78 | } |
93 | } | 79 | |
80 | protected void highlightSingleValue(EObject object, EReference reference, IHighlightedPositionAcceptor acceptor) { | ||
81 | EObject valueObj = (EObject) object.eGet(reference); | ||
82 | String[] highlightClass = getHighlightClass(valueObj); | ||
83 | if (highlightClass.length > 0) { | ||
84 | highlightFeature(acceptor, object, reference, highlightClass); | ||
85 | } | ||
86 | } | ||
87 | |||
88 | protected void highlightManyValues(EObject object, EReference reference, IHighlightedPositionAcceptor acceptor) { | ||
89 | @SuppressWarnings("unchecked") | ||
90 | EList<? extends EObject> values = (EList<? extends EObject>) object.eGet(reference); | ||
91 | List<INode> nodes = NodeModelUtils.findNodesForFeature(object, reference); | ||
92 | int size = Math.min(values.size(), nodes.size()); | ||
93 | for (var i = 0; i < size; i++) { | ||
94 | EObject valueInList = values.get(i); | ||
95 | INode node = nodes.get(i); | ||
96 | String[] highlightClass = getHighlightClass(valueInList); | ||
97 | if (highlightClass.length > 0) { | ||
98 | highlightNode(acceptor, node, highlightClass); | ||
94 | } | 99 | } |
95 | } | 100 | } |
96 | } | 101 | } |
97 | 102 | ||
98 | protected String[] getHighlightClass(EObject eObject) { | 103 | protected String[] getHighlightClass(EObject eObject) { |
99 | if (isBuiltIn(eObject)) { | 104 | if (ProblemUtil.isBuiltIn(eObject)) { |
100 | return new String[] { BUILTIN_CLASS }; | 105 | return new String[] { BUILTIN_CLASS }; |
101 | } | 106 | } |
102 | ImmutableList.Builder<String> classesBuilder = ImmutableList.builder(); | 107 | ImmutableList.Builder<String> classesBuilder = ImmutableList.builder(); |
103 | if (eObject instanceof ClassDeclaration) { | 108 | if (eObject instanceof ClassDeclaration) { |
104 | classesBuilder.add(CLASS_CLASS); | 109 | classesBuilder.add(CLASS_CLASS); |
105 | ClassDeclaration classDeclaration = (ClassDeclaration) eObject; | 110 | var classDeclaration = (ClassDeclaration) eObject; |
106 | if (classDeclaration.isAbstract()) { | 111 | if (classDeclaration.isAbstract()) { |
107 | classesBuilder.add(ABSTRACT_CLASS); | 112 | classesBuilder.add(ABSTRACT_CLASS); |
108 | } | 113 | } |
@@ -112,21 +117,21 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
112 | } | 117 | } |
113 | if (eObject instanceof ReferenceDeclaration) { | 118 | if (eObject instanceof ReferenceDeclaration) { |
114 | classesBuilder.add(REFERENCE_CLASS); | 119 | classesBuilder.add(REFERENCE_CLASS); |
115 | ReferenceDeclaration referenceDeclaration = (ReferenceDeclaration) eObject; | 120 | var referenceDeclaration = (ReferenceDeclaration) eObject; |
116 | if (referenceDeclaration.isContainment()) { | 121 | if (referenceDeclaration.isContainment()) { |
117 | classesBuilder.add(CONTAINMENT_CLASS); | 122 | classesBuilder.add(CONTAINMENT_CLASS); |
118 | } | 123 | } |
119 | } | 124 | } |
120 | if (eObject instanceof PredicateDefinition) { | 125 | if (eObject instanceof PredicateDefinition) { |
121 | classesBuilder.add(PREDICATE_CLASS); | 126 | classesBuilder.add(PREDICATE_CLASS); |
122 | PredicateDefinition predicateDefinition = (PredicateDefinition) eObject; | 127 | var predicateDefinition = (PredicateDefinition) eObject; |
123 | if (predicateDefinition.isError()) { | 128 | if (predicateDefinition.isError()) { |
124 | classesBuilder.add(ERROR_CLASS); | 129 | classesBuilder.add(ERROR_CLASS); |
125 | } | 130 | } |
126 | } | 131 | } |
127 | if (eObject instanceof Node) { | 132 | if (eObject instanceof Node) { |
128 | classesBuilder.add(NODE_CLASS); | 133 | classesBuilder.add(NODE_CLASS); |
129 | Node node = (Node) eObject; | 134 | var node = (Node) eObject; |
130 | if (ProblemUtil.isEnumNode(node)) { | 135 | if (ProblemUtil.isEnumNode(node)) { |
131 | classesBuilder.add(ENUM_NODE_CLASS); | 136 | classesBuilder.add(ENUM_NODE_CLASS); |
132 | } | 137 | } |
@@ -139,7 +144,7 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
139 | } | 144 | } |
140 | if (eObject instanceof Variable) { | 145 | if (eObject instanceof Variable) { |
141 | classesBuilder.add(VARIABLE_CLASS); | 146 | classesBuilder.add(VARIABLE_CLASS); |
142 | Variable variable = (Variable) eObject; | 147 | var variable = (Variable) eObject; |
143 | if (ProblemUtil.isSingletonVariable(variable)) { | 148 | if (ProblemUtil.isSingletonVariable(variable)) { |
144 | classesBuilder.add(SINGLETON_VARIABLE_CLASS); | 149 | classesBuilder.add(SINGLETON_VARIABLE_CLASS); |
145 | } | 150 | } |
@@ -147,14 +152,4 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
147 | List<String> classes = classesBuilder.build(); | 152 | List<String> classes = classesBuilder.build(); |
148 | return classes.toArray(new String[0]); | 153 | return classes.toArray(new String[0]); |
149 | } | 154 | } |
150 | |||
151 | protected boolean isBuiltIn(EObject eObject) { | ||
152 | if (eObject != null) { | ||
153 | Resource eResource = eObject.eResource(); | ||
154 | if (eResource != null) { | ||
155 | return ProblemGlobalScopeProvider.BULTIN_LIBRARY_URI.equals(eResource.getURI()); | ||
156 | } | ||
157 | } | ||
158 | return false; | ||
159 | } | ||
160 | } | 155 | } |
diff --git a/language-model/build.gradle b/language-model/build.gradle index 56ab4a19..2d9b54b9 100644 --- a/language-model/build.gradle +++ b/language-model/build.gradle | |||
@@ -1,14 +1,10 @@ | |||
1 | configurations { | 1 | apply from: "${rootDir}/gradle/java-common.gradle" |
2 | mwe2 { | 2 | apply from: "${rootDir}/gradle/mwe2.gradle" |
3 | extendsFrom compile | ||
4 | } | ||
5 | } | ||
6 | 3 | ||
7 | dependencies { | 4 | dependencies { |
8 | compile "org.eclipse.emf:org.eclipse.emf.ecore:${ecoreVersion}" | 5 | compile "org.eclipse.emf:org.eclipse.emf.ecore:${ecoreVersion}" |
9 | mwe2 "org.eclipse.emf:org.eclipse.emf.codegen.ecore:${ecoreCodegenVersion}" | 6 | mwe2 "org.eclipse.emf:org.eclipse.emf.codegen.ecore:${ecoreCodegenVersion}" |
10 | mwe2 "org.eclipse.emf:org.eclipse.emf.mwe.utils:${mweVersion}" | 7 | mwe2 "org.eclipse.emf:org.eclipse.emf.mwe.utils:${mweVersion}" |
11 | mwe2 "org.eclipse.emf:org.eclipse.emf.mwe2.launch:${mwe2Version}" | ||
12 | mwe2 "org.eclipse.emf:org.eclipse.emf.mwe2.lib:${mwe2Version}" | 8 | mwe2 "org.eclipse.emf:org.eclipse.emf.mwe2.lib:${mwe2Version}" |
13 | mwe2 "org.eclipse.xtext:org.eclipse.xtext:${xtextVersion}" | 9 | mwe2 "org.eclipse.xtext:org.eclipse.xtext:${xtextVersion}" |
14 | mwe2 "org.eclipse.xtext:org.eclipse.xtext.xbase:${xtextVersion}" | 10 | mwe2 "org.eclipse.xtext:org.eclipse.xtext.xbase:${xtextVersion}" |
@@ -35,12 +31,4 @@ task generateEPackage(type: JavaExec) { | |||
35 | compileJava.dependsOn(generateEPackage) | 31 | compileJava.dependsOn(generateEPackage) |
36 | clean.dependsOn(cleanGenerateEPackage) | 32 | clean.dependsOn(cleanGenerateEPackage) |
37 | 33 | ||
38 | eclipse { | 34 | eclipse.project.natures += ['org.eclipse.sirius.nature.modelingproject', 'org.eclipse.pde.PluginNature'] |
39 | project { | ||
40 | natures += ['org.eclipse.sirius.nature.modelingproject', 'org.eclipse.pde.PluginNature'] | ||
41 | } | ||
42 | |||
43 | classpath { | ||
44 | plusConfigurations += [configurations.mwe2] | ||
45 | } | ||
46 | } \ No newline at end of file | ||
diff --git a/language-mwe2/build.gradle b/language-mwe2/build.gradle index 8596b4c1..ae456c39 100644 --- a/language-mwe2/build.gradle +++ b/language-mwe2/build.gradle | |||
@@ -1,3 +1,5 @@ | |||
1 | apply from: "${rootDir}/gradle/java-common.gradle" | ||
2 | |||
1 | dependencies { | 3 | dependencies { |
2 | compile "org.eclipse.xtext:org.eclipse.xtext.xtext.generator:${xtextVersion}" | 4 | compile "org.eclipse.xtext:org.eclipse.xtext.xtext.generator:${xtextVersion}" |
3 | } | 5 | } |
diff --git a/language-mwe2/src/main/java/org/eclipse/viatra/solver/language/mwe2/ProblemWebIntegrationFragment.java b/language-mwe2/src/main/java/org/eclipse/viatra/solver/language/mwe2/ProblemWebIntegrationFragment.java index 83b56bc6..78311e0d 100644 --- a/language-mwe2/src/main/java/org/eclipse/viatra/solver/language/mwe2/ProblemWebIntegrationFragment.java +++ b/language-mwe2/src/main/java/org/eclipse/viatra/solver/language/mwe2/ProblemWebIntegrationFragment.java | |||
@@ -7,6 +7,10 @@ import org.eclipse.xtext.xtext.generator.web.WebIntegrationFragment; | |||
7 | import com.google.common.collect.Multimap; | 7 | import com.google.common.collect.Multimap; |
8 | 8 | ||
9 | public class ProblemWebIntegrationFragment extends WebIntegrationFragment { | 9 | public class ProblemWebIntegrationFragment extends WebIntegrationFragment { |
10 | private static final String START_STATE = "start"; | ||
11 | private static final String PREDICATE_BODY_STATE = "predicateBody"; | ||
12 | private static final String CM_MODE_META = "meta"; | ||
13 | |||
10 | public ProblemWebIntegrationFragment() { | 14 | public ProblemWebIntegrationFragment() { |
11 | setFramework(Framework.CODEMIRROR.name()); | 15 | setFramework(Framework.CODEMIRROR.name()); |
12 | // We use our custom token style for single-quoted names | 16 | // We use our custom token style for single-quoted names |
@@ -36,25 +40,27 @@ public class ProblemWebIntegrationFragment extends WebIntegrationFragment { | |||
36 | protected Multimap<String, String> createCodeMirrorPatterns(String langId, Set<String> keywords) { | 40 | protected Multimap<String, String> createCodeMirrorPatterns(String langId, Set<String> keywords) { |
37 | Multimap<String, String> patterns = super.createCodeMirrorPatterns(langId, keywords); | 41 | Multimap<String, String> patterns = super.createCodeMirrorPatterns(langId, keywords); |
38 | // We use our custom token style for single-quoted names | 42 | // We use our custom token style for single-quoted names |
39 | patterns.put("start", "{token: \"quoted-name\", regex: \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"}"); | 43 | patterns.put(START_STATE, "{token: \"quoted-name\", regex: \"['](?:(?:\\\\\\\\.)|(?:[^'\\\\\\\\]))*?[']\"}"); |
40 | // Use the CodeMirror default .cm-number instead of .cm-constant.cm-numeric | 44 | // Use the CodeMirror default .cm-number instead of .cm-constant.cm-numeric |
41 | patterns.put("start", | 45 | patterns.put(START_STATE, |
42 | "{token: \"number\", regex: \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"}"); | 46 | "{token: \"number\", regex: \"[+-]?\\\\d+(?:(?:\\\\.\\\\d*)?(?:[eE][+-]?\\\\d+)?)?\\\\b\"}"); |
43 | patterns.put("start", "{token: \"number\", regex: \"[*]\"}"); | 47 | patterns.put(START_STATE, "{token: \"number\", regex: \"[*]\"}"); |
44 | // We use our own custom single-line comments | 48 | // We use our own custom single-line comments |
45 | patterns.put("start", "{token: \"comment\", regex: \"%.*$\"}"); | 49 | patterns.put(START_STATE, "{token: \"comment\", regex: \"%.*$\"}"); |
46 | patterns.put("start", "{token: \"comment\", regex: \"\\\\/\\\\/.*$\"}"); | 50 | patterns.put(START_STATE, "{token: \"comment\", regex: \"\\\\/\\\\/.*$\"}"); |
47 | patterns.put("meta", "lineComment: \"%\""); | 51 | patterns.put(CM_MODE_META, "lineComment: \"%\""); |
48 | // Override indentation behavior | 52 | // Override indentation behavior |
49 | patterns.put("start", "{token: \"lparen\", indent: true, regex: \"[[({]\"}"); | 53 | patterns.put(START_STATE, "{token: \"lparen\", indent: true, regex: \"[[({]\"}"); |
50 | patterns.put("start", "{token: \"rparen\", dedent: true, regex: \"[\\\\])}]\"}"); | 54 | patterns.put(START_STATE, "{token: \"rparen\", dedent: true, regex: \"[\\\\])}]\"}"); |
51 | patterns.putAll("predicateBody", patterns.get("start")); | 55 | patterns.putAll(PREDICATE_BODY_STATE, patterns.get(START_STATE)); |
52 | patterns.put("start", "{indent: true, push: \"predicateBody\", regex: \"<=>\"}"); | 56 | patterns.put(START_STATE, "{indent: true, push: \"" + PREDICATE_BODY_STATE + "\", regex: \"<=>\"}"); |
53 | patterns.put("predicateBody", "{dedent: true, dedentIfLineStart: false, pop: true, regex: \"\\\\.\\\\s*$\"}"); | 57 | patterns.put(PREDICATE_BODY_STATE, |
54 | patterns.put("predicateBody", "{indent: true, dedent: true, regex: \"[;]\"}"); | 58 | "{dedent: true, dedentIfLineStart: false, pop: true, regex: \"\\\\.\\\\s*$\"}"); |
55 | // We must repeat the keyword rule here, because Xtext only adds it to "main" later. | 59 | patterns.put(PREDICATE_BODY_STATE, "{indent: true, dedent: true, regex: \"[;]\"}"); |
56 | patterns.put("predicateBody", "{token: \"keyword\", regex: \"\\\\b(?:\" + keywords + \")\\\\b\"}"); | 60 | // We must repeat the keyword rule here, because Xtext only adds it to "main" |
57 | patterns.put("meta", "electricChars: \"])];\""); | 61 | // later |
62 | patterns.put(PREDICATE_BODY_STATE, "{token: \"keyword\", regex: \"\\\\b(?:\" + keywords + \")\\\\b\"}"); | ||
63 | patterns.put(CM_MODE_META, "electricChars: \"])];\""); | ||
58 | return patterns; | 64 | return patterns; |
59 | } | 65 | } |
60 | } | 66 | } |
diff --git a/language-web/build.gradle b/language-web/build.gradle index e04af7cb..e00b88d8 100644 --- a/language-web/build.gradle +++ b/language-web/build.gradle | |||
@@ -1,3 +1,5 @@ | |||
1 | apply from: "${rootDir}/gradle/xtext-common.gradle" | ||
2 | |||
1 | dependencies { | 3 | dependencies { |
2 | compile project(':language') | 4 | compile project(':language') |
3 | compile project(':language-ide') | 5 | compile project(':language-ide') |
@@ -94,9 +96,7 @@ task webpackServe(type: NpmTask) { | |||
94 | } | 96 | } |
95 | 97 | ||
96 | eclipse { | 98 | eclipse { |
97 | project { | 99 | project.file.whenMerged { |
98 | file.whenMerged { | 100 | natures.remove('org.eclipse.wst.common.modulecore.ModuleCoreNature') |
99 | natures.remove('org.eclipse.wst.common.modulecore.ModuleCoreNature') | ||
100 | } | ||
101 | } | 101 | } |
102 | } | 102 | } |
diff --git a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ProblemServlet.java b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ProblemServlet.java index 5de708f0..337df54b 100644 --- a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ProblemServlet.java +++ b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ProblemServlet.java | |||
@@ -3,9 +3,9 @@ | |||
3 | */ | 3 | */ |
4 | package org.eclipse.viatra.solver.language.web; | 4 | package org.eclipse.viatra.solver.language.web; |
5 | 5 | ||
6 | import com.google.inject.Injector; | ||
7 | import javax.servlet.ServletException; | 6 | import javax.servlet.ServletException; |
8 | import javax.servlet.annotation.WebServlet; | 7 | import javax.servlet.annotation.WebServlet; |
8 | |||
9 | import org.eclipse.xtext.util.DisposableRegistry; | 9 | import org.eclipse.xtext.util.DisposableRegistry; |
10 | import org.eclipse.xtext.web.servlet.XtextServlet; | 10 | import org.eclipse.xtext.web.servlet.XtextServlet; |
11 | 11 | ||
@@ -17,14 +17,18 @@ public class ProblemServlet extends XtextServlet { | |||
17 | 17 | ||
18 | private static final long serialVersionUID = 1L; | 18 | private static final long serialVersionUID = 1L; |
19 | 19 | ||
20 | DisposableRegistry disposableRegistry; | 20 | // Xtext requires a mutable servlet instance field. |
21 | @SuppressWarnings("squid:S2226") | ||
22 | private DisposableRegistry disposableRegistry; | ||
21 | 23 | ||
24 | @Override | ||
22 | public void init() throws ServletException { | 25 | public void init() throws ServletException { |
23 | super.init(); | 26 | super.init(); |
24 | Injector injector = new ProblemWebSetup().createInjectorAndDoEMFRegistration(); | 27 | var injector = new ProblemWebSetup().createInjectorAndDoEMFRegistration(); |
25 | this.disposableRegistry = injector.getInstance(DisposableRegistry.class); | 28 | this.disposableRegistry = injector.getInstance(DisposableRegistry.class); |
26 | } | 29 | } |
27 | 30 | ||
31 | @Override | ||
28 | public void destroy() { | 32 | public void destroy() { |
29 | if (disposableRegistry != null) { | 33 | if (disposableRegistry != null) { |
30 | disposableRegistry.dispose(); | 34 | disposableRegistry.dispose(); |
diff --git a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java index efa6b034..2c0413df 100644 --- a/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java +++ b/language-web/src/main/java/org/eclipse/viatra/solver/language/web/ServerLauncher.java | |||
@@ -7,7 +7,6 @@ import java.io.IOException; | |||
7 | import java.net.InetSocketAddress; | 7 | import java.net.InetSocketAddress; |
8 | import java.net.URI; | 8 | import java.net.URI; |
9 | import java.net.URISyntaxException; | 9 | import java.net.URISyntaxException; |
10 | import java.net.URL; | ||
11 | 10 | ||
12 | import org.eclipse.jetty.annotations.AnnotationConfiguration; | 11 | import org.eclipse.jetty.annotations.AnnotationConfiguration; |
13 | import org.eclipse.jetty.server.Server; | 12 | import org.eclipse.jetty.server.Server; |
@@ -24,9 +23,9 @@ public class ServerLauncher { | |||
24 | 23 | ||
25 | private final Server server; | 24 | private final Server server; |
26 | 25 | ||
27 | public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource) throws IOException, URISyntaxException { | 26 | public ServerLauncher(InetSocketAddress bindAddress, Resource baseResource) { |
28 | server = new Server(bindAddress); | 27 | server = new Server(bindAddress); |
29 | WebAppContext ctx = new WebAppContext(); | 28 | var ctx = new WebAppContext(); |
30 | ctx.setBaseResource(baseResource); | 29 | ctx.setBaseResource(baseResource); |
31 | ctx.setWelcomeFiles(new String[] { "index.html" }); | 30 | ctx.setWelcomeFiles(new String[] { "index.html" }); |
32 | ctx.setContextPath("/"); | 31 | ctx.setContextPath("/"); |
@@ -40,27 +39,13 @@ public class ServerLauncher { | |||
40 | public void start() throws Exception { | 39 | public void start() throws Exception { |
41 | server.start(); | 40 | server.start(); |
42 | LOG.info("Server started " + server.getURI() + "..."); | 41 | LOG.info("Server started " + server.getURI() + "..."); |
43 | new Thread() { | 42 | LOG.info("Press enter to stop the server..."); |
44 | public void run() { | 43 | int key = System.in.read(); |
45 | try { | 44 | if (key != -1) { |
46 | LOG.info("Press enter to stop the server..."); | 45 | server.stop(); |
47 | int key = System.in.read(); | 46 | } else { |
48 | if (key != -1) { | 47 | LOG.warn( |
49 | server.stop(); | 48 | "Console input is not available. In order to stop the server, you need to cancel process manually."); |
50 | } else { | ||
51 | LOG.warn( | ||
52 | "Console input is not available. In order to stop the server, you need to cancel process manually."); | ||
53 | } | ||
54 | } catch (Exception e) { | ||
55 | LOG.warn(e); | ||
56 | System.exit(-1); | ||
57 | } | ||
58 | } | ||
59 | }.start(); | ||
60 | try { | ||
61 | server.join(); | ||
62 | } catch (InterruptedException e) { | ||
63 | LOG.info(e); | ||
64 | } | 49 | } |
65 | } | 50 | } |
66 | 51 | ||
@@ -75,34 +60,34 @@ public class ServerLauncher { | |||
75 | if (baseResourceOverride != null) { | 60 | if (baseResourceOverride != null) { |
76 | return Resource.newResource(baseResourceOverride); | 61 | return Resource.newResource(baseResourceOverride); |
77 | } | 62 | } |
78 | URL indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); | 63 | var indexUrlInJar = ServerLauncher.class.getResource("/webapp/index.html"); |
79 | if (indexUrlInJar == null) { | 64 | if (indexUrlInJar == null) { |
80 | throw new RuntimeException("Cannot find pacakged web assets"); | 65 | throw new IOException("Cannot find pacakged web assets"); |
81 | } | 66 | } |
82 | URI webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); | 67 | var webRootUri = URI.create(indexUrlInJar.toURI().toASCIIString().replaceFirst("/index.html$", "/")); |
83 | return Resource.newResource(webRootUri); | 68 | return Resource.newResource(webRootUri); |
84 | } | 69 | } |
85 | 70 | ||
86 | public static void main(String[] args) { | 71 | public static void main(String[] args) { |
87 | String listenAddress = System.getenv("LISTEN_ADDRESS"); | 72 | var listenAddress = System.getenv("LISTEN_ADDRESS"); |
88 | if (listenAddress == null) { | 73 | if (listenAddress == null) { |
89 | listenAddress = "localhost"; | 74 | listenAddress = "localhost"; |
90 | } | 75 | } |
91 | int port = 1312; | 76 | var port = 1312; |
92 | String portStr = System.getenv("LISTEN_PORT"); | 77 | var portStr = System.getenv("LISTEN_PORT"); |
93 | if (portStr != null) { | 78 | if (portStr != null) { |
94 | try { | 79 | try { |
95 | port = Integer.parseInt(portStr); | 80 | port = Integer.parseInt(portStr); |
96 | } catch (NumberFormatException e) { | 81 | } catch (NumberFormatException e) { |
97 | LOG.warn(e); | 82 | LOG.warn(e); |
98 | System.exit(-1); | 83 | System.exit(1); |
99 | } | 84 | } |
100 | } | 85 | } |
101 | String baseResourceOverride = System.getenv("BASE_RESOURCE"); | 86 | var baseResourceOverride = System.getenv("BASE_RESOURCE"); |
102 | try { | 87 | try { |
103 | InetSocketAddress bindAddress = getBindAddress(listenAddress, port); | 88 | var bindAddress = getBindAddress(listenAddress, port); |
104 | Resource baseResource = getBaseResource(baseResourceOverride); | 89 | var baseResource = getBaseResource(baseResourceOverride); |
105 | ServerLauncher serverLauncher = new ServerLauncher(bindAddress, baseResource); | 90 | var serverLauncher = new ServerLauncher(bindAddress, baseResource); |
106 | serverLauncher.start(); | 91 | serverLauncher.start(); |
107 | } catch (Exception exception) { | 92 | } catch (Exception exception) { |
108 | LOG.warn(exception); | 93 | LOG.warn(exception); |
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 @@ | |||
1 | configurations { | 1 | apply from: "${rootDir}/gradle/xtext-common.gradle" |
2 | mwe2 { | 2 | apply from: "${rootDir}/gradle/mwe2.gradle" |
3 | extendsFrom compile | ||
4 | } | ||
5 | } | ||
6 | 3 | ||
7 | dependencies { | 4 | dependencies { |
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 | ||
21 | jar { | ||
22 | from(sourceSets.main.allSource) { | ||
23 | include '**/*.xtext' | ||
24 | } | ||
25 | } | ||
26 | |||
25 | task generateXtextLanguage(type: JavaExec) { | 27 | task 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 | ||
44 | generateXtext.dependsOn(generateXtextLanguage) | 46 | generateXtext.dependsOn(generateXtextLanguage) |
45 | clean.dependsOn(cleanGenerateXtextLanguage) | 47 | clean.dependsOn(cleanGenerateXtextLanguage) |
46 | |||
47 | eclipse.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; | |||
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 | } |