@domainlang/language 0.6.0 → 0.8.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 (88) hide show
  1. package/README.md +1 -1
  2. package/out/domain-lang-module.d.ts +2 -0
  3. package/out/domain-lang-module.js +23 -2
  4. package/out/domain-lang-module.js.map +1 -1
  5. package/out/lsp/domain-lang-completion.d.ts +142 -1
  6. package/out/lsp/domain-lang-completion.js +620 -22
  7. package/out/lsp/domain-lang-completion.js.map +1 -1
  8. package/out/lsp/domain-lang-document-symbol-provider.d.ts +79 -0
  9. package/out/lsp/domain-lang-document-symbol-provider.js +210 -0
  10. package/out/lsp/domain-lang-document-symbol-provider.js.map +1 -0
  11. package/out/lsp/domain-lang-index-manager.d.ts +98 -1
  12. package/out/lsp/domain-lang-index-manager.js +214 -7
  13. package/out/lsp/domain-lang-index-manager.js.map +1 -1
  14. package/out/lsp/domain-lang-node-kind-provider.d.ts +27 -0
  15. package/out/lsp/domain-lang-node-kind-provider.js +87 -0
  16. package/out/lsp/domain-lang-node-kind-provider.js.map +1 -0
  17. package/out/lsp/domain-lang-scope-provider.d.ts +100 -0
  18. package/out/lsp/domain-lang-scope-provider.js +170 -0
  19. package/out/lsp/domain-lang-scope-provider.js.map +1 -0
  20. package/out/lsp/domain-lang-workspace-manager.d.ts +46 -0
  21. package/out/lsp/domain-lang-workspace-manager.js +148 -4
  22. package/out/lsp/domain-lang-workspace-manager.js.map +1 -1
  23. package/out/lsp/hover/domain-lang-hover.d.ts +16 -6
  24. package/out/lsp/hover/domain-lang-hover.js +160 -134
  25. package/out/lsp/hover/domain-lang-hover.js.map +1 -1
  26. package/out/lsp/hover/hover-builders.d.ts +57 -0
  27. package/out/lsp/hover/hover-builders.js +171 -0
  28. package/out/lsp/hover/hover-builders.js.map +1 -0
  29. package/out/main.js +116 -20
  30. package/out/main.js.map +1 -1
  31. package/out/sdk/index.d.ts +2 -1
  32. package/out/sdk/index.js +1 -1
  33. package/out/sdk/index.js.map +1 -1
  34. package/out/sdk/loader-node.js +1 -1
  35. package/out/sdk/loader-node.js.map +1 -1
  36. package/out/sdk/loader.d.ts +55 -2
  37. package/out/sdk/loader.js +87 -28
  38. package/out/sdk/loader.js.map +1 -1
  39. package/out/sdk/query.js +14 -11
  40. package/out/sdk/query.js.map +1 -1
  41. package/out/services/import-resolver.d.ts +29 -6
  42. package/out/services/import-resolver.js +48 -9
  43. package/out/services/import-resolver.js.map +1 -1
  44. package/out/services/package-boundary-detector.d.ts +101 -0
  45. package/out/services/package-boundary-detector.js +211 -0
  46. package/out/services/package-boundary-detector.js.map +1 -0
  47. package/out/services/performance-optimizer.js +6 -2
  48. package/out/services/performance-optimizer.js.map +1 -1
  49. package/out/services/types.d.ts +24 -0
  50. package/out/services/types.js.map +1 -1
  51. package/out/services/workspace-manager.d.ts +73 -6
  52. package/out/services/workspace-manager.js +210 -57
  53. package/out/services/workspace-manager.js.map +1 -1
  54. package/out/utils/import-utils.d.ts +9 -6
  55. package/out/utils/import-utils.js +26 -15
  56. package/out/utils/import-utils.js.map +1 -1
  57. package/out/validation/constants.d.ts +20 -0
  58. package/out/validation/constants.js +39 -3
  59. package/out/validation/constants.js.map +1 -1
  60. package/out/validation/import.d.ts +22 -1
  61. package/out/validation/import.js +104 -16
  62. package/out/validation/import.js.map +1 -1
  63. package/out/validation/maps.js +101 -3
  64. package/out/validation/maps.js.map +1 -1
  65. package/package.json +5 -5
  66. package/src/domain-lang-module.ts +26 -3
  67. package/src/lsp/domain-lang-completion.ts +736 -27
  68. package/src/lsp/domain-lang-document-symbol-provider.ts +254 -0
  69. package/src/lsp/domain-lang-index-manager.ts +250 -7
  70. package/src/lsp/domain-lang-node-kind-provider.ts +119 -0
  71. package/src/lsp/domain-lang-scope-provider.ts +250 -0
  72. package/src/lsp/domain-lang-workspace-manager.ts +187 -4
  73. package/src/lsp/hover/domain-lang-hover.ts +189 -131
  74. package/src/lsp/hover/hover-builders.ts +208 -0
  75. package/src/main.ts +156 -23
  76. package/src/sdk/index.ts +2 -1
  77. package/src/sdk/loader-node.ts +2 -1
  78. package/src/sdk/loader.ts +125 -34
  79. package/src/sdk/query.ts +15 -11
  80. package/src/services/import-resolver.ts +60 -9
  81. package/src/services/package-boundary-detector.ts +238 -0
  82. package/src/services/performance-optimizer.ts +6 -2
  83. package/src/services/types.ts +25 -0
  84. package/src/services/workspace-manager.ts +259 -62
  85. package/src/utils/import-utils.ts +27 -15
  86. package/src/validation/constants.ts +47 -6
  87. package/src/validation/import.ts +124 -16
  88. package/src/validation/maps.ts +118 -4
