diff options
author | Kristóf Marussy <kristof@marussy.com> | 2024-02-02 16:28:19 +0100 |
---|---|---|
committer | Kristóf Marussy <kristof@marussy.com> | 2024-02-02 17:36:24 +0100 |
commit | 2dfcb286216419976368ad926f8ac7f018aa2bf9 (patch) | |
tree | b9d235ebf2049e42e58126e743c782333d64681a /subprojects | |
parent | refactor: serialize solutions as modules (diff) | |
download | refinery-2dfcb286216419976368ad926f8ac7f018aa2bf9.tar.gz refinery-2dfcb286216419976368ad926f8ac7f018aa2bf9.tar.zst refinery-2dfcb286216419976368ad926f8ac7f018aa2bf9.zip |
refactor(language): name disambiguation
* Use fully qualified names starting with :: (as in C++) to unambiguously refer
to an element.
* Name shadowing within modules.
Diffstat (limited to 'subprojects')
33 files changed, 697 insertions, 130 deletions
diff --git a/subprojects/frontend/src/editor/EditorTheme.ts b/subprojects/frontend/src/editor/EditorTheme.ts index f499b0d9..4978c7f7 100644 --- a/subprojects/frontend/src/editor/EditorTheme.ts +++ b/subprojects/frontend/src/editor/EditorTheme.ts | |||
@@ -40,7 +40,9 @@ function createTypeHashStyles( | |||
40 | export default styled('div', { | 40 | export default styled('div', { |
41 | name: 'EditorTheme', | 41 | name: 'EditorTheme', |
42 | shouldForwardProp: (propName) => | 42 | shouldForwardProp: (propName) => |
43 | propName !== 'showLineNumbers' && propName !== 'showActiveLine', | 43 | propName !== 'showLineNumbers' && |
44 | propName !== 'showActiveLine' && | ||
45 | propName !== 'colorIdentifiers', | ||
44 | })<{ | 46 | })<{ |
45 | showLineNumbers: boolean; | 47 | showLineNumbers: boolean; |
46 | showActiveLine: boolean; | 48 | showActiveLine: boolean; |
diff --git a/subprojects/frontend/src/language/problem.grammar b/subprojects/frontend/src/language/problem.grammar index ac451e7a..e39ce102 100644 --- a/subprojects/frontend/src/language/problem.grammar +++ b/subprojects/frontend/src/language/problem.grammar | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -22,6 +22,9 @@ | |||
22 | @top Problem { statement* } | 22 | @top Problem { statement* } |
23 | 23 | ||
24 | statement { | 24 | statement { |
25 | ImportStatement { | ||
26 | kw<"import"> QualifiedName (kw<"as"> identifier)? "." | ||
27 | } | | ||
25 | Assertion { | 28 | Assertion { |
26 | kw<"default">? (NotOp | UnknownOp)? RelationName | 29 | kw<"default">? (NotOp | UnknownOp)? RelationName |
27 | ParameterList<AssertionArgument> | 30 | ParameterList<AssertionArgument> |
@@ -170,7 +173,7 @@ VariableName[@dynamicPrecedence=10] { QualifiedName ~name } | |||
170 | 173 | ||
171 | NodeName { QualifiedName } | 174 | NodeName { QualifiedName } |
172 | 175 | ||
173 | QualifiedName[implicitCompletion=true] { identifier ("::" identifier)* } | 176 | QualifiedName[implicitCompletion=true] { "::"? identifier (QualifiedNameSeparator "::" identifier)* } |
174 | 177 | ||
175 | kw<term> { @specialize[@name={term},implicitCompletion=true]<identifier, term> } | 178 | kw<term> { @specialize[@name={term},implicitCompletion=true]<identifier, term> } |
176 | 179 | ||
@@ -184,6 +187,10 @@ sep1<separator, content> { content (separator content)* } | |||
184 | 187 | ||
185 | @skip { LineComment | BlockComment | whitespace } | 188 | @skip { LineComment | BlockComment | whitespace } |
186 | 189 | ||
190 | @external tokens qualifiedNameSeparator from "./tokens" { | ||
191 | QualifiedNameSeparator | ||
192 | } | ||
193 | |||
187 | @tokens { | 194 | @tokens { |
188 | whitespace { std.whitespace+ } | 195 | whitespace { std.whitespace+ } |
189 | 196 | ||
diff --git a/subprojects/frontend/src/language/problemLanguageSupport.ts b/subprojects/frontend/src/language/problemLanguageSupport.ts index 2483c2e3..aebccfa4 100644 --- a/subprojects/frontend/src/language/problemLanguageSupport.ts +++ b/subprojects/frontend/src/language/problemLanguageSupport.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -28,7 +28,7 @@ const parserWithMetadata = parser.configure({ | |||
28 | LineComment: t.lineComment, | 28 | LineComment: t.lineComment, |
29 | BlockComment: t.blockComment, | 29 | BlockComment: t.blockComment, |
30 | 'module problem class enum pred fn scope': t.definitionKeyword, | 30 | 'module problem class enum pred fn scope': t.definitionKeyword, |
31 | 'declare atom multi': t.definitionKeyword, | 31 | 'import as declare atom multi': t.definitionKeyword, |
32 | 'abstract extends refers contains container opposite': t.modifier, | 32 | 'abstract extends refers contains container opposite': t.modifier, |
33 | 'default error contained containment': t.modifier, | 33 | 'default error contained containment': t.modifier, |
34 | 'true false unknown error': t.keyword, | 34 | 'true false unknown error': t.keyword, |
diff --git a/subprojects/frontend/src/language/tokens.ts b/subprojects/frontend/src/language/tokens.ts new file mode 100644 index 00000000..b5d022f1 --- /dev/null +++ b/subprojects/frontend/src/language/tokens.ts | |||
@@ -0,0 +1,46 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2018-2024 by Marijn Haverbeke <marijnh@gmail.com> and others | ||
3 | * Copyright (C) 2024 The Refinery Authors <https://refinery.tools/> | ||
4 | * | ||
5 | * SPDX-License-Identifier: MIT AND EPL-2.0 | ||
6 | * | ||
7 | * Based on the CSS tokenizer at | ||
8 | * https://github.com/lezer-parser/css/blob/790568c968a660a94bf0fbd97a86c66da1c529e5/src/tokens.js | ||
9 | */ | ||
10 | |||
11 | import { ExternalTokenizer } from '@lezer/lr'; | ||
12 | |||
13 | /* eslint-disable-next-line import/no-unresolved -- | ||
14 | Synthetic import from `@lezer/generator/rollup` cannot be found by ESLint. | ||
15 | */ | ||
16 | import { QualifiedNameSeparator } from './problem.grammar.terms'; | ||
17 | |||
18 | const colon = 58; | ||
19 | const underscore = 95; | ||
20 | |||
21 | function isAlpha(ch: number) { | ||
22 | return (ch >= 65 && ch <= 90) || (ch >= 97 && ch <= 122) || ch >= 161; | ||
23 | } | ||
24 | |||
25 | function isDigit(ch: number) { | ||
26 | return ch >= 48 && ch <= 57; | ||
27 | } | ||
28 | |||
29 | function isIdentifier(ch: number) { | ||
30 | return isAlpha(ch) || isDigit(ch) || ch === underscore; | ||
31 | } | ||
32 | |||
33 | /* eslint-disable-next-line import/prefer-default-export -- | ||
34 | Lezer requires a named export. | ||
35 | */ | ||
36 | export const qualifiedNameSeparator = new ExternalTokenizer((input) => { | ||
37 | if (input.peek(0) === colon && input.peek(1) === colon) { | ||
38 | const previous = input.peek(-1); | ||
39 | if (isIdentifier(previous)) { | ||
40 | // Inject an extra 0-length token into the token stream to let Lezer | ||
41 | // consume the `::` on its own. Explicitly consuming 2 characters here | ||
42 | // leads to inconsistent highlighting of qualified names. | ||
43 | input.acceptToken(QualifiedNameSeparator); | ||
44 | } | ||
45 | } | ||
46 | }); | ||
diff --git a/subprojects/frontend/src/xtext/ContentAssistService.ts b/subprojects/frontend/src/xtext/ContentAssistService.ts index ac8ab36a..d42dde14 100644 --- a/subprojects/frontend/src/xtext/ContentAssistService.ts +++ b/subprojects/frontend/src/xtext/ContentAssistService.ts | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -108,7 +108,11 @@ function createCompletion(entry: ContentAssistEntry): Completion { | |||
108 | boost = -90; | 108 | boost = -90; |
109 | break; | 109 | break; |
110 | default: | 110 | default: |
111 | { | 111 | if (entry.proposal.startsWith('::')) { |
112 | // Move absolute names below relative names, | ||
113 | // they should only be preferred if no relative name is available. | ||
114 | boost = -60; | ||
115 | } else { | ||
112 | // Penalize qualified names (vs available unqualified names). | 116 | // Penalize qualified names (vs available unqualified names). |
113 | const extraSegments = entry.proposal.match(/::/g)?.length || 0; | 117 | const extraSegments = entry.proposal.match(/::/g)?.length || 0; |
114 | boost = Math.max(-5 * extraSegments, -50); | 118 | boost = Math.max(-5 * extraSegments, -50); |
diff --git a/subprojects/frontend/types/grammar.d.ts b/subprojects/frontend/types/grammar.d.ts index 92f99ec3..c7848e33 100644 --- a/subprojects/frontend/types/grammar.d.ts +++ b/subprojects/frontend/types/grammar.d.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2018 by Marijn Haverbeke <marijn@haverbeke.berlin> and others | 2 | * Copyright (C) 2018 by Marijn Haverbeke <marijn@haverbeke.berlin> and others |
3 | * Copyright (C) 2021-2023 The Refinery Authors <https://refinery.tools/> | 3 | * Copyright (C) 2021-2024 The Refinery Authors <https://refinery.tools/> |
4 | * | 4 | * |
5 | * SPDX-License-Identifier: MIT | 5 | * SPDX-License-Identifier: MIT |
6 | */ | 6 | */ |
@@ -10,3 +10,7 @@ declare module '*.grammar' { | |||
10 | 10 | ||
11 | export const parser: LRParser; | 11 | export const parser: LRParser; |
12 | } | 12 | } |
13 | |||
14 | declare module '*.terms' { | ||
15 | export const QualifiedNameSeparator: number; | ||
16 | } | ||
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java index 166b4400..fa04a012 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/contentassist/ProblemCrossrefProposalProvider.java | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -15,13 +15,14 @@ import org.eclipse.xtext.EcoreUtil2; | |||
15 | import org.eclipse.xtext.GrammarUtil; | 15 | import org.eclipse.xtext.GrammarUtil; |
16 | import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext; | 16 | import org.eclipse.xtext.ide.editor.contentassist.ContentAssistContext; |
17 | import org.eclipse.xtext.ide.editor.contentassist.IdeCrossrefProposalProvider; | 17 | import org.eclipse.xtext.ide.editor.contentassist.IdeCrossrefProposalProvider; |
18 | import org.eclipse.xtext.naming.QualifiedName; | ||
19 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; | 18 | import org.eclipse.xtext.nodemodel.util.NodeModelUtils; |
20 | import org.eclipse.xtext.resource.IEObjectDescription; | 19 | import org.eclipse.xtext.resource.IEObjectDescription; |
21 | import org.eclipse.xtext.scoping.IScope; | 20 | import org.eclipse.xtext.scoping.IScope; |
22 | import org.eclipse.xtext.xtext.CurrentTypeFinder; | 21 | import org.eclipse.xtext.xtext.CurrentTypeFinder; |
23 | import org.jetbrains.annotations.Nullable; | 22 | import org.jetbrains.annotations.Nullable; |
24 | import tools.refinery.language.model.problem.*; | 23 | import tools.refinery.language.model.problem.*; |
24 | import tools.refinery.language.naming.NamingUtil; | ||
25 | import tools.refinery.language.naming.ProblemQualifiedNameConverter; | ||
25 | import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; | 26 | import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; |
26 | import tools.refinery.language.utils.BuiltinSymbols; | 27 | import tools.refinery.language.utils.BuiltinSymbols; |
27 | import tools.refinery.language.utils.ProblemDesugarer; | 28 | import tools.refinery.language.utils.ProblemDesugarer; |
@@ -46,14 +47,12 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider | |||
46 | @Override | 47 | @Override |
47 | protected Iterable<IEObjectDescription> queryScope(IScope scope, CrossReference crossReference, | 48 | protected Iterable<IEObjectDescription> queryScope(IScope scope, CrossReference crossReference, |
48 | ContentAssistContext context) { | 49 | ContentAssistContext context) { |
49 | var eObjectDescriptionsByName = new HashMap<QualifiedName, List<IEObjectDescription>>(); | 50 | var eObjectDescriptionsByName = new HashMap<ProblemResourceDescriptionStrategy.ShadowingKey, |
51 | List<IEObjectDescription>>(); | ||
50 | for (var candidate : super.queryScope(scope, crossReference, context)) { | 52 | for (var candidate : super.queryScope(scope, crossReference, context)) { |
51 | if (isExistingObject(candidate, crossReference, context)) { | 53 | if (isExistingObject(candidate, crossReference, context)) { |
52 | // {@code getQualifiedName()} will refer to the full name for objects that are loaded from the global | 54 | var shadowingKey = ProblemResourceDescriptionStrategy.getShadowingKey(candidate); |
53 | // scope, but {@code getName()} returns the qualified name that we set in | 55 | var candidateList = eObjectDescriptionsByName.computeIfAbsent(shadowingKey, |
54 | // {@code ProblemResourceDescriptionStrategy}. | ||
55 | var qualifiedName = candidate.getName(); | ||
56 | var candidateList = eObjectDescriptionsByName.computeIfAbsent(qualifiedName, | ||
57 | ignored -> new ArrayList<>()); | 56 | ignored -> new ArrayList<>()); |
58 | candidateList.add(candidate); | 57 | candidateList.add(candidate); |
59 | } | 58 | } |
@@ -61,7 +60,7 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider | |||
61 | var eObjectDescriptions = new ArrayList<IEObjectDescription>(); | 60 | var eObjectDescriptions = new ArrayList<IEObjectDescription>(); |
62 | for (var candidates : eObjectDescriptionsByName.values()) { | 61 | for (var candidates : eObjectDescriptionsByName.values()) { |
63 | if (candidates.size() == 1) { | 62 | if (candidates.size() == 1) { |
64 | var candidate = candidates.get(0); | 63 | var candidate = candidates.getFirst(); |
65 | if (shouldBeVisible(candidate, crossReference, context)) { | 64 | if (shouldBeVisible(candidate, crossReference, context)) { |
66 | eObjectDescriptions.add(candidate); | 65 | eObjectDescriptions.add(candidate); |
67 | } | 66 | } |
@@ -96,6 +95,11 @@ public class ProblemCrossrefProposalProvider extends IdeCrossrefProposalProvider | |||
96 | 95 | ||
97 | protected boolean shouldBeVisible(IEObjectDescription candidate, CrossReference crossReference, | 96 | protected boolean shouldBeVisible(IEObjectDescription candidate, CrossReference crossReference, |
98 | ContentAssistContext context) { | 97 | ContentAssistContext context) { |
98 | if (NamingUtil.isFullyQualified(candidate.getName()) && | ||
99 | !context.getPrefix().startsWith(ProblemQualifiedNameConverter.DELIMITER)) { | ||
100 | // Do not propose names with a root prefix unless explicitly asked for. | ||
101 | return false; | ||
102 | } | ||
99 | var errorPredicate = candidate.getUserData(ProblemResourceDescriptionStrategy.ERROR_PREDICATE); | 103 | var errorPredicate = candidate.getUserData(ProblemResourceDescriptionStrategy.ERROR_PREDICATE); |
100 | if (ProblemResourceDescriptionStrategy.ERROR_PREDICATE_TRUE.equals(errorPredicate)) { | 104 | if (ProblemResourceDescriptionStrategy.ERROR_PREDICATE_TRUE.equals(errorPredicate)) { |
101 | return false; | 105 | return false; |
diff --git a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java index 94a61c4f..891c73c7 100644 --- a/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java +++ b/subprojects/language-ide/src/main/java/tools/refinery/language/ide/syntaxcoloring/ProblemSemanticHighlightingCalculator.java | |||
@@ -99,7 +99,7 @@ public class ProblemSemanticHighlightingCalculator extends DefaultSemanticHighli | |||
99 | 99 | ||
100 | protected String[] getHighlightClass(EObject eObject, EReference reference) { | 100 | protected String[] getHighlightClass(EObject eObject, EReference reference) { |
101 | boolean isError = ProblemUtil.isError(eObject); | 101 | boolean isError = ProblemUtil.isError(eObject); |
102 | if (ProblemUtil.isBuiltIn(eObject)) { | 102 | if (ProblemUtil.isBuiltIn(eObject) && !(eObject instanceof Problem)) { |
103 | var className = isError ? ERROR_CLASS : BUILTIN_CLASS; | 103 | var className = isError ? ERROR_CLASS : BUILTIN_CLASS; |
104 | return new String[]{className}; | 104 | return new String[]{className}; |
105 | } | 105 | } |
diff --git a/subprojects/language-model/problem.aird b/subprojects/language-model/problem.aird index a3420a04..6583d364 100644 --- a/subprojects/language-model/problem.aird +++ b/subprojects/language-model/problem.aird | |||
@@ -7,7 +7,7 @@ | |||
7 | <semanticResources>build/resources/main/model/problem.genmodel</semanticResources> | 7 | <semanticResources>build/resources/main/model/problem.genmodel</semanticResources> |
8 | <ownedViews xmi:type="viewpoint:DView" uid="_CsAAYKA4EeuqkpDnuik1sg"> | 8 | <ownedViews xmi:type="viewpoint:DView" uid="_CsAAYKA4EeuqkpDnuik1sg"> |
9 | <viewpoint xmi:type="description:Viewpoint" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']"/> | 9 | <viewpoint xmi:type="description:Viewpoint" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']"/> |
10 | <ownedRepresentationDescriptors xmi:type="viewpoint:DRepresentationDescriptor" uid="_CsYa4KA4EeuqkpDnuik1sg" name="declarations" repPath="#_CsUwgKA4EeuqkpDnuik1sg" changeId="1706658830410"> | 10 | <ownedRepresentationDescriptors xmi:type="viewpoint:DRepresentationDescriptor" uid="_CsYa4KA4EeuqkpDnuik1sg" name="declarations" repPath="#_CsUwgKA4EeuqkpDnuik1sg" changeId="1706722245720"> |
11 | <description xmi:type="description_1:DiagramDescription" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']"/> | 11 | <description xmi:type="description_1:DiagramDescription" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']"/> |
12 | <target xmi:type="ecore:EPackage" href="src/main/resources/model/problem.ecore#/"/> | 12 | <target xmi:type="ecore:EPackage" href="src/main/resources/model/problem.ecore#/"/> |
13 | </ownedRepresentationDescriptors> | 13 | </ownedRepresentationDescriptors> |
@@ -478,6 +478,19 @@ | |||
478 | <styles xmi:type="notation:ShapeStyle" xmi:id="_aq0Q0b_KEe6Mo_-4--GvQg" fontName="Noto Sans" fontHeight="8"/> | 478 | <styles xmi:type="notation:ShapeStyle" xmi:id="_aq0Q0b_KEe6Mo_-4--GvQg" fontName="Noto Sans" fontHeight="8"/> |
479 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_aq0Q0r_KEe6Mo_-4--GvQg" x="131" y="716" width="120" height="100"/> | 479 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_aq0Q0r_KEe6Mo_-4--GvQg" x="131" y="716" width="120" height="100"/> |
480 | </children> | 480 | </children> |
481 | <children xmi:type="notation:Node" xmi:id="_GTtOgMBeEe6Mo_-4--GvQg" type="2003" element="_GTZsgMBeEe6Mo_-4--GvQg"> | ||
482 | <children xmi:type="notation:Node" xmi:id="_GTtOg8BeEe6Mo_-4--GvQg" type="5007"/> | ||
483 | <children xmi:type="notation:Node" xmi:id="_GTtOhMBeEe6Mo_-4--GvQg" type="7004"> | ||
484 | <children xmi:type="notation:Node" xmi:id="_dTgyIMBeEe6Mo_-4--GvQg" type="3010" element="_dTNQIMBeEe6Mo_-4--GvQg"> | ||
485 | <styles xmi:type="notation:FontStyle" xmi:id="_dTgyIcBeEe6Mo_-4--GvQg" fontColor="2697711" fontName="Noto Sans" fontHeight="8"/> | ||
486 | <layoutConstraint xmi:type="notation:Location" xmi:id="_dTgyIsBeEe6Mo_-4--GvQg"/> | ||
487 | </children> | ||
488 | <styles xmi:type="notation:SortingStyle" xmi:id="_GTtOhcBeEe6Mo_-4--GvQg"/> | ||
489 | <styles xmi:type="notation:FilteringStyle" xmi:id="_GTtOhsBeEe6Mo_-4--GvQg"/> | ||
490 | </children> | ||
491 | <styles xmi:type="notation:ShapeStyle" xmi:id="_GTtOgcBeEe6Mo_-4--GvQg" fontName="Noto Sans" fontHeight="8"/> | ||
492 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_GTtOgsBeEe6Mo_-4--GvQg" x="-48" y="524" width="120" height="100"/> | ||
493 | </children> | ||
481 | <styles xmi:type="notation:DiagramStyle" xmi:id="_CsZB8qA4EeuqkpDnuik1sg"/> | 494 | <styles xmi:type="notation:DiagramStyle" xmi:id="_CsZB8qA4EeuqkpDnuik1sg"/> |
482 | <edges xmi:type="notation:Edge" xmi:id="_4eaYwKA8EeuqkpDnuik1sg" type="4001" element="_4eU5TqA8EeuqkpDnuik1sg" source="_D1D6MKA4EeuqkpDnuik1sg" target="_xsq_MKA8EeuqkpDnuik1sg"> | 495 | <edges xmi:type="notation:Edge" xmi:id="_4eaYwKA8EeuqkpDnuik1sg" type="4001" element="_4eU5TqA8EeuqkpDnuik1sg" source="_D1D6MKA4EeuqkpDnuik1sg" target="_xsq_MKA8EeuqkpDnuik1sg"> |
483 | <children xmi:type="notation:Node" xmi:id="_4ea_06A8EeuqkpDnuik1sg" type="6001"> | 496 | <children xmi:type="notation:Node" xmi:id="_4ea_06A8EeuqkpDnuik1sg" type="6001"> |
@@ -1357,6 +1370,38 @@ | |||
1357 | <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_8s_6QDrXEe62Q_vL_UTCsA" id="(0.3586206896551724,0.0)"/> | 1370 | <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_8s_6QDrXEe62Q_vL_UTCsA" id="(0.3586206896551724,0.0)"/> |
1358 | <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_8s_6QTrXEe62Q_vL_UTCsA" id="(0.5338983050847458,1.0)"/> | 1371 | <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_8s_6QTrXEe62Q_vL_UTCsA" id="(0.5338983050847458,1.0)"/> |
1359 | </edges> | 1372 | </edges> |
1373 | <edges xmi:type="notation:Edge" xmi:id="_UVB0MMBeEe6Mo_-4--GvQg" type="4001" element="_UU0Y5cBeEe6Mo_-4--GvQg" source="_GTtOgMBeEe6Mo_-4--GvQg" target="_e73WIKA9EeuqkpDnuik1sg"> | ||
1374 | <children xmi:type="notation:Node" xmi:id="_UVB0NMBeEe6Mo_-4--GvQg" type="6001"> | ||
1375 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_UVB0NcBeEe6Mo_-4--GvQg" y="-10"/> | ||
1376 | </children> | ||
1377 | <children xmi:type="notation:Node" xmi:id="_UVB0NsBeEe6Mo_-4--GvQg" type="6002"> | ||
1378 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_UVB0N8BeEe6Mo_-4--GvQg" y="10"/> | ||
1379 | </children> | ||
1380 | <children xmi:type="notation:Node" xmi:id="_UVB0OMBeEe6Mo_-4--GvQg" type="6003"> | ||
1381 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_UVB0OcBeEe6Mo_-4--GvQg" y="10"/> | ||
1382 | </children> | ||
1383 | <styles xmi:type="notation:ConnectorStyle" xmi:id="_UVB0McBeEe6Mo_-4--GvQg" routing="Tree"/> | ||
1384 | <styles xmi:type="notation:FontStyle" xmi:id="_UVB0MsBeEe6Mo_-4--GvQg" fontName="Noto Sans" fontHeight="8"/> | ||
1385 | <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_UVB0M8BeEe6Mo_-4--GvQg" points="[0, 0, -706, 180]$[706, -180, 0, 0]"/> | ||
1386 | <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_UVCbQMBeEe6Mo_-4--GvQg" id="(0.635593220338983,0.030612244897959183)"/> | ||
1387 | <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_UVCbQcBeEe6Mo_-4--GvQg" id="(0.5,0.0)"/> | ||
1388 | </edges> | ||
1389 | <edges xmi:type="notation:Edge" xmi:id="_bYblgMBeEe6Mo_-4--GvQg" type="4001" element="_bYOKL8BeEe6Mo_-4--GvQg" source="_GTtOgMBeEe6Mo_-4--GvQg" target="_D1D6MKA4EeuqkpDnuik1sg"> | ||
1390 | <children xmi:type="notation:Node" xmi:id="_bYblhMBeEe6Mo_-4--GvQg" type="6001"> | ||
1391 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_bYblhcBeEe6Mo_-4--GvQg" x="-13" y="-10"/> | ||
1392 | </children> | ||
1393 | <children xmi:type="notation:Node" xmi:id="_bYblhsBeEe6Mo_-4--GvQg" type="6002"> | ||
1394 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_bYblh8BeEe6Mo_-4--GvQg" x="4" y="10"/> | ||
1395 | </children> | ||
1396 | <children xmi:type="notation:Node" xmi:id="_bYbliMBeEe6Mo_-4--GvQg" type="6003"> | ||
1397 | <layoutConstraint xmi:type="notation:Bounds" xmi:id="_bYblicBeEe6Mo_-4--GvQg" x="-4" y="10"/> | ||
1398 | </children> | ||
1399 | <styles xmi:type="notation:ConnectorStyle" xmi:id="_bYblgcBeEe6Mo_-4--GvQg" routing="Rectilinear"/> | ||
1400 | <styles xmi:type="notation:FontStyle" xmi:id="_bYblgsBeEe6Mo_-4--GvQg" fontColor="7490599" fontName="Noto Sans" fontHeight="8"/> | ||
1401 | <bendpoints xmi:type="notation:RelativeBendpoints" xmi:id="_bYblg8BeEe6Mo_-4--GvQg" points="[0, 0, -778, 292]$[0, -293, -778, -1]$[776, -293, -2, -1]"/> | ||
1402 | <sourceAnchor xmi:type="notation:IdentityAnchor" xmi:id="_bYblisBeEe6Mo_-4--GvQg" id="(0.4067796610169492,0.0)"/> | ||
1403 | <targetAnchor xmi:type="notation:IdentityAnchor" xmi:id="_bYbli8BeEe6Mo_-4--GvQg" id="(0.01694915254237288,0.5714285714285714)"/> | ||
1404 | </edges> | ||
1360 | </data> | 1405 | </data> |
1361 | </ownedAnnotationEntries> | 1406 | </ownedAnnotationEntries> |
1362 | <ownedAnnotationEntries xmi:type="description:AnnotationEntry" uid="_Csiy8KA4EeuqkpDnuik1sg" source="DANNOTATION_CUSTOMIZATION_KEY"> | 1407 | <ownedAnnotationEntries xmi:type="description:AnnotationEntry" uid="_Csiy8KA4EeuqkpDnuik1sg" source="DANNOTATION_CUSTOMIZATION_KEY"> |
@@ -1372,7 +1417,7 @@ | |||
1372 | </computedStyleDescriptions> | 1417 | </computedStyleDescriptions> |
1373 | </data> | 1418 | </data> |
1374 | </ownedAnnotationEntries> | 1419 | </ownedAnnotationEntries> |
1375 | <ownedDiagramElements xmi:type="diagram:DNodeList" uid="_D05iIKA4EeuqkpDnuik1sg" name="Problem" tooltipText="" outgoingEdges="_4eU5TqA8EeuqkpDnuik1sg _hU64ZqA9EeuqkpDnuik1sg _m-6OTNXtEeuF_d0WEhR3Xw" width="12" height="10"> | 1420 | <ownedDiagramElements xmi:type="diagram:DNodeList" uid="_D05iIKA4EeuqkpDnuik1sg" name="Problem" tooltipText="" outgoingEdges="_4eU5TqA8EeuqkpDnuik1sg _hU64ZqA9EeuqkpDnuik1sg _m-6OTNXtEeuF_d0WEhR3Xw" incomingEdges="_bYOKL8BeEe6Mo_-4--GvQg" width="12" height="10"> |
1376 | <target xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//Problem"/> | 1421 | <target xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//Problem"/> |
1377 | <semanticElements xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//Problem"/> | 1422 | <semanticElements xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//Problem"/> |
1378 | <arrangeConstraints>KEEP_LOCATION</arrangeConstraints> | 1423 | <arrangeConstraints>KEEP_LOCATION</arrangeConstraints> |
@@ -1578,7 +1623,7 @@ | |||
1578 | </ownedStyle> | 1623 | </ownedStyle> |
1579 | <actualMapping xmi:type="description_1:ContainerMapping" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@containerMappings[name='EC%20EClass']"/> | 1624 | <actualMapping xmi:type="description_1:ContainerMapping" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@containerMappings[name='EC%20EClass']"/> |
1580 | </ownedDiagramElements> | 1625 | </ownedDiagramElements> |
1581 | <ownedDiagramElements xmi:type="diagram:DNodeList" uid="_e7ydoKA9EeuqkpDnuik1sg" name="Statement" tooltipText="" incomingEdges="_hU64ZqA9EeuqkpDnuik1sg _mzziwKA9EeuqkpDnuik1sg _plK3JqA9EeuqkpDnuik1sg _vdptgqA9EeuqkpDnuik1sg _WX_5w9bGEeuymriYTNxK2g _s68oXAGyEey7cfH5K6RyCw" width="12" height="10"> | 1626 | <ownedDiagramElements xmi:type="diagram:DNodeList" uid="_e7ydoKA9EeuqkpDnuik1sg" name="Statement" tooltipText="" incomingEdges="_hU64ZqA9EeuqkpDnuik1sg _mzziwKA9EeuqkpDnuik1sg _plK3JqA9EeuqkpDnuik1sg _vdptgqA9EeuqkpDnuik1sg _WX_5w9bGEeuymriYTNxK2g _s68oXAGyEey7cfH5K6RyCw _UU0Y5cBeEe6Mo_-4--GvQg" width="12" height="10"> |
1582 | <target xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//Statement"/> | 1627 | <target xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//Statement"/> |
1583 | <semanticElements xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//Statement"/> | 1628 | <semanticElements xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//Statement"/> |
1584 | <arrangeConstraints>KEEP_LOCATION</arrangeConstraints> | 1629 | <arrangeConstraints>KEEP_LOCATION</arrangeConstraints> |
@@ -2684,6 +2729,47 @@ | |||
2684 | <actualMapping xmi:type="description_1:NodeMapping" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@containerMappings[name='EC%20EEnum']/@subNodeMappings[name='EC%20EEnumLiteral']"/> | 2729 | <actualMapping xmi:type="description_1:NodeMapping" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@containerMappings[name='EC%20EEnum']/@subNodeMappings[name='EC%20EEnumLiteral']"/> |
2685 | </ownedElements> | 2730 | </ownedElements> |
2686 | </ownedDiagramElements> | 2731 | </ownedDiagramElements> |
2732 | <ownedDiagramElements xmi:type="diagram:DNodeList" uid="_GTZsgMBeEe6Mo_-4--GvQg" name="ImportStatement" tooltipText="" outgoingEdges="_UU0Y5cBeEe6Mo_-4--GvQg _bYOKL8BeEe6Mo_-4--GvQg" width="12" height="10"> | ||
2733 | <target xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//ImportStatement"/> | ||
2734 | <semanticElements xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//ImportStatement"/> | ||
2735 | <arrangeConstraints>KEEP_LOCATION</arrangeConstraints> | ||
2736 | <arrangeConstraints>KEEP_SIZE</arrangeConstraints> | ||
2737 | <arrangeConstraints>KEEP_RATIO</arrangeConstraints> | ||
2738 | <ownedStyle xmi:type="diagram:FlatContainerStyle" uid="_d1xxt8BeEe6Mo_-4--GvQg" borderSize="1" borderSizeComputationExpression="1" backgroundStyle="Liquid" foregroundColor="255,252,216"> | ||
2739 | <description xmi:type="style:FlatContainerStyleDescription" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@containerMappings[name='EC%20EClass']/@style"/> | ||
2740 | </ownedStyle> | ||
2741 | <actualMapping xmi:type="description_1:ContainerMapping" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@containerMappings[name='EC%20EClass']"/> | ||
2742 | <ownedElements xmi:type="diagram:DNodeListElement" uid="_dTNQIMBeEe6Mo_-4--GvQg" name="alias : EString" tooltipText=""> | ||
2743 | <target xmi:type="ecore:EAttribute" href="src/main/resources/model/problem.ecore#//ImportStatement/alias"/> | ||
2744 | <semanticElements xmi:type="ecore:EAttribute" href="src/main/resources/model/problem.ecore#//ImportStatement/alias"/> | ||
2745 | <ownedStyle xmi:type="diagram:BundledImage" uid="_d1y_0sBeEe6Mo_-4--GvQg" labelAlignment="LEFT"> | ||
2746 | <description xmi:type="style:BundledImageDescription" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@containerMappings[name='EC%20EClass']/@subNodeMappings[name='EC%20EAttribute']/@style"/> | ||
2747 | </ownedStyle> | ||
2748 | <actualMapping xmi:type="description_1:NodeMapping" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@containerMappings[name='EC%20EClass']/@subNodeMappings[name='EC%20EAttribute']"/> | ||
2749 | </ownedElements> | ||
2750 | </ownedDiagramElements> | ||
2751 | <ownedDiagramElements xmi:type="diagram:DEdge" uid="_UU0Y5cBeEe6Mo_-4--GvQg" sourceNode="_GTZsgMBeEe6Mo_-4--GvQg" targetNode="_e7ydoKA9EeuqkpDnuik1sg"> | ||
2752 | <target xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//ImportStatement"/> | ||
2753 | <semanticElements xmi:type="ecore:EClass" href="src/main/resources/model/problem.ecore#//ImportStatement"/> | ||
2754 | <ownedStyle xmi:type="diagram:EdgeStyle" uid="_d134gMBeEe6Mo_-4--GvQg" lineStyle="dash" targetArrow="InputClosedArrow" routingStyle="tree"> | ||
2755 | <description xmi:type="style:EdgeStyleDescription" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@edgeMappings[name='EC%20ESupertypes']/@conditionnalStyles.0/@style"/> | ||
2756 | <beginLabelStyle xmi:type="diagram:BeginLabelStyle" uid="_d134gcBeEe6Mo_-4--GvQg" showIcon="false"> | ||
2757 | <labelFormat>italic</labelFormat> | ||
2758 | </beginLabelStyle> | ||
2759 | <centerLabelStyle xmi:type="diagram:CenterLabelStyle" uid="_d134gsBeEe6Mo_-4--GvQg" showIcon="false"/> | ||
2760 | </ownedStyle> | ||
2761 | <actualMapping xmi:type="description_1:EdgeMapping" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@edgeMappings[name='EC%20ESupertypes']"/> | ||
2762 | </ownedDiagramElements> | ||
2763 | <ownedDiagramElements xmi:type="diagram:DEdge" uid="_bYOKL8BeEe6Mo_-4--GvQg" name="[0..1] importedModule" sourceNode="_GTZsgMBeEe6Mo_-4--GvQg" targetNode="_D05iIKA4EeuqkpDnuik1sg"> | ||
2764 | <target xmi:type="ecore:EReference" href="src/main/resources/model/problem.ecore#//ImportStatement/importedModule"/> | ||
2765 | <semanticElements xmi:type="ecore:EReference" href="src/main/resources/model/problem.ecore#//ImportStatement/importedModule"/> | ||
2766 | <ownedStyle xmi:type="diagram:EdgeStyle" uid="_bYOKMMBeEe6Mo_-4--GvQg" routingStyle="manhattan" strokeColor="0,0,0"> | ||
2767 | <description xmi:type="style:EdgeStyleDescription" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@edgeMappings[name='EC_EReference']/@style"/> | ||
2768 | <centerLabelStyle xmi:type="diagram:CenterLabelStyle" uid="_bYOKMsBeEe6Mo_-4--GvQg" showIcon="false"/> | ||
2769 | <endLabelStyle xmi:type="diagram:EndLabelStyle" uid="_bYOKMcBeEe6Mo_-4--GvQg" labelSize="6" showIcon="false" labelColor="39,76,114"/> | ||
2770 | </ownedStyle> | ||
2771 | <actualMapping xmi:type="description_1:EdgeMapping" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer/@edgeMappings[name='EC_EReference']"/> | ||
2772 | </ownedDiagramElements> | ||
2687 | <description xmi:type="description_1:DiagramDescription" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']"/> | 2773 | <description xmi:type="description_1:DiagramDescription" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']"/> |
2688 | <filterVariableHistory xmi:type="diagram:FilterVariableHistory" uid="_CsWlsKA4EeuqkpDnuik1sg"/> | 2774 | <filterVariableHistory xmi:type="diagram:FilterVariableHistory" uid="_CsWlsKA4EeuqkpDnuik1sg"/> |
2689 | <activatedLayers xmi:type="description_1:Layer" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer"/> | 2775 | <activatedLayers xmi:type="description_1:Layer" href="platform:/plugin/org.eclipse.emf.ecoretools.design/description/ecore.odesign#//@ownedViewpoints[name='Design']/@ownedRepresentations[name='Entities']/@defaultLayer"/> |
diff --git a/subprojects/language-model/problem.aird.license b/subprojects/language-model/problem.aird.license index e5db6ccd..a73a3364 100644 --- a/subprojects/language-model/problem.aird.license +++ b/subprojects/language-model/problem.aird.license | |||
@@ -1,3 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 1 | SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
2 | 2 | ||
3 | SPDX-License-Identifier: EPL-2.0 | 3 | SPDX-License-Identifier: EPL-2.0 |
diff --git a/subprojects/language-model/src/main/resources/model/problem.ecore b/subprojects/language-model/src/main/resources/model/problem.ecore index aa05a2fe..f7c85290 100644 --- a/subprojects/language-model/src/main/resources/model/problem.ecore +++ b/subprojects/language-model/src/main/resources/model/problem.ecore | |||
@@ -270,4 +270,8 @@ | |||
270 | <eLiterals name="ATOM" value="1"/> | 270 | <eLiterals name="ATOM" value="1"/> |
271 | <eLiterals name="MULTI" value="2"/> | 271 | <eLiterals name="MULTI" value="2"/> |
272 | </eClassifiers> | 272 | </eClassifiers> |
273 | <eClassifiers xsi:type="ecore:EClass" name="ImportStatement" eSuperTypes="#//Statement"> | ||
274 | <eStructuralFeatures xsi:type="ecore:EReference" name="importedModule" eType="#//Problem"/> | ||
275 | <eStructuralFeatures xsi:type="ecore:EAttribute" name="alias" eType="ecore:EDataType http://www.eclipse.org/emf/2002/Ecore#//EString"/> | ||
276 | </eClassifiers> | ||
273 | </ecore:EPackage> | 277 | </ecore:EPackage> |
diff --git a/subprojects/language-model/src/main/resources/model/problem.ecore.license b/subprojects/language-model/src/main/resources/model/problem.ecore.license index e5db6ccd..a73a3364 100644 --- a/subprojects/language-model/src/main/resources/model/problem.ecore.license +++ b/subprojects/language-model/src/main/resources/model/problem.ecore.license | |||
@@ -1,3 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 1 | SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
2 | 2 | ||
3 | SPDX-License-Identifier: EPL-2.0 | 3 | SPDX-License-Identifier: EPL-2.0 |
diff --git a/subprojects/language-model/src/main/resources/model/problem.genmodel b/subprojects/language-model/src/main/resources/model/problem.genmodel index be8b62eb..85cd802b 100644 --- a/subprojects/language-model/src/main/resources/model/problem.genmodel +++ b/subprojects/language-model/src/main/resources/model/problem.genmodel | |||
@@ -238,5 +238,9 @@ | |||
238 | <genClasses ecoreClass="problem.ecore#//LogicConstant"> | 238 | <genClasses ecoreClass="problem.ecore#//LogicConstant"> |
239 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute problem.ecore#//LogicConstant/logicValue"/> | 239 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute problem.ecore#//LogicConstant/logicValue"/> |
240 | </genClasses> | 240 | </genClasses> |
241 | <genClasses ecoreClass="problem.ecore#//ImportStatement"> | ||
242 | <genFeatures notify="false" createChild="false" propertySortChoices="true" ecoreFeature="ecore:EReference problem.ecore#//ImportStatement/importedModule"/> | ||
243 | <genFeatures createChild="false" ecoreFeature="ecore:EAttribute problem.ecore#//ImportStatement/alias"/> | ||
244 | </genClasses> | ||
241 | </genPackages> | 245 | </genPackages> |
242 | </genmodel:GenModel> | 246 | </genmodel:GenModel> |
diff --git a/subprojects/language-model/src/main/resources/model/problem.genmodel.license b/subprojects/language-model/src/main/resources/model/problem.genmodel.license index e5db6ccd..a73a3364 100644 --- a/subprojects/language-model/src/main/resources/model/problem.genmodel.license +++ b/subprojects/language-model/src/main/resources/model/problem.genmodel.license | |||
@@ -1,3 +1,3 @@ | |||
1 | SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 1 | SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
2 | 2 | ||
3 | SPDX-License-Identifier: EPL-2.0 | 3 | SPDX-License-Identifier: EPL-2.0 |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java index b462fd70..7c649232 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ModelInitializer.java | |||
@@ -247,7 +247,7 @@ public class ModelInitializer { | |||
247 | } | 247 | } |
248 | 248 | ||
249 | private String getName(Relation relation) { | 249 | private String getName(Relation relation) { |
250 | return semanticsUtils.getName(relation).orElseGet(() -> "::" + relationInfoMap.size()); | 250 | return semanticsUtils.getNameWithoutRootPrefix(relation).orElseGet(() -> "::" + relationInfoMap.size()); |
251 | } | 251 | } |
252 | 252 | ||
253 | private void collectMetamodel() { | 253 | private void collectMetamodel() { |
@@ -659,7 +659,7 @@ public class ModelInitializer { | |||
659 | var variableOrNode = variableOrNodeExpr.getVariableOrNode(); | 659 | var variableOrNode = variableOrNodeExpr.getVariableOrNode(); |
660 | if (variableOrNode instanceof Node node) { | 660 | if (variableOrNode instanceof Node node) { |
661 | int nodeId = getNodeId(node); | 661 | int nodeId = getNodeId(node); |
662 | var tempVariable = Variable.of(semanticsUtils.getName(node).orElse("_" + nodeId)); | 662 | var tempVariable = Variable.of(semanticsUtils.getNameWithoutRootPrefix(node).orElse("_" + nodeId)); |
663 | literals.add(new ConstantLiteral(tempVariable, nodeId)); | 663 | literals.add(new ConstantLiteral(tempVariable, nodeId)); |
664 | argumentList.add(tempVariable); | 664 | argumentList.add(tempVariable); |
665 | } else if (variableOrNode instanceof tools.refinery.language.model.problem.Variable problemVariable) { | 665 | } else if (variableOrNode instanceof tools.refinery.language.model.problem.Variable problemVariable) { |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java index f686e980..aef0fd89 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/ProblemTraceImpl.java | |||
@@ -79,7 +79,7 @@ class ProblemTraceImpl implements ProblemTrace { | |||
79 | try { | 79 | try { |
80 | return nodeTrace.getOrThrow(node); | 80 | return nodeTrace.getOrThrow(node); |
81 | } catch (IllegalStateException e) { | 81 | } catch (IllegalStateException e) { |
82 | var qualifiedName = semanticsUtils.getName(node); | 82 | var qualifiedName = semanticsUtils.getNameWithoutRootPrefix(node); |
83 | throw new TracedException(node, "No node ID for " + qualifiedName, e); | 83 | throw new TracedException(node, "No node ID for " + qualifiedName, e); |
84 | } | 84 | } |
85 | } | 85 | } |
@@ -144,7 +144,7 @@ class ProblemTraceImpl implements ProblemTrace { | |||
144 | public PartialRelation getPartialRelation(Relation relation) { | 144 | public PartialRelation getPartialRelation(Relation relation) { |
145 | var partialRelation = mutableRelationTrace.get(relation); | 145 | var partialRelation = mutableRelationTrace.get(relation); |
146 | if (partialRelation == null) { | 146 | if (partialRelation == null) { |
147 | var qualifiedName = semanticsUtils.getName(relation); | 147 | var qualifiedName = semanticsUtils.getNameWithoutRootPrefix(relation); |
148 | throw new TracedException(relation, "No partial relation for " + qualifiedName); | 148 | throw new TracedException(relation, "No partial relation for " + qualifiedName); |
149 | } | 149 | } |
150 | return partialRelation; | 150 | return partialRelation; |
diff --git a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java index b72ba697..110295b2 100644 --- a/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java +++ b/subprojects/language-semantics/src/main/java/tools/refinery/language/semantics/SemanticsUtils.java | |||
@@ -7,6 +7,7 @@ package tools.refinery.language.semantics; | |||
7 | 7 | ||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import com.google.inject.Singleton; | 9 | import com.google.inject.Singleton; |
10 | import com.google.inject.name.Named; | ||
10 | import org.eclipse.emf.ecore.EObject; | 11 | import org.eclipse.emf.ecore.EObject; |
11 | import org.eclipse.emf.ecore.util.EcoreUtil; | 12 | import org.eclipse.emf.ecore.util.EcoreUtil; |
12 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | 13 | import org.eclipse.xtext.naming.IQualifiedNameConverter; |
@@ -16,6 +17,7 @@ import org.eclipse.xtext.scoping.IScope; | |||
16 | import org.jetbrains.annotations.NotNull; | 17 | import org.jetbrains.annotations.NotNull; |
17 | import org.jetbrains.annotations.Nullable; | 18 | import org.jetbrains.annotations.Nullable; |
18 | import tools.refinery.language.model.problem.Problem; | 19 | import tools.refinery.language.model.problem.Problem; |
20 | import tools.refinery.language.naming.ProblemQualifiedNameProvider; | ||
19 | 21 | ||
20 | import java.util.Optional; | 22 | import java.util.Optional; |
21 | 23 | ||
@@ -25,10 +27,14 @@ public class SemanticsUtils { | |||
25 | private IQualifiedNameProvider qualifiedNameProvider; | 27 | private IQualifiedNameProvider qualifiedNameProvider; |
26 | 28 | ||
27 | @Inject | 29 | @Inject |
30 | @Named(ProblemQualifiedNameProvider.NAMED_DELEGATE) | ||
31 | private IQualifiedNameProvider delegateQualifiedNameProvider; | ||
32 | |||
33 | @Inject | ||
28 | private IQualifiedNameConverter qualifiedNameConverter; | 34 | private IQualifiedNameConverter qualifiedNameConverter; |
29 | 35 | ||
30 | public Optional<String> getName(EObject eObject) { | 36 | public Optional<String> getNameWithoutRootPrefix(EObject eObject) { |
31 | var qualifiedName = qualifiedNameProvider.getFullyQualifiedName(eObject); | 37 | var qualifiedName = delegateQualifiedNameProvider.getFullyQualifiedName(eObject); |
32 | if (qualifiedName == null) { | 38 | if (qualifiedName == null) { |
33 | return Optional.empty(); | 39 | return Optional.empty(); |
34 | } | 40 | } |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java index efe04592..ff811033 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/PartialInterpretation2Json.java | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2023-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -32,7 +32,7 @@ public class PartialInterpretation2Json { | |||
32 | var relation = entry.getKey(); | 32 | var relation = entry.getKey(); |
33 | var partialSymbol = entry.getValue(); | 33 | var partialSymbol = entry.getValue(); |
34 | var tuples = getTuplesJson(facade, partialSymbol); | 34 | var tuples = getTuplesJson(facade, partialSymbol); |
35 | var name = semanticsUtils.getName(relation).orElse(partialSymbol.name()); | 35 | var name = semanticsUtils.getNameWithoutRootPrefix(relation).orElse(partialSymbol.name()); |
36 | json.add(name, tuples); | 36 | json.add(name, tuples); |
37 | cancellationToken.checkCancelled(); | 37 | cancellationToken.checkCancelled(); |
38 | } | 38 | } |
diff --git a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java index 1f49b0d0..1858fc87 100644 --- a/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java +++ b/subprojects/language-web/src/main/java/tools/refinery/language/web/semantics/metadata/MetadataCreator.java | |||
@@ -7,6 +7,7 @@ package tools.refinery.language.web.semantics.metadata; | |||
7 | 7 | ||
8 | import com.google.inject.Inject; | 8 | import com.google.inject.Inject; |
9 | import com.google.inject.Provider; | 9 | import com.google.inject.Provider; |
10 | import com.google.inject.name.Named; | ||
10 | import org.eclipse.emf.ecore.EObject; | 11 | import org.eclipse.emf.ecore.EObject; |
11 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | 12 | import org.eclipse.xtext.naming.IQualifiedNameConverter; |
12 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | 13 | import org.eclipse.xtext.naming.IQualifiedNameProvider; |
@@ -14,6 +15,7 @@ import org.eclipse.xtext.naming.QualifiedName; | |||
14 | import org.eclipse.xtext.scoping.IScope; | 15 | import org.eclipse.xtext.scoping.IScope; |
15 | import org.eclipse.xtext.scoping.IScopeProvider; | 16 | import org.eclipse.xtext.scoping.IScopeProvider; |
16 | import tools.refinery.language.model.problem.*; | 17 | import tools.refinery.language.model.problem.*; |
18 | import tools.refinery.language.naming.ProblemQualifiedNameProvider; | ||
17 | import tools.refinery.language.semantics.ProblemTrace; | 19 | import tools.refinery.language.semantics.ProblemTrace; |
18 | import tools.refinery.language.semantics.TracedException; | 20 | import tools.refinery.language.semantics.TracedException; |
19 | import tools.refinery.language.utils.ProblemUtil; | 21 | import tools.refinery.language.utils.ProblemUtil; |
@@ -32,6 +34,7 @@ public class MetadataCreator { | |||
32 | private IScopeProvider scopeProvider; | 34 | private IScopeProvider scopeProvider; |
33 | 35 | ||
34 | @Inject | 36 | @Inject |
37 | @Named(ProblemQualifiedNameProvider.NAMED_DELEGATE) | ||
35 | private IQualifiedNameProvider qualifiedNameProvider; | 38 | private IQualifiedNameProvider qualifiedNameProvider; |
36 | 39 | ||
37 | @Inject | 40 | @Inject |
@@ -122,17 +125,13 @@ public class MetadataCreator { | |||
122 | if (ProblemUtil.isBuiltIn(relation) && !ProblemUtil.isError(relation)) { | 125 | if (ProblemUtil.isBuiltIn(relation) && !ProblemUtil.isError(relation)) { |
123 | return getBuiltInDetail(); | 126 | return getBuiltInDetail(); |
124 | } | 127 | } |
125 | if (relation instanceof ClassDeclaration classDeclaration) { | 128 | return switch (relation) { |
126 | return getClassDetail(classDeclaration); | 129 | case ClassDeclaration classDeclaration -> getClassDetail(classDeclaration); |
127 | } else if (relation instanceof ReferenceDeclaration) { | 130 | case ReferenceDeclaration ignored -> getReferenceDetail(partialRelation); |
128 | return getReferenceDetail(partialRelation); | 131 | case EnumDeclaration ignored -> getEnumDetail(); |
129 | } else if (relation instanceof EnumDeclaration) { | 132 | case PredicateDefinition predicateDefinition -> getPredicateDetail(predicateDefinition); |
130 | return getEnumDetail(); | 133 | default -> throw new TracedException(relation, "Unknown relation"); |
131 | } else if (relation instanceof PredicateDefinition predicateDefinition) { | 134 | }; |
132 | return getPredicateDetail(predicateDefinition); | ||
133 | } else { | ||
134 | throw new TracedException(relation, "Unknown relation"); | ||
135 | } | ||
136 | } | 135 | } |
137 | 136 | ||
138 | private RelationDetail getBuiltInDetail() { | 137 | private RelationDetail getBuiltInDetail() { |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext index 4ce3fae1..f0d6c38c 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext +++ b/subprojects/language/src/main/java/tools/refinery/language/Problem.xtext | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -16,10 +16,13 @@ enum ModuleKind: | |||
16 | PROBLEM="problem" | MODULE="module"; | 16 | PROBLEM="problem" | MODULE="module"; |
17 | 17 | ||
18 | Statement: | 18 | Statement: |
19 | Assertion | ClassDeclaration | EnumDeclaration | | 19 | ImportStatement | Assertion | ClassDeclaration | EnumDeclaration | |
20 | PredicateDefinition | /* FunctionDefinition | RuleDefinition | */ | 20 | PredicateDefinition | /* FunctionDefinition | RuleDefinition | */ |
21 | ScopeDeclaration | NodeDeclaration; | 21 | ScopeDeclaration | NodeDeclaration; |
22 | 22 | ||
23 | ImportStatement: | ||
24 | "import" importedModule=[Problem|QualifiedName] ("as" alias=ID)? "."; | ||
25 | |||
23 | ClassDeclaration: | 26 | ClassDeclaration: |
24 | abstract?="abstract"? "class" | 27 | abstract?="abstract"? "class" |
25 | name=Identifier | 28 | name=Identifier |
@@ -266,10 +269,10 @@ UpperBound returns ecore::EInt: | |||
266 | INT | "*"; | 269 | INT | "*"; |
267 | 270 | ||
268 | QualifiedName hidden(): | 271 | QualifiedName hidden(): |
269 | Identifier ("::" Identifier)*; | 272 | "::"? Identifier (QUALIFIED_NAME_SEPARATOR Identifier)*; |
270 | 273 | ||
271 | NonContainmentQualifiedName hidden(): | 274 | NonContainmentQualifiedName hidden(): |
272 | NonContainmentIdentifier ("::" Identifier)*; | 275 | (NonContainmentIdentifier | "::" Identifier) (QUALIFIED_NAME_SEPARATOR Identifier)*; |
273 | 276 | ||
274 | Identifier: | 277 | Identifier: |
275 | NonContainmentIdentifier | "contains" | "container"; | 278 | NonContainmentIdentifier | "contains" | "container"; |
@@ -284,6 +287,9 @@ Real returns ecore::EDouble: | |||
284 | terminal TRANSITIVE_CLOSURE: | 287 | terminal TRANSITIVE_CLOSURE: |
285 | "synthetic:TRANSITIVE_CLOSURE"; | 288 | "synthetic:TRANSITIVE_CLOSURE"; |
286 | 289 | ||
290 | terminal QUALIFIED_NAME_SEPARATOR: | ||
291 | "synthetic::QUALIFIED_NAME_SEPARATOR"; | ||
292 | |||
287 | @Override | 293 | @Override |
288 | terminal ID: | 294 | terminal ID: |
289 | ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*; | 295 | ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java b/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java index 00dd3de3..19816da4 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java +++ b/subprojects/language/src/main/java/tools/refinery/language/ProblemRuntimeModule.java | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -14,6 +14,7 @@ import com.google.inject.name.Names; | |||
14 | import org.eclipse.xtext.conversion.IValueConverterService; | 14 | import org.eclipse.xtext.conversion.IValueConverterService; |
15 | import org.eclipse.xtext.linking.ILinkingService; | 15 | import org.eclipse.xtext.linking.ILinkingService; |
16 | import org.eclipse.xtext.naming.IQualifiedNameConverter; | 16 | import org.eclipse.xtext.naming.IQualifiedNameConverter; |
17 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | ||
17 | import org.eclipse.xtext.parser.IParser; | 18 | import org.eclipse.xtext.parser.IParser; |
18 | import org.eclipse.xtext.resource.*; | 19 | import org.eclipse.xtext.resource.*; |
19 | import org.eclipse.xtext.scoping.IGlobalScopeProvider; | 20 | import org.eclipse.xtext.scoping.IGlobalScopeProvider; |
@@ -26,12 +27,11 @@ import org.eclipse.xtext.validation.IResourceValidator; | |||
26 | import org.eclipse.xtext.xbase.annotations.validation.DerivedStateAwareResourceValidator; | 27 | import org.eclipse.xtext.xbase.annotations.validation.DerivedStateAwareResourceValidator; |
27 | import tools.refinery.language.conversion.ProblemValueConverterService; | 28 | import tools.refinery.language.conversion.ProblemValueConverterService; |
28 | import tools.refinery.language.linking.ProblemLinkingService; | 29 | import tools.refinery.language.linking.ProblemLinkingService; |
30 | import tools.refinery.language.naming.ProblemDelegateQualifiedNameProvider; | ||
29 | import tools.refinery.language.naming.ProblemQualifiedNameConverter; | 31 | import tools.refinery.language.naming.ProblemQualifiedNameConverter; |
32 | import tools.refinery.language.naming.ProblemQualifiedNameProvider; | ||
30 | import tools.refinery.language.parser.antlr.TokenSourceInjectingProblemParser; | 33 | import tools.refinery.language.parser.antlr.TokenSourceInjectingProblemParser; |
31 | import tools.refinery.language.resource.ProblemDerivedStateComputer; | 34 | import tools.refinery.language.resource.*; |
32 | import tools.refinery.language.resource.ProblemLocationInFileProvider; | ||
33 | import tools.refinery.language.resource.ProblemResource; | ||
34 | import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; | ||
35 | import tools.refinery.language.scoping.ProblemGlobalScopeProvider; | 35 | import tools.refinery.language.scoping.ProblemGlobalScopeProvider; |
36 | import tools.refinery.language.scoping.ProblemLocalScopeProvider; | 36 | import tools.refinery.language.scoping.ProblemLocalScopeProvider; |
37 | import tools.refinery.language.serializer.PreferShortAssertionsProblemSemanticSequencer; | 37 | import tools.refinery.language.serializer.PreferShortAssertionsProblemSemanticSequencer; |
@@ -54,6 +54,17 @@ public class ProblemRuntimeModule extends AbstractProblemRuntimeModule { | |||
54 | return ProblemQualifiedNameConverter.class; | 54 | return ProblemQualifiedNameConverter.class; |
55 | } | 55 | } |
56 | 56 | ||
57 | public void configureIQualifiedNameProviderDelegate(Binder binder) { | ||
58 | binder.bind(IQualifiedNameProvider.class) | ||
59 | .annotatedWith(Names.named(ProblemQualifiedNameProvider.NAMED_DELEGATE)) | ||
60 | .to(ProblemDelegateQualifiedNameProvider.class); | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public Class<? extends IQualifiedNameProvider> bindIQualifiedNameProvider() { | ||
65 | return ProblemQualifiedNameProvider.class; | ||
66 | } | ||
67 | |||
57 | public Class<? extends IDefaultResourceDescriptionStrategy> bindIDefaultResourceDescriptionStrategy() { | 68 | public Class<? extends IDefaultResourceDescriptionStrategy> bindIDefaultResourceDescriptionStrategy() { |
58 | return ProblemResourceDescriptionStrategy.class; | 69 | return ProblemResourceDescriptionStrategy.class; |
59 | } | 70 | } |
@@ -87,7 +98,7 @@ public class ProblemRuntimeModule extends AbstractProblemRuntimeModule { | |||
87 | // Method name follows Xtext convention. | 98 | // Method name follows Xtext convention. |
88 | @SuppressWarnings("squid:S100") | 99 | @SuppressWarnings("squid:S100") |
89 | public Class<? extends IResourceDescription.Manager> bindIResourceDescription$Manager() { | 100 | public Class<? extends IResourceDescription.Manager> bindIResourceDescription$Manager() { |
90 | return DerivedStateAwareResourceDescriptionManager.class; | 101 | return ProblemResourceDescriptionManager.class; |
91 | } | 102 | } |
92 | 103 | ||
93 | public Class<? extends IResourceValidator> bindIResourceValidator() { | 104 | public Class<? extends IResourceValidator> bindIResourceValidator() { |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/naming/NamingUtil.java b/subprojects/language/src/main/java/tools/refinery/language/naming/NamingUtil.java index 1647d4e7..feae5ebb 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/naming/NamingUtil.java +++ b/subprojects/language/src/main/java/tools/refinery/language/naming/NamingUtil.java | |||
@@ -1,21 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.naming; | 6 | package tools.refinery.language.naming; |
7 | 7 | ||
8 | import org.eclipse.xtext.naming.QualifiedName; | ||
9 | |||
8 | import java.util.regex.Pattern; | 10 | import java.util.regex.Pattern; |
9 | 11 | ||
10 | public final class NamingUtil { | 12 | public final class NamingUtil { |
11 | private static final String SINGLETON_VARIABLE_PREFIX = "_"; | 13 | private static final String SINGLETON_VARIABLE_PREFIX = "_"; |
12 | 14 | public static final QualifiedName ROOT_NAME = QualifiedName.create(""); | |
13 | private static final Pattern ID_REGEX = Pattern.compile("[_a-zA-Z][_0-9a-zA-Z]*"); | 15 | |
16 | private static final Pattern ID_REGEX = Pattern.compile("[_a-zA-Z]\\w*"); | ||
14 | 17 | ||
15 | private NamingUtil() { | 18 | private NamingUtil() { |
16 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); | 19 | throw new IllegalStateException("This is a static utility class and should not be instantiated directly"); |
17 | } | 20 | } |
18 | 21 | ||
19 | public static boolean isNullOrEmpty(String name) { | 22 | public static boolean isNullOrEmpty(String name) { |
20 | return name == null || name.isEmpty(); | 23 | return name == null || name.isEmpty(); |
21 | } | 24 | } |
@@ -23,8 +26,28 @@ public final class NamingUtil { | |||
23 | public static boolean isSingletonVariableName(String name) { | 26 | public static boolean isSingletonVariableName(String name) { |
24 | return name != null && name.startsWith(SINGLETON_VARIABLE_PREFIX); | 27 | return name != null && name.startsWith(SINGLETON_VARIABLE_PREFIX); |
25 | } | 28 | } |
26 | 29 | ||
30 | // This method name only makes sense if it checks for the positive case. | ||
31 | @SuppressWarnings("BooleanMethodIsAlwaysInverted") | ||
27 | public static boolean isValidId(String name) { | 32 | public static boolean isValidId(String name) { |
28 | return name != null && ID_REGEX.matcher(name).matches(); | 33 | return name != null && ID_REGEX.matcher(name).matches(); |
29 | } | 34 | } |
35 | |||
36 | public static boolean isFullyQualified(QualifiedName name) { | ||
37 | return name.startsWith(ROOT_NAME); | ||
38 | } | ||
39 | |||
40 | public static QualifiedName stripRootPrefix(QualifiedName name) { | ||
41 | if (name == null) { | ||
42 | return null; | ||
43 | } | ||
44 | return isFullyQualified(name) ? name.skipFirst(ROOT_NAME.getSegmentCount()) : name; | ||
45 | } | ||
46 | |||
47 | public static QualifiedName addRootPrefix(QualifiedName name) { | ||
48 | if (name == null) { | ||
49 | return null; | ||
50 | } | ||
51 | return isFullyQualified(name) ? name : ROOT_NAME.append(name); | ||
52 | } | ||
30 | } | 53 | } |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemDelegateQualifiedNameProvider.java b/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemDelegateQualifiedNameProvider.java new file mode 100644 index 00000000..1e78cee1 --- /dev/null +++ b/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemDelegateQualifiedNameProvider.java | |||
@@ -0,0 +1,18 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.naming; | ||
7 | |||
8 | import org.eclipse.xtext.naming.DefaultDeclarativeQualifiedNameProvider; | ||
9 | import org.eclipse.xtext.naming.QualifiedName; | ||
10 | import tools.refinery.language.model.problem.Problem; | ||
11 | |||
12 | public class ProblemDelegateQualifiedNameProvider extends DefaultDeclarativeQualifiedNameProvider { | ||
13 | protected QualifiedName qualifiedName(Problem ele) { | ||
14 | var qualifiedName = computeFullyQualifiedNameFromNameAttribute(ele); | ||
15 | // Strip the root prefix even if explicitly provided. | ||
16 | return NamingUtil.stripRootPrefix(qualifiedName); | ||
17 | } | ||
18 | } | ||
diff --git a/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameConverter.java b/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameConverter.java index 74b4e208..88a0fe9a 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameConverter.java +++ b/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameConverter.java | |||
@@ -12,7 +12,7 @@ import com.google.inject.Singleton; | |||
12 | @Singleton | 12 | @Singleton |
13 | public class ProblemQualifiedNameConverter extends IQualifiedNameConverter.DefaultImpl { | 13 | public class ProblemQualifiedNameConverter extends IQualifiedNameConverter.DefaultImpl { |
14 | public static final String DELIMITER = "::"; | 14 | public static final String DELIMITER = "::"; |
15 | 15 | ||
16 | @Override | 16 | @Override |
17 | public String getDelimiter() { | 17 | public String getDelimiter() { |
18 | return DELIMITER; | 18 | return DELIMITER; |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameProvider.java b/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameProvider.java new file mode 100644 index 00000000..5b682058 --- /dev/null +++ b/subprojects/language/src/main/java/tools/refinery/language/naming/ProblemQualifiedNameProvider.java | |||
@@ -0,0 +1,41 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.naming; | ||
7 | |||
8 | import com.google.inject.Inject; | ||
9 | import com.google.inject.name.Named; | ||
10 | import org.eclipse.emf.ecore.EObject; | ||
11 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | ||
12 | import org.eclipse.xtext.naming.QualifiedName; | ||
13 | import org.eclipse.xtext.util.IResourceScopeCache; | ||
14 | import org.eclipse.xtext.util.Tuples; | ||
15 | import tools.refinery.language.resource.ProblemResourceDescriptionStrategy; | ||
16 | |||
17 | public class ProblemQualifiedNameProvider extends IQualifiedNameProvider.AbstractImpl { | ||
18 | private static final String PREFIX = "tools.refinery.language.naming.ProblemQualifiedNameProvider."; | ||
19 | public static final String NAMED_DELEGATE = PREFIX + "NAMED_DELEGATE"; | ||
20 | public static final String CACHE_KEY = PREFIX + "CACHE_KEY"; | ||
21 | |||
22 | @Inject | ||
23 | @Named(NAMED_DELEGATE) | ||
24 | private IQualifiedNameProvider delegate; | ||
25 | |||
26 | @Inject | ||
27 | private IResourceScopeCache cache = IResourceScopeCache.NullImpl.INSTANCE; | ||
28 | |||
29 | @Override | ||
30 | public QualifiedName getFullyQualifiedName(EObject obj) { | ||
31 | return cache.get(Tuples.pair(obj, CACHE_KEY), obj.eResource(), () -> computeFullyQualifiedName(obj)); | ||
32 | } | ||
33 | |||
34 | public QualifiedName computeFullyQualifiedName(EObject obj) { | ||
35 | var qualifiedName = delegate.getFullyQualifiedName(obj); | ||
36 | if (qualifiedName != null && ProblemResourceDescriptionStrategy.shouldExport(obj)) { | ||
37 | return NamingUtil.addRootPrefix(qualifiedName); | ||
38 | } | ||
39 | return qualifiedName; | ||
40 | } | ||
41 | } | ||
diff --git a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/IdentifierTokenProvider.java b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/IdentifierTokenProvider.java index 306a86fc..0e19357f 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/IdentifierTokenProvider.java +++ b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/IdentifierTokenProvider.java | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -59,7 +59,7 @@ public class IdentifierTokenProvider { | |||
59 | 59 | ||
60 | private void createValueToTokenIdMap() { | 60 | private void createValueToTokenIdMap() { |
61 | var tokenIdToValueMap = tokenDefProvider.getTokenDefMap(); | 61 | var tokenIdToValueMap = tokenDefProvider.getTokenDefMap(); |
62 | valueToTokenIdMap = new HashMap<>(tokenIdToValueMap.size()); | 62 | valueToTokenIdMap = HashMap.newHashMap(tokenIdToValueMap.size()); |
63 | for (var entry : tokenIdToValueMap.entrySet()) { | 63 | for (var entry : tokenIdToValueMap.entrySet()) { |
64 | valueToTokenIdMap.put(entry.getValue(), entry.getKey()); | 64 | valueToTokenIdMap.put(entry.getValue(), entry.getKey()); |
65 | } | 65 | } |
@@ -74,17 +74,16 @@ public class IdentifierTokenProvider { | |||
74 | } | 74 | } |
75 | 75 | ||
76 | private void collectIdentifierTokensFromElement(AbstractElement element) { | 76 | private void collectIdentifierTokensFromElement(AbstractElement element) { |
77 | if (element instanceof Alternatives alternatives) { | 77 | switch (element) { |
78 | for (var alternative : alternatives.getElements()) { | 78 | case Alternatives alternatives -> { |
79 | collectIdentifierTokensFromElement(alternative); | 79 | for (var alternative : alternatives.getElements()) { |
80 | } | 80 | collectIdentifierTokensFromElement(alternative); |
81 | } else if (element instanceof RuleCall ruleCall) { | 81 | } |
82 | collectIdentifierTokensFromRule(ruleCall.getRule()); | 82 | } |
83 | } else if (element instanceof Keyword keyword) { | 83 | case RuleCall ruleCall -> collectIdentifierTokensFromRule(ruleCall.getRule()); |
84 | collectToken("'" + keyword.getValue() + "'"); | 84 | case Keyword keyword -> collectToken("'" + keyword.getValue() + "'"); |
85 | } else { | 85 | default -> throw new IllegalArgumentException("Unknown Xtext grammar element: " + element); |
86 | throw new IllegalArgumentException("Unknown Xtext grammar element: " + element); | 86 | } |
87 | } | ||
88 | } | 87 | } |
89 | 88 | ||
90 | private void collectToken(String value) { | 89 | private void collectToken(String value) { |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/ProblemTokenSource.java b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/ProblemTokenSource.java index 5b91a6cc..487e4ceb 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/ProblemTokenSource.java +++ b/subprojects/language/src/main/java/tools/refinery/language/parser/antlr/ProblemTokenSource.java | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
@@ -28,6 +28,8 @@ public class ProblemTokenSource implements TokenSource { | |||
28 | 28 | ||
29 | private boolean seenId; | 29 | private boolean seenId; |
30 | 30 | ||
31 | private boolean lastVisible; | ||
32 | |||
31 | public ProblemTokenSource(TokenSource delegate) { | 33 | public ProblemTokenSource(TokenSource delegate) { |
32 | this.delegate = delegate; | 34 | this.delegate = delegate; |
33 | } | 35 | } |
@@ -47,18 +49,18 @@ public class ProblemTokenSource implements TokenSource { | |||
47 | 49 | ||
48 | @Override | 50 | @Override |
49 | public Token nextToken() { | 51 | public Token nextToken() { |
50 | if (!buffer.isEmpty()) { | 52 | boolean fromStream = buffer.isEmpty(); |
51 | return buffer.removeFirst(); | 53 | var token = fromStream ? delegate.nextToken() : buffer.removeFirst(); |
52 | } | 54 | if (seenId) { |
53 | var token = delegate.nextToken(); | 55 | if (fromStream && isPlusOrTransitiveClosure(token) && peekForTransitiveClosure()) { |
54 | if (isIdentifier(token)) { | ||
55 | seenId = true; | ||
56 | } else if (seenId && isPlusOrTransitiveClosure(token)) { | ||
57 | if (peekForTransitiveClosure()) { | ||
58 | token.setType(InternalProblemParser.RULE_TRANSITIVE_CLOSURE); | 56 | token.setType(InternalProblemParser.RULE_TRANSITIVE_CLOSURE); |
57 | } else if (lastVisible && isQualifiedNameSeparator(token)) { | ||
58 | token.setType(InternalProblemParser.RULE_QUALIFIED_NAME_SEPARATOR); | ||
59 | } | 59 | } |
60 | } else if (isVisibleToken(token)) { | 60 | } |
61 | seenId = false; | 61 | lastVisible = isVisibleToken(token); |
62 | if (lastVisible) { | ||
63 | seenId = isIdentifier(token); | ||
62 | } | 64 | } |
63 | return token; | 65 | return token; |
64 | } | 66 | } |
@@ -76,6 +78,10 @@ public class ProblemTokenSource implements TokenSource { | |||
76 | return token.getType() == InternalProblemParser.PlusSign; | 78 | return token.getType() == InternalProblemParser.PlusSign; |
77 | } | 79 | } |
78 | 80 | ||
81 | protected boolean isQualifiedNameSeparator(Token token) { | ||
82 | return token.getType() == InternalProblemParser.ColonColon; | ||
83 | } | ||
84 | |||
79 | protected boolean isVisibleToken(Token token) { | 85 | protected boolean isVisibleToken(Token token) { |
80 | int tokenId = token.getType(); | 86 | int tokenId = token.getType(); |
81 | return tokenId != InternalProblemParser.RULE_WS && tokenId != InternalProblemParser.RULE_SL_COMMENT && | 87 | return tokenId != InternalProblemParser.RULE_WS && tokenId != InternalProblemParser.RULE_SL_COMMENT && |
@@ -87,11 +93,16 @@ public class ProblemTokenSource implements TokenSource { | |||
87 | if (token.getType() != InternalProblemParser.LeftParenthesis) { | 93 | if (token.getType() != InternalProblemParser.LeftParenthesis) { |
88 | return false; | 94 | return false; |
89 | } | 95 | } |
96 | boolean allowFullyQualifiedName = true; | ||
90 | while (true) { | 97 | while (true) { |
91 | token = peekWithSkipWhitespace(); | 98 | token = peekWithSkipWhitespace(); |
99 | if (allowFullyQualifiedName && token.getType() == InternalProblemParser.ColonColon) { | ||
100 | token = peekWithSkipWhitespace(); | ||
101 | } | ||
92 | if (!isIdentifier(token)) { | 102 | if (!isIdentifier(token)) { |
93 | return false; | 103 | return false; |
94 | } | 104 | } |
105 | allowFullyQualifiedName = false; | ||
95 | token = peekWithSkipWhitespace(); | 106 | token = peekWithSkipWhitespace(); |
96 | switch (token.getType()) { | 107 | switch (token.getType()) { |
97 | case InternalProblemParser.Comma: | 108 | case InternalProblemParser.Comma: |
@@ -112,11 +123,6 @@ public class ProblemTokenSource implements TokenSource { | |||
112 | 123 | ||
113 | protected Token peekToken() { | 124 | protected Token peekToken() { |
114 | var token = delegate.nextToken(); | 125 | var token = delegate.nextToken(); |
115 | if (isIdentifier(token)) { | ||
116 | seenId = true; | ||
117 | } else if (isVisibleToken(token)) { | ||
118 | seenId = false; | ||
119 | } | ||
120 | buffer.addLast(token); | 126 | buffer.addLast(token); |
121 | return token; | 127 | return token; |
122 | } | 128 | } |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescription.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescription.java new file mode 100644 index 00000000..498a7c57 --- /dev/null +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescription.java | |||
@@ -0,0 +1,106 @@ | |||
1 | /******************************************************************************* | ||
2 | * Copyright (c) 2009, 2011 itemis AG (http://www.itemis.eu) and others. | ||
3 | * Copyright (c) 2024 The Refinery Authors <https://refinery.tools/> | ||
4 | * This program and the accompanying materials are made available under the | ||
5 | * terms of the Eclipse Public License 2.0 which is available at | ||
6 | * http://www.eclipse.org/legal/epl-2.0. | ||
7 | * SPDX-License-Identifier: EPL-2.0 | ||
8 | *******************************************************************************/ | ||
9 | package tools.refinery.language.resource; | ||
10 | |||
11 | import org.apache.log4j.Logger; | ||
12 | import org.eclipse.emf.common.util.TreeIterator; | ||
13 | import org.eclipse.emf.ecore.EObject; | ||
14 | import org.eclipse.emf.ecore.resource.Resource; | ||
15 | import org.eclipse.emf.ecore.util.EcoreUtil; | ||
16 | import org.eclipse.xtext.resource.IDefaultResourceDescriptionStrategy; | ||
17 | import org.eclipse.xtext.resource.IEObjectDescription; | ||
18 | import org.eclipse.xtext.resource.impl.DefaultResourceDescription; | ||
19 | import org.eclipse.xtext.resource.impl.EObjectDescriptionLookUp; | ||
20 | import org.eclipse.xtext.util.IAcceptor; | ||
21 | import tools.refinery.language.naming.NamingUtil; | ||
22 | |||
23 | import java.io.IOException; | ||
24 | import java.util.*; | ||
25 | |||
26 | /** | ||
27 | * A resource description that takes {@link ProblemResourceDescriptionStrategy#SHADOWING_KEY} into account when | ||
28 | * describing EObjects. | ||
29 | * <p> | ||
30 | * Based on {@link DefaultResourceDescription}. | ||
31 | */ | ||
32 | public class ProblemResourceDescription extends DefaultResourceDescription { | ||
33 | private static final Logger log = Logger.getLogger(ProblemResourceDescription.class); | ||
34 | |||
35 | private final IDefaultResourceDescriptionStrategy strategy; | ||
36 | |||
37 | public ProblemResourceDescription(Resource resource, IDefaultResourceDescriptionStrategy strategy) { | ||
38 | super(resource, strategy); | ||
39 | this.strategy = strategy; | ||
40 | } | ||
41 | |||
42 | /** | ||
43 | * Based on {@link DefaultResourceDescription#computeExportedObjects()}. | ||
44 | * | ||
45 | * @return The computed exported objects, taking shadowing into account. | ||
46 | */ | ||
47 | @Override | ||
48 | protected List<IEObjectDescription> computeExportedObjects() { | ||
49 | if (!getResource().isLoaded()) { | ||
50 | try { | ||
51 | getResource().load(null); | ||
52 | } catch (IOException e) { | ||
53 | log.error(e.getMessage(), e); | ||
54 | return Collections.emptyList(); | ||
55 | } | ||
56 | } | ||
57 | final Map<ProblemResourceDescriptionStrategy.ShadowingKey, List<IEObjectDescription>> nameToDescriptionsMap = | ||
58 | new LinkedHashMap<>(); | ||
59 | IAcceptor<IEObjectDescription> acceptor = eObjectDescription -> { | ||
60 | var key = ProblemResourceDescriptionStrategy.getShadowingKey(eObjectDescription); | ||
61 | var descriptions = nameToDescriptionsMap.computeIfAbsent(key, ignored -> new ArrayList<>()); | ||
62 | descriptions.add(eObjectDescription); | ||
63 | }; | ||
64 | TreeIterator<EObject> allProperContents = EcoreUtil.getAllProperContents(getResource(), false); | ||
65 | while (allProperContents.hasNext()) { | ||
66 | EObject content = allProperContents.next(); | ||
67 | if (!strategy.createEObjectDescriptions(content, acceptor)) { | ||
68 | allProperContents.prune(); | ||
69 | } | ||
70 | } | ||
71 | return omitShadowedNames(nameToDescriptionsMap); | ||
72 | } | ||
73 | |||
74 | private static List<IEObjectDescription> omitShadowedNames( | ||
75 | Map<ProblemResourceDescriptionStrategy.ShadowingKey, List<IEObjectDescription>> nameToDescriptionsMap) { | ||
76 | final List<IEObjectDescription> exportedEObjects = new ArrayList<>(); | ||
77 | for (var entry : nameToDescriptionsMap.entrySet()) { | ||
78 | var descriptions = entry.getValue(); | ||
79 | if (NamingUtil.isFullyQualified(entry.getKey().name())) { | ||
80 | exportedEObjects.addAll(descriptions); | ||
81 | } else { | ||
82 | boolean foundPreferred = false; | ||
83 | for (var description : descriptions) { | ||
84 | if (ProblemResourceDescriptionStrategy.PREFERRED_NAME_TRUE.equals( | ||
85 | description.getUserData(ProblemResourceDescriptionStrategy.PREFERRED_NAME))) { | ||
86 | exportedEObjects.add(description); | ||
87 | foundPreferred = true; | ||
88 | } | ||
89 | } | ||
90 | if (!foundPreferred) { | ||
91 | exportedEObjects.addAll(descriptions); | ||
92 | } | ||
93 | } | ||
94 | } | ||
95 | return exportedEObjects; | ||
96 | } | ||
97 | |||
98 | // Based on {@code DerivedStateAwareResourceDescriptionManager#createResourceDescription}. | ||
99 | @Override | ||
100 | protected EObjectDescriptionLookUp getLookUp() { | ||
101 | if (lookup == null) { | ||
102 | lookup = new EObjectDescriptionLookUp(computeExportedObjects()); | ||
103 | } | ||
104 | return lookup; | ||
105 | } | ||
106 | } | ||
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionManager.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionManager.java new file mode 100644 index 00000000..23ca139a --- /dev/null +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionManager.java | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.resource; | ||
7 | |||
8 | import org.eclipse.emf.ecore.resource.Resource; | ||
9 | import org.eclipse.xtext.resource.DerivedStateAwareResourceDescriptionManager; | ||
10 | import org.eclipse.xtext.resource.IDefaultResourceDescriptionStrategy; | ||
11 | import org.eclipse.xtext.resource.IResourceDescription; | ||
12 | |||
13 | public class ProblemResourceDescriptionManager extends DerivedStateAwareResourceDescriptionManager { | ||
14 | @Override | ||
15 | protected IResourceDescription createResourceDescription(Resource resource, | ||
16 | IDefaultResourceDescriptionStrategy strategy) { | ||
17 | return new ProblemResourceDescription(resource, strategy); | ||
18 | } | ||
19 | } | ||
diff --git a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java index 79dad6e7..76fd5852 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java +++ b/subprojects/language/src/main/java/tools/refinery/language/resource/ProblemResourceDescriptionStrategy.java | |||
@@ -25,9 +25,16 @@ import java.util.Map; | |||
25 | @Singleton | 25 | @Singleton |
26 | public class ProblemResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy { | 26 | public class ProblemResourceDescriptionStrategy extends DefaultResourceDescriptionStrategy { |
27 | private static final String DATA_PREFIX = "tools.refinery.language.resource.ProblemResourceDescriptionStrategy."; | 27 | private static final String DATA_PREFIX = "tools.refinery.language.resource.ProblemResourceDescriptionStrategy."; |
28 | |||
28 | public static final String ARITY = DATA_PREFIX + "ARITY"; | 29 | public static final String ARITY = DATA_PREFIX + "ARITY"; |
29 | public static final String ERROR_PREDICATE = DATA_PREFIX + "ERROR_PREDICATE"; | 30 | public static final String ERROR_PREDICATE = DATA_PREFIX + "ERROR_PREDICATE"; |
30 | public static final String ERROR_PREDICATE_TRUE = "true"; | 31 | public static final String ERROR_PREDICATE_TRUE = "true"; |
32 | public static final String SHADOWING_KEY = DATA_PREFIX + "SHADOWING_KEY"; | ||
33 | public static final String SHADOWING_KEY_PROBLEM = "problem"; | ||
34 | public static final String SHADOWING_KEY_NODE = "node"; | ||
35 | public static final String SHADOWING_KEY_RELATION = "relation"; | ||
36 | public static final String PREFERRED_NAME = DATA_PREFIX + "PREFERRED_NAME"; | ||
37 | public static final String PREFERRED_NAME_TRUE = "true"; | ||
31 | public static final String COLOR_RELATION = DATA_PREFIX + "COLOR_RELATION"; | 38 | public static final String COLOR_RELATION = DATA_PREFIX + "COLOR_RELATION"; |
32 | public static final String COLOR_RELATION_TRUE = "true"; | 39 | public static final String COLOR_RELATION_TRUE = "true"; |
33 | 40 | ||
@@ -44,8 +51,12 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti | |||
44 | return true; | 51 | return true; |
45 | } | 52 | } |
46 | var problem = EcoreUtil2.getContainerOfType(eObject, Problem.class); | 53 | var problem = EcoreUtil2.getContainerOfType(eObject, Problem.class); |
47 | var problemQualifiedName = getNameAsQualifiedName(problem); | ||
48 | var userData = getUserData(eObject); | 54 | var userData = getUserData(eObject); |
55 | if (eObject.equals(problem)) { | ||
56 | acceptEObjectDescription(eObject, qualifiedName, QualifiedName.EMPTY, userData, true, acceptor); | ||
57 | return true; | ||
58 | } | ||
59 | var problemQualifiedName = getNameAsQualifiedName(problem); | ||
49 | QualifiedName lastQualifiedNameToExport = null; | 60 | QualifiedName lastQualifiedNameToExport = null; |
50 | if (shouldExportSimpleName(eObject)) { | 61 | if (shouldExportSimpleName(eObject)) { |
51 | lastQualifiedNameToExport = qualifiedName; | 62 | lastQualifiedNameToExport = qualifiedName; |
@@ -82,10 +93,14 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti | |||
82 | if (NamingUtil.isNullOrEmpty(name)) { | 93 | if (NamingUtil.isNullOrEmpty(name)) { |
83 | return null; | 94 | return null; |
84 | } | 95 | } |
85 | return qualifiedNameConverter.toQualifiedName(name); | 96 | var qualifiedName = qualifiedNameConverter.toQualifiedName(name); |
97 | if (eObject instanceof Problem) { | ||
98 | return NamingUtil.stripRootPrefix(qualifiedName); | ||
99 | } | ||
100 | return qualifiedName; | ||
86 | } | 101 | } |
87 | 102 | ||
88 | protected boolean shouldExport(EObject eObject) { | 103 | public static boolean shouldExport(EObject eObject) { |
89 | if (eObject instanceof Variable) { | 104 | if (eObject instanceof Variable) { |
90 | // Variables are always private to the containing predicate definition. | 105 | // Variables are always private to the containing predicate definition. |
91 | return false; | 106 | return false; |
@@ -98,7 +113,12 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti | |||
98 | 113 | ||
99 | protected Map<String, String> getUserData(EObject eObject) { | 114 | protected Map<String, String> getUserData(EObject eObject) { |
100 | var builder = ImmutableMap.<String, String>builder(); | 115 | var builder = ImmutableMap.<String, String>builder(); |
101 | if (eObject instanceof Relation relation) { | 116 | if (eObject instanceof Problem) { |
117 | builder.put(SHADOWING_KEY, SHADOWING_KEY_PROBLEM); | ||
118 | } else if (eObject instanceof Node) { | ||
119 | builder.put(SHADOWING_KEY, SHADOWING_KEY_NODE); | ||
120 | } else if (eObject instanceof Relation relation) { | ||
121 | builder.put(SHADOWING_KEY, SHADOWING_KEY_RELATION); | ||
102 | int arity = ProblemUtil.getArity(relation); | 122 | int arity = ProblemUtil.getArity(relation); |
103 | builder.put(ARITY, Integer.toString(arity)); | 123 | builder.put(ARITY, Integer.toString(arity)); |
104 | } | 124 | } |
@@ -124,20 +144,31 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti | |||
124 | } | 144 | } |
125 | 145 | ||
126 | private void acceptEObjectDescription(EObject eObject, QualifiedName prefix, QualifiedName qualifiedName, | 146 | private void acceptEObjectDescription(EObject eObject, QualifiedName prefix, QualifiedName qualifiedName, |
127 | Map<String, String> userData, boolean fullyQualified, | 147 | Map<String, String> userData, boolean preferredName, |
128 | IAcceptor<IEObjectDescription> acceptor) { | 148 | IAcceptor<IEObjectDescription> acceptor) { |
129 | var qualifiedNameWithPrefix = prefix == null ? qualifiedName : prefix.append(qualifiedName); | 149 | var qualifiedNameWithPrefix = prefix == null ? qualifiedName : prefix.append(qualifiedName); |
130 | Map<String, String> userDataWithFullyQualified; | 150 | var userDataWithPreference = userData; |
131 | if (fullyQualified && shouldColorRelation(eObject)) { | 151 | if (preferredName) { |
132 | userDataWithFullyQualified = ImmutableMap.<String, String>builder() | 152 | userDataWithPreference = ImmutableMap.<String, String>builder() |
133 | .putAll(userData) | 153 | .putAll(userData) |
134 | .put(COLOR_RELATION, COLOR_RELATION_TRUE) | 154 | .put(PREFERRED_NAME, PREFERRED_NAME_TRUE) |
135 | .build(); | 155 | .build(); |
136 | } else { | ||
137 | userDataWithFullyQualified = userData; | ||
138 | } | 156 | } |
139 | var description = EObjectDescription.create(qualifiedNameWithPrefix, eObject, userDataWithFullyQualified); | 157 | var description = EObjectDescription.create(qualifiedNameWithPrefix, eObject, userDataWithPreference); |
140 | acceptor.accept(description); | 158 | acceptor.accept(description); |
159 | if (!preferredName) { | ||
160 | return; | ||
161 | } | ||
162 | var userDataWithFullyQualified = userDataWithPreference; | ||
163 | if (shouldColorRelation(eObject)) { | ||
164 | userDataWithFullyQualified = ImmutableMap.<String, String>builder() | ||
165 | .putAll(userDataWithPreference) | ||
166 | .put(COLOR_RELATION, COLOR_RELATION_TRUE) | ||
167 | .build(); | ||
168 | } | ||
169 | var rootQualifiedName = NamingUtil.addRootPrefix(qualifiedNameWithPrefix); | ||
170 | var rootDescription = EObjectDescription.create(rootQualifiedName, eObject, userDataWithFullyQualified); | ||
171 | acceptor.accept(rootDescription); | ||
141 | } | 172 | } |
142 | 173 | ||
143 | private boolean shouldColorRelation(EObject eObject) { | 174 | private boolean shouldColorRelation(EObject eObject) { |
@@ -146,4 +177,11 @@ public class ProblemResourceDescriptionStrategy extends DefaultResourceDescripti | |||
146 | } | 177 | } |
147 | return eObject instanceof ClassDeclaration || eObject instanceof EnumDeclaration; | 178 | return eObject instanceof ClassDeclaration || eObject instanceof EnumDeclaration; |
148 | } | 179 | } |
180 | |||
181 | public static ShadowingKey getShadowingKey(IEObjectDescription description) { | ||
182 | return new ShadowingKey(description.getName(), description.getUserData(SHADOWING_KEY)); | ||
183 | } | ||
184 | |||
185 | public record ShadowingKey(QualifiedName name, String shadowingKey) { | ||
186 | } | ||
149 | } | 187 | } |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java b/subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java new file mode 100644 index 00000000..0c7828d8 --- /dev/null +++ b/subprojects/language/src/main/java/tools/refinery/language/scoping/NormalizedSelectable.java | |||
@@ -0,0 +1,122 @@ | |||
1 | /* | ||
2 | * SPDX-FileCopyrightText: 2024 The Refinery Authors <https://refinery.tools/> | ||
3 | * | ||
4 | * SPDX-License-Identifier: EPL-2.0 | ||
5 | */ | ||
6 | package tools.refinery.language.scoping; | ||
7 | |||
8 | import com.google.common.collect.Iterables; | ||
9 | import org.eclipse.emf.ecore.EClass; | ||
10 | import org.eclipse.emf.ecore.EObject; | ||
11 | import org.eclipse.xtext.naming.QualifiedName; | ||
12 | import org.eclipse.xtext.resource.IEObjectDescription; | ||
13 | import org.eclipse.xtext.resource.ISelectable; | ||
14 | import org.eclipse.xtext.resource.impl.AliasedEObjectDescription; | ||
15 | import org.jetbrains.annotations.NotNull; | ||
16 | |||
17 | import java.util.Iterator; | ||
18 | import java.util.NoSuchElementException; | ||
19 | |||
20 | public class NormalizedSelectable implements ISelectable { | ||
21 | private final ISelectable delegateSelectable; | ||
22 | private final QualifiedName originalPrefix; | ||
23 | private final QualifiedName normalizedPrefix; | ||
24 | |||
25 | private NormalizedSelectable(ISelectable delegateSelectable, QualifiedName originalPrefix, | ||
26 | QualifiedName normalizedPrefix) { | ||
27 | this.delegateSelectable = delegateSelectable; | ||
28 | this.originalPrefix = originalPrefix; | ||
29 | this.normalizedPrefix = normalizedPrefix; | ||
30 | } | ||
31 | |||
32 | @Override | ||
33 | public boolean isEmpty() { | ||
34 | return delegateSelectable.isEmpty(); | ||
35 | } | ||
36 | |||
37 | @Override | ||
38 | public Iterable<IEObjectDescription> getExportedObjects() { | ||
39 | var delegateIterable = delegateSelectable.getExportedObjects(); | ||
40 | var aliasedIterable = getAliasedElements(delegateIterable); | ||
41 | return Iterables.concat(delegateIterable, aliasedIterable); | ||
42 | } | ||
43 | |||
44 | @Override | ||
45 | public Iterable<IEObjectDescription> getExportedObjects(EClass type, QualifiedName name, boolean ignoreCase) { | ||
46 | var delegateIterable = delegateSelectable.getExportedObjects(type, name, ignoreCase); | ||
47 | boolean startsWith = ignoreCase ? name.startsWithIgnoreCase(normalizedPrefix) : | ||
48 | name.startsWith(normalizedPrefix); | ||
49 | if (startsWith && name.getSegmentCount() > normalizedPrefix.getSegmentCount()) { | ||
50 | var originalName = originalPrefix.append(name.skipFirst(normalizedPrefix.getSegmentCount())); | ||
51 | var originalIterable = Iterables.transform( | ||
52 | delegateSelectable.getExportedObjects(type, originalName, ignoreCase), | ||
53 | description -> { | ||
54 | var normalizedName = normalizedPrefix.append( | ||
55 | description.getName().skipFirst(originalPrefix.getSegmentCount())); | ||
56 | return new AliasedEObjectDescription(normalizedName, description); | ||
57 | }); | ||
58 | return Iterables.concat(originalIterable, delegateIterable); | ||
59 | } | ||
60 | return delegateIterable; | ||
61 | } | ||
62 | |||
63 | @Override | ||
64 | public Iterable<IEObjectDescription> getExportedObjectsByType(EClass type) { | ||
65 | var delegateIterable = delegateSelectable.getExportedObjectsByType(type); | ||
66 | var aliasedIterable = getAliasedElements(delegateIterable); | ||
67 | return Iterables.concat(delegateIterable, aliasedIterable); | ||
68 | } | ||
69 | |||
70 | @Override | ||
71 | public Iterable<IEObjectDescription> getExportedObjectsByObject(EObject object) { | ||
72 | var delegateIterable = delegateSelectable.getExportedObjectsByObject(object); | ||
73 | var aliasedIterable = getAliasedElements(delegateIterable); | ||
74 | return Iterables.concat(delegateIterable, aliasedIterable); | ||
75 | } | ||
76 | |||
77 | private Iterable<IEObjectDescription> getAliasedElements(Iterable<IEObjectDescription> delegateIterable) { | ||
78 | return () -> new Iterator<>() { | ||
79 | private final Iterator<IEObjectDescription> delegateIterator = delegateIterable.iterator(); | ||
80 | private IEObjectDescription next = computeNext(); | ||
81 | |||
82 | @Override | ||
83 | public boolean hasNext() { | ||
84 | return next != null; | ||
85 | } | ||
86 | |||
87 | @Override | ||
88 | public IEObjectDescription next() { | ||
89 | if (!hasNext()) { | ||
90 | throw new NoSuchElementException(); | ||
91 | } | ||
92 | var current = next; | ||
93 | next = computeNext(); | ||
94 | return current; | ||
95 | } | ||
96 | |||
97 | private IEObjectDescription computeNext() { | ||
98 | while (delegateIterator.hasNext()) { | ||
99 | var description = delegateIterator.next(); | ||
100 | var qualifiedName = description.getName(); | ||
101 | if (qualifiedName.startsWith(originalPrefix) && | ||
102 | qualifiedName.getSegmentCount() > originalPrefix.getSegmentCount()) { | ||
103 | var alias = normalizedPrefix.append(qualifiedName.skipFirst(originalPrefix.getSegmentCount())); | ||
104 | return new AliasedEObjectDescription(alias, description); | ||
105 | } | ||
106 | } | ||
107 | return null; | ||
108 | } | ||
109 | }; | ||
110 | } | ||
111 | |||
112 | public static ISelectable of(@NotNull ISelectable delegateSelectable, @NotNull QualifiedName originalPrefix, | ||
113 | @NotNull QualifiedName normalizedPrefix) { | ||
114 | if (originalPrefix.equals(normalizedPrefix)) { | ||
115 | return delegateSelectable; | ||
116 | } | ||
117 | if (originalPrefix.equals(QualifiedName.EMPTY)) { | ||
118 | throw new IllegalArgumentException("Cannot normalize empty qualified name prefix"); | ||
119 | } | ||
120 | return new NormalizedSelectable(delegateSelectable, originalPrefix, normalizedPrefix); | ||
121 | } | ||
122 | } | ||
diff --git a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemGlobalScopeProvider.java b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemGlobalScopeProvider.java index 4d2dd772..37a67c0c 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemGlobalScopeProvider.java +++ b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemGlobalScopeProvider.java | |||
@@ -5,14 +5,21 @@ | |||
5 | */ | 5 | */ |
6 | package tools.refinery.language.scoping; | 6 | package tools.refinery.language.scoping; |
7 | 7 | ||
8 | import java.util.LinkedHashSet; | 8 | import com.google.common.base.Predicate; |
9 | |||
10 | import org.eclipse.emf.common.util.URI; | 9 | import org.eclipse.emf.common.util.URI; |
10 | import org.eclipse.emf.ecore.EClass; | ||
11 | import org.eclipse.emf.ecore.resource.Resource; | 11 | import org.eclipse.emf.ecore.resource.Resource; |
12 | import org.eclipse.xtext.naming.QualifiedName; | ||
13 | import org.eclipse.xtext.resource.IEObjectDescription; | ||
14 | import org.eclipse.xtext.resource.IResourceDescriptions; | ||
15 | import org.eclipse.xtext.resource.ISelectable; | ||
16 | import org.eclipse.xtext.scoping.IScope; | ||
12 | import org.eclipse.xtext.scoping.impl.ImportUriGlobalScopeProvider; | 17 | import org.eclipse.xtext.scoping.impl.ImportUriGlobalScopeProvider; |
13 | 18 | import org.eclipse.xtext.scoping.impl.SelectableBasedScope; | |
14 | import tools.refinery.language.utils.ProblemUtil; | 19 | import tools.refinery.language.utils.ProblemUtil; |
15 | 20 | ||
21 | import java.util.LinkedHashSet; | ||
22 | |||
16 | public class ProblemGlobalScopeProvider extends ImportUriGlobalScopeProvider { | 23 | public class ProblemGlobalScopeProvider extends ImportUriGlobalScopeProvider { |
17 | @Override | 24 | @Override |
18 | protected LinkedHashSet<URI> getImportedUris(Resource resource) { | 25 | protected LinkedHashSet<URI> getImportedUris(Resource resource) { |
@@ -20,4 +27,14 @@ public class ProblemGlobalScopeProvider extends ImportUriGlobalScopeProvider { | |||
20 | importedUris.add(ProblemUtil.BUILTIN_LIBRARY_URI); | 27 | importedUris.add(ProblemUtil.BUILTIN_LIBRARY_URI); |
21 | return importedUris; | 28 | return importedUris; |
22 | } | 29 | } |
30 | |||
31 | @Override | ||
32 | protected IScope createLazyResourceScope(IScope parent, URI uri, IResourceDescriptions descriptions, EClass type, | ||
33 | Predicate<IEObjectDescription> filter, boolean ignoreCase) { | ||
34 | ISelectable description = descriptions.getResourceDescription(uri); | ||
35 | if (description != null && ProblemUtil.BUILTIN_LIBRARY_URI.equals(uri)) { | ||
36 | description = NormalizedSelectable.of(description, QualifiedName.create("builtin"), QualifiedName.EMPTY); | ||
37 | } | ||
38 | return SelectableBasedScope.createScope(parent, description, filter, type, ignoreCase); | ||
39 | } | ||
23 | } | 40 | } |
diff --git a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemLocalScopeProvider.java b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemLocalScopeProvider.java index 229960a0..9be32636 100644 --- a/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemLocalScopeProvider.java +++ b/subprojects/language/src/main/java/tools/refinery/language/scoping/ProblemLocalScopeProvider.java | |||
@@ -1,47 +1,42 @@ | |||
1 | /* | 1 | /* |
2 | * SPDX-FileCopyrightText: 2021-2023 The Refinery Authors <https://refinery.tools/> | 2 | * SPDX-FileCopyrightText: 2021-2024 The Refinery Authors <https://refinery.tools/> |
3 | * | 3 | * |
4 | * SPDX-License-Identifier: EPL-2.0 | 4 | * SPDX-License-Identifier: EPL-2.0 |
5 | */ | 5 | */ |
6 | package tools.refinery.language.scoping; | 6 | package tools.refinery.language.scoping; |
7 | 7 | ||
8 | import java.util.List; | 8 | import com.google.inject.Inject; |
9 | |||
10 | import org.eclipse.emf.ecore.EObject; | ||
11 | import org.eclipse.emf.ecore.resource.Resource; | 9 | import org.eclipse.emf.ecore.resource.Resource; |
10 | import org.eclipse.xtext.naming.IQualifiedNameProvider; | ||
12 | import org.eclipse.xtext.naming.QualifiedName; | 11 | import org.eclipse.xtext.naming.QualifiedName; |
13 | import org.eclipse.xtext.resource.IResourceDescriptions; | ||
14 | import org.eclipse.xtext.resource.IResourceDescriptionsProvider; | 12 | import org.eclipse.xtext.resource.IResourceDescriptionsProvider; |
15 | import org.eclipse.xtext.resource.ISelectable; | 13 | import org.eclipse.xtext.resource.ISelectable; |
16 | import org.eclipse.xtext.scoping.impl.ImportNormalizer; | 14 | import org.eclipse.xtext.scoping.impl.SimpleLocalScopeProvider; |
17 | import org.eclipse.xtext.scoping.impl.ImportedNamespaceAwareLocalScopeProvider; | 15 | import tools.refinery.language.naming.NamingUtil; |
18 | |||
19 | import com.google.inject.Inject; | ||
20 | |||
21 | import tools.refinery.language.utils.ProblemUtil; | ||
22 | 16 | ||
23 | public class ProblemLocalScopeProvider extends ImportedNamespaceAwareLocalScopeProvider { | 17 | public class ProblemLocalScopeProvider extends SimpleLocalScopeProvider { |
24 | private static final QualifiedName BUILTIN_LIBRARY_QUALIFIED_NAME = QualifiedName | 18 | @Inject |
25 | .create(ProblemUtil.BUILTIN_LIBRARY_NAME); | 19 | private IQualifiedNameProvider qualifiedNameProvider; |
26 | 20 | ||
27 | @Inject | 21 | @Inject |
28 | private IResourceDescriptionsProvider resourceDescriptionsProvider; | 22 | private IResourceDescriptionsProvider resourceDescriptionsProvider; |
29 | 23 | ||
30 | @Override | 24 | @Override |
31 | protected List<ImportNormalizer> getImplicitImports(boolean ignoreCase) { | 25 | protected ISelectable getAllDescriptions(Resource resource) { |
32 | return List.of(doCreateImportNormalizer(BUILTIN_LIBRARY_QUALIFIED_NAME, true, ignoreCase)); | ||
33 | } | ||
34 | |||
35 | @Override | ||
36 | protected List<ImportNormalizer> getImportedNamespaceResolvers(EObject context, boolean ignoreCase) { | ||
37 | return List.of(); | ||
38 | } | ||
39 | |||
40 | @Override | ||
41 | protected ISelectable internalGetAllDescriptions(Resource resource) { | ||
42 | // Force the use of ProblemResourceDescriptionStrategy to include all QualifiedNames of objects. | 26 | // Force the use of ProblemResourceDescriptionStrategy to include all QualifiedNames of objects. |
43 | IResourceDescriptions resourceDescriptions = resourceDescriptionsProvider | 27 | var resourceDescriptions = resourceDescriptionsProvider |
44 | .getResourceDescriptions(resource.getResourceSet()); | 28 | .getResourceDescriptions(resource.getResourceSet()); |
45 | return resourceDescriptions.getResourceDescription(resource.getURI()); | 29 | var resourceDescription = resourceDescriptions.getResourceDescription(resource.getURI()); |
30 | if (resourceDescription != null && !resource.getContents().isEmpty()) { | ||
31 | var rootElement = resource.getContents().getFirst(); | ||
32 | if (rootElement != null) { | ||
33 | var rootName = NamingUtil.stripRootPrefix(qualifiedNameProvider.getFullyQualifiedName(rootElement)); | ||
34 | if (rootName == null) { | ||
35 | return resourceDescription; | ||
36 | } | ||
37 | return NormalizedSelectable.of(resourceDescription, rootName, QualifiedName.EMPTY); | ||
38 | } | ||
39 | } | ||
40 | return resourceDescription; | ||
46 | } | 41 | } |
47 | } | 42 | } |