typescript-language-server 1.2.0 → 2.0.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.
Files changed (73) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +28 -2
  3. package/lib/cli.js +6 -6
  4. package/lib/cli.js.map +1 -1
  5. package/lib/completion.d.ts +1 -2
  6. package/lib/completion.d.ts.map +1 -1
  7. package/lib/completion.js +38 -26
  8. package/lib/completion.js.map +1 -1
  9. package/lib/configuration-manager.js +1 -1
  10. package/lib/configuration-manager.js.map +1 -1
  11. package/lib/diagnostic-queue.d.ts +1 -1
  12. package/lib/diagnostic-queue.d.ts.map +1 -1
  13. package/lib/lsp-connection.d.ts +5 -5
  14. package/lib/lsp-connection.d.ts.map +1 -1
  15. package/lib/lsp-connection.js +2 -3
  16. package/lib/lsp-connection.js.map +1 -1
  17. package/lib/lsp-server.d.ts +5 -6
  18. package/lib/lsp-server.d.ts.map +1 -1
  19. package/lib/lsp-server.js +16 -31
  20. package/lib/lsp-server.js.map +1 -1
  21. package/lib/lsp-server.spec.js +319 -96
  22. package/lib/lsp-server.spec.js.map +1 -1
  23. package/lib/test-utils.d.ts +3 -1
  24. package/lib/test-utils.d.ts.map +1 -1
  25. package/lib/test-utils.js +19 -8
  26. package/lib/test-utils.js.map +1 -1
  27. package/lib/ts-protocol.d.ts +27 -7
  28. package/lib/ts-protocol.d.ts.map +1 -1
  29. package/lib/ts-protocol.js +7 -1
  30. package/lib/ts-protocol.js.map +1 -1
  31. package/lib/tsServer/cancellation.d.ts +7 -4
  32. package/lib/tsServer/cancellation.d.ts.map +1 -1
  33. package/lib/tsServer/cancellation.js +7 -8
  34. package/lib/tsServer/cancellation.js.map +1 -1
  35. package/lib/tsServer/logDirectoryProvider.d.ts +13 -0
  36. package/lib/tsServer/logDirectoryProvider.d.ts.map +1 -0
  37. package/lib/tsServer/logDirectoryProvider.js +49 -0
  38. package/lib/tsServer/logDirectoryProvider.js.map +1 -0
  39. package/lib/tsServer/server.d.ts +3 -1
  40. package/lib/tsServer/server.d.ts.map +1 -1
  41. package/lib/tsServer/server.js +8 -7
  42. package/lib/tsServer/server.js.map +1 -1
  43. package/lib/tsServer/spawner.d.ts +7 -2
  44. package/lib/tsServer/spawner.d.ts.map +1 -1
  45. package/lib/tsServer/spawner.js +27 -19
  46. package/lib/tsServer/spawner.js.map +1 -1
  47. package/lib/tsServer/tracer.d.ts +26 -0
  48. package/lib/tsServer/tracer.d.ts.map +1 -0
  49. package/lib/tsServer/tracer.js +80 -0
  50. package/lib/tsServer/tracer.js.map +1 -0
  51. package/lib/tsServer/versionProvider.d.ts +7 -7
  52. package/lib/tsServer/versionProvider.d.ts.map +1 -1
  53. package/lib/tsServer/versionProvider.js +26 -20
  54. package/lib/tsServer/versionProvider.js.map +1 -1
  55. package/lib/tsp-client.d.ts +8 -3
  56. package/lib/tsp-client.d.ts.map +1 -1
  57. package/lib/tsp-client.js +4 -5
  58. package/lib/tsp-client.js.map +1 -1
  59. package/lib/tsp-client.spec.js +15 -5
  60. package/lib/tsp-client.spec.js.map +1 -1
  61. package/lib/utils/configuration.d.ts +17 -8
  62. package/lib/utils/configuration.d.ts.map +1 -1
  63. package/lib/utils/configuration.js +43 -1
  64. package/lib/utils/configuration.js.map +1 -1
  65. package/lib/utils/logger.d.ts +65 -0
  66. package/lib/utils/logger.d.ts.map +1 -0
  67. package/lib/utils/logger.js +189 -0
  68. package/lib/utils/logger.js.map +1 -0
  69. package/package.json +11 -11
  70. package/lib/logger.d.ts +0 -48
  71. package/lib/logger.d.ts.map +0 -1
  72. package/lib/logger.js +0 -106
  73. package/lib/logger.js.map +0 -1