@@ -0,0 +1,170 @@
1
+ /**
2
+ * DomainLang Scope Provider
3
+ *
4
+ * Implements import-based scoping with alias support and package-boundary transitive imports.
5
+ *
6
+ * **Key Concepts (per ADR-003):**
7
+ * - Elements are only visible if defined in current document OR explicitly imported
8
+ * - Import aliases control visibility: `import "pkg" as ddd` makes types visible as `ddd.*` only
9
+ * - Package-boundary transitive imports: External packages (.dlang/packages/) can re-export
10
+ * - Local file imports remain non-transitive (explicit dependencies only)
11
+ *
12
+ * **Why this matters:**
13
+ * Without this, Langium's DefaultScopeProvider would make ALL indexed documents visible
14
+ * in the global scope, which would:
15
+ * 1. Allow referencing elements that haven't been imported
16
+ * 2. Make the import system meaningless
17
+ * 3. Create confusion about dependencies between files
18
+ *
19
+ * @see https://langium.org/docs/recipes/scoping/ for Langium scoping patterns
20
+ * @see ADR-003 for alias and package-boundary design decisions
21
+ */
22
+ import { AstUtils, DefaultScopeProvider, EMPTY_SCOPE, MapScope, stream } from 'langium';
23
+ /**
24
+ * Custom scope provider that restricts cross-file references to imported documents only.
25
+ *
26
+ * Extends Langium's DefaultScopeProvider to override the global scope computation.
27
+ */
28
+ export class DomainLangScopeProvider extends DefaultScopeProvider {
29
+ constructor(services) {
30
+ super(services);
31
+ this.domainLangIndexManager = services.shared.workspace.IndexManager;
32
+ this.packageBoundaryDetector = services.imports.PackageBoundaryDetector;
33
+ }
34
+ /**
35
+ * Override getGlobalScope to implement alias-scoped and package-boundary transitive imports.
36
+ *
37
+ * The default Langium behavior includes ALL documents in the workspace.
38
+ * We restrict and transform scope to:
39
+ * 1. The current document's own exported symbols
40
+ * 2. Symbols from directly imported documents (with alias prefixing)
41
+ * 3. Symbols from package-boundary transitive imports (external packages only)
42
+ *
43
+ * @param referenceType - The AST type being referenced
44
+ * @param context - Information about the reference
45
+ * @returns A scope containing only visible elements
46
+ */
47
+ getGlobalScope(referenceType, context) {
48
+ try {
49
+ const document = AstUtils.getDocument(context.container);
50
+ if (!document) {
51
+ return EMPTY_SCOPE;
52
+ }
53
+ const descriptions = this.computeVisibleDescriptions(referenceType, document);
54
+ return new MapScope(descriptions);
55
+ }
56
+ catch (error) {
57
+ console.error('Error in getGlobalScope:', error);
58
+ return EMPTY_SCOPE;
59
+ }
60
+ }
61
+ /**
62
+ * Computes all visible descriptions for a document, including:
63
+ * - Current document's own symbols
64
+ * - Direct imports (with alias prefixing)
65
+ * - Package-boundary transitive imports
66
+ *
67
+ * @param referenceType - The AST type being referenced
68
+ * @param document - The document making the reference
69
+ * @returns Stream of visible descriptions
70
+ */
71
+ computeVisibleDescriptions(referenceType, document) {
72
+ const docUri = document.uri.toString();
73
+ const allVisibleDescriptions = [];
74
+ // 1. Always include current document's own symbols
75
+ const ownDescriptions = this.indexManager.allElements(referenceType)
76
+ .filter(desc => desc.documentUri.toString() === docUri);
77
+ allVisibleDescriptions.push(...ownDescriptions.toArray());
78
+ // 2. Get import info (with aliases)
79
+ const importInfo = this.domainLangIndexManager.getImportInfo(docUri);
80
+ // Track which documents we've already included to avoid duplicates
81
+ const processedUris = new Set([docUri]);
82
+ // 3. Process each direct import
83
+ for (const imp of importInfo) {
84
+ if (!imp.resolvedUri || processedUris.has(imp.resolvedUri)) {
85
+ continue;
86
+ }
87
+ // Add descriptions from the directly imported document
88
+ this.addDescriptionsFromImport(imp, referenceType, processedUris, allVisibleDescriptions);
89
+ // 4. Check for package-boundary transitive imports
90
+ this.addPackageBoundaryTransitiveImports(imp, referenceType, document, processedUris, allVisibleDescriptions);
91
+ }
92
+ return stream(allVisibleDescriptions);
93
+ }
94
+ /**
95
+ * Adds descriptions from a single import, applying alias prefixing if needed.
96
+ *
97
+ * @param imp - Import information (specifier, alias, resolved URI)
98
+ * @param referenceType - The AST type being referenced
99
+ * @param processedUris - Set of already-processed URIs to avoid duplicates
100
+ * @param output - Array to append visible descriptions to
101
+ */
102
+ addDescriptionsFromImport(imp, referenceType, processedUris, output) {
103
+ const descriptions = this.indexManager.allElements(referenceType)
104
+ .filter(desc => desc.documentUri.toString() === imp.resolvedUri);
105
+ if (imp.alias) {
106
+ // With alias: prefix all names with alias
107
+ // Example: CoreDomain → ddd.CoreDomain
108
+ for (const desc of descriptions) {
109
+ output.push(this.createAliasedDescription(desc, imp.alias));
110
+ }
111
+ }
112
+ else {
113
+ // Without alias: use original names
114
+ output.push(...descriptions.toArray());
115
+ }
116
+ processedUris.add(imp.resolvedUri);
117
+ }
118
+ /**
119
+ * Adds package-boundary transitive imports for external packages.
120
+ *
121
+ * When document A imports package document B (e.g., index.dlang),
122
+ * and B imports internal package files C, D, etc. (same package root),
123
+ * then A can see types from C, D, etc. (package re-exports).
124
+ *
125
+ * Local file imports remain non-transitive.
126
+ *
127
+ * @param imp - Import information for the direct import
128
+ * @param referenceType - The AST type being referenced
129
+ * @param currentDocument - The document making the reference
130
+ * @param processedUris - Set of already-processed URIs to avoid duplicates
131
+ * @param output - Array to append visible descriptions to
132
+ */
133
+ addPackageBoundaryTransitiveImports(imp, referenceType, currentDocument, processedUris, output) {
134
+ // Get the imports of the imported document (B's imports)
135
+ const transitiveImports = this.domainLangIndexManager.getImportInfo(imp.resolvedUri);
136
+ for (const transitiveImp of transitiveImports) {
137
+ if (!transitiveImp.resolvedUri || processedUris.has(transitiveImp.resolvedUri)) {
138
+ continue;
139
+ }
140
+ // Check if both documents are in the same external package
141
+ // (package boundary = same commit directory within .dlang/packages/)
142
+ const samePackage = this.packageBoundaryDetector.areInSamePackageSync(imp.resolvedUri, transitiveImp.resolvedUri);
143
+ if (samePackage) {
144
+ // Within package boundary: include transitive imports
145
+ // Apply the top-level import's alias (if any)
146
+ this.addDescriptionsFromImport({
147
+ specifier: transitiveImp.specifier,
148
+ alias: imp.alias, // Use the top-level import's alias
149
+ resolvedUri: transitiveImp.resolvedUri
150
+ }, referenceType, processedUris, output);
151
+ }
152
+ }
153
+ }
154
+ /**
155
+ * Creates an alias-prefixed version of a description.
156
+ *
157
+ * Example: CoreDomain with alias "ddd" → ddd.CoreDomain
158
+ *
159
+ * @param original - Original description
160
+ * @param alias - Import alias to prefix with
161
+ * @returns New description with prefixed name
162
+ */
163
+ createAliasedDescription(original, alias) {
164
+ return {
165
+ ...original,
166
+ name: `${alias}.${original.name}`
167
+ };
168
+ }
169
+ }
170
+ //# sourceMappingURL=domain-lang-scope-provider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"domain-lang-scope-provider.js","sourceRoot":"","sources":["../../src/lsp/domain-lang-scope-provider.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { DefaultWorkspaceManager, type FileSystemNode, type LangiumDocument, type LangiumSharedCoreServices, type WorkspaceFolder } from 'langium';
2
2
  import type { CancellationToken } from 'vscode-languageserver-protocol';
