@kerebron/extension-lsp 0.7.8 → 0.8.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 (46) hide show
  1. package/esm/ExtensionLsp.d.ts +2 -6
  2. package/esm/ExtensionLsp.d.ts.map +1 -1
  3. package/esm/ExtensionLsp.js +44 -36
  4. package/esm/ExtensionLsp.js.map +1 -1
  5. package/esm/LSPClient.d.ts +5 -4
  6. package/esm/LSPClient.d.ts.map +1 -1
  7. package/esm/LSPClient.js +14 -5
  8. package/esm/LSPClient.js.map +1 -1
  9. package/esm/LSPPlugin.d.ts +38 -0
  10. package/esm/LSPPlugin.d.ts.map +1 -0
  11. package/esm/LSPPlugin.js +190 -0
  12. package/esm/LSPPlugin.js.map +1 -0
  13. package/esm/{LspWebSocketTransport.d.ts → LSPWebSocketTransport.d.ts} +2 -2
  14. package/esm/{LspWebSocketTransport.d.ts.map → LSPWebSocketTransport.d.ts.map} +1 -1
  15. package/esm/{LspWebSocketTransport.js → LSPWebSocketTransport.js} +2 -2
  16. package/esm/{LspWebSocketTransport.js.map → LSPWebSocketTransport.js.map} +1 -1
  17. package/esm/LSPWorkspace.d.ts +39 -0
  18. package/esm/LSPWorkspace.d.ts.map +1 -0
  19. package/esm/LSPWorkspace.js +118 -0
  20. package/esm/LSPWorkspace.js.map +1 -0
  21. package/esm/createLspAutocomplete.d.ts +3 -9
  22. package/esm/createLspAutocomplete.d.ts.map +1 -1
  23. package/esm/createLspAutocomplete.js +4 -5
  24. package/esm/createLspAutocomplete.js.map +1 -1
  25. package/esm/mod.d.ts +1 -1
  26. package/esm/mod.d.ts.map +1 -1
  27. package/esm/mod.js +1 -1
  28. package/esm/mod.js.map +1 -1
  29. package/esm/workspace.d.ts +6 -35
  30. package/esm/workspace.d.ts.map +1 -1
  31. package/esm/workspace.js +3 -98
  32. package/esm/workspace.js.map +1 -1
  33. package/package.json +6 -6
  34. package/src/ExtensionLsp.ts +47 -47
  35. package/src/LSPClient.ts +21 -13
  36. package/src/LSPPlugin.ts +323 -0
  37. package/src/{LspWebSocketTransport.ts → LSPWebSocketTransport.ts} +1 -1
  38. package/src/LSPWorkspace.ts +172 -0
  39. package/src/createLspAutocomplete.ts +10 -7
  40. package/src/mod.ts +1 -1
  41. package/src/workspace.ts +8 -147
  42. package/esm/DiagnosticPlugin.d.ts +0 -32
  43. package/esm/DiagnosticPlugin.d.ts.map +0 -1
  44. package/esm/DiagnosticPlugin.js +0 -117
  45. package/esm/DiagnosticPlugin.js.map +0 -1
  46. package/src/DiagnosticPlugin.ts +0 -196
package/src/workspace.ts CHANGED
@@ -1,13 +1,7 @@
1
- import type * as lsp from 'vscode-languageserver-protocol';
2
- import { TextDocumentSyncKind } from 'vscode-languageserver-protocol';
3
-
4
1
  import type { EditorUi } from '@kerebron/editor';
5
-
6
- import { LSPClient } from './LSPClient.js';
7
2
  import { PositionMapper } from '@kerebron/extension-markdown/PositionMapper';
8
- import { computeIncrementalChanges } from './computeIncrementalChanges.js';
9
3
 
