stan-language-server 0.2.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/README.md +94 -13
- package/dist/handlers/compilation/compilation.d.ts +2 -1
- package/dist/handlers/diagnostics.d.ts +1 -1
- package/dist/handlers/hover.d.ts +3 -6
- package/dist/language/diagnostics/provider.d.ts +7 -3
- package/dist/server/index.js +88 -115
- package/dist/types/common.d.ts +0 -13
- package/dist/types/index.d.ts +0 -1
- package/package.json +3 -3
- package/dist/language/diagnostics/index.d.ts +0 -2
- package/dist/language/diagnostics/linter.d.ts +0 -5
- package/dist/types/diagnostics.d.ts +0 -18
- /package/dist/__tests__/language/diagnostics/{linter.test.d.ts → provider.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -10,28 +10,80 @@ A language server for the Stan probabilistic programming language written in Typ
|
|
|
10
10
|
- **Code formatting**: Using the official Stan compiler
|
|
11
11
|
- **Include file support**: Full `#include` resolution and compilation
|
|
12
12
|
|
|
13
|
-
To install dependencies:
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
bun install
|
|
17
|
-
```
|
|
14
|
+
## Editor-specific configuration
|
|
18
15
|
|
|
19
|
-
|
|
16
|
+
### VSCode:
|
|
20
17
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
Install the [extension](https://github.com/WardBrian/vscode-stan-extension)
|
|
19
|
+
from [Marketplace](https://marketplace.visualstudio.com/items?itemName=wardbrian.vscode-stan-extension)
|
|
20
|
+
or [open-vsx](https://open-vsx.org/extension/wardbrian/vscode-stan-extension).
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
### Neovim
|
|
26
23
|
|
|
27
|
-
|
|
28
|
-
|
|
24
|
+
There are many ways to install language servers in neovim. Here is one (if you have a different or better way, consider contributing it!):
|
|
25
|
+
|
|
26
|
+
Download the latest language server executable from [GitHub](https://github.com/tomatitito/stan-language-server/tags) and put it somewhere in your PATH. Then in your `nvim` config folder add `lua/lsp/init.lua` with:
|
|
27
|
+
```lua
|
|
28
|
+
local servers = {
|
|
29
|
+
stan_ls = "lsp.stan",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
local function setup_server(name, config_module)
|
|
33
|
+
local config = require(config_module)
|
|
34
|
+
|
|
35
|
+
vim.api.nvim_create_autocmd("FileType", {
|
|
36
|
+
pattern = config.filetypes,
|
|
37
|
+
callback = function()
|
|
38
|
+
if #vim.lsp.get_clients({ bufnr = 0, name = name }) > 0 then
|
|
39
|
+
return
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
local root_dir = vim.fs.root(0, config.root_markers)
|
|
43
|
+
print(string.format("Starting %s for buffer %d with root: %s", name, vim.api.nvim_get_current_buf(),
|
|
44
|
+
root_dir or "none"))
|
|
45
|
+
|
|
46
|
+
vim.lsp.start({
|
|
47
|
+
name = name,
|
|
48
|
+
cmd = config.cmd,
|
|
49
|
+
root_dir = root_dir,
|
|
50
|
+
initialization_options = config.settings or {},
|
|
51
|
+
on_exit = function(code, signal)
|
|
52
|
+
print(string.format("%s exited with code %d, signal %d", name, code, signal))
|
|
53
|
+
end,
|
|
54
|
+
})
|
|
55
|
+
end,
|
|
56
|
+
})
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
for server_name, config_path in pairs(servers) do
|
|
60
|
+
setup_server(server_name, config_path)
|
|
61
|
+
end
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Then in `lua/lsp/stan.lua` add the following:
|
|
65
|
+
```lua
|
|
66
|
+
return {
|
|
67
|
+
cmd = { "stan-language-server", "--stdio" },
|
|
68
|
+
filetypes = { "stan" },
|
|
69
|
+
root_markers = { ".git" },
|
|
70
|
+
settings = {
|
|
71
|
+
maxLineLength = 78,
|
|
72
|
+
includePaths = {},
|
|
73
|
+
},
|
|
74
|
+
}
|
|
29
75
|
```
|
|
30
76
|
|
|
31
|
-
|
|
77
|
+
### Zed
|
|
78
|
+
|
|
79
|
+
Install the [Stan extension](https://zed.dev/extensions/stan).
|
|
32
80
|
|
|
33
81
|
### Sublime Text 4
|
|
34
82
|
|
|
83
|
+
Using [LSP for Sublime Text](https://lsp.sublimetext.io/),
|
|
84
|
+
[download the latest release](https://github.com/tomatitito/stan-language-server/releases)
|
|
85
|
+
and add the following to the settings file:
|
|
86
|
+
|
|
35
87
|
```json
|
|
36
88
|
{
|
|
37
89
|
"clients": {
|
|
@@ -50,10 +102,39 @@ bun build server.ts --compile --outfile stan-language-server
|
|
|
50
102
|
|
|
51
103
|
### Emacs (eglot)
|
|
52
104
|
|
|
53
|
-
Assuming you are using stan-ts-mode
|
|
105
|
+
Assuming you are using [stan-ts-mode](https://github.com/WardBrian/stan-ts-mode),
|
|
106
|
+
[download the latest release](https://github.com/tomatitito/stan-language-server/releases)
|
|
107
|
+
and add the following to your `init.el`:
|
|
54
108
|
|
|
55
109
|
```elisp
|
|
110
|
+
; elgot is built in to emacs 29+, but a similar config would work for lsp-mode
|
|
56
111
|
(with-eval-after-load 'eglot
|
|
57
112
|
(add-to-list 'eglot-server-programs
|
|
58
113
|
'(stan-ts-mode . ("/YOUR/PATH/TO/stan-language-server" "--stdio"))))
|
|
59
114
|
```
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
## For developers
|
|
118
|
+
|
|
119
|
+
To install dependencies:
|
|
120
|
+
|
|
121
|
+
```bash
|
|
122
|
+
bun install
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
Building a binary executable:
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
bun build:binary
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
To run unit tests:
|
|
132
|
+
```bash
|
|
133
|
+
bun test
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
To run end-to-end tests:
|
|
137
|
+
```bash
|
|
138
|
+
pip install pytest pytest-lsp
|
|
139
|
+
bun build:binary && pytest tests/
|
|
140
|
+
```
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { TextDocument } from "vscode-languageserver-textdocument";
|
|
2
2
|
import { type TextDocuments, type WorkspaceFolder, type RemoteConsole } from "vscode-languageserver";
|
|
3
|
-
import type { FileSystemReader
|
|
3
|
+
import type { FileSystemReader } from "../../types/common";
|
|
4
|
+
import { type StancReturn } from "stanc3";
|
|
4
5
|
export interface Settings {
|
|
5
6
|
maxLineLength: number;
|
|
6
7
|
includePaths: string[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Diagnostic, TextDocuments, WorkspaceFolder, type DocumentDiagnosticParams, type RemoteConsole } from "vscode-languageserver";
|
|
2
2
|
import { TextDocument } from "vscode-languageserver-textdocument";
|
|
3
|
-
import { type Settings } from "./compilation/compilation";
|
|
4
3
|
import type { FileSystemReader } from "../types";
|
|
4
|
+
import { type Settings } from "./compilation/compilation";
|
|
5
5
|
export declare function handleDiagnostics(params: DocumentDiagnosticParams, documents: TextDocuments<TextDocument>, workspaceFolders: WorkspaceFolder[], settings: Settings, logger: RemoteConsole, reader?: FileSystemReader): Promise<Diagnostic[]>;
|
package/dist/handlers/hover.d.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
|
-
import type { HoverParams, Hover
|
|
1
|
+
import type { HoverParams, Hover } from "vscode-languageserver";
|
|
2
2
|
import type { TextDocument } from "vscode-languageserver-textdocument";
|
|
3
3
|
export declare const manual_functions: string[];
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export declare const handleHover: (getMarkupLookupFn: GetMarkupLookupMapFn) => (document: TextDocument, params: HoverParams) => Promise<Hover | null>;
|
|
7
|
-
declare const _default: (document: TextDocument, params: HoverParams) => Promise<Hover | null>;
|
|
8
|
-
export default _default;
|
|
4
|
+
declare function handleHover(document: TextDocument, params: HoverParams): Promise<Hover | null>;
|
|
5
|
+
export default handleHover;
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type {
|
|
3
|
-
export declare function provideDiagnostics(compilerResult: StancReturn):
|
|
1
|
+
import type { StancReturn } from "stanc3";
|
|
2
|
+
import type { Range } from "vscode-languageserver";
|
|
3
|
+
export declare function provideDiagnostics(compilerResult: StancReturn): {
|
|
4
|
+
range: Range;
|
|
5
|
+
severity: string;
|
|
6
|
+
message: string;
|
|
7
|
+
}[];
|
package/dist/server/index.js
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
DiagnosticRefreshRequest,
|
|
5
5
|
DidChangeConfigurationNotification,
|
|
6
6
|
DocumentDiagnosticRequest,
|
|
7
|
+
MessageType,
|
|
7
8
|
TextDocumentSyncKind,
|
|
8
9
|
TextDocuments as TextDocuments3
|
|
9
10
|
} from "vscode-languageserver/node";
|
|
@@ -217,6 +218,7 @@ var setupDistributionMap = () => {
|
|
|
217
218
|
}
|
|
218
219
|
return distributionToFunctionMap;
|
|
219
220
|
};
|
|
221
|
+
var DISTRIBUTION_FUNCTION_MAP = setupDistributionMap();
|
|
220
222
|
var tildeBefore = (text, pos) => {
|
|
221
223
|
for (let i = pos - 1;i >= 0; i--) {
|
|
222
224
|
const char = text[i];
|
|
@@ -233,9 +235,8 @@ var tildeBefore = (text, pos) => {
|
|
|
233
235
|
var tryDistributionHover = (text, beginningOfWord, endOfWord) => {
|
|
234
236
|
if (!tildeBefore(text, beginningOfWord))
|
|
235
237
|
return null;
|
|
236
|
-
const distributionToFunctionMap = setupDistributionMap();
|
|
237
238
|
const dist = text.substring(beginningOfWord, endOfWord).trim();
|
|
238
|
-
const functionName =
|
|
239
|
+
const functionName = DISTRIBUTION_FUNCTION_MAP.get(dist);
|
|
239
240
|
if (!functionName)
|
|
240
241
|
return null;
|
|
241
242
|
return functionName;
|
|
@@ -325,6 +326,7 @@ var initializeFunctionMarkupMap = () => {
|
|
|
325
326
|
}
|
|
326
327
|
return markupLookupMap;
|
|
327
328
|
};
|
|
329
|
+
var FUNCTION_MARKUP_LOOKUP = initializeFunctionMarkupMap();
|
|
328
330
|
function markupContentToHover(content, document, beginningOfWord, endOfWord) {
|
|
329
331
|
return {
|
|
330
332
|
contents: content,
|
|
@@ -334,15 +336,7 @@ function markupContentToHover(content, document, beginningOfWord, endOfWord) {
|
|
|
334
336
|
}
|
|
335
337
|
};
|
|
336
338
|
}
|
|
337
|
-
|
|
338
|
-
const functionMarkupLookup = getMarkupLookupFn();
|
|
339
|
-
const currentLine = document.getText({
|
|
340
|
-
start: { line: params.position.line, character: 0 },
|
|
341
|
-
end: { line: params.position.line + 1, character: 0 }
|
|
342
|
-
}).trim();
|
|
343
|
-
if (!currentLine || !currentLine.includes("(")) {
|
|
344
|
-
return null;
|
|
345
|
-
}
|
|
339
|
+
async function handleHover(document, params) {
|
|
346
340
|
const text = document.getText();
|
|
347
341
|
const offset = document.offsetAt(params.position);
|
|
348
342
|
if (!isWordChar(text[offset])) {
|
|
@@ -355,14 +349,14 @@ var handleHover = (getMarkupLookupFn) => async (document, params) => {
|
|
|
355
349
|
const beginningOfWord = previousWordBoundary(text, offset);
|
|
356
350
|
const hoverName = provideHover(text, beginningOfWord, nextParen);
|
|
357
351
|
if (hoverName) {
|
|
358
|
-
const hoverContent =
|
|
352
|
+
const hoverContent = FUNCTION_MARKUP_LOOKUP.get(hoverName);
|
|
359
353
|
if (hoverContent !== undefined) {
|
|
360
354
|
return markupContentToHover(hoverContent, document, beginningOfWord, nextParen);
|
|
361
355
|
}
|
|
362
356
|
}
|
|
363
357
|
return null;
|
|
364
|
-
}
|
|
365
|
-
var hover_default = handleHover
|
|
358
|
+
}
|
|
359
|
+
var hover_default = handleHover;
|
|
366
360
|
|
|
367
361
|
// src/language/completion/providers/functions.ts
|
|
368
362
|
var provideFunctionCompletions = (text, position, functionSignatures) => {
|
|
@@ -457,31 +451,21 @@ function constraintToCompletionItem(constraint) {
|
|
|
457
451
|
kind: CompletionItemKind.Property
|
|
458
452
|
};
|
|
459
453
|
}
|
|
460
|
-
|
|
461
|
-
return {
|
|
462
|
-
line: position.line,
|
|
463
|
-
character: position.character
|
|
464
|
-
};
|
|
465
|
-
}
|
|
466
|
-
function getDistributionData() {
|
|
467
|
-
return dump_stan_math_distributions2().split(`
|
|
454
|
+
var DISTRIBUTION_DATA = dump_stan_math_distributions2().split(`
|
|
468
455
|
`).map((line) => line.split(":")[0]?.trim() ?? "").filter((name) => name !== "");
|
|
469
|
-
|
|
470
|
-
function getFunctionData() {
|
|
471
|
-
return dump_stan_math_signatures2().split(`
|
|
456
|
+
var FUNCTION_DATA = dump_stan_math_signatures2().split(`
|
|
472
457
|
`);
|
|
473
|
-
}
|
|
474
458
|
function handleCompletion(params, documents) {
|
|
475
459
|
const document = documents.get(params.textDocument.uri);
|
|
476
460
|
if (!document) {
|
|
477
461
|
return [];
|
|
478
462
|
}
|
|
479
463
|
const text = document.getText();
|
|
480
|
-
const position =
|
|
464
|
+
const position = params.position;
|
|
481
465
|
const keywords = provideKeywordCompletions(text, position);
|
|
482
|
-
const distributions = provideDistributionCompletions(text, position,
|
|
466
|
+
const distributions = provideDistributionCompletions(text, position, DISTRIBUTION_DATA);
|
|
483
467
|
const datatypes = provideDatatypeCompletions(text, position);
|
|
484
|
-
const functions = provideFunctionCompletions(text, position,
|
|
468
|
+
const functions = provideFunctionCompletions(text, position, FUNCTION_DATA);
|
|
485
469
|
const constraints = provideConstraintCompletions(text, position);
|
|
486
470
|
const allItems = [
|
|
487
471
|
...keywords.map(keywordToCompletionItem),
|
|
@@ -494,14 +478,18 @@ function handleCompletion(params, documents) {
|
|
|
494
478
|
}
|
|
495
479
|
// src/handlers/diagnostics.ts
|
|
496
480
|
import {
|
|
497
|
-
DiagnosticSeverity
|
|
481
|
+
DiagnosticSeverity
|
|
498
482
|
} from "vscode-languageserver";
|
|
499
483
|
|
|
500
|
-
// src/
|
|
501
|
-
|
|
502
|
-
|
|
484
|
+
// src/constants/index.ts
|
|
485
|
+
var SERVER_ID = "stan-language-server";
|
|
486
|
+
|
|
487
|
+
// src/language/diagnostics/provider.ts
|
|
488
|
+
function getRangeFromMessage(message) {
|
|
489
|
+
const msg = String(message);
|
|
490
|
+
if (!msg)
|
|
503
491
|
return;
|
|
504
|
-
const start =
|
|
492
|
+
const start = msg.matchAll(/'.*', line (\d+), column (\d+)( to)?/g);
|
|
505
493
|
const lastMatch = Array.from(start).pop();
|
|
506
494
|
if (!lastMatch || !lastMatch[1] || !lastMatch[2]) {
|
|
507
495
|
return;
|
|
@@ -511,7 +499,7 @@ function rangeFromMessage(message) {
|
|
|
511
499
|
let endLine = startLine;
|
|
512
500
|
let endColumn = startColumn;
|
|
513
501
|
if (lastMatch[3]) {
|
|
514
|
-
const end =
|
|
502
|
+
const end = msg.match(/to (line (\d+), )?column (\d+)/);
|
|
515
503
|
if (end && end[3]) {
|
|
516
504
|
if (end[1] && end[2]) {
|
|
517
505
|
endLine = parseInt(end[2]) - 1;
|
|
@@ -525,62 +513,57 @@ function rangeFromMessage(message) {
|
|
|
525
513
|
};
|
|
526
514
|
}
|
|
527
515
|
function getWarningMessage(message) {
|
|
528
|
-
|
|
516
|
+
const msg = String(message);
|
|
517
|
+
let warning = msg.replace(/Warning.*column \d+: /s, "");
|
|
529
518
|
warning = warning.replace(/\s+/gs, " ");
|
|
530
519
|
warning = warning.trim();
|
|
531
|
-
warning =
|
|
520
|
+
warning = msg.includes("included from") ? `Warning in included file:
|
|
532
521
|
` + warning : warning;
|
|
533
522
|
return warning;
|
|
534
523
|
}
|
|
535
524
|
function getErrorMessage(message) {
|
|
536
|
-
|
|
537
|
-
|
|
525
|
+
const msg = String(message);
|
|
526
|
+
let error = msg;
|
|
527
|
+
if (msg.includes(`------
|
|
538
528
|
`)) {
|
|
539
529
|
error = error.split(`------
|
|
540
530
|
`)[2] ?? error;
|
|
541
531
|
}
|
|
542
532
|
error = error.trim();
|
|
543
|
-
error =
|
|
533
|
+
error = msg.includes("included from") ? `Error in included file:
|
|
544
534
|
` + error : error;
|
|
545
535
|
error = error.includes("given information about") ? error + `
|
|
546
536
|
Try opening the included file and making the Stan language server aware of it.` : error;
|
|
547
537
|
return error;
|
|
548
538
|
}
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
539
|
+
function provideErrorMessageAndRange(message) {
|
|
540
|
+
return { range: getRangeFromMessage(message), message: getErrorMessage(message) };
|
|
541
|
+
}
|
|
542
|
+
function provideWarningMessageAndRange(message) {
|
|
543
|
+
return { range: getRangeFromMessage(message), message: getWarningMessage(message) };
|
|
544
|
+
}
|
|
554
545
|
function provideDiagnostics(compilerResult) {
|
|
555
|
-
const
|
|
556
|
-
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
range,
|
|
575
|
-
severity: 2 /* Warning */,
|
|
576
|
-
message: getWarningMessage(warning),
|
|
577
|
-
source: SERVER_ID
|
|
578
|
-
});
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
}
|
|
582
|
-
return diagnostics;
|
|
546
|
+
const errorDiagnostics = compilerResult.errors?.map((msg) => {
|
|
547
|
+
return provideErrorMessageAndRange(msg);
|
|
548
|
+
}).filter((item) => item.range !== undefined && item.message !== undefined).map(({ range, message }) => {
|
|
549
|
+
return {
|
|
550
|
+
range,
|
|
551
|
+
severity: "error",
|
|
552
|
+
message
|
|
553
|
+
};
|
|
554
|
+
}) ?? [];
|
|
555
|
+
const warningDiagnostics = compilerResult.warnings?.map((msg) => {
|
|
556
|
+
return provideWarningMessageAndRange(msg);
|
|
557
|
+
}).filter((item) => item.range !== undefined).map(({ range, message }) => {
|
|
558
|
+
return {
|
|
559
|
+
range,
|
|
560
|
+
severity: "warning",
|
|
561
|
+
message
|
|
562
|
+
};
|
|
563
|
+
}) ?? [];
|
|
564
|
+
return [...errorDiagnostics, ...warningDiagnostics];
|
|
583
565
|
}
|
|
566
|
+
|
|
584
567
|
// src/handlers/compilation/includes.ts
|
|
585
568
|
import { join } from "path";
|
|
586
569
|
import { URI, Utils } from "vscode-uri";
|
|
@@ -682,48 +665,30 @@ async function handleCompilation(document, documentManager, workspaceFolders, se
|
|
|
682
665
|
}
|
|
683
666
|
|
|
684
667
|
// src/handlers/diagnostics.ts
|
|
685
|
-
function stanDiagnosticToLspDiagnostic(stanDiag) {
|
|
686
|
-
return {
|
|
687
|
-
range: domainRangeToLspRange(stanDiag.range),
|
|
688
|
-
severity: domainSeverityToLspSeverity(stanDiag.severity),
|
|
689
|
-
message: stanDiag.message,
|
|
690
|
-
source: stanDiag.source ?? SERVER_ID
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
function domainRangeToLspRange(domainRange) {
|
|
694
|
-
return {
|
|
695
|
-
start: {
|
|
696
|
-
line: domainRange.start.line,
|
|
697
|
-
character: domainRange.start.character
|
|
698
|
-
},
|
|
699
|
-
end: {
|
|
700
|
-
line: domainRange.end.line,
|
|
701
|
-
character: domainRange.end.character
|
|
702
|
-
}
|
|
703
|
-
};
|
|
704
|
-
}
|
|
705
|
-
function domainSeverityToLspSeverity(domainSeverity) {
|
|
706
|
-
switch (domainSeverity) {
|
|
707
|
-
case 1:
|
|
708
|
-
return DiagnosticSeverity2.Error;
|
|
709
|
-
case 2:
|
|
710
|
-
return DiagnosticSeverity2.Warning;
|
|
711
|
-
case 3:
|
|
712
|
-
return DiagnosticSeverity2.Information;
|
|
713
|
-
case 4:
|
|
714
|
-
return DiagnosticSeverity2.Hint;
|
|
715
|
-
default:
|
|
716
|
-
return DiagnosticSeverity2.Error;
|
|
717
|
-
}
|
|
718
|
-
}
|
|
719
668
|
async function handleDiagnostics(params, documents, workspaceFolders, settings, logger, reader) {
|
|
720
669
|
const document = documents.get(params.textDocument.uri);
|
|
721
670
|
if (!document) {
|
|
722
671
|
return [];
|
|
723
672
|
}
|
|
724
673
|
const compilerResult = await handleCompilation(document, documents, workspaceFolders, settings, logger, reader);
|
|
725
|
-
const
|
|
726
|
-
|
|
674
|
+
const diagnostics = provideDiagnostics(compilerResult).map((diagnostic) => {
|
|
675
|
+
if (diagnostic.severity === "error") {
|
|
676
|
+
return {
|
|
677
|
+
range: diagnostic.range,
|
|
678
|
+
severity: DiagnosticSeverity.Error,
|
|
679
|
+
message: diagnostic.message,
|
|
680
|
+
source: SERVER_ID
|
|
681
|
+
};
|
|
682
|
+
} else if (diagnostic.severity === "warning") {
|
|
683
|
+
return {
|
|
684
|
+
range: diagnostic.range,
|
|
685
|
+
severity: DiagnosticSeverity.Warning,
|
|
686
|
+
message: diagnostic.message,
|
|
687
|
+
source: SERVER_ID
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
}).filter((diagnostic) => diagnostic !== undefined);
|
|
691
|
+
return diagnostics;
|
|
727
692
|
}
|
|
728
693
|
// src/handlers/formatting.ts
|
|
729
694
|
async function handleFormatting(params, documents, workspaceFolders, settings, logger, reader) {
|
|
@@ -755,11 +720,13 @@ async function handleFormatting(params, documents, workspaceFolders, settings, l
|
|
|
755
720
|
var startLanguageServer = (connection, reader) => {
|
|
756
721
|
let hasConfigurationCapability = false;
|
|
757
722
|
let hasWorkspaceFolderCapability = false;
|
|
723
|
+
let hasDynamicConfigurationRequestCapability = false;
|
|
758
724
|
connection.onInitialize((params) => {
|
|
759
725
|
connection.console.info("Initializing Stan language server...");
|
|
760
726
|
let capabilities = params.capabilities;
|
|
761
|
-
hasConfigurationCapability =
|
|
762
|
-
|
|
727
|
+
hasConfigurationCapability = Boolean(capabilities.workspace?.configuration);
|
|
728
|
+
hasDynamicConfigurationRequestCapability = Boolean(capabilities.workspace?.configuration && capabilities.workspace?.didChangeConfiguration?.dynamicRegistration);
|
|
729
|
+
hasWorkspaceFolderCapability = Boolean(capabilities.workspace?.workspaceFolders);
|
|
763
730
|
return {
|
|
764
731
|
capabilities: {
|
|
765
732
|
textDocumentSync: TextDocumentSyncKind.Incremental,
|
|
@@ -768,6 +735,7 @@ var startLanguageServer = (connection, reader) => {
|
|
|
768
735
|
resolveProvider: false
|
|
769
736
|
},
|
|
770
737
|
documentFormattingProvider: true,
|
|
738
|
+
documentRangeFormattingProvider: false,
|
|
771
739
|
workspace: {
|
|
772
740
|
workspaceFolders: {
|
|
773
741
|
supported: hasWorkspaceFolderCapability
|
|
@@ -781,9 +749,10 @@ var startLanguageServer = (connection, reader) => {
|
|
|
781
749
|
}
|
|
782
750
|
};
|
|
783
751
|
});
|
|
784
|
-
connection.onInitialized(() => {
|
|
785
|
-
if (
|
|
786
|
-
connection.client.register(DidChangeConfigurationNotification.type);
|
|
752
|
+
connection.onInitialized(async () => {
|
|
753
|
+
if (hasDynamicConfigurationRequestCapability) {
|
|
754
|
+
await connection.client.register(DidChangeConfigurationNotification.type);
|
|
755
|
+
connection.console.info("Registered for didChangeConfiguration");
|
|
787
756
|
}
|
|
788
757
|
connection.console.info("Stan language server is initialized!");
|
|
789
758
|
});
|
|
@@ -793,7 +762,7 @@ var startLanguageServer = (connection, reader) => {
|
|
|
793
762
|
let globalSettings = defaultSettings;
|
|
794
763
|
let documentSettings = new Map;
|
|
795
764
|
connection.onDidChangeConfiguration((change) => {
|
|
796
|
-
if (
|
|
765
|
+
if (hasDynamicConfigurationRequestCapability) {
|
|
797
766
|
documentSettings.clear();
|
|
798
767
|
} else {
|
|
799
768
|
const incomingSettings = change.settings[SERVER_ID] || {};
|
|
@@ -846,6 +815,10 @@ var startLanguageServer = (connection, reader) => {
|
|
|
846
815
|
for (const error of formattingResult.errors) {
|
|
847
816
|
connection.console.error(error);
|
|
848
817
|
}
|
|
818
|
+
connection.sendNotification("window/showMessage", {
|
|
819
|
+
type: MessageType.Error,
|
|
820
|
+
message: "Formatting failed due to compile errors. See diagnostics for details."
|
|
821
|
+
});
|
|
849
822
|
return [];
|
|
850
823
|
}
|
|
851
824
|
});
|
package/dist/types/common.d.ts
CHANGED
|
@@ -3,17 +3,4 @@ export interface Position {
|
|
|
3
3
|
line: number;
|
|
4
4
|
character: number;
|
|
5
5
|
}
|
|
6
|
-
type StancSuccess = {
|
|
7
|
-
errors: undefined;
|
|
8
|
-
result: string;
|
|
9
|
-
warnings?: string[];
|
|
10
|
-
};
|
|
11
|
-
type StancFailure = {
|
|
12
|
-
errors: string[];
|
|
13
|
-
result: undefined;
|
|
14
|
-
warnings?: string[];
|
|
15
|
-
};
|
|
16
|
-
export type StancReturn = StancSuccess | StancFailure;
|
|
17
|
-
export type StancFunction = (filename: string, code: string, options: string[], includes?: Record<string, string>) => StancReturn;
|
|
18
6
|
export type FileSystemReader = (filename: Filename) => Promise<FileContent>;
|
|
19
|
-
export {};
|
package/dist/types/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stan-language-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Language Server Protocol implementation for the Stan probabilistic programming language",
|
|
5
5
|
"main": "dist/server/index.js",
|
|
6
6
|
"module": "src/server/index.ts",
|
|
@@ -64,11 +64,11 @@
|
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
66
|
"@types/bun": "latest",
|
|
67
|
-
"@types/node": "24.
|
|
67
|
+
"@types/node": "24.7.0",
|
|
68
68
|
"@typescript-eslint/eslint-plugin": "^8.0.0",
|
|
69
69
|
"@typescript-eslint/parser": "^8.0.0",
|
|
70
70
|
"eslint": "^9.0.0",
|
|
71
|
-
"typescript": "5.9.
|
|
71
|
+
"typescript": "5.9.3"
|
|
72
72
|
},
|
|
73
73
|
"dependencies": {
|
|
74
74
|
"stanc3": "^2.37.0",
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
import type { Range } from "../../types/diagnostics";
|
|
2
|
-
declare function rangeFromMessage(message: string): Range | undefined;
|
|
3
|
-
declare function getWarningMessage(message: string): string;
|
|
4
|
-
declare function getErrorMessage(message: string): string;
|
|
5
|
-
export { rangeFromMessage, getWarningMessage, getErrorMessage };
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Position } from "./common";
|
|
2
|
-
export type { Position };
|
|
3
|
-
export interface Range {
|
|
4
|
-
start: Position;
|
|
5
|
-
end: Position;
|
|
6
|
-
}
|
|
7
|
-
export declare enum DiagnosticSeverity {
|
|
8
|
-
Error = 1,
|
|
9
|
-
Warning = 2,
|
|
10
|
-
Information = 3,
|
|
11
|
-
Hint = 4
|
|
12
|
-
}
|
|
13
|
-
export interface StanDiagnostic {
|
|
14
|
-
range: Range;
|
|
15
|
-
severity: DiagnosticSeverity;
|
|
16
|
-
message: string;
|
|
17
|
-
source?: string;
|
|
18
|
-
}
|
|
File without changes
|