@velarscript/cli 0.12.1 → 0.14.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 +5 -13
- package/dist/browser-process-owner.d.ts +23 -0
- package/dist/browser-process-owner.d.ts.map +1 -1
- package/dist/browser-process-owner.js +46 -2
- package/dist/browser-process-owner.js.map +1 -1
- package/dist/browser-test-runner.d.ts.map +1 -1
- package/dist/browser-test-runner.js +110 -14
- package/dist/browser-test-runner.js.map +1 -1
- package/dist/cli.js +186 -106
- package/dist/cli.js.map +1 -1
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +28 -4
- package/dist/config.js.map +1 -1
- package/dist/dev-server.d.ts +18 -0
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +168 -8
- package/dist/dev-server.js.map +1 -1
- package/dist/extension-metadata.d.ts +6 -0
- package/dist/extension-metadata.d.ts.map +1 -1
- package/dist/extension-metadata.js +71 -4
- package/dist/extension-metadata.js.map +1 -1
- package/dist/format-guard.d.ts +20 -0
- package/dist/format-guard.d.ts.map +1 -0
- package/dist/format-guard.js +13 -0
- package/dist/format-guard.js.map +1 -0
- package/dist/framework-host.d.ts.map +1 -1
- package/dist/framework-host.js +15 -2
- package/dist/framework-host.js.map +1 -1
- package/dist/language-server-bundle-entry.js +0 -2
- package/dist/language-server-bundle-entry.js.map +1 -1
- package/dist/language-server-tool.d.ts.map +1 -1
- package/dist/language-server-tool.js +0 -2
- package/dist/language-server-tool.js.map +1 -1
- package/dist/language-server.d.ts +1 -1
- package/dist/language-server.d.ts.map +1 -1
- package/dist/language-server.js +87 -293
- package/dist/language-server.js.map +1 -1
- package/dist/local-request-guard.d.ts +18 -0
- package/dist/local-request-guard.d.ts.map +1 -0
- package/dist/local-request-guard.js +75 -0
- package/dist/local-request-guard.js.map +1 -0
- package/dist/mechanical-fixer.d.ts.map +1 -1
- package/dist/mechanical-fixer.js +116 -2
- package/dist/mechanical-fixer.js.map +1 -1
- package/dist/module-assets.d.ts +23 -0
- package/dist/module-assets.d.ts.map +1 -1
- package/dist/module-assets.js +216 -14
- package/dist/module-assets.js.map +1 -1
- package/dist/node-application.d.ts +8 -7
- package/dist/node-application.d.ts.map +1 -1
- package/dist/node-application.js +63 -32
- package/dist/node-application.js.map +1 -1
- package/dist/node-runtime-dependencies.d.ts +3 -0
- package/dist/node-runtime-dependencies.d.ts.map +1 -0
- package/dist/node-runtime-dependencies.js +32 -0
- package/dist/node-runtime-dependencies.js.map +1 -0
- package/dist/npm.d.ts +29 -0
- package/dist/npm.d.ts.map +1 -1
- package/dist/npm.js +39 -2
- package/dist/npm.js.map +1 -1
- package/dist/official-language-server-extensions.d.ts.map +1 -1
- package/dist/official-language-server-extensions.js +13 -0
- package/dist/official-language-server-extensions.js.map +1 -1
- package/dist/ownership-graph.d.ts.map +1 -1
- package/dist/ownership-graph.js +155 -38
- package/dist/ownership-graph.js.map +1 -1
- package/dist/package-manager.d.ts.map +1 -1
- package/dist/package-manager.js +4 -1
- package/dist/package-manager.js.map +1 -1
- package/dist/preview-server.d.ts.map +1 -1
- package/dist/preview-server.js +12 -4
- package/dist/preview-server.js.map +1 -1
- package/dist/production-build.d.ts.map +1 -1
- package/dist/production-build.js +24 -6
- package/dist/production-build.js.map +1 -1
- package/dist/production-verifier.js +3 -0
- package/dist/production-verifier.js.map +1 -1
- package/dist/project-check.d.ts +14 -1
- package/dist/project-check.d.ts.map +1 -1
- package/dist/project-check.js +17 -4
- package/dist/project-check.js.map +1 -1
- package/dist/project-format.d.ts +9 -0
- package/dist/project-format.d.ts.map +1 -1
- package/dist/project-format.js +13 -0
- package/dist/project-format.js.map +1 -1
- package/dist/project-semantic.d.ts.map +1 -1
- package/dist/project-semantic.js +15 -4
- package/dist/project-semantic.js.map +1 -1
- package/dist/project.d.ts +25 -0
- package/dist/project.d.ts.map +1 -1
- package/dist/project.js +341 -42
- package/dist/project.js.map +1 -1
- package/dist/reproduction.d.ts +18 -0
- package/dist/reproduction.d.ts.map +1 -1
- package/dist/reproduction.js +47 -6
- package/dist/reproduction.js.map +1 -1
- package/dist/stable-order.d.ts +17 -0
- package/dist/stable-order.d.ts.map +1 -0
- package/dist/stable-order.js +19 -0
- package/dist/stable-order.js.map +1 -0
- package/dist/standard-modules.d.ts +2 -2
- package/dist/standard-modules.d.ts.map +1 -1
- package/dist/standard-modules.js +2 -2
- package/dist/standard-modules.js.map +1 -1
- package/dist/static-deployment.d.ts.map +1 -1
- package/dist/static-deployment.js +27 -0
- package/dist/static-deployment.js.map +1 -1
- package/dist/test-runner.d.ts.map +1 -1
- package/dist/test-runner.js +196 -100
- package/dist/test-runner.js.map +1 -1
- package/dist/test-worker.d.ts +64 -0
- package/dist/test-worker.d.ts.map +1 -0
- package/dist/test-worker.js +161 -0
- package/dist/test-worker.js.map +1 -0
- package/dist/typescript-declarations.d.ts +1 -1
- package/dist/typescript-declarations.d.ts.map +1 -1
- package/dist/typescript-declarations.js +233 -21
- package/dist/typescript-declarations.js.map +1 -1
- package/dist/unowned-errors.d.ts +15 -2
- package/dist/unowned-errors.d.ts.map +1 -1
- package/dist/unowned-errors.js +13 -2
- package/dist/unowned-errors.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dist/workspace-index.d.ts.map +1 -1
- package/dist/workspace-index.js +42 -17
- package/dist/workspace-index.js.map +1 -1
- package/package.json +8 -8
- package/skill/ai-skill-node.md +91 -22
- package/skill/ai-skill-server.md +173 -0
- package/skill/ai-skill-web.md +51 -1
- package/skill/ai-skill.md +36 -13
- package/dist/official-script-language-service.d.ts +0 -2
- package/dist/official-script-language-service.d.ts.map +0 -1
- package/dist/official-script-language-service.js +0 -10
- package/dist/official-script-language-service.js.map +0 -1
- package/dist/official-tool-assets.d.ts +0 -3
- package/dist/official-tool-assets.d.ts.map +0 -1
- package/dist/official-tool-assets.js +0 -60
- package/dist/official-tool-assets.js.map +0 -1
- package/dist/script-language-service.d.ts +0 -82
- package/dist/script-language-service.d.ts.map +0 -1
- package/dist/script-language-service.js +0 -18
- package/dist/script-language-service.js.map +0 -1
package/dist/language-server.js
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
2
2
|
import { isAbsolute, relative, resolve } from "node:path";
|
|
3
|
-
import { compile, CORE_CONTEXTUAL_KEYWORD_WORDS, CORE_PRELUDE_NAMES,
|
|
3
|
+
import { compile, CORE_CONTEXTUAL_KEYWORD_WORDS, CORE_PRELUDE_NAMES, isSourceIdentifierPart, keywordKinds, PERMANENT_NAMESPACE_NAMES, permanentNamespaceCoveringModule, } from "@velarscript/compiler";
|
|
4
4
|
import { standardModuleInterfaces } from "./standard-modules.js";
|
|
5
5
|
import { VelarProjectSessions } from "./project-session.js";
|
|
6
6
|
import { VELAR_VERSION } from "./version.js";
|
|
7
7
|
import { hostErrorMessage } from "./host-error.js";
|
|
8
|
+
import { formatSourceChecked } from "./format-guard.js";
|
|
8
9
|
import { canonicalizePotentialPath, canonicalPathWithinCanonicalRoot } from "./canonical-path.js";
|
|
9
|
-
import { createScriptLanguageDocument, scriptLanguageFor, } from "./script-language-service.js";
|
|
10
10
|
import { buildOwnershipGraph, ownershipGraphRevision } from "./ownership-graph.js";
|
|
11
11
|
import { projectDefinitionAt, projectCompletionsAt, projectCompletionContextAt, projectDocumentSymbols, projectExpressionAt, projectMemberSymbolAt, projectPrepareRenameAt, projectReferencesAt, projectRenameAt, projectSemanticTokens, projectSignatureAt, projectSymbolAt, projectWorkspaceSymbols, } from "./project-semantic.js";
|
|
12
12
|
import { MAX_WORKSPACE_SEARCH_RESULTS, MAX_WORKSPACE_TEXT_FILES, MAX_WORKSPACE_CHANGE_PATHS, MAX_WORKSPACE_CHANGE_PATH_CODE_UNITS, MAX_WORKSPACE_CHANGE_TEXT_CODE_UNITS, WORKSPACE_TEXT_EXTENSIONS, WorkspaceIndexCancelledError, WorkspaceTextIndex, } from "./workspace-index.js";
|
|
13
|
-
export const VELAR_LANGUAGE_SERVER_PROTOCOL_VERSION =
|
|
13
|
+
export const VELAR_LANGUAGE_SERVER_PROTOCOL_VERSION = 5;
|
|
14
14
|
let activePositionEncoding = "utf-16";
|
|
15
15
|
let confinedWorkspaceRoot = null;
|
|
16
16
|
let confinedCanonicalRoot = null;
|
|
@@ -25,6 +25,21 @@ const semanticTokenTypes = [
|
|
|
25
25
|
"interface", "comment", "string", "keyword", "number", "regexp", "operator",
|
|
26
26
|
];
|
|
27
27
|
const semanticTokenModifiers = ["declaration", "readonly", "static"];
|
|
28
|
+
const nonVelarDocumentResults = new Map([
|
|
29
|
+
["textDocument/completion", { isIncomplete: false, items: [] }],
|
|
30
|
+
["textDocument/hover", null],
|
|
31
|
+
["textDocument/definition", null],
|
|
32
|
+
["textDocument/references", []],
|
|
33
|
+
["textDocument/documentHighlight", []],
|
|
34
|
+
["textDocument/prepareRename", null],
|
|
35
|
+
["textDocument/rename", null],
|
|
36
|
+
["textDocument/documentSymbol", []],
|
|
37
|
+
["textDocument/signatureHelp", null],
|
|
38
|
+
["textDocument/inlayHint", []],
|
|
39
|
+
["textDocument/semanticTokens/full", { data: [] }],
|
|
40
|
+
["textDocument/codeAction", []],
|
|
41
|
+
["textDocument/formatting", []],
|
|
42
|
+
]);
|
|
28
43
|
const keywordDocumentation = new Map([
|
|
29
44
|
["assert", "Requires a boolean or optional invariant and narrows stable values in following statements."],
|
|
30
45
|
["not", "Negates a checked condition; use `not in` for negative membership and `is not` for a negative runtime type test."],
|
|
@@ -134,7 +149,6 @@ export async function runLanguageServer() {
|
|
|
134
149
|
const configuredCanonical = configuredCanonicalRoot() ?? confinedWorkspaceRoot;
|
|
135
150
|
confinedCanonicalRoot = configuredCanonical ? await canonicalizePotentialPath(configuredCanonical) : null;
|
|
136
151
|
const documents = new Map();
|
|
137
|
-
const scriptDocuments = new Map();
|
|
138
152
|
const sessions = new VelarProjectSessions();
|
|
139
153
|
const workspaceIndex = new WorkspaceTextIndex();
|
|
140
154
|
const pendingRequests = new Set();
|
|
@@ -166,13 +180,13 @@ export async function runLanguageServer() {
|
|
|
166
180
|
process.stdout.write(`Content-Length: ${Buffer.byteLength(fallbackJson, "utf8")}\r\n\r\n${fallbackJson}`);
|
|
167
181
|
};
|
|
168
182
|
const overrides = () => new Map([...documents.values()].flatMap((item) => {
|
|
169
|
-
if (
|
|
183
|
+
if (!isVelarDocument(item))
|
|
170
184
|
return [];
|
|
171
185
|
const itemPath = pathOf(item.uri);
|
|
172
186
|
return itemPath ? [[itemPath, item.text]] : [];
|
|
173
187
|
}));
|
|
174
188
|
const projectFor = async (document) => {
|
|
175
|
-
if (
|
|
189
|
+
if (!isVelarDocument(document))
|
|
176
190
|
return null;
|
|
177
191
|
const path = pathOf(document.uri);
|
|
178
192
|
if (!path)
|
|
@@ -204,20 +218,16 @@ export async function runLanguageServer() {
|
|
|
204
218
|
const current = documents.get(document.uri);
|
|
205
219
|
if (!current || current.version !== document.version)
|
|
206
220
|
return;
|
|
207
|
-
|
|
208
|
-
if (script) {
|
|
221
|
+
if (!isVelarDocument(document)) {
|
|
209
222
|
send({
|
|
210
223
|
jsonrpc: "2.0",
|
|
211
224
|
method: "textDocument/publishDiagnostics",
|
|
212
|
-
params: {
|
|
213
|
-
uri: document.uri,
|
|
214
|
-
version: document.version,
|
|
215
|
-
diagnostics: boundedScriptDiagnostics(document.text, script.analysis()),
|
|
216
|
-
},
|
|
225
|
+
params: { uri: document.uri, version: document.version, diagnostics: [] },
|
|
217
226
|
});
|
|
218
227
|
return;
|
|
219
228
|
}
|
|
220
229
|
let diagnostics = [];
|
|
230
|
+
let advisories = [];
|
|
221
231
|
let notices = [];
|
|
222
232
|
let source;
|
|
223
233
|
try {
|
|
@@ -232,24 +242,28 @@ export async function runLanguageServer() {
|
|
|
232
242
|
.filter((failure) => failure.path === path)
|
|
233
243
|
.map((failure) => ({ code: "VEL9001", message: failure.message, span: { start: 0, end: 1 } })),
|
|
234
244
|
];
|
|
245
|
+
advisories = module.result.advisories;
|
|
235
246
|
notices = (project?.notices ?? []).filter((notice) => notice.path === path).map((notice) => notice.message);
|
|
236
247
|
source = module.result.source;
|
|
237
248
|
}
|
|
238
249
|
else {
|
|
239
250
|
const result = compile(document.text, { path });
|
|
240
251
|
diagnostics = result.diagnostics;
|
|
252
|
+
advisories = result.advisories;
|
|
241
253
|
source = result.source;
|
|
242
254
|
}
|
|
243
255
|
}
|
|
244
256
|
else {
|
|
245
257
|
const result = compile(document.text, { path: document.uri });
|
|
246
258
|
diagnostics = result.diagnostics;
|
|
259
|
+
advisories = result.advisories;
|
|
247
260
|
source = result.source;
|
|
248
261
|
}
|
|
249
262
|
}
|
|
250
263
|
catch (error) {
|
|
251
264
|
const result = compile(document.text, { path: document.uri });
|
|
252
265
|
diagnostics = [{ code: "VEL9001", message: hostErrorMessage(error), span: { start: 0, end: 1 } }];
|
|
266
|
+
advisories = [];
|
|
253
267
|
source = result.source;
|
|
254
268
|
}
|
|
255
269
|
if (documents.get(document.uri)?.version !== document.version)
|
|
@@ -260,7 +274,7 @@ export async function runLanguageServer() {
|
|
|
260
274
|
params: {
|
|
261
275
|
uri: document.uri,
|
|
262
276
|
version: document.version,
|
|
263
|
-
diagnostics: boundedDiagnostics(source, diagnostics, notices),
|
|
277
|
+
diagnostics: boundedDiagnostics(source, diagnostics, notices, advisories),
|
|
264
278
|
},
|
|
265
279
|
});
|
|
266
280
|
};
|
|
@@ -290,7 +304,7 @@ export async function runLanguageServer() {
|
|
|
290
304
|
const currentOverrides = overrides();
|
|
291
305
|
const roots = new Map();
|
|
292
306
|
for (const document of documents.values()) {
|
|
293
|
-
if (
|
|
307
|
+
if (!isVelarDocument(document))
|
|
294
308
|
continue;
|
|
295
309
|
const documentPath = pathOf(document.uri);
|
|
296
310
|
if (!documentPath)
|
|
@@ -338,6 +352,14 @@ export async function runLanguageServer() {
|
|
|
338
352
|
return;
|
|
339
353
|
}
|
|
340
354
|
const params = message.params;
|
|
355
|
+
if (message.id !== undefined && message.method && nonVelarDocumentResults.has(message.method)) {
|
|
356
|
+
const descriptor = params?.textDocument;
|
|
357
|
+
const document = descriptor?.uri ? documents.get(descriptor.uri) : undefined;
|
|
358
|
+
if (document && !isVelarDocument(document)) {
|
|
359
|
+
respond(message.id, nonVelarDocumentResults.get(message.method));
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
341
363
|
switch (message.method) {
|
|
342
364
|
case "initialize":
|
|
343
365
|
activePositionEncoding = requestedPositionEncoding(params);
|
|
@@ -375,9 +397,6 @@ export async function runLanguageServer() {
|
|
|
375
397
|
watchedFiles: true,
|
|
376
398
|
workspaceRescan: true,
|
|
377
399
|
cancellation: true,
|
|
378
|
-
scriptLanguages: ["javascript", "typescript"],
|
|
379
|
-
scriptImplementation: "velarscript",
|
|
380
|
-
incrementalScriptLexing: true,
|
|
381
400
|
workspaceSearch: true,
|
|
382
401
|
workspaceTextExtensions: WORKSPACE_TEXT_EXTENSIONS,
|
|
383
402
|
workspaceTextFileLimit: MAX_WORKSPACE_TEXT_FILES,
|
|
@@ -422,11 +441,7 @@ export async function runLanguageServer() {
|
|
|
422
441
|
documents.set(value.uri, value);
|
|
423
442
|
if (path)
|
|
424
443
|
workspaceIndex.openDocument(path, value.text);
|
|
425
|
-
|
|
426
|
-
const script = scriptLanguage ? createScriptLanguageDocument(scriptLanguage, value.text) : null;
|
|
427
|
-
if (script)
|
|
428
|
-
scriptDocuments.set(value.uri, script);
|
|
429
|
-
if (path && !script) {
|
|
444
|
+
if (path && isVelarDocument(value)) {
|
|
430
445
|
try {
|
|
431
446
|
await sessions.snapshot(path, overrides());
|
|
432
447
|
}
|
|
@@ -448,10 +463,6 @@ export async function runLanguageServer() {
|
|
|
448
463
|
const nextPath = pathOf(next.uri);
|
|
449
464
|
if (nextPath)
|
|
450
465
|
workspaceIndex.changeDocument(nextPath, next.text);
|
|
451
|
-
const script = scriptDocuments.get(next.uri);
|
|
452
|
-
const edit = script ? scriptTextEdit(current.text, next.text) : null;
|
|
453
|
-
if (script && edit)
|
|
454
|
-
script.apply([edit]);
|
|
455
466
|
schedulePublish(next.uri);
|
|
456
467
|
break;
|
|
457
468
|
}
|
|
@@ -464,14 +475,13 @@ export async function runLanguageServer() {
|
|
|
464
475
|
}
|
|
465
476
|
case "textDocument/didClose": {
|
|
466
477
|
const descriptor = params?.textDocument;
|
|
478
|
+
const current = documents.get(descriptor.uri);
|
|
467
479
|
documents.delete(descriptor.uri);
|
|
468
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
469
|
-
scriptDocuments.delete(descriptor.uri);
|
|
470
480
|
diagnosticUris.delete(descriptor.uri);
|
|
471
481
|
const path = pathOf(descriptor.uri);
|
|
472
482
|
if (path)
|
|
473
483
|
await queueWorkspaceIndex(() => workspaceIndex.closeDocument(path));
|
|
474
|
-
if (path &&
|
|
484
|
+
if (path && current && isVelarDocument(current))
|
|
475
485
|
await sessions.update(path, new Set([path]), overrides());
|
|
476
486
|
send({ jsonrpc: "2.0", method: "textDocument/publishDiagnostics", params: { uri: descriptor.uri, diagnostics: [] } });
|
|
477
487
|
break;
|
|
@@ -597,7 +607,7 @@ export async function runLanguageServer() {
|
|
|
597
607
|
break;
|
|
598
608
|
}
|
|
599
609
|
const document = documents.get(descriptor.uri);
|
|
600
|
-
if (!document ||
|
|
610
|
+
if (!document || !isVelarDocument(document)) {
|
|
601
611
|
respondError(message.id, "velar/ownershipGraph requires an open VelarScript document", -32602);
|
|
602
612
|
break;
|
|
603
613
|
}
|
|
@@ -661,7 +671,7 @@ export async function runLanguageServer() {
|
|
|
661
671
|
break;
|
|
662
672
|
}
|
|
663
673
|
const document = documents.get(descriptor.uri);
|
|
664
|
-
if (!document ||
|
|
674
|
+
if (!document || !isVelarDocument(document)) {
|
|
665
675
|
respondError(message.id, "velar/emittedJavaScript requires an open VelarScript document", -32602);
|
|
666
676
|
break;
|
|
667
677
|
}
|
|
@@ -690,7 +700,7 @@ export async function runLanguageServer() {
|
|
|
690
700
|
generatedChars: code?.length ?? 0,
|
|
691
701
|
sourceMapChars: sourceMap?.length ?? 0,
|
|
692
702
|
limitReached: (code?.length ?? 0) > limit || (sourceMap?.length ?? 0) > limit,
|
|
693
|
-
diagnostics: boundedDiagnostics(module.result.source, module.result.diagnostics, []),
|
|
703
|
+
diagnostics: boundedDiagnostics(module.result.source, module.result.diagnostics, [], module.result.advisories),
|
|
694
704
|
});
|
|
695
705
|
break;
|
|
696
706
|
}
|
|
@@ -707,7 +717,7 @@ export async function runLanguageServer() {
|
|
|
707
717
|
await waitForWorkspaceIndex(message.id);
|
|
708
718
|
const projects = new Map();
|
|
709
719
|
for (const document of documents.values()) {
|
|
710
|
-
if (
|
|
720
|
+
if (!isVelarDocument(document))
|
|
711
721
|
continue;
|
|
712
722
|
const path = pathOf(document.uri);
|
|
713
723
|
if (!path)
|
|
@@ -758,16 +768,6 @@ export async function runLanguageServer() {
|
|
|
758
768
|
const descriptor = params?.textDocument;
|
|
759
769
|
const position = params?.position;
|
|
760
770
|
const document = documents.get(descriptor.uri);
|
|
761
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
762
|
-
if (document && script) {
|
|
763
|
-
const items = script.completionsAt(scriptOffsetAt(document.text, position)).slice(0, MAX_LSP_RESULT_ITEMS).map((item) => ({
|
|
764
|
-
label: clipLspText(item.label),
|
|
765
|
-
kind: lspCompletionKind(item.kind),
|
|
766
|
-
detail: clipLspText(item.detail),
|
|
767
|
-
}));
|
|
768
|
-
respond(message.id, { isIncomplete: false, items });
|
|
769
|
-
break;
|
|
770
|
-
}
|
|
771
771
|
const path = pathOf(descriptor.uri);
|
|
772
772
|
const project = document ? await projectFor(document) : null;
|
|
773
773
|
const offset = document ? offsetAt(document.text, position) : 0;
|
|
@@ -790,15 +790,6 @@ export async function runLanguageServer() {
|
|
|
790
790
|
const descriptor = params?.textDocument;
|
|
791
791
|
const position = params?.position;
|
|
792
792
|
const document = documents.get(descriptor.uri);
|
|
793
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
794
|
-
if (document && script) {
|
|
795
|
-
const result = script.hoverAt(scriptOffsetAt(document.text, position));
|
|
796
|
-
respond(message.id, result ? {
|
|
797
|
-
contents: { kind: "markdown", value: `\`\`${clipLspText(result.contents)}\`\`` },
|
|
798
|
-
range: scriptRange(document.text, result),
|
|
799
|
-
} : null);
|
|
800
|
-
break;
|
|
801
|
-
}
|
|
802
793
|
respond(message.id, document ? await hover(document, position, await projectFor(document)) : null);
|
|
803
794
|
break;
|
|
804
795
|
}
|
|
@@ -806,12 +797,6 @@ export async function runLanguageServer() {
|
|
|
806
797
|
const descriptor = params?.textDocument;
|
|
807
798
|
const position = params?.position;
|
|
808
799
|
const document = documents.get(descriptor.uri);
|
|
809
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
810
|
-
if (document && script) {
|
|
811
|
-
const location = script.definitionAt(scriptOffsetAt(document.text, position));
|
|
812
|
-
respond(message.id, location ? { uri: descriptor.uri, range: scriptRange(document.text, location) } : null);
|
|
813
|
-
break;
|
|
814
|
-
}
|
|
815
800
|
const path = pathOf(descriptor.uri);
|
|
816
801
|
const project = document ? await projectFor(document) : null;
|
|
817
802
|
const location = document && path && project ? projectDefinitionAt(project, path, offsetAt(document.text, position)) : null;
|
|
@@ -823,14 +808,6 @@ export async function runLanguageServer() {
|
|
|
823
808
|
const position = params?.position;
|
|
824
809
|
const context = params?.context;
|
|
825
810
|
const document = documents.get(descriptor.uri);
|
|
826
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
827
|
-
if (document && script) {
|
|
828
|
-
const locations = script.referencesAt(scriptOffsetAt(document.text, position), context?.includeDeclaration ?? false)
|
|
829
|
-
.slice(0, MAX_LSP_RESULT_ITEMS)
|
|
830
|
-
.map((span) => ({ uri: descriptor.uri, range: scriptRange(document.text, span) }));
|
|
831
|
-
respond(message.id, locations);
|
|
832
|
-
break;
|
|
833
|
-
}
|
|
834
811
|
const path = pathOf(descriptor.uri);
|
|
835
812
|
const project = document ? await projectFor(document) : null;
|
|
836
813
|
const locations = document && path && project
|
|
@@ -844,14 +821,6 @@ export async function runLanguageServer() {
|
|
|
844
821
|
const descriptor = params?.textDocument;
|
|
845
822
|
const position = params?.position;
|
|
846
823
|
const document = documents.get(descriptor.uri);
|
|
847
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
848
|
-
if (document && script) {
|
|
849
|
-
const locations = script.referencesAt(scriptOffsetAt(document.text, position), true)
|
|
850
|
-
.slice(0, MAX_LSP_RESULT_ITEMS)
|
|
851
|
-
.map((span) => ({ range: scriptRange(document.text, span), kind: 1 }));
|
|
852
|
-
respond(message.id, locations);
|
|
853
|
-
break;
|
|
854
|
-
}
|
|
855
824
|
const path = pathOf(descriptor.uri);
|
|
856
825
|
const project = document ? await projectFor(document) : null;
|
|
857
826
|
const locations = document && path && project
|
|
@@ -869,12 +838,6 @@ export async function runLanguageServer() {
|
|
|
869
838
|
const descriptor = params?.textDocument;
|
|
870
839
|
const position = params?.position;
|
|
871
840
|
const document = documents.get(descriptor.uri);
|
|
872
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
873
|
-
if (document && script) {
|
|
874
|
-
const symbol = script.symbolAt(scriptOffsetAt(document.text, position));
|
|
875
|
-
respond(message.id, symbol ? { range: scriptRange(document.text, symbol), placeholder: symbol.name } : null);
|
|
876
|
-
break;
|
|
877
|
-
}
|
|
878
841
|
const path = pathOf(descriptor.uri);
|
|
879
842
|
const project = document ? await projectFor(document) : null;
|
|
880
843
|
const prepared = document && path && project ? projectPrepareRenameAt(project, path, offsetAt(document.text, position)) : null;
|
|
@@ -887,19 +850,6 @@ export async function runLanguageServer() {
|
|
|
887
850
|
const position = params?.position;
|
|
888
851
|
const newName = params?.newName;
|
|
889
852
|
const document = documents.get(descriptor.uri);
|
|
890
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
891
|
-
if (document && script) {
|
|
892
|
-
const renamed = script.renameAt(scriptOffsetAt(document.text, position), newName);
|
|
893
|
-
if (renamed.error)
|
|
894
|
-
respondError(message.id, renamed.error);
|
|
895
|
-
else if (renamed.edits.length > MAX_LSP_RESULT_ITEMS)
|
|
896
|
-
respondError(message.id, `Rename affects more than ${MAX_LSP_RESULT_ITEMS} locations`);
|
|
897
|
-
else
|
|
898
|
-
respond(message.id, {
|
|
899
|
-
changes: { [descriptor.uri]: renamed.edits.map((edit) => ({ range: scriptRange(document.text, edit), newText: edit.replacement })) },
|
|
900
|
-
});
|
|
901
|
-
break;
|
|
902
|
-
}
|
|
903
853
|
const path = pathOf(descriptor.uri);
|
|
904
854
|
const project = document ? await projectFor(document) : null;
|
|
905
855
|
const renamed = document && path && project ? projectRenameAt(project, path, offsetAt(document.text, position), newName) : "No renameable VelarScript symbol at this position";
|
|
@@ -914,17 +864,6 @@ export async function runLanguageServer() {
|
|
|
914
864
|
case "textDocument/documentSymbol": {
|
|
915
865
|
const descriptor = params?.textDocument;
|
|
916
866
|
const document = documents.get(descriptor.uri);
|
|
917
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
918
|
-
if (document && script) {
|
|
919
|
-
respond(message.id, script.analysis().symbols.slice(0, MAX_LSP_RESULT_ITEMS).map((symbol) => ({
|
|
920
|
-
name: clipLspText(symbol.name),
|
|
921
|
-
detail: clipLspText(symbol.type),
|
|
922
|
-
kind: lspSymbolKind(symbol.kind),
|
|
923
|
-
range: scriptRange(document.text, symbol),
|
|
924
|
-
selectionRange: scriptRange(document.text, symbol),
|
|
925
|
-
})));
|
|
926
|
-
break;
|
|
927
|
-
}
|
|
928
867
|
const path = pathOf(descriptor.uri);
|
|
929
868
|
const project = document ? await projectFor(document) : null;
|
|
930
869
|
respond(message.id, path && project ? projectDocumentSymbols(project, path).slice(0, MAX_LSP_RESULT_ITEMS).map((symbol) => ({
|
|
@@ -940,10 +879,6 @@ export async function runLanguageServer() {
|
|
|
940
879
|
const descriptor = params?.textDocument;
|
|
941
880
|
const position = params?.position;
|
|
942
881
|
const document = documents.get(descriptor.uri);
|
|
943
|
-
if (scriptDocuments.has(descriptor.uri)) {
|
|
944
|
-
respond(message.id, null);
|
|
945
|
-
break;
|
|
946
|
-
}
|
|
947
882
|
const path = pathOf(descriptor.uri);
|
|
948
883
|
const project = document ? await projectFor(document) : null;
|
|
949
884
|
const signature = document && path && project ? projectSignatureAt(project, path, offsetAt(document.text, position)) : null;
|
|
@@ -958,10 +893,6 @@ export async function runLanguageServer() {
|
|
|
958
893
|
const descriptor = params?.textDocument;
|
|
959
894
|
const range = params?.range;
|
|
960
895
|
const document = documents.get(descriptor.uri);
|
|
961
|
-
if (scriptDocuments.has(descriptor.uri)) {
|
|
962
|
-
respond(message.id, []);
|
|
963
|
-
break;
|
|
964
|
-
}
|
|
965
896
|
const path = pathOf(descriptor.uri);
|
|
966
897
|
const project = document ? await projectFor(document) : null;
|
|
967
898
|
respond(message.id, document && path && project ? projectInlayHints(project, path, document.text, range) : []);
|
|
@@ -970,11 +901,6 @@ export async function runLanguageServer() {
|
|
|
970
901
|
case "textDocument/semanticTokens/full": {
|
|
971
902
|
const descriptor = params?.textDocument;
|
|
972
903
|
const document = documents.get(descriptor.uri);
|
|
973
|
-
const script = scriptDocuments.get(descriptor.uri);
|
|
974
|
-
if (document && script) {
|
|
975
|
-
respond(message.id, { data: scriptSemanticTokenData(document.text, script.analysis()) });
|
|
976
|
-
break;
|
|
977
|
-
}
|
|
978
904
|
const path = pathOf(descriptor.uri);
|
|
979
905
|
const project = document ? await projectFor(document) : null;
|
|
980
906
|
const tokens = path && project ? projectSemanticTokens(project, path).slice(0, MAX_LSP_RESULT_ITEMS) : [];
|
|
@@ -985,10 +911,6 @@ export async function runLanguageServer() {
|
|
|
985
911
|
const descriptor = params?.textDocument;
|
|
986
912
|
const context = params?.context;
|
|
987
913
|
const document = documents.get(descriptor.uri);
|
|
988
|
-
if (scriptDocuments.has(descriptor.uri)) {
|
|
989
|
-
respond(message.id, []);
|
|
990
|
-
break;
|
|
991
|
-
}
|
|
992
914
|
const acceptsQuickFix = !context?.only || context.only.some((kind) => kind === "quickfix" || kind.startsWith("quickfix."));
|
|
993
915
|
const fixPath = pathOf(descriptor.uri);
|
|
994
916
|
const fixProject = document && acceptsQuickFix ? await projectFor(document) : null;
|
|
@@ -1004,13 +926,13 @@ export async function runLanguageServer() {
|
|
|
1004
926
|
respond(message.id, []);
|
|
1005
927
|
break;
|
|
1006
928
|
}
|
|
1007
|
-
if (scriptDocuments.has(descriptor.uri)) {
|
|
1008
|
-
respond(message.id, []);
|
|
1009
|
-
break;
|
|
1010
|
-
}
|
|
1011
929
|
const project = await projectFor(document);
|
|
1012
|
-
const formatted =
|
|
1013
|
-
|
|
930
|
+
const { text: formatted, stable } = formatSourceChecked(document.text, { extensions: project?.compilerExtensions ?? [] });
|
|
931
|
+
// Formatting is idempotent by contract, so a result the formatter would
|
|
932
|
+
// change again is a formatter defect. Offering it as an edit hands
|
|
933
|
+
// format-on-save a module the next save corrupts, and an editor cannot
|
|
934
|
+
// undo what it never saw as a change; no edits is the honest answer.
|
|
935
|
+
respond(message.id, !stable || formatted === document.text ? [] : [{ range: fullRange(document.text), newText: formatted }]);
|
|
1014
936
|
break;
|
|
1015
937
|
}
|
|
1016
938
|
default:
|
|
@@ -1096,49 +1018,33 @@ function isRpcMessage(value) {
|
|
|
1096
1018
|
function clipLspText(value) {
|
|
1097
1019
|
return value.length <= MAX_LSP_TEXT_CHARS ? value : `${value.slice(0, MAX_LSP_TEXT_CHARS - 1)}…`;
|
|
1098
1020
|
}
|
|
1099
|
-
function boundedDiagnostics(source, diagnostics, notices) {
|
|
1021
|
+
function boundedDiagnostics(source, diagnostics, notices, advisories) {
|
|
1100
1022
|
const output = [];
|
|
1101
1023
|
for (const diagnostic of diagnostics) {
|
|
1102
1024
|
if (output.length >= MAX_LSP_RESULT_ITEMS)
|
|
1103
1025
|
break;
|
|
1104
1026
|
output.push(lspDiagnostic(source, diagnostic));
|
|
1105
1027
|
}
|
|
1028
|
+
// D89: advisories are published on the same channel the protocol gives an
|
|
1029
|
+
// editor, one severity below an error, so the squiggle a reader sees says
|
|
1030
|
+
// "this spelling means something else" without claiming the file failed.
|
|
1031
|
+
for (const item of advisories) {
|
|
1032
|
+
if (output.length >= MAX_LSP_RESULT_ITEMS)
|
|
1033
|
+
break;
|
|
1034
|
+
output.push(lspAdvisory(source, item));
|
|
1035
|
+
}
|
|
1106
1036
|
for (const notice of notices) {
|
|
1107
1037
|
if (output.length >= MAX_LSP_RESULT_ITEMS)
|
|
1108
1038
|
break;
|
|
1109
1039
|
output.push(lspNotice(source, notice));
|
|
1110
1040
|
}
|
|
1111
|
-
if (diagnostics.length + notices.length > MAX_LSP_RESULT_ITEMS) {
|
|
1041
|
+
if (diagnostics.length + advisories.length + notices.length > MAX_LSP_RESULT_ITEMS) {
|
|
1112
1042
|
if (output.length >= MAX_LSP_RESULT_ITEMS)
|
|
1113
1043
|
output.pop();
|
|
1114
1044
|
output.push(lspNotice(source, `Diagnostics were truncated to ${MAX_LSP_RESULT_ITEMS} items`));
|
|
1115
1045
|
}
|
|
1116
1046
|
return output;
|
|
1117
1047
|
}
|
|
1118
|
-
function boundedScriptDiagnostics(text, analysis) {
|
|
1119
|
-
const diagnostics = analysis.diagnostics.slice(0, MAX_LSP_RESULT_ITEMS);
|
|
1120
|
-
const ends = diagnostics.map((diagnostic) => Math.max(diagnostic.start + 1, diagnostic.end));
|
|
1121
|
-
const positions = scriptPositionsAt(text, diagnostics.flatMap((diagnostic, index) => [diagnostic.start, ends[index]]));
|
|
1122
|
-
const output = diagnostics.map((diagnostic, index) => ({
|
|
1123
|
-
range: scriptRangeFromPositions(positions, diagnostic.start, ends[index]),
|
|
1124
|
-
severity: diagnostic.severity === "error" ? 1 : 2,
|
|
1125
|
-
code: diagnostic.code,
|
|
1126
|
-
source: "velar-script",
|
|
1127
|
-
message: clipLspText(diagnostic.message),
|
|
1128
|
-
}));
|
|
1129
|
-
if (analysis.diagnostics.length > MAX_LSP_RESULT_ITEMS) {
|
|
1130
|
-
if (output.length >= MAX_LSP_RESULT_ITEMS)
|
|
1131
|
-
output.pop();
|
|
1132
|
-
output.push({
|
|
1133
|
-
range: scriptRange(text, { start: 0, end: Math.min(1, codePointCount(text, 0, text.length)) }),
|
|
1134
|
-
severity: 2,
|
|
1135
|
-
code: "SCRIPT9001",
|
|
1136
|
-
source: "velar-script",
|
|
1137
|
-
message: `Script diagnostics were truncated to ${MAX_LSP_RESULT_ITEMS} items`,
|
|
1138
|
-
});
|
|
1139
|
-
}
|
|
1140
|
-
return output;
|
|
1141
|
-
}
|
|
1142
1048
|
function oversizedDiagnosticsFallback(params) {
|
|
1143
1049
|
const input = params && typeof params === "object" && !Array.isArray(params)
|
|
1144
1050
|
? params
|
|
@@ -1173,6 +1079,21 @@ function lspDiagnostic(source, item) {
|
|
|
1173
1079
|
message: clipLspText(item.message),
|
|
1174
1080
|
};
|
|
1175
1081
|
}
|
|
1082
|
+
/** D89: severity 2 is Warning — an advisory is reported, never a failure. */
|
|
1083
|
+
function lspAdvisory(source, item) {
|
|
1084
|
+
const start = lspSourcePosition(source, item.span.start);
|
|
1085
|
+
const end = lspSourcePosition(source, Math.max(item.span.start + 1, item.span.end));
|
|
1086
|
+
return {
|
|
1087
|
+
range: {
|
|
1088
|
+
start,
|
|
1089
|
+
end,
|
|
1090
|
+
},
|
|
1091
|
+
severity: 2,
|
|
1092
|
+
code: item.code,
|
|
1093
|
+
source: "velar",
|
|
1094
|
+
message: clipLspText(item.message),
|
|
1095
|
+
};
|
|
1096
|
+
}
|
|
1176
1097
|
function lspNotice(source, message) {
|
|
1177
1098
|
const start = lspSourcePosition(source, 0);
|
|
1178
1099
|
const end = lspSourcePosition(source, Math.min(1, source.text.length));
|
|
@@ -1267,74 +1188,20 @@ function semanticTokenData(source, tokens) {
|
|
|
1267
1188
|
}
|
|
1268
1189
|
return data;
|
|
1269
1190
|
}
|
|
1270
|
-
function scriptSemanticTokenData(text, analysis) {
|
|
1271
|
-
const tokens = analysis.tokens.slice(0, MAX_LSP_RESULT_ITEMS);
|
|
1272
|
-
const positions = scriptPositionsAt(text, tokens.flatMap((token) => [token.start, token.end]));
|
|
1273
|
-
const declarations = new Map(analysis.symbols.map((symbol) => [`${symbol.start}:${symbol.end}`, symbol]));
|
|
1274
|
-
const references = new Map(analysis.references.map((reference) => [`${reference.start}:${reference.end}`, reference]));
|
|
1275
|
-
const symbols = new Map(analysis.symbols.map((symbol) => [symbol.id, symbol]));
|
|
1276
|
-
const data = [];
|
|
1277
|
-
let previousLine = 0;
|
|
1278
|
-
let previousCharacter = 0;
|
|
1279
|
-
for (const token of tokens) {
|
|
1280
|
-
const key = `${token.start}:${token.end}`;
|
|
1281
|
-
const declaration = declarations.get(key);
|
|
1282
|
-
const reference = references.get(key);
|
|
1283
|
-
const symbol = declaration ?? (reference ? symbols.get(reference.symbolId) : undefined);
|
|
1284
|
-
const type = symbol ? scriptSemanticSymbolType(symbol.kind) : scriptLexicalTokenType(token.kind);
|
|
1285
|
-
if (!type)
|
|
1286
|
-
continue;
|
|
1287
|
-
const range = scriptRangeFromPositions(positions, token.start, token.end);
|
|
1288
|
-
if (range.start.line !== range.end.line || range.end.character <= range.start.character)
|
|
1289
|
-
continue;
|
|
1290
|
-
const deltaLine = range.start.line - previousLine;
|
|
1291
|
-
const deltaCharacter = deltaLine === 0 ? range.start.character - previousCharacter : range.start.character;
|
|
1292
|
-
const tokenType = semanticTokenTypes.indexOf(type);
|
|
1293
|
-
if (tokenType < 0 || deltaLine < 0 || deltaCharacter < 0)
|
|
1294
|
-
continue;
|
|
1295
|
-
const modifiers = (declaration ? 1 << semanticTokenModifiers.indexOf("declaration") : 0)
|
|
1296
|
-
| (symbol && (symbol.kind === "constant" || symbol.kind === "import") ? 1 << semanticTokenModifiers.indexOf("readonly") : 0);
|
|
1297
|
-
data.push(deltaLine, deltaCharacter, range.end.character - range.start.character, tokenType, modifiers);
|
|
1298
|
-
previousLine = range.start.line;
|
|
1299
|
-
previousCharacter = range.start.character;
|
|
1300
|
-
}
|
|
1301
|
-
return data;
|
|
1302
|
-
}
|
|
1303
|
-
function scriptSemanticSymbolType(kind) {
|
|
1304
|
-
switch (kind) {
|
|
1305
|
-
case "class": return "class";
|
|
1306
|
-
case "interface": return "interface";
|
|
1307
|
-
case "type": return "type";
|
|
1308
|
-
case "enum": return "enum";
|
|
1309
|
-
case "function": return "function";
|
|
1310
|
-
case "parameter": return "parameter";
|
|
1311
|
-
default: return "variable";
|
|
1312
|
-
}
|
|
1313
|
-
}
|
|
1314
|
-
function scriptLexicalTokenType(kind) {
|
|
1315
|
-
switch (kind) {
|
|
1316
|
-
case "comment": return "comment";
|
|
1317
|
-
case "string":
|
|
1318
|
-
case "template": return "string";
|
|
1319
|
-
case "keyword": return "keyword";
|
|
1320
|
-
case "number": return "number";
|
|
1321
|
-
case "regexp": return "regexp";
|
|
1322
|
-
case "operator": return "operator";
|
|
1323
|
-
case "identifier": return "variable";
|
|
1324
|
-
default: return null;
|
|
1325
|
-
}
|
|
1326
|
-
}
|
|
1327
1191
|
/**
|
|
1328
1192
|
* D38 §48: an editor quick fix is the same mechanical rewrite `velar fix`
|
|
1329
1193
|
* applies, read from the diagnostic that named it. The compiler registers the
|
|
1330
1194
|
* rewrite where it reports the diagnostic, so the editor never re-derives one
|
|
1331
|
-
* from message text and the two surfaces can never drift apart.
|
|
1195
|
+
* from message text and the two surfaces can never drift apart. D89: an
|
|
1196
|
+
* advisory that names one rewrite registers it the same way, so the editor
|
|
1197
|
+
* offers A2's swap as an ordinary quick fix; `velar fix` still reads
|
|
1198
|
+
* diagnostics only, because which name binds which value is a judgment.
|
|
1332
1199
|
*/
|
|
1333
1200
|
function quickFixes(document, module, diagnostics) {
|
|
1334
1201
|
if (!module)
|
|
1335
1202
|
return [];
|
|
1336
1203
|
const source = module.result.source;
|
|
1337
|
-
const registered = module.result.diagnostics
|
|
1204
|
+
const registered = [...module.result.diagnostics, ...module.result.advisories]
|
|
1338
1205
|
.filter((item) => item.fix && item.fix.edits.length > 0)
|
|
1339
1206
|
.map((item) => ({ code: item.code, range: lspRange(source, boundedDiagnosticSpan(source, item.span)), fix: item.fix }));
|
|
1340
1207
|
if (registered.length === 0)
|
|
@@ -1461,6 +1328,13 @@ function rawPathOf(uri) {
|
|
|
1461
1328
|
return null;
|
|
1462
1329
|
}
|
|
1463
1330
|
}
|
|
1331
|
+
function isVelarDocument(document) {
|
|
1332
|
+
const language = document.languageId.trim().toLowerCase();
|
|
1333
|
+
if (language === "velar" || language === "velarscript")
|
|
1334
|
+
return true;
|
|
1335
|
+
const path = rawPathOf(document.uri);
|
|
1336
|
+
return path !== null && path.toLowerCase().endsWith(".vel");
|
|
1337
|
+
}
|
|
1464
1338
|
async function authorizedPathOf(uri) {
|
|
1465
1339
|
const path = pathOf(uri);
|
|
1466
1340
|
if (!path || !confinedCanonicalRoot)
|
|
@@ -1485,24 +1359,6 @@ function applyContentChanges(text, changes) {
|
|
|
1485
1359
|
}
|
|
1486
1360
|
return result;
|
|
1487
1361
|
}
|
|
1488
|
-
function scriptTextEdit(previous, next) {
|
|
1489
|
-
if (previous === next)
|
|
1490
|
-
return null;
|
|
1491
|
-
const before = Array.from(previous);
|
|
1492
|
-
const after = Array.from(next);
|
|
1493
|
-
const limit = Math.min(before.length, after.length);
|
|
1494
|
-
let prefix = 0;
|
|
1495
|
-
while (prefix < limit && before[prefix] === after[prefix])
|
|
1496
|
-
prefix += 1;
|
|
1497
|
-
let suffix = 0;
|
|
1498
|
-
while (suffix < limit - prefix && before[before.length - suffix - 1] === after[after.length - suffix - 1])
|
|
1499
|
-
suffix += 1;
|
|
1500
|
-
return {
|
|
1501
|
-
start: prefix,
|
|
1502
|
-
end: before.length - suffix,
|
|
1503
|
-
replacement: after.slice(prefix, after.length - suffix).join(""),
|
|
1504
|
-
};
|
|
1505
|
-
}
|
|
1506
1362
|
function offsetAt(text, position) {
|
|
1507
1363
|
const requestedLine = Number.isSafeInteger(position?.line) && position.line >= 0
|
|
1508
1364
|
? position.line
|
|
@@ -1520,68 +1376,6 @@ function offsetAt(text, position) {
|
|
|
1520
1376
|
? Math.min(end, offset + requestedCharacter)
|
|
1521
1377
|
: codeUnitOffsetAt(text, offset, end, requestedCharacter);
|
|
1522
1378
|
}
|
|
1523
|
-
function scriptOffsetAt(text, position) {
|
|
1524
|
-
return codePointCount(text, 0, offsetAt(text, position));
|
|
1525
|
-
}
|
|
1526
|
-
function scriptRange(text, span) {
|
|
1527
|
-
const positions = scriptPositionsAt(text, [span.start, span.end]);
|
|
1528
|
-
return scriptRangeFromPositions(positions, span.start, span.end);
|
|
1529
|
-
}
|
|
1530
|
-
function scriptRangeFromPositions(positions, start, end) {
|
|
1531
|
-
const startPosition = positions.get(start);
|
|
1532
|
-
const endPosition = positions.get(end);
|
|
1533
|
-
if (!startPosition || !endPosition)
|
|
1534
|
-
throw new Error("Script coordinate map is incomplete");
|
|
1535
|
-
return { start: startPosition, end: endPosition };
|
|
1536
|
-
}
|
|
1537
|
-
function scriptPositionsAt(text, offsets) {
|
|
1538
|
-
const requested = [...new Set(offsets.map((offset) => Math.max(0, offset)))].sort((left, right) => left - right);
|
|
1539
|
-
const output = new Map();
|
|
1540
|
-
let codeUnit = 0;
|
|
1541
|
-
let codePoint = 0;
|
|
1542
|
-
let line = 0;
|
|
1543
|
-
let lineCodeUnit = 0;
|
|
1544
|
-
let lineCodePoint = 0;
|
|
1545
|
-
let pendingCarriageReturn = false;
|
|
1546
|
-
for (const requestedOffset of requested) {
|
|
1547
|
-
while (codePoint < requestedOffset && codeUnit < text.length) {
|
|
1548
|
-
const value = text.codePointAt(codeUnit);
|
|
1549
|
-
const width = value > 0xffff ? 2 : 1;
|
|
1550
|
-
const character = text[codeUnit];
|
|
1551
|
-
codeUnit += width;
|
|
1552
|
-
codePoint += 1;
|
|
1553
|
-
if (pendingCarriageReturn) {
|
|
1554
|
-
pendingCarriageReturn = false;
|
|
1555
|
-
if (character === "\n") {
|
|
1556
|
-
line += 1;
|
|
1557
|
-
lineCodeUnit = codeUnit;
|
|
1558
|
-
lineCodePoint = codePoint;
|
|
1559
|
-
continue;
|
|
1560
|
-
}
|
|
1561
|
-
}
|
|
1562
|
-
if (character === "\r") {
|
|
1563
|
-
if (text[codeUnit] === "\n")
|
|
1564
|
-
pendingCarriageReturn = true;
|
|
1565
|
-
else {
|
|
1566
|
-
line += 1;
|
|
1567
|
-
lineCodeUnit = codeUnit;
|
|
1568
|
-
lineCodePoint = codePoint;
|
|
1569
|
-
}
|
|
1570
|
-
}
|
|
1571
|
-
else if (character === "\n") {
|
|
1572
|
-
line += 1;
|
|
1573
|
-
lineCodeUnit = codeUnit;
|
|
1574
|
-
lineCodePoint = codePoint;
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
const boundedOffset = Math.min(requestedOffset, codePoint);
|
|
1578
|
-
output.set(requestedOffset, {
|
|
1579
|
-
line,
|
|
1580
|
-
character: activePositionEncoding === "utf-16" ? codeUnit - lineCodeUnit : boundedOffset - lineCodePoint,
|
|
1581
|
-
});
|
|
1582
|
-
}
|
|
1583
|
-
return output;
|
|
1584
|
-
}
|
|
1585
1379
|
function positionAt(text, requestedOffset) {
|
|
1586
1380
|
const offset = Math.max(0, Math.min(text.length, requestedOffset));
|
|
1587
1381
|
let line = 0;
|