typescript-language-server 0.6.2 → 0.7.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 (72) hide show
  1. package/CHANGELOG.md +77 -0
  2. package/README.md +253 -31
  3. package/lib/calls.js +9 -9
  4. package/lib/calls.js.map +1 -1
  5. package/lib/cli.js +6 -11
  6. package/lib/cli.js.map +1 -1
  7. package/lib/commands.d.ts +4 -1
  8. package/lib/commands.d.ts.map +1 -1
  9. package/lib/commands.js +5 -2
  10. package/lib/commands.js.map +1 -1
  11. package/lib/completion.d.ts.map +1 -1
  12. package/lib/completion.js +60 -34
  13. package/lib/completion.js.map +1 -1
  14. package/lib/diagnostic-queue.d.ts +4 -4
  15. package/lib/diagnostic-queue.d.ts.map +1 -1
  16. package/lib/diagnostic-queue.js +3 -3
  17. package/lib/diagnostic-queue.js.map +1 -1
  18. package/lib/document-symbol.js +8 -8
  19. package/lib/document-symbol.js.map +1 -1
  20. package/lib/file-lsp-server.spec.js +27 -5
  21. package/lib/file-lsp-server.spec.js.map +1 -1
  22. package/lib/hover.js +6 -6
  23. package/lib/hover.js.map +1 -1
  24. package/lib/lsp-connection.d.ts.map +1 -1
  25. package/lib/lsp-connection.js +3 -0
  26. package/lib/lsp-connection.js.map +1 -1
  27. package/lib/lsp-protocol.calls.proposed.d.ts.map +1 -1
  28. package/lib/lsp-protocol.calls.proposed.js.map +1 -1
  29. package/lib/lsp-protocol.inlayHints.proposed.d.ts +36 -0
  30. package/lib/lsp-protocol.inlayHints.proposed.d.ts.map +1 -0
  31. package/lib/lsp-protocol.inlayHints.proposed.js +25 -0
  32. package/lib/lsp-protocol.inlayHints.proposed.js.map +1 -0
  33. package/lib/lsp-server.d.ts +10 -2
  34. package/lib/lsp-server.d.ts.map +1 -1
  35. package/lib/lsp-server.js +241 -118
  36. package/lib/lsp-server.js.map +1 -1
  37. package/lib/lsp-server.spec.js +294 -47
  38. package/lib/lsp-server.spec.js.map +1 -1
  39. package/lib/modules-resolver.spec.js +1 -1
  40. package/lib/modules-resolver.spec.js.map +1 -1
  41. package/lib/organize-imports.d.ts +2 -1
  42. package/lib/organize-imports.d.ts.map +1 -1
  43. package/lib/organize-imports.js +7 -5
  44. package/lib/organize-imports.js.map +1 -1
  45. package/lib/organize-imports.spec.js +15 -8
  46. package/lib/organize-imports.spec.js.map +1 -1
  47. package/lib/protocol-translation.d.ts +8 -4
  48. package/lib/protocol-translation.d.ts.map +1 -1
  49. package/lib/protocol-translation.js +22 -11
  50. package/lib/protocol-translation.js.map +1 -1
  51. package/lib/quickfix.js +1 -1
  52. package/lib/quickfix.js.map +1 -1
  53. package/lib/test-utils.js +4 -4
  54. package/lib/test-utils.js.map +1 -1
  55. package/lib/ts-protocol.d.ts +11 -1
  56. package/lib/ts-protocol.d.ts.map +1 -1
  57. package/lib/ts-protocol.js.map +1 -1
  58. package/lib/tsp-client.d.ts +2 -0
  59. package/lib/tsp-client.d.ts.map +1 -1
  60. package/lib/tsp-client.js +20 -11
  61. package/lib/tsp-client.js.map +1 -1
  62. package/lib/tsp-client.spec.js +28 -8
  63. package/lib/tsp-client.spec.js.map +1 -1
  64. package/lib/tsp-command-types.d.ts +14 -1
  65. package/lib/tsp-command-types.d.ts.map +1 -1
  66. package/lib/tsp-command-types.js +21 -1
  67. package/lib/tsp-command-types.js.map +1 -1
  68. package/lib/utils/api.d.ts +45 -0
  69. package/lib/utils/api.d.ts.map +1 -0
  70. package/lib/utils/api.js +95 -0
  71. package/lib/utils/api.js.map +1 -0
  72. package/package.json +5 -5
package/lib/lsp-server.js CHANGED
@@ -61,12 +61,14 @@ const refactor_1 = require("./refactor");
61
61
  const organize_imports_1 = require("./organize-imports");
62
62
  const document_symbol_1 = require("./document-symbol");
63
63
  const calls_1 = require("./calls");
