@singapore-editor/lsp-plugin 0.1.1

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.
Files changed (185) hide show
  1. package/README.md +103 -0
  2. package/dist/bufferSync.d.ts +12 -0
  3. package/dist/bufferSync.d.ts.map +1 -0
  4. package/dist/bufferSync.js +35 -0
  5. package/dist/bufferSync.js.map +1 -0
  6. package/dist/codeActions.d.ts +83 -0
  7. package/dist/codeActions.d.ts.map +1 -0
  8. package/dist/codeActions.js +294 -0
  9. package/dist/codeActions.js.map +1 -0
  10. package/dist/colorAlpha.d.ts +4 -0
  11. package/dist/colorAlpha.d.ts.map +1 -0
  12. package/dist/colorAlpha.js +28 -0
  13. package/dist/colorAlpha.js.map +1 -0
  14. package/dist/completion.d.ts +124 -0
  15. package/dist/completion.d.ts.map +1 -0
  16. package/dist/completion.js +609 -0
  17. package/dist/completion.js.map +1 -0
  18. package/dist/completionCommit.d.ts +19 -0
  19. package/dist/completionCommit.d.ts.map +1 -0
  20. package/dist/completionCommit.js +57 -0
  21. package/dist/completionCommit.js.map +1 -0
  22. package/dist/completionController.d.ts +89 -0
  23. package/dist/completionController.d.ts.map +1 -0
  24. package/dist/completionController.js +376 -0
  25. package/dist/completionController.js.map +1 -0
  26. package/dist/completionProviders.d.ts +50 -0
  27. package/dist/completionProviders.d.ts.map +1 -0
  28. package/dist/completionProviders.js +64 -0
  29. package/dist/completionProviders.js.map +1 -0
  30. package/dist/connectionContext.d.ts +7 -0
  31. package/dist/connectionContext.d.ts.map +1 -0
  32. package/dist/definitionLinkController.d.ts +54 -0
  33. package/dist/definitionLinkController.d.ts.map +1 -0
  34. package/dist/definitionLinkController.js +221 -0
  35. package/dist/definitionLinkController.js.map +1 -0
  36. package/dist/definitionNavigation.d.ts +76 -0
  37. package/dist/definitionNavigation.d.ts.map +1 -0
  38. package/dist/definitionNavigation.js +143 -0
  39. package/dist/definitionNavigation.js.map +1 -0
  40. package/dist/diagnosticNotes.d.ts +7 -0
  41. package/dist/diagnosticNotes.d.ts.map +1 -0
  42. package/dist/diagnosticNotes.js +37 -0
  43. package/dist/diagnosticNotes.js.map +1 -0
  44. package/dist/diagnosticProjection.d.ts +31 -0
  45. package/dist/diagnosticProjection.d.ts.map +1 -0
  46. package/dist/diagnosticProjection.js +79 -0
  47. package/dist/diagnosticProjection.js.map +1 -0
  48. package/dist/diagnostics.d.ts +16 -0
  49. package/dist/diagnostics.d.ts.map +1 -0
  50. package/dist/diagnostics.js +94 -0
  51. package/dist/diagnostics.js.map +1 -0
  52. package/dist/diagnosticsPresenter.d.ts +64 -0
  53. package/dist/diagnosticsPresenter.d.ts.map +1 -0
  54. package/dist/diagnosticsPresenter.js +305 -0
  55. package/dist/diagnosticsPresenter.js.map +1 -0
  56. package/dist/document.d.ts +69 -0
  57. package/dist/document.d.ts.map +1 -0
  58. package/dist/document.js +190 -0
  59. package/dist/document.js.map +1 -0
  60. package/dist/documentHighlightController.d.ts +34 -0
  61. package/dist/documentHighlightController.d.ts.map +1 -0
  62. package/dist/documentHighlightController.js +101 -0
  63. package/dist/documentHighlightController.js.map +1 -0
  64. package/dist/documentSnapshot.d.ts +9 -0
  65. package/dist/documentSnapshot.d.ts.map +1 -0
  66. package/dist/documentSnapshot.js +31 -0
  67. package/dist/documentSnapshot.js.map +1 -0
  68. package/dist/documentSync.d.ts +53 -0
  69. package/dist/documentSync.d.ts.map +1 -0
  70. package/dist/documentSync.js +334 -0
  71. package/dist/documentSync.js.map +1 -0
  72. package/dist/documentSyncController.d.ts +26 -0
  73. package/dist/documentSyncController.d.ts.map +1 -0
  74. package/dist/documentSyncController.js +24 -0
  75. package/dist/documentSyncController.js.map +1 -0
  76. package/dist/formatOnType.d.ts +43 -0
  77. package/dist/formatOnType.d.ts.map +1 -0
  78. package/dist/formatOnType.js +198 -0
  79. package/dist/formatOnType.js.map +1 -0
  80. package/dist/formatting.d.ts +18 -0
  81. package/dist/formatting.d.ts.map +1 -0
  82. package/dist/formatting.js +52 -0
  83. package/dist/formatting.js.map +1 -0
  84. package/dist/fuzzyMatch.d.ts +22 -0
  85. package/dist/fuzzyMatch.d.ts.map +1 -0
  86. package/dist/fuzzyMatch.js +216 -0
  87. package/dist/fuzzyMatch.js.map +1 -0
  88. package/dist/hoverParticipant.d.ts +24 -0
  89. package/dist/hoverParticipant.d.ts.map +1 -0
  90. package/dist/hoverParticipant.js +156 -0
  91. package/dist/hoverParticipant.js.map +1 -0
  92. package/dist/index.d.ts +18 -0
  93. package/dist/index.d.ts.map +1 -0
  94. package/dist/index.js +17 -0
  95. package/dist/keyCommands.d.ts +19 -0
  96. package/dist/keyCommands.d.ts.map +1 -0
  97. package/dist/keyCommands.js +21 -0
  98. package/dist/keyCommands.js.map +1 -0
  99. package/dist/lane.d.ts +28 -0
  100. package/dist/lane.d.ts.map +1 -0
  101. package/dist/lane.js +138 -0
  102. package/dist/lane.js.map +1 -0
  103. package/dist/lspConnection.d.ts +94 -0
  104. package/dist/lspConnection.d.ts.map +1 -0
  105. package/dist/lspConnection.js +195 -0
  106. package/dist/lspConnection.js.map +1 -0
  107. package/dist/lspConnectionPool.d.ts +34 -0
  108. package/dist/lspConnectionPool.d.ts.map +1 -0
  109. package/dist/lspConnectionPool.js +255 -0
  110. package/dist/lspConnectionPool.js.map +1 -0
  111. package/dist/minimalEdits.d.ts +21 -0
  112. package/dist/minimalEdits.d.ts.map +1 -0
  113. package/dist/minimalEdits.js +181 -0
  114. package/dist/minimalEdits.js.map +1 -0
  115. package/dist/paths.d.ts +6 -0
  116. package/dist/paths.d.ts.map +1 -0
  117. package/dist/paths.js +38 -0
  118. package/dist/paths.js.map +1 -0
  119. package/dist/plugin.d.ts +100 -0
  120. package/dist/plugin.d.ts.map +1 -0
  121. package/dist/plugin.js +837 -0
  122. package/dist/plugin.js.map +1 -0
  123. package/dist/plugin.styles.d.ts +31 -0
  124. package/dist/plugin.styles.d.ts.map +1 -0
  125. package/dist/plugin.styles.js +102 -0
  126. package/dist/plugin.styles.js.map +1 -0
  127. package/dist/pluginTypes.d.ts +41 -0
  128. package/dist/pluginTypes.d.ts.map +1 -0
  129. package/dist/pluginTypes.js +0 -0
  130. package/dist/pullDiagnostics.d.ts +30 -0
  131. package/dist/pullDiagnostics.d.ts.map +1 -0
  132. package/dist/pullDiagnostics.js +94 -0
  133. package/dist/pullDiagnostics.js.map +1 -0
  134. package/dist/renameWidget.d.ts +30 -0
  135. package/dist/renameWidget.d.ts.map +1 -0
  136. package/dist/renameWidget.js +117 -0
  137. package/dist/renameWidget.js.map +1 -0
  138. package/dist/semanticTokenDecoder.d.ts +81 -0
  139. package/dist/semanticTokenDecoder.d.ts.map +1 -0
  140. package/dist/semanticTokenDecoder.js +132 -0
  141. package/dist/semanticTokenDecoder.js.map +1 -0
  142. package/dist/semanticTokens.d.ts +47 -0
  143. package/dist/semanticTokens.d.ts.map +1 -0
  144. package/dist/semanticTokens.js +68 -0
  145. package/dist/semanticTokens.js.map +1 -0
  146. package/dist/serverSet.d.ts +69 -0
  147. package/dist/serverSet.d.ts.map +1 -0
  148. package/dist/serverSet.js +331 -0
  149. package/dist/serverSet.js.map +1 -0
  150. package/dist/signatureHelp.d.ts +40 -0
  151. package/dist/signatureHelp.d.ts.map +1 -0
  152. package/dist/signatureHelp.js +108 -0
  153. package/dist/signatureHelp.js.map +1 -0
  154. package/dist/signatureHelpController.d.ts +52 -0
  155. package/dist/signatureHelpController.d.ts.map +1 -0
  156. package/dist/signatureHelpController.js +160 -0
  157. package/dist/signatureHelpController.js.map +1 -0
  158. package/dist/sourceText.d.ts +22 -0
  159. package/dist/sourceText.d.ts.map +1 -0
  160. package/dist/sourceText.js +70 -0
  161. package/dist/sourceText.js.map +1 -0
  162. package/dist/types.d.ts +238 -0
  163. package/dist/types.d.ts.map +1 -0
  164. package/dist/types.js +17 -0
  165. package/dist/types.js.map +1 -0
  166. package/dist/viewDocumentSnapshot.d.ts +5 -0
  167. package/dist/viewDocumentSnapshot.d.ts.map +1 -0
  168. package/dist/viewDocumentSnapshot.js +12 -0
  169. package/dist/viewDocumentSnapshot.js.map +1 -0
  170. package/dist/websocket.d.ts +6 -0
  171. package/dist/websocket.d.ts.map +1 -0
  172. package/dist/websocket.js +4 -0
  173. package/dist/workspaceEdit.d.ts +66 -0
  174. package/dist/workspaceEdit.d.ts.map +1 -0
  175. package/dist/workspaceEdit.js +276 -0
  176. package/dist/workspaceEdit.js.map +1 -0
  177. package/dist/workspaceEditProvenance.d.ts +5 -0
  178. package/dist/workspaceEditProvenance.d.ts.map +1 -0
  179. package/dist/workspaceEditProvenance.js +16 -0
  180. package/dist/workspaceEditProvenance.js.map +1 -0
  181. package/dist/workspaceTextEdits.d.ts +60 -0
  182. package/dist/workspaceTextEdits.d.ts.map +1 -0
  183. package/dist/workspaceTextEdits.js +395 -0
  184. package/dist/workspaceTextEdits.js.map +1 -0
  185. package/package.json +118 -0
