@domainlang/language 0.6.0 → 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 (35) hide show
  1. package/README.md +1 -1
  2. package/out/domain-lang-module.js +2 -0
  3. package/out/domain-lang-module.js.map +1 -1
  4. package/out/lsp/domain-lang-index-manager.d.ts +69 -1
  5. package/out/lsp/domain-lang-index-manager.js +173 -5
  6. package/out/lsp/domain-lang-index-manager.js.map +1 -1
  7. package/out/lsp/domain-lang-scope-provider.d.ts +67 -0
  8. package/out/lsp/domain-lang-scope-provider.js +95 -0
  9. package/out/lsp/domain-lang-scope-provider.js.map +1 -0
  10. package/out/lsp/domain-lang-workspace-manager.d.ts +25 -0
  11. package/out/lsp/domain-lang-workspace-manager.js +102 -3
  12. package/out/lsp/domain-lang-workspace-manager.js.map +1 -1
  13. package/out/main.js +114 -19
  14. package/out/main.js.map +1 -1
  15. package/out/services/import-resolver.d.ts +29 -6
  16. package/out/services/import-resolver.js +48 -9
  17. package/out/services/import-resolver.js.map +1 -1
  18. package/out/validation/constants.d.ts +13 -0
  19. package/out/validation/constants.js +18 -0
  20. package/out/validation/constants.js.map +1 -1
  21. package/out/validation/import.d.ts +11 -0
  22. package/out/validation/import.js +62 -2
  23. package/out/validation/import.js.map +1 -1
  24. package/out/validation/maps.js +51 -2
  25. package/out/validation/maps.js.map +1 -1
  26. package/package.json +1 -1
  27. package/src/domain-lang-module.ts +2 -0
  28. package/src/lsp/domain-lang-index-manager.ts +196 -5
  29. package/src/lsp/domain-lang-scope-provider.ts +134 -0
  30. package/src/lsp/domain-lang-workspace-manager.ts +128 -3
  31. package/src/main.ts +153 -22
  32. package/src/services/import-resolver.ts +60 -9
  33. package/src/validation/constants.ts +24 -0
  34. package/src/validation/import.ts +75 -2
  35. package/src/validation/maps.ts +59 -2
@@ -9,12 +9,14 @@ import type { DomainLangServices } from '../domain-lang-module.js';
9
9
  * the shared WorkspaceManager service with its cached manifest/lock file reading.
10
10
  *
11
11
  * Checks:
12
+ * - All import URIs resolve to existing files
12
13
  * - External imports require manifest + alias
13
14
  * - Local path dependencies stay inside workspace
14
15
  * - Lock file exists for external dependencies
15
16
  */
