stan-language-server 0.4.6 → 0.4.8

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.
@@ -5,6 +5,8 @@ import { type StancReturn } from "stanc3";
5
5
  export interface Settings {
6
6
  maxLineLength: number;
7
7
  includePaths: string[];
8
+ warnPedantic: boolean;
8
9
  }
9
10
  export declare const defaultSettings: Settings;
10
- export declare function handleCompilation(document: TextDocument, documentManager: TextDocuments<TextDocument>, workspaceFolders: WorkspaceFolder[], settings: Settings, logger: RemoteConsole, reader?: FileSystemReader): Promise<StancReturn>;
11
+ export type Purpose = "formatting" | "linting";
12
+ export declare function handleCompilation(document: TextDocument, documentManager: TextDocuments<TextDocument>, workspaceFolders: WorkspaceFolder[], settings: Settings, purpose: Purpose, logger: RemoteConsole, reader?: FileSystemReader): Promise<StancReturn>;
@@ -1,4 +1,4 @@
1
1
  import { type CompletionParams, TextDocuments, CompletionItem } from "vscode-languageserver";
2
2
  import { TextDocument, type Position } from "vscode-languageserver-textdocument";
3
3
  export declare const getTextUpToCursor: (text: string, position: Position) => string;
4
- export declare function handleCompletion(params: CompletionParams, documents: TextDocuments<TextDocument>, supportsSnippets: boolean): CompletionItem[];
4
+ export declare function handleCompletion({ position, textDocument }: CompletionParams, documents: TextDocuments<TextDocument>, supportsSnippets: boolean): CompletionItem[];
@@ -6,7 +6,8 @@ import {
6
6
  DocumentDiagnosticRequest,
7
7
  MessageType,
8
8
  TextDocumentSyncKind,
9
- TextDocuments as TextDocuments3
9
+ TextDocuments as TextDocuments3,
10
+ CompletionItemKind as CompletionItemKind8
10
11
  } from "vscode-languageserver/node";
11
12
 
12
13
  // src/handlers/completion.ts
