stan-language-server 0.3.0 → 0.3.2
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 +2 -0
- package/dist/__tests__/e2e/completion.test.d.ts +1 -0
- package/dist/__tests__/e2e/diagnostics.test.d.ts +1 -0
- package/dist/__tests__/e2e/formatting.test.d.ts +1 -0
- package/dist/__tests__/e2e/hover.test.d.ts +1 -0
- package/dist/__tests__/e2e/lsp-client.d.ts +50 -0
- package/dist/__tests__/e2e/server_lifecycle.test.d.ts +1 -0
- package/dist/handlers/compilation/includes.d.ts +2 -2
- package/dist/server/index.js +16 -11
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import type { CompletionItem, CompletionList, DocumentDiagnosticReport, Hover, InitializeResult, LSPAny, TextEdit } from "vscode-languageserver-protocol";
|
|
2
|
+
export interface LSPMessage {
|
|
3
|
+
jsonrpc: "2.0";
|
|
4
|
+
id?: number | string;
|
|
5
|
+
method?: string;
|
|
6
|
+
params?: any;
|
|
7
|
+
result?: any;
|
|
8
|
+
error?: {
|
|
9
|
+
code: number;
|
|
10
|
+
message: string;
|
|
11
|
+
data?: any;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export declare class LSPTestClient {
|
|
15
|
+
private server;
|
|
16
|
+
private messageId;
|
|
17
|
+
private pendingRequests;
|
|
18
|
+
private buffer;
|
|
19
|
+
private currentSettings;
|
|
20
|
+
private workspaceUri;
|
|
21
|
+
private registrationResolve;
|
|
22
|
+
private openDocumentUris;
|
|
23
|
+
serverMessages: LSPMessage[];
|
|
24
|
+
numRefreshRequest: number;
|
|
25
|
+
start(): Promise<void>;
|
|
26
|
+
stop(): Promise<void>;
|
|
27
|
+
private handleServerMessage;
|
|
28
|
+
private handleMessage;
|
|
29
|
+
private handleDiagnosticRefresh;
|
|
30
|
+
private handleConfigurationRequest;
|
|
31
|
+
private handleWorkspaceFoldersRequest;
|
|
32
|
+
private handleRegisterCapability;
|
|
33
|
+
private sendMessage;
|
|
34
|
+
private sendRequest;
|
|
35
|
+
private sendNotification;
|
|
36
|
+
initialize(workspaceUri?: string, dynamicRegistration?: boolean): Promise<InitializeResult>;
|
|
37
|
+
initialized(): Promise<void>;
|
|
38
|
+
waitForRegistration(timeout?: number): Promise<void>;
|
|
39
|
+
shutdown(): Promise<void>;
|
|
40
|
+
exit(): Promise<void>;
|
|
41
|
+
didOpen(uri: string, languageId: string, text: string): Promise<void>;
|
|
42
|
+
didChange(uri: string, text: string, version: number): Promise<void>;
|
|
43
|
+
didClose(uri: string): Promise<void>;
|
|
44
|
+
closeAll(): Promise<void>;
|
|
45
|
+
didChangeConfiguration(settings?: LSPAny): Promise<void>;
|
|
46
|
+
completion(uri: string, line: number, character: number): Promise<CompletionList | CompletionItem[]>;
|
|
47
|
+
formatting(uri: string): Promise<TextEdit[]>;
|
|
48
|
+
hover(uri: string, line: number, character: number): Promise<Hover | null>;
|
|
49
|
+
diagnostics(uri: string): Promise<DocumentDiagnosticReport>;
|
|
50
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TextDocuments, WorkspaceFolder, type RemoteConsole } from "vscode-languageserver";
|
|
2
|
-
import
|
|
2
|
+
import { TextDocument } from "vscode-languageserver-textdocument";
|
|
3
3
|
import type { FileSystemReader } from "../../types";
|
|
4
4
|
export type Filename = string;
|
|
5
5
|
export type FileContent = string;
|
|
@@ -8,4 +8,4 @@ export type FilePathError = {
|
|
|
8
8
|
};
|
|
9
9
|
export declare function getFilenames(fileContent: string): Filename[];
|
|
10
10
|
export declare function isFilePathError(value: unknown): value is FilePathError;
|
|
11
|
-
export declare function handleIncludes(document: TextDocument, documentManager: TextDocuments<TextDocument>, workspaceFolders: WorkspaceFolder[], includePaths: string[], logger: RemoteConsole, reader?: FileSystemReader): Promise<Record<Filename, FileContent>>;
|
|
11
|
+
export declare function handleIncludes(document: TextDocument, documentManager: TextDocuments<TextDocument>, workspaceFolders: WorkspaceFolder[], includePaths: string[], logger: RemoteConsole, reader?: FileSystemReader, alreadyIncluded?: Set<Filename>): Promise<Record<Filename, FileContent>>;
|
package/dist/server/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/server/index.ts
|
|
2
|
-
import { TextDocument } from "vscode-languageserver-textdocument";
|
|
2
|
+
import { TextDocument as TextDocument2 } from "vscode-languageserver-textdocument";
|
|
3
3
|
import {
|
|
4
4
|
DiagnosticRefreshRequest,
|
|
5
5
|
DidChangeConfigurationNotification,
|
|
@@ -566,6 +566,7 @@ function provideDiagnostics(compilerResult) {
|
|
|
566
566
|
|
|
567
567
|
// src/handlers/compilation/includes.ts
|
|
568
568
|
import { join } from "path";
|
|
569
|
+
import { TextDocument } from "vscode-languageserver-textdocument";
|
|
569
570
|
import { URI, Utils } from "vscode-uri";
|
|
570
571
|
function getFilenames(fileContent) {
|
|
571
572
|
const includePattern = /#include\s*[<"]?([^>"\s]*)[>"]?/g;
|
|
@@ -576,13 +577,16 @@ function getFilenames(fileContent) {
|
|
|
576
577
|
function isFilePathError(value) {
|
|
577
578
|
return typeof value === "object" && value !== null && "msg" in value;
|
|
578
579
|
}
|
|
579
|
-
async function handleIncludes(document, documentManager, workspaceFolders, includePaths, logger, reader) {
|
|
580
|
+
async function handleIncludes(document, documentManager, workspaceFolders, includePaths, logger, reader, alreadyIncluded = new Set) {
|
|
580
581
|
try {
|
|
581
582
|
const includeFilenames = getFilenames(document.getText());
|
|
582
583
|
if (includeFilenames.length === 0) {
|
|
583
584
|
return {};
|
|
584
585
|
}
|
|
585
586
|
const allResults = await Promise.all(includeFilenames.map(async (filename) => {
|
|
587
|
+
if (alreadyIncluded.has(filename)) {
|
|
588
|
+
return [filename, { msg: `File already included: ${filename}` }];
|
|
589
|
+
}
|
|
586
590
|
try {
|
|
587
591
|
const content = await readIncludedFile(document, documentManager, workspaceFolders, includePaths, filename, reader);
|
|
588
592
|
return [filename, content];
|
|
@@ -591,7 +595,10 @@ async function handleIncludes(document, documentManager, workspaceFolders, inclu
|
|
|
591
595
|
}
|
|
592
596
|
}));
|
|
593
597
|
const validResults = allResults.filter(([_, content]) => !isFilePathError(content));
|
|
594
|
-
|
|
598
|
+
const currentlyIncluded = new Set(validResults.map(([filename, _]) => filename)).union(alreadyIncluded);
|
|
599
|
+
const recursiveIncludes = await Promise.all(validResults.map(async ([_, content]) => await handleIncludes(content, documentManager, workspaceFolders, includePaths, logger, reader, currentlyIncluded)));
|
|
600
|
+
const results = validResults.map(([filename, contents]) => [filename, contents.getText()]).concat(recursiveIncludes.map(Object.entries).flat());
|
|
601
|
+
return Object.fromEntries(results);
|
|
595
602
|
} catch (error) {
|
|
596
603
|
logger.warn(`Resolving included files failed: ${error}`);
|
|
597
604
|
return Promise.resolve({});
|
|
@@ -604,10 +611,7 @@ var readIncludedFile = async (document, documentManager, workspaceFolders, inclu
|
|
|
604
611
|
return Promise.resolve(includedFileContent);
|
|
605
612
|
}
|
|
606
613
|
if (reader) {
|
|
607
|
-
includedFileContent = await readIncludedFileFromFileSystem(filename, [
|
|
608
|
-
currentDir.fsPath,
|
|
609
|
-
...includePaths
|
|
610
|
-
], reader);
|
|
614
|
+
includedFileContent = await readIncludedFileFromFileSystem(filename, [currentDir.fsPath, ...includePaths], reader);
|
|
611
615
|
}
|
|
612
616
|
if (!isFilePathError(includedFileContent)) {
|
|
613
617
|
return Promise.resolve(includedFileContent);
|
|
@@ -628,13 +632,14 @@ var readIncludedFileFromWorkspace = (documentManager, workspaceFolders, filename
|
|
|
628
632
|
if (!includedFile) {
|
|
629
633
|
return Promise.resolve({ msg: `File not found: ${filename}` });
|
|
630
634
|
}
|
|
631
|
-
return Promise.resolve(includedFile
|
|
635
|
+
return Promise.resolve(includedFile);
|
|
632
636
|
};
|
|
633
637
|
var readIncludedFileFromFileSystem = async (filename, dirs, fileSystemReader) => {
|
|
634
638
|
for (const currentDir of dirs) {
|
|
635
639
|
try {
|
|
636
640
|
const localPath = join(currentDir, filename);
|
|
637
|
-
|
|
641
|
+
const content = await fileSystemReader(localPath);
|
|
642
|
+
return TextDocument.create(URI.file(localPath).toString(), "stan", 0, content);
|
|
638
643
|
} catch (error) {}
|
|
639
644
|
}
|
|
640
645
|
return Promise.resolve({ msg: `File not found: ${filename}` });
|
|
@@ -754,7 +759,7 @@ var startLanguageServer = (connection, reader) => {
|
|
|
754
759
|
await connection.client.register(DidChangeConfigurationNotification.type);
|
|
755
760
|
connection.console.info("Registered for didChangeConfiguration");
|
|
756
761
|
}
|
|
757
|
-
connection.console.info("Stan language server is initialized
|
|
762
|
+
connection.console.info("Stan language server is initialized");
|
|
758
763
|
});
|
|
759
764
|
connection.onExit(() => {
|
|
760
765
|
connection.console.info("Stan language server is exiting...");
|
|
@@ -786,7 +791,7 @@ var startLanguageServer = (connection, reader) => {
|
|
|
786
791
|
documentSettings.set(resource, docSettings);
|
|
787
792
|
return docSettings;
|
|
788
793
|
};
|
|
789
|
-
const documents = new TextDocuments3(
|
|
794
|
+
const documents = new TextDocuments3(TextDocument2);
|
|
790
795
|
connection.onCompletion((params) => {
|
|
791
796
|
return handleCompletion(params, documents);
|
|
792
797
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "stan-language-server",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.2",
|
|
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",
|
|
@@ -60,19 +60,22 @@
|
|
|
60
60
|
"typecheck": "tsc --noEmit",
|
|
61
61
|
"check": "bun run lint && bun run typecheck",
|
|
62
62
|
"test": "bun test",
|
|
63
|
+
"test:unit": "bun test src/__tests__/handlers src/__tests__/language",
|
|
64
|
+
"test:e2e": "bun run build:binary && bun test src/__tests__/e2e/",
|
|
65
|
+
"test:e2e:ci": "bun test src/__tests__/e2e/",
|
|
63
66
|
"dev": "bun run src/server/cli.ts"
|
|
64
67
|
},
|
|
65
68
|
"devDependencies": {
|
|
66
69
|
"@types/bun": "latest",
|
|
67
|
-
"@types/node": "
|
|
68
|
-
"@typescript-eslint/eslint-plugin": "
|
|
69
|
-
"@typescript-eslint/parser": "
|
|
70
|
-
"eslint": "
|
|
70
|
+
"@types/node": "25.0.8",
|
|
71
|
+
"@typescript-eslint/eslint-plugin": "8.53.0",
|
|
72
|
+
"@typescript-eslint/parser": "8.53.0",
|
|
73
|
+
"eslint": "9.39.2",
|
|
71
74
|
"typescript": "5.9.3"
|
|
72
75
|
},
|
|
73
76
|
"dependencies": {
|
|
74
|
-
"stanc3": "
|
|
75
|
-
"trie-search": "2.2.
|
|
77
|
+
"stanc3": "2.38.0",
|
|
78
|
+
"trie-search": "2.2.1",
|
|
76
79
|
"vscode-languageserver": "9.0.1",
|
|
77
80
|
"vscode-languageserver-textdocument": "1.0.12",
|
|
78
81
|
"vscode-uri": "3.1.0"
|