16
17
  export declare class ImportValidator {
17
18
  private readonly workspaceManager;
19
+ private readonly importResolver;
18
20
  constructor(services: DomainLangServices);
19
21
  /**
20
22
  * Validates an import statement asynchronously.
@@ -32,6 +34,15 @@ export declare class ImportValidator {
32
34
  * - External: owner/package (requires manifest dependencies)
33
35
  */
34
36
  private isExternalImport;
37
+ /**
38
+ * Validates that an import URI resolves to an existing file.
39
+ * Returns true if there was an error (import doesn't resolve).
40
+ */
41
+ private validateImportResolves;
42
+ /**
43
+ * Checks if a file exists (async).
44
+ */
45
+ private fileExists;
35
46
  /**
36
47
  * Gets the normalized dependency configuration for an alias.
37
48
  */
@@ -8,6 +8,7 @@ import { ValidationMessages, buildCodeDescription, IssueCodes } from './constant
8
8
  * the shared WorkspaceManager service with its cached manifest/lock file reading.
9
9
  *
10
10
  * Checks:
11
+ * - All import URIs resolve to existing files
11
12
  * - External imports require manifest + alias
12
13
  * - Local path dependencies stay inside workspace
13
14
  * - Lock file exists for external dependencies
@@ -15,6 +16,7 @@ import { ValidationMessages, buildCodeDescription, IssueCodes } from './constant
15
16
  export class ImportValidator {
16
17
  constructor(services) {
17
18
  this.workspaceManager = services.imports.WorkspaceManager;
19
+ this.importResolver = services.imports.ImportResolver;
18
20
  }
19
21
  /**
20
22
  * Validates an import statement asynchronously.
@@ -32,6 +34,12 @@ export class ImportValidator {
32
34
  });
33
35
  return;
34
36
  }
37
+ // First, verify the import resolves to a valid file
38
+ // This catches renamed/moved/deleted files immediately
39
+ const resolveError = await this.validateImportResolves(imp, document, accept);
40
+ if (resolveError) {
41
+ return; // Don't continue with other validations if can't resolve
42
+ }
35
43
  if (!this.isExternalImport(imp.uri)) {
36
44
  return;
37
45
  }
@@ -92,6 +100,54 @@ export class ImportValidator {
92
100
  }
93
101
  return true;
94
102
  }
103
+ /**
104
+ * Validates that an import URI resolves to an existing file.
105
+ * Returns true if there was an error (import doesn't resolve).
106
+ */
107
+ async validateImportResolves(imp, document, accept) {
108
+ if (!imp.uri) {
109
+ return true; // Error already reported
110
+ }
111
+ const docDir = path.dirname(document.uri.fsPath);
112
+ try {
113
+ const resolvedUri = await this.importResolver.resolveFrom(docDir, imp.uri);
114
+ // Check if the resolved file actually exists
115
+ const filePath = resolvedUri.fsPath;
116
+ const exists = await this.fileExists(filePath);
117
+ if (!exists) {
118
+ accept('error', ValidationMessages.IMPORT_UNRESOLVED(imp.uri), {
119
+ node: imp,
120
+ property: 'uri',
121
+ codeDescription: buildCodeDescription('language.md', 'imports'),
122
+ data: { code: IssueCodes.ImportUnresolved, uri: imp.uri }
123
+ });
124
+ return true;
125
+ }
126
+ return false;
127
+ }
128
+ catch {
129
+ // Resolution failed - report as unresolved import
130
+ accept('error', ValidationMessages.IMPORT_UNRESOLVED(imp.uri), {
131
+ node: imp,
132
+ property: 'uri',
133
+ codeDescription: buildCodeDescription('language.md', 'imports'),
134
+ data: { code: IssueCodes.ImportUnresolved, uri: imp.uri }
135
+ });
136
+ return true;
137
+ }
138
+ }
139
+ /**
140
+ * Checks if a file exists (async).
141
+ */
142
+ async fileExists(filePath) {
143
+ try {
144
+ const stat = await fs.stat(filePath);
145
+ return stat.isFile();
146
+ }
147
+ catch {
148
+ return false;
149
+ }
150
+ }
95
151
  /**
96
152
  * Gets the normalized dependency configuration for an alias.
97
153
  */
@@ -240,9 +296,13 @@ export function createImportChecks(services) {
240
296
  return {
241
297
  // Langium 4.x supports async validators via MaybePromise<void>
242
298
  ImportStatement: async (imp, accept, cancelToken) => {
243
- const document = imp.$document;
244
- if (!document)
299
+ // Get document from root (Model), not from ImportStatement
300
+ // Langium sets $document only on the root AST node
301
+ const root = imp.$container;
302
+ const document = root?.$document;
303
+ if (!document) {
245
304
  return;
305
+ }
246
306
  await validator.checkImportPath(imp, accept, document, cancelToken);
247
307
  }
248
308
  };
@@ -1 +1 @@
1
- {"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/validation/import.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/validation/import.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { ValidationMessages, buildCodeDescription } from './constants.js';
1
+ import { ValidationMessages, buildCodeDescription, IssueCodes } from './constants.js';
2
2
  /**
3
3
  * Validates that a context map contains at least one bounded context.
4
4
  * Empty context maps are not useful for documentation purposes.
@@ -15,6 +15,32 @@ function validateContextMapHasContexts(map, accept) {
15
15
  });
16
16
  }
17
17
  }
18
+ /**
19
+ * Validates that MultiReference items in a context map resolve.
20
+ * Langium doesn't report errors for unresolved MultiReference items by default,
21
+ * so we need custom validation to catch these cases.
22
+ *
23
+ * @param map - The context map to validate
24
+ * @param accept - The validation acceptor for reporting issues
25
+ */
26
+ function validateContextMapReferences(map, accept) {
27
+ if (!map.boundedContexts)
28
+ return;
29
+ for (const multiRef of map.boundedContexts) {
30
+ // A MultiReference has a $refText (the source text) and items (resolved refs)
31
+ // If $refText exists but items is empty, the reference didn't resolve
32
+ const refText = multiRef.$refText;
33
+ if (refText && multiRef.items.length === 0) {
34
+ accept('error', ValidationMessages.UNRESOLVED_REFERENCE('BoundedContext', refText), {
35
+ node: map,
36
+ // Find the CST node for this specific reference
37
+ property: 'boundedContexts',
38
+ index: map.boundedContexts.indexOf(multiRef),
39
+ code: IssueCodes.UnresolvedReference
40
+ });
41
+ }
42
+ }
43
+ }
18
44
  /**
19
45
  * Validates that a context map has at least one relationship if it contains multiple contexts.
20
46
  * Multiple unrelated contexts should have documented relationships.
@@ -50,11 +76,34 @@ function validateDomainMapHasDomains(map, accept) {
50
76
  });
51
77
  }
52
78
  }
79
+ /**
80
+ * Validates that MultiReference items in a domain map resolve.
81
+ *
82
+ * @param map - The domain map to validate
83
+ * @param accept - The validation acceptor for reporting issues
84
+ */
85
+ function validateDomainMapReferences(map, accept) {
86
+ if (!map.domains)
87
+ return;
88
+ for (const multiRef of map.domains) {
89
+ const refText = multiRef.$refText;
90
+ if (refText && multiRef.items.length === 0) {
91
+ accept('error', ValidationMessages.UNRESOLVED_REFERENCE('Domain', refText), {
92
+ node: map,
93
+ property: 'domains',
94
+ index: map.domains.indexOf(multiRef),
95
+ code: IssueCodes.UnresolvedReference
96
+ });
97
+ }
98
+ }
99
+ }
53
100
  export const contextMapChecks = [
54
101
  validateContextMapHasContexts,
102
+ validateContextMapReferences,
55
103
  validateContextMapHasRelationships
56
104
  ];
57
105
  export const domainMapChecks = [
58
- validateDomainMapHasDomains
106
+ validateDomainMapHasDomains,
107
+ validateDomainMapReferences
59
108
  ];
60
109
  //# sourceMappingURL=maps.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"maps.js","sourceRoot":"","sources":["../../src/validation/maps.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,kBAAkB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE1E;;;;;;GAMG;AACH,SAAS,6BAA6B,CAClC,GAAe,EACf,MAA0B;IAE1B,IAAI,CAAC,GAAG,CAAC,eAAe,IAAI,GAAG,CAAC,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3D,MAAM,CAAC,SAAS,EAAE,kBAAkB,CAAC,uBAAuB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YACpE,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,UAAU;YACnB,eAAe,EAAE,oBAAoB,CAAC,aAAa,EAAE,cAAc,CAAC;SACvE,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAS,kCAAkC,CACvC,GAAe,EACf,MAA0B;IAE1B,MAAM,YAAY,GAAG,GAAG,CAAC,eAAe,EAAE,MAAM,IAAI,CAAC,CAAC;IACtD,MAAM,iBAAiB,GAAG,GAAG,CAAC,aAAa,EAAE,MAAM,IAAI,CAAC,CAAC;IAEzD,6DAA6D;IAC7D,IAAI,YAAY,GAAG,CAAC,IAAI,iBAAiB,KAAK,CAAC,EAAE,CAAC;QAC9C,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,4BAA4B,CAAC,GAAG,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE;YACpF,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,YAAY;YACrB,eAAe,EAAE,oBAAoB,CAAC,aAAa,EAAE,cAAc,CAAC;SACvE,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,SAAS,2BAA2B,CAChC,GAAc,EACd,MAA0B;IAE1B,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3C,MAAM,CAAC,SAAS,EAAE,kBAAkB,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;YAClE,IAAI,EAAE,GAAG;YACT,OAAO,EAAE,UAAU;YACnB,eAAe,EAAE,oBAAoB,CAAC,aAAa,EAAE,aAAa,CAAC;SACtE,CAAC,CAAC;IACP,CAAC;AACL,CAAC;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC5B,6BAA6B;IAC7B,kCAAkC;CACrC,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAG;IAC3B,2BAA2B;CAC9B,CAAC"}
1
+ {"version":3,"file":"maps.js","sourceRoot":"","sources":["../../src/validation/maps.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@domainlang/language",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "displayName": "DomainLang Language",
5
5
  "description": "Core language library for DomainLang - parse, validate, and query Domain-Driven Design models programmatically",
6
6
  "author": "larsbaunwall",
@@ -11,6 +11,7 @@ import { DomainLangGeneratedModule, DomainLangGeneratedSharedModule } from './ge
11
11
  import { registerValidationChecks } from './validation/domain-lang-validator.js';
12
12
  import { QualifiedNameProvider } from './lsp/domain-lang-naming.js';
13
13
  import { DomainLangScopeComputation } from './lsp/domain-lang-scope.js';
14
+ import { DomainLangScopeProvider } from './lsp/domain-lang-scope-provider.js';
14
15
  import { DomainLangFormatter } from './lsp/domain-lang-formatter.js';
15
16
  import { DomainLangHoverProvider } from './lsp/hover/domain-lang-hover.js';
16
17
  import { DomainLangCompletionProvider } from './lsp/domain-lang-completion.js';
@@ -64,6 +65,7 @@ export const DomainLangModule: Module<DomainLangServices, PartialLangiumServices
64
65
  },
65
66
  references: {
66
67
  ScopeComputation: (services) => new DomainLangScopeComputation(services),
68
+ ScopeProvider: (services) => new DomainLangScopeProvider(services),
67
69
  QualifiedNameProvider: () => new QualifiedNameProvider()
68
70
  },
69
71
  lsp: {
@@ -17,6 +17,7 @@ import type { Model } from '../generated/ast.js';
17
17
  * **How it works:**
18
18
  * - When a document is indexed, we ensure all its imports are also loaded
19
19
  * - Maintains a reverse dependency graph: importedUri → Set<importingUri>
20
+ * - Also tracks import specifiers to detect when file moves affect resolution
20
21
  * - Overrides `isAffected()` to also check this graph
21
22
  * - This integrates with Langium's native `DocumentBuilder.update()` flow
22
23
  *
@@ -35,6 +36,14 @@ export class DomainLangIndexManager extends DefaultIndexManager {
35
36
  */
36
37
  private readonly importDependencies = new Map<string, Set<string>>();
37
38
 
39
+ /**
40
+ * Maps document URI to its import specifiers and their resolved URIs.
41
+ * Used to detect when file moves could affect import resolution.
42
+ * Key: importing document URI
43
+ * Value: Map of import specifier → resolved URI
44
+ */
45
+ private readonly documentImportSpecifiers = new Map<string, Map<string, string>>();
46
+
38
47
  /**
39
48
  * Tracks documents that have had their imports loaded to avoid redundant work.
40
49
  * Cleared on workspace config changes.
@@ -115,7 +124,9 @@ export class DomainLangIndexManager extends DefaultIndexManager {
115
124
 
116
125
  /**
117
126
  * Tracks import dependencies for a document.
118
- * For each import in the document, records that the imported URI is depended upon.
127
+ * For each import in the document, records:
128
+ * 1. That the imported URI is depended upon (for direct change detection)
129
+ * 2. The import specifier used (for file move detection)
119
130
  */
120
131
  private async trackImportDependencies(document: LangiumDocument): Promise<void> {
121
132
  const importingUri = document.uri.toString();
@@ -123,6 +134,7 @@ export class DomainLangIndexManager extends DefaultIndexManager {
123
134
  // First, remove old dependencies from this document
124
135
  // (in case imports changed)
125
136
  this.removeDocumentFromDependencies(importingUri);
137
+ this.documentImportSpecifiers.delete(importingUri);
126
138
 
127
139
  // Skip if document isn't ready (no parse result)
128
140
  if (document.state < DocumentState.Parsed) {
@@ -134,6 +146,8 @@ export class DomainLangIndexManager extends DefaultIndexManager {
134
146
  return;
135
147
  }
136
148
 
149
+ const specifierMap = new Map<string, string>();
150
+
137
151
  for (const imp of model.imports) {
138
152
  if (!imp.uri) continue;
139
153
 
@@ -141,6 +155,9 @@ export class DomainLangIndexManager extends DefaultIndexManager {
141
155
  const resolvedUri = await resolveImportPath(document, imp.uri);
142
156
  const importedUri = resolvedUri.toString();
143
157
 
158
+ // Track the specifier → resolved URI mapping
159
+ specifierMap.set(imp.uri, importedUri);
160
+
144
161
  // Add to reverse dependency graph: importedUri → importingUri
145
162
  let dependents = this.importDependencies.get(importedUri);
146
163
  if (!dependents) {
@@ -149,9 +166,14 @@ export class DomainLangIndexManager extends DefaultIndexManager {
149
166
  }
150
167
  dependents.add(importingUri);
151
168
  } catch {
152
- // Import resolution failed - validation will report the error
169
+ // Import resolution failed - still track the specifier with empty resolution
170
+ specifierMap.set(imp.uri, '');
153
171
  }
154
172
  }
173
+
174
+ if (specifierMap.size > 0) {
175
+ this.documentImportSpecifiers.set(importingUri, specifierMap);
176
+ }
155
177
  }
156
178
 
157
179
  /**
@@ -199,8 +221,10 @@ export class DomainLangIndexManager extends DefaultIndexManager {
199
221
  // Load or create the imported document
200
222
  const importedDoc = await langiumDocuments.getOrCreateDocument(resolvedUri);
201
223
 
202
- // If document is new (not yet indexed), add to batch
203
- if (importedDoc.state < DocumentState.IndexedContent) {
224
+ // If document is not yet validated, add to batch for building
225
+ // This ensures all imported documents reach Validated state,
226
+ // preventing "workspace state is already Validated" errors
227
+ if (importedDoc.state < DocumentState.Validated) {
204
228
  newDocs.push(importedDoc);
205
229
  }
206
230
  } catch {
@@ -208,7 +232,7 @@ export class DomainLangIndexManager extends DefaultIndexManager {
208
232
  }
209
233
  }
210
234
 
211
- // Build any newly discovered documents
235
+ // Build any newly discovered documents to Validated state
212
236
  // This triggers indexing which will recursively load their imports
213
237
  if (newDocs.length > 0) {
214
238
  await documentBuilder.build(newDocs, { validation: true });
@@ -243,6 +267,7 @@ export class DomainLangIndexManager extends DefaultIndexManager {
243
267
  */
244
268
  clearImportDependencies(): void {
245
269
  this.importDependencies.clear();
270
+ this.documentImportSpecifiers.clear();
246
271
  this.importsLoaded.clear();
247
272
  }
248
273
 
@@ -253,4 +278,170 @@ export class DomainLangIndexManager extends DefaultIndexManager {
253
278
  markForReprocessing(uri: string): void {
254
279
  this.importsLoaded.delete(uri);
255
280
  }
281
+
282
+ /**
283
+ * Gets all documents that import the given URI.
284
+ * Used to find documents that need rebuilding when a file changes.
285
+ *
286
+ * @param uri - The URI of the changed/deleted file
287
+ * @returns Set of URIs (as strings) of documents that import this file
288
+ */
289
+ getDependentDocuments(uri: string): Set<string> {
290
+ return this.importDependencies.get(uri) ?? new Set();
291
+ }
292
+
293
+ /**
294
+ * Gets the resolved import URIs for a document.
295
+ * Returns only URIs where import resolution succeeded (non-empty resolved URI).
296
+ *
297
+ * @param documentUri - The URI of the document
298
+ * @returns Set of resolved import URIs, or empty set if none
299
+ */
300
+ getResolvedImports(documentUri: string): Set<string> {
301
+ const specifierMap = this.documentImportSpecifiers.get(documentUri);
302
+ if (!specifierMap) {
303
+ return new Set();
304
+ }
305
+
306
+ const resolved = new Set<string>();
307
+ for (const resolvedUri of specifierMap.values()) {
308
+ // Only include successfully resolved imports (non-empty string)
309
+ if (resolvedUri) {
310
+ resolved.add(resolvedUri);
311
+ }
312
+ }
313
+ return resolved;
314
+ }
315
+
316
+ /**
317
+ * Gets all documents that would be affected by changes to the given URIs.
318
+ * This includes direct dependents and transitive dependents.
319
+ *
320
+ * @param changedUris - URIs of changed/deleted files
321
+ * @returns Set of all affected document URIs
322
+ */
323
+ getAllAffectedDocuments(changedUris: Iterable<string>): Set<string> {
324
+ const affected = new Set<string>();
325
+ const toProcess = [...changedUris];
326
+
327
+ while (toProcess.length > 0) {
328
+ const uri = toProcess.pop();
329
+ if (!uri) {
330
+ continue;
331
+ }
332
+ const dependents = this.importDependencies.get(uri);
333
+ if (dependents) {
334
+ for (const dep of dependents) {
335
+ if (!affected.has(dep)) {
336
+ affected.add(dep);
337
+ // Also check transitive dependents
338
+ toProcess.push(dep);
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ return affected;
345
+ }
346
+
347
+ /**
348
+ * Gets documents that have import specifiers which might be affected by file moves.
349
+ *
350
+ * When a file is moved/renamed, import specifiers that previously resolved to it
351
+ * (or could now resolve to it) need to be re-evaluated. This method finds documents
352
+ * whose imports might resolve differently after the file system change.
353
+ *
354
+ * @param changedUris - URIs of changed/deleted/created files
355
+ * @returns Set of document URIs that should be rebuilt
356
+ */
357
+ getDocumentsWithPotentiallyAffectedImports(changedUris: Iterable<string>): Set<string> {
358
+ const changedPaths = this.extractPathSegments(changedUris);
359
+ return this.findDocumentsMatchingPaths(changedPaths);
360
+ }
361
+
362
+ /**
363
+ * Extracts path segments from URIs for fuzzy matching.
364
+ */
365
+ private extractPathSegments(uris: Iterable<string>): Set<string> {
366
+ const paths = new Set<string>();
367
+
368
+ for (const uri of uris) {
369
+ this.addPathSegmentsFromUri(uri, paths);
370
+ }
371
+
372
+ return paths;
373
+ }
374
+
375
+ /**
376
+ * Adds path segments from a single URI to the set.
377
+ */
378
+ private addPathSegmentsFromUri(uri: string, paths: Set<string>): void {
379
+ try {
380
+ const url = new URL(uri);
381
+ const pathParts = url.pathname.split('/').filter(p => p.length > 0);
382
+
383
+ // Add filename
384
+ const fileName = pathParts.at(-1);
385
+ if (fileName) {
386
+ paths.add(fileName);
387
+ }
388
+
389
+ // Add parent/filename combination
390
+ if (pathParts.length >= 2) {
391
+ paths.add(pathParts.slice(-2).join('/'));
392
+ }
393
+
394
+ // Add grandparent/parent/filename combination
395
+ if (pathParts.length >= 3) {
396
+ paths.add(pathParts.slice(-3).join('/'));
397
+ }
398
+ } catch {
399
+ // Invalid URI, skip
400
+ }
401
+ }
402
+
403
+ /**
404
+ * Finds documents with import specifiers matching any of the given paths.
405
+ */
406
+ private findDocumentsMatchingPaths(changedPaths: Set<string>): Set<string> {
407
+ const affected = new Set<string>();
408
+
409
+ for (const [docUri, specifierMap] of this.documentImportSpecifiers) {
410
+ if (this.hasMatchingSpecifierOrResolvedUri(specifierMap, changedPaths)) {
411
+ affected.add(docUri);
412
+ }
413
+ }
414
+
415
+ return affected;
416
+ }
417
+
418
+ /**
419
+ * Checks if any specifier OR its resolved URI matches the changed paths.
420
+ *
421
+ * This handles both regular imports and path aliases:
422
+ * - Regular: `./domains/sales.dlang` matches path `sales.dlang`
423
+ * - Aliased: `@domains/sales.dlang` resolves to `/full/path/domains/sales.dlang`
424
+ * When the file moves, the resolved URI matches but the specifier doesn't
425
+ *
426
+ * We check both to ensure moves of aliased imports trigger revalidation.
427
+ */
428
+ private hasMatchingSpecifierOrResolvedUri(specifierMap: Map<string, string>, changedPaths: Set<string>): boolean {
429
+ for (const [specifier, resolvedUri] of specifierMap.entries()) {
430
+ const normalizedSpecifier = specifier.replace(/^[.@/]+/, '');
431
+
432
+ for (const changedPath of changedPaths) {
433
+ // Check the raw specifier (handles relative imports)
434
+ if (specifier.includes(changedPath) || changedPath.endsWith(normalizedSpecifier)) {
435
+ return true;
436
+ }
437
+
438
+ // Check the resolved URI (handles path aliases like @domains/...)
439
+ // The resolved URI contains the full file path which matches moved files
440
+ if (resolvedUri?.includes(changedPath)) {
441
+ return true;
442
+ }
443
+ }
444
+ }
445
+ return false;
446
+ }
256
447
  }