@@ -7,10 +7,11 @@
7
7
  import * as chai from 'chai';
8
8
  import fs from 'fs-extra';
9
9
  import * as lsp from 'vscode-languageserver';
10
+ import { TextDocument } from 'vscode-languageserver-textdocument';
10
11
  import * as lspcalls from './lsp-protocol.calls.proposed.js';
11
12
  import { uri, createServer, position, lastPosition, filePath, positionAfter, readContents, toPlatformEOL } from './test-utils.js';
12
- import { TextDocument } from 'vscode-languageserver-textdocument';
13
13
  import { Commands } from './commands.js';
14
+ import { SemicolonPreference } from './ts-protocol.js';
14
15
  import { CodeActionKind } from './utils/types.js';
15
16
  const assert = chai.assert;
16
17
  const diagnostics = new Map();
@@ -20,13 +21,6 @@ before(async () => {
20
21
  rootUri: uri(),
21
22
  publishDiagnostics: args => diagnostics.set(args.uri, args),
22
23
  });
23
- server.didChangeConfiguration({
24
- settings: {
25
- completions: {
26
- completeFunctionCalls: true,
27
- },
28
- },
29
- });
30
24
  });
31
25
  beforeEach(() => {
32
26
  server.closeAll();
@@ -204,8 +198,33 @@ describe('completion', () => {
204
198
  assert.isNotNull(proposals);
205
199
  const completion = proposals.items.find(completion => completion.label === 'getById');
206
200
  assert.isDefined(completion);
207
- assert.isDefined(completion.textEdit);
208
- assert.containsAllKeys(completion.textEdit, ['newText', 'insert', 'replace']);
201
+ assert.deepInclude(completion, {
202
+ label: 'getById',
203
+ kind: lsp.CompletionItemKind.Method,
204
+ textEdit: {
205
+ newText: 'getById',
206
+ insert: {
207
+ start: {
208
+ line: 6,
209
+ character: 20,
210
+ },
211
+ end: {
212
+ line: 6,
213
+ character: 23,
214
+ },
215
+ },
216
+ replace: {
217
+ start: {
218
+ line: 6,
219
+ character: 20,
220
+ },
221
+ end: {
222
+ line: 6,
223
+ character: 27,
224
+ },
225
+ },
226
+ },
227
+ });
209
228
  server.didCloseTextDocument({ textDocument: doc });
210
229
  });
211
230
  it('completions for clients that do not support insertReplaceSupport', async () => {
@@ -246,6 +265,39 @@ describe('completion', () => {
246
265
  localServer.closeAll();
247
266
  localServer.shutdown();
248
267
  });
268
+ it('provides snippet completion in import statement', async () => {
269
+ const doc = {
270
+ uri: uri('bar.ts'),
271
+ languageId: 'typescript',
272
+ version: 1,
273
+ text: 'import { readFile }',
274
+ };
275
+ server.didOpenTextDocument({ textDocument: doc });
276
+ const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, 'readFile') });
277
+ assert.isNotNull(proposals);
278
+ const completion = proposals.items.find(completion => completion.label === 'readFile');
279
+ assert.isDefined(completion);
280
+ assert.deepInclude(completion, {
281
+ label: 'readFile',
282
+ kind: lsp.CompletionItemKind.Function,
283
+ insertTextFormat: lsp.InsertTextFormat.Snippet,
284
+ detail: 'fs',
285
+ textEdit: {
286
+ newText: 'import { readFile$1 } from "fs";',
287
+ range: {
288
+ start: {
289
+ line: 0,
290
+ character: 0,
291
+ },
292
+ end: {
293
+ line: 0,
294
+ character: 19,
295
+ },
296
+ },
297
+ },
298
+ });
299
+ server.didCloseTextDocument({ textDocument: doc });
300
+ });
249
301
  it('includes detail field with package name for auto-imports', async () => {
250
302
  const doc = {
251
303
  uri: uri('bar.ts'),
@@ -259,7 +311,6 @@ describe('completion', () => {
259
311
  const completion = proposals.items.find(completion => completion.label === 'readFile');
260
312
  assert.isDefined(completion);
261
313
  assert.strictEqual(completion.detail, 'fs');
262
- assert.strictEqual(completion.insertTextFormat, /* snippet */ 2);
263
314
  server.didCloseTextDocument({ textDocument: doc });
264
315
  });
265
316
  it('resolves text edit for auto-import completion', async () => {
@@ -293,13 +344,11 @@ describe('completion', () => {
293
344
  server.didCloseTextDocument({ textDocument: doc });
294
345
  });
295
346
  it('resolves text edit for auto-import completion in right format', async () => {
296
- server.didChangeConfiguration({
297
- settings: {
298
- typescript: {
299
- format: {
300
- semicolons: 'remove',
301
- insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: false,
302
- },
347
+ server.updateWorkspaceSettings({
348
+ typescript: {
349
+ format: {
350
+ semicolons: SemicolonPreference.Remove,
351
+ insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: false,
303
352
  },
304
353
  },
305
354
  });
@@ -331,21 +380,21 @@ describe('completion', () => {
331
380
  },
332
381
  ]);
333
382
  server.didCloseTextDocument({ textDocument: doc });
334
- server.didChangeConfiguration({
335
- settings: {
336
- completions: {
337
- completeFunctionCalls: true,
338
- },
339
- typescript: {
340
- format: {
341
- semicolons: 'ignore',
342
- insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
343
- },
383
+ server.updateWorkspaceSettings({
384
+ typescript: {
385
+ format: {
386
+ semicolons: SemicolonPreference.Ignore,
387
+ insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
344
388
  },
345
389
  },
346
390
  });
347
391
  });
348
392
  it('resolves a snippet for method completion', async () => {
393
+ server.updateWorkspaceSettings({
394
+ completions: {
395
+ completeFunctionCalls: true,
396
+ },
397
+ });
349
398
  const doc = {
350
399
  uri: uri('bar.ts'),
351
400
  languageId: 'typescript',
@@ -359,14 +408,198 @@ describe('completion', () => {
359
408
  const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, 'readFile') });
360
409
  assert.isNotNull(proposals);
361
410
  const completion = proposals.items.find(completion => completion.label === 'readFile');
362
- assert.strictEqual(completion.insertTextFormat, lsp.InsertTextFormat.Snippet);
363
- assert.strictEqual(completion.label, 'readFile');
364
411
  const resolvedItem = await server.completionResolve(completion);
365
- assert.strictEqual(resolvedItem.insertTextFormat, lsp.InsertTextFormat.Snippet);
366
- // eslint-disable-next-line no-template-curly-in-string
367
- assert.strictEqual(resolvedItem.insertText, 'readFile(${1:path}, ${2:options}, ${3:callback})$0');
412
+ assert.deepInclude(resolvedItem, {
413
+ label: 'readFile',
414
+ insertTextFormat: lsp.InsertTextFormat.Snippet,
415
+ // eslint-disable-next-line no-template-curly-in-string
416
+ insertText: 'readFile(${1:path}, ${2:options}, ${3:callback})$0',
417
+ textEdit: {
418
+ // eslint-disable-next-line no-template-curly-in-string
419
+ newText: 'readFile(${1:path}, ${2:options}, ${3:callback})$0',
420
+ insert: {
421
+ start: {
422
+ line: 2,
423
+ character: 19,
424
+ },
425
+ end: {
426
+ line: 2,
427
+ character: 27,
428
+ },
429
+ },
430
+ replace: {
431
+ start: {
432
+ line: 2,
433
+ character: 19,
434
+ },
435
+ end: {
436
+ line: 2,
437
+ character: 27,
438
+ },
439
+ },
440
+ },
441
+ });
442
+ server.didCloseTextDocument({ textDocument: doc });
443
+ server.updateWorkspaceSettings({
444
+ completions: {
445
+ completeFunctionCalls: false,
446
+ },
447
+ });
448
+ });
449
+ it('does not provide snippet completion for "$" function when completeFunctionCalls disabled', async () => {
450
+ const doc = {
451
+ uri: uri('bar.ts'),
452
+ languageId: 'typescript',
453
+ version: 1,
454
+ text: `
455
+ function $(): void {}
456
+ /**/$
457
+ `,
458
+ };
459
+ server.didOpenTextDocument({ textDocument: doc });
460
+ const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, '/**/') });
461
+ assert.isNotNull(proposals);
462
+ const completion = proposals.items.find(completion => completion.label === '$');
463
+ assert.deepInclude(completion, {
464
+ label: '$',
465
+ textEdit: {
466
+ newText: '$',
467
+ insert: {
468
+ start: {
469
+ line: 2,
470
+ character: 20,
471
+ },
472
+ end: {
473
+ line: 2,
474
+ character: 20,
475
+ },
476
+ },
477
+ replace: {
478
+ start: {
479
+ line: 2,
480
+ character: 20,
481
+ },
482
+ end: {
483
+ line: 2,
484
+ character: 21,
485
+ },
486
+ },
487
+ },
488
+ });
489
+ const resolvedItem = await server.completionResolve(completion);
490
+ assert.deepInclude(resolvedItem, {
491
+ label: '$',
492
+ textEdit: {
493
+ newText: '$',
494
+ insert: {
495
+ start: {
496
+ line: 2,
497
+ character: 20,
498
+ },
499
+ end: {
500
+ line: 2,
501
+ character: 20,
502
+ },
503
+ },
504
+ replace: {
505
+ start: {
506
+ line: 2,
507
+ character: 20,
508
+ },
509
+ end: {
510
+ line: 2,
511
+ character: 21,
512
+ },
513
+ },
514
+ },
515
+ });
368
516
  server.didCloseTextDocument({ textDocument: doc });
369
517
  });
518
+ it('provides snippet completions for "$" function when completeFunctionCalls enabled', async () => {
519
+ server.updateWorkspaceSettings({
520
+ completions: {
521
+ completeFunctionCalls: true,
522
+ },
523
+ });
524
+ const doc = {
525
+ uri: uri('bar.ts'),
526
+ languageId: 'typescript',
527
+ version: 1,
528
+ text: `
529
+ function $(): void {}
530
+ /**/$
531
+ `,
532
+ };
533
+ server.didOpenTextDocument({ textDocument: doc });
534
+ const proposals = await server.completion({ textDocument: doc, position: positionAfter(doc, '/**/') });
535
+ assert.isNotNull(proposals);
536
+ const completion = proposals.items.find(completion => completion.label === '$');
537
+ // NOTE: Technically not valid until resolved.
538
+ assert.deepInclude(completion, {
539
+ label: '$',
540
+ insertTextFormat: lsp.InsertTextFormat.Snippet,
541
+ textEdit: {
542
+ newText: '$',
543
+ insert: {
544
+ start: {
545
+ line: 2,
546
+ character: 20,
547
+ },
548
+ end: {
549
+ line: 2,
550
+ character: 20,
551
+ },
552
+ },
553
+ replace: {
554
+ start: {
555
+ line: 2,
556
+ character: 20,
557
+ },
558
+ end: {
559
+ line: 2,
560
+ character: 21,
561
+ },
562
+ },
563
+ },
564
+ });
565
+ const resolvedItem = await server.completionResolve(completion);
566
+ assert.deepInclude(resolvedItem, {
567
+ label: '$',
568
+ insertTextFormat: lsp.InsertTextFormat.Snippet,
569
+ // eslint-disable-next-line no-template-curly-in-string
570
+ insertText: '\\$()$0',
571
+ textEdit: {
572
+ // eslint-disable-next-line no-template-curly-in-string
573
+ newText: '\\$()$0',
574
+ insert: {
575
+ start: {
576
+ line: 2,
577
+ character: 20,
578
+ },
579
+ end: {
580
+ line: 2,
581
+ character: 20,
582
+ },
583
+ },
584
+ replace: {
585
+ start: {
586
+ line: 2,
587
+ character: 20,
588
+ },
589
+ end: {
590
+ line: 2,
591
+ character: 21,
592
+ },
593
+ },
594
+ },
595
+ });
596
+ server.didCloseTextDocument({ textDocument: doc });
597
+ server.updateWorkspaceSettings({
598
+ completions: {
599
+ completeFunctionCalls: false,
600
+ },
601
+ });
602
+ });
370
603
  it('includes textEdit for string completion', async () => {
371
604
  const doc = {
372
605
  uri: uri('bar.ts'),
@@ -391,27 +624,19 @@ describe('completion', () => {
391
624
  });
392
625
  assert.isNotNull(proposals);
393
626
  const completion = proposals.items.find(completion => completion.label === 'fs/read');
394
- assert.strictEqual(completion.label, 'fs/read');
395
- assert.deepStrictEqual(completion.textEdit, {
396
- newText: 'fs/read',
397
- insert: {
398
- start: {
399
- line: 5,
400
- character: 20,
401
- },
402
- end: {
403
- line: 5,
404
- character: 23,
405
- },
406
- },
407
- replace: {
408
- start: {
409
- line: 5,
410
- character: 20,
411
- },
412
- end: {
413
- line: 5,
414
- character: 24,
627
+ assert.deepInclude(completion, {
628
+ label: 'fs/read',
629
+ textEdit: {
630
+ newText: 'fs/read',
631
+ range: {
632
+ start: {
633
+ line: 5,
634
+ character: 20,
635
+ },
636
+ end: {
637
+ line: 5,
638
+ character: 24,
639
+ },
415
640
  },
416
641
  },
417
642
  });
@@ -439,16 +664,14 @@ describe('completion', () => {
439
664
  assert.lengthOf(proposals.items, 2);
440
665
  assert.deepInclude(proposals.items[0], {
441
666
  label: 'bar',
442
- kind: 2,
443
- insertTextFormat: 2,
667
+ kind: lsp.CompletionItemKind.Method,
444
668
  });
445
669
  assert.deepInclude(proposals.items[1], {
446
670
  label: 'bar',
447
671
  labelDetails: {
448
672
  detail: '(x)',
449
673
  },
450
- kind: 2,
451
- insertTextFormat: 2,
674
+ kind: lsp.CompletionItemKind.Method,
452
675
  insertText: toPlatformEOL('bar(x) {\n $0\n},'),
453
676
  });
454
677
  });
@@ -652,11 +875,9 @@ describe('diagnostics', () => {
652
875
  assert.equal(diagnosticsForDoc2.diagnostics.length, 1, JSON.stringify(diagnostics));
653
876
  });
654
877
  it('code 6133 (ununsed variable) is ignored', async () => {
655
- server.didChangeConfiguration({
656
- settings: {
657
- diagnostics: {
658
- ignoredCodes: [6133],
659
- },
878
+ server.updateWorkspaceSettings({
879
+ diagnostics: {
880
+ ignoredCodes: [6133],
660
881
  },
661
882
  });
662
883
  const doc = {
@@ -862,24 +1083,22 @@ describe('references', () => {
862
1083
  // export function foo(): void {
863
1084
  // console.log('test')
864
1085
  // }
865
- // `
1086
+ // `,
866
1087
  // };
867
1088
  // server.didOpenTextDocument({
868
- // textDocument: doc
1089
+ // textDocument: doc,
869
1090
  // });
870
- // server.didChangeConfiguration({
871
- // settings: {
872
- // typescript: {
873
- // format: {
874
- // insertSpaceAfterCommaDelimiter: true
875
- // }
1091
+ // server.updateWorkspaceSettingsttings({
1092
+ // typescript: {
1093
+ // format: {
1094
+ // insertSpaceAfterCommaDelimiter: true,
876
1095
  // },
877
- // javascript: {
878
- // format: {
879
- // insertSpaceAfterCommaDelimiter: false
880
- // }
881
- // }
882
- // }
1096
+ // },
1097
+ // javascript: {
1098
+ // format: {
1099
+ // insertSpaceAfterCommaDelimiter: false,
1100
+ // },
1101
+ // },
883
1102
  // });
884
1103
  // const file = filePath('bar.ts');
885
1104
  // const settings = server.getWorkspacePreferencesForDocument(file);
@@ -890,6 +1109,16 @@ describe('formatting', () => {
890
1109
  const uriString = uri('bar.ts');
891
1110
  const languageId = 'typescript';
892
1111
  const version = 1;
1112
+ before(async () => {
1113
+ server.updateWorkspaceSettings({
1114
+ typescript: {
1115
+ format: {
1116
+ semicolons: SemicolonPreference.Ignore,
1117
+ insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces: true,
1118
+ },
1119
+ },
1120
+ });
1121
+ });
893
1122
  it('full document formatting', async () => {
894
1123
  const text = 'export function foo ( ) : void { }';
895
1124
  const textDocument = {
@@ -944,13 +1173,11 @@ describe('formatting', () => {
944
1173
  uri: uriString, languageId, version, text,
945
1174
  };
946
1175
  server.didOpenTextDocument({ textDocument });
947
- server.didChangeConfiguration({
948
- settings: {
949
- typescript: {
950
- format: {
951
- newLineCharacter: '\n',
952
- placeOpenBraceOnNewLineForFunctions: true,
953
- },
1176
+ server.updateWorkspaceSettings({
1177
+ typescript: {
1178
+ format: {
1179
+ newLineCharacter: '\n',
1180
+ placeOpenBraceOnNewLineForFunctions: true,
954
1181
  },
955
1182
  },
956
1183
  });
@@ -1853,23 +2080,19 @@ describe('jsx/tsx project', () => {
1853
2080
  });
1854
2081
  describe('inlayHints', () => {
1855
2082
  before(async () => {
1856
- server.didChangeConfiguration({
1857
- settings: {
1858
- typescript: {
1859
- inlayHints: {
1860
- includeInlayFunctionLikeReturnTypeHints: true,
1861
- },
2083
+ server.updateWorkspaceSettings({
2084
+ typescript: {
2085
+ inlayHints: {
2086
+ includeInlayFunctionLikeReturnTypeHints: true,
1862
2087
  },
1863
2088
  },
1864
2089
  });
1865
2090
  });
1866
2091
  after(() => {
1867
- server.didChangeConfiguration({
1868
- settings: {
1869
- typescript: {
1870
- inlayHints: {
1871
- includeInlayFunctionLikeReturnTypeHints: false,
1872
- },
2092
+ server.updateWorkspaceSettings({
2093
+ typescript: {
2094
+ inlayHints: {
2095
+ includeInlayFunctionLikeReturnTypeHints: false,
1873
2096
  },
1874
2097
  },
1875
2098
  });