@@ -38,6 +39,8 @@ var DATATYPES = [
38
39
  "int",
39
40
  "real",
40
41
  "complex",
42
+ "array",
43
+ "tuple",
41
44
  "vector",
42
45
  "row_vector",
43
46
  "matrix",
@@ -69,17 +72,12 @@ var KEYWORDS = [
69
72
  "for",
70
73
  "in",
71
74
  "while",
72
- "repeat",
73
- "until",
74
75
  "if",
75
76
  "then",
76
77
  "else",
77
78
  "break",
78
79
  "continue",
79
80
  "return",
80
- "true",
81
- "false",
82
- "target",
83
81
  "functions",
84
82
  "data",
85
83
  "transformed",
@@ -91,21 +89,11 @@ var KEYWORDS = [
91
89
  "reject",
92
90
  "fatal_error",
93
91
  "profile",
94
- "get_lp",
95
- "struct",
96
- "typedef",
97
- "export",
98
- "auto",
99
- "extern",
100
- "var",
101
- "static",
102
- "array",
103
92
  "lower",
104
93
  "upper",
105
94
  "offset",
106
95
  "multiplier",
107
- "tuple",
108
- "truncate",
96
+ "target",
109
97
  "jacobian"
110
98
  ].map(keywordToCompletionItem);
111
99
 
@@ -475,6 +463,12 @@ var getFunctions = () => {
475
463
  var FUNCTIONS = getFunctions();
476
464
 
477
465
  // src/handlers/completion.ts
466
+ var addTextEdit = (item, position, prefix_length) => {
467
+ const start = { line: position.line, character: position.character - prefix_length };
468
+ const end = position;
469
+ const textEdit = { range: { start, end }, newText: item.insertText || item.label };
470
+ return { ...item, textEdit };
471
+ };
478
472
  var COMPLETION_TRIE = new TrieSearch("label", {
479
473
  splitOnRegEx: /[\s_]/g,
480
474
  min: 0
@@ -486,7 +480,7 @@ COMPLETION_TRIE.addAll([
486
480
  ...FUNCTIONS,
487
481
  ...SNIPPETS
488
482
  ]);
489
- var searchWords = (textUpToCursor, supportsSnippets) => {
483
+ var searchWords = (position, textUpToCursor, supportsSnippets) => {
490
484
  const match = textUpToCursor.match(/(?:^|\s)([\w_]+)$/);
491
485
  if (match) {
492
486
  const word = match[1] || "";
@@ -494,7 +488,7 @@ var searchWords = (textUpToCursor, supportsSnippets) => {
494
488
  if (!supportsSnippets) {
495
489
  return completionProposals.filter((item) => item.kind !== CompletionItemKind7.Snippet);
496
490
  }
497
- return completionProposals;
491
+ return completionProposals.map((item) => addTextEdit(item, position, word.length));
498
492
  }
499
493
  return [];
500
494
  };
@@ -503,7 +497,7 @@ var DISTRIBUTION_TRIE = new TrieSearch("label", {
503
497
  min: 0
504
498
  });
505
499
  DISTRIBUTION_TRIE.addAll(DISTRIBUTIONS);
506
- var searchDistributions = (textUpToCursor) => {
500
+ var searchDistributions = (position, textUpToCursor) => {
507
501
  const match = textUpToCursor.match(/.*~\s*([\w_]*)$/);
508
502
  if (match) {
509
503
  const distName = match[1] || "";
@@ -513,7 +507,7 @@ var searchDistributions = (textUpToCursor) => {
513
507
  } else {
514
508
  completionProposals = DISTRIBUTION_TRIE.search(distName);
515
509
  }
516
- return completionProposals;
510
+ return completionProposals.map((item) => addTextEdit(item, position, distName.length));
517
511
  }
518
512
  return [];
519
513
  };
@@ -523,15 +517,15 @@ var getTextUpToCursor = (text, position) => {
523
517
  const currentLine = lines[position.line] || "";
524
518
  return currentLine.substring(0, position.character);
525
519
  };
526
- function handleCompletion(params, documents, supportsSnippets) {
527
- const document = documents.get(params.textDocument.uri);
528
- if (!document) {
520
+ function handleCompletion({ position, textDocument }, documents, supportsSnippets) {
521
+ const document = documents.get(textDocument.uri);
522
+ if (!document || !document.languageId.startsWith("stan")) {
529
523
  return [];
530
524
  }
531
- const textUpToCursor = getTextUpToCursor(document.getText(), params.position);
525
+ const textUpToCursor = getTextUpToCursor(document.getText(), position);
532
526
  return [
533
- ...searchDistributions(textUpToCursor),
534
- ...searchWords(textUpToCursor, supportsSnippets)
527
+ ...searchDistributions(position, textUpToCursor),
528
+ ...searchWords(position, textUpToCursor, supportsSnippets)
535
529
  ];
536
530
  }
537
531
  // src/handlers/diagnostics.ts
@@ -572,7 +566,7 @@ function getRangeFromMessage(message) {
572
566
  }
573
567
  function getWarningMessage(message) {
574
568
  const msg = String(message);
575
- let warning = msg.replace(/Warning.*column \d+: /s, "");
569
+ let warning = msg.replace(/Warning.*column \d+:/s, "");
576
570
  warning = warning.replace(/\s+/gs, " ");
577
571
  warning = warning.trim();
578
572
  warning = msg.includes("included from") ? `Warning in included file:
@@ -708,32 +702,32 @@ import { URI as URI2 } from "vscode-uri";
708
702
  import { stanc } from "stanc3";
709
703
  var defaultSettings = {
710
704
  maxLineLength: 78,
711
- includePaths: []
705
+ includePaths: [],
706
+ warnPedantic: false
712
707
  };
713
- async function handleCompilation(document, documentManager, workspaceFolders, settings, logger, reader) {
708
+ async function handleCompilation(document, documentManager, workspaceFolders, settings, purpose, logger, reader) {
714
709
  const filename = URI2.parse(document.uri).fsPath;
715
710
  const code = document.getText();
716
711
  const includes = await handleIncludes(document, documentManager, workspaceFolders, settings.includePaths, logger, reader);
717
- const stanc_args = [
718
- "auto-format",
719
- `filename-in-msg=${filename}`,
720
- `max-line-length=${settings.maxLineLength}`,
721
- "canonicalze=deprecations",
722
- "allow-undefined"
723
- ];
712
+ const stanc_args = [`filename-in-msg=${filename}`, "allow-undefined"];
724
713
  if (filename.endsWith(".stanfunctions")) {
725
714
  stanc_args.push("functions-only");
726
715
  }
716
+ if (purpose === "formatting") {
717
+ stanc_args.push("auto-format", `max-line-length=${settings.maxLineLength}`, "canonicalze=deprecations");
718
+ } else if (settings.warnPedantic) {
719
+ stanc_args.push("warn-pedantic");
720
+ }
727
721
  return Promise.resolve(stanc(filename, code, stanc_args, includes));
728
722
  }
729
723
 
730
724
  // src/handlers/diagnostics.ts
731
725
  async function handleDiagnostics(params, documents, workspaceFolders, settings, logger, reader) {
732
726
  const document = documents.get(params.textDocument.uri);
733
- if (!document) {
727
+ if (!document || !document.languageId.startsWith("stan")) {
734
728
  return [];
735
729
  }
736
- const compilerResult = await handleCompilation(document, documents, workspaceFolders, settings, logger, reader);
730
+ const compilerResult = await handleCompilation(document, documents, workspaceFolders, settings, "linting", logger, reader);
737
731
  const diagnostics = provideDiagnostics(compilerResult).map((diagnostic) => {
738
732
  if (diagnostic.severity === "error") {
739
733
  return {
@@ -756,10 +750,10 @@ async function handleDiagnostics(params, documents, workspaceFolders, settings,
756
750
  // src/handlers/formatting.ts
757
751
  async function handleFormatting(params, documents, workspaceFolders, settings, logger, reader) {
758
752
  const document = documents.get(params.textDocument.uri);
759
- if (!document) {
753
+ if (!document || !document.languageId.startsWith("stan")) {
760
754
  return [];
761
755
  }
762
- const result = await handleCompilation(document, documents, workspaceFolders, settings, logger, reader);
756
+ const result = await handleCompilation(document, documents, workspaceFolders, settings, "formatting", logger, reader);
763
757
  if (result.errors && result.errors.length > 0) {
764
758
  return { errors: result.errors };
765
759
  } else if (result.result) {
@@ -791,7 +785,7 @@ var startLanguageServer = (connection, reader) => {
791
785
  hasConfigurationCapability = Boolean(capabilities.workspace?.configuration);
792
786
  hasDynamicConfigurationRequestCapability = Boolean(capabilities.workspace?.configuration && capabilities.workspace?.didChangeConfiguration?.dynamicRegistration);
793
787
  hasWorkspaceFolderCapability = Boolean(capabilities.workspace?.workspaceFolders);
794
- hasSnippetSupport = Boolean(capabilities.textDocument?.completion?.completionItem?.snippetSupport);
788
+ hasSnippetSupport = Boolean(capabilities.textDocument?.completion?.completionItem?.snippetSupport || capabilities.textDocument?.completion?.completionItemKind?.valueSet?.some((kind) => kind === CompletionItemKind8.Snippet));
795
789
  return {
796
790
  capabilities: {
797
791
  textDocumentSync: TextDocumentSyncKind.Incremental,
@@ -889,7 +883,7 @@ var startLanguageServer = (connection, reader) => {
889
883
  });
890
884
  connection.onHover((params) => {
891
885
  const document = documents.get(params.textDocument.uri);
892
- if (!document) {
886
+ if (!document || !document.languageId.startsWith("stan")) {
893
887
  return null;
894
888
  }
895
889
  return hover_default(document, params);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "stan-language-server",
3
- "version": "0.4.6",
3
+ "version": "0.4.8",
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",
@@ -68,14 +68,14 @@
68
68
  },
69
69
  "devDependencies": {
70
70
  "@types/bun": "latest",
71
- "@types/node": "25.5.0",
72
- "@typescript-eslint/eslint-plugin": "8.57.1",
73
- "@typescript-eslint/parser": "8.57.1",
74
- "eslint": "10.0.3",
71
+ "@types/node": "25.6.0",
72
+ "@typescript-eslint/eslint-plugin": "8.59.1",
73
+ "@typescript-eslint/parser": "8.59.1",
74
+ "eslint": "10.3.0",
75
75
  "globals": "^17.3.0",
76
76
  "@eslint/js": "^10.0.1",
77
77
  "typescript-eslint": "^8.57.0",
78
- "typescript": "5.9.3"
78
+ "typescript": "6.0.3"
79
79
  },
80
80
  "dependencies": {
81
81
  "stanc3": "2.38.0",