64
+ const api_1 = __importDefault(require("./utils/api"));
64
65
  class LspServer {
65
66
  constructor(options) {
66
67
  this.options = options;
67
68
  this.documents = new document_1.LspDocuments();
68
- this.requestDiagnostics = p_debounce_1.default(() => this.doRequestDiagnostics(), 200);
69
+ this.requestDiagnostics = (0, p_debounce_1.default)(() => this.doRequestDiagnostics(), 200);
69
70
  this.logger = new logger_1.PrefixingLogger(options.logger, '[lspserver]');
71
+ this.workspaceConfiguration = {};
70
72
  }
71
73
  closeAll() {
72
74
  for (const file of [...this.documents.files]) {
@@ -78,41 +80,75 @@ class LspServer {
78
80
  return this.options.tsserverPath;
79
81
  }
80
82
  const tsServerPath = path.join('typescript', 'lib', 'tsserver.js');
81
- // 1) look into .yarn/sdks of workspace root
82
- const sdk = modules_resolver_1.findPathToYarnSdk(this.rootPath(), tsServerPath);
83
- if (sdk) {
84
- return sdk;
85
- }
86
- // 2) look into node_modules of workspace root
87
- const executable = modules_resolver_1.findPathToModule(this.rootPath(), tsServerPath);
88
- if (executable) {
89
- return executable;
83
+ if (this.workspaceRoot) {
84
+ // 1) look into .yarn/sdks of workspace root
85
+ const sdk = (0, modules_resolver_1.findPathToYarnSdk)(this.workspaceRoot, tsServerPath);
86
+ if (sdk) {
87
+ return sdk;
88
+ }
89
+ // 2) look into node_modules of workspace root
90
+ const executable = (0, modules_resolver_1.findPathToModule)(this.workspaceRoot, tsServerPath);
91
+ if (executable) {
92
+ return executable;
93
+ }
90
94
  }
91
95
  // 3) use globally installed tsserver
92
- if (commandExists.sync(utils_1.getTsserverExecutable())) {
93
- return utils_1.getTsserverExecutable();
96
+ if (commandExists.sync((0, utils_1.getTsserverExecutable)())) {
97
+ return (0, utils_1.getTsserverExecutable)();
94
98
  }
95
99
  // 4) look into node_modules of typescript-language-server
96
- const bundled = modules_resolver_1.findPathToModule(__dirname, tsServerPath);
100
+ const bundled = (0, modules_resolver_1.findPathToModule)(__dirname, tsServerPath);
97
101
  if (!bundled) {
98
- throw Error(`Couldn't find '${utils_1.getTsserverExecutable()}' executable or 'tsserver.js' module`);
102
+ throw Error(`Couldn't find '${(0, utils_1.getTsserverExecutable)()}' executable or 'tsserver.js' module`);
99
103
  }
100
104
  return bundled;
101
105
  }
106
+ getTypeScriptVersion(serverPath) {
107
+ if (!fs.existsSync(serverPath)) {
108
+ return undefined;
109
+ }
110
+ const p = serverPath.split(path.sep);
111
+ if (p.length <= 2) {
112
+ return undefined;
113
+ }
114
+ const p2 = p.slice(0, -2);
115
+ const modulePath = p2.join(path.sep);
116
+ let fileName = path.join(modulePath, 'package.json');
117
+ if (!fs.existsSync(fileName)) {
118
+ // Special case for ts dev versions
119
+ if (path.basename(modulePath) === 'built') {
120
+ fileName = path.join(modulePath, '..', 'package.json');
121
+ }
122
+ }
123
+ if (!fs.existsSync(fileName)) {
124
+ return undefined;
125
+ }
126
+ const contents = fs.readFileSync(fileName).toString();
127
+ let desc = null;
128
+ try {
129
+ desc = JSON.parse(contents);
130
+ }
131
+ catch (err) {
132
+ return undefined;
133
+ }
134
+ if (!desc || !desc.version) {
135
+ return undefined;
136
+ }
137
+ return desc.version ? api_1.default.fromVersionString(desc.version) : undefined;
138
+ }
102
139
  initialize(params) {
103
140
  var _a;
104
141
  return __awaiter(this, void 0, void 0, function* () {
105
142
  this.logger.log('initialize', params);
106
143
  this.initializeParams = params;
107
- if ((_a = this.initializeParams.capabilities.textDocument) === null || _a === void 0 ? void 0 : _a.publishDiagnostics) {
108
- this.diagnosticQueue = new diagnostic_queue_1.DiagnosticEventQueue(diagnostics => this.options.lspClient.publishDiagnostics(diagnostics), this.documents, this.initializeParams.capabilities.textDocument.publishDiagnostics, this.logger);
109
- }
144
+ this.workspaceRoot = this.initializeParams.rootUri ? (0, protocol_translation_1.uriToPath)(this.initializeParams.rootUri) : this.initializeParams.rootPath || undefined;
145
+ this.diagnosticQueue = new diagnostic_queue_1.DiagnosticEventQueue(diagnostics => this.options.lspClient.publishDiagnostics(diagnostics), this.documents, (_a = this.initializeParams.capabilities.textDocument) === null || _a === void 0 ? void 0 : _a.publishDiagnostics, this.logger);
110
146
  const userInitializationOptions = this.initializeParams.initializationOptions || {};
111
- const { hostInfo, maxTsServerMemory } = userInitializationOptions;
147
+ const { disableAutomaticTypingAcquisition, hostInfo, maxTsServerMemory } = userInitializationOptions;
112
148
  const { logVerbosity, plugins, preferences } = {
113
149
  logVerbosity: userInitializationOptions.logVerbosity || this.options.tsserverLogVerbosity,
114
150
  plugins: userInitializationOptions.plugins || [],
115
- preferences: Object.assign({ includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, userInitializationOptions.preferences)
151
+ preferences: Object.assign({ allowIncompleteCompletions: true, allowRenameOfImportPath: true, allowTextChangesInNewFiles: true, displayPartsForJSDoc: true, generateReturnInDocTemplate: true, includeAutomaticOptionalChainCompletions: true, includeCompletionsForImportStatements: true, includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true, includeCompletionsWithSnippetText: true }, userInitializationOptions.preferences)
116
152
  };
117
153
  const logFile = this.getLogFile(logVerbosity);
118
154
  const globalPlugins = [];
@@ -122,10 +158,13 @@ class LspServer {
122
158
  pluginProbeLocations.push(plugin.location);
123
159
  }
124
160
  const tsserverPath = this.findTsserverPath();
161
+ const typescriptVersion = this.getTypeScriptVersion(tsserverPath);
162
+ this.logger.info(`Using Typescript version ${typescriptVersion === null || typescriptVersion === void 0 ? void 0 : typescriptVersion.displayName} from path: ${tsserverPath}`);
125
163
  this.tspClient = new tsp_client_1.TspClient({
126
164
  tsserverPath,
127
165
  logFile,
128
166
  logVerbosity,
167
+ disableAutomaticTypingAcquisition,
129
168
  maxTsServerMemory,
130
169
  globalPlugins,
131
170
  pluginProbeLocations,
@@ -133,7 +172,10 @@ class LspServer {
133
172
  onEvent: this.onTsEvent.bind(this)
134
173
  });
135
174
  this.tspClient.start();
136
- this.tspClient.request("configure" /* Configure */, Object.assign(Object.assign({}, hostInfo ? { hostInfo } : {}), { preferences: Object.assign({ allowTextChangesInNewFiles: true }, preferences) }));
175
+ this.tspClient.request("configure" /* Configure */, Object.assign(Object.assign({}, hostInfo ? { hostInfo } : {}), { formatOptions: {
176
+ // We can use \n here since the editor should normalize later on to its line endings.
177
+ newLineCharacter: '\n'
178
+ }, preferences }));
137
179
  this.tspClient.request("compilerOptionsForInferredProjects" /* CompilerOptionsForInferredProjects */, {
138
180
  options: {
139
181
  module: "CommonJS" /* CommonJS */,
@@ -144,7 +186,7 @@ class LspServer {
144
186
  allowNonTsExtensions: true
145
187
  }
146
188
  });
147
- const logFileUri = logFile && protocol_translation_1.pathToUri(logFile, undefined);
189
+ const logFileUri = logFile && (0, protocol_translation_1.pathToUri)(logFile, undefined);
148
190
  this.initializeResult = {
149
191
  capabilities: {
150
192
  textDocumentSync: lsp.TextDocumentSyncKind.Incremental,
@@ -152,7 +194,9 @@ class LspServer {
152
194
  triggerCharacters: ['.', '"', '\'', '/', '@', '<'],
153
195
  resolveProvider: true
154
196
  },
155
- codeActionProvider: true,
197
+ codeActionProvider: {
198
+ codeActionKinds: [commands_1.CodeActions.SourceOrganizeImportsTsLs]
199
+ },
156
200
  definitionProvider: true,
157
201
  documentFormattingProvider: true,
158
202
  documentRangeFormattingProvider: true,
@@ -203,14 +247,23 @@ class LspServer {
203
247
  if (this.options.tsserverLogFile) {
204
248
  return this.options.tsserverLogFile;
205
249
  }
206
- if (this.initializeParams.rootUri) {
207
- return path.join(protocol_translation_1.uriToPath(this.initializeParams.rootUri), '.log/tsserver.log');
208
- }
209
- if (this.initializeParams.rootPath) {
210
- return path.join(this.initializeParams.rootPath, '.log/tsserver.log');
250
+ if (this.workspaceRoot) {
251
+ return path.join(this.workspaceRoot, '.log/tsserver.log');
211
252
  }
212
253
  return undefined;
213
254
  }
255
+ didChangeConfiguration(params) {
256
+ this.workspaceConfiguration = params.settings || {};
257
+ }
258
+ getWorkspacePreferencesForDocument(file) {
259
+ var _a;
260
+ const doc = this.documents.get(file);
261
+ if (!doc) {
262
+ return {};
263
+ }
264
+ const preferencesKey = doc.languageId.startsWith('typescript') ? 'typescript' : 'javascript';
265
+ return (_a = this.workspaceConfiguration[preferencesKey]) !== null && _a !== void 0 ? _a : {};
266
+ }
214
267
  interuptDiagnostics(f) {
215
268
  if (!this.diagnosticsTokenSource) {
216
269
  return f();
@@ -242,7 +295,7 @@ class LspServer {
242
295
  }
243
296
  }
244
297
  didOpenTextDocument(params) {
245
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
298
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
246
299
  this.logger.log('onDidOpenTextDocument', params, file);
247
300
  if (!file) {
248
301
  return;
@@ -252,7 +305,7 @@ class LspServer {
252
305
  file,
253
306
  fileContent: params.textDocument.text,
254
307
  scriptKindName: this.getScriptKindName(params.textDocument.languageId),
255
- projectRootPath: this.rootPath()
308
+ projectRootPath: this.workspaceRoot
256
309
  });
257
310
  this.requestDiagnostics();
258
311
  }
@@ -278,7 +331,7 @@ class LspServer {
278
331
  return undefined;
279
332
  }
280
333
  didCloseTextDocument(params) {
281
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
334
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
282
335
  this.logger.log('onDidCloseTextDocument', params, file);
283
336
  if (!file) {
284
337
  return;
@@ -300,7 +353,7 @@ class LspServer {
300
353
  }
301
354
  didChangeTextDocument(params) {
302
355
  const { textDocument } = params;
303
- const file = protocol_translation_1.uriToPath(textDocument.uri);
356
+ const file = (0, protocol_translation_1.uriToPath)(textDocument.uri);
304
357
  this.logger.log('onDidChangeTextDocument', params, file);
305
358
  if (!file) {
306
359
  return;
@@ -373,7 +426,7 @@ class LspServer {
373
426
  }
374
427
  getDefinition({ type, params }) {
375
428
  return __awaiter(this, void 0, void 0, function* () {
376
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
429
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
377
430
  this.logger.log(type, params, file);
378
431
  if (!file) {
379
432
  return [];
@@ -383,12 +436,12 @@ class LspServer {
383
436
  line: params.position.line + 1,
384
437
  offset: params.position.character + 1
385
438
  });
386
- return result.body ? result.body.map(fileSpan => protocol_translation_1.toLocation(fileSpan, this.documents)) : [];
439
+ return result.body ? result.body.map(fileSpan => (0, protocol_translation_1.toLocation)(fileSpan, this.documents)) : [];
387
440
  });
388
441
  }
389
442
  documentSymbol(params) {
390
443
  return __awaiter(this, void 0, void 0, function* () {
391
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
444
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
392
445
  this.logger.log('symbol', params, file);
393
446
  if (!file) {
394
447
  return [];
@@ -403,13 +456,13 @@ class LspServer {
403
456
  if (this.supportHierarchicalDocumentSymbol) {
404
457
  const symbols = [];
405
458
  for (const item of tree.childItems) {
406
- document_symbol_1.collectDocumentSymbols(item, symbols);
459
+ (0, document_symbol_1.collectDocumentSymbols)(item, symbols);
407
460
  }
408
461
  return symbols;
409
462
  }
410
463
  const symbols = [];
411
464
  for (const item of tree.childItems) {
412
- document_symbol_1.collectSymbolInformation(params.textDocument.uri, item, symbols);
465
+ (0, document_symbol_1.collectSymbolInformation)(params.textDocument.uri, item, symbols);
413
466
  }
414
467
  return symbols;
415
468
  });
@@ -425,7 +478,7 @@ class LspServer {
425
478
  */
426
479
  completion(params) {
427
480
  return __awaiter(this, void 0, void 0, function* () {
428
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
481
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
429
482
  this.logger.log('completion', params, file);
430
483
  if (!file) {
431
484
  return lsp.CompletionList.create([]);
@@ -443,7 +496,7 @@ class LspServer {
443
496
  const { body } = result;
444
497
  const completions = (body ? body.entries : [])
445
498
  .filter(entry => entry.kind !== 'warning')
446
- .map(entry => completion_1.asCompletionItem(entry, file, params.position, document));
499
+ .map(entry => (0, completion_1.asCompletionItem)(entry, file, params.position, document));
447
500
  return lsp.CompletionList.create(completions, body === null || body === void 0 ? void 0 : body.isIncomplete);
448
501
  }
449
502
  catch (error) {
@@ -465,12 +518,12 @@ class LspServer {
465
518
  if (!details) {
466
519
  return item;
467
520
  }
468
- return completion_1.asResolvedCompletionItem(item, details);
521
+ return (0, completion_1.asResolvedCompletionItem)(item, details);
469
522
  });
470
523
  }
471
524
  hover(params) {
472
525
  return __awaiter(this, void 0, void 0, function* () {
473
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
526
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
474
527
  this.logger.log('hover', params, file);
475
528
  if (!file) {
476
529
  return { contents: [] };
@@ -479,12 +532,13 @@ class LspServer {
479
532
  if (!result || !result.body) {
480
533
  return { contents: [] };
481
534
  }
482
- const range = protocol_translation_1.asRange(result.body);
483
- const contents = [
484
- { language: 'typescript', value: result.body.displayString }
485
- ];
486
- const tags = protocol_translation_1.asTagsDocumentation(result.body.tags);
487
- const documentation = protocol_translation_1.asPlainText(result.body.documentation);
535
+ const range = (0, protocol_translation_1.asRange)(result.body);
536
+ const contents = [];
537
+ if (result.body.displayString) {
538
+ contents.push({ language: 'typescript', value: result.body.displayString });
539
+ }
540
+ const tags = (0, protocol_translation_1.asTagsDocumentation)(result.body.tags);
541
+ const documentation = (0, protocol_translation_1.asPlainText)(result.body.documentation);
488
542
  contents.push(documentation + (tags ? '\n\n' + tags : ''));
489
543
  return {
490
544
  contents,
@@ -508,7 +562,7 @@ class LspServer {
508
562
  }
509
563
  rename(params) {
510
564
  return __awaiter(this, void 0, void 0, function* () {
511
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
565
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
512
566
  this.logger.log('onRename', params, file);
513
567
  if (!file) {
514
568
  return undefined;
@@ -526,13 +580,13 @@ class LspServer {
526
580
  };
527
581
  result.body.locs
528
582
  .forEach((spanGroup) => {
529
- const uri = protocol_translation_1.pathToUri(spanGroup.file, this.documents), textEdits = workspaceEdit.changes[uri] || (workspaceEdit.changes[uri] = []);
583
+ const uri = (0, protocol_translation_1.pathToUri)(spanGroup.file, this.documents), textEdits = workspaceEdit.changes[uri] || (workspaceEdit.changes[uri] = []);
530
584
  spanGroup.locs.forEach((textSpan) => {
531
585
  textEdits.push({
532
586
  newText: params.newName,
533
587
  range: {
534
- start: protocol_translation_1.toPosition(textSpan.start),
535
- end: protocol_translation_1.toPosition(textSpan.end)
588
+ start: (0, protocol_translation_1.toPosition)(textSpan.start),
589
+ end: (0, protocol_translation_1.toPosition)(textSpan.end)
536
590
  }
537
591
  });
538
592
  });
@@ -542,7 +596,7 @@ class LspServer {
542
596
  }
543
597
  references(params) {
544
598
  return __awaiter(this, void 0, void 0, function* () {
545
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
599
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
546
600
  this.logger.log('onReferences', params, file);
547
601
  if (!file) {
548
602
  return [];
@@ -556,33 +610,20 @@ class LspServer {
556
610
  return [];
557
611
  }
558
612
  return result.body.refs
559
- .map(fileSpan => protocol_translation_1.toLocation(fileSpan, this.documents));
613
+ .map(fileSpan => (0, protocol_translation_1.toLocation)(fileSpan, this.documents));
560
614
  });
561
615
  }
562
616
  documentFormatting(params) {
563
617
  return __awaiter(this, void 0, void 0, function* () {
564
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
618
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
565
619
  this.logger.log('documentFormatting', params, file);
566
620
  if (!file) {
567
621
  return [];
568
622
  }
569
- let opts = Object.assign({}, params.options);
570
- // translate
571
- if (opts.convertTabsToSpaces === undefined) {
572
- opts.convertTabsToSpaces = params.options.insertSpaces;
573
- }
574
- if (opts.indentSize === undefined) {
575
- opts.indentSize = params.options.tabSize;
576
- }
577
- try {
578
- opts = JSON.parse(fs.readFileSync(this.rootPath() + '/tsfmt.json', 'utf-8'));
579
- }
580
- catch (err) {
581
- this.logger.log(`No formatting options found ${err}`);
582
- }
623
+ const formatOptions = this.getFormattingOptions(file, params.options);
583
624
  // options are not yet supported in tsserver, but we can send a configure request first
584
625
  yield this.tspClient.request("configure" /* Configure */, {
585
- formatOptions: opts
626
+ formatOptions
586
627
  });
587
628
  const response = yield this.tspClient.request("format" /* Format */, {
588
629
  file,
@@ -590,38 +631,25 @@ class LspServer {
590
631
  offset: 1,
591
632
  endLine: Number.MAX_SAFE_INTEGER,
592
633
  endOffset: Number.MAX_SAFE_INTEGER,
593
- options: opts
634
+ options: formatOptions
594
635
  });
595
636
  if (response.body) {
596
- return response.body.map(e => protocol_translation_1.toTextEdit(e));
637
+ return response.body.map(e => (0, protocol_translation_1.toTextEdit)(e));
597
638
  }
598
639
  return [];
599
640
  });
600
641
  }
601
642
  documentRangeFormatting(params) {
602
643
  return __awaiter(this, void 0, void 0, function* () {
603
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
644
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
604
645
  this.logger.log('documentRangeFormatting', params, file);
605
646
  if (!file) {
606
647
  return [];
607
648
  }
608
- let opts = Object.assign({}, params.options);
609
- // translate
610
- if (opts.convertTabsToSpaces === undefined) {
611
- opts.convertTabsToSpaces = params.options.insertSpaces;
612
- }
613
- if (opts.indentSize === undefined) {
614
- opts.indentSize = params.options.tabSize;
615
- }
616
- try {
617
- opts = JSON.parse(fs.readFileSync(this.rootPath() + '/tsfmt.json', 'utf-8'));
618
- }
619
- catch (err) {
620
- this.logger.log(`No formatting options found ${err}`);
621
- }
649
+ const formatOptions = this.getFormattingOptions(file, params.options);
622
650
  // options are not yet supported in tsserver, but we can send a configure request first
623
651
  yield this.tspClient.request("configure" /* Configure */, {
624
- formatOptions: opts
652
+ formatOptions
625
653
  });
626
654
  const response = yield this.tspClient.request("format" /* Format */, {
627
655
  file,
@@ -629,17 +657,37 @@ class LspServer {
629
657
  offset: params.range.start.character + 1,
630
658
  endLine: params.range.end.line + 1,
631
659
  endOffset: params.range.end.character + 1,
632
- options: opts
660
+ options: formatOptions
633
661
  });
634
662
  if (response.body) {
635
- return response.body.map(e => protocol_translation_1.toTextEdit(e));
663
+ return response.body.map(e => (0, protocol_translation_1.toTextEdit)(e));
636
664
  }
637
665
  return [];
638
666
  });
639
667
  }
668
+ getFormattingOptions(file, requestOptions) {
669
+ const workspacePreference = this.getWorkspacePreferencesForDocument(file);
670
+ let opts = Object.assign(Object.assign({}, (workspacePreference === null || workspacePreference === void 0 ? void 0 : workspacePreference.format) || {}), requestOptions);
671
+ // translate
672
+ if (opts.convertTabsToSpaces === undefined) {
673
+ opts.convertTabsToSpaces = requestOptions.insertSpaces;
674
+ }
675
+ if (opts.indentSize === undefined) {
676
+ opts.indentSize = requestOptions.tabSize;
677
+ }
678
+ if (this.workspaceRoot) {
679
+ try {
680
+ opts = JSON.parse(fs.readFileSync(this.workspaceRoot + '/tsfmt.json', 'utf-8'));
681
+ }
682
+ catch (err) {
683
+ this.logger.log(`No formatting options found ${err}`);
684
+ }
685
+ }
686
+ return opts;
687
+ }
640
688
  signatureHelp(params) {
641
689
  return __awaiter(this, void 0, void 0, function* () {
642
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
690
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
643
691
  this.logger.log('signatureHelp', params, file);
644
692
  if (!file) {
645
693
  return undefined;
@@ -648,7 +696,7 @@ class LspServer {
648
696
  if (!response || !response.body) {
649
697
  return undefined;
650
698
  }
651
- return hover_1.asSignatureHelp(response.body);
699
+ return (0, hover_1.asSignatureHelp)(response.body);
652
700
  });
653
701
  }
654
702
  getSignatureHelp(file, position) {
@@ -666,24 +714,34 @@ class LspServer {
666
714
  });
667
715
  }
668
716
  codeAction(params) {
717
+ var _a;
669
718
  return __awaiter(this, void 0, void 0, function* () {
670
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
719
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
671
720
  this.logger.log('codeAction', params, file);
672
721
  if (!file) {
673
722
  return [];
674
723
  }
675
- const args = protocol_translation_1.toFileRangeRequestArgs(file, params.range);
724
+ const args = (0, protocol_translation_1.toFileRangeRequestArgs)(file, params.range);
676
725
  const actions = [];
677
726
  if (!params.context.only || params.context.only.includes(node_1.CodeActionKind.QuickFix)) {
678
727
  const errorCodes = params.context.diagnostics.map(diagnostic => Number(diagnostic.code));
679
- actions.push(...quickfix_1.provideQuickFix(yield this.getCodeFixes(Object.assign(Object.assign({}, args), { errorCodes })), this.documents));
728
+ actions.push(...(0, quickfix_1.provideQuickFix)(yield this.getCodeFixes(Object.assign(Object.assign({}, args), { errorCodes })), this.documents));
680
729
  }
681
730
  if (!params.context.only || params.context.only.includes(node_1.CodeActionKind.Refactor)) {
682
- actions.push(...refactor_1.provideRefactors(yield this.getRefactors(args), args));
731
+ actions.push(...(0, refactor_1.provideRefactors)(yield this.getRefactors(args), args));
683
732
  }
684
733
  // organize import is provided by tsserver for any line, so we only get it if explicitly requested
685
- if (params.context.only && params.context.only.includes(node_1.CodeActionKind.SourceOrganizeImports)) {
686
- actions.push(...organize_imports_1.provideOrganizeImports(yield this.getOrganizeImports({ scope: { type: 'file', args } })));
734
+ if ((_a = params.context.only) === null || _a === void 0 ? void 0 : _a.includes(commands_1.CodeActions.SourceOrganizeImportsTsLs)) {
735
+ // see this issue for more context about how this argument is used
736
+ // https://github.com/microsoft/TypeScript/issues/43051
737
+ const skipDestructiveCodeActions = params.context.diagnostics.some(
738
+ // assume no severity is an error
739
+ d => { var _a; return ((_a = d.severity) !== null && _a !== void 0 ? _a : 0) <= 2; });
740
+ const response = yield this.getOrganizeImports({
741
+ scope: { type: 'file', args },
742
+ skipDestructiveCodeActions
743
+ });
744
+ actions.push(...(0, organize_imports_1.provideOrganizeImports)(response, this.documents));
687
745
  }
688
746
  return actions;
689
747
  });
@@ -754,19 +812,21 @@ class LspServer {
754
812
  if (renameLocation) {
755
813
  yield this.options.lspClient.rename({
756
814
  textDocument: {
757
- uri: protocol_translation_1.pathToUri(args.file, this.documents)
815
+ uri: (0, protocol_translation_1.pathToUri)(args.file, this.documents)
758
816
  },
759
- position: protocol_translation_1.toPosition(renameLocation)
817
+ position: (0, protocol_translation_1.toPosition)(renameLocation)
760
818
  });
761
819
  }
762
820
  }
763
821
  else if (arg.command === commands_1.Commands.ORGANIZE_IMPORTS && arg.arguments) {
764
822
  const file = arg.arguments[0];
823
+ const additionalArguments = arg.arguments[1] || {};
765
824
  const { body } = yield this.tspClient.request("organizeImports" /* OrganizeImports */, {
766
825
  scope: {
767
826
  type: 'file',
768
827
  args: { file }
769
- }
828
+ },
829
+ skipDestructiveCodeActions: additionalArguments.skipDestructiveCodeActions
770
830
  });
771
831
  yield this.applyFileCodeEdits(body);
772
832
  }
@@ -774,6 +834,19 @@ class LspServer {
774
834
  const { sourceUri, targetUri } = arg.arguments[0];
775
835
  this.applyRenameFile(sourceUri, targetUri);
776
836
  }
837
+ else if (arg.command === commands_1.Commands.APPLY_COMPLETION_CODE_ACTION && arg.arguments) {
838
+ const [_, codeActions] = arg.arguments;
839
+ for (const codeAction of codeActions) {
840
+ yield this.applyFileCodeEdits(codeAction.changes);
841
+ if (codeAction.commands && codeAction.commands.length) {
842
+ for (const command of codeAction.commands) {
843
+ yield this.tspClient.request("applyCodeActionCommand" /* ApplyCodeActionCommand */, { command });
844
+ }
845
+ }
846
+ // Execute only the first code action.
847
+ break;
848
+ }
849
+ }
777
850
  else {
778
851
  this.logger.error(`Unknown command ${arg.command}.`);
779
852
  }
@@ -786,7 +859,7 @@ class LspServer {
786
859
  }
787
860
  const changes = {};
788
861
  for (const edit of edits) {
789
- changes[protocol_translation_1.pathToUri(edit.fileName, this.documents)] = edit.textChanges.map(protocol_translation_1.toTextEdit);
862
+ changes[(0, protocol_translation_1.pathToUri)(edit.fileName, this.documents)] = edit.textChanges.map(protocol_translation_1.toTextEdit);
790
863
  }
791
864
  const { applied } = yield this.options.lspClient.applyWorkspaceEdit({
792
865
  edit: { changes }
@@ -802,8 +875,8 @@ class LspServer {
802
875
  }
803
876
  getEditsForFileRename(sourceUri, targetUri) {
804
877
  return __awaiter(this, void 0, void 0, function* () {
805
- const newFilePath = protocol_translation_1.uriToPath(targetUri);
806
- const oldFilePath = protocol_translation_1.uriToPath(sourceUri);
878
+ const newFilePath = (0, protocol_translation_1.uriToPath)(targetUri);
879
+ const oldFilePath = (0, protocol_translation_1.uriToPath)(sourceUri);
807
880
  if (!newFilePath || !oldFilePath) {
808
881
  return [];
809
882
  }
@@ -821,7 +894,7 @@ class LspServer {
821
894
  }
822
895
  documentHighlight(arg) {
823
896
  return __awaiter(this, void 0, void 0, function* () {
824
- const file = protocol_translation_1.uriToPath(arg.textDocument.uri);
897
+ const file = (0, protocol_translation_1.uriToPath)(arg.textDocument.uri);
825
898
  this.logger.log('documentHighlight', arg, file);
826
899
  if (!file) {
827
900
  return [];
@@ -845,19 +918,16 @@ class LspServer {
845
918
  for (const item of response.body) {
846
919
  // tsp returns item.file with POSIX path delimiters, whereas file is platform specific.
847
920
  // Converting to a URI and back to a path ensures consistency.
848
- if (protocol_translation_1.uriToPath(protocol_translation_1.pathToUri(item.file, this.documents)) === file) {
849
- const highlights = protocol_translation_1.toDocumentHighlight(item);
921
+ if ((0, protocol_translation_1.normalizePath)(item.file) === file) {
922
+ const highlights = (0, protocol_translation_1.toDocumentHighlight)(item);
850
923
  result.push(...highlights);
851
924
  }
852
925
  }
853
926
  return result;
854
927
  });
855
928
  }
856
- rootPath() {
857
- return this.initializeParams.rootUri ? protocol_translation_1.uriToPath(this.initializeParams.rootUri) : this.initializeParams.rootPath;
858
- }
859
929
  lastFileOrDummy() {
860
- return this.documents.files[0] || this.rootPath();
930
+ return this.documents.files[0] || this.workspaceRoot;
861
931
  }
862
932
  workspaceSymbol(params) {
863
933
  return __awaiter(this, void 0, void 0, function* () {
@@ -871,13 +941,13 @@ class LspServer {
871
941
  return result.body.map(item => {
872
942
  return {
873
943
  location: {
874
- uri: protocol_translation_1.pathToUri(item.file, this.documents),
944
+ uri: (0, protocol_translation_1.pathToUri)(item.file, this.documents),
875
945
  range: {
876
- start: protocol_translation_1.toPosition(item.start),
877
- end: protocol_translation_1.toPosition(item.end)
946
+ start: (0, protocol_translation_1.toPosition)(item.start),
947
+ end: (0, protocol_translation_1.toPosition)(item.end)
878
948
  }
879
949
  },
880
- kind: protocol_translation_1.toSymbolKind(item.kind),
950
+ kind: (0, protocol_translation_1.toSymbolKind)(item.kind),
881
951
  name: item.name
882
952
  };
883
953
  });
@@ -888,7 +958,7 @@ class LspServer {
888
958
  */
889
959
  foldingRanges(params) {
890
960
  return __awaiter(this, void 0, void 0, function* () {
891
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
961
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
892
962
  this.logger.log('foldingRanges', params, file);
893
963
  if (!file) {
894
964
  return undefined;
@@ -912,7 +982,7 @@ class LspServer {
912
982
  });
913
983
  }
914
984
  asFoldingRange(span, document) {
915
- const range = protocol_translation_1.asRange(span.textSpan);
985
+ const range = (0, protocol_translation_1.asRange)(span.textSpan);
916
986
  const kind = this.asFoldingRangeKind(span);
917
987
  // workaround for https://github.com/Microsoft/vscode/issues/49904
918
988
  if (span.kind === 'comment') {
@@ -955,21 +1025,74 @@ class LspServer {
955
1025
  calls(params) {
956
1026
  return __awaiter(this, void 0, void 0, function* () {
957
1027
  let callsResult = { calls: [] };
958
- const file = protocol_translation_1.uriToPath(params.textDocument.uri);
1028
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
959
1029
  this.logger.log('calls', params, file);
960
1030
  if (!file) {
961
1031
  return callsResult;
962
1032
  }
963
1033
  if (params.direction === lspcalls.CallDirection.Outgoing) {
964
1034
  const documentProvider = (file) => this.documents.get(file);
965
- callsResult = yield calls_1.computeCallees(this.tspClient, params, documentProvider);
1035
+ callsResult = yield (0, calls_1.computeCallees)(this.tspClient, params, documentProvider);
966
1036
  }
967
1037
  else {
968
- callsResult = yield calls_1.computeCallers(this.tspClient, params);
1038
+ callsResult = yield (0, calls_1.computeCallers)(this.tspClient, params);
969
1039
  }
970
1040
  return callsResult;
971
1041
  });
972
1042
  }
1043
+ inlayHints(params) {
1044
+ var _a, _b, _c, _d, _e, _f;
1045
+ return __awaiter(this, void 0, void 0, function* () {
1046
+ const file = (0, protocol_translation_1.uriToPath)(params.textDocument.uri);
1047
+ this.logger.log('inlayHints', params, file);
1048
+ if (!file) {
1049
+ return { inlayHints: [] };
1050
+ }
1051
+ const inlayHintsOptions = this.getInlayHintsOptions(file);
1052
+ this.tspClient.request("configure" /* Configure */, {
1053
+ preferences: inlayHintsOptions
1054
+ });
1055
+ const doc = this.documents.get(file);
1056
+ if (!doc) {
1057
+ return { inlayHints: [] };
1058
+ }
1059
+ const start = doc.offsetAt((_b = (_a = params.range) === null || _a === void 0 ? void 0 : _a.start) !== null && _b !== void 0 ? _b : {
1060
+ line: 0,
1061
+ character: 0
1062
+ });
1063
+ const end = doc.offsetAt((_d = (_c = params.range) === null || _c === void 0 ? void 0 : _c.end) !== null && _d !== void 0 ? _d : {
1064
+ line: doc.lineCount + 1,
1065
+ character: 0
1066
+ });
1067
+ try {
1068
+ const result = yield this.tspClient.request("provideInlayHints" /* ProvideInlayHints */, {
1069
+ file,
1070
+ start: start,
1071
+ length: end - start
1072
+ });
1073
+ return {
1074
+ inlayHints: (_f = (_e = result.body) === null || _e === void 0 ? void 0 : _e.map((item) => ({
1075
+ text: item.text,
1076
+ position: (0, protocol_translation_1.toPosition)(item.position),
1077
+ whitespaceAfter: item.whitespaceAfter,
1078
+ whitespaceBefore: item.whitespaceBefore,
1079
+ kind: item.kind
1080
+ }))) !== null && _f !== void 0 ? _f : []
1081
+ };
1082
+ }
1083
+ catch (_g) {
1084
+ return {
1085
+ inlayHints: []
1086
+ };
1087
+ }
1088
+ });
1089
+ }
1090
+ getInlayHintsOptions(file) {
1091
+ var _a, _b;
1092
+ const workspacePreference = this.getWorkspacePreferencesForDocument(file);
1093
+ const userPreferences = ((_a = this.initializeParams.initializationOptions) === null || _a === void 0 ? void 0 : _a.preferences) || {};
1094
+ return Object.assign(Object.assign({}, userPreferences), (_b = workspacePreference.inlayHints) !== null && _b !== void 0 ? _b : {});
1095
+ }
973
1096
  }
974
1097
  exports.LspServer = LspServer;
975
1098
  //# sourceMappingURL=lsp-server.js.map