diff options
author | Kristóf Marussy <marussy@mit.bme.hu> | 2021-06-28 02:45:33 +0200 |
---|---|---|
committer | Kristóf Marussy <marussy@mit.bme.hu> | 2021-06-28 02:47:34 +0200 |
commit | b7db563dc425dbf90e42b1c69fb4d52c41a18503 (patch) | |
tree | 99bf06a66e6d63b9afda017f6f23266cac46def2 /language/src/main/java/org | |
parent | Add data constant support (diff) | |
download | refinery-b7db563dc425dbf90e42b1c69fb4d52c41a18503.tar.gz refinery-b7db563dc425dbf90e42b1c69fb4d52c41a18503.tar.zst refinery-b7db563dc425dbf90e42b1c69fb4d52c41a18503.zip |
Add scoping tests and simplify implicit nodes
* Do not export implicit nodes to the global scope
* Enum literals must not be quoted
* Plan for the future: unify quoted nodes from the global scope in
post-processing
Diffstat (limited to 'language/src/main/java/org')
7 files changed, 122 insertions, 92 deletions
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2 b/language/src/main/java/org/eclipse/viatra/solver/language/GenerateProblem.mwe2 index a63681c8..da5e95a4 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 | |||
@@ -43,9 +43,7 @@ Workflow { | |||
43 | validator = { | 43 | validator = { |
44 | generateDeprecationValidation = true | 44 | generateDeprecationValidation = true |
45 | } | 45 | } |
46 | generator = { | 46 | generator = null |
47 | generateXtendStub = true | ||
48 | } | ||
49 | junitSupport = { | 47 | junitSupport = { |
50 | junitVersion = "5" | 48 | junitVersion = "5" |
51 | } | 49 | } |
diff --git a/language/src/main/java/org/eclipse/viatra/solver/language/Problem.xtext b/language/src/main/java/org/eclipse/viatra/solver/language/Problem.xtext index 7e253ef5..495f50e4 100644 --- a/language/src/main/java/org/eclipse/viatra/solver/language/Problem.xtext +++ b/language/src/main/java/org/eclipse/viatra/solver/language/Problem.xtext | |||
@@ -22,7 +22,7 @@ EnumDeclaration: | |||
22 | ("{" (literals+=EnumLiteral ("," literals+=EnumLiteral)* ("," | ";")?)? "}" | "."); | 22 | ("{" (literals+=EnumLiteral ("," literals+=EnumLiteral)* ("," | ";")?)? "}" | "."); |
23 | 23 | ||
24 | EnumLiteral returns Node: | 24 | EnumLiteral returns Node: |
25 | name=QuotedOrUnquotedId; | 25 | name=Identifier; |
26 | 26 | ||
27 | ReferenceDeclaration: | 27 | ReferenceDeclaration: |
28 | (containment?="contains" | "refers")? | 28 | (containment?="contains" | "refers")? |
@@ -129,11 +129,8 @@ ExactMultiplicity: | |||
129 | UpperBound returns ecore::EInt: | 129 | UpperBound returns ecore::EInt: |
130 | INT | "*"; | 130 | INT | "*"; |
131 | 131 | ||
132 | QuotedOrUnquotedId: | ||
133 | QUOTED_ID | Identifier; | ||
134 | |||
135 | QualifiedName hidden(): | 132 | QualifiedName hidden(): |
136 | QUOTED_ID | Identifier ("::" Identifier)* ("::" QUOTED_ID)?; | 133 | QUOTED_ID | Identifier ("::" Identifier)*; |
137 | 134 | ||
138 | Identifier: | 135 | Identifier: |
139 | ID | "true" | "false" | "e" | "E"; | 136 | ID | "true" | "false" | "e" | "E"; |
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 new file mode 100644 index 00000000..b6ea3553 --- /dev/null +++ b/language/src/main/java/org/eclipse/viatra/solver/language/generator/ProblemGenerator.java | |||
@@ -0,0 +1,30 @@ | |||
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/generator/ProblemGenerator.xtend b/language/src/main/java/org/eclipse/viatra/solver/language/generator/ProblemGenerator.xtend deleted file mode 100644 index 0930f244..00000000 --- a/language/src/main/java/org/eclipse/viatra/solver/language/generator/ProblemGenerator.xtend +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | /* | ||
2 | * generated by Xtext 2.25.0 | ||
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 | class ProblemGenerator extends AbstractGenerator { | ||
17 | |||
18 | override void doGenerate(Resource resource, IFileSystemAccess2 fsa, IGeneratorContext context) { | ||
19 | // fsa.generateFile('greetings.txt', 'People to greet: ' + | ||
20 | // resource.allContents | ||
21 | // .filter(Greeting) | ||
22 | // .map[name] | ||
23 | // .join(', ')) | ||
24 | } | ||
25 | } | ||
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 fc03fa87..56d8ad71 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 | |||
@@ -73,13 +73,14 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer { | |||
73 | 73 | ||
74 | protected void installDerivedProblemState(Problem problem, boolean preLinkingPhase) { | 74 | protected void installDerivedProblemState(Problem problem, boolean preLinkingPhase) { |
75 | installNewNodes(problem); | 75 | installNewNodes(problem); |
76 | if (!preLinkingPhase) { | 76 | if (preLinkingPhase) { |
77 | installDerivedNodes(problem); | 77 | return; |
78 | for (Statement statement : problem.getStatements()) { | 78 | } |
79 | if (statement instanceof PredicateDefinition) { | 79 | Set<String> nodeNames = installDerivedNodes(problem); |
80 | PredicateDefinition definition = (PredicateDefinition) statement; | 80 | for (Statement statement : problem.getStatements()) { |
81 | installDerivedPredicateDefinitionState(definition); | 81 | if (statement instanceof PredicateDefinition) { |
82 | } | 82 | PredicateDefinition definition = (PredicateDefinition) statement; |
83 | installDerivedPredicateDefinitionState(definition, nodeNames); | ||
83 | } | 84 | } |
84 | } | 85 | } |
85 | } | 86 | } |
@@ -88,7 +89,7 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer { | |||
88 | for (Statement statement : problem.getStatements()) { | 89 | for (Statement statement : problem.getStatements()) { |
89 | if (statement instanceof ClassDeclaration) { | 90 | if (statement instanceof ClassDeclaration) { |
90 | ClassDeclaration declaration = (ClassDeclaration) statement; | 91 | ClassDeclaration declaration = (ClassDeclaration) statement; |
91 | if (!declaration.isAbstract()) { | 92 | if (!declaration.isAbstract() && declaration.getNewNode() == null) { |
92 | Node newNode = createNode(NEW_NODE); | 93 | Node newNode = createNode(NEW_NODE); |
93 | declaration.setNewNode(newNode); | 94 | declaration.setNewNode(newNode); |
94 | } | 95 | } |
@@ -96,7 +97,7 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer { | |||
96 | } | 97 | } |
97 | } | 98 | } |
98 | 99 | ||
99 | protected void installDerivedNodes(Problem problem) { | 100 | protected Set<String> installDerivedNodes(Problem problem) { |
100 | IScope nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__ARGUMENTS); | 101 | IScope nodeScope = scopeProvider.getScope(problem, ProblemPackage.Literals.ASSERTION__ARGUMENTS); |
101 | Set<String> nodeNames = new HashSet<>(); | 102 | Set<String> nodeNames = new HashSet<>(); |
102 | for (Statement statement : problem.getStatements()) { | 103 | for (Statement statement : problem.getStatements()) { |
@@ -142,6 +143,7 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer { | |||
142 | Node graphNode = createNode(nodeName); | 143 | Node graphNode = createNode(nodeName); |
143 | grapNodes.add(graphNode); | 144 | grapNodes.add(graphNode); |
144 | } | 145 | } |
146 | return nodeNames; | ||
145 | } | 147 | } |
146 | 148 | ||
147 | private void addNodeNames(Set<String> nodeNames, IScope nodeScope, EObject eObject, EStructuralFeature feature, | 149 | private void addNodeNames(Set<String> nodeNames, IScope nodeScope, EObject eObject, EStructuralFeature feature, |
@@ -165,16 +167,17 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer { | |||
165 | return node; | 167 | return node; |
166 | } | 168 | } |
167 | 169 | ||
168 | protected void installDerivedPredicateDefinitionState(PredicateDefinition definition) { | 170 | protected void installDerivedPredicateDefinitionState(PredicateDefinition definition, Set<String> nodeNames) { |
169 | Set<String> parameterNames = new HashSet<>(); | 171 | Set<String> knownVariables = new HashSet<>(); |
172 | knownVariables.addAll(nodeNames); | ||
170 | for (Parameter parameter : definition.getParameters()) { | 173 | for (Parameter parameter : definition.getParameters()) { |
171 | String name = parameter.getName(); | 174 | String name = parameter.getName(); |
172 | if (name != null) { | 175 | if (name != null) { |
173 | parameterNames.add(name); | 176 | knownVariables.add(name); |
174 | } | 177 | } |
175 | } | 178 | } |
176 | for (Conjunction body : definition.getBodies()) { | 179 | for (Conjunction body : definition.getBodies()) { |
177 | installDeriveConjunctionState(body, parameterNames); | 180 | installDeriveConjunctionState(body, knownVariables); |
178 | } | 181 | } |
179 | } | 182 | } |
180 | 183 | ||
@@ -271,10 +274,9 @@ public class ProblemDerivedStateComputer implements IDerivedStateComputer { | |||
271 | protected void discardDerivedProblemState(Problem problem) { | 274 | protected void discardDerivedProblemState(Problem problem) { |
272 | problem.getNodes().clear(); | 275 | problem.getNodes().clear(); |
273 | for (Statement statement : problem.getStatements()) { | 276 | for (Statement statement : problem.getStatements()) { |
274 | if (statement instanceof ClassDeclaration) { | 277 | // We deliberately don't clean up {@link ClassDeclaration#getNewNode()} nodes, |
275 | ClassDeclaration classDeclaration = (ClassDeclaration) statement; | 278 | // because they have already been exported to the Xtext index. |
276 | classDeclaration.setNewNode(null); | 279 | if (statement instanceof PredicateDefinition) { |
277 | } else if (statement instanceof PredicateDefinition) { | ||
278 | PredicateDefinition definition = (PredicateDefinition) statement; | 280 | PredicateDefinition definition = (PredicateDefinition) statement; |
279 | for (Conjunction body : definition.getBodies()) { | 281 | for (Conjunction body : definition.getBodies()) { |
280 | body.getImplicitVariables().clear(); | 282 | body.getImplicitVariables().clear(); |
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 edb25a1c..4d932a92 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 | |||
@@ -24,56 +24,70 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti | |||
24 | 24 | ||
25 | @Override | 25 | @Override |
26 | public boolean createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) { | 26 | public boolean createEObjectDescriptions(EObject eObject, IAcceptor<IEObjectDescription> acceptor) { |
27 | if (eObject instanceof Variable) { | 27 | if (!shouldExport(eObject)) { |
28 | return false; | 28 | return false; |
29 | } | 29 | } |
30 | if (eObject instanceof NamedElement) { | 30 | if (!(eObject instanceof NamedElement)) { |
31 | NamedElement namedElement = (NamedElement) eObject; | 31 | return true; |
32 | String name = namedElement.getName(); | 32 | } |
33 | if (name == null || name.isEmpty()) { | 33 | NamedElement namedElement = (NamedElement) eObject; |
34 | return true; | 34 | String name = namedElement.getName(); |
35 | } | 35 | if (name == null || name.isEmpty()) { |
36 | Problem problem = EcoreUtil2.getContainerOfType(namedElement, Problem.class); | 36 | return true; |
37 | QualifiedName problemQualifiedName = null; | 37 | } |
38 | if (problem != null) { | 38 | Problem problem = EcoreUtil2.getContainerOfType(namedElement, Problem.class); |
39 | String problemName = problem.getName(); | 39 | QualifiedName problemQualifiedName = null; |
40 | if (problemName != null && !problemName.isEmpty()) { | 40 | if (problem != null) { |
41 | problemQualifiedName = qualifiedNameConverter.toQualifiedName(problemName); | 41 | String problemName = problem.getName(); |
42 | } | 42 | if (problemName != null && !problemName.isEmpty()) { |
43 | } | 43 | problemQualifiedName = qualifiedNameConverter.toQualifiedName(problemName); |
44 | QualifiedName qualifiedName = qualifiedNameConverter.toQualifiedName(namedElement.getName()); | ||
45 | boolean nameExported; | ||
46 | if (shouldExportSimpleName(namedElement)) { | ||
47 | acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); | ||
48 | nameExported = true; | ||
49 | } else { | ||
50 | nameExported = false; | ||
51 | } | 44 | } |
52 | EObject parent = namedElement.eContainer(); | 45 | } |
53 | while (parent != null && parent != problem) { | 46 | QualifiedName qualifiedName = qualifiedNameConverter.toQualifiedName(namedElement.getName()); |
54 | if (parent instanceof NamedElement) { | 47 | boolean nameExported; |
55 | NamedElement namedParent = (NamedElement) parent; | 48 | if (shouldExportSimpleName(namedElement)) { |
56 | String parentName = namedParent.getName(); | 49 | acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); |
57 | if (parentName != null || !name.isEmpty()) { | 50 | nameExported = true; |
58 | QualifiedName parentQualifiedName = qualifiedNameConverter.toQualifiedName(parentName); | 51 | } else { |
59 | qualifiedName = parentQualifiedName.append(qualifiedName); | 52 | nameExported = false; |
60 | if (shouldExportSimpleName(parent)) { | 53 | } |
61 | acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); | 54 | EObject parent = namedElement.eContainer(); |
62 | nameExported = true; | 55 | while (parent != null && parent != problem) { |
63 | } else { | 56 | if (parent instanceof NamedElement) { |
64 | nameExported = false; | 57 | NamedElement namedParent = (NamedElement) parent; |
65 | } | 58 | String parentName = namedParent.getName(); |
59 | if (parentName != null || !name.isEmpty()) { | ||
60 | QualifiedName parentQualifiedName = qualifiedNameConverter.toQualifiedName(parentName); | ||
61 | qualifiedName = parentQualifiedName.append(qualifiedName); | ||
62 | if (shouldExportSimpleName(namedParent)) { | ||
63 | acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); | ||
64 | nameExported = true; | ||
65 | } else { | ||
66 | nameExported = false; | ||
66 | } | 67 | } |
67 | } | 68 | } |
68 | parent = parent.eContainer(); | ||
69 | } | ||
70 | if (!nameExported) { | ||
71 | acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); | ||
72 | } | 69 | } |
70 | parent = parent.eContainer(); | ||
71 | } | ||
72 | if (!nameExported) { | ||
73 | acceptEObjectDescription(namedElement, problemQualifiedName, qualifiedName, acceptor); | ||
73 | } | 74 | } |
74 | return true; | 75 | return true; |
75 | } | 76 | } |
76 | 77 | ||
78 | protected boolean shouldExport(EObject eObject) { | ||
79 | if (eObject instanceof Variable) { | ||
80 | // Variables are always private to the containing predicate definition. | ||
81 | return false; | ||
82 | } | ||
83 | if (eObject instanceof Node) { | ||
84 | Node node = (Node) eObject; | ||
85 | // Only enum literals and new nodes are visible across problem files. | ||
86 | return ProblemUtil.isEnumLiteral(node) || ProblemUtil.isNewNode(node); | ||
87 | } | ||
88 | return true; | ||
89 | } | ||
90 | |||
77 | protected boolean shouldExportSimpleName(EObject eObject) { | 91 | protected boolean shouldExportSimpleName(EObject eObject) { |
78 | if (eObject instanceof Node) { | 92 | if (eObject instanceof Node) { |
79 | return !ProblemUtil.isNewNode((Node) eObject); | 93 | return !ProblemUtil.isNewNode((Node) eObject); |
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 3748e81d..597085a8 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 | |||
@@ -13,6 +13,7 @@ import org.eclipse.viatra.solver.language.ProblemUtil; | |||
13 | import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; | 13 | import org.eclipse.viatra.solver.language.model.problem.ClassDeclaration; |
14 | import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier; | 14 | import org.eclipse.viatra.solver.language.model.problem.ExistentialQuantifier; |
15 | import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; | 15 | import org.eclipse.viatra.solver.language.model.problem.PredicateDefinition; |
16 | import org.eclipse.viatra.solver.language.model.problem.Problem; | ||
16 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; | 17 | import org.eclipse.viatra.solver.language.model.problem.ProblemPackage; |
17 | import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; | 18 | import org.eclipse.viatra.solver.language.model.problem.ReferenceDeclaration; |
18 | import org.eclipse.viatra.solver.language.model.problem.Relation; | 19 | import org.eclipse.viatra.solver.language.model.problem.Relation; |
@@ -34,14 +35,27 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider { | |||
34 | @Override | 35 | @Override |
35 | public IScope getScope(EObject context, EReference reference) { | 36 | public IScope getScope(EObject context, EReference reference) { |
36 | IScope scope = super.getScope(context, reference); | 37 | IScope scope = super.getScope(context, reference); |
38 | if (reference == ProblemPackage.Literals.NODE_ASSERTION_ARGUMENT__NODE | ||
39 | || reference == ProblemPackage.Literals.NODE_VALUE_ASSERTION__NODE) { | ||
40 | return getNodesScope(context, scope); | ||
41 | } | ||
37 | if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE) { | 42 | if (reference == ProblemPackage.Literals.VARIABLE_OR_NODE_ARGUMENT__VARIABLE_OR_NODE) { |
38 | return getVariableScope(context, scope); | 43 | return getVariableScope(context, scope); |
39 | } else if (reference == ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE) { | 44 | } |
45 | if (reference == ProblemPackage.Literals.REFERENCE_DECLARATION__OPPOSITE) { | ||
40 | return getOppositeScope(context, scope); | 46 | return getOppositeScope(context, scope); |
41 | } | 47 | } |
42 | return scope; | 48 | return scope; |
43 | } | 49 | } |
44 | 50 | ||
51 | protected IScope getNodesScope(EObject context, IScope delegateScope) { | ||
52 | Problem problem = EcoreUtil2.getContainerOfType(context, Problem.class); | ||
53 | if (problem == null) { | ||
54 | return delegateScope; | ||
55 | } | ||
56 | return Scopes.scopeFor(problem.getNodes(), delegateScope); | ||
57 | } | ||
58 | |||
45 | protected IScope getVariableScope(EObject context, IScope delegateScope) { | 59 | protected IScope getVariableScope(EObject context, IScope delegateScope) { |
46 | List<Variable> variables = new ArrayList<>(); | 60 | List<Variable> variables = new ArrayList<>(); |
47 | EObject currentContext = context; | 61 | EObject currentContext = context; |
@@ -63,7 +77,7 @@ public class ProblemScopeProvider extends AbstractProblemScopeProvider { | |||
63 | PredicateDefinition definition = (PredicateDefinition) currentContext; | 77 | PredicateDefinition definition = (PredicateDefinition) currentContext; |
64 | variables.addAll(definition.getParameters()); | 78 | variables.addAll(definition.getParameters()); |
65 | } | 79 | } |
66 | return Scopes.scopeFor(variables, delegateScope); | 80 | return Scopes.scopeFor(variables, getNodesScope(context, delegateScope)); |
67 | } | 81 | } |
68 | 82 | ||
69 | protected IScope getOppositeScope(EObject context, IScope delegateScope) { | 83 | protected IScope getOppositeScope(EObject context, IScope delegateScope) { |