@@ -0,0 +1,34 @@
1
+ import type { EditorViewContributionContext, EditorViewContributionUpdateKind, EditorViewSnapshot } from '@singapore-editor/core';
2
+ import type { ActiveDocument } from './pluginTypes';
3
+ import type { LanguageServerFeatureRouter } from './serverSet';
4
+ export type DocumentHighlightControllerOptions = {
5
+ readonly context: EditorViewContributionContext;
6
+ readonly router: LanguageServerFeatureRouter;
7
+ readonly highlightName: string;
8
+ readonly getActiveDocument: () => ActiveDocument | null;
9
+ readonly onRequestError: (error: unknown) => void;
10
+ };
11
+ /**
12
+ * Paints every reference to the symbol under the caret, as the language server sees them.
13
+ *
14
+ * More precise than a textual occurrence match: the server knows scope, so a local `value` does not
15
+ * light up an unrelated `value` in another function. The textual highlighter stays as the fallback
16
+ * for documents with no server.
17
+ */
18
+ export declare class DocumentHighlightController {
19
+ private readonly options;
20
+ private timer;
21
+ private abort;
22
+ private requestId;
23
+ private painted;
24
+ private disposed;
25
+ constructor(options: DocumentHighlightControllerOptions);
26
+ update(snapshot: EditorViewSnapshot, kind: EditorViewContributionUpdateKind): void;
27
+ dispose(): void;
28
+ private schedule;
29
+ private cancel;
30
+ private request;
31
+ private paint;
32
+ private clear;
33
+ }
34
+ //# sourceMappingURL=documentHighlightController.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentHighlightController.d.ts","sourceRoot":"","sources":["../src/documentHighlightController.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,6BAA6B,EAC7B,gCAAgC,EAChC,kBAAkB,EACnB,MAAM,wBAAwB,CAAA;AAG/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAA;AACnD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAK9D,MAAM,MAAM,kCAAkC,GAAG;IAC/C,QAAQ,CAAC,OAAO,EAAE,6BAA6B,CAAA;IAC/C,QAAQ,CAAC,MAAM,EAAE,2BAA2B,CAAA;IAC5C,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,cAAc,GAAG,IAAI,CAAA;IACvD,QAAQ,CAAC,cAAc,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;CAClD,CAAA;AAED;;;;;;GAMG;AACH,qBAAa,2BAA2B;IAOnB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAN3C,OAAO,CAAC,KAAK,CAA6C;IAC1D,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,SAAS,CAAI;IACrB,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,QAAQ,CAAQ;gBAEY,OAAO,EAAE,kCAAkC;IAExE,MAAM,CAAC,QAAQ,EAAE,kBAAkB,EAAE,IAAI,EAAE,gCAAgC,GAAG,IAAI;IAiBlF,OAAO,IAAI,IAAI;IAOtB,OAAO,CAAC,QAAQ;IAahB,OAAO,CAAC,MAAM;YAOA,OAAO;IA+BrB,OAAO,CAAC,KAAK;IAiBb,OAAO,CAAC,KAAK;CAOd"}
@@ -0,0 +1,101 @@
1
+ import { lspPositionToOffsetInSnapshot, offsetToLspPositionInSnapshot } from "@singapore-editor/lsp";
2
+ //#region src/documentHighlightController.ts
3
+ /** Matches the hover debounce: both answer "what is under the caret", and should feel alike. */
4
+ var DOCUMENT_HIGHLIGHT_DEBOUNCE_MS = 150;
5
+ /**
6
+ * Paints every reference to the symbol under the caret, as the language server sees them.
7
+ *
8
+ * More precise than a textual occurrence match: the server knows scope, so a local `value` does not
9
+ * light up an unrelated `value` in another function. The textual highlighter stays as the fallback
10
+ * for documents with no server.
11
+ */
12
+ var DocumentHighlightController = class {
13
+ options;
14
+ timer = null;
15
+ abort = null;
16
+ requestId = 0;
17
+ painted = false;
18
+ disposed = false;
19
+ constructor(options) {
20
+ this.options = options;
21
+ }
22
+ update(snapshot, kind) {
23
+ if (kind === "document" || kind === "clear") {
24
+ this.clear();
25
+ return;
26
+ }
27
+ if (kind !== "selection" && kind !== "content") return;
28
+ const primary = snapshot.selections[0];
29
+ if (!primary || primary.startOffset !== primary.endOffset) {
30
+ this.clear();
31
+ return;
32
+ }
33
+ this.schedule(primary.headOffset);
34
+ }
35
+ dispose() {
36
+ if (this.disposed) return;
37
+ this.disposed = true;
38
+ this.clear();
39
+ }
40
+ schedule(offset) {
41
+ this.cancel();
42
+ /**
43
+ * @justification Debounces a request to the language server against the caret, not against
44
+ * rendering, and `cancel()` clears it on every move — so the server sees one question per
45
+ * pause rather than one per keystroke.
46
+ */
47
+ this.timer = setTimeout(() => {
48
+ this.timer = null;
49
+ this.request(offset);
50
+ }, DOCUMENT_HIGHLIGHT_DEBOUNCE_MS);
51
+ }
52
+ cancel() {
53
+ if (this.timer) clearTimeout(this.timer);
54
+ this.timer = null;
55
+ this.abort?.abort();
56
+ this.abort = null;
57
+ }
58
+ async request(offset) {
59
+ const active = this.options.getActiveDocument();
60
+ if (!active) return this.clear();
61
+ if (!this.options.router.hasReady("documentHighlights", "textDocument/documentHighlight")) return;
62
+ const abort = new AbortController();
63
+ const requestId = this.requestId + 1;
64
+ this.requestId = requestId;
65
+ this.abort = abort;
66
+ try {
67
+ const highlights = await this.options.router.request("textDocument/documentHighlight", {
68
+ position: offsetToLspPositionInSnapshot(active, offset),
69
+ textDocument: { uri: active.uri }
70
+ }, { signal: abort.signal });
71
+ if (requestId !== this.requestId) return;
72
+ if (this.disposed) return;
73
+ if (active !== this.options.getActiveDocument()) return;
74
+ this.paint(active, highlights);
75
+ } catch (error) {
76
+ this.options.onRequestError(error);
77
+ }
78
+ }
79
+ paint(active, highlights) {
80
+ const ranges = (highlights ?? []).map((highlight) => ({
81
+ end: lspPositionToOffsetInSnapshot(active, highlight.range.end),
82
+ start: lspPositionToOffsetInSnapshot(active, highlight.range.start)
83
+ }));
84
+ if (ranges.length < 2) {
85
+ this.clear();
86
+ return;
87
+ }
88
+ this.painted = true;
89
+ this.options.context.setRangeHighlight(this.options.highlightName, ranges, { backgroundColor: "rgba(128, 128, 128, 0.18)" });
90
+ }
91
+ clear() {
92
+ this.cancel();
93
+ if (!this.painted) return;
94
+ this.painted = false;
95
+ this.options.context.clearRangeHighlight(this.options.highlightName);
96
+ }
97
+ };
98
+ //#endregion
99
+ export { DocumentHighlightController };
100
+
101
+ //# sourceMappingURL=documentHighlightController.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentHighlightController.js","names":[],"sources":["../src/documentHighlightController.ts"],"sourcesContent":["import type * as lsp from 'vscode-languageserver-protocol'\n\nimport type {\n EditorViewContributionContext,\n EditorViewContributionUpdateKind,\n EditorViewSnapshot,\n} from '@singapore-editor/core'\nimport { lspPositionToOffsetInSnapshot, offsetToLspPositionInSnapshot } from '@singapore-editor/lsp'\n\nimport type { ActiveDocument } from './pluginTypes'\nimport type { LanguageServerFeatureRouter } from './serverSet'\n\n/** Matches the hover debounce: both answer \"what is under the caret\", and should feel alike. */\nconst DOCUMENT_HIGHLIGHT_DEBOUNCE_MS = 150\n\nexport type DocumentHighlightControllerOptions = {\n readonly context: EditorViewContributionContext\n readonly router: LanguageServerFeatureRouter\n readonly highlightName: string\n readonly getActiveDocument: () => ActiveDocument | null\n readonly onRequestError: (error: unknown) => void\n}\n\n/**\n * Paints every reference to the symbol under the caret, as the language server sees them.\n *\n * More precise than a textual occurrence match: the server knows scope, so a local `value` does not\n * light up an unrelated `value` in another function. The textual highlighter stays as the fallback\n * for documents with no server.\n */\nexport class DocumentHighlightController {\n private timer: ReturnType<typeof setTimeout> | null = null\n private abort: AbortController | null = null\n private requestId = 0\n private painted = false\n private disposed = false\n\n public constructor(private readonly options: DocumentHighlightControllerOptions) {}\n\n public update(snapshot: EditorViewSnapshot, kind: EditorViewContributionUpdateKind): void {\n if (kind === 'document' || kind === 'clear') {\n this.clear()\n return\n }\n if (kind !== 'selection' && kind !== 'content') return\n\n const primary = snapshot.selections[0]\n // A dragged selection has its own meaning; only a resting caret asks \"where else is this used\".\n if (!primary || primary.startOffset !== primary.endOffset) {\n this.clear()\n return\n }\n\n this.schedule(primary.headOffset)\n }\n\n public dispose(): void {\n if (this.disposed) return\n\n this.disposed = true\n this.clear()\n }\n\n private schedule(offset: number): void {\n this.cancel()\n /**\n * @justification Debounces a request to the language server against the caret, not against\n * rendering, and `cancel()` clears it on every move — so the server sees one question per\n * pause rather than one per keystroke.\n */\n this.timer = setTimeout(() => {\n this.timer = null\n void this.request(offset)\n }, DOCUMENT_HIGHLIGHT_DEBOUNCE_MS)\n }\n\n private cancel(): void {\n if (this.timer) clearTimeout(this.timer)\n this.timer = null\n this.abort?.abort()\n this.abort = null\n }\n\n private async request(offset: number): Promise<void> {\n const active = this.options.getActiveDocument()\n if (!active) return this.clear()\n if (!this.options.router.hasReady('documentHighlights', 'textDocument/documentHighlight')) {\n return\n }\n\n const abort = new AbortController()\n const requestId = this.requestId + 1\n this.requestId = requestId\n this.abort = abort\n\n try {\n const highlights = await this.options.router.request<lsp.DocumentHighlight[] | null>(\n 'textDocument/documentHighlight',\n {\n position: offsetToLspPositionInSnapshot(active, offset),\n textDocument: { uri: active.uri },\n },\n { signal: abort.signal },\n )\n if (requestId !== this.requestId) return\n if (this.disposed) return\n if (active !== this.options.getActiveDocument()) return\n\n this.paint(active, highlights)\n } catch (error) {\n this.options.onRequestError(error)\n }\n }\n\n private paint(active: ActiveDocument, highlights: lsp.DocumentHighlight[] | null): void {\n const ranges = (highlights ?? []).map((highlight) => ({\n end: lspPositionToOffsetInSnapshot(active, highlight.range.end),\n start: lspPositionToOffsetInSnapshot(active, highlight.range.start),\n }))\n // A lone highlight is the symbol the caret is already in — painting it says nothing.\n if (ranges.length < 2) {\n this.clear()\n return\n }\n\n this.painted = true\n this.options.context.setRangeHighlight(this.options.highlightName, ranges, {\n backgroundColor: 'rgba(128, 128, 128, 0.18)',\n })\n }\n\n private clear(): void {\n this.cancel()\n if (!this.painted) return\n\n this.painted = false\n this.options.context.clearRangeHighlight(this.options.highlightName)\n }\n}\n"],"mappings":";;;AAaA,IAAM,iCAAiC;;;;;;;;AAiBvC,IAAa,8BAAb,MAAyC;CAOH;CANpC,QAAsD;CACtD,QAAwC;CACxC,YAAoB;CACpB,UAAkB;CAClB,WAAmB;CAEnB,YAAmB,SAA8D;EAA7C,KAAA,UAAA;CAA8C;CAElF,OAAc,UAA8B,MAA8C;EACxF,IAAI,SAAS,cAAc,SAAS,SAAS;GAC3C,KAAK,MAAM;GACX;EACF;EACA,IAAI,SAAS,eAAe,SAAS,WAAW;EAEhD,MAAM,UAAU,SAAS,WAAW;EAEpC,IAAI,CAAC,WAAW,QAAQ,gBAAgB,QAAQ,WAAW;GACzD,KAAK,MAAM;GACX;EACF;EAEA,KAAK,SAAS,QAAQ,UAAU;CAClC;CAEA,UAAuB;EACrB,IAAI,KAAK,UAAU;EAEnB,KAAK,WAAW;EAChB,KAAK,MAAM;CACb;CAEA,SAAiB,QAAsB;EACrC,KAAK,OAAO;;;;;;EAMZ,KAAK,QAAQ,iBAAiB;GAC5B,KAAK,QAAQ;GACb,KAAU,QAAQ,MAAM;EAC1B,GAAG,8BAA8B;CACnC;CAEA,SAAuB;EACrB,IAAI,KAAK,OAAO,aAAa,KAAK,KAAK;EACvC,KAAK,QAAQ;EACb,KAAK,OAAO,MAAM;EAClB,KAAK,QAAQ;CACf;CAEA,MAAc,QAAQ,QAA+B;EACnD,MAAM,SAAS,KAAK,QAAQ,kBAAkB;EAC9C,IAAI,CAAC,QAAQ,OAAO,KAAK,MAAM;EAC/B,IAAI,CAAC,KAAK,QAAQ,OAAO,SAAS,sBAAsB,gCAAgC,GACtF;EAGF,MAAM,QAAQ,IAAI,gBAAgB;EAClC,MAAM,YAAY,KAAK,YAAY;EACnC,KAAK,YAAY;EACjB,KAAK,QAAQ;EAEb,IAAI;GACF,MAAM,aAAa,MAAM,KAAK,QAAQ,OAAO,QAC3C,kCACA;IACE,UAAU,8BAA8B,QAAQ,MAAM;IACtD,cAAc,EAAE,KAAK,OAAO,IAAI;GAClC,GACA,EAAE,QAAQ,MAAM,OAAO,CACzB;GACA,IAAI,cAAc,KAAK,WAAW;GAClC,IAAI,KAAK,UAAU;GACnB,IAAI,WAAW,KAAK,QAAQ,kBAAkB,GAAG;GAEjD,KAAK,MAAM,QAAQ,UAAU;EAC/B,SAAS,OAAO;GACd,KAAK,QAAQ,eAAe,KAAK;EACnC;CACF;CAEA,MAAc,QAAwB,YAAkD;EACtF,MAAM,UAAU,cAAc,CAAC,EAAA,CAAG,KAAK,eAAe;GACpD,KAAK,8BAA8B,QAAQ,UAAU,MAAM,GAAG;GAC9D,OAAO,8BAA8B,QAAQ,UAAU,MAAM,KAAK;EACpE,EAAE;EAEF,IAAI,OAAO,SAAS,GAAG;GACrB,KAAK,MAAM;GACX;EACF;EAEA,KAAK,UAAU;EACf,KAAK,QAAQ,QAAQ,kBAAkB,KAAK,QAAQ,eAAe,QAAQ,EACzE,iBAAiB,4BACnB,CAAC;CACH;CAEA,QAAsB;EACpB,KAAK,OAAO;EACZ,IAAI,CAAC,KAAK,SAAS;EAEnB,KAAK,UAAU;EACf,KAAK,QAAQ,QAAQ,oBAAoB,KAAK,QAAQ,aAAa;CACrE;AACF"}
@@ -0,0 +1,9 @@
1
+ import type { EditorTextBuffer } from '@singapore-editor/core/document';
2
+ import type { LanguageServerDocumentSnapshot } from './types';
3
+ export declare function bufferDocumentSnapshot({ buffer, documentId, uri, languageId, }: {
4
+ readonly buffer: EditorTextBuffer;
5
+ readonly documentId?: string;
6
+ readonly uri: string;
7
+ readonly languageId: string;
8
+ }): LanguageServerDocumentSnapshot;
9
+ //# sourceMappingURL=documentSnapshot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentSnapshot.d.ts","sourceRoot":"","sources":["../src/documentSnapshot.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AACvE,OAAO,KAAK,EAAE,8BAA8B,EAAE,MAAM,SAAS,CAAA;AAE7D,wBAAgB,sBAAsB,CAAC,EACrC,MAAM,EACN,UAAU,EACV,GAAG,EACH,UAAU,GACX,EAAE;IACD,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAA;IACjC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B,GAAG,8BAA8B,CA4BjC"}
@@ -0,0 +1,31 @@
1
+ //#region src/documentSnapshot.ts
2
+ function bufferDocumentSnapshot({ buffer, documentId, uri, languageId }) {
3
+ const textSnapshot = buffer.getTextSnapshot();
4
+ const point = buffer.getDocumentSyncPoint();
5
+ const lineStartsView = {
6
+ length: textSnapshot.lineCount,
7
+ at: (index) => index < 0 || index >= textSnapshot.lineCount ? void 0 : textSnapshot.lineStart(index),
8
+ indexForOffset: (offset) => textSnapshot.lineAt(offset),
9
+ firstIndexAtOrAfter: (offset) => {
10
+ const index = textSnapshot.lineAt(offset);
11
+ return textSnapshot.lineStart(index) < offset ? index + 1 : index;
12
+ },
13
+ toArray: () => Array.from({ length: textSnapshot.lineCount }, (_, index) => textSnapshot.lineStart(index))
14
+ };
15
+ return {
16
+ documentId: documentId ?? uri,
17
+ languageId,
18
+ textSnapshot,
19
+ textVersion: point.textVersion,
20
+ documentSyncPoint: point,
21
+ changesSinceDocumentSyncPoint: (previous, scope) => buffer.changesSinceDocumentSyncPoint(previous, scope),
22
+ lineStartsView,
23
+ get lineStarts() {
24
+ return lineStartsView.toArray();
25
+ }
26
+ };
27
+ }
28
+ //#endregion
29
+ export { bufferDocumentSnapshot };
30
+
31
+ //# sourceMappingURL=documentSnapshot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentSnapshot.js","names":[],"sources":["../src/documentSnapshot.ts"],"sourcesContent":["import type { EditorTextBuffer } from '@singapore-editor/core/document'\nimport type { LanguageServerDocumentSnapshot } from './types'\n\nexport function bufferDocumentSnapshot({\n buffer,\n documentId,\n uri,\n languageId,\n}: {\n readonly buffer: EditorTextBuffer\n readonly documentId?: string\n readonly uri: string\n readonly languageId: string\n}): LanguageServerDocumentSnapshot {\n const textSnapshot = buffer.getTextSnapshot()\n const point = buffer.getDocumentSyncPoint()\n const lineStartsView = {\n length: textSnapshot.lineCount,\n at: (index: number) =>\n index < 0 || index >= textSnapshot.lineCount ? undefined : textSnapshot.lineStart(index),\n indexForOffset: (offset: number) => textSnapshot.lineAt(offset),\n firstIndexAtOrAfter: (offset: number) => {\n const index = textSnapshot.lineAt(offset)\n return textSnapshot.lineStart(index) < offset ? index + 1 : index\n },\n toArray: () =>\n Array.from({ length: textSnapshot.lineCount }, (_, index) => textSnapshot.lineStart(index)),\n }\n return {\n documentId: documentId ?? uri,\n languageId,\n textSnapshot,\n textVersion: point.textVersion,\n documentSyncPoint: point,\n changesSinceDocumentSyncPoint: (previous, scope) =>\n buffer.changesSinceDocumentSyncPoint(previous, scope),\n lineStartsView,\n get lineStarts() {\n return lineStartsView.toArray()\n },\n }\n}\n"],"mappings":";AAGA,SAAgB,uBAAuB,EACrC,QACA,YACA,KACA,cAMiC;CACjC,MAAM,eAAe,OAAO,gBAAgB;CAC5C,MAAM,QAAQ,OAAO,qBAAqB;CAC1C,MAAM,iBAAiB;EACrB,QAAQ,aAAa;EACrB,KAAK,UACH,QAAQ,KAAK,SAAS,aAAa,YAAY,KAAA,IAAY,aAAa,UAAU,KAAK;EACzF,iBAAiB,WAAmB,aAAa,OAAO,MAAM;EAC9D,sBAAsB,WAAmB;GACvC,MAAM,QAAQ,aAAa,OAAO,MAAM;GACxC,OAAO,aAAa,UAAU,KAAK,IAAI,SAAS,QAAQ,IAAI;EAC9D;EACA,eACE,MAAM,KAAK,EAAE,QAAQ,aAAa,UAAU,IAAI,GAAG,UAAU,aAAa,UAAU,KAAK,CAAC;CAC9F;CACA,OAAO;EACL,YAAY,cAAc;EAC1B;EACA;EACA,aAAa,MAAM;EACnB,mBAAmB;EACnB,gCAAgC,UAAU,UACxC,OAAO,8BAA8B,UAAU,KAAK;EACtD;EACA,IAAI,aAAa;GACf,OAAO,eAAe,QAAQ;EAChC;CACF;AACF"}
@@ -0,0 +1,53 @@
1
+ import type { LanguageServerDocumentSnapshot } from './types';
2
+ import { type DocumentLogicalRevisionScope } from '@singapore-editor/core/document';
3
+ import type { EditorContributionChange, EditorViewContributionUpdateKind } from '@singapore-editor/core/extensions';
4
+ import { type LspTextDocumentSnapshot, type LspWorkspace } from '@singapore-editor/lsp';
5
+ import type * as lsp from 'vscode-languageserver-protocol';
6
+ import type { LanguageServerDocumentUriTransition } from './documentSyncController';
7
+ import type { ActiveDocument } from './pluginTypes';
8
+ import type { LanguageServerDocumentSyncOptions } from './types';
9
+ /** `result` came from the server; `reset` is the client emptying the list itself. */
10
+ export type DocumentSyncSummaryKind = 'result' | 'reset';
11
+ export type DocumentSyncDiagnosticsPresenter = {
12
+ clear(): void;
13
+ render(document: LspTextDocumentSnapshot, diagnostics: readonly lsp.Diagnostic[]): void;
14
+ publishSummary(uri: lsp.DocumentUri, version: number | null, diagnostics: readonly lsp.Diagnostic[], kind: DocumentSyncSummaryKind): void;
15
+ };
16
+ export type DocumentSyncOptions = LanguageServerDocumentSyncOptions & {
17
+ readonly logicalRevisionScope: DocumentLogicalRevisionScope;
18
+ onDocumentClosed(): void;
19
+ };
20
+ export declare class DocumentSync {
21
+ private readonly workspace;
22
+ private readonly presenter;
23
+ private readonly options;
24
+ private attachment;
25
+ private document;
26
+ private diagnosticItems;
27
+ private readonly logicalRevisionScope;
28
+ private pendingUriProjection;
29
+ private syncPoint;
30
+ constructor(workspace: LspWorkspace, presenter: DocumentSyncDiagnosticsPresenter, options: DocumentSyncOptions);
31
+ get activeDocument(): ActiveDocument | null;
32
+ get diagnostics(): readonly lsp.Diagnostic[];
33
+ shouldSync(kind: EditorViewContributionUpdateKind, snapshot: LanguageServerDocumentSnapshot): boolean;
34
+ sync(snapshot: LanguageServerDocumentSnapshot, change: EditorContributionChange | null): void;
35
+ close(): void;
36
+ transitionDocumentUri(snapshot: LanguageServerDocumentSnapshot, transition: LanguageServerDocumentUriTransition): boolean;
37
+ private detachDocument;
38
+ private matchesTransitionSource;
39
+ private projectedDocumentUri;
40
+ publishDiagnostics(params: unknown): void;
41
+ pullDiagnostics(uri: lsp.DocumentUri, version: number, diagnostics: readonly lsp.Diagnostic[]): void;
42
+ clearDiagnostics(): void;
43
+ private openOrUpdateDocument;
44
+ private replaceDiagnostics;
45
+ private openDocument;
46
+ private replaceOrTransitionDocument;
47
+ private transitionDocument;
48
+ private updateDocument;
49
+ private synchronizeWorkspaceDocument;
50
+ private adoptDocumentTransition;
51
+ }
52
+ export declare function activeDocumentForSnapshot(snapshot: LanguageServerDocumentSnapshot, options: LanguageServerDocumentSyncOptions): ActiveDocument | null;
53
+ //# sourceMappingURL=documentSync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentSync.d.ts","sourceRoot":"","sources":["../src/documentSync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,334 @@
1
+ import { projectDiagnosticsInSnapshot } from "./diagnosticProjection.js";
2
+ import { pathOrUriToDocumentUri } from "./paths.js";
3
+ import { viewDocumentSnapshot } from "./viewDocumentSnapshot.js";
4
+ import "@singapore-editor/core/document";
5
+ import { recordLspPerformanceDiagnostic } from "@singapore-editor/lsp";
6
+ //#region src/documentSync.ts
7
+ var DocumentSync = class {
8
+ workspace;
9
+ presenter;
10
+ options;
11
+ attachment = null;
12
+ document = null;
13
+ diagnosticItems = [];
14
+ logicalRevisionScope;
15
+ pendingUriProjection = null;
16
+ syncPoint = null;
17
+ constructor(workspace, presenter, options) {
18
+ this.workspace = workspace;
19
+ this.presenter = presenter;
20
+ this.options = options;
21
+ this.logicalRevisionScope = options.logicalRevisionScope;
22
+ }
23
+ get activeDocument() {
24
+ return this.document;
25
+ }
26
+ get diagnostics() {
27
+ return this.diagnosticItems;
28
+ }
29
+ shouldSync(kind, snapshot) {
30
+ if (kind === "document" || kind === "content" || kind === "clear") return true;
31
+ if (!this.document) return false;
32
+ return !sameSyncPoint(this.syncPoint, snapshot.documentSyncPoint);
33
+ }
34
+ sync(snapshot, change) {
35
+ const projectedUri = this.projectedDocumentUri(snapshot);
36
+ const descriptor = documentDescriptor(snapshot, this.options, projectedUri);
37
+ if (!descriptor) {
38
+ this.detachDocument();
39
+ return;
40
+ }
41
+ this.openOrUpdateDocument(descriptor, change, snapshot);
42
+ }
43
+ close() {
44
+ this.pendingUriProjection = null;
45
+ this.detachDocument();
46
+ }
47
+ transitionDocumentUri(snapshot, transition) {
48
+ if (!this.matchesTransitionSource(snapshot, transition)) return false;
49
+ const descriptor = documentDescriptor(snapshot, this.options, transition.toUri, transition.textSnapshot);
50
+ if (!descriptor) {
51
+ this.detachDocument();
52
+ this.pendingUriProjection = pendingUriProjection(transition);
53
+ return true;
54
+ }
55
+ this.transitionDocument(descriptor, transition.syncPoint);
56
+ return true;
57
+ }
58
+ detachDocument() {
59
+ const active = this.document;
60
+ const attachment = this.attachment;
61
+ this.attachment = null;
62
+ this.document = null;
63
+ this.diagnosticItems = [];
64
+ this.syncPoint = null;
65
+ this.options.onDocumentClosed();
66
+ if (!active) return;
67
+ this.presenter.clear();
68
+ if (attachment) this.workspace.closeDocument(attachment);
69
+ this.presenter.publishSummary(active.uri, active.lspVersion, [], "reset");
70
+ }
71
+ matchesTransitionSource(snapshot, transition) {
72
+ const active = this.document;
73
+ const point = this.syncPoint;
74
+ if (!active || !this.attachment || !point) return false;
75
+ if (active.uri !== transition.fromUri) return false;
76
+ if (active.textSnapshot !== transition.textSnapshot) return false;
77
+ if (snapshot.textSnapshot !== transition.textSnapshot) return false;
78
+ if (point.revision !== transition.syncPoint.revision) return false;
79
+ if (point.textVersion !== transition.syncPoint.textVersion) return false;
80
+ return point.segment !== transition.syncPoint.segment;
81
+ }
82
+ projectedDocumentUri(snapshot) {
83
+ const projection = this.pendingUriProjection;
84
+ if (!projection) return void 0;
85
+ if (snapshot.documentSyncPoint.segment !== projection.segment) {
86
+ this.pendingUriProjection = null;
87
+ return;
88
+ }
89
+ const uri = documentUri(snapshot, this.options);
90
+ if (uri === null) {
91
+ this.pendingUriProjection = null;
92
+ return;
93
+ }
94
+ if (uri === projection.fromUri) return projection.toUri;
95
+ this.pendingUriProjection = null;
96
+ }
97
+ publishDiagnostics(params) {
98
+ const diagnostics = publishDiagnosticsParams(params);
99
+ if (!diagnostics) return;
100
+ const active = this.document;
101
+ if (!active) return;
102
+ if (diagnostics.uri !== active.uri) return;
103
+ if (diagnostics.version !== null && diagnostics.version !== active.lspVersion) return;
104
+ this.replaceDiagnostics(active, diagnostics.version, diagnostics.diagnostics);
105
+ }
106
+ pullDiagnostics(uri, version, diagnostics) {
107
+ const active = this.document;
108
+ if (!active || active.uri !== uri || active.lspVersion !== version) return;
109
+ this.replaceDiagnostics(active, version, diagnostics);
110
+ }
111
+ clearDiagnostics() {
112
+ const active = this.document;
113
+ this.diagnosticItems = [];
114
+ this.presenter.clear();
115
+ if (!active) return;
116
+ this.presenter.publishSummary(active.uri, active.lspVersion, [], "reset");
117
+ }
118
+ openOrUpdateDocument(descriptor, change, snapshot) {
119
+ const active = this.document;
120
+ if (!active) {
121
+ this.openDocument(descriptor, snapshot.documentSyncPoint);
122
+ return;
123
+ }
124
+ if (active.uri !== descriptor.uri) {
125
+ this.replaceOrTransitionDocument(descriptor, snapshot.documentSyncPoint);
126
+ return;
127
+ }
128
+ if (active.languageId !== descriptor.languageId) {
129
+ this.openDocument(descriptor, snapshot.documentSyncPoint);
130
+ return;
131
+ }
132
+ if (sameSyncPoint(this.syncPoint, snapshot.documentSyncPoint)) return;
133
+ this.updateDocument(descriptor, change, snapshot);
134
+ }
135
+ replaceDiagnostics(active, version, diagnostics) {
136
+ this.diagnosticItems = diagnostics;
137
+ this.presenter.render(active, diagnostics);
138
+ this.presenter.publishSummary(active.uri, version, diagnostics, "result");
139
+ }
140
+ openDocument(descriptor, syncPoint) {
141
+ this.close();
142
+ const result = this.workspace.openDocumentSnapshot({
143
+ uri: descriptor.uri,
144
+ languageId: descriptor.languageId,
145
+ textSnapshot: descriptor.textSnapshot,
146
+ lineStarts: descriptor.lineStarts,
147
+ sourceRevision: syncPoint.revision,
148
+ sourceSegment: syncPoint.segment,
149
+ onDocumentTransition: (transition) => this.adoptDocumentTransition(transition)
150
+ });
151
+ this.attachment = result.attachment;
152
+ this.document = activeDocument(descriptor, result.document.version);
153
+ this.syncPoint = syncPoint;
154
+ }
155
+ replaceOrTransitionDocument(descriptor, syncPoint) {
156
+ if (!isSharedUriTransition(this.document, this.syncPoint, descriptor, syncPoint)) {
157
+ this.openDocument(descriptor, syncPoint);
158
+ return;
159
+ }
160
+ this.transitionDocument(descriptor, syncPoint);
161
+ }
162
+ transitionDocument(descriptor, syncPoint) {
163
+ const attachment = this.attachment;
164
+ if (!attachment) throw new Error("An active LSP document must retain its workspace attachment.");
165
+ const result = this.workspace.transitionDocumentUri(attachment, {
166
+ uri: descriptor.uri,
167
+ languageId: descriptor.languageId,
168
+ textSnapshot: descriptor.textSnapshot,
169
+ lineStarts: descriptor.lineStarts,
170
+ sourceRevision: syncPoint.revision,
171
+ sourceSegment: syncPoint.segment,
172
+ sourceTextVersion: syncPoint.textVersion
173
+ });
174
+ this.document = activeDocument(descriptor, result.document.version);
175
+ this.syncPoint = syncPoint;
176
+ }
177
+ updateDocument(descriptor, change, snapshot) {
178
+ const active = this.document;
179
+ const diagnostics = projectDiagnosticsInSnapshot(this.diagnosticItems, {
180
+ previousDocument: active ?? descriptor,
181
+ nextDocument: descriptor,
182
+ change
183
+ });
184
+ const changes = changesSinceLastSync(snapshot, this.syncPoint, this.logicalRevisionScope, change, active?.textSnapshot ?? descriptor.textSnapshot, descriptor.textSnapshot);
185
+ recordLspPerformanceDiagnostic("lsp.documentSync.editChain", {
186
+ chained: changes.edits === null ? "null" : changes.edits.length,
187
+ logicalRevisionCount: changes.logicalRevisionCount,
188
+ activeTextVersion: active?.textVersion ?? -1,
189
+ snapshotTextVersion: snapshot.textVersion,
190
+ changeEditCount: change?.edits.length ?? -1
191
+ });
192
+ const document = this.synchronizeWorkspaceDocument(descriptor, changes);
193
+ this.document = activeDocument(descriptor, document.version);
194
+ this.syncPoint = changes.syncPointAfter;
195
+ if (diagnostics === this.diagnosticItems) return;
196
+ this.diagnosticItems = diagnostics;
197
+ this.presenter.render(descriptor, diagnostics);
198
+ }
199
+ synchronizeWorkspaceDocument(descriptor, changes) {
200
+ const source = {
201
+ textSnapshot: descriptor.textSnapshot,
202
+ lineStarts: descriptor.lineStarts,
203
+ sourceRevision: changes.syncPointAfter.revision,
204
+ sourceSegment: changes.syncPointAfter.segment
205
+ };
206
+ if (changes.logicalRevisionCount === 0) return this.workspace.adoptUnchangedDocumentSource(descriptor.uri, source);
207
+ return this.workspace.updateDocumentSnapshot(descriptor.uri, {
208
+ ...source,
209
+ edits: changes.edits,
210
+ logicalRevisionCount: changes.logicalRevisionCount
211
+ });
212
+ }
213
+ adoptDocumentTransition(transition) {
214
+ const active = this.document;
215
+ if (!active) return;
216
+ this.diagnosticItems = [];
217
+ this.presenter.clear();
218
+ this.presenter.publishSummary(active.uri, active.lspVersion, [], "reset");
219
+ this.pendingUriProjection = {
220
+ fromUri: active.uri,
221
+ toUri: transition.document.uri,
222
+ segment: transition.sourceSegment
223
+ };
224
+ this.document = activeDocumentForTransition(active, transition);
225
+ this.syncPoint = {
226
+ revision: transition.sourceRevision,
227
+ segment: transition.sourceSegment,
228
+ textVersion: transition.sourceTextVersion
229
+ };
230
+ }
231
+ };
232
+ function pendingUriProjection(transition) {
233
+ return {
234
+ fromUri: transition.fromUri,
235
+ toUri: transition.toUri,
236
+ segment: transition.syncPoint.segment
237
+ };
238
+ }
239
+ function changesSinceLastSync(snapshot, point, scope, change, previousTextSnapshot, nextTextSnapshot) {
240
+ if (!point) return fallbackSyncChanges(snapshot, null, change, scope, previousTextSnapshot, nextTextSnapshot);
241
+ const changes = snapshot.changesSinceDocumentSyncPoint(point, scope);
242
+ if (changes) return {
243
+ edits: changes.edits,
244
+ logicalRevisionCount: changes.logicalRevisionCount,
245
+ syncPointAfter: changes.syncPointAfter
246
+ };
247
+ return fallbackSyncChanges(snapshot, point, change, scope, previousTextSnapshot, nextTextSnapshot);
248
+ }
249
+ function fallbackSyncChanges(snapshot, point, change, scope, previousTextSnapshot, nextTextSnapshot) {
250
+ const nextPoint = snapshot.documentSyncPoint;
251
+ return {
252
+ edits: null,
253
+ logicalRevisionCount: fallbackLogicalRevisionCount(change, scope, previousTextSnapshot !== nextTextSnapshot || point === null || point.textVersion !== nextPoint.textVersion, point, nextPoint),
254
+ syncPointAfter: nextPoint
255
+ };
256
+ }
257
+ function fallbackLogicalRevisionCount(change, scope, textChanged, point, nextPoint) {
258
+ if (change?.logicalRevisionScope === scope) return change.logicalRevisionCount;
259
+ if (!textChanged) return 0;
260
+ if (!point) return 1;
261
+ return Math.max(1, nextPoint.textVersion - point.textVersion);
262
+ }
263
+ function sameSyncPoint(left, right) {
264
+ if (!left) return false;
265
+ return left.revision === right.revision && left.segment === right.segment && left.textVersion === right.textVersion;
266
+ }
267
+ function isSharedUriTransition(active, currentPoint, descriptor, nextPoint) {
268
+ if (!active || !currentPoint) return false;
269
+ if (active.textSnapshot !== descriptor.textSnapshot) return false;
270
+ if (currentPoint.revision !== nextPoint.revision) return false;
271
+ if (currentPoint.textVersion !== nextPoint.textVersion) return false;
272
+ return currentPoint.segment !== nextPoint.segment;
273
+ }
274
+ function activeDocument(descriptor, lspVersion) {
275
+ return {
276
+ uri: descriptor.uri,
277
+ languageId: descriptor.languageId,
278
+ textSnapshot: descriptor.textSnapshot,
279
+ lineStarts: descriptor.lineStarts,
280
+ textVersion: descriptor.textVersion,
281
+ lspVersion
282
+ };
283
+ }
284
+ function activeDocumentForTransition(active, transition) {
285
+ const document = transition.document;
286
+ return {
287
+ uri: document.uri,
288
+ languageId: document.languageId,
289
+ textSnapshot: document.textSnapshot,
290
+ lineStarts: document.lineStarts,
291
+ textVersion: active.textVersion,
292
+ lspVersion: document.version
293
+ };
294
+ }
295
+ function documentUri(snapshot, options) {
296
+ if (!snapshot.documentId) return null;
297
+ if (options.uriForDocument) return options.uriForDocument(snapshot);
298
+ return pathOrUriToDocumentUri(snapshot.documentId);
299
+ }
300
+ function documentDescriptor(snapshot, options, projectedUri, projectedTextSnapshot) {
301
+ if (!snapshot.languageId) return null;
302
+ if (options.shouldSyncLanguageId?.(snapshot.languageId, snapshot) === false) return null;
303
+ const resolvedUri = documentUri(snapshot, options);
304
+ if (resolvedUri === null) return null;
305
+ const uri = projectedUri ?? resolvedUri;
306
+ if (options.shouldSyncUri?.(uri, snapshot) === false) return null;
307
+ const document = viewDocumentSnapshot(snapshot);
308
+ return {
309
+ uri,
310
+ languageId: options.languageIdForDocument?.(snapshot.languageId, uri) ?? snapshot.languageId,
311
+ textSnapshot: projectedTextSnapshot ?? document.textSnapshot,
312
+ lineStarts: document.lineStarts,
313
+ textVersion: snapshot.textVersion
314
+ };
315
+ }
316
+ function activeDocumentForSnapshot(snapshot, options) {
317
+ const descriptor = documentDescriptor(snapshot, options);
318
+ return descriptor ? activeDocument(descriptor, 0) : null;
319
+ }
320
+ function publishDiagnosticsParams(params) {
321
+ if (!isRecord(params)) return null;
322
+ if (typeof params.uri !== "string") return null;
323
+ if (!Array.isArray(params.diagnostics)) return null;
324
+ return {
325
+ uri: params.uri,
326
+ version: typeof params.version === "number" ? params.version : null,
327
+ diagnostics: params.diagnostics
328
+ };
329
+ }
330
+ var isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
331
+ //#endregion
332
+ export { DocumentSync, activeDocumentForSnapshot };
333
+
334
+ //# sourceMappingURL=documentSync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"documentSync.js","names":[],"sources":["../src/documentSync.ts"],"sourcesContent":["import type { LanguageServerDocumentSnapshot } from './types'\nimport {\n type DocumentLogicalRevisionScope,\n type DocumentSyncPoint,\n type DocumentSyncSegment,\n type TextEdit,\n} from '@singapore-editor/core/document'\nimport type {\n EditorContributionChange,\n EditorViewContributionUpdateKind,\n} from '@singapore-editor/core/extensions'\nimport {\n recordLspPerformanceDiagnostic,\n type LspDocumentTransitionNotification,\n type LspTextDocumentSnapshot,\n type LspTextSnapshot,\n type LspWorkspaceDocumentAttachment,\n type LspWorkspace,\n} from '@singapore-editor/lsp'\nimport type * as lsp from 'vscode-languageserver-protocol'\n\nimport { projectDiagnosticsInSnapshot } from './diagnosticProjection'\nimport type { LanguageServerDocumentUriTransition } from './documentSyncController'\nimport { pathOrUriToDocumentUri } from './paths'\nimport type { ActiveDocument, DocumentDescriptor } from './pluginTypes'\nimport type { LanguageServerDocumentSyncOptions } from './types'\nimport { viewDocumentSnapshot } from './viewDocumentSnapshot'\n\n/** `result` came from the server; `reset` is the client emptying the list itself. */\nexport type DocumentSyncSummaryKind = 'result' | 'reset'\n\nexport type DocumentSyncDiagnosticsPresenter = {\n clear(): void\n render(document: LspTextDocumentSnapshot, diagnostics: readonly lsp.Diagnostic[]): void\n publishSummary(\n uri: lsp.DocumentUri,\n version: number | null,\n diagnostics: readonly lsp.Diagnostic[],\n kind: DocumentSyncSummaryKind,\n ): void\n}\n\nexport type DocumentSyncOptions = LanguageServerDocumentSyncOptions & {\n readonly logicalRevisionScope: DocumentLogicalRevisionScope\n onDocumentClosed(): void\n}\n\nexport class DocumentSync {\n private attachment: LspWorkspaceDocumentAttachment | null = null\n private document: ActiveDocument | null = null\n private diagnosticItems: readonly lsp.Diagnostic[] = []\n private readonly logicalRevisionScope: DocumentLogicalRevisionScope\n private pendingUriProjection: PendingUriProjection | null = null\n private syncPoint: DocumentSyncPoint | null = null\n\n public constructor(\n private readonly workspace: LspWorkspace,\n private readonly presenter: DocumentSyncDiagnosticsPresenter,\n private readonly options: DocumentSyncOptions,\n ) {\n this.logicalRevisionScope = options.logicalRevisionScope\n }\n\n public get activeDocument(): ActiveDocument | null {\n return this.document\n }\n\n public get diagnostics(): readonly lsp.Diagnostic[] {\n return this.diagnosticItems\n }\n\n public shouldSync(\n kind: EditorViewContributionUpdateKind,\n snapshot: LanguageServerDocumentSnapshot,\n ): boolean {\n if (kind === 'document' || kind === 'content' || kind === 'clear') return true\n if (!this.document) return false\n return !sameSyncPoint(this.syncPoint, snapshot.documentSyncPoint)\n }\n\n public sync(\n snapshot: LanguageServerDocumentSnapshot,\n change: EditorContributionChange | null,\n ): void {\n const projectedUri = this.projectedDocumentUri(snapshot)\n const descriptor = documentDescriptor(snapshot, this.options, projectedUri)\n if (!descriptor) {\n this.detachDocument()\n return\n }\n\n this.openOrUpdateDocument(descriptor, change, snapshot)\n }\n\n public close(): void {\n this.pendingUriProjection = null\n this.detachDocument()\n }\n\n public transitionDocumentUri(\n snapshot: LanguageServerDocumentSnapshot,\n transition: LanguageServerDocumentUriTransition,\n ): boolean {\n if (!this.matchesTransitionSource(snapshot, transition)) return false\n\n const descriptor = documentDescriptor(\n snapshot,\n this.options,\n transition.toUri,\n transition.textSnapshot,\n )\n if (!descriptor) {\n this.detachDocument()\n this.pendingUriProjection = pendingUriProjection(transition)\n return true\n }\n\n this.transitionDocument(descriptor, transition.syncPoint)\n return true\n }\n\n private detachDocument(): void {\n const active = this.document\n const attachment = this.attachment\n this.attachment = null\n this.document = null\n this.diagnosticItems = []\n this.syncPoint = null\n this.options.onDocumentClosed()\n if (!active) return\n\n this.presenter.clear()\n if (attachment) this.workspace.closeDocument(attachment)\n this.presenter.publishSummary(active.uri, active.lspVersion, [], 'reset')\n }\n\n private matchesTransitionSource(\n snapshot: LanguageServerDocumentSnapshot,\n transition: LanguageServerDocumentUriTransition,\n ): boolean {\n const active = this.document\n const point = this.syncPoint\n if (!active || !this.attachment || !point) return false\n if (active.uri !== transition.fromUri) return false\n if (active.textSnapshot !== transition.textSnapshot) return false\n if (snapshot.textSnapshot !== transition.textSnapshot) return false\n if (point.revision !== transition.syncPoint.revision) return false\n if (point.textVersion !== transition.syncPoint.textVersion) return false\n return point.segment !== transition.syncPoint.segment\n }\n\n private projectedDocumentUri(\n snapshot: LanguageServerDocumentSnapshot,\n ): lsp.DocumentUri | undefined {\n const projection = this.pendingUriProjection\n if (!projection) return undefined\n if (snapshot.documentSyncPoint.segment !== projection.segment) {\n this.pendingUriProjection = null\n return undefined\n }\n const uri = documentUri(snapshot, this.options)\n if (uri === null) {\n this.pendingUriProjection = null\n return undefined\n }\n\n if (uri === projection.fromUri) return projection.toUri\n this.pendingUriProjection = null\n return undefined\n }\n\n public publishDiagnostics(params: unknown): void {\n const diagnostics = publishDiagnosticsParams(params)\n if (!diagnostics) return\n\n const active = this.document\n if (!active) return\n if (diagnostics.uri !== active.uri) return\n if (diagnostics.version !== null && diagnostics.version !== active.lspVersion) return\n\n this.replaceDiagnostics(active, diagnostics.version, diagnostics.diagnostics)\n }\n\n public pullDiagnostics(\n uri: lsp.DocumentUri,\n version: number,\n diagnostics: readonly lsp.Diagnostic[],\n ): void {\n const active = this.document\n if (!active || active.uri !== uri || active.lspVersion !== version) return\n\n this.replaceDiagnostics(active, version, diagnostics)\n }\n\n public clearDiagnostics(): void {\n const active = this.document\n this.diagnosticItems = []\n this.presenter.clear()\n if (!active) return\n\n this.presenter.publishSummary(active.uri, active.lspVersion, [], 'reset')\n }\n\n private openOrUpdateDocument(\n descriptor: DocumentDescriptor,\n change: EditorContributionChange | null,\n snapshot: LanguageServerDocumentSnapshot,\n ): void {\n const active = this.document\n if (!active) {\n this.openDocument(descriptor, snapshot.documentSyncPoint)\n return\n }\n\n if (active.uri !== descriptor.uri) {\n this.replaceOrTransitionDocument(descriptor, snapshot.documentSyncPoint)\n return\n }\n if (active.languageId !== descriptor.languageId) {\n this.openDocument(descriptor, snapshot.documentSyncPoint)\n return\n }\n if (sameSyncPoint(this.syncPoint, snapshot.documentSyncPoint)) return\n this.updateDocument(descriptor, change, snapshot)\n }\n\n private replaceDiagnostics(\n active: ActiveDocument,\n version: number | null,\n diagnostics: readonly lsp.Diagnostic[],\n ): void {\n this.diagnosticItems = diagnostics\n this.presenter.render(active, diagnostics)\n this.presenter.publishSummary(active.uri, version, diagnostics, 'result')\n }\n\n private openDocument(descriptor: DocumentDescriptor, syncPoint: DocumentSyncPoint): void {\n this.close()\n const result = this.workspace.openDocumentSnapshot({\n uri: descriptor.uri,\n languageId: descriptor.languageId,\n textSnapshot: descriptor.textSnapshot,\n lineStarts: descriptor.lineStarts,\n sourceRevision: syncPoint.revision,\n sourceSegment: syncPoint.segment,\n onDocumentTransition: (transition) => this.adoptDocumentTransition(transition),\n })\n this.attachment = result.attachment\n this.document = activeDocument(descriptor, result.document.version)\n this.syncPoint = syncPoint\n }\n\n private replaceOrTransitionDocument(\n descriptor: DocumentDescriptor,\n syncPoint: DocumentSyncPoint,\n ): void {\n if (!isSharedUriTransition(this.document, this.syncPoint, descriptor, syncPoint)) {\n this.openDocument(descriptor, syncPoint)\n return\n }\n this.transitionDocument(descriptor, syncPoint)\n }\n\n private transitionDocument(descriptor: DocumentDescriptor, syncPoint: DocumentSyncPoint): void {\n const attachment = this.attachment\n if (!attachment) throw new Error('An active LSP document must retain its workspace attachment.')\n\n const result = this.workspace.transitionDocumentUri(attachment, {\n uri: descriptor.uri,\n languageId: descriptor.languageId,\n textSnapshot: descriptor.textSnapshot,\n lineStarts: descriptor.lineStarts,\n sourceRevision: syncPoint.revision,\n sourceSegment: syncPoint.segment,\n sourceTextVersion: syncPoint.textVersion,\n })\n this.document = activeDocument(descriptor, result.document.version)\n this.syncPoint = syncPoint\n }\n\n private updateDocument(\n descriptor: DocumentDescriptor,\n change: EditorContributionChange | null,\n snapshot: LanguageServerDocumentSnapshot,\n ): void {\n const active = this.document\n const diagnostics = projectDiagnosticsInSnapshot(this.diagnosticItems, {\n previousDocument: active ?? descriptor,\n nextDocument: descriptor,\n change,\n })\n const changes = changesSinceLastSync(\n snapshot,\n this.syncPoint,\n this.logicalRevisionScope,\n change,\n active?.textSnapshot ?? descriptor.textSnapshot,\n descriptor.textSnapshot,\n )\n recordLspPerformanceDiagnostic('lsp.documentSync.editChain', {\n chained: changes.edits === null ? 'null' : changes.edits.length,\n logicalRevisionCount: changes.logicalRevisionCount,\n activeTextVersion: active?.textVersion ?? -1,\n snapshotTextVersion: snapshot.textVersion,\n changeEditCount: change?.edits.length ?? -1,\n })\n const document = this.synchronizeWorkspaceDocument(descriptor, changes)\n this.document = activeDocument(descriptor, document.version)\n this.syncPoint = changes.syncPointAfter\n if (diagnostics === this.diagnosticItems) return\n\n this.diagnosticItems = diagnostics\n this.presenter.render(descriptor, diagnostics)\n }\n\n private synchronizeWorkspaceDocument(\n descriptor: DocumentDescriptor,\n changes: SyncChanges,\n ): ReturnType<LspWorkspace['updateDocumentSnapshot']> {\n const source = {\n textSnapshot: descriptor.textSnapshot,\n lineStarts: descriptor.lineStarts,\n sourceRevision: changes.syncPointAfter.revision,\n sourceSegment: changes.syncPointAfter.segment,\n }\n if (changes.logicalRevisionCount === 0) {\n return this.workspace.adoptUnchangedDocumentSource(descriptor.uri, source)\n }\n\n return this.workspace.updateDocumentSnapshot(descriptor.uri, {\n ...source,\n edits: changes.edits,\n logicalRevisionCount: changes.logicalRevisionCount,\n })\n }\n\n private adoptDocumentTransition(transition: LspDocumentTransitionNotification): void {\n const active = this.document\n if (!active) return\n\n this.diagnosticItems = []\n this.presenter.clear()\n this.presenter.publishSummary(active.uri, active.lspVersion, [], 'reset')\n this.pendingUriProjection = {\n fromUri: active.uri,\n toUri: transition.document.uri,\n segment: transition.sourceSegment as DocumentSyncSegment,\n }\n this.document = activeDocumentForTransition(active, transition)\n this.syncPoint = {\n revision: transition.sourceRevision,\n segment: transition.sourceSegment as DocumentSyncSegment,\n textVersion: transition.sourceTextVersion,\n }\n }\n}\n\ntype PendingUriProjection = {\n readonly fromUri: lsp.DocumentUri\n readonly toUri: lsp.DocumentUri\n readonly segment: DocumentSyncSegment\n}\n\nfunction pendingUriProjection(\n transition: LanguageServerDocumentUriTransition,\n): PendingUriProjection {\n return {\n fromUri: transition.fromUri,\n toUri: transition.toUri,\n segment: transition.syncPoint.segment,\n }\n}\n\ntype SyncChanges = {\n readonly edits: readonly TextEdit[] | null\n readonly logicalRevisionCount: number\n readonly syncPointAfter: DocumentSyncPoint\n}\n\nfunction changesSinceLastSync(\n snapshot: LanguageServerDocumentSnapshot,\n point: DocumentSyncPoint | null,\n scope: DocumentLogicalRevisionScope,\n change: EditorContributionChange | null,\n previousTextSnapshot: LspTextSnapshot,\n nextTextSnapshot: LspTextSnapshot,\n): SyncChanges {\n if (!point) {\n return fallbackSyncChanges(\n snapshot,\n null,\n change,\n scope,\n previousTextSnapshot,\n nextTextSnapshot,\n )\n }\n\n const changes = snapshot.changesSinceDocumentSyncPoint(point, scope)\n if (changes) {\n return {\n edits: changes.edits,\n logicalRevisionCount: changes.logicalRevisionCount,\n syncPointAfter: changes.syncPointAfter,\n }\n }\n return fallbackSyncChanges(snapshot, point, change, scope, previousTextSnapshot, nextTextSnapshot)\n}\n\nfunction fallbackSyncChanges(\n snapshot: LanguageServerDocumentSnapshot,\n point: DocumentSyncPoint | null,\n change: EditorContributionChange | null,\n scope: DocumentLogicalRevisionScope,\n previousTextSnapshot: LspTextSnapshot,\n nextTextSnapshot: LspTextSnapshot,\n): SyncChanges {\n const nextPoint = snapshot.documentSyncPoint\n const textChanged =\n previousTextSnapshot !== nextTextSnapshot ||\n point === null ||\n point.textVersion !== nextPoint.textVersion\n return {\n edits: null,\n logicalRevisionCount: fallbackLogicalRevisionCount(\n change,\n scope,\n textChanged,\n point,\n nextPoint,\n ),\n syncPointAfter: nextPoint,\n }\n}\n\nfunction fallbackLogicalRevisionCount(\n change: EditorContributionChange | null,\n scope: DocumentLogicalRevisionScope,\n textChanged: boolean,\n point: DocumentSyncPoint | null,\n nextPoint: DocumentSyncPoint,\n): number {\n if (change?.logicalRevisionScope === scope) return change.logicalRevisionCount\n if (!textChanged) return 0\n if (!point) return 1\n return Math.max(1, nextPoint.textVersion - point.textVersion)\n}\n\nfunction sameSyncPoint(left: DocumentSyncPoint | null, right: DocumentSyncPoint): boolean {\n if (!left) return false\n return (\n left.revision === right.revision &&\n left.segment === right.segment &&\n left.textVersion === right.textVersion\n )\n}\n\nfunction isSharedUriTransition(\n active: ActiveDocument | null,\n currentPoint: DocumentSyncPoint | null,\n descriptor: DocumentDescriptor,\n nextPoint: DocumentSyncPoint,\n): boolean {\n if (!active || !currentPoint) return false\n if (active.textSnapshot !== descriptor.textSnapshot) return false\n if (currentPoint.revision !== nextPoint.revision) return false\n if (currentPoint.textVersion !== nextPoint.textVersion) return false\n return currentPoint.segment !== nextPoint.segment\n}\n\nfunction activeDocument(descriptor: DocumentDescriptor, lspVersion: number): ActiveDocument {\n return {\n uri: descriptor.uri,\n languageId: descriptor.languageId,\n textSnapshot: descriptor.textSnapshot,\n lineStarts: descriptor.lineStarts,\n textVersion: descriptor.textVersion,\n lspVersion,\n }\n}\n\nfunction activeDocumentForTransition(\n active: ActiveDocument,\n transition: LspDocumentTransitionNotification,\n): ActiveDocument {\n const document = transition.document\n return {\n uri: document.uri,\n languageId: document.languageId,\n textSnapshot: document.textSnapshot,\n lineStarts: document.lineStarts,\n textVersion: active.textVersion,\n lspVersion: document.version,\n }\n}\n\nfunction documentUri(\n snapshot: LanguageServerDocumentSnapshot,\n options: LanguageServerDocumentSyncOptions,\n): lsp.DocumentUri | null {\n if (!snapshot.documentId) return null\n if (options.uriForDocument) return options.uriForDocument(snapshot)\n return pathOrUriToDocumentUri(snapshot.documentId)\n}\n\nfunction documentDescriptor(\n snapshot: LanguageServerDocumentSnapshot,\n options: LanguageServerDocumentSyncOptions,\n projectedUri?: lsp.DocumentUri,\n projectedTextSnapshot?: LspTextSnapshot,\n): DocumentDescriptor | null {\n if (!snapshot.languageId) return null\n if (options.shouldSyncLanguageId?.(snapshot.languageId, snapshot) === false) return null\n\n const resolvedUri = documentUri(snapshot, options)\n if (resolvedUri === null) return null\n const uri = projectedUri ?? resolvedUri\n if (options.shouldSyncUri?.(uri, snapshot) === false) return null\n\n const document = viewDocumentSnapshot(snapshot)\n return {\n uri,\n // `shouldSyncLanguageId` above still filters on the view's id, not this one.\n languageId: options.languageIdForDocument?.(snapshot.languageId, uri) ?? snapshot.languageId,\n textSnapshot: projectedTextSnapshot ?? document.textSnapshot,\n lineStarts: document.lineStarts,\n textVersion: snapshot.textVersion,\n }\n}\n\nexport function activeDocumentForSnapshot(\n snapshot: LanguageServerDocumentSnapshot,\n options: LanguageServerDocumentSyncOptions,\n): ActiveDocument | null {\n const descriptor = documentDescriptor(snapshot, options)\n return descriptor ? activeDocument(descriptor, 0) : null\n}\n\nfunction publishDiagnosticsParams(params: unknown): {\n readonly uri: lsp.DocumentUri\n readonly version: number | null\n readonly diagnostics: readonly lsp.Diagnostic[]\n} | null {\n if (!isRecord(params)) return null\n if (typeof params.uri !== 'string') return null\n if (!Array.isArray(params.diagnostics)) return null\n\n return {\n uri: params.uri,\n version: typeof params.version === 'number' ? params.version : null,\n diagnostics: params.diagnostics as lsp.Diagnostic[],\n }\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n"],"mappings":"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"}