@rohal12/spindle-lsp 0.1.0 → 0.3.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 +332 -5
- package/dist/bin.js.map +4 -4
- package/package.json +1 -1
package/dist/bin.js
CHANGED
|
@@ -2397,8 +2397,11 @@ function parseConfig(content, format) {
|
|
|
2397
2397
|
return { macros: {} };
|
|
2398
2398
|
}
|
|
2399
2399
|
const obj = raw;
|
|
2400
|
+
const spindle0 = obj["spindle-0"];
|
|
2401
|
+
const source = spindle0 && typeof spindle0 === "object" ? spindle0 : obj;
|
|
2400
2402
|
return {
|
|
2401
|
-
macros: typeof
|
|
2403
|
+
macros: typeof source.macros === "object" && source.macros !== null ? source.macros : {},
|
|
2404
|
+
enums: typeof source.enums === "object" && source.enums !== null ? source.enums : void 0
|
|
2402
2405
|
};
|
|
2403
2406
|
}
|
|
2404
2407
|
function findConfigFile(workspaceRoot) {
|
|
@@ -2426,7 +2429,10 @@ var init_config_loader = __esm({
|
|
|
2426
2429
|
CONFIG_FILENAMES = [
|
|
2427
2430
|
"spindle.config.yaml",
|
|
2428
2431
|
"spindle.config.yml",
|
|
2429
|
-
"spindle.config.json"
|
|
2432
|
+
"spindle.config.json",
|
|
2433
|
+
"t3lt.twee-config.yaml",
|
|
2434
|
+
"t3lt.twee-config.yml",
|
|
2435
|
+
"t3lt.twee-config.json"
|
|
2430
2436
|
];
|
|
2431
2437
|
EMPTY_CONFIG = { macros: {} };
|
|
2432
2438
|
}
|
|
@@ -2685,7 +2691,26 @@ async function runCheck(args2) {
|
|
|
2685
2691
|
}
|
|
2686
2692
|
return 0;
|
|
2687
2693
|
}
|
|
2688
|
-
|
|
2694
|
+
let configRoot;
|
|
2695
|
+
if (options.configPath) {
|
|
2696
|
+
configRoot = resolve(cwd, options.configPath, "..");
|
|
2697
|
+
} else {
|
|
2698
|
+
const dirs = uniqueFiles.map((f) => resolve(f, ".."));
|
|
2699
|
+
configRoot = dirs.reduce((a, b) => {
|
|
2700
|
+
while (!b.startsWith(a)) a = resolve(a, "..");
|
|
2701
|
+
return a;
|
|
2702
|
+
});
|
|
2703
|
+
let search = configRoot;
|
|
2704
|
+
for (let i = 0; i < 10; i++) {
|
|
2705
|
+
if (findConfigFile(search)) {
|
|
2706
|
+
configRoot = search;
|
|
2707
|
+
break;
|
|
2708
|
+
}
|
|
2709
|
+
const parent = resolve(search, "..");
|
|
2710
|
+
if (parent === search) break;
|
|
2711
|
+
search = parent;
|
|
2712
|
+
}
|
|
2713
|
+
}
|
|
2689
2714
|
const projectConfig = loadConfigFromDisk(configRoot);
|
|
2690
2715
|
const workspace = new WorkspaceModel();
|
|
2691
2716
|
const fileContents = /* @__PURE__ */ new Map();
|
|
@@ -4453,6 +4478,299 @@ var init_code_actions = __esm({
|
|
|
4453
4478
|
}
|
|
4454
4479
|
});
|
|
4455
4480
|
|
|
4481
|
+
// src/plugins/document-symbol.ts
|
|
4482
|
+
import { SymbolKind } from "vscode-languageserver";
|
|
4483
|
+
function computeDocumentSymbols(uri, workspace) {
|
|
4484
|
+
const text = workspace.documents.getText(uri);
|
|
4485
|
+
if (text === void 0) return [];
|
|
4486
|
+
const passages = workspace.passages.getPassagesInDocument(uri);
|
|
4487
|
+
if (passages.length === 0) return [];
|
|
4488
|
+
const storyVarsPassage = workspace.passages.getStoryVariables();
|
|
4489
|
+
const lines = text.split("\n");
|
|
4490
|
+
const symbols = [];
|
|
4491
|
+
for (const passage of passages) {
|
|
4492
|
+
const headerLine = passage.range.start.line;
|
|
4493
|
+
const selectionRange = {
|
|
4494
|
+
start: { line: headerLine, character: 0 },
|
|
4495
|
+
end: { line: headerLine, character: lines[headerLine]?.length ?? 0 }
|
|
4496
|
+
};
|
|
4497
|
+
const passageSymbol = {
|
|
4498
|
+
name: passage.name,
|
|
4499
|
+
kind: SymbolKind.Namespace,
|
|
4500
|
+
range: passage.range,
|
|
4501
|
+
selectionRange,
|
|
4502
|
+
children: []
|
|
4503
|
+
};
|
|
4504
|
+
if (passage.tags?.includes("widget")) {
|
|
4505
|
+
const contentStart = passage.range.start.line + 1;
|
|
4506
|
+
const contentEnd = passage.range.end.line + 1;
|
|
4507
|
+
const widgetDefRegex2 = /\{widget\s+"([^"]+)"[^}]*\}/gi;
|
|
4508
|
+
for (let i = contentStart; i < contentEnd && i < lines.length; i++) {
|
|
4509
|
+
widgetDefRegex2.lastIndex = 0;
|
|
4510
|
+
let match;
|
|
4511
|
+
while ((match = widgetDefRegex2.exec(lines[i])) !== null) {
|
|
4512
|
+
const charStart = match.index;
|
|
4513
|
+
const charEnd = charStart + match[0].length;
|
|
4514
|
+
passageSymbol.children.push({
|
|
4515
|
+
name: match[1],
|
|
4516
|
+
kind: SymbolKind.Function,
|
|
4517
|
+
range: {
|
|
4518
|
+
start: { line: i, character: charStart },
|
|
4519
|
+
end: { line: i, character: charEnd }
|
|
4520
|
+
},
|
|
4521
|
+
selectionRange: {
|
|
4522
|
+
start: { line: i, character: charStart },
|
|
4523
|
+
end: { line: i, character: charEnd }
|
|
4524
|
+
}
|
|
4525
|
+
});
|
|
4526
|
+
}
|
|
4527
|
+
}
|
|
4528
|
+
}
|
|
4529
|
+
if (storyVarsPassage && storyVarsPassage.uri === uri && passage.name === "StoryVariables") {
|
|
4530
|
+
const contentStart = passage.range.start.line + 1;
|
|
4531
|
+
const contentEnd = passage.range.end.line + 1;
|
|
4532
|
+
for (let i = contentStart; i < contentEnd && i < lines.length; i++) {
|
|
4533
|
+
const varMatch = lines[i].match(/^\$([A-Za-z_$][\w$]*)\s*=/);
|
|
4534
|
+
if (varMatch) {
|
|
4535
|
+
const charEnd = varMatch[0].length;
|
|
4536
|
+
passageSymbol.children.push({
|
|
4537
|
+
name: "$" + varMatch[1],
|
|
4538
|
+
kind: SymbolKind.Variable,
|
|
4539
|
+
range: {
|
|
4540
|
+
start: { line: i, character: 0 },
|
|
4541
|
+
end: { line: i, character: lines[i].length }
|
|
4542
|
+
},
|
|
4543
|
+
selectionRange: {
|
|
4544
|
+
start: { line: i, character: 0 },
|
|
4545
|
+
end: { line: i, character: charEnd }
|
|
4546
|
+
}
|
|
4547
|
+
});
|
|
4548
|
+
}
|
|
4549
|
+
}
|
|
4550
|
+
}
|
|
4551
|
+
symbols.push(passageSymbol);
|
|
4552
|
+
}
|
|
4553
|
+
return symbols;
|
|
4554
|
+
}
|
|
4555
|
+
function toLspRange7(r) {
|
|
4556
|
+
return {
|
|
4557
|
+
start: { line: r.start.line, character: r.start.character },
|
|
4558
|
+
end: { line: r.end.line, character: r.end.character }
|
|
4559
|
+
};
|
|
4560
|
+
}
|
|
4561
|
+
function toLspDocumentSymbol(sym) {
|
|
4562
|
+
return {
|
|
4563
|
+
name: sym.name,
|
|
4564
|
+
kind: sym.kind,
|
|
4565
|
+
range: toLspRange7(sym.range),
|
|
4566
|
+
selectionRange: toLspRange7(sym.selectionRange),
|
|
4567
|
+
children: sym.children?.map(toLspDocumentSymbol)
|
|
4568
|
+
};
|
|
4569
|
+
}
|
|
4570
|
+
var documentSymbolPlugin;
|
|
4571
|
+
var init_document_symbol = __esm({
|
|
4572
|
+
"src/plugins/document-symbol.ts"() {
|
|
4573
|
+
"use strict";
|
|
4574
|
+
documentSymbolPlugin = {
|
|
4575
|
+
id: "document-symbol",
|
|
4576
|
+
capabilities: {
|
|
4577
|
+
documentSymbolProvider: true
|
|
4578
|
+
},
|
|
4579
|
+
initialize(ctx) {
|
|
4580
|
+
ctx.connection.onDocumentSymbol((params) => {
|
|
4581
|
+
const symbols = computeDocumentSymbols(params.textDocument.uri, ctx.workspace);
|
|
4582
|
+
return symbols.map(toLspDocumentSymbol);
|
|
4583
|
+
});
|
|
4584
|
+
}
|
|
4585
|
+
};
|
|
4586
|
+
}
|
|
4587
|
+
});
|
|
4588
|
+
|
|
4589
|
+
// src/plugins/workspace-symbol.ts
|
|
4590
|
+
import { SymbolKind as SymbolKind2 } from "vscode-languageserver";
|
|
4591
|
+
function searchWorkspaceSymbols(query, workspace) {
|
|
4592
|
+
const lowerQuery = query.toLowerCase();
|
|
4593
|
+
const results = [];
|
|
4594
|
+
for (const passage of workspace.passages.getAllPassages()) {
|
|
4595
|
+
if (lowerQuery && !passage.name.toLowerCase().includes(lowerQuery)) continue;
|
|
4596
|
+
results.push({
|
|
4597
|
+
name: passage.name,
|
|
4598
|
+
kind: SymbolKind2.Namespace,
|
|
4599
|
+
uri: passage.uri,
|
|
4600
|
+
range: passage.range
|
|
4601
|
+
});
|
|
4602
|
+
}
|
|
4603
|
+
for (const widget of workspace.widgets.getAllWidgets()) {
|
|
4604
|
+
if (lowerQuery && !widget.name.toLowerCase().includes(lowerQuery)) continue;
|
|
4605
|
+
results.push({
|
|
4606
|
+
name: widget.name,
|
|
4607
|
+
kind: SymbolKind2.Function,
|
|
4608
|
+
uri: widget.uri,
|
|
4609
|
+
range: widget.range
|
|
4610
|
+
});
|
|
4611
|
+
}
|
|
4612
|
+
for (const [name, decl] of workspace.variables.getDeclared()) {
|
|
4613
|
+
const displayName = "$" + name;
|
|
4614
|
+
if (lowerQuery && !displayName.toLowerCase().includes(lowerQuery)) continue;
|
|
4615
|
+
results.push({
|
|
4616
|
+
name: displayName,
|
|
4617
|
+
kind: SymbolKind2.Variable,
|
|
4618
|
+
uri: decl.declarationUri ?? "",
|
|
4619
|
+
range: decl.declarationRange ?? { start: { line: 0, character: 0 }, end: { line: 0, character: 0 } }
|
|
4620
|
+
});
|
|
4621
|
+
}
|
|
4622
|
+
return results;
|
|
4623
|
+
}
|
|
4624
|
+
function toLspRange8(r) {
|
|
4625
|
+
return {
|
|
4626
|
+
start: { line: r.start.line, character: r.start.character },
|
|
4627
|
+
end: { line: r.end.line, character: r.end.character }
|
|
4628
|
+
};
|
|
4629
|
+
}
|
|
4630
|
+
var workspaceSymbolPlugin;
|
|
4631
|
+
var init_workspace_symbol = __esm({
|
|
4632
|
+
"src/plugins/workspace-symbol.ts"() {
|
|
4633
|
+
"use strict";
|
|
4634
|
+
workspaceSymbolPlugin = {
|
|
4635
|
+
id: "workspace-symbol",
|
|
4636
|
+
capabilities: {
|
|
4637
|
+
workspaceSymbolProvider: true
|
|
4638
|
+
},
|
|
4639
|
+
initialize(ctx) {
|
|
4640
|
+
ctx.connection.onWorkspaceSymbol((params) => {
|
|
4641
|
+
const symbols = searchWorkspaceSymbols(params.query, ctx.workspace);
|
|
4642
|
+
return symbols.map((s) => ({
|
|
4643
|
+
name: s.name,
|
|
4644
|
+
kind: s.kind,
|
|
4645
|
+
location: {
|
|
4646
|
+
uri: s.uri,
|
|
4647
|
+
range: toLspRange8(s.range)
|
|
4648
|
+
}
|
|
4649
|
+
}));
|
|
4650
|
+
});
|
|
4651
|
+
}
|
|
4652
|
+
};
|
|
4653
|
+
}
|
|
4654
|
+
});
|
|
4655
|
+
|
|
4656
|
+
// src/plugins/folding-range.ts
|
|
4657
|
+
import { FoldingRangeKind } from "vscode-languageserver";
|
|
4658
|
+
function computeFoldingRanges(uri, workspace) {
|
|
4659
|
+
const text = workspace.documents.getText(uri);
|
|
4660
|
+
if (text === void 0) return [];
|
|
4661
|
+
const ranges = [];
|
|
4662
|
+
const passages = workspace.passages.getPassagesInDocument(uri);
|
|
4663
|
+
for (const passage of passages) {
|
|
4664
|
+
const startLine = passage.range.start.line;
|
|
4665
|
+
const endLine = passage.range.end.line;
|
|
4666
|
+
if (endLine > startLine) {
|
|
4667
|
+
ranges.push({
|
|
4668
|
+
startLine,
|
|
4669
|
+
endLine,
|
|
4670
|
+
kind: "region"
|
|
4671
|
+
});
|
|
4672
|
+
}
|
|
4673
|
+
}
|
|
4674
|
+
const macros = parseMacros(text);
|
|
4675
|
+
pairMacros(macros, (name) => workspace.macros.isBlock(name));
|
|
4676
|
+
for (const macro of macros) {
|
|
4677
|
+
if (macro.open && macro.pair !== -1) {
|
|
4678
|
+
const closingMacro = macros[macro.pair];
|
|
4679
|
+
const startLine = macro.range.start.line;
|
|
4680
|
+
const endLine = closingMacro.range.start.line;
|
|
4681
|
+
if (endLine > startLine) {
|
|
4682
|
+
ranges.push({
|
|
4683
|
+
startLine,
|
|
4684
|
+
endLine
|
|
4685
|
+
});
|
|
4686
|
+
}
|
|
4687
|
+
}
|
|
4688
|
+
}
|
|
4689
|
+
return ranges;
|
|
4690
|
+
}
|
|
4691
|
+
var foldingRangePlugin;
|
|
4692
|
+
var init_folding_range = __esm({
|
|
4693
|
+
"src/plugins/folding-range.ts"() {
|
|
4694
|
+
"use strict";
|
|
4695
|
+
init_macro_parser();
|
|
4696
|
+
foldingRangePlugin = {
|
|
4697
|
+
id: "folding-range",
|
|
4698
|
+
capabilities: {
|
|
4699
|
+
foldingRangeProvider: true
|
|
4700
|
+
},
|
|
4701
|
+
initialize(ctx) {
|
|
4702
|
+
ctx.connection.onFoldingRanges((params) => {
|
|
4703
|
+
const ranges = computeFoldingRanges(params.textDocument.uri, ctx.workspace);
|
|
4704
|
+
return ranges.map((r) => ({
|
|
4705
|
+
startLine: r.startLine,
|
|
4706
|
+
endLine: r.endLine,
|
|
4707
|
+
kind: r.kind === "region" ? FoldingRangeKind.Region : void 0
|
|
4708
|
+
}));
|
|
4709
|
+
});
|
|
4710
|
+
}
|
|
4711
|
+
};
|
|
4712
|
+
}
|
|
4713
|
+
});
|
|
4714
|
+
|
|
4715
|
+
// src/plugins/document-link.ts
|
|
4716
|
+
function computeDocumentLinks(uri, workspace) {
|
|
4717
|
+
const text = workspace.documents.getText(uri);
|
|
4718
|
+
if (text === void 0) return [];
|
|
4719
|
+
const passages = workspace.passages.getPassagesInDocument(uri);
|
|
4720
|
+
if (passages.length === 0) return [];
|
|
4721
|
+
const links = [];
|
|
4722
|
+
for (const passage of passages) {
|
|
4723
|
+
const contentStartLine = passage.range.start.line + 1;
|
|
4724
|
+
const contentEndLine = passage.range.end.line + 1;
|
|
4725
|
+
const lines = text.split("\n");
|
|
4726
|
+
const contentLines = lines.slice(contentStartLine, contentEndLine);
|
|
4727
|
+
const content = contentLines.join("\n");
|
|
4728
|
+
const passageLinks = parseLinks(content, contentStartLine);
|
|
4729
|
+
for (const ref of passageLinks) {
|
|
4730
|
+
const targetPassage = workspace.passages.getPassage(ref.name);
|
|
4731
|
+
let target;
|
|
4732
|
+
if (targetPassage) {
|
|
4733
|
+
target = `${targetPassage.uri}#L${targetPassage.range.start.line + 1}`;
|
|
4734
|
+
}
|
|
4735
|
+
links.push({
|
|
4736
|
+
range: ref.range,
|
|
4737
|
+
target
|
|
4738
|
+
});
|
|
4739
|
+
}
|
|
4740
|
+
}
|
|
4741
|
+
return links;
|
|
4742
|
+
}
|
|
4743
|
+
function toLspRange9(r) {
|
|
4744
|
+
return {
|
|
4745
|
+
start: { line: r.start.line, character: r.start.character },
|
|
4746
|
+
end: { line: r.end.line, character: r.end.character }
|
|
4747
|
+
};
|
|
4748
|
+
}
|
|
4749
|
+
var documentLinkPlugin;
|
|
4750
|
+
var init_document_link = __esm({
|
|
4751
|
+
"src/plugins/document-link.ts"() {
|
|
4752
|
+
"use strict";
|
|
4753
|
+
init_link_parser();
|
|
4754
|
+
documentLinkPlugin = {
|
|
4755
|
+
id: "document-link",
|
|
4756
|
+
capabilities: {
|
|
4757
|
+
documentLinkProvider: {
|
|
4758
|
+
resolveProvider: false
|
|
4759
|
+
}
|
|
4760
|
+
},
|
|
4761
|
+
initialize(ctx) {
|
|
4762
|
+
ctx.connection.onDocumentLinks((params) => {
|
|
4763
|
+
const links = computeDocumentLinks(params.textDocument.uri, ctx.workspace);
|
|
4764
|
+
return links.map((l) => ({
|
|
4765
|
+
range: toLspRange9(l.range),
|
|
4766
|
+
target: l.target
|
|
4767
|
+
}));
|
|
4768
|
+
});
|
|
4769
|
+
}
|
|
4770
|
+
};
|
|
4771
|
+
}
|
|
4772
|
+
});
|
|
4773
|
+
|
|
4456
4774
|
// src/plugins/index.ts
|
|
4457
4775
|
var allPlugins;
|
|
4458
4776
|
var init_plugins = __esm({
|
|
@@ -4470,6 +4788,10 @@ var init_plugins = __esm({
|
|
|
4470
4788
|
init_semantic_tokens();
|
|
4471
4789
|
init_code_actions();
|
|
4472
4790
|
init_format();
|
|
4791
|
+
init_document_symbol();
|
|
4792
|
+
init_workspace_symbol();
|
|
4793
|
+
init_folding_range();
|
|
4794
|
+
init_document_link();
|
|
4473
4795
|
allPlugins = [
|
|
4474
4796
|
diagnosticsPlugin,
|
|
4475
4797
|
completionsPlugin,
|
|
@@ -4482,7 +4804,11 @@ var init_plugins = __esm({
|
|
|
4482
4804
|
inlayHintsPlugin,
|
|
4483
4805
|
semanticTokensPlugin,
|
|
4484
4806
|
codeActionsPlugin,
|
|
4485
|
-
formatPlugin
|
|
4807
|
+
formatPlugin,
|
|
4808
|
+
documentSymbolPlugin,
|
|
4809
|
+
workspaceSymbolPlugin,
|
|
4810
|
+
foldingRangePlugin,
|
|
4811
|
+
documentLinkPlugin
|
|
4486
4812
|
];
|
|
4487
4813
|
}
|
|
4488
4814
|
});
|
|
@@ -4546,7 +4872,8 @@ function startServer(_args) {
|
|
|
4546
4872
|
{ globPattern: "**/*.twee" },
|
|
4547
4873
|
{ globPattern: "**/*.js" },
|
|
4548
4874
|
{ globPattern: "**/*.ts" },
|
|
4549
|
-
{ globPattern: "**/spindle.config.*" }
|
|
4875
|
+
{ globPattern: "**/spindle.config.*" },
|
|
4876
|
+
{ globPattern: "**/*twee-config.*" }
|
|
4550
4877
|
]
|
|
4551
4878
|
});
|
|
4552
4879
|
if (workspace) {
|