3
+ import type { DomainLangServices } from '../domain-lang-module.js';
3
4
  /**
4
5
  * Langium WorkspaceManager override implementing manifest-centric import loading per PRS-010.
5
6
  *
@@ -48,10 +49,46 @@ import type { CancellationToken } from 'vscode-languageserver-protocol';
48
49
  */
49
50
  export declare class DomainLangWorkspaceManager extends DefaultWorkspaceManager {
50
51
  private readonly sharedServices;
52
+ /**
53
+ * DI-injected import resolver. Set via late-binding because
54
+ * WorkspaceManager (shared module) is created before ImportResolver (language module).
55
+ * Falls back to standalone ensureImportGraphFromDocument when not set.
56
+ */
57
+ private importResolver;
51
58
  constructor(services: LangiumSharedCoreServices);
59
+ /**
60
+ * Late-binds the language-specific services after DI initialization.
61
+ * Called from `createDomainLangServices()` after the language module is created.
62
+ */
63
+ setLanguageServices(services: DomainLangServices): void;
52
64
  shouldIncludeEntry(entry: FileSystemNode): boolean;
53
65
  initializeWorkspace(folders: WorkspaceFolder[], cancelToken?: CancellationToken): Promise<void>;
54
66
  protected loadAdditionalDocuments(folders: WorkspaceFolder[], collector: (document: LangiumDocument) => void): Promise<void>;
67
+ /**
68
+ * Loads standalone .dlang files from workspace folders recursively.
69
+ *
70
+ * Skips:
71
+ * - Module directories (directories with model.yaml) - loaded via import graph
72
+ * - `.dlang/packages` directory - package cache managed by CLI
73
+ *
74
+ * @param folders - Workspace folders to scan
75
+ * @param moduleDirectories - Set of directories containing model.yaml (to skip)
76
+ * @param collector - Document collector callback
77
+ */
78
+ private loadStandaloneFiles;
79
+ /**
80
+ * Recursively loads .dlang files from a directory.
81
+ * Skips module directories and the .dlang/packages cache.
82
+ */
83
+ private loadDlangFilesRecursively;
84
+ /**
85
+ * Checks if a directory entry is a .dlang file.
86
+ */
87
+ private isDlangFile;
88
+ /**
89
+ * Attempts to load a document, returning undefined on failure.
90
+ */
91
+ private tryLoadDocument;
55
92
  /**
56
93
  * Finds ALL model.yaml files in the workspace.
57
94
  * Delegates to shared manifest utilities.
@@ -60,4 +97,13 @@ export declare class DomainLangWorkspaceManager extends DefaultWorkspaceManager
60
97
  * @returns Array of manifest info (one per model.yaml found)
61
98
  */
62
99
  private findAllManifestsInFolders;
100
+ /**
101
+ * Recursively builds the import graph from a document.
102
+ * Uses the DI-injected ImportResolver when available,
103
+ * falling back to the standalone utility.
104
+ *
105
+ * @param document - The starting document
106
+ * @returns Set of URIs (as strings) for all documents in the import graph
107
+ */
108
+ private loadImportGraph;
63
109
  }
