@rohal12/spindle-lsp 0.7.1 → 0.8.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/dist/bin.js +90 -11
- package/dist/bin.js.map +2 -2
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -448,8 +448,10 @@ var init_variable_tracker = __esm({
|
|
|
448
448
|
VariableTracker = class {
|
|
449
449
|
declared = /* @__PURE__ */ new Map();
|
|
450
450
|
_hasStoryVariables = false;
|
|
451
|
+
_nullDeclarations = [];
|
|
451
452
|
declaredTransient = /* @__PURE__ */ new Map();
|
|
452
453
|
_hasStoryTransients = false;
|
|
454
|
+
_nullTransientDeclarations = [];
|
|
453
455
|
/** Per-URI list of variable usages. */
|
|
454
456
|
usagesByUri = /* @__PURE__ */ new Map();
|
|
455
457
|
/** Per-URI list of transient variable usages. */
|
|
@@ -458,17 +460,32 @@ var init_variable_tracker = __esm({
|
|
|
458
460
|
* Parse the StoryVariables passage content for declarations.
|
|
459
461
|
* Each line like `$name = value` becomes a declaration.
|
|
460
462
|
*/
|
|
461
|
-
parseStoryVariables(content) {
|
|
463
|
+
parseStoryVariables(content, contentStartLine = 0) {
|
|
462
464
|
this.declared.clear();
|
|
463
465
|
this._hasStoryVariables = true;
|
|
466
|
+
this._nullDeclarations = [];
|
|
464
467
|
const lines = content.split("\n");
|
|
465
|
-
for (
|
|
466
|
-
const trimmed =
|
|
468
|
+
for (let i = 0; i < lines.length; i++) {
|
|
469
|
+
const trimmed = lines[i].trim();
|
|
467
470
|
if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("<!--")) continue;
|
|
468
471
|
const match = /^\$([A-Za-z_$][\w$]*)\s*=\s*(.*)$/.exec(trimmed);
|
|
469
472
|
if (!match) continue;
|
|
470
473
|
const name = match[1];
|
|
471
474
|
const expr = match[2].trim();
|
|
475
|
+
if (expr === "null") {
|
|
476
|
+
const charIdx = lines[i].indexOf("null", lines[i].indexOf("="));
|
|
477
|
+
const absLine = contentStartLine + i;
|
|
478
|
+
this._nullDeclarations.push({
|
|
479
|
+
name,
|
|
480
|
+
sigil: "$",
|
|
481
|
+
range: {
|
|
482
|
+
start: { line: absLine, character: charIdx },
|
|
483
|
+
end: { line: absLine, character: charIdx + 4 }
|
|
484
|
+
}
|
|
485
|
+
});
|
|
486
|
+
this.declared.set(name, { name, sigil: "$" });
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
472
489
|
const decl = { name, sigil: "$" };
|
|
473
490
|
if (expr.startsWith("{")) {
|
|
474
491
|
const fieldRegex = /(\w+)\s*:/g;
|
|
@@ -488,17 +505,32 @@ var init_variable_tracker = __esm({
|
|
|
488
505
|
* Parse the StoryTransients passage content for declarations.
|
|
489
506
|
* Each line like `%name = value` becomes a declaration.
|
|
490
507
|
*/
|
|
491
|
-
parseStoryTransients(content) {
|
|
508
|
+
parseStoryTransients(content, contentStartLine = 0) {
|
|
492
509
|
this.declaredTransient.clear();
|
|
493
510
|
this._hasStoryTransients = true;
|
|
511
|
+
this._nullTransientDeclarations = [];
|
|
494
512
|
const lines = content.split("\n");
|
|
495
|
-
for (
|
|
496
|
-
const trimmed =
|
|
513
|
+
for (let i = 0; i < lines.length; i++) {
|
|
514
|
+
const trimmed = lines[i].trim();
|
|
497
515
|
if (!trimmed || trimmed.startsWith("//") || trimmed.startsWith("<!--")) continue;
|
|
498
516
|
const match = /^%([A-Za-z_$][\w$]*)\s*=\s*(.*)$/.exec(trimmed);
|
|
499
517
|
if (!match) continue;
|
|
500
518
|
const name = match[1];
|
|
501
519
|
const expr = match[2].trim();
|
|
520
|
+
if (expr === "null") {
|
|
521
|
+
const charIdx = lines[i].indexOf("null", lines[i].indexOf("="));
|
|
522
|
+
const absLine = contentStartLine + i;
|
|
523
|
+
this._nullTransientDeclarations.push({
|
|
524
|
+
name,
|
|
525
|
+
sigil: "%",
|
|
526
|
+
range: {
|
|
527
|
+
start: { line: absLine, character: charIdx },
|
|
528
|
+
end: { line: absLine, character: charIdx + 4 }
|
|
529
|
+
}
|
|
530
|
+
});
|
|
531
|
+
this.declaredTransient.set(name, { name, sigil: "%" });
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
502
534
|
const decl = { name, sigil: "%" };
|
|
503
535
|
if (expr.startsWith("{")) {
|
|
504
536
|
const fieldRegex = /(\w+)\s*:/g;
|
|
@@ -660,6 +692,14 @@ var init_variable_tracker = __esm({
|
|
|
660
692
|
hasStoryTransients() {
|
|
661
693
|
return this._hasStoryTransients;
|
|
662
694
|
}
|
|
695
|
+
/** Get variables declared with null values in StoryVariables. */
|
|
696
|
+
getNullDeclarations() {
|
|
697
|
+
return this._nullDeclarations;
|
|
698
|
+
}
|
|
699
|
+
/** Get transient variables declared with null values in StoryTransients. */
|
|
700
|
+
getNullTransientDeclarations() {
|
|
701
|
+
return this._nullTransientDeclarations;
|
|
702
|
+
}
|
|
663
703
|
};
|
|
664
704
|
}
|
|
665
705
|
});
|
|
@@ -1238,7 +1278,7 @@ var init_workspace_model = __esm({
|
|
|
1238
1278
|
}
|
|
1239
1279
|
}
|
|
1240
1280
|
const content = lines.slice(contentStart, contentEnd).join("\n");
|
|
1241
|
-
this.variables.parseStoryVariables(content);
|
|
1281
|
+
this.variables.parseStoryVariables(content, contentStart);
|
|
1242
1282
|
}
|
|
1243
1283
|
}
|
|
1244
1284
|
const storyTransients = this.passages.getStoryTransients();
|
|
@@ -1255,7 +1295,7 @@ var init_workspace_model = __esm({
|
|
|
1255
1295
|
}
|
|
1256
1296
|
}
|
|
1257
1297
|
const content = lines.slice(contentStart, contentEnd).join("\n");
|
|
1258
|
-
this.variables.parseStoryTransients(content);
|
|
1298
|
+
this.variables.parseStoryTransients(content, contentStart);
|
|
1259
1299
|
}
|
|
1260
1300
|
}
|
|
1261
1301
|
for (const uri of this.documents.getUris()) {
|
|
@@ -1306,6 +1346,7 @@ var init_diagnostic_codes = __esm({
|
|
|
1306
1346
|
UndeclaredField: "SP201",
|
|
1307
1347
|
NoStoryVariables: "SP202",
|
|
1308
1348
|
UndeclaredTransient: "SP203",
|
|
1349
|
+
NullVariableValue: "SP204",
|
|
1309
1350
|
BrokenPassageLink: "SP300",
|
|
1310
1351
|
WidgetArgCountMismatch: "SP301",
|
|
1311
1352
|
DeadEndPassage: "SP400",
|
|
@@ -1324,10 +1365,11 @@ var init_diagnostic_codes = __esm({
|
|
|
1324
1365
|
SP112: "warning",
|
|
1325
1366
|
SP114: "error",
|
|
1326
1367
|
SP115: "error",
|
|
1327
|
-
SP200: "
|
|
1368
|
+
SP200: "error",
|
|
1328
1369
|
SP201: "warning",
|
|
1329
1370
|
SP202: "info",
|
|
1330
1371
|
SP203: "warning",
|
|
1372
|
+
SP204: "error",
|
|
1331
1373
|
SP300: "warning",
|
|
1332
1374
|
SP301: "warning",
|
|
1333
1375
|
SP400: "hint",
|
|
@@ -2434,6 +2476,16 @@ function validateVariables(uri, workspace, diagnostics) {
|
|
|
2434
2476
|
`Variable '$${u.name}' is not declared in StoryVariables`
|
|
2435
2477
|
));
|
|
2436
2478
|
}
|
|
2479
|
+
const storyVars = workspace.passages.getStoryVariables();
|
|
2480
|
+
if (storyVars && storyVars.uri === uri) {
|
|
2481
|
+
for (const nd of workspace.variables.getNullDeclarations()) {
|
|
2482
|
+
diagnostics.push(makeDiag(
|
|
2483
|
+
nd.range,
|
|
2484
|
+
DiagnosticCode.NullVariableValue,
|
|
2485
|
+
`Variable '$${nd.name}' is set to null. Spindle does not support null \u2014 use a valid default (number, string, boolean, array, or object).`
|
|
2486
|
+
));
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2437
2489
|
}
|
|
2438
2490
|
if (workspace.variables.hasStoryTransients()) {
|
|
2439
2491
|
const undeclaredTransient = workspace.variables.getUndeclaredTransient(uri);
|
|
@@ -2444,6 +2496,16 @@ function validateVariables(uri, workspace, diagnostics) {
|
|
|
2444
2496
|
`Transient variable '%${u.name}' is not declared in StoryTransients`
|
|
2445
2497
|
));
|
|
2446
2498
|
}
|
|
2499
|
+
const storyTransients = workspace.passages.getStoryTransients();
|
|
2500
|
+
if (storyTransients && storyTransients.uri === uri) {
|
|
2501
|
+
for (const nd of workspace.variables.getNullTransientDeclarations()) {
|
|
2502
|
+
diagnostics.push(makeDiag(
|
|
2503
|
+
nd.range,
|
|
2504
|
+
DiagnosticCode.NullVariableValue,
|
|
2505
|
+
`Transient variable '%${nd.name}' is set to null. Spindle does not support null \u2014 use a valid default (number, string, boolean, array, or object).`
|
|
2506
|
+
));
|
|
2507
|
+
}
|
|
2508
|
+
}
|
|
2447
2509
|
}
|
|
2448
2510
|
}
|
|
2449
2511
|
function validateLinks(text, passages, passageNames, diagnostics) {
|
|
@@ -5387,6 +5449,11 @@ function computeCodeActions(uri, diagnostics, workspace) {
|
|
|
5387
5449
|
if (action) actions.push(action);
|
|
5388
5450
|
break;
|
|
5389
5451
|
}
|
|
5452
|
+
case DiagnosticCode.NullVariableValue: {
|
|
5453
|
+
const action = fixNullVariableValue(uri, diag);
|
|
5454
|
+
if (action) actions.push(action);
|
|
5455
|
+
break;
|
|
5456
|
+
}
|
|
5390
5457
|
}
|
|
5391
5458
|
}
|
|
5392
5459
|
return actions;
|
|
@@ -5443,7 +5510,7 @@ function fixUndeclaredVariable(diag, workspace) {
|
|
|
5443
5510
|
start: { line: insertLine, character: 0 },
|
|
5444
5511
|
end: { line: insertLine, character: 0 }
|
|
5445
5512
|
},
|
|
5446
|
-
newText: `$${varName} =
|
|
5513
|
+
newText: `$${varName} = 0
|
|
5447
5514
|
`
|
|
5448
5515
|
}]
|
|
5449
5516
|
};
|
|
@@ -5498,11 +5565,23 @@ function fixUndeclaredTransient(diag, workspace) {
|
|
|
5498
5565
|
start: { line: insertLine, character: 0 },
|
|
5499
5566
|
end: { line: insertLine, character: 0 }
|
|
5500
5567
|
},
|
|
5501
|
-
newText: `%${varName} =
|
|
5568
|
+
newText: `%${varName} = 0
|
|
5502
5569
|
`
|
|
5503
5570
|
}]
|
|
5504
5571
|
};
|
|
5505
5572
|
}
|
|
5573
|
+
function fixNullVariableValue(uri, diag) {
|
|
5574
|
+
return {
|
|
5575
|
+
title: "Replace null with 0",
|
|
5576
|
+
kind: "quickfix",
|
|
5577
|
+
diagnosticCodes: [DiagnosticCode.NullVariableValue],
|
|
5578
|
+
edits: [{
|
|
5579
|
+
uri,
|
|
5580
|
+
range: diag.range,
|
|
5581
|
+
newText: "0"
|
|
5582
|
+
}]
|
|
5583
|
+
};
|
|
5584
|
+
}
|
|
5506
5585
|
function toLspRange6(r) {
|
|
5507
5586
|
return {
|
|
5508
5587
|
start: { line: r.start.line, character: r.start.character },
|