@oml/language 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +44 -0
  2. package/out/oml/generated/ast.d.ts +2109 -0
  3. package/out/oml/generated/ast.js +1807 -0
  4. package/out/oml/generated/ast.js.map +1 -0
  5. package/out/oml/generated/grammar.d.ts +6 -0
  6. package/out/oml/generated/grammar.js +6885 -0
  7. package/out/oml/generated/grammar.js.map +1 -0
  8. package/out/oml/generated/module.d.ts +13 -0
  9. package/out/oml/generated/module.js +21 -0
  10. package/out/oml/generated/module.js.map +1 -0
  11. package/out/oml/index.d.ts +17 -0
  12. package/out/oml/index.js +19 -0
  13. package/out/oml/index.js.map +1 -0
  14. package/out/oml/oml-candidates.d.ts +27 -0
  15. package/out/oml/oml-candidates.js +146 -0
  16. package/out/oml/oml-candidates.js.map +1 -0
  17. package/out/oml/oml-code-actions.d.ts +6 -0
  18. package/out/oml/oml-code-actions.js +79 -0
  19. package/out/oml/oml-code-actions.js.map +1 -0
  20. package/out/oml/oml-completion.d.ts +50 -0
  21. package/out/oml/oml-completion.js +188 -0
  22. package/out/oml/oml-completion.js.map +1 -0
  23. package/out/oml/oml-converter.d.ts +10 -0
  24. package/out/oml/oml-converter.js +62 -0
  25. package/out/oml/oml-converter.js.map +1 -0
  26. package/out/oml/oml-document-validator.d.ts +10 -0
  27. package/out/oml/oml-document-validator.js +31 -0
  28. package/out/oml/oml-document-validator.js.map +1 -0
  29. package/out/oml/oml-document.d.ts +9 -0
  30. package/out/oml/oml-document.js +18 -0
  31. package/out/oml/oml-document.js.map +1 -0
  32. package/out/oml/oml-edit.d.ts +72 -0
  33. package/out/oml/oml-edit.js +1155 -0
  34. package/out/oml/oml-edit.js.map +1 -0
  35. package/out/oml/oml-formatter.d.ts +22 -0
  36. package/out/oml/oml-formatter.js +357 -0
  37. package/out/oml/oml-formatter.js.map +1 -0
  38. package/out/oml/oml-hover.d.ts +13 -0
  39. package/out/oml/oml-hover.js +71 -0
  40. package/out/oml/oml-hover.js.map +1 -0
  41. package/out/oml/oml-index-manager.d.ts +10 -0
  42. package/out/oml/oml-index-manager.js +48 -0
  43. package/out/oml/oml-index-manager.js.map +1 -0
  44. package/out/oml/oml-index.d.ts +20 -0
  45. package/out/oml/oml-index.js +133 -0
  46. package/out/oml/oml-index.js.map +1 -0
  47. package/out/oml/oml-module.d.ts +42 -0
  48. package/out/oml/oml-module.js +76 -0
  49. package/out/oml/oml-module.js.map +1 -0
  50. package/out/oml/oml-rename.d.ts +14 -0
  51. package/out/oml/oml-rename.js +114 -0
  52. package/out/oml/oml-rename.js.map +1 -0
  53. package/out/oml/oml-scope.d.ts +30 -0
  54. package/out/oml/oml-scope.js +225 -0
  55. package/out/oml/oml-scope.js.map +1 -0
  56. package/out/oml/oml-serializer.d.ts +2 -0
  57. package/out/oml/oml-serializer.js +883 -0
  58. package/out/oml/oml-serializer.js.map +1 -0
  59. package/out/oml/oml-utils.d.ts +53 -0
  60. package/out/oml/oml-utils.js +241 -0
  61. package/out/oml/oml-utils.js.map +1 -0
  62. package/out/oml/oml-validator.d.ts +49 -0
  63. package/out/oml/oml-validator.js +668 -0
  64. package/out/oml/oml-validator.js.map +1 -0
  65. package/out/oml/oml-workspace.d.ts +23 -0
  66. package/out/oml/oml-workspace.js +68 -0
  67. package/out/oml/oml-workspace.js.map +1 -0
  68. package/package.json +50 -0
  69. package/src/oml/generated/ast.ts +2641 -0
  70. package/src/oml/generated/grammar.ts +6887 -0
  71. package/src/oml/generated/module.ts +25 -0
  72. package/src/oml/index.ts +19 -0
  73. package/src/oml/oml-candidates.ts +176 -0
  74. package/src/oml/oml-code-actions.ts +120 -0
  75. package/src/oml/oml-completion.ts +222 -0
  76. package/src/oml/oml-converter.ts +66 -0
  77. package/src/oml/oml-document-validator.ts +39 -0
  78. package/src/oml/oml-document.ts +24 -0
  79. package/src/oml/oml-edit.ts +1292 -0
  80. package/src/oml/oml-formatter.ts +390 -0
  81. package/src/oml/oml-hover.ts +93 -0
  82. package/src/oml/oml-index-manager.ts +56 -0
  83. package/src/oml/oml-index.ts +145 -0
  84. package/src/oml/oml-module.ts +105 -0
  85. package/src/oml/oml-rename.ts +140 -0
  86. package/src/oml/oml-scope.ts +279 -0
  87. package/src/oml/oml-serializer.ts +1080 -0
  88. package/src/oml/oml-utils.ts +294 -0
  89. package/src/oml/oml-validator.ts +725 -0
  90. package/src/oml/oml-workspace.ts +81 -0
  91. package/src/oml/oml.langium +594 -0