@@ -1,3 +1,5 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
1
3
  import { DefaultWorkspaceManager, URI, UriUtils } from 'langium';
2
4
  import { ensureImportGraphFromDocument } from '../utils/import-utils.js';
3
5
  import { findManifestsInDirectories } from '../utils/manifest-utils.js';
@@ -52,6 +54,13 @@ export class DomainLangWorkspaceManager extends DefaultWorkspaceManager {
52
54
  super(services);
53
55
  this.sharedServices = services;
54
56
  }
57
+ /**
58
+ * Late-binds the language-specific services after DI initialization.
59
+ * Called from `createDomainLangServices()` after the language module is created.
60
+ */
61
+ setLanguageServices(services) {
62
+ this.importResolver = services.imports.ImportResolver;
63
+ }
55
64
  shouldIncludeEntry(entry) {
56
65
  // Prevent auto-including .dlang files; we'll load via entry/import graph
57
66
  const name = UriUtils.basename(entry.uri);
@@ -66,9 +75,8 @@ export class DomainLangWorkspaceManager extends DefaultWorkspaceManager {
66
75
  async loadAdditionalDocuments(folders, collector) {
67
76
  // Find ALL model.yaml files in workspace (supports mixed mode)
68
77
  const manifestInfos = await this.findAllManifestsInFolders(folders);
69
- if (manifestInfos.length === 0) {
70
- return; // Pure Mode B: no manifests, all files loaded on-demand
71
- }
78
+ // Track directories covered by manifests to avoid loading their files as standalone
79
+ const moduleDirectories = new Set(manifestInfos.map(m => path.dirname(m.manifestPath)));
72
80
  // Mode A or Mode C: Load each module's entry + import graph
73
81
  for (const manifestInfo of manifestInfos) {
74
82
  try {
@@ -79,7 +87,7 @@ export class DomainLangWorkspaceManager extends DefaultWorkspaceManager {
79
87
  await this.sharedServices.workspace.DocumentBuilder.build([entryDoc], {
80
88
  validation: true
81
89
  });
82
- const uris = await ensureImportGraphFromDocument(entryDoc, this.langiumDocuments);
90
+ const uris = await this.loadImportGraph(entryDoc);
83
91
  const importedDocs = [];
84
92
  for (const uriString of uris) {
85
93
  const uri = URI.parse(uriString);
@@ -100,6 +108,104 @@ export class DomainLangWorkspaceManager extends DefaultWorkspaceManager {
100
108
  // Continue with other modules - partial failure is acceptable
101
109
  }
102
110
  }
111
+ // Load standalone .dlang files in workspace root folders
112
+ // These are files NOT covered by any module's import graph
113
+ await this.loadStandaloneFiles(folders, moduleDirectories, collector);
114
+ }
115
+ /**
116
+ * Loads standalone .dlang files from workspace folders recursively.
117
+ *
118
+ * Skips:
119
+ * - Module directories (directories with model.yaml) - loaded via import graph
120
+ * - `.dlang/packages` directory - package cache managed by CLI
121
+ *
122
+ * @param folders - Workspace folders to scan
123
+ * @param moduleDirectories - Set of directories containing model.yaml (to skip)
124
+ * @param collector - Document collector callback
125
+ */
126
+ async loadStandaloneFiles(folders, moduleDirectories, collector) {
127
+ const standaloneDocs = [];
128
+ for (const folder of folders) {
129
+ const folderPath = URI.parse(folder.uri).fsPath;
130
+ const docs = await this.loadDlangFilesRecursively(folderPath, moduleDirectories, collector);
131
+ standaloneDocs.push(...docs);
132
+ }
133
+ // Build all standalone documents in batch for performance
134
+ if (standaloneDocs.length > 0) {
135
+ await this.sharedServices.workspace.DocumentBuilder.build(standaloneDocs, {
136
+ validation: true
137
+ });
138
+ }
139
+ }
140
+ /**
141
+ * Recursively loads .dlang files from a directory.
142
+ * Skips module directories and the .dlang/packages cache.
143
+ */
144
+ async loadDlangFilesRecursively(dirPath, moduleDirectories, collector) {
145
+ // Skip module directories - they're loaded via import graph
146
+ if (moduleDirectories.has(dirPath)) {
147
+ return [];
148
+ }
149
+ // Skip .dlang/packages - package cache managed by CLI
150
+ const baseName = path.basename(dirPath);
151
+ const parentName = path.basename(path.dirname(dirPath));
152
+ if (baseName === 'packages' && parentName === '.dlang') {
153
+ return [];
154
+ }
155
+ // Also skip the .dlang directory itself (contains packages cache)
156
+ if (baseName === '.dlang') {
157
+ return [];
158
+ }
159
+ const docs = [];
160
+ try {
161
+ const entries = await fs.readdir(dirPath, { withFileTypes: true });
162
+ for (const entry of entries) {
163
+ const entryPath = path.join(dirPath, entry.name);
164
+ if (entry.isDirectory()) {
165
+ // Recurse into subdirectories
166
+ const subDocs = await this.loadDlangFilesRecursively(entryPath, moduleDirectories, collector);
167
+ docs.push(...subDocs);
168
+ }
169
+ else if (this.isDlangFile(entry)) {
170
+ const doc = await this.tryLoadDocument(dirPath, entry.name, collector);
171
+ if (doc) {
172
+ docs.push(doc);
173
+ }
174
+ }
175
+ }
176
+ }
177
+ catch (error) {
178
+ const message = error instanceof Error ? error.message : String(error);
179
+ console.warn(`Failed to read directory ${dirPath}: ${message}`);
180
+ }
181
+ return docs;
182
+ }
183
+ /**
184
+ * Checks if a directory entry is a .dlang file.
185
+ */
186
+ isDlangFile(entry) {
187
+ return entry.isFile() && entry.name.toLowerCase().endsWith('.dlang');
188
+ }
189
+ /**
190
+ * Attempts to load a document, returning undefined on failure.
191
+ */
192
+ async tryLoadDocument(folderPath, fileName, collector) {
193
+ const filePath = path.join(folderPath, fileName);
194
+ const uri = URI.file(filePath);
195
+ // Skip if already loaded (e.g., through imports)
196
+ if (this.langiumDocuments.hasDocument(uri)) {
197
+ return undefined;
198
+ }
199
+ try {
200
+ const doc = await this.langiumDocuments.getOrCreateDocument(uri);
201
+ collector(doc);
202
+ return doc;
203
+ }
204
+ catch (error) {
205
+ const message = error instanceof Error ? error.message : String(error);
206
+ console.warn(`Failed to load standalone file ${filePath}: ${message}`);
207
+ return undefined;
208
+ }
103
209
  }
104
210
  /**
105
211
  * Finds ALL model.yaml files in the workspace.
@@ -112,5 +218,43 @@ export class DomainLangWorkspaceManager extends DefaultWorkspaceManager {
112
218
  const directories = folders.map(f => URI.parse(f.uri).fsPath);
113
219
  return findManifestsInDirectories(directories);
114
220
  }
221
+ /**
222
+ * Recursively builds the import graph from a document.
223
+ * Uses the DI-injected ImportResolver when available,
224
+ * falling back to the standalone utility.
225
+ *
226
+ * @param document - The starting document
227
+ * @returns Set of URIs (as strings) for all documents in the import graph
228
+ */
229
+ async loadImportGraph(document) {
230
+ if (!this.importResolver) {
231
+ // Fallback to standalone utility when DI isn't wired
232
+ return ensureImportGraphFromDocument(document, this.langiumDocuments);
233
+ }
234
+ const resolver = this.importResolver;
235
+ const langiumDocuments = this.langiumDocuments;
236
+ const visited = new Set();
237
+ async function visit(doc) {
238
+ const uriString = doc.uri.toString();
239
+ if (visited.has(uriString))
240
+ return;
241
+ visited.add(uriString);
242
+ const model = doc.parseResult.value;
243
+ for (const imp of model.imports ?? []) {
244
+ if (!imp.uri)
245
+ continue;
246
+ try {
247
+ const resolvedUri = await resolver.resolveForDocument(doc, imp.uri);
248
+ const childDoc = await langiumDocuments.getOrCreateDocument(resolvedUri);
249
+ await visit(childDoc);
250
+ }
251
+ catch {
252
+ // Import resolution failed — validation will report the error
253
+ }
254
+ }
255
+ }
256
+ await visit(document);
257
+ return visited;
258
+ }
115
259
  }
116
260
  //# sourceMappingURL=domain-lang-workspace-manager.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"domain-lang-workspace-manager.js","sourceRoot":"","sources":["../../src/lsp/domain-lang-workspace-manager.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"domain-lang-workspace-manager.js","sourceRoot":"","sources":["../../src/lsp/domain-lang-workspace-manager.ts"],"names":[],"mappings":"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"}
@@ -3,6 +3,7 @@ import type { LangiumServices } from 'langium/lsp';
3
3
  import { AstNodeHoverProvider } from 'langium/lsp';
4
4
  import type { Hover, HoverParams } from 'vscode-languageserver';
5
5
  import { QualifiedNameProvider } from '../domain-lang-naming.js';
6
+ import type { DomainLangIndexManager } from '../domain-lang-index-manager.js';
6
7
  /**
7
8
  * Provides hover information for DomainLang elements.
8
9
  *
@@ -13,6 +14,7 @@ export declare class DomainLangHoverProvider extends AstNodeHoverProvider {
13
14
  protected readonly documentationProvider: DocumentationProvider;
14
15
  protected readonly commentProvider: CommentProvider;
15
16
  protected readonly qualifiedNameProvider: QualifiedNameProvider;
17
+ protected readonly indexManager: DomainLangIndexManager;
16
18
  /**
17
19
  * Registry of type-specific hover content generators.
18
20
  * Each generator returns content for its node type, or undefined to skip.
@@ -22,6 +24,8 @@ export declare class DomainLangHoverProvider extends AstNodeHoverProvider {
22
24
  getHoverContent(document: LangiumDocument, params: HoverParams): Promise<Hover | undefined>;
23
25
  /**
24
26
  * Try to get hover for a declaration node (AST node).
27
+ * For qualified name references, only shows hover when hovering over the last segment.
28
+ * For qualified name declarations (like namespace names), shows hover on any segment.
25
29
  */
26
30
  private tryGetDeclarationHover;
27
31
  /**
@@ -29,7 +33,12 @@ export declare class DomainLangHoverProvider extends AstNodeHoverProvider {
29
33
  * Uses the keyword dictionary for all keywords.
30
34
  */
31
35
  private tryGetKeywordHover;
32
- protected getAstNodeHoverContent(node: AstNode): MaybePromise<string | undefined>;
36
+ protected getAstNodeHoverContent(node: AstNode, currentDocument?: LangiumDocument): MaybePromise<string | undefined>;
37
+ /**
38
+ * Gets the import alias for a node if it's from an imported document.
39
+ * Returns undefined if the node is in the same document or not imported with an alias.
40
+ */
41
+ private getImportAliasForNode;
33
42
  private getDomainHover;
34
43
  private getThisRefHover;
35
44
  private getBoundedContextHover;
@@ -47,17 +56,18 @@ export declare class DomainLangHoverProvider extends AstNodeHoverProvider {
47
56
  private getImportHover;
48
57
  private getDefaultHover;
49
58
  /**
50
- * Formats a relationship line for hover display.
59
+ * Computes the display name for a node in hover, considering import aliases.
60
+ * If node is imported with an alias, shows `alias.name`, otherwise shows full qualified name.
51
61
  */
52
- private formatRelationshipLine;
62
+ private getDisplayNameForHover;
53
63
  /**
54
- * Wraps text in a domain-lang code block.
64
+ * Formats a relationship line for hover display.
55
65
  */
56
- private codeBlock;
66
+ private formatRelationshipLine;
57
67
  /**
58
68
  * Formats the final hover content with consistent structure.
69
+ * Delegates to the shared hover-builders utility.
59
70
  */
60
71
  private formatHover;
61
- private getRefName;
62
72
  private refLink;
63
73
  }