typescript-language-server
Advanced tools
Comparing version 0.6.1 to 0.6.2
# Changelog | ||
All notable changes to this project will be documented in this file. | ||
## [0.6.2] - 2021-08-16 | ||
- Mark completion items as deprecated if JSDoc says so (#227) | ||
- Add a `maxTsServerMemory` option (#252) | ||
- (chore) Add Windows and Mac CI runner (#248) | ||
## [0.6.1] - 2021-08-16 | ||
@@ -5,0 +11,0 @@ |
@@ -70,10 +70,16 @@ "use strict"; | ||
} | ||
if (entry.kindModifiers && entry.kindModifiers.match(/\boptional\b/)) { | ||
if (!insertText) { | ||
insertText = item.label; | ||
if (entry.kindModifiers) { | ||
const kindModifiers = new Set(entry.kindModifiers.split(/,|\s+/g)); | ||
if (kindModifiers.has('optional')) { | ||
if (!insertText) { | ||
insertText = item.label; | ||
} | ||
if (!item.filterText) { | ||
item.filterText = item.label; | ||
} | ||
item.label += '?'; | ||
} | ||
if (!item.filterText) { | ||
item.filterText = item.label; | ||
if (kindModifiers.has('deprecated')) { | ||
item.tags = [lsp.CompletionItemTag.Deprecated]; | ||
} | ||
item.label += '?'; | ||
} | ||
@@ -80,0 +86,0 @@ if (insertText && replacementRange) { |
@@ -111,3 +111,3 @@ "use strict"; | ||
const userInitializationOptions = this.initializeParams.initializationOptions || {}; | ||
const { hostInfo } = userInitializationOptions; | ||
const { hostInfo, maxTsServerMemory } = userInitializationOptions; | ||
const { logVerbosity, plugins, preferences } = { | ||
@@ -130,2 +130,3 @@ logVerbosity: userInitializationOptions.logVerbosity || this.options.tsserverLogVerbosity, | ||
logVerbosity, | ||
maxTsServerMemory, | ||
globalPlugins, | ||
@@ -132,0 +133,0 @@ pluginProbeLocations, |
@@ -43,3 +43,3 @@ "use strict"; | ||
const assert = chai.assert; | ||
let diagnostics; | ||
const diagnostics = new Map(); | ||
let server; | ||
@@ -49,3 +49,3 @@ before(() => __awaiter(void 0, void 0, void 0, function* () { | ||
rootUri: null, | ||
publishDiagnostics: args => diagnostics.push(args) | ||
publishDiagnostics: args => diagnostics.set(args.uri, args) | ||
}); | ||
@@ -56,3 +56,3 @@ })); | ||
// "closeAll" triggers final publishDiagnostics with an empty list so clear last. | ||
diagnostics = []; | ||
diagnostics.clear(); | ||
}); | ||
@@ -80,10 +80,9 @@ after(() => { | ||
assert.isNotNull(proposals); | ||
assert.isAbove(proposals.items.length, 800); | ||
assert.isAtLeast(proposals.items.length, 800); | ||
const item = proposals.items.find(i => i.label === 'addEventListener'); | ||
assert.isDefined(item); | ||
const resolvedItem = yield server.completionResolve(item); | ||
assert.isDefined(resolvedItem.detail, JSON.stringify(resolvedItem, undefined, 2)); | ||
server.didCloseTextDocument({ | ||
textDocument: doc | ||
}); | ||
assert.isNotTrue(resolvedItem.deprecated, 'resolved item is not deprecated'); | ||
assert.isDefined(resolvedItem.detail); | ||
server.didCloseTextDocument({ textDocument: doc }); | ||
})).timeout(10000); | ||
@@ -107,6 +106,7 @@ it('simple JS test', () => __awaiter(void 0, void 0, void 0, function* () { | ||
assert.isNotNull(proposals); | ||
assert.isAbove(proposals.items.length, 800); | ||
assert.isAtLeast(proposals.items.length, 800); | ||
const item = proposals.items.find(i => i.label === 'addEventListener'); | ||
assert.isDefined(item); | ||
const resolvedItem = yield server.completionResolve(item); | ||
assert.isTrue(resolvedItem.detail !== undefined, JSON.stringify(resolvedItem, undefined, 2)); | ||
assert.isDefined(resolvedItem.detail); | ||
const containsInvalidCompletions = proposals.items.reduce((accumulator, current) => { | ||
@@ -121,5 +121,34 @@ if (accumulator) { | ||
assert.isFalse(containsInvalidCompletions); | ||
server.didCloseTextDocument({ | ||
server.didCloseTextDocument({ textDocument: doc }); | ||
})).timeout(10000); | ||
it('deprecated by JSDoc', () => __awaiter(void 0, void 0, void 0, function* () { | ||
const doc = { | ||
uri: test_utils_1.uri('bar.ts'), | ||
languageId: 'typescript', | ||
version: 1, | ||
text: ` | ||
/** | ||
* documentation | ||
* @deprecated for a reason | ||
*/ | ||
export function foo() { | ||
console.log('test') | ||
} | ||
foo(); // call me | ||
` | ||
}; | ||
server.didOpenTextDocument({ | ||
textDocument: doc | ||
}); | ||
const pos = test_utils_1.position(doc, 'foo(); // call me'); | ||
const proposals = yield server.completion({ textDocument: doc, position: pos }); | ||
assert.isNotNull(proposals); | ||
const item = proposals.items.find(i => i.label === 'foo'); | ||
assert.isDefined(item); | ||
const resolvedItem = yield server.completionResolve(item); | ||
assert.isDefined(resolvedItem.detail); | ||
assert.isArray(resolvedItem.tags); | ||
assert.include(resolvedItem.tags, lsp.CompletionItemTag.Deprecated, 'resolved item is deprecated'); | ||
server.didCloseTextDocument({ textDocument: doc }); | ||
})).timeout(10000); | ||
@@ -143,5 +172,3 @@ it('incorrect source location', () => __awaiter(void 0, void 0, void 0, function* () { | ||
assert.isNull(proposals); | ||
server.didCloseTextDocument({ | ||
textDocument: doc | ||
}); | ||
server.didCloseTextDocument({ textDocument: doc }); | ||
})).timeout(10000); | ||
@@ -155,5 +182,3 @@ it('includes completions from global modules', () => __awaiter(void 0, void 0, void 0, function* () { | ||
}; | ||
server.didOpenTextDocument({ | ||
textDocument: doc | ||
}); | ||
server.didOpenTextDocument({ textDocument: doc }); | ||
const proposals = yield server.completion({ textDocument: doc, position: test_utils_1.position(doc, 'ex') }); | ||
@@ -163,5 +188,3 @@ assert.isNotNull(proposals); | ||
assert.isDefined(pathExistsCompletion); | ||
server.didCloseTextDocument({ | ||
textDocument: doc | ||
}); | ||
server.didCloseTextDocument({ textDocument: doc }); | ||
})).timeout(10000); | ||
@@ -182,5 +205,3 @@ it('includes completions with invalid identifier names', () => __awaiter(void 0, void 0, void 0, function* () { | ||
}; | ||
server.didOpenTextDocument({ | ||
textDocument: doc | ||
}); | ||
server.didOpenTextDocument({ textDocument: doc }); | ||
const proposals = yield server.completion({ textDocument: doc, position: test_utils_1.positionAfter(doc, '.i') }); | ||
@@ -192,5 +213,3 @@ assert.isNotNull(proposals); | ||
assert.equal(completion.textEdit.newText, '["invalid-identifier-name"]'); | ||
server.didCloseTextDocument({ | ||
textDocument: doc | ||
}); | ||
server.didCloseTextDocument({ textDocument: doc }); | ||
})).timeout(10000); | ||
@@ -215,5 +234,5 @@ }); | ||
yield new Promise(resolve => setTimeout(resolve, 200)); | ||
const diagnosticsForThisFile = diagnostics.filter(d => d.uri === doc.uri); | ||
assert.equal(diagnosticsForThisFile.length, 1, JSON.stringify(diagnostics)); | ||
const fileDiagnostics = diagnosticsForThisFile[0].diagnostics; | ||
const resultsForFile = diagnostics.get(doc.uri); | ||
assert.isDefined(resultsForFile); | ||
const fileDiagnostics = resultsForFile.diagnostics; | ||
assert.equal(fileDiagnostics.length, 1); | ||
@@ -240,3 +259,3 @@ assert.equal("Cannot find name 'missing'.", fileDiagnostics[0].message); | ||
yield new Promise(resolve => setTimeout(resolve, 200)); | ||
const resultsForFile = diagnostics.find(d => d.uri === doc.uri); | ||
const resultsForFile = diagnostics.get(doc.uri); | ||
assert.isDefined(resultsForFile); | ||
@@ -281,5 +300,9 @@ const fileDiagnostics = resultsForFile.diagnostics; | ||
yield new Promise(resolve => setTimeout(resolve, 200)); | ||
const diagnosticsForThisTest = diagnostics.filter(d => d.uri === doc.uri || d.uri === doc2.uri); | ||
yield new Promise(resolve => setTimeout(resolve, 200)); | ||
assert.equal(diagnosticsForThisTest.length, 2, JSON.stringify(diagnostics)); | ||
assert.equal(diagnostics.size, 2); | ||
const diagnosticsForDoc = diagnostics.get(doc.uri); | ||
const diagnosticsForDoc2 = diagnostics.get(doc2.uri); | ||
assert.isDefined(diagnosticsForDoc); | ||
assert.isDefined(diagnosticsForDoc2); | ||
assert.equal(diagnosticsForDoc.diagnostics.length, 1, JSON.stringify(diagnostics)); | ||
assert.equal(diagnosticsForDoc2.diagnostics.length, 1, JSON.stringify(diagnostics)); | ||
})).timeout(10000); | ||
@@ -428,3 +451,5 @@ }); | ||
yield new Promise(resolve => setTimeout(resolve, 200)); | ||
const fileDiagnostics = diagnostics.filter(d => d.uri === doc.uri)[0].diagnostics; | ||
const resultsForFile = diagnostics.get(doc.uri); | ||
assert.isDefined(resultsForFile); | ||
const fileDiagnostics = resultsForFile.diagnostics; | ||
assert.isTrue(fileDiagnostics.length >= 1, fileDiagnostics.map(d => d.message).join(',')); | ||
@@ -863,3 +888,3 @@ assert.equal("Cannot find name 'missing'.", fileDiagnostics[0].message); | ||
rootUri: null, | ||
publishDiagnostics: args => diagnostics.push(args), | ||
publishDiagnostics: args => diagnostics.set(args.uri, args), | ||
clientCapabilitiesOverride | ||
@@ -884,6 +909,6 @@ }); | ||
yield new Promise(resolve => setTimeout(resolve, 200)); | ||
const diagnosticsForThisFile = diagnostics.filter(d => d.uri === doc.uri); | ||
assert.isEmpty(diagnosticsForThisFile, 'Unexpected diagnostics received'); | ||
const resultsForFile = diagnostics.get(doc.uri); | ||
assert.isUndefined(resultsForFile, 'Unexpected diagnostics received'); | ||
})).timeout(10000); | ||
}); | ||
//# sourceMappingURL=lsp-server.spec.js.map |
@@ -31,2 +31,3 @@ "use strict"; | ||
const commands_1 = require("./commands"); | ||
const protocol_translation_1 = require("./protocol-translation"); | ||
const node_1 = require("vscode-languageserver/node"); | ||
@@ -37,5 +38,5 @@ function provideOrganizeImports(response) { | ||
} | ||
return response.body.map(edit => lsp.CodeAction.create('Organize imports', lsp.Command.create('', commands_1.Commands.ORGANIZE_IMPORTS, edit.fileName), node_1.CodeActionKind.SourceOrganizeImports)); | ||
return response.body.map(edit => lsp.CodeAction.create('Organize imports', lsp.Command.create('', commands_1.Commands.ORGANIZE_IMPORTS, protocol_translation_1.normalizeFileNameToFsPath(edit.fileName)), node_1.CodeActionKind.SourceOrganizeImports)); | ||
} | ||
exports.provideOrganizeImports = provideOrganizeImports; | ||
//# sourceMappingURL=organize-imports.js.map |
@@ -24,8 +24,10 @@ "use strict"; | ||
const organize_imports_1 = require("./organize-imports"); | ||
const test_utils_1 = require("./test-utils"); | ||
describe('provideOrganizeImports', () => { | ||
it('converts tsserver response to lsp code actions', () => { | ||
const fileName = test_utils_1.filePath('file'); | ||
const response = { | ||
body: [ | ||
{ | ||
fileName: '/my/file', | ||
fileName, | ||
textChanges: [] | ||
@@ -42,3 +44,3 @@ } | ||
command: '_typescript.organizeImports', | ||
arguments: ['/my/file'] | ||
arguments: [fileName] | ||
} | ||
@@ -45,0 +47,0 @@ }]; |
@@ -6,2 +6,11 @@ import * as lsp from 'vscode-languageserver/node'; | ||
export declare function pathToUri(filepath: string, documents: LspDocuments | undefined): string; | ||
/** | ||
* Normalizes the file system path. | ||
* | ||
* On systems other than Windows it should be an no-op. | ||
* | ||
* On Windows, an input path in a format like "c:/path/file.ts" | ||
* will be normalized to "c:\path\file.ts" (same as returned through URI.fsPath). | ||
*/ | ||
export declare function normalizeFileNameToFsPath(fileName: string): string; | ||
export declare function toPosition(location: tsp.Location): lsp.Position; | ||
@@ -8,0 +17,0 @@ export declare function toLocation(fileSpan: tsp.FileSpan, documents: LspDocuments | undefined): lsp.Location; |
@@ -31,3 +31,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.Range = exports.asPlainText = exports.asTagBodyText = exports.asTagDocumentation = exports.asTagsDocumentation = exports.asDocumentation = exports.asRange = exports.toDocumentHighlight = exports.toTextDocumentEdit = exports.toTextEdit = exports.toDiagnostic = exports.toSymbolKind = exports.toFileRangeRequestArgs = exports.toLocation = exports.toPosition = exports.pathToUri = exports.uriToPath = void 0; | ||
exports.Range = exports.asPlainText = exports.asTagBodyText = exports.asTagDocumentation = exports.asTagsDocumentation = exports.asDocumentation = exports.asRange = exports.toDocumentHighlight = exports.toTextDocumentEdit = exports.toTextEdit = exports.toDiagnostic = exports.toSymbolKind = exports.toFileRangeRequestArgs = exports.toLocation = exports.toPosition = exports.normalizeFileNameToFsPath = exports.pathToUri = exports.uriToPath = void 0; | ||
const lsp = __importStar(require("vscode-languageserver/node")); | ||
@@ -58,2 +58,14 @@ const vscode_uri_1 = __importDefault(require("vscode-uri")); | ||
exports.pathToUri = pathToUri; | ||
/** | ||
* Normalizes the file system path. | ||
* | ||
* On systems other than Windows it should be an no-op. | ||
* | ||
* On Windows, an input path in a format like "c:/path/file.ts" | ||
* will be normalized to "c:\path\file.ts" (same as returned through URI.fsPath). | ||
*/ | ||
function normalizeFileNameToFsPath(fileName) { | ||
return vscode_uri_1.default.file(fileName).fsPath; | ||
} | ||
exports.normalizeFileNameToFsPath = normalizeFileNameToFsPath; | ||
function currentVersion(filepath, documents) { | ||
@@ -60,0 +72,0 @@ const fileUri = vscode_uri_1.default.file(filepath); |
@@ -44,2 +44,3 @@ "use strict"; | ||
const logger_1 = require("./logger"); | ||
const utils_1 = require("./utils"); | ||
const vscode_languageserver_textdocument_1 = require("vscode-languageserver-textdocument"); | ||
@@ -71,3 +72,3 @@ function getDefaultClientCapabilities() { | ||
function filePath(suffix = '') { | ||
return path.resolve(__dirname, '../test-data', suffix); | ||
return protocol_translation_1.normalizeFileNameToFsPath(path.resolve(__dirname, '../test-data', suffix)); | ||
} | ||
@@ -105,3 +106,3 @@ exports.filePath = filePath; | ||
logger, | ||
tsserverPath: 'tsserver', | ||
tsserverPath: utils_1.getTsserverExecutable(), | ||
tsserverLogVerbosity: options.tsserverLogVerbosity, | ||
@@ -108,0 +109,0 @@ tsserverLogFile: path.resolve(__dirname, '../tsserver.log'), |
@@ -15,2 +15,3 @@ /** | ||
logVerbosity?: string; | ||
maxTsServerMemory?: number; | ||
plugins: TypeScriptPlugin[]; | ||
@@ -17,0 +18,0 @@ preferences?: UserPreferences; |
@@ -10,2 +10,3 @@ import protocol from 'typescript/lib/protocol'; | ||
logVerbosity?: string; | ||
maxTsServerMemory?: number; | ||
globalPlugins?: string[]; | ||
@@ -22,3 +23,2 @@ pluginProbeLocations?: string[]; | ||
'completionInfo': [protocol.CompletionsRequestArgs, protocol.CompletionInfoResponse]; | ||
'completions': [protocol.CompletionsRequestArgs, protocol.CompletionsResponse]; | ||
'configure': [protocol.ConfigureRequestArguments, protocol.ConfigureResponse]; | ||
@@ -25,0 +25,0 @@ 'definition': [protocol.FileLocationRequestArgs, protocol.DefinitionResponse]; |
@@ -52,22 +52,28 @@ "use strict"; | ||
} | ||
const { tsserverPath, logFile, logVerbosity, globalPlugins, pluginProbeLocations } = this.options; | ||
const { tsserverPath, logFile, logVerbosity, maxTsServerMemory, globalPlugins, pluginProbeLocations } = this.options; | ||
const args = []; | ||
if (logFile) { | ||
args.push('--logFile', logFile); | ||
args.push(`--logFile=${logFile}`); | ||
} | ||
if (logVerbosity) { | ||
args.push('--logVerbosity', logVerbosity); | ||
args.push(`--logVerbosity=${logVerbosity}`); | ||
} | ||
if (globalPlugins && globalPlugins.length) { | ||
args.push('--globalPlugins', globalPlugins.join(',')); | ||
args.push(`--globalPlugins=${globalPlugins.join(',')}`); | ||
} | ||
if (pluginProbeLocations && pluginProbeLocations.length) { | ||
args.push('--pluginProbeLocations', pluginProbeLocations.join(',')); | ||
args.push(`--pluginProbeLocations=${pluginProbeLocations.join(',')}`); | ||
} | ||
this.cancellationPipeName = tempy_1.default.file({ name: 'tscancellation' }); | ||
args.push('--cancellationPipeName', this.cancellationPipeName + '*'); | ||
args.push(`--cancellationPipeName=${this.cancellationPipeName}*`); | ||
this.logger.info(`Starting tsserver : '${tsserverPath} ${args.join(' ')}'`); | ||
const tsserverPathIsModule = path.extname(tsserverPath) === '.js'; | ||
const options = { | ||
silent: true, | ||
execArgv: [ | ||
...maxTsServerMemory ? [`--max-old-space-size=${maxTsServerMemory}`] : [] | ||
] | ||
}; | ||
this.tsserverProc = tsserverPathIsModule | ||
? cp.fork(tsserverPath, args, { silent: true, execArgv: [] }) | ||
? cp.fork(tsserverPath, args, options) | ||
: cp.spawn(tsserverPath, args); | ||
@@ -74,0 +80,0 @@ this.readlineInterface = readline.createInterface(this.tsserverProc.stdout, this.tsserverProc.stdin, undefined); |
@@ -27,2 +27,11 @@ "use strict"; | ||
}; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -35,6 +44,7 @@ const chai = __importStar(require("chai")); | ||
const modules_resolver_1 = require("./modules-resolver"); | ||
const utils_1 = require("./utils"); | ||
const assert = chai.assert; | ||
const executableServer = new tsp_client_1.TspClient({ | ||
logger: new logger_1.ConsoleLogger(), | ||
tsserverPath: 'tsserver' | ||
tsserverPath: utils_1.getTsserverExecutable() | ||
}); | ||
@@ -47,8 +57,8 @@ const tsserverModuleRelativePath = path.join('typescript', 'lib', 'tsserver.js'); | ||
}); | ||
const servers = { executableServer, moduleServer }; | ||
Object.keys(servers).forEach(serverName => { | ||
const server = servers[serverName]; | ||
server.start(); | ||
for (const [serverName, server] of Object.entries({ executableServer, moduleServer })) { | ||
describe('ts server client using ' + serverName, () => { | ||
it('completion', () => { | ||
before(() => { | ||
server.start(); | ||
}); | ||
it('completion', () => __awaiter(void 0, void 0, void 0, function* () { | ||
const f = test_utils_1.filePath('module2.ts'); | ||
@@ -59,14 +69,12 @@ server.notify("open" /* Open */, { | ||
}); | ||
return server.request("completions" /* Completions */, { | ||
const completions = yield server.request("completionInfo" /* CompletionInfo */, { | ||
file: f, | ||
line: 1, | ||
offset: 0, | ||
prefix: 'im', | ||
includeExternalModuleExports: true, | ||
includeInsertTextCompletions: true | ||
}).then(completions => { | ||
assert.equal(completions.body[1].name, 'ImageBitmap'); | ||
prefix: 'im' | ||
}); | ||
}).timeout(5000); | ||
it('references', () => { | ||
assert.isDefined(completions.body); | ||
assert.equal(completions.body.entries[1].name, 'ImageBitmap'); | ||
})).timeout(10000); | ||
it('references', () => __awaiter(void 0, void 0, void 0, function* () { | ||
const f = test_utils_1.filePath('module2.ts'); | ||
@@ -77,11 +85,11 @@ server.notify("open" /* Open */, { | ||
}); | ||
return server.request("references" /* References */, { | ||
const references = yield server.request("references" /* References */, { | ||
file: f, | ||
line: 8, | ||
offset: 16 | ||
}).then(references => { | ||
assert.equal(references.body.symbolName, 'doStuff'); | ||
}); | ||
}).timeout(5000); | ||
it('documentHighlight', () => { | ||
assert.isDefined(references.body); | ||
assert.equal(references.body.symbolName, 'doStuff'); | ||
})).timeout(10000); | ||
it('documentHighlight', () => __awaiter(void 0, void 0, void 0, function* () { | ||
const f = test_utils_1.filePath('module2.ts'); | ||
@@ -92,3 +100,3 @@ server.notify("open" /* Open */, { | ||
}); | ||
return server.request("documentHighlights" /* DocumentHighlights */, { | ||
const response = yield server.request("documentHighlights" /* DocumentHighlights */, { | ||
file: f, | ||
@@ -98,9 +106,9 @@ line: 8, | ||
filesToSearch: [f] | ||
}).then(response => { | ||
assert.isTrue(response.body.some(({ file }) => file.endsWith('module2.ts')), JSON.stringify(response.body, undefined, 2)); | ||
assert.isFalse(response.body.some(({ file }) => file.endsWith('module1.ts')), JSON.stringify(response.body, undefined, 2)); | ||
}); | ||
}).timeout(5000); | ||
assert.isDefined(response.body); | ||
assert.isTrue(response.body.some(({ file }) => file.endsWith('module2.ts')), JSON.stringify(response.body, undefined, 2)); | ||
assert.isFalse(response.body.some(({ file: file_1 }) => file_1.endsWith('module1.ts')), JSON.stringify(response.body, undefined, 2)); | ||
})).timeout(10000); | ||
}); | ||
}); | ||
} | ||
//# sourceMappingURL=tsp-client.spec.js.map |
@@ -25,4 +25,2 @@ /** | ||
Close = "close", | ||
/** @deprecated Prefer CompletionInfo -- see comment on CompletionsResponse */ | ||
Completions = "completions", | ||
CompletionInfo = "completionInfo", | ||
@@ -29,0 +27,0 @@ CompletionDetails = "completionEntryDetails", |
{ | ||
"name": "typescript-language-server", | ||
"version": "0.6.1", | ||
"version": "0.6.2", | ||
"description": "Language Server Protocol (LSP) implementation for TypeScript using tsserver", | ||
@@ -34,3 +34,3 @@ "author": "TypeFox and others", | ||
"test": "mocha --exit --reporter spec \"./lib/**/*.spec.js\"", | ||
"lint": "eslint --ext '.js,.ts' src", | ||
"lint": "eslint --ext \".js,.ts\" src", | ||
"build": "concurrently -n compile,lint -c blue,green \"yarn compile\" \"yarn lint\"", | ||
@@ -37,0 +37,0 @@ "compile": "tsc -b", |
111
README.md
@@ -5,2 +5,3 @@ [](https://travis-ci.org/theia-ide/typescript-language-server) | ||
# TypeScript Language Server | ||
[Language Server Protocol](https://github.com/Microsoft/language-server-protocol) implementation for TypeScript wrapping `tsserver`. | ||
@@ -14,23 +15,2 @@ | ||
# Supported Protocol features | ||
- [x] textDocument/didChange (incremental) | ||
- [x] textDocument/didClose | ||
- [x] textDocument/didOpen | ||
- [x] textDocument/didSave | ||
- [x] textDocument/codeAction | ||
- [x] textDocument/completion (incl. completion/resolve) | ||
- [x] textDocument/definition | ||
- [x] textDocument/documentHighlight | ||
- [x] textDocument/documentSymbol | ||
- [x] textDocument/executeCommand | ||
- [x] textDocument/formatting | ||
- [x] textDocument/rangeFormatting | ||
- [x] textDocument/hover | ||
- [x] textDocument/rename | ||
- [x] textDocument/references | ||
- [x] textDocument/signatureHelp | ||
- [x] workspace/symbol | ||
# Installing | ||
@@ -48,3 +28,3 @@ | ||
## Options | ||
## CLI Options | ||
@@ -68,2 +48,89 @@ ``` | ||
## initializationOptions | ||
The language server accepts various settings through the `initializationOptions` object passed through the `initialize` request. Refer to your LSP client's documentation on how to set these. Here is the list of supported options: | ||
| Setting | Type | Description | | ||
|:------------------|:---------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | ||
| hostInfo | string | Information about the host, for example `"Emacs 24.4"` or `"Sublime Text v3075"`. **Default**: `undefined` | | ||
| logVerbosity | string | The verbosity level of the information printed in the log. Accepts values: `"off"`, `"terse"`, `"normal"`, `"requesttime"`, `"verbose"`. **Default**: `undefined` (`"off"`). | | ||
| maxTsServerMemory | number | The maximum size of the V8's old memory section in megabytes (for example `4096` means 4GB). The default value is dynamically configured by Node so can differ per system. Increase for very big projects that exceed allowed memory usage. **Default**: `undefined` | | ||
| plugins | object[] | An array of `{ name: string, location: string }` objects for registering a Typescript plugins. **Default**: [] | | ||
| preferences | object | Preferences passed to the Typescript (`tsserver`) process. See below for more info. | | ||
The `preferences` object is an object specifying preferences for the internal `tsserver` process. Those options depend on the version of Typescript used but at the time of writing Typescript v4.3.4 contains these options: | ||
```ts | ||
interface UserPreferences { | ||
disableSuggestions?: boolean; | ||
quotePreference?: "auto" | "double" | "single"; | ||
/** | ||
* If enabled, TypeScript will search through all external modules' exports and add them to the completions list. | ||
* This affects lone identifier completions but not completions on the right hand side of `obj.`. | ||
*/ | ||
includeCompletionsForModuleExports?: boolean; | ||
/** | ||
* Enables auto-import-style completions on partially-typed import statements. E.g., allows | ||
* `import write|` to be completed to `import { writeFile } from "fs"`. | ||
*/ | ||
includeCompletionsForImportStatements?: boolean; | ||
/** | ||
* Allows completions to be formatted with snippet text, indicated by `CompletionItem["isSnippet"]`. | ||
*/ | ||
includeCompletionsWithSnippetText?: boolean; | ||
/** | ||
* If enabled, the completion list will include completions with invalid identifier names. | ||
* For those entries, The `insertText` and `replacementSpan` properties will be set to change from `.x` property access to `["x"]`. | ||
*/ | ||
includeCompletionsWithInsertText?: boolean; | ||
/** | ||
* Unless this option is `false`, or `includeCompletionsWithInsertText` is not enabled, | ||
* member completion lists triggered with `.` will include entries on potentially-null and potentially-undefined | ||
* values, with insertion text to replace preceding `.` tokens with `?.`. | ||
*/ | ||
includeAutomaticOptionalChainCompletions?: boolean; | ||
importModuleSpecifierPreference?: "shortest" | "project-relative" | "relative" | "non-relative"; | ||
/** Determines whether we import `foo/index.ts` as "foo", "foo/index", or "foo/index.js" */ | ||
importModuleSpecifierEnding?: "auto" | "minimal" | "index" | "js"; | ||
allowTextChangesInNewFiles?: boolean; | ||
lazyConfiguredProjectsFromExternalProject?: boolean; | ||
providePrefixAndSuffixTextForRename?: boolean; | ||
provideRefactorNotApplicableReason?: boolean; | ||
allowRenameOfImportPath?: boolean; | ||
includePackageJsonAutoImports?: "auto" | "on" | "off"; | ||
displayPartsForJSDoc?: boolean; | ||
generateReturnInDocTemplate?: boolean; | ||
} | ||
``` | ||
From the `preferences` options listed above, this server explicilty sets the following options (all other options use their default values): | ||
```js | ||
{ | ||
includeCompletionsForModuleExports: true, | ||
includeCompletionsWithInsertText: true, | ||
} | ||
``` | ||
# Supported Protocol features | ||
- [x] textDocument/didChange (incremental) | ||
- [x] textDocument/didClose | ||
- [x] textDocument/didOpen | ||
- [x] textDocument/didSave | ||
- [x] textDocument/codeAction | ||
- [x] textDocument/completion (incl. completion/resolve) | ||
- [x] textDocument/definition | ||
- [x] textDocument/documentHighlight | ||
- [x] textDocument/documentSymbol | ||
- [x] textDocument/executeCommand | ||
- [x] textDocument/formatting | ||
- [x] textDocument/rangeFormatting | ||
- [x] textDocument/hover | ||
- [x] textDocument/rename | ||
- [x] textDocument/references | ||
- [x] textDocument/signatureHelp | ||
- [x] workspace/symbol | ||
# Development | ||
@@ -70,0 +137,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
378808
5009
157