@domainlang/language 0.10.0 → 0.12.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 +44 -102
- package/out/diagram/context-map-diagram-generator.d.ts +65 -0
- package/out/diagram/context-map-diagram-generator.js +356 -0
- package/out/diagram/context-map-diagram-generator.js.map +1 -0
- package/out/diagram/context-map-layout-configurator.d.ts +15 -0
- package/out/diagram/context-map-layout-configurator.js +39 -0
- package/out/diagram/context-map-layout-configurator.js.map +1 -0
- package/out/diagram/elk-layout-factory.d.ts +43 -0
- package/out/diagram/elk-layout-factory.js +64 -0
- package/out/diagram/elk-layout-factory.js.map +1 -0
- package/out/domain-lang-module.d.ts +9 -2
- package/out/domain-lang-module.js +13 -4
- package/out/domain-lang-module.js.map +1 -1
- package/out/index.d.ts +6 -0
- package/out/index.js +7 -0
- package/out/index.js.map +1 -1
- package/out/lsp/domain-lang-code-lens-provider.d.ts +8 -0
- package/out/lsp/domain-lang-code-lens-provider.js +48 -0
- package/out/lsp/domain-lang-code-lens-provider.js.map +1 -0
- package/out/lsp/domain-lang-completion.js +1 -1
- package/out/lsp/domain-lang-completion.js.map +1 -1
- package/out/lsp/domain-lang-document-symbol-provider.js +5 -5
- package/out/lsp/domain-lang-document-symbol-provider.js.map +1 -1
- package/out/lsp/domain-lang-index-manager.d.ts +149 -5
- package/out/lsp/domain-lang-index-manager.js +388 -52
- package/out/lsp/domain-lang-index-manager.js.map +1 -1
- package/out/lsp/domain-lang-refresh.d.ts +35 -0
- package/out/lsp/domain-lang-refresh.js +129 -0
- package/out/lsp/domain-lang-refresh.js.map +1 -0
- package/out/lsp/domain-lang-workspace-manager.d.ts +10 -0
- package/out/lsp/domain-lang-workspace-manager.js +35 -0
- package/out/lsp/domain-lang-workspace-manager.js.map +1 -1
- package/out/lsp/tool-handlers.js +63 -57
- package/out/lsp/tool-handlers.js.map +1 -1
- package/out/main.js +30 -190
- package/out/main.js.map +1 -1
- package/out/sdk/loader-node.js +1 -1
- package/out/sdk/loader-node.js.map +1 -1
- package/out/sdk/validator.js +17 -14
- package/out/sdk/validator.js.map +1 -1
- package/out/services/import-resolver.d.ts +67 -17
- package/out/services/import-resolver.js +146 -65
- package/out/services/import-resolver.js.map +1 -1
- package/out/services/lsp-logger.d.ts +42 -0
- package/out/services/lsp-logger.js +50 -0
- package/out/services/lsp-logger.js.map +1 -0
- package/out/services/lsp-runtime-settings.d.ts +20 -0
- package/out/services/lsp-runtime-settings.js +20 -0
- package/out/services/lsp-runtime-settings.js.map +1 -0
- package/out/services/performance-optimizer.d.ts +9 -9
- package/out/services/performance-optimizer.js +17 -41
- package/out/services/performance-optimizer.js.map +1 -1
- package/out/services/workspace-manager.d.ts +22 -1
- package/out/services/workspace-manager.js +57 -9
- package/out/services/workspace-manager.js.map +1 -1
- package/out/utils/import-utils.js +6 -6
- package/out/utils/import-utils.js.map +1 -1
- package/out/validation/constants.d.ts +6 -0
- package/out/validation/constants.js +7 -0
- package/out/validation/constants.js.map +1 -1
- package/out/validation/import.d.ts +13 -3
- package/out/validation/import.js +54 -10
- package/out/validation/import.js.map +1 -1
- package/package.json +5 -2
- package/src/diagram/context-map-diagram-generator.ts +451 -0
- package/src/diagram/context-map-layout-configurator.ts +43 -0
- package/src/diagram/elk-layout-factory.ts +83 -0
- package/src/domain-lang-module.ts +22 -5
- package/src/index.ts +8 -0
- package/src/lsp/domain-lang-code-lens-provider.ts +54 -0
- package/src/lsp/domain-lang-completion.ts +3 -3
- package/src/lsp/domain-lang-document-symbol-provider.ts +5 -5
- package/src/lsp/domain-lang-index-manager.ts +438 -56
- package/src/lsp/domain-lang-refresh.ts +205 -0
- package/src/lsp/domain-lang-workspace-manager.ts +45 -0
- package/src/lsp/tool-handlers.ts +61 -47
- package/src/main.ts +36 -244
- package/src/sdk/loader-node.ts +1 -1
- package/src/sdk/validator.ts +17 -13
- package/src/services/import-resolver.ts +196 -89
- package/src/services/lsp-logger.ts +89 -0
- package/src/services/lsp-runtime-settings.ts +34 -0
- package/src/services/performance-optimizer.ts +18 -57
- package/src/services/workspace-manager.ts +62 -10
- package/src/utils/import-utils.ts +6 -6
- package/src/validation/constants.ts +9 -0
- package/src/validation/import.ts +67 -12
|
@@ -1,6 +1,25 @@
|
|
|
1
1
|
import fs from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { DocumentCache, SimpleCache, URI } from 'langium';
|
|
4
|
+
import { getLspRuntimeSettings } from './lsp-runtime-settings.js';
|
|
5
|
+
/**
|
|
6
|
+
* Structured error for import resolution failures.
|
|
7
|
+
*
|
|
8
|
+
* Carries the specifier, attempted paths, a reason code, and
|
|
9
|
+
* a human-readable hint so callers can build precise diagnostics
|
|
10
|
+
* without parsing error message strings.
|
|
11
|
+
*/
|
|
12
|
+
export class ImportResolutionError extends Error {
|
|
13
|
+
constructor(opts) {
|
|
14
|
+
const msg = opts.message ?? `Cannot resolve import '${opts.specifier}': ${opts.hint}`;
|
|
15
|
+
super(msg);
|
|
16
|
+
this.name = 'ImportResolutionError';
|
|
17
|
+
this.specifier = opts.specifier;
|
|
18
|
+
this.attemptedPaths = Object.freeze(opts.attemptedPaths ?? []);
|
|
19
|
+
this.reason = opts.reason;
|
|
20
|
+
this.hint = opts.hint;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
4
23
|
/**
|
|
5
24
|
* ImportResolver resolves import statements using manifest-centric rules (PRS-010).
|
|
6
25
|
*
|
|
@@ -13,18 +32,21 @@ import { DocumentState, SimpleCache, WorkspaceCache, URI } from 'langium';
|
|
|
13
32
|
* - ./types → ./types/index.dlang → ./types.dlang
|
|
14
33
|
* - Module entry defaults to index.dlang (no model.yaml required)
|
|
15
34
|
*
|
|
16
|
-
* Caching Strategy (uses Langium standard infrastructure):
|
|
17
|
-
* - LSP mode: Uses `
|
|
18
|
-
*
|
|
35
|
+
* Caching Strategy (PRS-017 R1 — uses Langium standard infrastructure):
|
|
36
|
+
* - LSP mode: Uses `DocumentCache` keyed by importing document URI
|
|
37
|
+
* Each document's import resolutions are cached independently.
|
|
38
|
+
* When a document changes, only ITS cache entries are auto-cleared.
|
|
39
|
+
* Cross-document invalidation (when an imported file moves/deletes) is
|
|
40
|
+
* handled by DomainLangIndexManager calling `invalidateForDocuments()`
|
|
41
|
+
* with the reverse dependency graph.
|
|
19
42
|
* - Standalone mode: Uses `SimpleCache` - manual invalidation via clearCache()
|
|
20
43
|
*
|
|
21
|
-
* Why
|
|
22
|
-
* -
|
|
23
|
-
* -
|
|
24
|
-
* -
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
* WorkspaceCache clears on ANY change, ensuring correct re-resolution
|
|
44
|
+
* Why DocumentCache with manual cross-invalidation (not WorkspaceCache)?
|
|
45
|
+
* - WorkspaceCache clears the ENTIRE cache on ANY document change
|
|
46
|
+
* - In a 50-file workspace, editing one file caused ~50 redundant re-resolutions
|
|
47
|
+
* - DocumentCache + targeted invalidation via reverse dep graph only clears
|
|
48
|
+
* the changed file and its direct/transitive importers
|
|
49
|
+
* - This matches gopls' per-package invalidation strategy
|
|
28
50
|
*
|
|
29
51
|
* @see https://langium.org/docs/recipes/caching/ for Langium caching patterns
|
|
30
52
|
*/
|
|
@@ -32,57 +54,89 @@ export class ImportResolver {
|
|
|
32
54
|
/**
|
|
33
55
|
* Creates an ImportResolver.
|
|
34
56
|
*
|
|
35
|
-
* @param services - DomainLang services. If `services.shared` is present, uses
|
|
36
|
-
* for
|
|
57
|
+
* @param services - DomainLang services. If `services.shared` is present, uses DocumentCache
|
|
58
|
+
* for per-document invalidation. Otherwise uses SimpleCache for standalone mode.
|
|
37
59
|
*/
|
|
38
60
|
constructor(services) {
|
|
39
|
-
this.workspaceManager = services.imports.
|
|
40
|
-
// Use Langium's
|
|
61
|
+
this.workspaceManager = services.imports.ManifestManager;
|
|
62
|
+
// Use Langium's DocumentCache when shared services are available (LSP mode)
|
|
41
63
|
// Fall back to SimpleCache for standalone utilities (SDK, CLI)
|
|
42
64
|
const shared = services.shared;
|
|
43
65
|
if (shared) {
|
|
44
|
-
// LSP mode:
|
|
45
|
-
//
|
|
46
|
-
// This follows the standard pattern used by TypeScript, rust-analyzer, gopls:
|
|
47
|
-
// - Cache is valid for a "workspace snapshot"
|
|
48
|
-
// - Invalidates after a batch of changes completes linking (debounced ~300ms)
|
|
49
|
-
// - Invalidates immediately on file deletion
|
|
50
|
-
// - Does NOT invalidate during typing (would be too expensive)
|
|
66
|
+
// LSP mode: DocumentCache — per-document sub-maps (PRS-017 R1)
|
|
51
67
|
//
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
// -
|
|
55
|
-
//
|
|
56
|
-
|
|
68
|
+
// Each document's import resolutions are cached in a separate sub-map.
|
|
69
|
+
// When a document changes, only ITS sub-map is auto-cleared.
|
|
70
|
+
// Cross-document invalidation (imported file moved/deleted) is handled
|
|
71
|
+
// by DomainLangIndexManager calling invalidateForDocuments() with the
|
|
72
|
+
// reverse dependency graph.
|
|
73
|
+
//
|
|
74
|
+
// This replaces the previous WorkspaceCache which cleared EVERYTHING
|
|
75
|
+
// on any change, causing redundant re-resolutions across the workspace.
|
|
76
|
+
this.resolverCache = new DocumentCache(shared);
|
|
77
|
+
this.isDocumentCache = true;
|
|
57
78
|
}
|
|
58
79
|
else {
|
|
59
80
|
// Standalone mode: simple key-value cache, manual invalidation
|
|
60
81
|
this.resolverCache = new SimpleCache();
|
|
82
|
+
this.isDocumentCache = false;
|
|
61
83
|
}
|
|
62
84
|
}
|
|
63
85
|
/**
|
|
64
86
|
* Clears the entire import resolution cache.
|
|
65
|
-
* In LSP mode, this is also triggered automatically by WorkspaceCache on any document change.
|
|
66
87
|
* Call explicitly when model.yaml or model.lock changes.
|
|
67
88
|
*/
|
|
68
89
|
clearCache() {
|
|
69
90
|
this.resolverCache.clear();
|
|
70
91
|
}
|
|
92
|
+
/**
|
|
93
|
+
* Invalidates cached import resolutions for specific documents (PRS-017 R1).
|
|
94
|
+
*
|
|
95
|
+
* Called by DomainLangIndexManager when files change, using the reverse
|
|
96
|
+
* dependency graph to determine which documents' caches need clearing.
|
|
97
|
+
* This provides targeted invalidation instead of clearing the entire cache.
|
|
98
|
+
*
|
|
99
|
+
* @param uris - Document URIs whose import resolution caches should be cleared
|
|
100
|
+
*/
|
|
101
|
+
invalidateForDocuments(uris) {
|
|
102
|
+
if (this.isDocumentCache) {
|
|
103
|
+
const docCache = this.resolverCache;
|
|
104
|
+
for (const uri of uris) {
|
|
105
|
+
docCache.clear(URI.parse(uri));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
71
109
|
/**
|
|
72
110
|
* Resolve an import specifier relative to a Langium document.
|
|
73
|
-
* Results are cached using
|
|
111
|
+
* Results are cached per-document using DocumentCache (PRS-017 R1).
|
|
74
112
|
*/
|
|
75
113
|
async resolveForDocument(document, specifier) {
|
|
76
|
-
|
|
114
|
+
if (this.isDocumentCache) {
|
|
115
|
+
// LSP mode: DocumentCache with (documentUri, specifier) as two-part key
|
|
116
|
+
const docCache = this.resolverCache;
|
|
117
|
+
const cached = docCache.get(document.uri, specifier);
|
|
118
|
+
if (cached) {
|
|
119
|
+
this.trace(`[cache hit] ${specifier} from ${document.uri.fsPath}`);
|
|
120
|
+
return cached;
|
|
121
|
+
}
|
|
122
|
+
const baseDir = path.dirname(document.uri.fsPath);
|
|
123
|
+
const result = await this.resolveFrom(baseDir, specifier);
|
|
124
|
+
this.trace(`[resolved] ${specifier} from ${document.uri.fsPath} → ${result.fsPath}`);
|
|
125
|
+
docCache.set(document.uri, specifier, result);
|
|
126
|
+
return result;
|
|
127
|
+
}
|
|
128
|
+
// Standalone mode: SimpleCache with composite key
|
|
129
|
+
const simpleCache = this.resolverCache;
|
|
77
130
|
const cacheKey = `${document.uri.toString()}|${specifier}`;
|
|
78
|
-
const cached =
|
|
131
|
+
const cached = simpleCache.get(cacheKey);
|
|
79
132
|
if (cached) {
|
|
133
|
+
this.trace(`[cache hit] ${specifier}`);
|
|
80
134
|
return cached;
|
|
81
135
|
}
|
|
82
|
-
// Resolve and cache
|
|
83
136
|
const baseDir = path.dirname(document.uri.fsPath);
|
|
84
137
|
const result = await this.resolveFrom(baseDir, specifier);
|
|
85
|
-
this.
|
|
138
|
+
this.trace(`[resolved] ${specifier} → ${result.fsPath}`);
|
|
139
|
+
simpleCache.set(cacheKey, result);
|
|
86
140
|
return result;
|
|
87
141
|
}
|
|
88
142
|
/**
|
|
@@ -126,10 +180,12 @@ export class ImportResolver {
|
|
|
126
180
|
const resolved = path.join(root, relativePath);
|
|
127
181
|
return this.resolveLocalPath(resolved, specifier);
|
|
128
182
|
}
|
|
129
|
-
throw new
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
` "${specifier.split('/')[0]}": "./some/path"
|
|
183
|
+
throw new ImportResolutionError({
|
|
184
|
+
specifier,
|
|
185
|
+
reason: 'unknown-alias',
|
|
186
|
+
hint: `Define it in model.yaml paths section:\n paths:\n "${specifier.split('/')[0]}": "./some/path"`,
|
|
187
|
+
message: `Unknown path alias '${specifier.split('/')[0]}' in import '${specifier}'.\nHint: Define it in model.yaml paths section.`
|
|
188
|
+
});
|
|
133
189
|
}
|
|
134
190
|
/**
|
|
135
191
|
* Finds the longest matching alias for a specifier.
|
|
@@ -164,26 +220,31 @@ export class ImportResolver {
|
|
|
164
220
|
async resolveExternalDependency(specifier) {
|
|
165
221
|
const manifest = await this.workspaceManager.getManifest();
|
|
166
222
|
if (!manifest) {
|
|
167
|
-
throw new
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
` ${specifier}:\n
|
|
171
|
-
|
|
223
|
+
throw new ImportResolutionError({
|
|
224
|
+
specifier,
|
|
225
|
+
reason: 'missing-manifest',
|
|
226
|
+
hint: `Create model.yaml and add the dependency:\n dependencies:\n ${specifier}:\n ref: v1.0.0`,
|
|
227
|
+
message: `External dependency '${specifier}' requires model.yaml.`
|
|
228
|
+
});
|
|
172
229
|
}
|
|
173
230
|
const lock = await this.workspaceManager.getLockFile();
|
|
174
231
|
if (!lock) {
|
|
175
|
-
throw new
|
|
176
|
-
|
|
232
|
+
throw new ImportResolutionError({
|
|
233
|
+
specifier,
|
|
234
|
+
reason: 'not-installed',
|
|
235
|
+
hint: "Run 'dlang install' to fetch dependencies and generate model.lock.",
|
|
236
|
+
message: `Dependency '${specifier}' not installed.`
|
|
237
|
+
});
|
|
177
238
|
}
|
|
178
239
|
// Use WorkspaceManager to resolve from cache (read-only, no network)
|
|
179
240
|
const resolved = await this.workspaceManager.resolveDependencyPath(specifier);
|
|
180
241
|
if (!resolved) {
|
|
181
|
-
throw new
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
` ${specifier}:\n
|
|
185
|
-
|
|
186
|
-
|
|
242
|
+
throw new ImportResolutionError({
|
|
243
|
+
specifier,
|
|
244
|
+
reason: 'dependency-not-found',
|
|
245
|
+
hint: `Add it to your dependencies:\n dependencies:\n ${specifier}:\n ref: v1.0.0\nThen run 'dlang install' to fetch it.`,
|
|
246
|
+
message: `Dependency '${specifier}' not found in model.yaml or not installed.`
|
|
247
|
+
});
|
|
187
248
|
}
|
|
188
249
|
return URI.file(resolved);
|
|
189
250
|
}
|
|
@@ -204,8 +265,13 @@ export class ImportResolver {
|
|
|
204
265
|
return URI.file(resolved);
|
|
205
266
|
}
|
|
206
267
|
if (ext && ext !== '.dlang') {
|
|
207
|
-
throw new
|
|
208
|
-
|
|
268
|
+
throw new ImportResolutionError({
|
|
269
|
+
specifier: original,
|
|
270
|
+
attemptedPaths: [resolved],
|
|
271
|
+
reason: 'unresolvable',
|
|
272
|
+
hint: `DomainLang files must use the .dlang extension.`,
|
|
273
|
+
message: `Invalid file extension '${ext}' in import '${original}'.`
|
|
274
|
+
});
|
|
209
275
|
}
|
|
210
276
|
// No extension → directory-first resolution
|
|
211
277
|
return this.resolveDirectoryFirst(resolved, original);
|
|
@@ -228,11 +294,12 @@ export class ImportResolver {
|
|
|
228
294
|
return URI.file(entryFile);
|
|
229
295
|
}
|
|
230
296
|
// Directory exists but no entry file
|
|
231
|
-
throw new
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
` entry: main.dlang`
|
|
297
|
+
throw new ImportResolutionError({
|
|
298
|
+
specifier: original,
|
|
299
|
+
attemptedPaths: [path.join(resolved, entryPoint)],
|
|
300
|
+
reason: 'missing-entry',
|
|
301
|
+
hint: `Create '${entryPoint}' in the module directory, or specify a custom entry in model.yaml:\n model:\n entry: main.dlang`
|
|
302
|
+
});
|
|
236
303
|
}
|
|
237
304
|
// Step 2: Try .dlang file fallback
|
|
238
305
|
const fileWithExt = `${resolved}.dlang`;
|
|
@@ -240,11 +307,12 @@ export class ImportResolver {
|
|
|
240
307
|
return URI.file(fileWithExt);
|
|
241
308
|
}
|
|
242
309
|
// Neither directory nor file found
|
|
243
|
-
throw new
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
310
|
+
throw new ImportResolutionError({
|
|
311
|
+
specifier: original,
|
|
312
|
+
attemptedPaths: [`${resolved}/index.dlang`, `${resolved}.dlang`],
|
|
313
|
+
reason: 'file-not-found',
|
|
314
|
+
hint: 'Check that the path is correct and the file exists.'
|
|
315
|
+
});
|
|
248
316
|
}
|
|
249
317
|
/**
|
|
250
318
|
* Reads the entry point from a module's model.yaml.
|
|
@@ -291,15 +359,28 @@ export class ImportResolver {
|
|
|
291
359
|
async getLockFile() {
|
|
292
360
|
return this.workspaceManager.getLockFile();
|
|
293
361
|
}
|
|
362
|
+
// --- PRS-017 R10: Import resolution tracing ---
|
|
363
|
+
/**
|
|
364
|
+
* Logs an import resolution trace message when `domainlang.lsp.traceImports` is enabled.
|
|
365
|
+
* Output goes to stderr so it's visible in the LSP output channel.
|
|
366
|
+
*/
|
|
367
|
+
trace(message) {
|
|
368
|
+
if (getLspRuntimeSettings().traceImports) {
|
|
369
|
+
console.warn(`[ImportResolver] ${message}`);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
294
372
|
}
|
|
295
373
|
async function assertFileExists(filePath, original) {
|
|
296
374
|
try {
|
|
297
375
|
await fs.access(filePath);
|
|
298
376
|
}
|
|
299
377
|
catch {
|
|
300
|
-
throw new
|
|
301
|
-
|
|
302
|
-
|
|
378
|
+
throw new ImportResolutionError({
|
|
379
|
+
specifier: original,
|
|
380
|
+
attemptedPaths: [filePath],
|
|
381
|
+
reason: 'file-not-found',
|
|
382
|
+
hint: 'Check that the file exists and the path is correct.'
|
|
383
|
+
});
|
|
303
384
|
}
|
|
304
385
|
}
|
|
305
386
|
//# sourceMappingURL=import-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-resolver.js","sourceRoot":"","sources":["../../src/services/import-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,
|
|
1
|
+
{"version":3,"file":"import-resolver.js","sourceRoot":"","sources":["../../src/services/import-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured LSP logger for DomainLang (PRS-017 R17).
|
|
3
|
+
*
|
|
4
|
+
* Wraps console.warn/error with structured context (component name,
|
|
5
|
+
* document URI, timing data) so that log messages are easy to
|
|
6
|
+
* correlate when debugging multi-file change propagation.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* ```ts
|
|
10
|
+
* const log = createLogger('IndexManager');
|
|
11
|
+
* log.info('exports changed', { uri, count: 3 });
|
|
12
|
+
* log.warn('stale cache entry');
|
|
13
|
+
* log.error('cycle detected', { cycle: ['a', 'b', 'a'] });
|
|
14
|
+
* log.timed('rebuildAll', async () => { ...work... });
|
|
15
|
+
* ```
|
|
16
|
+
*
|
|
17
|
+
* Output goes to stderr (visible in VS Code's "Output" → "DomainLang" channel)
|
|
18
|
+
* because the LSP protocol uses stdout for JSON-RPC messages.
|
|
19
|
+
*/
|
|
20
|
+
/** Structured context attached to log messages. */
|
|
21
|
+
export interface LogContext {
|
|
22
|
+
/** Langium document URI, shortened for readability. */
|
|
23
|
+
uri?: string;
|
|
24
|
+
/** Additional key → value pairs (serialised as JSON). */
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
export interface LspLogger {
|
|
28
|
+
info(message: string, context?: LogContext): void;
|
|
29
|
+
warn(message: string, context?: LogContext): void;
|
|
30
|
+
error(message: string, context?: LogContext): void;
|
|
31
|
+
/**
|
|
32
|
+
* Measures and logs the duration of an async operation.
|
|
33
|
+
* Returns the operation's result.
|
|
34
|
+
*/
|
|
35
|
+
timed<T>(label: string, fn: () => T | Promise<T>): Promise<T>;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Creates a structured logger scoped to a named component.
|
|
39
|
+
*
|
|
40
|
+
* @param component - Short component name (e.g. 'IndexManager', 'ImportResolver')
|
|
41
|
+
*/
|
|
42
|
+
export declare function createLogger(component: string): LspLogger;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { getLspRuntimeSettings } from './lsp-runtime-settings.js';
|
|
2
|
+
function formatContext(ctx) {
|
|
3
|
+
if (!ctx || Object.keys(ctx).length === 0)
|
|
4
|
+
return '';
|
|
5
|
+
// Shorten file:// URIs to just the filename for readability
|
|
6
|
+
const display = { ...ctx };
|
|
7
|
+
if (typeof display.uri === 'string') {
|
|
8
|
+
const parts = display.uri.split('/');
|
|
9
|
+
display.uri = parts.at(-1);
|
|
10
|
+
}
|
|
11
|
+
return ` ${JSON.stringify(display)}`;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Creates a structured logger scoped to a named component.
|
|
15
|
+
*
|
|
16
|
+
* @param component - Short component name (e.g. 'IndexManager', 'ImportResolver')
|
|
17
|
+
*/
|
|
18
|
+
export function createLogger(component) {
|
|
19
|
+
const prefix = `[DomainLang:${component}]`;
|
|
20
|
+
return {
|
|
21
|
+
info(message, context) {
|
|
22
|
+
if (getLspRuntimeSettings().infoLogs) {
|
|
23
|
+
console.warn(`${prefix} ${message}${formatContext(context)}`);
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
warn(message, context) {
|
|
27
|
+
console.warn(`${prefix} WARN ${message}${formatContext(context)}`);
|
|
28
|
+
},
|
|
29
|
+
error(message, context) {
|
|
30
|
+
console.error(`${prefix} ERROR ${message}${formatContext(context)}`);
|
|
31
|
+
},
|
|
32
|
+
async timed(label, fn) {
|
|
33
|
+
const start = performance.now();
|
|
34
|
+
try {
|
|
35
|
+
const result = await fn();
|
|
36
|
+
const elapsed = (performance.now() - start).toFixed(1);
|
|
37
|
+
if (getLspRuntimeSettings().infoLogs) {
|
|
38
|
+
console.warn(`${prefix} ${label} completed in ${elapsed}ms`);
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
catch (err) {
|
|
43
|
+
const elapsed = (performance.now() - start).toFixed(1);
|
|
44
|
+
console.error(`${prefix} ${label} failed after ${elapsed}ms`);
|
|
45
|
+
throw err;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=lsp-logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lsp-logger.js","sourceRoot":"","sources":["../../src/services/lsp-logger.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AAyClE,SAAS,aAAa,CAAC,GAA2B;IAC9C,IAAI,CAAC,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IACrD,4DAA4D;IAC5D,MAAM,OAAO,GAAG,EAAE,GAAG,GAAG,EAAE,CAAC;IAC3B,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrC,OAAO,CAAC,GAAG,GAAG,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,SAAiB;IAC1C,MAAM,MAAM,GAAG,eAAe,SAAS,GAAG,CAAC;IAE3C,OAAO;QACH,IAAI,CAAC,OAAe,EAAE,OAAoB;YACtC,IAAI,qBAAqB,EAAE,CAAC,QAAQ,EAAE,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAClE,CAAC;QACL,CAAC;QACD,IAAI,CAAC,OAAe,EAAE,OAAoB;YACtC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,SAAS,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,KAAK,CAAC,OAAe,EAAE,OAAoB;YACvC,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,UAAU,OAAO,GAAG,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACzE,CAAC;QACD,KAAK,CAAC,KAAK,CAAI,KAAa,EAAE,EAAwB;YAClD,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;YAChC,IAAI,CAAC;gBACD,MAAM,MAAM,GAAG,MAAM,EAAE,EAAE,CAAC;gBAC1B,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACvD,IAAI,qBAAqB,EAAE,CAAC,QAAQ,EAAE,CAAC;oBACnC,OAAO,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,KAAK,iBAAiB,OAAO,IAAI,CAAC,CAAC;gBACjE,CAAC;gBACD,OAAO,MAAM,CAAC;YAClB,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACX,MAAM,OAAO,GAAG,CAAC,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;gBACvD,OAAO,CAAC,KAAK,CAAC,GAAG,MAAM,IAAI,KAAK,iBAAiB,OAAO,IAAI,CAAC,CAAC;gBAC9D,MAAM,GAAG,CAAC;YACd,CAAC;QACL,CAAC;KACJ,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Runtime LSP settings configured by the VS Code client.
|
|
3
|
+
*
|
|
4
|
+
* Defaults are conservative (both disabled) and can be updated via
|
|
5
|
+
* initialization options and workspace configuration changes.
|
|
6
|
+
*/
|
|
7
|
+
export interface DomainLangLspRuntimeSettings {
|
|
8
|
+
/** Enables import resolution trace logging. */
|
|
9
|
+
traceImports: boolean;
|
|
10
|
+
/** Enables info-level/timing logs. Warnings/errors are always logged. */
|
|
11
|
+
infoLogs: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Updates runtime settings.
|
|
15
|
+
*/
|
|
16
|
+
export declare function setLspRuntimeSettings(next: Partial<DomainLangLspRuntimeSettings>): void;
|
|
17
|
+
/**
|
|
18
|
+
* Returns current runtime settings.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getLspRuntimeSettings(): DomainLangLspRuntimeSettings;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
let runtimeSettings = {
|
|
2
|
+
traceImports: false,
|
|
3
|
+
infoLogs: false,
|
|
4
|
+
};
|
|
5
|
+
/**
|
|
6
|
+
* Updates runtime settings.
|
|
7
|
+
*/
|
|
8
|
+
export function setLspRuntimeSettings(next) {
|
|
9
|
+
runtimeSettings = {
|
|
10
|
+
...runtimeSettings,
|
|
11
|
+
...next,
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Returns current runtime settings.
|
|
16
|
+
*/
|
|
17
|
+
export function getLspRuntimeSettings() {
|
|
18
|
+
return runtimeSettings;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=lsp-runtime-settings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"lsp-runtime-settings.js","sourceRoot":"","sources":["../../src/services/lsp-runtime-settings.ts"],"names":[],"mappings":"AAaA,IAAI,eAAe,GAAiC;IAChD,YAAY,EAAE,KAAK;IACnB,QAAQ,EAAE,KAAK;CAClB,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAA2C;IAC7E,eAAe,GAAG;QACd,GAAG,eAAe;QAClB,GAAG,IAAI;KACV,CAAC;AACN,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB;IACjC,OAAO,eAAe,CAAC;AAC3B,CAAC"}
|
|
@@ -5,19 +5,22 @@
|
|
|
5
5
|
* - In-memory caching of frequently accessed lock files
|
|
6
6
|
* - Parallel dependency downloads
|
|
7
7
|
* - Cache warming strategies
|
|
8
|
-
* -
|
|
8
|
+
* - Event-based invalidation (PRS-017 R15)
|
|
9
9
|
*/
|
|
10
10
|
import type { LockFile } from './types.js';
|
|
11
11
|
/**
|
|
12
12
|
* Performance optimizer with in-memory caching.
|
|
13
|
+
*
|
|
14
|
+
* PRS-017 R15: Cache entries are valid until explicitly invalidated
|
|
15
|
+
* by `invalidateCache()` or `clearAllCaches()`. The previous TTL-based
|
|
16
|
+
* approach could serve stale data (within window) or unnecessarily
|
|
17
|
+
* re-read unchanged files (after expiry). Event-based invalidation
|
|
18
|
+
* via `processManifestChanges()` and `processLockFileChanges()` is
|
|
19
|
+
* always correct and immediate.
|
|
13
20
|
*/
|
|
14
21
|
export declare class PerformanceOptimizer {
|
|
15
22
|
private lockFileCache;
|
|
16
23
|
private manifestCache;
|
|
17
|
-
private readonly cacheTTL;
|
|
18
|
-
constructor(options?: {
|
|
19
|
-
cacheTTL?: number;
|
|
20
|
-
});
|
|
21
24
|
/**
|
|
22
25
|
* Gets a lock file from cache or loads it from disk.
|
|
23
26
|
*/
|
|
@@ -28,6 +31,7 @@ export declare class PerformanceOptimizer {
|
|
|
28
31
|
getCachedManifest(manifestPath: string): Promise<unknown | undefined>;
|
|
29
32
|
/**
|
|
30
33
|
* Invalidates cache for a specific workspace.
|
|
34
|
+
* Called when model.lock or model.yaml changes (event-based, PRS-017 R15).
|
|
31
35
|
*/
|
|
32
36
|
invalidateCache(workspaceRoot: string): void;
|
|
33
37
|
/**
|
|
@@ -41,10 +45,6 @@ export declare class PerformanceOptimizer {
|
|
|
41
45
|
lockFiles: number;
|
|
42
46
|
manifests: number;
|
|
43
47
|
};
|
|
44
|
-
/**
|
|
45
|
-
* Detects if cached files are stale compared to disk.
|
|
46
|
-
*/
|
|
47
|
-
detectStaleCaches(): Promise<string[]>;
|
|
48
48
|
/**
|
|
49
49
|
* Normalizes a file path for cache keys.
|
|
50
50
|
*/
|