@rohal12/spindle-lsp 0.15.17 → 0.15.19

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 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.17";
58
+ VERSION = false ? pkg.version : "0.15.19";
59
59
  }
60
60
  });
61
61
 
@@ -34510,6 +34510,8 @@ var init_diagnostic_codes = __esm({
34510
34510
  UnsupportedSpindleVersion: "SP001",
34511
34511
  /** A fatal Twee source error reported by the public compiler parser. */
34512
34512
  TweeSyntaxError: "SP002",
34513
+ /** StoryData explicitly selects an entry passage absent from the story. */
34514
+ MissingEntryPassage: "SP004",
34513
34515
  /** `unknown-macro`: a macro that is none of the built-in, configured or defined ones. */
34514
34516
  UndefinedMacro: "SP100",
34515
34517
  /** `unclosed-block`, `mismatched-closer`, `stray-closer` of a macro. */
@@ -34560,6 +34562,7 @@ var init_diagnostic_codes = __esm({
34560
34562
  severityMap = {
34561
34563
  [DiagnosticCode.UnsupportedSpindleVersion]: "warning",
34562
34564
  [DiagnosticCode.TweeSyntaxError]: "error",
34565
+ [DiagnosticCode.MissingEntryPassage]: "error",
34563
34566
  [DiagnosticCode.UndefinedMacro]: "warning",
34564
34567
  [DiagnosticCode.MalformedContainer]: "error",
34565
34568
  [DiagnosticCode.MalformedElement]: "error",
@@ -34857,6 +34860,7 @@ function computeDiagnostics(uri, workspace, options) {
34857
34860
  }
34858
34861
  };
34859
34862
  const story = storyReport(workspace);
34863
+ diagnostics.push(...story.metadata.get(doc) ?? []);
34860
34864
  const effective = new Set(workspace.passages.getEffectivePassages());
34861
34865
  for (const passage of doc.passages) {
34862
34866
  if (!effective.has(passage.passage)) continue;
@@ -34962,6 +34966,7 @@ function buildReport(documents, workspace) {
34962
34966
  }
34963
34967
  return {
34964
34968
  documents,
34969
+ metadata: storyDataDiagnostics(documents, workspace),
34965
34970
  passages,
34966
34971
  macros,
34967
34972
  markup,
@@ -34973,6 +34978,22 @@ function buildReport(documents, workspace) {
34973
34978
  variableDiagnostics: /* @__PURE__ */ new Map()
34974
34979
  };
34975
34980
  }
34981
+ function storyDataDiagnostics(documents, workspace) {
34982
+ const found = /* @__PURE__ */ new Map();
34983
+ const effective = workspace.passages.getEffectivePassage("StoryData");
34984
+ for (const doc of documents) {
34985
+ const diagnostics = [];
34986
+ for (const passage of doc.passages) {
34987
+ if (passage.passage !== effective) continue;
34988
+ const data2 = readStoryData(passage.content);
34989
+ if (data2.start && !workspace.passages.getEffectivePassage(data2.start)) {
34990
+ diagnostics.push(makeDiag(passage.passage.nameRange, DiagnosticCode.MissingEntryPassage, `Starting passage "${data2.start}" not found.`));
34991
+ }
34992
+ }
34993
+ found.set(doc, diagnostics);
34994
+ }
34995
+ return found;
34996
+ }
34976
34997
  function declarationsOf(workspace, name) {
34977
34998
  const passage = name === "StoryVariables" ? workspace.passages.getStoryVariables() : workspace.passages.getStoryTransients();
34978
34999
  if (!passage || !isRuntimePassage(passage)) return void 0;
@@ -35145,15 +35166,17 @@ function parentDiagnostics(passage, token, ancestors, workspace) {
35145
35166
  return [makeDiag(range2, DiagnosticCode.InvalidChildren, `Invalid: {${token.name}} can only be inside {${parentList}}`)];
35146
35167
  }
35147
35168
  function childDiagnostics(passage, node, token, workspace) {
35148
- const constraints = workspace.getEffectiveMacro(token.name)?.children;
35169
+ const macro = workspace.getEffectiveMacro(token.name);
35170
+ const constraints = macro?.children;
35149
35171
  if (!constraints || constraints.length === 0 || !node.body?.close) return [];
35150
35172
  const direct = [...node.body.children];
35151
35173
  for (const branch of node.body.branches) direct.push({ token: branch.tag, start: branch.tag.start, end: branch.tag.end }, ...branch.children);
35174
+ const consumesOptions = macro?.source === "builtin" && ["listbox", "cycle"].includes(token.name.toLowerCase());
35152
35175
  const counts = /* @__PURE__ */ Object.create(null);
35153
35176
  for (const child of direct) {
35154
35177
  if (child.token.type !== "macro" || child.token.isClose) continue;
35155
35178
  const key = child.token.name.toLowerCase();
35156
- if (workspace.getEffectiveMacro(key)) counts[key] = (counts[key] ?? 0) + 1;
35179
+ if (consumesOptions && key === "option" || workspace.getEffectiveMacro(key)) counts[key] = (counts[key] ?? 0) + 1;
35157
35180
  }
35158
35181
  const diagnostics = [];
35159
35182
  const range2 = passage.range(token.start, token.end);
@@ -35180,7 +35203,7 @@ function temporaryRefRegex(name) {
35180
35203
  return new RegExp(`(?<![.\\w$@%])_(${name.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")})(?![\\w$])`, "g");
35181
35204
  }
35182
35205
  function maskLiterals(code) {
35183
- const chars = Array.from(code, (ch) => ch === "\n" ? "\n" : " ");
35206
+ const chars = code.split("").map((ch) => ch === "\n" ? "\n" : " ");
35184
35207
  const copy = (text3, index) => {
35185
35208
  for (let i2 = 0; i2 < text3.length; i2++) chars[index + i2] = text3[i2];
35186
35209
  };
@@ -35250,13 +35273,15 @@ function loopDiagnostics(passage, token, ancestors, workspace) {
35250
35273
  const close = loop?.node.body?.close;
35251
35274
  if (!loop || !close) return [];
35252
35275
  const targets = macro === "computed" ? computedTemporaryTarget(token.rawArgs) : setTemporaryTargets(token.rawArgs);
35276
+ const view = sourceView(passage, token.argsStart, token.argsEnd);
35277
+ const argsIndex = viewIndex(view, token.argsStart);
35253
35278
  const bodyStart = loop.node.token.end;
35254
35279
  const diagnostics = [];
35255
35280
  for (const target of targets) {
35256
35281
  if (!isReadInBody(passage, bodyStart, close.start, target.name, token.start, token.end)) continue;
35257
- const start = token.argsStart + target.offset;
35282
+ const start = argsIndex + target.offset;
35258
35283
  diagnostics.push(makeDiag(
35259
- passage.range(start, start + 1 + target.name.length),
35284
+ passage.range(pieceOffset(view, start), pieceOffset(view, start + 1 + target.name.length)),
35260
35285
  DiagnosticCode.TemporaryAssignedInLoop,
35261
35286
  `Temporary '_${target.name}' is assigned inside {${loop.name}} and read in the loop body. Temporaries are shared by every iteration, so all iterations end up seeing the value assigned by the last one. Use the iteration-local '@${target.name}' instead, or assign it once before the loop if the value does not depend on the iteration.`
35262
35287
  ));
@@ -35452,6 +35477,7 @@ var init_diagnostics = __esm({
35452
35477
  init_link_parser();
35453
35478
  init_passage_parser();
35454
35479
  init_story_variables_owner();
35480
+ init_story_data();
35455
35481
  init_macro_sources();
35456
35482
  init_spindle_version();
35457
35483
  tweeReports = /* @__PURE__ */ new WeakMap();