@rohal12/spindle-lsp 0.15.34 → 0.15.36
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/dist/bin.js +216 -118
- package/dist/bin.js.map +4 -4
- package/package.json +2 -2
package/dist/bin.js
CHANGED
|
@@ -55,7 +55,7 @@ var VERSION;
|
|
|
55
55
|
var init_version = __esm({
|
|
56
56
|
"src/version.ts"() {
|
|
57
57
|
"use strict";
|
|
58
|
-
VERSION = false ? pkg.version : "0.15.
|
|
58
|
+
VERSION = false ? pkg.version : "0.15.36";
|
|
59
59
|
}
|
|
60
60
|
});
|
|
61
61
|
|
|
@@ -14056,6 +14056,9 @@ function peg$parse(input2, options) {
|
|
|
14056
14056
|
if (peg$success) return peg$result;
|
|
14057
14057
|
else peg$throw();
|
|
14058
14058
|
}
|
|
14059
|
+
function isOptionClause(name) {
|
|
14060
|
+
return name.toLowerCase() === OPTION_CLAUSE;
|
|
14061
|
+
}
|
|
14059
14062
|
function consumesOptionClauses(macro) {
|
|
14060
14063
|
const name = macro.name.toLowerCase();
|
|
14061
14064
|
return macro.source === "builtin" && !macro.widget && (name === "listbox" || name === "cycle");
|
|
@@ -21872,6 +21875,71 @@ function blockLookup(macros, includeRuntime = true) {
|
|
|
21872
21875
|
for (const macro of effectiveToolingMacros(macros)) definitions.set(macro.name, macro.block);
|
|
21873
21876
|
return (name) => includeRuntime && isRegisteredBlockMacro(name) || (definitions.get(name) ?? (includeRuntime ? isBlockMacro(name) : isBuiltinBlockMacro(name)));
|
|
21874
21877
|
}
|
|
21878
|
+
function macroCalls(source, macros = []) {
|
|
21879
|
+
const all = effectiveToolingMacros(macros);
|
|
21880
|
+
const definitions = new NameMap(all.map((macro) => [macro.name, macro]));
|
|
21881
|
+
const parametersOf2 = parameterLookup(all);
|
|
21882
|
+
const options = tokenizationOptions({
|
|
21883
|
+
macros: all,
|
|
21884
|
+
hooks: { isBlock: blockLookup(all, false) }
|
|
21885
|
+
});
|
|
21886
|
+
const hooks = options.hooks;
|
|
21887
|
+
const tokens2 = tokenizeMarkupTolerant$1(source, options).tokens;
|
|
21888
|
+
const calls = [];
|
|
21889
|
+
const classify2 = (tokens3) => {
|
|
21890
|
+
const found = /* @__PURE__ */ new Map();
|
|
21891
|
+
const pending = pairMarkup(tokens3, hooks).nodes.map((node2) => ({ node: node2 }));
|
|
21892
|
+
while (pending.length) {
|
|
21893
|
+
const { node: node2, parent } = pending.pop();
|
|
21894
|
+
const token = node2.token;
|
|
21895
|
+
if (token.type === "macro") {
|
|
21896
|
+
const definition2 = parent && definitions.get(parent.name);
|
|
21897
|
+
const value = definition2 && consumesOptionClauses(definition2) && isOptionClause(token.name);
|
|
21898
|
+
found.set(token, {
|
|
21899
|
+
token,
|
|
21900
|
+
kind: value ? "value" : "invocation",
|
|
21901
|
+
...value && { owner: parent }
|
|
21902
|
+
});
|
|
21903
|
+
}
|
|
21904
|
+
if (!node2.body) continue;
|
|
21905
|
+
const owner = token.type === "macro" ? token : void 0;
|
|
21906
|
+
for (const child of node2.body.children) pending.push({
|
|
21907
|
+
node: child,
|
|
21908
|
+
parent: owner
|
|
21909
|
+
});
|
|
21910
|
+
for (const branch of node2.body.branches) {
|
|
21911
|
+
found.set(branch.tag, {
|
|
21912
|
+
token: branch.tag,
|
|
21913
|
+
kind: "branch",
|
|
21914
|
+
owner
|
|
21915
|
+
});
|
|
21916
|
+
for (const child of branch.children) pending.push({
|
|
21917
|
+
node: child,
|
|
21918
|
+
parent: owner
|
|
21919
|
+
});
|
|
21920
|
+
}
|
|
21921
|
+
}
|
|
21922
|
+
for (const token of tokens3) {
|
|
21923
|
+
if (token.type !== "macro" || token.isClose) continue;
|
|
21924
|
+
const call = found.get(token) ?? {
|
|
21925
|
+
token,
|
|
21926
|
+
kind: "branch"
|
|
21927
|
+
};
|
|
21928
|
+
calls.push(call);
|
|
21929
|
+
}
|
|
21930
|
+
};
|
|
21931
|
+
classify2(tokens2);
|
|
21932
|
+
for (const piece of passagePiecesOf(source, tokens2, parametersOf2, { isBlock: hooks.isBlock })) {
|
|
21933
|
+
if (piece.kind !== "text" || !piece.tokens.length) continue;
|
|
21934
|
+
classify2(piece.tokens);
|
|
21935
|
+
}
|
|
21936
|
+
let literalEnd = -1;
|
|
21937
|
+
return calls.sort((a, b) => a.token.start - b.token.start).filter((call) => {
|
|
21938
|
+
if (call.token.start < literalEnd) return false;
|
|
21939
|
+
if (call.kind === "value" || call.kind === "branch") literalEnd = call.token.argsEnd;
|
|
21940
|
+
return true;
|
|
21941
|
+
});
|
|
21942
|
+
}
|
|
21875
21943
|
function passagePieces(source, macros = []) {
|
|
21876
21944
|
const all = effectiveToolingMacros(macros);
|
|
21877
21945
|
const parametersOf2 = parameterLookup(all);
|
|
@@ -33216,6 +33284,7 @@ var init_passage_markup = __esm({
|
|
|
33216
33284
|
cachedTokens;
|
|
33217
33285
|
cachedPairing;
|
|
33218
33286
|
cachedPieces;
|
|
33287
|
+
cachedInvocations;
|
|
33219
33288
|
cachedDeclarations;
|
|
33220
33289
|
/** The document offset of `contentOffset`. */
|
|
33221
33290
|
docOffset(contentOffset) {
|
|
@@ -33268,6 +33337,16 @@ var init_passage_markup = __esm({
|
|
|
33268
33337
|
get pieces() {
|
|
33269
33338
|
return this.cachedPieces ??= this.isMarkup ? passagePieces(this.content, this.doc.context.macros) : [];
|
|
33270
33339
|
}
|
|
33340
|
+
/** Contextual calls, excluding parent-owned clauses and widget registration heads. */
|
|
33341
|
+
get invocations() {
|
|
33342
|
+
if (!this.cachedInvocations) {
|
|
33343
|
+
const macros = this.doc.context.macros;
|
|
33344
|
+
const definitions = widgetDefinitions([{ ...this.passage, content: this.content }], macros);
|
|
33345
|
+
const registration = new Set(definitions.map((definition2) => definition2.start));
|
|
33346
|
+
this.cachedInvocations = this.isMarkup ? macroCalls(this.content, macros).filter((call) => call.kind === "invocation" && !registration.has(call.token.start)).map((call) => call.token) : [];
|
|
33347
|
+
}
|
|
33348
|
+
return this.cachedInvocations;
|
|
33349
|
+
}
|
|
33271
33350
|
/** Whether the cursor is executable, with decoded code mapped back to `content`. */
|
|
33272
33351
|
completionAt(offset2) {
|
|
33273
33352
|
return this.isMarkup ? completionContext(this.content, offset2, this.doc.context.macros) : { kind: "literal" };
|
|
@@ -33607,24 +33686,6 @@ var init_variable_tracker = __esm({
|
|
|
33607
33686
|
}
|
|
33608
33687
|
});
|
|
33609
33688
|
|
|
33610
|
-
// src/core/markup/tokens.ts
|
|
33611
|
-
function* markupTokens(passage) {
|
|
33612
|
-
yield* passage.tokens;
|
|
33613
|
-
for (const piece of passage.pieces) {
|
|
33614
|
-
if (piece.kind === "text") yield* piece.tokens;
|
|
33615
|
-
}
|
|
33616
|
-
}
|
|
33617
|
-
function* macroTokens(passage) {
|
|
33618
|
-
for (const token of markupTokens(passage)) {
|
|
33619
|
-
if (token.type === "macro") yield token;
|
|
33620
|
-
}
|
|
33621
|
-
}
|
|
33622
|
-
var init_tokens = __esm({
|
|
33623
|
-
"src/core/markup/tokens.ts"() {
|
|
33624
|
-
"use strict";
|
|
33625
|
-
}
|
|
33626
|
-
});
|
|
33627
|
-
|
|
33628
33689
|
// src/core/markup/widgets.ts
|
|
33629
33690
|
function widgetSources(passages, macros) {
|
|
33630
33691
|
const sources = /* @__PURE__ */ new Map();
|
|
@@ -33650,7 +33711,6 @@ var init_widget_registry = __esm({
|
|
|
33650
33711
|
"src/core/workspace/widget-registry.ts"() {
|
|
33651
33712
|
"use strict";
|
|
33652
33713
|
init_tooling();
|
|
33653
|
-
init_tokens();
|
|
33654
33714
|
init_widgets();
|
|
33655
33715
|
WidgetRegistry = class {
|
|
33656
33716
|
/** Widgets keyed by lower-cased name; Spindle resolves widgets case-insensitively. */
|
|
@@ -33729,8 +33789,8 @@ var init_widget_registry = __esm({
|
|
|
33729
33789
|
recordInvocations(uri, passages) {
|
|
33730
33790
|
const names = /* @__PURE__ */ new Set();
|
|
33731
33791
|
for (const passage of passages) {
|
|
33732
|
-
for (const macro of
|
|
33733
|
-
|
|
33792
|
+
for (const macro of passage.invocations) {
|
|
33793
|
+
names.add(macro.name.toLowerCase());
|
|
33734
33794
|
}
|
|
33735
33795
|
}
|
|
33736
33796
|
this.invokedByUri.set(uri, names);
|
|
@@ -34759,7 +34819,9 @@ var init_diagnostic_codes = __esm({
|
|
|
34759
34819
|
UnsupportedSpindleVersion: "SP001",
|
|
34760
34820
|
/** A fatal Twee source error reported by the public compiler parser. */
|
|
34761
34821
|
TweeSyntaxError: "SP002",
|
|
34762
|
-
/**
|
|
34822
|
+
/** Compiler-owned errors decoding StoryData metadata. */
|
|
34823
|
+
InvalidStoryData: "SP003",
|
|
34824
|
+
/** The selected entry passage is absent or omitted from compiled story data. */
|
|
34763
34825
|
MissingEntryPassage: "SP004",
|
|
34764
34826
|
/** `unknown-macro`: a macro that is none of the built-in, configured or defined ones. */
|
|
34765
34827
|
UndefinedMacro: "SP100",
|
|
@@ -34815,6 +34877,7 @@ var init_diagnostic_codes = __esm({
|
|
|
34815
34877
|
severityMap = {
|
|
34816
34878
|
[DiagnosticCode.UnsupportedSpindleVersion]: "warning",
|
|
34817
34879
|
[DiagnosticCode.TweeSyntaxError]: "error",
|
|
34880
|
+
[DiagnosticCode.InvalidStoryData]: "error",
|
|
34818
34881
|
[DiagnosticCode.MissingEntryPassage]: "error",
|
|
34819
34882
|
[DiagnosticCode.UndefinedMacro]: "warning",
|
|
34820
34883
|
[DiagnosticCode.MalformedContainer]: "error",
|
|
@@ -34853,6 +34916,24 @@ var init_diagnostic_codes = __esm({
|
|
|
34853
34916
|
}
|
|
34854
34917
|
});
|
|
34855
34918
|
|
|
34919
|
+
// src/core/markup/tokens.ts
|
|
34920
|
+
function* markupTokens(passage) {
|
|
34921
|
+
yield* passage.tokens;
|
|
34922
|
+
for (const piece of passage.pieces) {
|
|
34923
|
+
if (piece.kind === "text") yield* piece.tokens;
|
|
34924
|
+
}
|
|
34925
|
+
}
|
|
34926
|
+
function* macroTokens(passage) {
|
|
34927
|
+
for (const token of markupTokens(passage)) {
|
|
34928
|
+
if (token.type === "macro") yield token;
|
|
34929
|
+
}
|
|
34930
|
+
}
|
|
34931
|
+
var init_tokens = __esm({
|
|
34932
|
+
"src/core/markup/tokens.ts"() {
|
|
34933
|
+
"use strict";
|
|
34934
|
+
}
|
|
34935
|
+
});
|
|
34936
|
+
|
|
34856
34937
|
// src/core/markup/source-view.ts
|
|
34857
34938
|
function viewIndex(view, offset2) {
|
|
34858
34939
|
if (!view.sourceOffsets) return offset2 - view.offset;
|
|
@@ -35117,12 +35198,14 @@ function computeDiagnostics(uri, workspace, options) {
|
|
|
35117
35198
|
const story = storyReport(workspace);
|
|
35118
35199
|
diagnostics.push(...story.metadata.get(doc) ?? []);
|
|
35119
35200
|
const effective = new Set(workspace.passages.getEffectivePassages());
|
|
35201
|
+
let passageNames;
|
|
35202
|
+
const getPassageNames = () => passageNames ??= [...effective].filter(isRuntimePassage).map((passage) => passage.name);
|
|
35120
35203
|
for (const passage of doc.passages) {
|
|
35121
35204
|
if (!effective.has(passage.passage)) continue;
|
|
35122
35205
|
attempt(() => diagnostics.push(...markupDiagnostics(passage, story, workspace)));
|
|
35123
35206
|
attempt(() => diagnostics.push(...variableDiagnostics(passage, story)));
|
|
35124
35207
|
attempt(() => diagnostics.push(...structureDiagnostics(passage, workspace)));
|
|
35125
|
-
attempt(() => diagnostics.push(...argumentDiagnostics(passage, workspace)));
|
|
35208
|
+
attempt(() => diagnostics.push(...argumentDiagnostics(passage, workspace, getPassageNames)));
|
|
35126
35209
|
attempt(() => diagnostics.push(...widgetDiagnostics(passage, story, workspace)));
|
|
35127
35210
|
}
|
|
35128
35211
|
attempt(() => diagnostics.push(...versionDiagnostics(uri, doc, workspace)));
|
|
@@ -35215,8 +35298,8 @@ function buildReport(documents, workspace) {
|
|
|
35215
35298
|
const invoked = /* @__PURE__ */ new Set();
|
|
35216
35299
|
for (const passage of passages) {
|
|
35217
35300
|
if (!passage.isMarkup) continue;
|
|
35218
|
-
for (const token of
|
|
35219
|
-
|
|
35301
|
+
for (const token of passage.invocations) {
|
|
35302
|
+
invoked.add(token.name.toLowerCase());
|
|
35220
35303
|
}
|
|
35221
35304
|
}
|
|
35222
35305
|
return {
|
|
@@ -35235,17 +35318,33 @@ function buildReport(documents, workspace) {
|
|
|
35235
35318
|
}
|
|
35236
35319
|
function storyDataDiagnostics(documents, workspace) {
|
|
35237
35320
|
const found = /* @__PURE__ */ new Map();
|
|
35238
|
-
const
|
|
35239
|
-
|
|
35321
|
+
const data2 = workspace.passages.getEffectivePassage("StoryData");
|
|
35322
|
+
const implicit = workspace.passages.getEffectivePassage("Start");
|
|
35323
|
+
if (!data2 && (!implicit || isRuntimePassage(implicit))) return found;
|
|
35324
|
+
const { parseTwee, StoryBuilder, startPassageDiagnostics } = createCompilerRequire3(import.meta.url)("@rohal12/twee-ts");
|
|
35325
|
+
const builder = new StoryBuilder();
|
|
35326
|
+
const sources = new Map(documents.flatMap((doc) => doc.passages.map((passage) => [passage.passage, passage])));
|
|
35327
|
+
const parsed = new Map(documents.map((doc) => [doc, new Map(parseTwee(doc.text).passages.map((passage) => [passage.source?.line, passage]))]));
|
|
35328
|
+
const effective = workspace.passages.getEffectivePassages();
|
|
35329
|
+
for (const source of effective) {
|
|
35330
|
+
const passage = sources.get(source);
|
|
35331
|
+
if (!passage) continue;
|
|
35332
|
+
const input2 = parsed.get(passage.doc)?.get(source.headerEnd.start.line + 1);
|
|
35333
|
+
if (!input2) continue;
|
|
35240
35334
|
const diagnostics = [];
|
|
35241
|
-
|
|
35242
|
-
|
|
35243
|
-
|
|
35244
|
-
if (data2.start && !workspace.passages.getEffectivePassage(data2.start)) {
|
|
35245
|
-
diagnostics.push(makeDiag(passage.passage.nameRange, DiagnosticCode.MissingEntryPassage, `Starting passage "${data2.start}" not found.`));
|
|
35246
|
-
}
|
|
35335
|
+
builder.add(input2, diagnostics);
|
|
35336
|
+
if (source.name === "StoryData") {
|
|
35337
|
+
found.set(passage.doc, diagnostics.filter((d) => d.level === "error").map((d) => makeDiag(passage.range(0, passage.content.trimEnd().length), DiagnosticCode.InvalidStoryData, d.message)));
|
|
35247
35338
|
}
|
|
35248
|
-
|
|
35339
|
+
}
|
|
35340
|
+
const story = builder.build();
|
|
35341
|
+
const entry = workspace.passages.getEffectivePassage(story.twine2.start || "Start");
|
|
35342
|
+
const owner = story.twine2.start ? workspace.passages.getEffectivePassage("StoryData") : entry;
|
|
35343
|
+
const markup = owner && sources.get(owner);
|
|
35344
|
+
if (markup) {
|
|
35345
|
+
const diagnostics = found.get(markup.doc) ?? [];
|
|
35346
|
+
diagnostics.push(...startPassageDiagnostics(story).map((d) => makeDiag(markup.passage.nameRange, DiagnosticCode.MissingEntryPassage, d.message)));
|
|
35347
|
+
found.set(markup.doc, diagnostics);
|
|
35249
35348
|
}
|
|
35250
35349
|
return found;
|
|
35251
35350
|
}
|
|
@@ -35559,9 +35658,8 @@ function isReadInBody(passage, bodyStart, bodyEnd, name, macroStart, macroEnd) {
|
|
|
35559
35658
|
}
|
|
35560
35659
|
return false;
|
|
35561
35660
|
}
|
|
35562
|
-
function argumentDiagnostics(passage, workspace) {
|
|
35661
|
+
function argumentDiagnostics(passage, workspace, getPassageNames) {
|
|
35563
35662
|
const diagnostics = [];
|
|
35564
|
-
const passageNames = workspace.passages.getEffectivePassages().filter(isRuntimePassage).map((candidate) => candidate.name);
|
|
35565
35663
|
for (const token of passage.isMarkup ? macroTokens(passage) : []) {
|
|
35566
35664
|
if (token.type !== "macro" || token.isClose) continue;
|
|
35567
35665
|
const info = workspace.getEffectiveMacro(token.name);
|
|
@@ -35581,7 +35679,7 @@ function argumentDiagnostics(passage, workspace) {
|
|
|
35581
35679
|
}
|
|
35582
35680
|
continue;
|
|
35583
35681
|
}
|
|
35584
|
-
const result2 = params.validate(args2, { passages:
|
|
35682
|
+
const result2 = params.validate(args2, { passages: getPassageNames() });
|
|
35585
35683
|
if (result2.variantIndex === null) continue;
|
|
35586
35684
|
for (const error62 of result2.errors) {
|
|
35587
35685
|
const code = error62.message.startsWith("Too many arguments") ? DiagnosticCode.TooManyArguments : DiagnosticCode.ParameterTypeError;
|
|
@@ -35597,8 +35695,7 @@ function widgetDiagnostics(passage, story, workspace) {
|
|
|
35597
35695
|
if (!passage.isMarkup) return [];
|
|
35598
35696
|
const diagnostics = [];
|
|
35599
35697
|
const macros = [...macroTokens(passage)];
|
|
35600
|
-
for (const token of
|
|
35601
|
-
if (token.isClose) continue;
|
|
35698
|
+
for (const token of passage.invocations) {
|
|
35602
35699
|
if (workspace.getEffectiveMacro(token.name)) continue;
|
|
35603
35700
|
const widget = story.widgets.get(token.name.toLowerCase());
|
|
35604
35701
|
if (!widget) continue;
|
|
@@ -35732,7 +35829,6 @@ var init_diagnostics = __esm({
|
|
|
35732
35829
|
init_link_parser();
|
|
35733
35830
|
init_passage_parser();
|
|
35734
35831
|
init_story_variables_owner();
|
|
35735
|
-
init_story_data();
|
|
35736
35832
|
init_macro_sources();
|
|
35737
35833
|
init_spindle_version();
|
|
35738
35834
|
tweeReports = /* @__PURE__ */ new WeakMap();
|
|
@@ -87171,7 +87267,7 @@ var init_markup_cursor = __esm({
|
|
|
87171
87267
|
const found = [];
|
|
87172
87268
|
for (const token of region.tokens) {
|
|
87173
87269
|
if (token.type !== "macro" || token.isClose || token.nameEnd >= at3 || at3 >= token.end) continue;
|
|
87174
|
-
found.push({ start: token.start, name: token.name, argsBefore: at3 >= token.argsStart ? region.view.text.slice(viewIndex(region.view, token.argsStart), viewIndex(region.view, at3)) : "" });
|
|
87270
|
+
found.push({ start: token.start, name: token.name, invocation: this.passage.invocations.some((call) => call.start === token.start), argsBefore: at3 >= token.argsStart ? region.view.text.slice(viewIndex(region.view, token.argsStart), viewIndex(region.view, at3)) : "" });
|
|
87175
87271
|
}
|
|
87176
87272
|
for (const error62 of region.errors) {
|
|
87177
87273
|
const source = region.view.text;
|
|
@@ -87181,7 +87277,7 @@ var init_markup_cursor = __esm({
|
|
|
87181
87277
|
if (name && name[0] !== "/") found.push({ start: error62.offset, name, argsBefore: source.slice(end, viewIndex(region.view, at3)).trimStart() });
|
|
87182
87278
|
}
|
|
87183
87279
|
const innermost = found.filter((macro) => known(macro.name)).sort((a, b) => b.start - a.start)[0];
|
|
87184
|
-
if (innermost) return
|
|
87280
|
+
if (innermost) return innermost;
|
|
87185
87281
|
}
|
|
87186
87282
|
return void 0;
|
|
87187
87283
|
}
|
|
@@ -87432,7 +87528,7 @@ function linkable(name) {
|
|
|
87432
87528
|
return tokens2.length === 1 && link.type === "link" && link.target === name && !bracketLinkMismatch("label", name);
|
|
87433
87529
|
}
|
|
87434
87530
|
function getPassageNameCompletions(workspace) {
|
|
87435
|
-
return workspace.passages.getEffectivePassages().filter((p) => isRuntimePassage(p) && linkable(p.name)).map((p) => ({
|
|
87531
|
+
return workspace.passages.getEffectivePassages().filter((p) => isRuntimePassage(p) && !isSpecialPassage(p.name) && linkable(p.name)).map((p) => ({
|
|
87436
87532
|
label: p.name,
|
|
87437
87533
|
kind: 18,
|
|
87438
87534
|
// CompletionItemKind.Reference
|
|
@@ -87473,6 +87569,65 @@ var init_completions = __esm({
|
|
|
87473
87569
|
}
|
|
87474
87570
|
});
|
|
87475
87571
|
|
|
87572
|
+
// src/core/markup/macro-heads.ts
|
|
87573
|
+
function* pairedHeads(paired, tokens2) {
|
|
87574
|
+
const unclosed = [];
|
|
87575
|
+
for (const node2 of walkNodes(paired.nodes)) {
|
|
87576
|
+
if (node2.token.type === "macro") yield { name: node2.token.name, closing: false, opener: node2.token.start, start: node2.token.nameStart, end: node2.token.nameEnd };
|
|
87577
|
+
for (const branch of node2.body?.branches ?? []) {
|
|
87578
|
+
yield { name: branch.tag.name, closing: false, opener: branch.tag.start, start: branch.tag.nameStart, end: branch.tag.nameEnd };
|
|
87579
|
+
}
|
|
87580
|
+
const close = node2.body?.close;
|
|
87581
|
+
if (node2.token.type !== "macro") continue;
|
|
87582
|
+
if (close?.type === "macro" && close.name.toLowerCase() === node2.token.name.toLowerCase()) {
|
|
87583
|
+
yield { name: close.name, closing: true, opener: node2.token.start, start: close.nameStart, end: close.nameEnd };
|
|
87584
|
+
} else if (node2.body && !close) {
|
|
87585
|
+
unclosed.push({ name: node2.token.name.toLowerCase(), start: node2.token.start });
|
|
87586
|
+
}
|
|
87587
|
+
}
|
|
87588
|
+
const byStart = new Map(tokens2.map((token) => [token.start, token]));
|
|
87589
|
+
for (const error62 of paired.errors) {
|
|
87590
|
+
const token = byStart.get(error62.start);
|
|
87591
|
+
if (error62.code !== "stray-closer" || token?.type !== "macro" || !token.isClose) continue;
|
|
87592
|
+
const name = token.name.toLowerCase();
|
|
87593
|
+
const open2 = unclosed.find((open3) => open3.name === name && open3.start < error62.start);
|
|
87594
|
+
if (open2) {
|
|
87595
|
+
yield { name: token.name, closing: true, opener: open2.start, start: token.nameStart, end: token.nameEnd };
|
|
87596
|
+
}
|
|
87597
|
+
}
|
|
87598
|
+
}
|
|
87599
|
+
function passageMacroHeads(passage) {
|
|
87600
|
+
let heads = kept2.get(passage);
|
|
87601
|
+
if (heads) return heads;
|
|
87602
|
+
const isBlock = (name) => passage.doc.context.isBlock(name);
|
|
87603
|
+
const found = [...pairedHeads(passage.pairing, passage.tokens)];
|
|
87604
|
+
for (const piece of passage.pieces) {
|
|
87605
|
+
if (piece.kind !== "text") continue;
|
|
87606
|
+
found.push(...pairedHeads(pairMarkup(piece.tokens, { isBlock }), piece.tokens));
|
|
87607
|
+
}
|
|
87608
|
+
const invocations = new Set(passage.invocations.map((token) => token.start));
|
|
87609
|
+
heads = found.sort((a, b) => a.start - b.start).map(({ opener, ...head }) => ({ ...head, invocation: invocations.has(opener), passage, range: passage.range(head.start, head.end) }));
|
|
87610
|
+
kept2.set(passage, heads);
|
|
87611
|
+
return heads;
|
|
87612
|
+
}
|
|
87613
|
+
function documentMacroHeads(doc) {
|
|
87614
|
+
return doc.passages.flatMap((passage) => passage.isMarkup ? [...passageMacroHeads(passage)] : []);
|
|
87615
|
+
}
|
|
87616
|
+
function macroHeadAt(doc, position) {
|
|
87617
|
+
const passage = doc.passageAt(position);
|
|
87618
|
+
if (!passage?.isMarkup) return void 0;
|
|
87619
|
+
return passageMacroHeads(passage).find(({ range: { start, end } }) => start.line === position.line && position.character >= start.character && position.character <= end.character);
|
|
87620
|
+
}
|
|
87621
|
+
var kept2;
|
|
87622
|
+
var init_macro_heads = __esm({
|
|
87623
|
+
"src/core/markup/macro-heads.ts"() {
|
|
87624
|
+
"use strict";
|
|
87625
|
+
init_tooling();
|
|
87626
|
+
init_tree();
|
|
87627
|
+
kept2 = /* @__PURE__ */ new WeakMap();
|
|
87628
|
+
}
|
|
87629
|
+
});
|
|
87630
|
+
|
|
87476
87631
|
// src/plugins/hover.ts
|
|
87477
87632
|
function getHoverInfo(uri, position, workspace) {
|
|
87478
87633
|
const doc = workspace.markup.get(uri);
|
|
@@ -87501,7 +87656,7 @@ function getMacroHover(passage, at3, workspace) {
|
|
|
87501
87656
|
return { contents: parts.join("\n"), range: range2 };
|
|
87502
87657
|
}
|
|
87503
87658
|
const widget = workspace.widgets.getWidget(macro.name);
|
|
87504
|
-
if (widget) return buildWidgetHover(widget, range2);
|
|
87659
|
+
if (widget && macroHeadAt(passage.doc, passage.position(at3))?.invocation) return buildWidgetHover(widget, range2);
|
|
87505
87660
|
}
|
|
87506
87661
|
return null;
|
|
87507
87662
|
}
|
|
@@ -87541,6 +87696,7 @@ var init_hover = __esm({
|
|
|
87541
87696
|
"use strict";
|
|
87542
87697
|
init_text();
|
|
87543
87698
|
init_tokens();
|
|
87699
|
+
init_macro_heads();
|
|
87544
87700
|
init_markup_symbols();
|
|
87545
87701
|
VARIABLE_KINDS = {
|
|
87546
87702
|
$: "Story variable",
|
|
@@ -87678,6 +87834,7 @@ ${p.documentation}`) : []
|
|
|
87678
87834
|
activeParameter: positional ? argument : 0
|
|
87679
87835
|
};
|
|
87680
87836
|
}
|
|
87837
|
+
if (enclosing.invocation === false) return null;
|
|
87681
87838
|
const widget = workspace.widgets.getWidget(macroName);
|
|
87682
87839
|
if (widget && widget.params.length > 0) {
|
|
87683
87840
|
const paramLabels = widget.params;
|
|
@@ -87741,63 +87898,6 @@ var init_signature = __esm({
|
|
|
87741
87898
|
}
|
|
87742
87899
|
});
|
|
87743
87900
|
|
|
87744
|
-
// src/core/markup/macro-heads.ts
|
|
87745
|
-
function* pairedHeads(paired, tokens2) {
|
|
87746
|
-
const unclosed = [];
|
|
87747
|
-
for (const node2 of walkNodes(paired.nodes)) {
|
|
87748
|
-
if (node2.token.type === "macro") yield { name: node2.token.name, closing: false, start: node2.token.nameStart, end: node2.token.nameEnd };
|
|
87749
|
-
for (const branch of node2.body?.branches ?? []) {
|
|
87750
|
-
yield { name: branch.tag.name, closing: false, start: branch.tag.nameStart, end: branch.tag.nameEnd };
|
|
87751
|
-
}
|
|
87752
|
-
const close = node2.body?.close;
|
|
87753
|
-
if (node2.token.type !== "macro") continue;
|
|
87754
|
-
if (close?.type === "macro" && close.name.toLowerCase() === node2.token.name.toLowerCase()) {
|
|
87755
|
-
yield { name: close.name, closing: true, start: close.nameStart, end: close.nameEnd };
|
|
87756
|
-
} else if (node2.body && !close) {
|
|
87757
|
-
unclosed.push({ name: node2.token.name.toLowerCase(), start: node2.token.start });
|
|
87758
|
-
}
|
|
87759
|
-
}
|
|
87760
|
-
const byStart = new Map(tokens2.map((token) => [token.start, token]));
|
|
87761
|
-
for (const error62 of paired.errors) {
|
|
87762
|
-
const token = byStart.get(error62.start);
|
|
87763
|
-
if (error62.code !== "stray-closer" || token?.type !== "macro" || !token.isClose) continue;
|
|
87764
|
-
const name = token.name.toLowerCase();
|
|
87765
|
-
if (unclosed.some((open2) => open2.name === name && open2.start < error62.start)) {
|
|
87766
|
-
yield { name: token.name, closing: true, start: token.nameStart, end: token.nameEnd };
|
|
87767
|
-
}
|
|
87768
|
-
}
|
|
87769
|
-
}
|
|
87770
|
-
function passageMacroHeads(passage) {
|
|
87771
|
-
let heads = kept2.get(passage);
|
|
87772
|
-
if (heads) return heads;
|
|
87773
|
-
const isBlock = (name) => passage.doc.context.isBlock(name);
|
|
87774
|
-
const found = [...pairedHeads(passage.pairing, passage.tokens)];
|
|
87775
|
-
for (const piece of passage.pieces) {
|
|
87776
|
-
if (piece.kind !== "text") continue;
|
|
87777
|
-
found.push(...pairedHeads(pairMarkup(piece.tokens, { isBlock }), piece.tokens));
|
|
87778
|
-
}
|
|
87779
|
-
heads = found.sort((a, b) => a.start - b.start).map((head) => ({ ...head, passage, range: passage.range(head.start, head.end) }));
|
|
87780
|
-
kept2.set(passage, heads);
|
|
87781
|
-
return heads;
|
|
87782
|
-
}
|
|
87783
|
-
function documentMacroHeads(doc) {
|
|
87784
|
-
return doc.passages.flatMap((passage) => passage.isMarkup ? [...passageMacroHeads(passage)] : []);
|
|
87785
|
-
}
|
|
87786
|
-
function macroHeadAt(doc, position) {
|
|
87787
|
-
const passage = doc.passageAt(position);
|
|
87788
|
-
if (!passage?.isMarkup) return void 0;
|
|
87789
|
-
return passageMacroHeads(passage).find(({ range: { start, end } }) => start.line === position.line && position.character >= start.character && position.character <= end.character);
|
|
87790
|
-
}
|
|
87791
|
-
var kept2;
|
|
87792
|
-
var init_macro_heads = __esm({
|
|
87793
|
-
"src/core/markup/macro-heads.ts"() {
|
|
87794
|
-
"use strict";
|
|
87795
|
-
init_tooling();
|
|
87796
|
-
init_tree();
|
|
87797
|
-
kept2 = /* @__PURE__ */ new WeakMap();
|
|
87798
|
-
}
|
|
87799
|
-
});
|
|
87800
|
-
|
|
87801
87901
|
// src/plugins/definition.ts
|
|
87802
87902
|
function getDefinition(uri, position, workspace) {
|
|
87803
87903
|
const text3 = workspace.documents.getText(uri);
|
|
@@ -87824,7 +87924,7 @@ function getPassageRefDefinition(uri, position, workspace) {
|
|
|
87824
87924
|
function getWidgetDefinition(uri, position, workspace) {
|
|
87825
87925
|
const doc = workspace.markup.get(uri);
|
|
87826
87926
|
const head = doc && macroHeadAt(doc, position);
|
|
87827
|
-
if (!head) return null;
|
|
87927
|
+
if (!head?.invocation) return null;
|
|
87828
87928
|
if (workspace.getEffectiveMacro(head.name)) return null;
|
|
87829
87929
|
const widget = workspace.widgets.getWidget(head.name);
|
|
87830
87930
|
return widget ? { uri: widget.uri, range: widget.range } : null;
|
|
@@ -87887,7 +87987,7 @@ function findReferences(uri, position, workspace, includeDeclaration) {
|
|
|
87887
87987
|
if (declaration) return findWidgetReferences(declaration.name, workspace, includeDeclaration);
|
|
87888
87988
|
const doc = workspace.markup.get(uri);
|
|
87889
87989
|
const head = doc && macroHeadAt(doc, position);
|
|
87890
|
-
if (head) {
|
|
87990
|
+
if (head?.invocation) {
|
|
87891
87991
|
const widget = workspace.widgets.getWidget(head.name);
|
|
87892
87992
|
if (!workspace.getEffectiveMacro(head.name) && widget && (!head.closing || workspace.isContainer(head.name))) {
|
|
87893
87993
|
return findWidgetReferences(head.name, workspace, includeDeclaration);
|
|
@@ -87957,17 +88057,11 @@ function findWidgetReferences(widgetName2, workspace, includeDeclaration, includ
|
|
|
87957
88057
|
if (workspace.getEffectiveMacro(widgetName2)) return locations;
|
|
87958
88058
|
const lowerName2 = widgetName2.toLowerCase();
|
|
87959
88059
|
const isBlock = workspace.isContainer(widgetName2);
|
|
87960
|
-
|
|
87961
|
-
const doc = workspace.markup.get(
|
|
87962
|
-
|
|
87963
|
-
|
|
87964
|
-
|
|
87965
|
-
if (head.name.toLowerCase() === lowerName2) {
|
|
87966
|
-
locations.push({ uri: docUri, range: head.range });
|
|
87967
|
-
}
|
|
87968
|
-
}
|
|
87969
|
-
}
|
|
87970
|
-
return locations;
|
|
88060
|
+
const calls = workspace.documents.getUris().flatMap((uri) => {
|
|
88061
|
+
const doc = workspace.markup.get(uri);
|
|
88062
|
+
return doc ? documentMacroHeads(doc).filter((head) => head.invocation && head.name.toLowerCase() === lowerName2 && (!head.closing || isBlock && includeClosingTags)).map((head) => ({ uri, range: head.range })) : [];
|
|
88063
|
+
});
|
|
88064
|
+
return locations.concat(calls);
|
|
87971
88065
|
}
|
|
87972
88066
|
function toLspRange3(r) {
|
|
87973
88067
|
return {
|
|
@@ -88292,7 +88386,7 @@ function resolveSymbolAtCursor(uri, position, workspace) {
|
|
|
88292
88386
|
if (declaration) return { kind: "widget", name: declaration.name, range: declaration.nameRange };
|
|
88293
88387
|
const doc = workspace.markup.get(uri);
|
|
88294
88388
|
const head = doc && macroHeadAt(doc, position);
|
|
88295
|
-
if (head) {
|
|
88389
|
+
if (head?.invocation) {
|
|
88296
88390
|
const widget = workspace.widgets.getWidget(head.name);
|
|
88297
88391
|
if (!workspace.getEffectiveMacro(head.name) && widget && (!head.closing || workspace.isContainer(head.name))) {
|
|
88298
88392
|
return { kind: "widget", name: head.name, range: head.range };
|
|
@@ -88479,7 +88573,7 @@ function computeInlayHints(uri, range2, workspace) {
|
|
|
88479
88573
|
function addWidgetParamHints(passages, inRange, workspace, hints) {
|
|
88480
88574
|
if (workspace.widgets.getAllWidgets().length === 0) return;
|
|
88481
88575
|
for (const passage of passages) {
|
|
88482
|
-
for (const token of
|
|
88576
|
+
for (const token of passage.invocations) {
|
|
88483
88577
|
if (token.isClose || token.rawArgs === "") continue;
|
|
88484
88578
|
if (!inRange(passage.position(token.start).line)) continue;
|
|
88485
88579
|
if (workspace.getEffectiveMacro(token.name)) continue;
|
|
@@ -88518,7 +88612,6 @@ var init_inlay_hints = __esm({
|
|
|
88518
88612
|
"use strict";
|
|
88519
88613
|
init_tooling();
|
|
88520
88614
|
init_source_view();
|
|
88521
|
-
init_tokens();
|
|
88522
88615
|
inlayHintsPlugin = {
|
|
88523
88616
|
id: "inlay-hints",
|
|
88524
88617
|
capabilities: {
|
|
@@ -88685,9 +88778,13 @@ var init_semantic_tokens = __esm({
|
|
|
88685
88778
|
import { readFileSync as readFileSync7 } from "node:fs";
|
|
88686
88779
|
import { basename as basename2, dirname as dirname5, join as join4 } from "node:path";
|
|
88687
88780
|
import { fileURLToPath as fileURLToPath4, pathToFileURL as pathToFileURL6 } from "node:url";
|
|
88781
|
+
import { isDeepStrictEqual } from "node:util";
|
|
88688
88782
|
function computeCodeActions(uri, diagnostics, workspace, options = {}) {
|
|
88689
88783
|
const actions = [];
|
|
88784
|
+
const current2 = computeDiagnostics(uri, workspace);
|
|
88690
88785
|
for (const diag of diagnostics) {
|
|
88786
|
+
const fresh = current2.find((candidate) => candidate.code === diag.code && isDeepStrictEqual(candidate.range, diag.range) && isDeepStrictEqual(candidate.data, diag.data));
|
|
88787
|
+
if (!fresh && diag.code !== DiagnosticCode.NoStoryVariables) continue;
|
|
88691
88788
|
switch (diag.code) {
|
|
88692
88789
|
case DiagnosticCode.UndefinedMacro:
|
|
88693
88790
|
actions.push(...fixUndefinedMacro(uri, diag, workspace, options));
|
|
@@ -89017,6 +89114,7 @@ var init_code_actions = __esm({
|
|
|
89017
89114
|
"use strict";
|
|
89018
89115
|
import_yaml3 = __toESM(require_dist(), 1);
|
|
89019
89116
|
init_diagnostic_codes();
|
|
89117
|
+
init_diagnostics();
|
|
89020
89118
|
init_config_loader();
|
|
89021
89119
|
init_story_variables_owner();
|
|
89022
89120
|
init_macro_sources();
|