@@ -0,0 +1,105 @@
1
+ // Copyright (c) 2026 Modelware. All rights reserved.
2
+
3
+ import { type Module, inject } from 'langium';
4
+ import { createDefaultModule, createDefaultSharedModule, type DefaultSharedModuleContext, type LangiumServices, type LangiumSharedServices, type PartialLangiumServices, type PartialLangiumSharedServices } from 'langium/lsp';
5
+ import { OmlGeneratedModule, OmlGeneratedSharedModule } from './generated/module.js';
6
+ import { OmlCompletionProvider } from './oml-completion.js';
7
+ import { OmlCodeActionProvider } from './oml-code-actions.js';
8
+ import { OmlValueConverter } from './oml-converter.js';
9
+ import { OmlDocumentValidator } from './oml-document-validator.js';
10
+ import { OmlDocumentUpdateHandler } from './oml-document.js';
11
+ import { OmlFormatter } from './oml-formatter.js';
12
+ import { OmlHoverProvider } from './oml-hover.js';
13
+ import { OmlRenameProvider } from './oml-rename.js';
14
+ import { OmlScopeComputation, OmlScopeProvider } from './oml-scope.js';
15
+ import { OmlValidator, registerValidationChecks } from './oml-validator.js';
16
+ import { OmlWorkspaceManager } from './oml-workspace.js';
17
+
18
+ /**
19
+ * Declaration of custom services - add your own service classes here.
20
+ */
21
+ export type OmlAddedServices = {
22
+ validation: {
23
+ OmlValidator: OmlValidator
24
+ }
25
+ }
26
+
27
+ /**
28
+ * Union of Langium default services and your custom services - use this as constructor parameter
29
+ * of custom service classes.
30
+ */
31
+ export type OmlServices = LangiumServices & OmlAddedServices
32
+
33
+ /**
34
+ * Dependency injection module that overrides Langium default services and contributes the
35
+ * declared custom services. The Langium defaults can be partially specified to override only
36
+ * selected services, while the custom services must be fully specified.
37
+ */
38
+ export const OmlModule: Module<OmlServices, PartialLangiumServices & OmlAddedServices> = {
39
+ lsp: {
40
+ CodeActionProvider: () => new OmlCodeActionProvider(),
41
+ CompletionProvider: (services) => new OmlCompletionProvider(services),
42
+ Formatter: () => new OmlFormatter(),
43
+ HoverProvider: (services) => new OmlHoverProvider(services),
44
+ RenameProvider: (services) => new OmlRenameProvider(services)
45
+ },
46
+ parser: {
47
+ ValueConverter: () => new OmlValueConverter()
48
+ },
49
+ references: {
50
+ ScopeComputation: (services) => new OmlScopeComputation(services),
51
+ ScopeProvider: (services) => new OmlScopeProvider(services)
52
+ },
53
+ validation: {
54
+ DocumentValidator: (services) => new OmlDocumentValidator(services),
55
+ OmlValidator: (services) => new OmlValidator(services)
56
+ }
57
+ };
58
+
59
+ export const OmlSharedModule: Module<LangiumSharedServices, PartialLangiumSharedServices> = {
60
+ lsp: {
61
+ DocumentUpdateHandler: (services) => new OmlDocumentUpdateHandler(services)
62
+ },
63
+ workspace: {
64
+ WorkspaceManager: (services) => new OmlWorkspaceManager(services)
65
+ }
66
+ };
67
+
68
+ /**
69
+ * Create the full set of services required by Langium.
70
+ *
71
+ * First inject the shared services by merging two modules:
72
+ * - Langium default shared services
73
+ * - Services generated by langium-cli
74
+ *
75
+ * Then inject the language-specific services by merging three modules:
76
+ * - Langium default language-specific services
77
+ * - Services generated by langium-cli
78
+ * - Services specified in this file
79
+ *
80
+ * @param context Optional module context with the LSP connection
81
+ * @returns An object wrapping the shared services and the language-specific services
82
+ */
83
+ export function createOmlServices(context: DefaultSharedModuleContext): {
84
+ shared: LangiumSharedServices,
85
+ Oml: OmlServices
86
+ } {
87
+ const shared = inject(
88
+ createDefaultSharedModule(context),
89
+ OmlGeneratedSharedModule,
90
+ OmlSharedModule
91
+ );
92
+ const Oml = inject(
93
+ createDefaultModule({ shared }),
94
+ OmlGeneratedModule,
95
+ OmlModule
96
+ );
97
+ shared.ServiceRegistry.register(Oml);
98
+ registerValidationChecks(Oml);
99
+ if (!context.connection) {
100
+ // We don't run inside a language server
101
+ // Therefore, initialize the configuration provider instantly
102
+ shared.workspace.ConfigurationProvider.initialized({});
103
+ }
104
+ return { shared, Oml };
105
+ }
@@ -0,0 +1,140 @@
1
+ // Copyright (c) 2026 Modelware. All rights reserved.
2
+
3
+ import { DefaultRenameProvider, type LangiumServices } from 'langium/lsp';
4
+ import type { Position, Range, RenameParams, TextDocumentPositionParams, WorkspaceEdit } from 'vscode-languageserver-protocol';
5
+ import { CstUtils, GrammarUtils, URI } from 'langium';
6
+ import type { LangiumDocument } from 'langium';
7
+ import { TextEdit } from 'vscode-languageserver-types';
8
+ import { isOntology, type Ontology } from './generated/ast.js';
9
+
10
+ export class OmlRenameProvider extends DefaultRenameProvider {
11
+ private readonly documents;
12
+
13
+ constructor(services: LangiumServices) {
14
+ super(services);
15
+ this.documents = services.shared.workspace.LangiumDocuments;
16
+ }
17
+
18
+ override async rename(
19
+ document: LangiumDocument,
20
+ params: RenameParams,
21
+ cancelToken?: any
22
+ ): Promise<WorkspaceEdit | undefined> {
23
+ const namespaceRename = this.renameOntologyNamespace(document, params.position, params.newName);
24
+ if (namespaceRename) {
25
+ return namespaceRename;
26
+ }
27
+ const result = await super.rename(document, params, cancelToken);
28
+ if (!result?.changes) {
29
+ return result;
30
+ }
31
+ for (const [uri, edits] of Object.entries(result.changes)) {
32
+ const refDoc = await this.documents.getOrCreateDocument(URI.parse(uri));
33
+ edits.forEach((edit) => {
34
+ const refText = refDoc.textDocument.getText(edit.range);
35
+ edit.newText = this.buildReplacement(refText, params.newName);
36
+ });
37
+ }
38
+ return result;
39
+ }
40
+
41
+ override async prepareRename(
42
+ document: LangiumDocument,
43
+ params: TextDocumentPositionParams,
44
+ cancelToken?: any
45
+ ) {
46
+ const target = this.findOntologyNamespaceRenameTarget(document, params.position);
47
+ if (target) {
48
+ return target.range;
49
+ }
50
+ return super.prepareRename(document, params, cancelToken);
51
+ }
52
+
53
+ private renameOntologyNamespace(document: LangiumDocument, position: Position, newName: string): WorkspaceEdit | undefined {
54
+ const target = this.findOntologyNamespaceRenameTarget(document, position);
55
+ if (!target) {
56
+ return undefined;
57
+ }
58
+
59
+ const newNamespaceText = this.toNamespaceToken(newName);
60
+ const changes: Record<string, TextEdit[]> = {};
61
+ changes[document.uri.toString()] = [TextEdit.replace(target.range, newNamespaceText)];
62
+
63
+ const references = this.references.findReferences(target.ontology, { includeDeclaration: false });
64
+ for (const ref of references) {
65
+ const uri = ref.sourceUri.toString();
66
+ const change = TextEdit.replace(ref.segment.range, newNamespaceText);
67
+ if (changes[uri]) {
68
+ changes[uri].push(change);
69
+ } else {
70
+ changes[uri] = [change];
71
+ }
72
+ }
73
+ return { changes };
74
+ }
75
+
76
+ private findOntologyNamespaceRenameTarget(
77
+ document: LangiumDocument,
78
+ position: Position
79
+ ): { ontology: Ontology; range: Range } | undefined {
80
+ const root = document.parseResult?.value;
81
+ const rootCst = root?.$cstNode;
82
+ if (!rootCst || !root || !isOntology(root)) {
83
+ return undefined;
84
+ }
85
+
86
+ const offset = document.textDocument.offsetAt(position);
87
+ const namespaceNode = GrammarUtils.findNodeForProperty(rootCst, 'namespace');
88
+ if (namespaceNode && offset >= namespaceNode.offset && offset <= namespaceNode.offset + namespaceNode.length) {
89
+ return { ontology: root, range: namespaceNode.range };
90
+ }
91
+
92
+ const leaf = CstUtils.findLeafNodeAtOffset(rootCst, offset);
93
+ if (!leaf) {
94
+ return undefined;
95
+ }
96
+ const declarations = this.references.findDeclarations(leaf);
97
+ const ontology = declarations.find((node): node is Ontology => isOntology(node));
98
+ if (!ontology) {
99
+ return undefined;
100
+ }
101
+ const ontologyNamespaceNode = GrammarUtils.findNodeForProperty(ontology.$cstNode, 'namespace');
102
+ if (!ontologyNamespaceNode) {
103
+ return undefined;
104
+ }
105
+ return { ontology, range: ontologyNamespaceNode.range };
106
+ }
107
+
108
+ private toNamespaceToken(name: string): string {
109
+ const trimmed = name.trim();
110
+ if (trimmed.startsWith('<') && trimmed.endsWith('>')) {
111
+ return trimmed;
112
+ }
113
+ return `<${trimmed.replace(/^<|>$/g, '')}>`;
114
+ }
115
+
116
+ private buildReplacement(refText: string, newName: string): string {
117
+ if (refText.startsWith('<') && refText.endsWith('>')) {
118
+ const inner = refText.slice(1, -1);
119
+ return `<${this.replaceIriTail(inner, newName)}>`;
120
+ }
121
+ if (refText.includes('://')) {
122
+ return this.replaceIriTail(refText, newName);
123
+ }
124
+ const qnameMatch = refText.match(/^([A-Za-z_][\w-]*:)[A-Za-z_][\w-]*$/);
125
+ if (qnameMatch) {
126
+ return `${qnameMatch[1]}${newName}`;
127
+ }
128
+ return newName;
129
+ }
130
+
131
+ private replaceIriTail(iri: string, newName: string): string {
132
+ const hashIdx = iri.lastIndexOf('#');
133
+ const slashIdx = iri.lastIndexOf('/');
134
+ const idx = Math.max(hashIdx, slashIdx);
135
+ if (idx >= 0) {
136
+ return `${iri.slice(0, idx + 1)}${newName}`;
137
+ }
138
+ return newName;
139
+ }
140
+ }
@@ -0,0 +1,279 @@
1
+ // Copyright (c) 2026 Modelware. All rights reserved.
2
+
3
+ /**
4
+ * OML Scope Provider
5
+ * Handles cross-file reference resolution, IRI abbreviation, and qualified name scoping
6
+ *
7
+ * Provides enhanced scope resolution for references across imported ontologies and abbreviated IRI names.
8
+ */
9
+
10
+ import { AstUtils, DefaultScopeComputation, DefaultScopeProvider, EMPTY_SCOPE, URI, stream } from 'langium';
11
+ import type { AstNodeDescription, LangiumCoreServices, ReferenceInfo, Scope } from 'langium';
12
+ import type { LangiumDocument } from 'langium';
13
+ import type { LangiumSharedServices } from 'langium/lsp';
14
+ import type { CancellationToken } from 'vscode-languageserver';
15
+ import { type Import, type Ontology, isOntology, isRelationBase, isRelationEntity } from './generated/ast.js';
16
+ import { getOntologyModelIndex } from './oml-index.js';
17
+ import {
18
+ normalizeNamespace,
19
+ } from './oml-utils.js';
20
+
21
+ interface ExportedSymbol {
22
+ node: any;
23
+ name: string;
24
+ relationAlias: boolean;
25
+ }
26
+
27
+ interface WorkspaceOntology {
28
+ document: LangiumDocument;
29
+ ontology: Ontology;
30
+ namespace: string;
31
+ }
32
+
33
+ interface ResolvedImport {
34
+ prefix?: string;
35
+ target: WorkspaceOntology;
36
+ }
37
+
38
+ export class OmlScopeComputation extends DefaultScopeComputation {
39
+ constructor(services: LangiumCoreServices) {
40
+ super(services);
41
+ }
42
+
43
+ override async collectExportedSymbols(
44
+ document: LangiumDocument,
45
+ cancelToken?: CancellationToken
46
+ ): Promise<AstNodeDescription[]> {
47
+ let exported: AstNodeDescription[];
48
+ try {
49
+ exported = await super.collectExportedSymbols(document, cancelToken);
50
+ } catch {
51
+ return [];
52
+ }
53
+ const root = document.parseResult?.value;
54
+ if (!root || !isOntology(root)) {
55
+ return exported;
56
+ }
57
+
58
+ const namespace = ((root as any).namespace ?? '').toString().replace(/^<|>$/g, '').trim();
59
+ if (!namespace) {
60
+ return exported;
61
+ }
62
+
63
+ const exportedNames = new Set(exported.filter((desc) => desc.node === root).map((desc) => desc.name));
64
+ const rawName = `<${namespace}>`;
65
+ if (!exportedNames.has(rawName)) {
66
+ exported.push(this.descriptions.createDescription(root, rawName, document));
67
+ }
68
+
69
+ // Default Langium exports only the root and its direct children. OML also needs
70
+ // nested forward/reverse relations exported so workspace-wide completion and
71
+ // cross-document linking can resolve them as SemanticProperty references.
72
+ const nestedExportKeys = new Set(exported.map((desc) => `${desc.path}|${desc.name}`));
73
+ const statements = (root as any).ownedStatements ?? [];
74
+ for (const statement of statements) {
75
+ if (!statement || typeof statement !== 'object') {
76
+ continue;
77
+ }
78
+ const forwardRelation = (statement as any).forwardRelation;
79
+ if (forwardRelation?.name) {
80
+ const key = `${document.uri.toString()}#${forwardRelation.$cstNode?.offset ?? ''}|${forwardRelation.name}`;
81
+ if (!nestedExportKeys.has(key)) {
82
+ exported.push(this.descriptions.createDescription(forwardRelation, forwardRelation.name as string, document));
83
+ nestedExportKeys.add(key);
84
+ }
85
+ }
86
+ if (isRelationBase(statement) && (statement as any).reverseRelation?.name) {
87
+ const reverseRelation = (statement as any).reverseRelation;
88
+ const key = `${document.uri.toString()}#${reverseRelation.$cstNode?.offset ?? ''}|${reverseRelation.name}`;
89
+ if (!nestedExportKeys.has(key)) {
90
+ exported.push(this.descriptions.createDescription(reverseRelation, reverseRelation.name as string, document));
91
+ nestedExportKeys.add(key);
92
+ }
93
+ }
94
+ }
95
+ return exported;
96
+ }
97
+ }
98
+
99
+ /**
100
+ * OML-specific scope provider for resolving cross-document references.
101
+ */
102
+ export class OmlScopeProvider extends DefaultScopeProvider {
103
+ protected services: LangiumCoreServices;
104
+
105
+ constructor(services: LangiumCoreServices) {
106
+ super(services);
107
+ this.services = services;
108
+ }
109
+
110
+ override getScope(context: ReferenceInfo): Scope {
111
+ let referenceType = '';
112
+
113
+ // Determine the expected reference type
114
+ try {
115
+ referenceType = this.reflection.getReferenceType(context);
116
+ } catch {
117
+ return EMPTY_SCOPE;
118
+ }
119
+
120
+ const document = AstUtils.getDocument(context.container);
121
+ const localSymbols = (document as any)?.localSymbols;
122
+ // Linking should stay local/import-based. Workspace-global scope is only for ontology imports.
123
+ let result: Scope = referenceType === 'Ontology'
124
+ ? this.getGlobalScope(referenceType, context)
125
+ : EMPTY_SCOPE;
126
+
127
+ // Add lexical local symbols (same behavior as DefaultScopeProvider, minus workspace-global fallback).
128
+ if (localSymbols) {
129
+ const scopes = [];
130
+ let currentNode: any = context.container;
131
+ do {
132
+ if (localSymbols.has(currentNode)) {
133
+ scopes.push(localSymbols.getStream(currentNode).filter((desc: any) => this.reflection.isSubtype(desc.type, referenceType)));
134
+ }
135
+ currentNode = currentNode.$container;
136
+ } while (currentNode);
137
+
138
+ for (let i = scopes.length - 1; i >= 0; i--) {
139
+ result = this.createScope(scopes[i], result);
140
+ }
141
+ }
142
+
143
+ // Enhance with cross-document IRI abbreviations from imports
144
+ const ontology = document?.parseResult?.value as Ontology | undefined;
145
+
146
+ if (ontology) {
147
+ result = this.addCurrentOntologyEntries(result, document, ontology);
148
+ result = this.addImportedOntologyEntries(result, ontology);
149
+ }
150
+
151
+ return result;
152
+ }
153
+
154
+ private getExportedSymbols(ontology: Ontology): ExportedSymbol[] {
155
+ const symbols: ExportedSymbol[] = [];
156
+ const statements = (ontology as any).ownedStatements || (ontology as any).ownedMembers || [];
157
+ for (const statement of statements) {
158
+ if (!statement || typeof statement !== 'object') {
159
+ continue;
160
+ }
161
+ if ('name' in statement && (statement as any).name) {
162
+ symbols.push({ node: statement, name: (statement as any).name as string, relationAlias: false });
163
+ }
164
+ if (isRelationEntity(statement) && (statement as any).forwardRelation?.name) {
165
+ symbols.push({
166
+ node: (statement as any).forwardRelation,
167
+ name: (statement as any).forwardRelation.name as string,
168
+ relationAlias: true
169
+ });
170
+ }
171
+ if (isRelationBase(statement) && (statement as any).reverseRelation?.name) {
172
+ symbols.push({
173
+ node: (statement as any).reverseRelation,
174
+ name: (statement as any).reverseRelation.name as string,
175
+ relationAlias: true
176
+ });
177
+ }
178
+ }
179
+ return symbols;
180
+ }
181
+
182
+ private getImportNamespace(imp: Import): string {
183
+ // IMPORTANT: never dereference `imp.imported.ref` while building scopes,
184
+ // otherwise linking can recursively try to resolve the same import.
185
+ const raw = (imp.imported as any)?.$refText
186
+ ?? (imp as any)?.imported
187
+ ?? '';
188
+ return typeof raw === 'string' ? raw.replace(/^<|>$/g, '') : '';
189
+ }
190
+
191
+ private resolveOntologyDocument(modelUri: string): WorkspaceOntology | undefined {
192
+ const document = this.services.shared.workspace.LangiumDocuments.getDocument(URI.parse(modelUri));
193
+ if (!document) {
194
+ return undefined;
195
+ }
196
+ const root = document.parseResult?.value;
197
+ if (!root || !isOntology(root)) {
198
+ return undefined;
199
+ }
200
+ const namespace = ((root as any).namespace ?? '').toString().replace(/^<|>$/g, '');
201
+ if (!namespace) {
202
+ return undefined;
203
+ }
204
+ return {
205
+ document,
206
+ ontology: root,
207
+ namespace
208
+ };
209
+ }
210
+
211
+ private findOntologyByNamespace(normalizedNamespace: string): WorkspaceOntology | undefined {
212
+ const index = getOntologyModelIndex(this.services.shared as LangiumSharedServices);
213
+ const modelUri = index.resolveModelUri(normalizedNamespace);
214
+ return modelUri ? this.resolveOntologyDocument(modelUri) : undefined;
215
+ }
216
+
217
+ private resolveImports(ontology: Ontology): ResolvedImport[] {
218
+ const imports = ((ontology as any).ownedImports ?? []) as Import[];
219
+ const resolved: ResolvedImport[] = [];
220
+ for (const imp of imports) {
221
+ const ns = this.getImportNamespace(imp);
222
+ const normalized = normalizeNamespace(ns);
223
+ if (!normalized) {
224
+ continue;
225
+ }
226
+ const target = this.findOntologyByNamespace(normalized);
227
+ if (!target) {
228
+ continue;
229
+ }
230
+ resolved.push({ prefix: imp.prefix, target });
231
+ }
232
+ return resolved;
233
+ }
234
+
235
+ private addDescription(scope: Scope, node: any, name: string, document: LangiumDocument): Scope {
236
+ try {
237
+ const desc = this.descriptions.createDescription(node, name, document);
238
+ return this.createScope(stream([desc]), scope);
239
+ } catch {
240
+ return scope;
241
+ }
242
+ }
243
+
244
+ private addCurrentOntologyEntries(scope: Scope, document: LangiumDocument, ontology: Ontology): Scope {
245
+ let result = scope;
246
+ const prefix = (ontology as any).prefix as string | undefined;
247
+ for (const symbol of this.getExportedSymbols(ontology)) {
248
+ if (prefix) {
249
+ result = this.addDescription(result, symbol.node, `${prefix}:${symbol.name}`, document);
250
+ }
251
+ if (symbol.relationAlias) {
252
+ result = this.addDescription(result, symbol.node, symbol.name, document);
253
+ }
254
+ }
255
+ return result;
256
+ }
257
+
258
+ private addImportedOntologyEntries(scope: Scope, current: Ontology): Scope {
259
+ let result = scope;
260
+ for (const resolvedImport of this.resolveImports(current)) {
261
+ const imported = resolvedImport.target;
262
+ const importedSymbols = this.getExportedSymbols(imported.ontology);
263
+ for (const symbol of importedSymbols) {
264
+ if (resolvedImport.prefix) {
265
+ result = this.addDescription(result, symbol.node, `${resolvedImport.prefix}:${symbol.name}`, imported.document);
266
+ }
267
+ const separator = imported.namespace.endsWith('#') || imported.namespace.endsWith('/') ? '' : '#';
268
+ result = this.addDescription(
269
+ result,
270
+ symbol.node,
271
+ `<${imported.namespace}${separator}${symbol.name}>`,
272
+ imported.document
273
+ );
274
+ }
275
+ }
276
+ return result;
277
+ }
278
+
279
+ }