TS: Add setting to prompt users about workspace tsdk (#95566)

* add a setting to prompt users to switch to tsdk version

* version manager in control

Co-authored-by: Duncan Walter <dwalter@hubspot.com>
This commit is contained in:
Duncan Walter 2020-04-22 13:57:22 -04:00 committed by GitHub
parent 4b178bfc9f
commit c7c2301bc2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 80 additions and 5 deletions

View file

@ -140,6 +140,12 @@
"usesOnlineServices"
]
},
"typescript.enablePromptUseWorkspaceTsdk": {
"type": "boolean",
"default": false,
"description": "%typescript.enablePromptUseWorkspaceTsdk%",
"scope": "window"
},
"typescript.npm": {
"type": [
"string",

View file

@ -7,6 +7,7 @@
"configuration.suggest.includeAutomaticOptionalChainCompletions": "Enable/disable showing completions on potentially undefined values that insert an optional chain call. Requires TS 3.7+ and strict null checks to be enabled.",
"typescript.tsdk.desc": "Specifies the folder path to the tsserver and lib*.d.ts files under a TypeScript install to use for IntelliSense, for example: `./node_modules/typescript/lib`.\n\n- When specified as a user setting, the TypeScript version from `typescript.tsdk` automatically replaces the built-in TypeScript version.\n- When specified as a workspace setting, `typescript.tsdk` allows you to switch to use that workspace version of TypeScript for IntelliSense with the `TypeScript: Select TypeScript version` command.\n\nSee the [TypeScript documentation](https://code.visualstudio.com/docs/typescript/typescript-compiling#_using-newer-typescript-versions) for more detail about managing TypeScript versions.",
"typescript.disableAutomaticTypeAcquisition": "Disables automatic type acquisition. Automatic type acquisition fetches `@types` packages from npm to improve IntelliSense for external libraries.",
"typescript.enablePromptUseWorkspaceTsdk": "Enables prompting of users to use the TypeScript version configured in the workspace for Intellisense.",
"typescript.tsserver.log": "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.",
"typescript.tsserver.pluginPaths": "Additional paths to discover TypeScript Language Service plugins. Requires using TypeScript 2.3.0 or newer in the workspace.",
"typescript.tsserver.pluginPaths.item": "Either an absolute or relative path. Relative path will be resolved against workspace folder(s).",

View file

@ -140,7 +140,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
this._configuration = TypeScriptServiceConfiguration.loadFromWorkspace();
this.versionProvider = new TypeScriptVersionProvider(this._configuration);
this.pluginPathsProvider = new TypeScriptPluginPathsProvider(this._configuration);
this._versionManager = this._register(new TypeScriptVersionManager(this.versionProvider, this.workspaceState));
this._versionManager = this._register(new TypeScriptVersionManager(this._configuration, this.versionProvider, this.workspaceState));
this._register(this._versionManager.onDidPickNewVersion(() => {
this.restartTsServer();
}));
@ -163,6 +163,7 @@ export default class TypeScriptServiceClient extends Disposable implements IType
this._configuration = TypeScriptServiceConfiguration.loadFromWorkspace();
this.versionProvider.updateConfiguration(this._configuration);
this._versionManager.updateConfiguration(this._configuration);
this.pluginPathsProvider.updateConfiguration(this._configuration);
this.tracer.updateConfiguration();

View file

@ -59,6 +59,7 @@ export class TypeScriptServiceConfiguration {
public readonly useSeparateSyntaxServer: boolean;
public readonly enableProjectDiagnostics: boolean;
public readonly maxTsServerMemory: number;
public readonly enablePromptUseWorkspaceTsdk: boolean;
public readonly watchOptions: protocol.WatchOptions | undefined;
public static loadFromWorkspace(): TypeScriptServiceConfiguration {
@ -80,6 +81,7 @@ export class TypeScriptServiceConfiguration {
this.useSeparateSyntaxServer = TypeScriptServiceConfiguration.readUseSeparateSyntaxServer(configuration);
this.enableProjectDiagnostics = TypeScriptServiceConfiguration.readEnableProjectDiagnostics(configuration);
this.maxTsServerMemory = TypeScriptServiceConfiguration.readMaxTsServerMemory(configuration);
this.enablePromptUseWorkspaceTsdk = TypeScriptServiceConfiguration.readEnablePromptUseWorkspaceTsdk(configuration);
this.watchOptions = TypeScriptServiceConfiguration.readWatchOptions(configuration);
}
@ -96,7 +98,8 @@ export class TypeScriptServiceConfiguration {
&& this.useSeparateSyntaxServer === other.useSeparateSyntaxServer
&& this.enableProjectDiagnostics === other.enableProjectDiagnostics
&& this.maxTsServerMemory === other.maxTsServerMemory
&& objects.equals(this.watchOptions, other.watchOptions);
&& objects.equals(this.watchOptions, other.watchOptions)
&& this.enablePromptUseWorkspaceTsdk === other.enablePromptUseWorkspaceTsdk;
}
private static fixPathPrefixes(inspectValue: string): string {
@ -175,4 +178,8 @@ export class TypeScriptServiceConfiguration {
}
return Math.max(memoryInMB, minimumMaxMemory);
}
private static readEnablePromptUseWorkspaceTsdk(configuration: vscode.WorkspaceConfiguration): boolean {
return configuration.get<boolean>('typescript.enablePromptUseWorkspaceTsdk', false);
}
}

View file

@ -7,10 +7,12 @@ import * as vscode from 'vscode';
import * as nls from 'vscode-nls';
import { TypeScriptVersion, TypeScriptVersionProvider } from './versionProvider';
import { Disposable } from './dispose';
import { TypeScriptServiceConfiguration } from '../utils/configuration';
const localize = nls.loadMessageBundle();
const useWorkspaceTsdkStorageKey = 'typescript.useWorkspaceTsdk';
const suppressPromptWorkspaceTsdkStorageKey = 'typescript.suppressPromptWorkspaceTsdk';
interface QuickPickItem extends vscode.QuickPickItem {
run(): void;
@ -21,6 +23,7 @@ export class TypeScriptVersionManager extends Disposable {
private _currentVersion: TypeScriptVersion;
public constructor(
private configuration: TypeScriptServiceConfiguration,
private readonly versionProvider: TypeScriptVersionProvider,
private readonly workspaceState: vscode.Memento
) {
@ -34,11 +37,30 @@ export class TypeScriptVersionManager extends Disposable {
this._currentVersion = localVersion;
}
}
if (this.isInPromptWorkspaceTsdkState(configuration)) {
setImmediate(() => {
this.promptUseWorkspaceTsdk();
});
}
}
private readonly _onDidPickNewVersion = this._register(new vscode.EventEmitter<void>());
public readonly onDidPickNewVersion = this._onDidPickNewVersion.event;
public updateConfiguration(nextConfiguration: TypeScriptServiceConfiguration) {
const lastConfiguration = this.configuration;
this.configuration = nextConfiguration;
if (
!this.isInPromptWorkspaceTsdkState(lastConfiguration)
&& this.isInPromptWorkspaceTsdkState(nextConfiguration)
) {
this.promptUseWorkspaceTsdk();
}
}
public get currentVersion(): TypeScriptVersion {
return this._currentVersion;
}
@ -71,7 +93,7 @@ export class TypeScriptVersionManager extends Disposable {
detail: bundledVersion.pathLabel,
run: async () => {
await this.workspaceState.update(useWorkspaceTsdkStorageKey, false);
this.updateForPickedVersion(bundledVersion);
this.updateActiveVersion(bundledVersion);
},
};
}
@ -88,13 +110,38 @@ export class TypeScriptVersionManager extends Disposable {
await this.workspaceState.update(useWorkspaceTsdkStorageKey, true);
const tsConfig = vscode.workspace.getConfiguration('typescript');
await tsConfig.update('tsdk', version.pathLabel, false);
this.updateForPickedVersion(version);
this.updateActiveVersion(version);
},
};
});
}
private updateForPickedVersion(pickedVersion: TypeScriptVersion) {
private async promptUseWorkspaceTsdk(): Promise<void> {
const workspaceVersion = this.versionProvider.localVersion;
if (workspaceVersion === undefined) {
throw new Error('Could not prompt to use workspace TypeScript version because no workspace version is specified');
}
const allowIt = localize('allow', 'Allow');
const dismissPrompt = localize('dismiss', 'Dismiss');
const suppressPrompt = localize('suppress prompt', 'Never in this Workspace');
const result = await vscode.window.showInformationMessage(localize('promptUseWorkspaceTsdk', 'This workspace contains a TypeScript version. Would you like to use the workspace TypeScript version for TypeScript and JavaScript language features?'),
allowIt,
dismissPrompt,
suppressPrompt
);
if (result === allowIt) {
await this.workspaceState.update(useWorkspaceTsdkStorageKey, true);
this.updateActiveVersion(workspaceVersion);
} else if (result === suppressPrompt) {
await this.workspaceState.update(suppressPromptWorkspaceTsdkStorageKey, true);
}
}
private updateActiveVersion(pickedVersion: TypeScriptVersion) {
const oldVersion = this.currentVersion;
this._currentVersion = pickedVersion;
if (!oldVersion.eq(pickedVersion)) {
@ -105,6 +152,19 @@ export class TypeScriptVersionManager extends Disposable {
private get useWorkspaceTsdkSetting(): boolean {
return this.workspaceState.get<boolean>(useWorkspaceTsdkStorageKey, false);
}
private get suppressPromptWorkspaceTsdkSetting(): boolean {
return this.workspaceState.get<boolean>(suppressPromptWorkspaceTsdkStorageKey, false);
}
private isInPromptWorkspaceTsdkState(configuration: TypeScriptServiceConfiguration) {
return (
configuration.localTsdk !== null
&& configuration.enablePromptUseWorkspaceTsdk === true
&& this.suppressPromptWorkspaceTsdkSetting === false
&& this.useWorkspaceTsdkSetting === false
);
}
}
const LearnMorePickItem: QuickPickItem = {