10
- export interface LspSource {
4
+ export interface LSPSource {
11
5
  ui: EditorUi;
12
6
  getMappedContent(): Promise<{ content: string; mapper: PositionMapper }>;
13
7
  }
@@ -17,50 +11,38 @@ export interface WorkspaceFile {
17
11
  languageId: string;
18
12
  version: number;
19
13
  content: string;
20
- source: LspSource;
14
+ source: LSPSource;
21
15
  getUi(): EditorUi | undefined;
22
16
  mapper: PositionMapper;
23
17
  }
24
18
 
25
- interface WorkspaceFileUpdate {
26
- file: WorkspaceFile;
27
- prevDoc: string;
28
- changes: lsp.TextDocumentContentChangeEvent[];
29
- }
30
-
31
- export abstract class Workspace {
19
+ export abstract class Workspace extends EventTarget {
32
20
  abstract files: WorkspaceFile[];
33
21
  protected isConnected = false;
34
22
 
35
- constructor(
36
- readonly client: LSPClient,
37
- ) {}
23
+ constructor() {
24
+ super();
25
+ }
38
26
 
39
27
  getFile(uri: string): WorkspaceFile | null {
40
28
  return this.files.find((f) => f.uri == uri) || null;
41
29
  }
42
30
 
43
- abstract syncFiles(): readonly WorkspaceFileUpdate[];
31
+ abstract syncFiles(): void;
44
32
 
45
33
  requestFile(uri: string): Promise<WorkspaceFile | null> {
46
34
  return Promise.resolve(this.getFile(uri));
47
35
  }
48
36
 
49
- abstract openFile(uri: string, languageId: string, source: LspSource): void;
37
+ abstract openFile(uri: string, languageId: string, source: LSPSource): void;
50
38
  abstract changedFile(uri: string): void;
51
39
  abstract closeFile(uri: string): void;
52
40
 
53
41
  async connected(): Promise<void> {
54
42
  this.isConnected = true;
55
- for await (const file of this.files) {
56
- const result = await this.client.didOpen(file);
57
- }
58
43
  }
59
44
 
60
45
  disconnected(): void {
61
- for (const file of this.files) {
62
- this.client.workspace.closeFile(file.uri);
63
- }
64
46
  this.isConnected = false;
65
47
  }
66
48
 
@@ -69,124 +51,3 @@ export abstract class Workspace {
69
51
  return Promise.resolve(file ? file.getUi() : undefined);
70
52
  }
71
53
  }
72
-
73
- class DefaultWorkspaceFile implements WorkspaceFile {
74
- public syncedContent: string = '';
75
- constructor(
76
- readonly uri: string,
77
- readonly languageId: string,
78
- public version: number,
79
- public content: string,
80
- public mapper: PositionMapper,
81
- public source: LspSource,
82
- ) {
83
- }
84
-
85
- getUi() {
86
- return this.source.ui;
87
- }
88
- }
89
-
90
- export class DefaultWorkspace extends Workspace {
91
- files: DefaultWorkspaceFile[] = [];
92
- private fileVersions: { [uri: string]: number } = Object.create(null);
93
-
94
- nextFileVersion(uri: string) {
95
- return this.fileVersions[uri] = (this.fileVersions[uri] ?? -1) + 1;
96
- }
97
-
98
- syncFiles() {
99
- if (!this.client.supportSync) {
100
- return [];
101
- }
102
-
103
- const result: WorkspaceFileUpdate[] = [];
104
- for (const file of this.files) {
105
- this.changedFile(file.uri);
106
- }
107
-
108
- return result;
109
- }
110
-
111
- async changedFile(uri: string) {
112
- const file = this.files.find((f) => f.uri == uri) || null;
113
-
114
- if (file) {
115
- const { content, mapper } = await file.source.getMappedContent();
116
-
117
- if (!this.isConnected) {
118
- file.content = content;
119
- file.mapper = mapper;
120
- return;
121
- }
122
-
123
- if (
124
- await this.client.notification<lsp.DidChangeTextDocumentParams>(
125
- 'textDocument/didChange',
126
- {
127
- textDocument: { uri: file.uri, version: file.version },
128
- contentChanges: contentChangesFor(
129
- file,
130
- content,
131
- mapper,
132
- this.client.supportSync == TextDocumentSyncKind.Incremental,
133
- ),
134
- },
135
- )
136
- ) {
137
- file.syncedContent = file.content;
138
- file.content = content;
139
- file.mapper = mapper;
140
- file.version = this.nextFileVersion(file.uri);
141
- }
142
- }
143
- }
144
-
145
- async openFile(uri: string, languageId: string, source: LspSource) {
146
- // if (uri) {}
147
-
148
- if (this.getFile(uri)) {
149
- this.closeFile(uri);
150
- }
151
-
152
- const mappedContent = await source.getMappedContent();
153
- const { content, mapper } = mappedContent;
154
- const file = new DefaultWorkspaceFile(
155
- uri,
156
- languageId,
157
- this.nextFileVersion(uri),
158
- content,
159
- mapper,
160
- source,
161
- );
162
- this.files.push(file);
163
-
164
- this.client.didOpen(file);
165
- }
166
-
167
- closeFile(uri: string) {
168
- const file = this.getFile(uri);
169
- if (file) {
170
- this.files = this.files.filter((f) => f.uri !== uri);
171
- this.client.didClose(uri);
172
- }
173
- }
174
- }
175
-
176
- const enum Sync {
177
- AlwaysIfSmaller = 1024,
178
- }
179
-
180
- function contentChangesFor(
181
- file: WorkspaceFile,
182
- newContent: string,
183
- mapper: PositionMapper,
184
- supportInc: boolean,
185
- ): lsp.TextDocumentContentChangeEvent[] {
186
- if (!supportInc || newContent.length < Sync.AlwaysIfSmaller) {
187
- return [{ text: newContent }];
188
- }
189
-
190
- const changes = computeIncrementalChanges(file.content, newContent);
191
- return changes.reverse();
192
- }
@@ -1,32 +0,0 @@
1
- import { Plugin } from 'prosemirror-state';
2
- import { ExtensionLsp } from './ExtensionLsp.js';
3
- import { PositionMapper } from '@kerebron/extension-markdown/PositionMapper';
4
- interface LspRange {
5
- line: number;
6
- character: number;
7
- }
8
- interface DiagnosticsItem {
9
- severity: number;
10
- range: {
11
- start: LspRange;
12
- end: LspRange;
13
- };
14
- message: string;
15
- source: string;
16
- code: string;
17
- data: any;
18
- }
19
- interface DiagnosticPluginState {
20
- diagnostics: DiagnosticsItem[];
21
- mapper?: PositionMapper;
22
- }
23
- interface DiagnosticConfig {
24
- }
25
- export declare class DiagnosticPlugin extends Plugin<DiagnosticPluginState> {
26
- diagListener: ((event: Event) => void) | undefined;
27
- listenerDisconnect: ((event: Event) => void) | undefined;
28
- listenerChange: ((event: Event) => void) | undefined;
29
- constructor(config: DiagnosticConfig, extension: ExtensionLsp);
30
- }
31
- export {};
32
- //# sourceMappingURL=DiagnosticPlugin.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DiagnosticPlugin.d.ts","sourceRoot":"","sources":["../src/DiagnosticPlugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAA0B,MAAM,mBAAmB,CAAC;AAEnE,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,6CAA6C,CAAC;AAE7E,UAAU,QAAQ;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE;QACL,KAAK,EAAE,QAAQ,CAAC;QAChB,GAAG,EAAE,QAAQ,CAAC;KACf,CAAC;IACF,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,GAAG,CAAC;CACX;AAED,UAAU,qBAAqB;IAC7B,WAAW,EAAE,eAAe,EAAE,CAAC;IAC/B,MAAM,CAAC,EAAE,cAAc,CAAC;CACzB;AAED,UAAU,gBAAgB;CACzB;AAID,qBAAa,gBAAiB,SAAQ,MAAM,CAAC,qBAAqB,CAAC;IACjE,YAAY,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACnD,kBAAkB,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;IACzD,cAAc,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC,GAAG,SAAS,CAAC;gBAEzC,MAAM,EAAE,gBAAgB,EAAE,SAAS,EAAE,YAAY;CA8J9D"}
@@ -1,117 +0,0 @@
1
- import { Plugin, PluginKey } from 'prosemirror-state';
2
- import { Decoration, DecorationSet } from 'prosemirror-view';
3
- const DiagnosticPluginKey = new PluginKey('lsp-diagnostic');
4
- export class DiagnosticPlugin extends Plugin {
5
- diagListener;
6
- listenerDisconnect;
7
- listenerChange;
8
- constructor(config, extension) {
9
- super({
10
- key: DiagnosticPluginKey,
11
- view(view) {
12
- return {
13
- destroy: () => {
14
- const client = extension.getClient(extension.mainLang);
15
- if (this.listener && client) {
16
- client.removeEventListener('textDocument/publishDiagnostics', this.listener);
17
- }
18
- if (this.listenerDisconnect && client) {
19
- client.removeEventListener('close', this.listenerDisconnect);
20
- }
21
- if (this.changeListener) {
22
- extension.getEditor().removeEventListener('change', this.changeListener);
23
- }
24
- },
25
- };
26
- },
27
- state: {
28
- init() {
29
- return {
30
- diagnostics: [],
31
- };
32
- },
33
- apply(tr, prev, oldState, newState) {
34
- const next = { ...prev };
35
- const meta = tr.getMeta(DiagnosticPluginKey);
36
- if (meta?.diagnostics) {
37
- next.diagnostics = meta.diagnostics;
38
- }
39
- if (meta?.mapper) {
40
- next.mapper = meta.mapper;
41
- }
42
- return next;
43
- },
44
- },
45
- props: {
46
- decorations(state) {
47
- const decorations = [];
48
- const pluginState = this.getState(state);
49
- if (pluginState) {
50
- const { diagnostics, mapper } = pluginState;
51
- if (mapper) {
52
- for (const diag of diagnostics) {
53
- const from = mapper.fromLineChar(diag.range.start.line, diag.range.start.character);
54
- const end = mapper.fromLineChar(diag.range.end.line, diag.range.end.character);
55
- if (from > -1 && end > -1) {
56
- const decoration = Decoration.inline(from, end, { class: 'kb-lsp__error', title: diag.message });
57
- decorations.push(decoration);
58
- }
59
- }
60
- }
61
- }
62
- return DecorationSet.create(state.doc, decorations);
63
- },
64
- },
65
- });
66
- let lastDiag = 0;
67
- const editor = extension.getEditor();
68
- const uri = editor.config.uri;
69
- if (uri) {
70
- const client = extension.getClient(extension.mainLang);
71
- this.diagListener = (event) => {
72
- const detail = event.detail;
73
- if (detail.params.uri !== uri) {
74
- return;
75
- }
76
- event.preventDefault();
77
- lastDiag = +Date();
78
- if (client) {
79
- const file = client.workspace.getFile(uri);
80
- if (file) {
81
- const { mapper } = file;
82
- const tr = editor.view.state.tr.setMeta(DiagnosticPluginKey, {
83
- diagnostics: detail.params.diagnostics,
84
- mapper,
85
- });
86
- editor.view.dispatch(tr);
87
- }
88
- }
89
- };
90
- if (client) {
91
- client.addEventListener('textDocument/publishDiagnostics', this.diagListener);
92
- }
93
- this.listenerDisconnect = (event) => {
94
- const tr = editor.view.state.tr.setMeta(DiagnosticPluginKey, {
95
- diagnostics: [],
96
- mapper: undefined,
97
- });
98
- editor.view.dispatch(tr);
99
- };
100
- if (client) {
101
- client.addEventListener('close', this.listenerDisconnect);
102
- }
103
- this.listenerChange = (event) => {
104
- if (lastDiag === 0 && +Date() - lastDiag > 10_1000) {
105
- return;
106
- }
107
- const tr = editor.view.state.tr.setMeta(DiagnosticPluginKey, {
108
- diagnostics: [],
109
- mapper: undefined,
110
- });
111
- editor.view.dispatch(tr);
112
- };
113
- // extension.getEditor().addEventListener('changed', this.listenerChange);
114
- }
115
- }
116
- }
117
- //# sourceMappingURL=DiagnosticPlugin.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"DiagnosticPlugin.js","sourceRoot":"","sources":["../src/DiagnosticPlugin.ts"],"names":[],"mappings":"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"}
@@ -1,196 +0,0 @@
1
- import { Plugin, PluginKey, Transaction } from 'prosemirror-state';
2
- import { Decoration, DecorationSet, EditorView } from 'prosemirror-view';
3
- import { ExtensionLsp } from './ExtensionLsp.js';
4
- import { PositionMapper } from '@kerebron/extension-markdown/PositionMapper';
5
-
6
- interface LspRange {
7
- line: number;
8
- character: number;
9
- }
10
-
11
- interface DiagnosticsItem {
12
- severity: number;
13
- range: {
14
- start: LspRange;
15
- end: LspRange;
16
- };
17
- message: string;
18
- source: string;
19
- code: string;
20
- data: any; // "data":{"kind":"todo","keyword":"TODO"}},
21
- }
22
-
23
- interface DiagnosticPluginState {
24
- diagnostics: DiagnosticsItem[];
25
- mapper?: PositionMapper;
26
- }
27
-
28
- interface DiagnosticConfig {
29
- }
30
-
31
- const DiagnosticPluginKey = new PluginKey('lsp-diagnostic');
32
-
33
- export class DiagnosticPlugin extends Plugin<DiagnosticPluginState> {
34
- diagListener: ((event: Event) => void) | undefined;
35
- listenerDisconnect: ((event: Event) => void) | undefined;
36
- listenerChange: ((event: Event) => void) | undefined;
37
-
38
- constructor(config: DiagnosticConfig, extension: ExtensionLsp) {
39
- super({
40
- key: DiagnosticPluginKey,
41
- view(view) {
42
- return {
43
- destroy: () => {
44
- const client = extension.getClient(extension.mainLang);
45
-
46
- if (this.listener && client) {
47
- client.removeEventListener(
48
- 'textDocument/publishDiagnostics',
49
- this.listener,
50
- );
51
- }
52
- if (this.listenerDisconnect && client) {
53
- client.removeEventListener(
54
- 'close',
55
- this.listenerDisconnect,
56
- );
57
- }
58
- if (this.changeListener) {
59
- extension.getEditor().removeEventListener(
60
- 'change',
61
- this.changeListener,
62
- );
63
- }
64
- },
65
- };
66
- },
67
- state: {
68
- init() {
69
- return {
70
- diagnostics: [],
71
- };
72
- },
73
- apply(
74
- tr: Transaction,
75
- prev: DiagnosticPluginState,
76
- oldState,
77
- newState,
78
- ) {
79
- const next = { ...prev };
80
-
81
- const meta = tr.getMeta(DiagnosticPluginKey);
82
- if (meta?.diagnostics) {
83
- next.diagnostics = meta.diagnostics;
84
- }
85
- if (meta?.mapper) {
86
- next.mapper = meta.mapper;
87
- }
88
-
89
- return next;
90
- },
91
- },
92
- props: {
93
- decorations(state) {
94
- const decorations: Decoration[] = [];
95
-
96
- const pluginState = this.getState(state);
97
- if (pluginState) {
98
- const { diagnostics, mapper } = pluginState;
99
-
100
- if (mapper) {
101
- for (const diag of diagnostics) {
102
- const from = mapper.fromLineChar(
103
- diag.range.start.line,
104
- diag.range.start.character,
105
- );
106
- const end = mapper.fromLineChar(
107
- diag.range.end.line,
108
- diag.range.end.character,
109
- );
110
-
111
- if (from > -1 && end > -1) {
112
- const decoration = Decoration.inline(
113
- from,
114
- end,
115
- { class: 'kb-lsp__error', title: diag.message },
116
- );
117
- decorations.push(decoration);
118
- }
119
- }
120
- }
121
- }
122
-
123
- return DecorationSet.create(state.doc, decorations);
124
- },
125
- },
126
- });
127
-
128
- let lastDiag = 0;
129
-
130
- const editor = extension.getEditor();
131
-
132
- const uri = editor.config.uri;
133
- if (uri) {
134
- const client = extension.getClient(extension.mainLang);
135
-
136
- this.diagListener = (event: Event) => {
137
- const detail = (event as CustomEvent).detail;
138
- if (detail.params.uri !== uri) {
139
- return;
140
- }
141
-
142
- event.preventDefault();
143
-
144
- lastDiag = +Date();
145
-
146
- if (client) {
147
- const file = client.workspace.getFile(uri);
148
- if (file) {
149
- const { mapper } = file;
150
-
151
- const tr = editor.view.state.tr.setMeta(DiagnosticPluginKey, {
152
- diagnostics: detail.params.diagnostics,
153
- mapper,
154
- });
155
- editor.view.dispatch(tr);
156
- }
157
- }
158
- };
159
-
160
- if (client) {
161
- client.addEventListener(
162
- 'textDocument/publishDiagnostics',
163
- this.diagListener,
164
- );
165
- }
166
-
167
- this.listenerDisconnect = (event: Event) => {
168
- const tr = editor.view.state.tr.setMeta(DiagnosticPluginKey, {
169
- diagnostics: [],
170
- mapper: undefined,
171
- });
172
- editor.view.dispatch(tr);
173
- };
174
-
175
- if (client) {
176
- client.addEventListener(
177
- 'close',
178
- this.listenerDisconnect,
179
- );
180
- }
181
-
182
- this.listenerChange = (event: Event) => {
183
- if (lastDiag === 0 && +Date() - lastDiag > 10_1000) {
184
- return;
185
- }
186
- const tr = editor.view.state.tr.setMeta(DiagnosticPluginKey, {
187
- diagnostics: [],
188
- mapper: undefined,
189
- });
190
- editor.view.dispatch(tr);
191
- };
192
-
193
- // extension.getEditor().addEventListener('changed', this.listenerChange);
194
- }
195
- }
196
- }