From 86ea7fa876a32ea6c10c4a44009bfb5f4cea4de0 Mon Sep 17 00:00:00 2001 From: Anton Kosyakov Date: Fri, 31 Aug 2018 12:39:06 +0000 Subject: [PATCH] fix #2653: open log and restart ts server commands Signed-off-by: Anton Kosyakov --- packages/json/src/browser/json-preferences.ts | 2 +- .../browser/language-client-contribution.ts | 27 ++++++- packages/typescript/package.json | 2 +- .../browser/typescript-client-contribution.ts | 45 ++++++++++- .../typescript-frontend-contribution.ts | 25 +++++++ .../src/browser/typescript-frontend-module.ts | 3 + .../src/browser/typescript-preferences.ts | 74 +++++++++++++++++++ .../src/node/typescript-contribution.ts | 1 - yarn.lock | 6 +- 9 files changed, 173 insertions(+), 12 deletions(-) create mode 100644 packages/typescript/src/browser/typescript-preferences.ts diff --git a/packages/json/src/browser/json-preferences.ts b/packages/json/src/browser/json-preferences.ts index efc7c7dc7e97b..69a009ca71d19 100644 --- a/packages/json/src/browser/json-preferences.ts +++ b/packages/json/src/browser/json-preferences.ts @@ -70,7 +70,7 @@ export const jsonPreferenceSchema: PreferenceSchema = { 'verbose' ], 'default': 'off', - 'description': 'Enable/disable default JSON formatter' + 'description': 'Enable/disable tracing communications with the JSON language server' } } }; diff --git a/packages/languages/src/browser/language-client-contribution.ts b/packages/languages/src/browser/language-client-contribution.ts index 59729d20c285c..ac0e533abb7c7 100644 --- a/packages/languages/src/browser/language-client-contribution.ts +++ b/packages/languages/src/browser/language-client-contribution.ts @@ -21,7 +21,7 @@ import { FrontendApplication, WebSocketConnectionProvider, WebSocketOptions } fr import { LanguageContribution, ILanguageClient, LanguageClientOptions, DocumentSelector, TextDocument, FileSystemWatcher, - Workspace, Languages + Workspace, Languages, State } from './language-client-services'; import { MessageConnection } from 'vscode-jsonrpc'; import { LanguageClientFactory } from './language-client-factory'; @@ -111,7 +111,20 @@ export abstract class BaseLanguageClientContribution implements LanguageClientCo return toDeactivate; } + protected state: State | undefined; + get running(): boolean { + return this.state === State.Running; + } + restart(): void { + if (this._languageClient) { + this._languageClient.stop(); + } + } + protected onWillStart(languageClient: ILanguageClient): void { + languageClient.onDidChangeState(({ newState }) => { + this.state = newState; + }); languageClient.onReady().then(() => this.onReady(languageClient)); } @@ -133,7 +146,7 @@ export abstract class BaseLanguageClientContribution implements LanguageClientCo } protected createOptions(): LanguageClientOptions { - const { id, documentSelector, fileEvents, configurationSection } = this; + const { id, documentSelector, fileEvents, configurationSection, initializationOptions } = this; return { documentSelector, synchronize: { fileEvents, configurationSection }, @@ -142,11 +155,17 @@ export abstract class BaseLanguageClientContribution implements LanguageClientCo this.messageService.error(`Failed to start ${this.name} language server${detail}`); return false; }, - diagnosticCollectionName: id + diagnosticCollectionName: id, + initializationOptions }; } - protected get configurationSection(): string | string[] | undefined { + // tslint:disable-next-line:no-any + protected get initializationOptions(): any | (() => any) | undefined { + return undefined; + } + + protected get configurationSection(): string | string[] | undefined { return undefined; } diff --git a/packages/typescript/package.json b/packages/typescript/package.json index 79970e5b08290..4570ac34ca86c 100644 --- a/packages/typescript/package.json +++ b/packages/typescript/package.json @@ -7,7 +7,7 @@ "@theia/core": "^0.3.14", "@theia/languages": "^0.3.14", "@theia/monaco": "^0.3.14", - "typescript-language-server": "^0.3.0" + "typescript-language-server": "^0.3.1" }, "publishConfig": { "access": "public" diff --git a/packages/typescript/src/browser/typescript-client-contribution.ts b/packages/typescript/src/browser/typescript-client-contribution.ts index e3a5ff0a76cd4..e802b652348de 100644 --- a/packages/typescript/src/browser/typescript-client-contribution.ts +++ b/packages/typescript/src/browser/typescript-client-contribution.ts @@ -14,9 +14,12 @@ * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 ********************************************************************************/ -import { injectable, inject } from 'inversify'; -import { BaseLanguageClientContribution, Workspace, Languages, LanguageClientFactory } from '@theia/languages/lib/browser'; +import { injectable, inject, postConstruct } from 'inversify'; +import URI from '@theia/core/lib/common/uri'; +import { BaseLanguageClientContribution, Workspace, Languages, LanguageClientFactory, ILanguageClient, State } from '@theia/languages/lib/browser'; +import { TypeScriptInitializationOptions, TypeScriptInitializeResult } from 'typescript-language-server/lib/ts-protocol'; import { TYPESCRIPT_LANGUAGE_ID, TYPESCRIPT_LANGUAGE_NAME, TYPESCRIPT_REACT_LANGUAGE_ID, JAVASCRIPT_LANGUAGE_ID, JAVASCRIPT_REACT_LANGUAGE_ID } from '../common'; +import { TypescriptPreferences } from './typescript-preferences'; @injectable() export class TypeScriptClientContribution extends BaseLanguageClientContribution { @@ -24,6 +27,9 @@ export class TypeScriptClientContribution extends BaseLanguageClientContribution readonly id = TYPESCRIPT_LANGUAGE_ID; readonly name = TYPESCRIPT_LANGUAGE_NAME; + @inject(TypescriptPreferences) + protected readonly preferences: TypescriptPreferences; + constructor( @inject(Workspace) protected readonly workspace: Workspace, @inject(Languages) protected readonly languages: Languages, @@ -32,6 +38,15 @@ export class TypeScriptClientContribution extends BaseLanguageClientContribution super(workspace, languages, languageClientFactory); } + @postConstruct() + protected init(): void { + this.preferences.onPreferenceChanged(e => { + if (e.preferenceName === 'typescript.server.log') { + this.restart(); + } + }); + } + protected get documentSelector(): string[] { return [ TYPESCRIPT_LANGUAGE_ID, @@ -55,4 +70,30 @@ export class TypeScriptClientContribution extends BaseLanguageClientContribution ]; } + protected get initializationOptions(): TypeScriptInitializationOptions { + const options: TypeScriptInitializationOptions = {}; + const logVerbosity = this.preferences['typescript.server.log']; + if (logVerbosity !== 'off') { + options.logVerbosity = logVerbosity; + } + return options; + } + + protected _logFileUri: URI | undefined; + get logFileUri(): URI | undefined { + return this._logFileUri; + } + protected onReady(languageClient: ILanguageClient): void { + if (languageClient.initializeResult) { + const initializeResult = languageClient.initializeResult as TypeScriptInitializeResult; + this._logFileUri = initializeResult.logFileUri !== undefined ? new URI(initializeResult.logFileUri) : undefined; + } + languageClient.onDidChangeState(({ newState }) => { + if (newState === State.Stopped) { + this._logFileUri = undefined; + } + }); + super.onReady(languageClient); + } + } diff --git a/packages/typescript/src/browser/typescript-frontend-contribution.ts b/packages/typescript/src/browser/typescript-frontend-contribution.ts index 2df41a701615a..f7727b9f9434e 100644 --- a/packages/typescript/src/browser/typescript-frontend-contribution.ts +++ b/packages/typescript/src/browser/typescript-frontend-contribution.ts @@ -36,6 +36,14 @@ export namespace TypeScriptCommands { label: 'TypeScript: Organize Imports', id: 'typescript.edit.organizeImports' }; + export const openServerLog: Command = { + label: 'TypeScript: Open Server Log', + id: 'typescript.server.openLog' + }; + export const restartServer: Command = { + label: 'TypeScript: Restart Server', + id: 'typescript.server.restart' + }; } @injectable() @@ -70,6 +78,16 @@ export class TypeScriptFrontendContribution implements CommandContribution, Menu isEnabled: () => !!this.currentEditor, isVisible: () => !!this.currentEditor }); + commands.registerCommand(TypeScriptCommands.openServerLog, { + execute: () => this.openServerLog(), + isEnabled: () => !!this.clientContribution.logFileUri, + isVisible: () => !!this.clientContribution.logFileUri + }); + commands.registerCommand(TypeScriptCommands.restartServer, { + execute: () => this.clientContribution.restart(), + isEnabled: () => this.clientContribution.running, + isVisible: () => this.clientContribution.running + }); } registerMenus(menus: MenuModelRegistry): void { @@ -87,6 +105,13 @@ export class TypeScriptFrontendContribution implements CommandContribution, Menu }); } + openServerLog(): void { + const logFileUri = this.clientContribution.logFileUri; + if (logFileUri) { + this.editorManager.open(logFileUri); + } + } + organizeImports(): void { const editor = MonacoEditor.get(this.currentEditor); if (editor) { diff --git a/packages/typescript/src/browser/typescript-frontend-module.ts b/packages/typescript/src/browser/typescript-frontend-module.ts index fe78e11886913..ee2e6cf1e105a 100644 --- a/packages/typescript/src/browser/typescript-frontend-module.ts +++ b/packages/typescript/src/browser/typescript-frontend-module.ts @@ -26,8 +26,11 @@ import { TypescriptGrammarContribution } from './typescript-language-config'; import { JavascriptGrammarContribution } from './javascript-language-config'; import { TypeScriptFrontendContribution } from './typescript-frontend-contribution'; import { TypeScriptEditorTextFocusContext } from './typescript-keybinding-contexts'; +import { bindTypescriptPreferences } from './typescript-preferences'; export default new ContainerModule(bind => { + bindTypescriptPreferences(bind); + bind(TypeScriptClientContribution).toSelf().inSingletonScope(); bind(LanguageClientContribution).toService(TypeScriptClientContribution); diff --git a/packages/typescript/src/browser/typescript-preferences.ts b/packages/typescript/src/browser/typescript-preferences.ts new file mode 100644 index 0000000000000..1c3d940913f84 --- /dev/null +++ b/packages/typescript/src/browser/typescript-preferences.ts @@ -0,0 +1,74 @@ +/******************************************************************************** + * Copyright (C) 2018 TypeFox and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License v. 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * This Source Code may also be made available under the following Secondary + * Licenses when the conditions for such availability set forth in the Eclipse + * Public License v. 2.0 are satisfied: GNU General Public License, version 2 + * with the GNU Classpath Exception which is available at + * https://www.gnu.org/software/classpath/license.html. + * + * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 + ********************************************************************************/ + +import { interfaces } from 'inversify'; +import { + createPreferenceProxy, + PreferenceProxy, + PreferenceService, + PreferenceContribution, + PreferenceSchema, + PreferenceChangeEvent +} from '@theia/core/lib/browser/preferences'; + +export const typescriptPreferenceSchema: PreferenceSchema = { + 'type': 'object', + 'properties': { + 'typescript.trace.server': { + 'type': 'string', + 'enum': [ + 'off', + 'messages', + 'verbose' + ], + 'default': 'off', + 'description': 'Enable/disable tracing communications with the TS language server.' + }, + 'typescript.server.log': { + 'type': 'string', + 'enum': [ + 'off', + 'terse', + 'normal', + 'verbose' + ], + 'default': 'off', + // tslint:disable:max-line-length + 'description': 'Enables logging of the TS server to a file. This log can be used to diagnose TS Server issues. The log may contain file paths, source code, and other potentially sensitive information from your project.' + } + } +}; + +export interface TypescriptConfiguration { + 'typescript.server.log': 'off' | 'terse' | 'normal' | 'verbose' +} +export type TypescriptPreferenceChange = PreferenceChangeEvent; + +export const TypescriptPreferences = Symbol('TypescriptPreferences'); +export type TypescriptPreferences = PreferenceProxy; + +export function createTypescriptPreferences(preferences: PreferenceService): TypescriptPreferences { + return createPreferenceProxy(preferences, typescriptPreferenceSchema); +} + +export function bindTypescriptPreferences(bind: interfaces.Bind): void { + bind(TypescriptPreferences).toDynamicValue(ctx => { + const preferences = ctx.container.get(PreferenceService); + return createTypescriptPreferences(preferences); + }).inSingletonScope(); + + bind(PreferenceContribution).toConstantValue({ schema: typescriptPreferenceSchema }); +} diff --git a/packages/typescript/src/node/typescript-contribution.ts b/packages/typescript/src/node/typescript-contribution.ts index fedd3d9488918..f3d2e90138cac 100644 --- a/packages/typescript/src/node/typescript-contribution.ts +++ b/packages/typescript/src/node/typescript-contribution.ts @@ -33,5 +33,4 @@ export class TypeScriptContribution extends BaseLanguageServerContribution { const serverConnection = this.createProcessStreamConnection(command, args); this.forward(clientConnection, serverConnection); } - } diff --git a/yarn.lock b/yarn.lock index 8f08cf46605b0..d04dcac0e53f0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9384,9 +9384,9 @@ typedoc@^0.8: typedoc-default-themes "^0.5.0" typescript "2.4.1" -typescript-language-server@^0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/typescript-language-server/-/typescript-language-server-0.3.0.tgz#f9594408ae7db2b21c1d2179d9470ed65c4b9906" +typescript-language-server@^0.3.1: + version "0.3.1" + resolved "https://registry.yarnpkg.com/typescript-language-server/-/typescript-language-server-0.3.1.tgz#220b7396afe45b0f0a838996943a524c17906b71" dependencies: command-exists "1.2.6" commander "^2.11.0"