ts-const-value-transformer 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,234 @@
1
+ // @internal
2
+ import * as console from 'console';
3
+ // @internal
4
+ import { SyncChildProcess } from 'sync-child-process';
5
+ export default class SyncLspClient {
6
+ /** process */
7
+ _p;
8
+ _id;
9
+ /** received data */
10
+ _r;
11
+ /** server message handlers */
12
+ _s;
13
+ /** notification handlers */
14
+ _n;
15
+ /** last buffer */
16
+ _l;
17
+ /** encoding */
18
+ _e;
19
+ constructor(command, argv, encoding = 'utf8') {
20
+ this._p = new SyncChildProcess(command, argv);
21
+ this._id = 0;
22
+ this._r = [];
23
+ this._s = [];
24
+ this._n = [];
25
+ this._e = encoding;
26
+ }
27
+ sendRaw(jsonRpc) {
28
+ const jsonRpcStr = JSON.stringify(jsonRpc);
29
+ // console.log(`sending: ${jsonRpcStr}`);
30
+ const contentLength = Buffer.from(jsonRpcStr, this._e).byteLength;
31
+ this._p.stdin.write(`Content-Length: ${contentLength}\r\n\r\n${jsonRpcStr}`);
32
+ }
33
+ sendMessage(method, params) {
34
+ const id = this._id++;
35
+ const jsonRpcRequest = {
36
+ jsonrpc: '2.0',
37
+ id,
38
+ method,
39
+ };
40
+ if (params) {
41
+ jsonRpcRequest.params = params;
42
+ }
43
+ this.sendRaw(jsonRpcRequest);
44
+ return id;
45
+ }
46
+ notifyMessage(method, params) {
47
+ const jsonRpcRequest = {
48
+ jsonrpc: '2.0',
49
+ method,
50
+ };
51
+ if (params) {
52
+ jsonRpcRequest.params = params;
53
+ }
54
+ this.sendRaw(jsonRpcRequest);
55
+ }
56
+ pushReceived(json) {
57
+ try {
58
+ const jsonData = JSON.parse(json);
59
+ // console.log('Received:', jsonData);
60
+ if (typeof jsonData !== 'object' || !jsonData) {
61
+ return;
62
+ }
63
+ if (!('jsonrpc' in jsonData) || jsonData.jsonrpc !== '2.0') {
64
+ return;
65
+ }
66
+ if ('id' in jsonData) {
67
+ if ('method' in jsonData) {
68
+ for (let s = this._s, l = s.length, i = 0; i < l; ++i) {
69
+ const o = s[i];
70
+ if (o.method === jsonData.method) {
71
+ const r = o.callback(o.method, jsonData.params);
72
+ this.sendRaw({
73
+ jsonrpc: '2.0',
74
+ id: jsonData.id,
75
+ result: r ?? null,
76
+ });
77
+ break;
78
+ }
79
+ }
80
+ }
81
+ else {
82
+ this._r.push(jsonData);
83
+ }
84
+ }
85
+ else if ('method' in jsonData) {
86
+ for (let n = this._n.slice(), l = n.length, i = 0; i < l; ++i) {
87
+ const o = n[i];
88
+ if (o.method === jsonData.method) {
89
+ o.callback(o.method, jsonData.params);
90
+ }
91
+ }
92
+ }
93
+ }
94
+ catch { }
95
+ }
96
+ pumpMessage(flushOnly = false) {
97
+ let returnIfNoData = flushOnly;
98
+ for (;;) {
99
+ const lastBuffer = this._l;
100
+ this._l = null;
101
+ if (lastBuffer) {
102
+ const headers = {};
103
+ let start = 0;
104
+ let cur = 0;
105
+ while (cur < lastBuffer.length) {
106
+ const c = lastBuffer[cur];
107
+ if (c === 10 ||
108
+ (c === 13 &&
109
+ cur < lastBuffer.length - 1 &&
110
+ lastBuffer[cur + 1] === 10)) {
111
+ if (start === cur) {
112
+ if (c === 13) {
113
+ ++cur;
114
+ }
115
+ ++cur;
116
+ break;
117
+ }
118
+ const headerLine = lastBuffer
119
+ .subarray(start, cur)
120
+ .toString(this._e);
121
+ const [n, v = ''] = headerLine.split(':', 2);
122
+ headers[n.trim().toLowerCase()] = v.trim();
123
+ if (c === 13) {
124
+ ++cur;
125
+ }
126
+ start = cur + 1;
127
+ }
128
+ ++cur;
129
+ }
130
+ if (cur === lastBuffer.length) {
131
+ // buffer is not enough
132
+ this._l = lastBuffer;
133
+ }
134
+ else {
135
+ // If no content-length, drop
136
+ if (headers['content-length'] != null) {
137
+ const last = cur + (Number(headers['content-length']) || 0);
138
+ if (last > lastBuffer.length) {
139
+ // buffer is not enough
140
+ this._l = lastBuffer;
141
+ }
142
+ else {
143
+ const bin = lastBuffer.subarray(cur, last);
144
+ if (last < lastBuffer.length) {
145
+ this._l = lastBuffer.subarray(last);
146
+ }
147
+ this.pushReceived(bin.toString(this._e));
148
+ returnIfNoData = true;
149
+ continue;
150
+ }
151
+ }
152
+ }
153
+ }
154
+ if (returnIfNoData) {
155
+ return true;
156
+ }
157
+ for (;;) {
158
+ const r = this._p.next();
159
+ if (r.done) {
160
+ return false;
161
+ }
162
+ const recv = r.value;
163
+ if (recv.type === 'stderr') {
164
+ console.error(recv.data.toString(this._e));
165
+ continue;
166
+ }
167
+ this._l = this._l ? Buffer.concat([this._l, recv.data]) : recv.data;
168
+ break;
169
+ }
170
+ }
171
+ }
172
+ receiveMessage(id) {
173
+ for (;;) {
174
+ for (let r = this._r, i = 0, l = r.length; i < l; ++i) {
175
+ const obj = r[i];
176
+ if (obj.id === id) {
177
+ r.splice(i, 1);
178
+ return obj.result;
179
+ }
180
+ }
181
+ if (!this.pumpMessage()) {
182
+ throw new Error('Peer closed');
183
+ }
184
+ }
185
+ }
186
+ registerServerMessageHandler(method, callback, once = false) {
187
+ // eslint-disable-next-line prefer-const
188
+ let unsub;
189
+ if (once) {
190
+ const cb = ((callback) => (method, params) => {
191
+ const r = callback(method, params);
192
+ unsub();
193
+ return r;
194
+ })(callback);
195
+ callback = cb;
196
+ }
197
+ this._s.push({ method, callback });
198
+ unsub = () => {
199
+ for (let s = this._s, l = s.length, i = 0; i < l; ++i) {
200
+ const o = s[i];
201
+ if (o.method === method && o.callback === callback) {
202
+ s.splice(i, 1);
203
+ break;
204
+ }
205
+ }
206
+ };
207
+ return unsub;
208
+ }
209
+ registerNotificationHandler(method, callback, once = false) {
210
+ // eslint-disable-next-line prefer-const
211
+ let unsub;
212
+ if (once) {
213
+ const cb = ((callback) => (method, params) => {
214
+ callback(method, params);
215
+ unsub();
216
+ })(callback);
217
+ callback = cb;
218
+ }
219
+ this._n.push({ method, callback });
220
+ unsub = () => {
221
+ for (let n = this._n, l = n.length, i = 0; i < l; ++i) {
222
+ const o = n[i];
223
+ if (o.method === method && o.callback === callback) {
224
+ n.splice(i, 1);
225
+ break;
226
+ }
227
+ }
228
+ };
229
+ return unsub;
230
+ }
231
+ close() {
232
+ this._p.stdin.end();
233
+ }
234
+ }
@@ -0,0 +1,29 @@
1
+ import SyncLspClient from './SyncLspClient.mjs';
2
+ export default class TsLspClient extends SyncLspClient {
3
+ private _supportPullDiagnostics;
4
+ private _firstDiagnosticsReceived;
5
+ private readonly _fileForDiagnostics;
6
+ constructor(command: string, argv: string[], encoding?: BufferEncoding);
7
+ initialize(rootDir: string): void;
8
+ waitForFirstDiagnosticsReceived(): void;
9
+ openDocument(fileName: string, content: string): void;
10
+ closeDocument(fileName: string): void;
11
+ /** Only returns first string from contents */
12
+ hoverForPosition(fileName: string, line: number, pos: number): [markdown: boolean, value: string];
13
+ getDefinition(fileName: string, line: number, pos: number): {
14
+ fileName: string;
15
+ lineStart: number;
16
+ posStart: number;
17
+ lineEnd: number;
18
+ posEnd: number;
19
+ } | null;
20
+ getTypeDefitition(fileName: string, line: number, pos: number): {
21
+ fileName: string;
22
+ lineStart: number;
23
+ posStart: number;
24
+ lineEnd: number;
25
+ posEnd: number;
26
+ } | null;
27
+ sendReplaceText(fileName: string, lineStart: number, posStart: number, lineEnd: number, posEnd: number, text: string): void;
28
+ exit(): void;
29
+ }
@@ -0,0 +1,271 @@
1
+ // @internal
2
+ import { fileURLToPath, pathToFileURL } from 'url';
3
+ // @internal
4
+ import version from '../version.mjs';
5
+ import SyncLspClient from './SyncLspClient.mjs';
6
+ /* eslint-disable @typescript-eslint/no-unsafe-member-access */
7
+ export default class TsLspClient extends SyncLspClient {
8
+ _supportPullDiagnostics;
9
+ _firstDiagnosticsReceived;
10
+ _fileForDiagnostics;
11
+ constructor(command, argv, encoding = 'utf8') {
12
+ super(command, argv, encoding);
13
+ this._supportPullDiagnostics = false;
14
+ this._firstDiagnosticsReceived = false;
15
+ this._fileForDiagnostics = new Map();
16
+ this.registerServerMessageHandler('client/registerCapability', () => {
17
+ return null;
18
+ });
19
+ this.registerServerMessageHandler('workspace/configuration', () => {
20
+ return {};
21
+ });
22
+ this.registerNotificationHandler('textDocument/publishDiagnostics', () => {
23
+ this._firstDiagnosticsReceived = true;
24
+ }, true);
25
+ }
26
+ initialize(rootDir) {
27
+ const uri = pathToFileURL(rootDir).href;
28
+ const id = this.sendMessage('initialize', {
29
+ processId: process.pid,
30
+ clientInfo: {
31
+ name: 'ts-const-value-transformer',
32
+ version,
33
+ },
34
+ capabilities: {
35
+ textDocument: {
36
+ publishDiagnostics: {
37
+ relatedInformation: true,
38
+ },
39
+ diagnostics: {
40
+ relatedInformation: true,
41
+ },
42
+ declaration: {
43
+ linkSupport: false,
44
+ },
45
+ typeDefinition: {
46
+ linkSupport: false,
47
+ },
48
+ hover: {
49
+ contentFormat: ['markdown', 'plaintext'],
50
+ },
51
+ },
52
+ },
53
+ workspaceFolders: [{ name: 'workspace', uri }],
54
+ rootUri: uri,
55
+ initializationOptions: {},
56
+ });
57
+ const r = this.receiveMessage(id);
58
+ if (r?.capabilities == null) {
59
+ throw new Error('Unexpected language server: no capabilities');
60
+ }
61
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
62
+ if (!r.capabilities.hoverProvider) {
63
+ throw new Error('Unexpected language server: hover not supported');
64
+ }
65
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
66
+ if (!r.capabilities.typeDefinitionProvider) {
67
+ throw new Error('Unexpected language server: go to type definition not supported');
68
+ }
69
+ this._supportPullDiagnostics = r.capabilities.diagnosticProvider != null;
70
+ this.notifyMessage('initialized');
71
+ if (!this.pumpMessage(true)) {
72
+ throw new Error('Peer closed');
73
+ }
74
+ if (!this._supportPullDiagnostics) {
75
+ this.registerNotificationHandler('textDocument/publishDiagnostics', (_, params) => {
76
+ if (!params || !('uri' in params) || !('diagnostics' in params)) {
77
+ return;
78
+ }
79
+ this._fileForDiagnostics.set(params.uri, params.diagnostics);
80
+ });
81
+ }
82
+ }
83
+ waitForFirstDiagnosticsReceived() {
84
+ if (this._firstDiagnosticsReceived) {
85
+ return;
86
+ }
87
+ if (!this.pumpMessage(true)) {
88
+ throw new Error('Peer closed');
89
+ }
90
+ while (!this._firstDiagnosticsReceived) {
91
+ if (!this.pumpMessage()) {
92
+ throw new Error('Peer closed');
93
+ }
94
+ }
95
+ }
96
+ openDocument(fileName, content) {
97
+ const uri = pathToFileURL(fileName).href;
98
+ this._fileForDiagnostics.delete(uri);
99
+ this.notifyMessage('textDocument/didOpen', {
100
+ textDocument: {
101
+ uri,
102
+ languageId: 'typescript',
103
+ version: 0,
104
+ text: content,
105
+ },
106
+ });
107
+ }
108
+ closeDocument(fileName) {
109
+ const uri = pathToFileURL(fileName).href;
110
+ this._fileForDiagnostics.delete(uri);
111
+ this.notifyMessage('textDocument/didClose', {
112
+ textDocument: {
113
+ uri,
114
+ },
115
+ });
116
+ }
117
+ // public receiveDiagnostics(fileName: string): object[] {
118
+ // const uri = pathToFileURL(fileName).href;
119
+ // if (this._supportPullDiagnostics) {
120
+ // const id = this.sendMessage('textDocument/diagnostic', {
121
+ // textDocument: {
122
+ // uri,
123
+ // },
124
+ // });
125
+ // const r: any = this.receiveMessage(id);
126
+ // // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
127
+ // if (!r) {
128
+ // return [];
129
+ // }
130
+ // if (r.kind === 'unchanged') {
131
+ // return [];
132
+ // }
133
+ // // eslint-disable-next-line @typescript-eslint/no-unsafe-return
134
+ // return r.items;
135
+ // } else {
136
+ // if (!this.pumpMessage(true)) {
137
+ // throw new Error('Peer closed');
138
+ // }
139
+ // for (;;) {
140
+ // const o = this._fileForDiagnostics.get(uri);
141
+ // if (o) {
142
+ // return o;
143
+ // }
144
+ // if (!this.pumpMessage()) {
145
+ // throw new Error('Peer closed');
146
+ // }
147
+ // }
148
+ // }
149
+ // }
150
+ /** Only returns first string from contents */
151
+ hoverForPosition(fileName, line, pos) {
152
+ const uri = pathToFileURL(fileName).href;
153
+ const id = this.sendMessage('textDocument/hover', {
154
+ textDocument: {
155
+ uri,
156
+ },
157
+ position: {
158
+ line,
159
+ character: pos,
160
+ },
161
+ });
162
+ const r = this.receiveMessage(id);
163
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
164
+ if (!r?.contents) {
165
+ return [false, ''];
166
+ }
167
+ if ('kind' in r.contents) {
168
+ return [r.contents.kind === 'markdown', r.contents.value];
169
+ }
170
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
171
+ const c = r.contents instanceof Array ? r.contents[0] : r.contents;
172
+ if (typeof c === 'string') {
173
+ return [true, c];
174
+ }
175
+ return [true, '```' + c.language + '\n' + c.value + '\n```'];
176
+ }
177
+ getDefinition(fileName, line, pos) {
178
+ const uri = pathToFileURL(fileName).href;
179
+ const id = this.sendMessage('textDocument/definition', {
180
+ textDocument: {
181
+ uri,
182
+ },
183
+ position: {
184
+ line,
185
+ character: pos,
186
+ },
187
+ });
188
+ const r = this.receiveMessage(id);
189
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
190
+ if (!r) {
191
+ return null;
192
+ }
193
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
194
+ const loc = r instanceof Array ? r[0] : r;
195
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
196
+ if (!loc) {
197
+ return null;
198
+ }
199
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
200
+ const defFileName = fileURLToPath(loc.uri);
201
+ return {
202
+ fileName: defFileName,
203
+ lineStart: loc.range.start.line,
204
+ posStart: loc.range.start.character,
205
+ lineEnd: loc.range.end.line,
206
+ posEnd: loc.range.end.character,
207
+ };
208
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment */
209
+ }
210
+ getTypeDefitition(fileName, line, pos) {
211
+ const uri = pathToFileURL(fileName).href;
212
+ const id = this.sendMessage('textDocument/typeDefinition', {
213
+ textDocument: {
214
+ uri,
215
+ },
216
+ position: {
217
+ line,
218
+ character: pos,
219
+ },
220
+ });
221
+ const r = this.receiveMessage(id);
222
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
223
+ if (!r) {
224
+ return null;
225
+ }
226
+ /* eslint-disable @typescript-eslint/no-unsafe-assignment */
227
+ const loc = r instanceof Array ? r[0] : r;
228
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
229
+ if (!loc) {
230
+ return null;
231
+ }
232
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
233
+ const defFileName = fileURLToPath(loc.uri);
234
+ return {
235
+ fileName: defFileName,
236
+ lineStart: loc.range.start.line,
237
+ posStart: loc.range.start.character,
238
+ lineEnd: loc.range.end.line,
239
+ posEnd: loc.range.end.character,
240
+ };
241
+ /* eslint-enable @typescript-eslint/no-unsafe-assignment */
242
+ }
243
+ sendReplaceText(fileName, lineStart, posStart, lineEnd, posEnd, text) {
244
+ const uri = pathToFileURL(fileName).href;
245
+ this._fileForDiagnostics.delete(uri);
246
+ this.notifyMessage('textDocument/didChange', {
247
+ textDocument: {
248
+ uri,
249
+ version: 0,
250
+ },
251
+ contentChanges: [
252
+ {
253
+ range: {
254
+ start: { line: lineStart, character: posStart },
255
+ end: { line: lineEnd, character: posEnd },
256
+ },
257
+ text,
258
+ },
259
+ ],
260
+ });
261
+ }
262
+ exit() {
263
+ const id = this.sendMessage('shutdown');
264
+ try {
265
+ this.receiveMessage(id);
266
+ this.notifyMessage('exit');
267
+ }
268
+ catch { }
269
+ this.close();
270
+ }
271
+ }
@@ -0,0 +1 @@
1
+ export {};