@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.
- package/README.md +1 -1
- package/out/domain-lang-module.d.ts +2 -0
- package/out/domain-lang-module.js +23 -2
- package/out/domain-lang-module.js.map +1 -1
- package/out/lsp/domain-lang-completion.d.ts +142 -1
- package/out/lsp/domain-lang-completion.js +620 -22
- package/out/lsp/domain-lang-completion.js.map +1 -1
- package/out/lsp/domain-lang-document-symbol-provider.d.ts +79 -0
- package/out/lsp/domain-lang-document-symbol-provider.js +210 -0
- package/out/lsp/domain-lang-document-symbol-provider.js.map +1 -0
- package/out/lsp/domain-lang-index-manager.d.ts +98 -1
- package/out/lsp/domain-lang-index-manager.js +214 -7
- package/out/lsp/domain-lang-index-manager.js.map +1 -1
- package/out/lsp/domain-lang-node-kind-provider.d.ts +27 -0
- package/out/lsp/domain-lang-node-kind-provider.js +87 -0
- package/out/lsp/domain-lang-node-kind-provider.js.map +1 -0
- package/out/lsp/domain-lang-scope-provider.d.ts +100 -0
- package/out/lsp/domain-lang-scope-provider.js +170 -0
- package/out/lsp/domain-lang-scope-provider.js.map +1 -0
- package/out/lsp/domain-lang-workspace-manager.d.ts +46 -0
- package/out/lsp/domain-lang-workspace-manager.js +148 -4
- package/out/lsp/domain-lang-workspace-manager.js.map +1 -1
- package/out/lsp/hover/domain-lang-hover.d.ts +16 -6
- package/out/lsp/hover/domain-lang-hover.js +160 -134
- package/out/lsp/hover/domain-lang-hover.js.map +1 -1
- package/out/lsp/hover/hover-builders.d.ts +57 -0
- package/out/lsp/hover/hover-builders.js +171 -0
- package/out/lsp/hover/hover-builders.js.map +1 -0
- package/out/main.js +116 -20
- package/out/main.js.map +1 -1
- package/out/sdk/index.d.ts +2 -1
- package/out/sdk/index.js +1 -1
- package/out/sdk/index.js.map +1 -1
- package/out/sdk/loader-node.js +1 -1
- package/out/sdk/loader-node.js.map +1 -1
- package/out/sdk/loader.d.ts +55 -2
- package/out/sdk/loader.js +87 -28
- package/out/sdk/loader.js.map +1 -1
- package/out/sdk/query.js +14 -11
- package/out/sdk/query.js.map +1 -1
- package/out/services/import-resolver.d.ts +29 -6
- package/out/services/import-resolver.js +48 -9
- package/out/services/import-resolver.js.map +1 -1
- package/out/services/package-boundary-detector.d.ts +101 -0
- package/out/services/package-boundary-detector.js +211 -0
- package/out/services/package-boundary-detector.js.map +1 -0
- package/out/services/performance-optimizer.js +6 -2
- package/out/services/performance-optimizer.js.map +1 -1
- package/out/services/types.d.ts +24 -0
- package/out/services/types.js.map +1 -1
- package/out/services/workspace-manager.d.ts +73 -6
- package/out/services/workspace-manager.js +210 -57
- package/out/services/workspace-manager.js.map +1 -1
- package/out/utils/import-utils.d.ts +9 -6
- package/out/utils/import-utils.js +26 -15
- package/out/utils/import-utils.js.map +1 -1
- package/out/validation/constants.d.ts +20 -0
- package/out/validation/constants.js +39 -3
- package/out/validation/constants.js.map +1 -1
- package/out/validation/import.d.ts +22 -1
- package/out/validation/import.js +104 -16
- package/out/validation/import.js.map +1 -1
- package/out/validation/maps.js +101 -3
- package/out/validation/maps.js.map +1 -1
- package/package.json +5 -5
- package/src/domain-lang-module.ts +26 -3
- package/src/lsp/domain-lang-completion.ts +736 -27
- package/src/lsp/domain-lang-document-symbol-provider.ts +254 -0
- package/src/lsp/domain-lang-index-manager.ts +250 -7
- package/src/lsp/domain-lang-node-kind-provider.ts +119 -0
- package/src/lsp/domain-lang-scope-provider.ts +250 -0
- package/src/lsp/domain-lang-workspace-manager.ts +187 -4
- package/src/lsp/hover/domain-lang-hover.ts +189 -131
- package/src/lsp/hover/hover-builders.ts +208 -0
- package/src/main.ts +156 -23
- package/src/sdk/index.ts +2 -1
- package/src/sdk/loader-node.ts +2 -1
- package/src/sdk/loader.ts +125 -34
- package/src/sdk/query.ts +15 -11
- package/src/services/import-resolver.ts +60 -9
- package/src/services/package-boundary-detector.ts +238 -0
- package/src/services/performance-optimizer.ts +6 -2
- package/src/services/types.ts +25 -0
- package/src/services/workspace-manager.ts +259 -62
- package/src/utils/import-utils.ts +27 -15
- package/src/validation/constants.ts +47 -6
- package/src/validation/import.ts +124 -16
- package/src/validation/maps.ts +118 -4
|
@@ -14,6 +14,7 @@ import { resolveImportPath } from '../utils/import-utils.js';
|
|
|
14
14
|
* **How it works:**
|
|
15
15
|
* - When a document is indexed, we ensure all its imports are also loaded
|
|
16
16
|
* - Maintains a reverse dependency graph: importedUri → Set<importingUri>
|
|
17
|
+
* - Also tracks import specifiers to detect when file moves affect resolution
|
|
17
18
|
* - Overrides `isAffected()` to also check this graph
|
|
18
19
|
* - This integrates with Langium's native `DocumentBuilder.update()` flow
|
|
19
20
|
*
|
|
@@ -33,6 +34,13 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
33
34
|
* Value: Set of URIs of documents that import the key document
|
|
34
35
|
*/
|
|
35
36
|
this.importDependencies = new Map();
|
|
37
|
+
/**
|
|
38
|
+
* Maps document URI to its import information (specifier, alias, resolved URI).
|
|
39
|
+
* Used for scope resolution with aliases and detecting when file moves affect imports.
|
|
40
|
+
* Key: importing document URI
|
|
41
|
+
* Value: Array of ImportInfo objects
|
|
42
|
+
*/
|
|
43
|
+
this.documentImportInfo = new Map();
|
|
36
44
|
/**
|
|
37
45
|
* Tracks documents that have had their imports loaded to avoid redundant work.
|
|
38
46
|
* Cleared on workspace config changes.
|
|
@@ -40,6 +48,27 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
40
48
|
this.importsLoaded = new Set();
|
|
41
49
|
this.sharedServices = services;
|
|
42
50
|
}
|
|
51
|
+
/**
|
|
52
|
+
* Late-binds the language-specific services after DI initialization.
|
|
53
|
+
* Called from `createDomainLangServices()` after the language module is created.
|
|
54
|
+
*
|
|
55
|
+
* This is necessary because the IndexManager lives in the shared module,
|
|
56
|
+
* which is created before the language module that provides ImportResolver.
|
|
57
|
+
*/
|
|
58
|
+
setLanguageServices(services) {
|
|
59
|
+
this.importResolver = services.imports.ImportResolver;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Resolves an import path using the DI-injected ImportResolver when available,
|
|
63
|
+
* falling back to the standalone resolver for backwards compatibility.
|
|
64
|
+
*/
|
|
65
|
+
async resolveImport(document, specifier) {
|
|
66
|
+
if (this.importResolver) {
|
|
67
|
+
return this.importResolver.resolveForDocument(document, specifier);
|
|
68
|
+
}
|
|
69
|
+
// Fallback for contexts where language services aren't wired (e.g., tests)
|
|
70
|
+
return resolveImportPath(document, specifier);
|
|
71
|
+
}
|
|
43
72
|
/**
|
|
44
73
|
* Extends the default content update to:
|
|
45
74
|
* 1. Ensure all imported documents are loaded
|
|
@@ -97,13 +126,16 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
97
126
|
}
|
|
98
127
|
/**
|
|
99
128
|
* Tracks import dependencies for a document.
|
|
100
|
-
* For each import in the document, records
|
|
129
|
+
* For each import in the document, records:
|
|
130
|
+
* 1. That the imported URI is depended upon (for direct change detection)
|
|
131
|
+
* 2. The import specifier and alias (for scope resolution)
|
|
101
132
|
*/
|
|
102
133
|
async trackImportDependencies(document) {
|
|
103
134
|
const importingUri = document.uri.toString();
|
|
104
135
|
// First, remove old dependencies from this document
|
|
105
136
|
// (in case imports changed)
|
|
106
137
|
this.removeDocumentFromDependencies(importingUri);
|
|
138
|
+
this.documentImportInfo.delete(importingUri);
|
|
107
139
|
// Skip if document isn't ready (no parse result)
|
|
108
140
|
if (document.state < DocumentState.Parsed) {
|
|
109
141
|
return;
|
|
@@ -112,12 +144,19 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
112
144
|
if (!model.imports) {
|
|
113
145
|
return;
|
|
114
146
|
}
|
|
147
|
+
const importInfoList = [];
|
|
115
148
|
for (const imp of model.imports) {
|
|
116
149
|
if (!imp.uri)
|
|
117
150
|
continue;
|
|
118
151
|
try {
|
|
119
|
-
const resolvedUri = await
|
|
152
|
+
const resolvedUri = await this.resolveImport(document, imp.uri);
|
|
120
153
|
const importedUri = resolvedUri.toString();
|
|
154
|
+
// Track the full import info (specifier, alias, resolved URI)
|
|
155
|
+
importInfoList.push({
|
|
156
|
+
specifier: imp.uri,
|
|
157
|
+
alias: imp.alias,
|
|
158
|
+
resolvedUri: importedUri
|
|
159
|
+
});
|
|
121
160
|
// Add to reverse dependency graph: importedUri → importingUri
|
|
122
161
|
let dependents = this.importDependencies.get(importedUri);
|
|
123
162
|
if (!dependents) {
|
|
@@ -127,9 +166,17 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
127
166
|
dependents.add(importingUri);
|
|
128
167
|
}
|
|
129
168
|
catch {
|
|
130
|
-
// Import resolution failed -
|
|
169
|
+
// Import resolution failed - still track the specifier with empty resolution
|
|
170
|
+
importInfoList.push({
|
|
171
|
+
specifier: imp.uri,
|
|
172
|
+
alias: imp.alias,
|
|
173
|
+
resolvedUri: ''
|
|
174
|
+
});
|
|
131
175
|
}
|
|
132
176
|
}
|
|
177
|
+
if (importInfoList.length > 0) {
|
|
178
|
+
this.documentImportInfo.set(importingUri, importInfoList);
|
|
179
|
+
}
|
|
133
180
|
}
|
|
134
181
|
/**
|
|
135
182
|
* Ensures all imported documents are loaded and available.
|
|
@@ -160,7 +207,7 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
160
207
|
if (!imp.uri)
|
|
161
208
|
continue;
|
|
162
209
|
try {
|
|
163
|
-
const resolvedUri = await
|
|
210
|
+
const resolvedUri = await this.resolveImport(document, imp.uri);
|
|
164
211
|
const importedUriString = resolvedUri.toString();
|
|
165
212
|
// Skip if already loaded
|
|
166
213
|
if (this.importsLoaded.has(importedUriString)) {
|
|
@@ -168,8 +215,10 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
168
215
|
}
|
|
169
216
|
// Load or create the imported document
|
|
170
217
|
const importedDoc = await langiumDocuments.getOrCreateDocument(resolvedUri);
|
|
171
|
-
// If document is
|
|
172
|
-
|
|
218
|
+
// If document is not yet validated, add to batch for building
|
|
219
|
+
// This ensures all imported documents reach Validated state,
|
|
220
|
+
// preventing "workspace state is already Validated" errors
|
|
221
|
+
if (importedDoc.state < DocumentState.Validated) {
|
|
173
222
|
newDocs.push(importedDoc);
|
|
174
223
|
}
|
|
175
224
|
}
|
|
@@ -177,7 +226,7 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
177
226
|
// Import resolution failed - validation will report the error
|
|
178
227
|
}
|
|
179
228
|
}
|
|
180
|
-
// Build any newly discovered documents
|
|
229
|
+
// Build any newly discovered documents to Validated state
|
|
181
230
|
// This triggers indexing which will recursively load their imports
|
|
182
231
|
if (newDocs.length > 0) {
|
|
183
232
|
await documentBuilder.build(newDocs, { validation: true });
|
|
@@ -208,6 +257,7 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
208
257
|
*/
|
|
209
258
|
clearImportDependencies() {
|
|
210
259
|
this.importDependencies.clear();
|
|
260
|
+
this.documentImportInfo.clear();
|
|
211
261
|
this.importsLoaded.clear();
|
|
212
262
|
}
|
|
213
263
|
/**
|
|
@@ -217,5 +267,162 @@ export class DomainLangIndexManager extends DefaultIndexManager {
|
|
|
217
267
|
markForReprocessing(uri) {
|
|
218
268
|
this.importsLoaded.delete(uri);
|
|
219
269
|
}
|
|
270
|
+
/**
|
|
271
|
+
* Gets all documents that import the given URI.
|
|
272
|
+
* Used to find documents that need rebuilding when a file changes.
|
|
273
|
+
*
|
|
274
|
+
* @param uri - The URI of the changed/deleted file
|
|
275
|
+
* @returns Set of URIs (as strings) of documents that import this file
|
|
276
|
+
*/
|
|
277
|
+
getDependentDocuments(uri) {
|
|
278
|
+
return this.importDependencies.get(uri) ?? new Set();
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Gets the resolved import URIs for a document.
|
|
282
|
+
* Returns only URIs where import resolution succeeded (non-empty resolved URI).
|
|
283
|
+
*
|
|
284
|
+
* @param documentUri - The URI of the document
|
|
285
|
+
* @returns Set of resolved import URIs, or empty set if none
|
|
286
|
+
*/
|
|
287
|
+
getResolvedImports(documentUri) {
|
|
288
|
+
const importInfoList = this.documentImportInfo.get(documentUri);
|
|
289
|
+
if (!importInfoList) {
|
|
290
|
+
return new Set();
|
|
291
|
+
}
|
|
292
|
+
const resolved = new Set();
|
|
293
|
+
for (const info of importInfoList) {
|
|
294
|
+
// Only include successfully resolved imports (non-empty string)
|
|
295
|
+
if (info.resolvedUri) {
|
|
296
|
+
resolved.add(info.resolvedUri);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
return resolved;
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Gets the full import information (including aliases) for a document.
|
|
303
|
+
* Used by the scope provider to implement alias-prefixed name resolution.
|
|
304
|
+
*
|
|
305
|
+
* @param documentUri - The URI of the document
|
|
306
|
+
* @returns Array of ImportInfo objects, or empty array if none
|
|
307
|
+
*/
|
|
308
|
+
getImportInfo(documentUri) {
|
|
309
|
+
return this.documentImportInfo.get(documentUri) ?? [];
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Gets all documents that would be affected by changes to the given URIs.
|
|
313
|
+
* This includes direct dependents and transitive dependents.
|
|
314
|
+
*
|
|
315
|
+
* @param changedUris - URIs of changed/deleted files
|
|
316
|
+
* @returns Set of all affected document URIs
|
|
317
|
+
*/
|
|
318
|
+
getAllAffectedDocuments(changedUris) {
|
|
319
|
+
const affected = new Set();
|
|
320
|
+
const toProcess = [...changedUris];
|
|
321
|
+
while (toProcess.length > 0) {
|
|
322
|
+
const uri = toProcess.pop();
|
|
323
|
+
if (!uri) {
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
const dependents = this.importDependencies.get(uri);
|
|
327
|
+
if (dependents) {
|
|
328
|
+
for (const dep of dependents) {
|
|
329
|
+
if (!affected.has(dep)) {
|
|
330
|
+
affected.add(dep);
|
|
331
|
+
// Also check transitive dependents
|
|
332
|
+
toProcess.push(dep);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
return affected;
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Gets documents that have import specifiers which might be affected by file moves.
|
|
341
|
+
*
|
|
342
|
+
* When a file is moved/renamed, import specifiers that previously resolved to it
|
|
343
|
+
* (or could now resolve to it) need to be re-evaluated. This method finds documents
|
|
344
|
+
* whose imports might resolve differently after the file system change.
|
|
345
|
+
*
|
|
346
|
+
* @param changedUris - URIs of changed/deleted/created files
|
|
347
|
+
* @returns Set of document URIs that should be rebuilt
|
|
348
|
+
*/
|
|
349
|
+
getDocumentsWithPotentiallyAffectedImports(changedUris) {
|
|
350
|
+
const changedPaths = this.extractPathSegments(changedUris);
|
|
351
|
+
return this.findDocumentsMatchingPaths(changedPaths);
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Extracts path segments from URIs for fuzzy matching.
|
|
355
|
+
*/
|
|
356
|
+
extractPathSegments(uris) {
|
|
357
|
+
const paths = new Set();
|
|
358
|
+
for (const uri of uris) {
|
|
359
|
+
this.addPathSegmentsFromUri(uri, paths);
|
|
360
|
+
}
|
|
361
|
+
return paths;
|
|
362
|
+
}
|
|
363
|
+
/**
|
|
364
|
+
* Adds path segments from a single URI to the set.
|
|
365
|
+
*/
|
|
366
|
+
addPathSegmentsFromUri(uri, paths) {
|
|
367
|
+
try {
|
|
368
|
+
const url = new URL(uri);
|
|
369
|
+
const pathParts = url.pathname.split('/').filter(p => p.length > 0);
|
|
370
|
+
// Add filename
|
|
371
|
+
const fileName = pathParts.at(-1);
|
|
372
|
+
if (fileName) {
|
|
373
|
+
paths.add(fileName);
|
|
374
|
+
}
|
|
375
|
+
// Add parent/filename combination
|
|
376
|
+
if (pathParts.length >= 2) {
|
|
377
|
+
paths.add(pathParts.slice(-2).join('/'));
|
|
378
|
+
}
|
|
379
|
+
// Add grandparent/parent/filename combination
|
|
380
|
+
if (pathParts.length >= 3) {
|
|
381
|
+
paths.add(pathParts.slice(-3).join('/'));
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
catch {
|
|
385
|
+
// Invalid URI, skip
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Finds documents with import specifiers matching any of the given paths.
|
|
390
|
+
*/
|
|
391
|
+
findDocumentsMatchingPaths(changedPaths) {
|
|
392
|
+
const affected = new Set();
|
|
393
|
+
for (const [docUri, importInfoList] of this.documentImportInfo) {
|
|
394
|
+
if (this.hasMatchingSpecifierOrResolvedUri(importInfoList, changedPaths)) {
|
|
395
|
+
affected.add(docUri);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
return affected;
|
|
399
|
+
}
|
|
400
|
+
/**
|
|
401
|
+
* Checks if any specifier OR its resolved URI matches the changed paths.
|
|
402
|
+
*
|
|
403
|
+
* This handles both regular imports and path aliases:
|
|
404
|
+
* - Regular: `./domains/sales.dlang` matches path `sales.dlang`
|
|
405
|
+
* - Aliased: `@domains/sales.dlang` resolves to `/full/path/domains/sales.dlang`
|
|
406
|
+
* When the file moves, the resolved URI matches but the specifier doesn't
|
|
407
|
+
*
|
|
408
|
+
* We check both to ensure moves of aliased imports trigger revalidation.
|
|
409
|
+
*/
|
|
410
|
+
hasMatchingSpecifierOrResolvedUri(importInfoList, changedPaths) {
|
|
411
|
+
for (const info of importInfoList) {
|
|
412
|
+
const normalizedSpecifier = info.specifier.replace(/^[.@/]+/, '');
|
|
413
|
+
for (const changedPath of changedPaths) {
|
|
414
|
+
// Check the raw specifier (handles relative imports)
|
|
415
|
+
if (info.specifier.includes(changedPath) || changedPath.endsWith(normalizedSpecifier)) {
|
|
416
|
+
return true;
|
|
417
|
+
}
|
|
418
|
+
// Check the resolved URI (handles path aliases like @domains/...)
|
|
419
|
+
// The resolved URI contains the full file path which matches moved files
|
|
420
|
+
if (info.resolvedUri?.includes(changedPath)) {
|
|
421
|
+
return true;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return false;
|
|
426
|
+
}
|
|
220
427
|
}
|
|
221
428
|
//# sourceMappingURL=domain-lang-index-manager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"domain-lang-index-manager.js","sourceRoot":"","sources":["../../src/lsp/domain-lang-index-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;
|
|
1
|
+
{"version":3,"file":"domain-lang-index-manager.js","sourceRoot":"","sources":["../../src/lsp/domain-lang-index-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom NodeKindProvider — maps DomainLang AST types to VS Code SymbolKinds.
|
|
3
|
+
*
|
|
4
|
+
* Langium's DefaultNodeKindProvider returns `SymbolKind.Field` for everything.
|
|
5
|
+
* This override provides semantically meaningful icons for the Outline view,
|
|
6
|
+
* breadcrumbs, Go to Symbol, and completion items.
|
|
7
|
+
*
|
|
8
|
+
* @module lsp/domain-lang-node-kind-provider
|
|
9
|
+
*/
|
|
10
|
+
import { DefaultNodeKindProvider } from 'langium/lsp';
|
|
11
|
+
import { CompletionItemKind, SymbolKind } from 'vscode-languageserver';
|
|
12
|
+
import type { AstNode, AstNodeDescription } from 'langium';
|
|
13
|
+
/**
|
|
14
|
+
* Maps DomainLang AST types to semantically appropriate SymbolKind values.
|
|
15
|
+
*
|
|
16
|
+
* Used by the DocumentSymbolProvider (outline/breadcrumbs), WorkspaceSymbolProvider,
|
|
17
|
+
* and the CompletionProvider.
|
|
18
|
+
*/
|
|
19
|
+
export declare class DomainLangNodeKindProvider extends DefaultNodeKindProvider {
|
|
20
|
+
getSymbolKind(node: AstNode | AstNodeDescription): SymbolKind;
|
|
21
|
+
getCompletionItemKind(node: AstNode | AstNodeDescription): CompletionItemKind;
|
|
22
|
+
/**
|
|
23
|
+
* Resolves an AstNode from an AstNodeDescription (which may only have a reference).
|
|
24
|
+
* Returns the node directly if it's already an AstNode.
|
|
25
|
+
*/
|
|
26
|
+
private resolveNode;
|
|
27
|
+
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom NodeKindProvider — maps DomainLang AST types to VS Code SymbolKinds.
|
|
3
|
+
*
|
|
4
|
+
* Langium's DefaultNodeKindProvider returns `SymbolKind.Field` for everything.
|
|
5
|
+
* This override provides semantically meaningful icons for the Outline view,
|
|
6
|
+
* breadcrumbs, Go to Symbol, and completion items.
|
|
7
|
+
*
|
|
8
|
+
* @module lsp/domain-lang-node-kind-provider
|
|
9
|
+
*/
|
|
10
|
+
import { DefaultNodeKindProvider } from 'langium/lsp';
|
|
11
|
+
import { CompletionItemKind, SymbolKind } from 'vscode-languageserver';
|
|
12
|
+
import { isDomain, isBoundedContext, isTeam, isClassification, isMetadata, isContextMap, isDomainMap, isNamespaceDeclaration, isRelationship, isDomainTerm, isDecision, isPolicy, isBusinessRule, isMetadataEntry, } from '../generated/ast.js';
|
|
13
|
+
const KIND_MAPPINGS = [
|
|
14
|
+
// Strategic design
|
|
15
|
+
[isDomain, SymbolKind.Namespace, CompletionItemKind.Folder],
|
|
16
|
+
[isBoundedContext, SymbolKind.Package, CompletionItemKind.Module],
|
|
17
|
+
// Tactical design
|
|
18
|
+
[isTeam, SymbolKind.Interface, CompletionItemKind.Interface],
|
|
19
|
+
[isClassification, SymbolKind.Enum, CompletionItemKind.Enum],
|
|
20
|
+
[isMetadata, SymbolKind.Enum, CompletionItemKind.Enum],
|
|
21
|
+
// Architecture mapping
|
|
22
|
+
[isContextMap, SymbolKind.Package, CompletionItemKind.Module],
|
|
23
|
+
[isDomainMap, SymbolKind.Package, CompletionItemKind.Module],
|
|
24
|
+
// Module system
|
|
25
|
+
[isNamespaceDeclaration, SymbolKind.Namespace, CompletionItemKind.Module],
|
|
26
|
+
// Relationships
|
|
27
|
+
[isRelationship, SymbolKind.Interface, CompletionItemKind.Interface],
|
|
28
|
+
// Documentation & governance
|
|
29
|
+
[isDomainTerm, SymbolKind.Field, CompletionItemKind.Field],
|
|
30
|
+
[isDecision, SymbolKind.Field, CompletionItemKind.Field],
|
|
31
|
+
[isPolicy, SymbolKind.Field, CompletionItemKind.Field],
|
|
32
|
+
[isBusinessRule, SymbolKind.Field, CompletionItemKind.Field],
|
|
33
|
+
// Metadata entries
|
|
34
|
+
[isMetadataEntry, SymbolKind.Field, CompletionItemKind.Field],
|
|
35
|
+
];
|
|
36
|
+
/**
|
|
37
|
+
* Maps DomainLang AST types to semantically appropriate SymbolKind values.
|
|
38
|
+
*
|
|
39
|
+
* Used by the DocumentSymbolProvider (outline/breadcrumbs), WorkspaceSymbolProvider,
|
|
40
|
+
* and the CompletionProvider.
|
|
41
|
+
*/
|
|
42
|
+
export class DomainLangNodeKindProvider extends DefaultNodeKindProvider {
|
|
43
|
+
getSymbolKind(node) {
|
|
44
|
+
try {
|
|
45
|
+
const astNode = this.resolveNode(node);
|
|
46
|
+
if (!astNode)
|
|
47
|
+
return super.getSymbolKind(node);
|
|
48
|
+
for (const [guard, symbolKind] of KIND_MAPPINGS) {
|
|
49
|
+
if (guard(astNode))
|
|
50
|
+
return symbolKind;
|
|
51
|
+
}
|
|
52
|
+
return super.getSymbolKind(node);
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error('Error in getSymbolKind:', error);
|
|
56
|
+
return super.getSymbolKind(node);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
getCompletionItemKind(node) {
|
|
60
|
+
try {
|
|
61
|
+
const astNode = this.resolveNode(node);
|
|
62
|
+
if (!astNode)
|
|
63
|
+
return super.getCompletionItemKind(node);
|
|
64
|
+
for (const [guard, , completionKind] of KIND_MAPPINGS) {
|
|
65
|
+
if (guard(astNode))
|
|
66
|
+
return completionKind;
|
|
67
|
+
}
|
|
68
|
+
return super.getCompletionItemKind(node);
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
console.error('Error in getCompletionItemKind:', error);
|
|
72
|
+
return super.getCompletionItemKind(node);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Resolves an AstNode from an AstNodeDescription (which may only have a reference).
|
|
77
|
+
* Returns the node directly if it's already an AstNode.
|
|
78
|
+
*/
|
|
79
|
+
resolveNode(node) {
|
|
80
|
+
if ('$type' in node) {
|
|
81
|
+
return node;
|
|
82
|
+
}
|
|
83
|
+
// AstNodeDescription — resolve if possible
|
|
84
|
+
return node.node;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=domain-lang-node-kind-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"domain-lang-node-kind-provider.js","sourceRoot":"","sources":["../../src/lsp/domain-lang-node-kind-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,100 @@
|
|
|
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 type { ReferenceInfo, Scope } from 'langium';
|
|
23
|
+
import { DefaultScopeProvider } from 'langium';
|
|
24
|
+
import type { DomainLangServices } from '../domain-lang-module.js';
|
|
25
|
+
/**
|
|
26
|
+
* Custom scope provider that restricts cross-file references to imported documents only.
|
|
27
|
+
*
|
|
28
|
+
* Extends Langium's DefaultScopeProvider to override the global scope computation.
|
|
29
|
+
*/
|
|
30
|
+
export declare class DomainLangScopeProvider extends DefaultScopeProvider {
|
|
31
|
+
/**
|
|
32
|
+
* Reference to IndexManager for getting resolved imports with aliases.
|
|
33
|
+
*/
|
|
34
|
+
private readonly domainLangIndexManager;
|
|
35
|
+
/**
|
|
36
|
+
* Detects package boundaries for transitive import resolution.
|
|
37
|
+
*/
|
|
38
|
+
private readonly packageBoundaryDetector;
|
|
39
|
+
constructor(services: DomainLangServices);
|
|
40
|
+
/**
|
|
41
|
+
* Override getGlobalScope to implement alias-scoped and package-boundary transitive imports.
|
|
42
|
+
*
|
|
43
|
+
* The default Langium behavior includes ALL documents in the workspace.
|
|
44
|
+
* We restrict and transform scope to:
|
|
45
|
+
* 1. The current document's own exported symbols
|
|
46
|
+
* 2. Symbols from directly imported documents (with alias prefixing)
|
|
47
|
+
* 3. Symbols from package-boundary transitive imports (external packages only)
|
|
48
|
+
*
|
|
49
|
+
* @param referenceType - The AST type being referenced
|
|
50
|
+
* @param context - Information about the reference
|
|
51
|
+
* @returns A scope containing only visible elements
|
|
52
|
+
*/
|
|
53
|
+
protected getGlobalScope(referenceType: string, context: ReferenceInfo): Scope;
|
|
54
|
+
/**
|
|
55
|
+
* Computes all visible descriptions for a document, including:
|
|
56
|
+
* - Current document's own symbols
|
|
57
|
+
* - Direct imports (with alias prefixing)
|
|
58
|
+
* - Package-boundary transitive imports
|
|
59
|
+
*
|
|
60
|
+
* @param referenceType - The AST type being referenced
|
|
61
|
+
* @param document - The document making the reference
|
|
62
|
+
* @returns Stream of visible descriptions
|
|
63
|
+
*/
|
|
64
|
+
private computeVisibleDescriptions;
|
|
65
|
+
/**
|
|
66
|
+
* Adds descriptions from a single import, applying alias prefixing if needed.
|
|
67
|
+
*
|
|
68
|
+
* @param imp - Import information (specifier, alias, resolved URI)
|
|
69
|
+
* @param referenceType - The AST type being referenced
|
|
70
|
+
* @param processedUris - Set of already-processed URIs to avoid duplicates
|
|
71
|
+
* @param output - Array to append visible descriptions to
|
|
72
|
+
*/
|
|
73
|
+
private addDescriptionsFromImport;
|
|
74
|
+
/**
|
|
75
|
+
* Adds package-boundary transitive imports for external packages.
|
|
76
|
+
*
|
|
77
|
+
* When document A imports package document B (e.g., index.dlang),
|
|
78
|
+
* and B imports internal package files C, D, etc. (same package root),
|
|
79
|
+
* then A can see types from C, D, etc. (package re-exports).
|
|
80
|
+
*
|
|
81
|
+
* Local file imports remain non-transitive.
|
|
82
|
+
*
|
|
83
|
+
* @param imp - Import information for the direct import
|
|
84
|
+
* @param referenceType - The AST type being referenced
|
|
85
|
+
* @param currentDocument - The document making the reference
|
|
86
|
+
* @param processedUris - Set of already-processed URIs to avoid duplicates
|
|
87
|
+
* @param output - Array to append visible descriptions to
|
|
88
|
+
*/
|
|
89
|
+
private addPackageBoundaryTransitiveImports;
|
|
90
|
+
/**
|
|
91
|
+
* Creates an alias-prefixed version of a description.
|
|
92
|
+
*
|
|
93
|
+
* Example: CoreDomain with alias "ddd" → ddd.CoreDomain
|
|
94
|
+
*
|
|
95
|
+
* @param original - Original description
|
|
96
|
+
* @param alias - Import alias to prefix with
|
|
97
|
+
* @returns New description with prefixed name
|
|
98
|
+
*/
|
|
99
|
+
private createAliasedDescription;
|
|
100
|
+
}
|