From a0cd135c8e4958bc22bf7c03beaacabced051ca5 Mon Sep 17 00:00:00 2001 From: Andrew Branch Date: Thu, 17 Apr 2025 12:13:49 -0700 Subject: [PATCH] Allow disabling built-in TS/JS extension in favor of tsgo --- .../typescript-language-features/package.json | 18 ++++ .../package.nls.json | 1 + .../src/commands/disableExtension.ts | 83 +++++++++++++++++++ .../src/commands/index.ts | 3 + .../src/extension.ts | 21 ++++- 5 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 extensions/typescript-language-features/src/commands/disableExtension.ts diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index 072cca645ff..6a2daba6ad6 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -202,6 +202,12 @@ "description": "%typescript.implementationsCodeLens.enabled%", "scope": "window" }, + "typescript.unstable.useTsgo": { + "type": "boolean", + "default": false, + "markdownDescription": "%typescript.useTsgo%", + "scope": "window" + }, "typescript.implementationsCodeLens.showOnInterfaceMethods": { "type": "boolean", "default": false, @@ -1626,6 +1632,18 @@ "command": "javascript.removeUnusedImports", "title": "%typescript.removeUnusedImports%", "category": "JavaScript" + }, + { + "command": "typescript.enableTsgo", + "title": "Use TypeScript Go", + "category": "TypeScript", + "enablement": "!config.typescript.unstable.useTsgo && config.typescript-go.executablePath" + }, + { + "command": "typescript.disableTsgo", + "title": "Stop using TypeScript Go", + "category": "TypeScript", + "enablement": "config.typescript.unstable.useTsgo" } ], "menus": { diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index abbc9896ce3..e30edb5befc 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -15,6 +15,7 @@ "configuration.suggest.completeFunctionCalls": "Complete functions with their parameter signature.", "configuration.suggest.includeAutomaticOptionalChainCompletions": "Enable/disable showing completions on potentially undefined values that insert an optional chain call. Requires strict null checks to be enabled.", "configuration.suggest.includeCompletionsForImportStatements": "Enable/disable auto-import-style completions on partially-typed import statements.", + "typescript.useTsgo": "Disables TypeScript and JavaScript language features to allow usage of the TypeScript Go experimental extension. Requires TypeScript Go to be installed and configured. Requires reloading extensions after changing this setting.", "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](https://code.visualstudio.com/docs/nodejs/working-with-javascript#_typings-and-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.", diff --git a/extensions/typescript-language-features/src/commands/disableExtension.ts b/extensions/typescript-language-features/src/commands/disableExtension.ts new file mode 100644 index 00000000000..bb8b9090c74 --- /dev/null +++ b/extensions/typescript-language-features/src/commands/disableExtension.ts @@ -0,0 +1,83 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { Command } from './commandManager'; + +/** + * Command that enables TypeScript Go by modifying the configuration setting + * and prompting the user to reload VS Code. + */ +export class EnableTsgoCommand implements Command { + public readonly id = 'typescript.enableTsgo'; + + public async execute(): Promise { + await updateTsgoSetting(true); + } +} + +/** + * Command that disables TypeScript Go by modifying the configuration setting + * and prompting the user to reload VS Code. + */ +export class DisableTsgoCommand implements Command { + public readonly id = 'typescript.disableTsgo'; + + public async execute(): Promise { + await updateTsgoSetting(false); + } +} + +/** + * Updates the TypeScript Go setting and prompts for reload. + * + * @param enable Whether to enable or disable TypeScript Go + */ +async function updateTsgoSetting(enable: boolean): Promise { + const tsgoExtension = vscode.extensions.getExtension('typescript.typescript-lsp'); + // Error if the TypeScript Go extension is not installed with a button to open the GitHub repo + if (!tsgoExtension) { + return vscode.window.showErrorMessage( + 'The TypeScript Go extension is not installed.', + { + title: 'Open on GitHub', + isCloseAffordance: true, + } + ).then(async (selection) => { + if (selection) { + await vscode.env.openExternal(vscode.Uri.parse('https://github.com/microsoft/typescript-go')); + } + }); + } + + const tsConfig = vscode.workspace.getConfiguration('typescript'); + const currentValue = tsConfig.get('useTsgo', false); + if (currentValue === enable) { + return; + } + + // Determine the target scope for the configuration update + let target = vscode.ConfigurationTarget.Global; + const inspect = tsConfig.inspect('useTsgo'); + if (inspect?.workspaceValue !== undefined) { + target = vscode.ConfigurationTarget.Workspace; + } else if (inspect?.workspaceFolderValue !== undefined) { + target = vscode.ConfigurationTarget.WorkspaceFolder; + } else { + // If setting is not defined yet, use the same scope as typescript-go.executablePath + const tsgoConfig = vscode.workspace.getConfiguration('typescript-go'); + const tsgoInspect = tsgoConfig.inspect('executablePath'); + + if (tsgoInspect?.workspaceValue !== undefined) { + target = vscode.ConfigurationTarget.Workspace; + } else if (tsgoInspect?.workspaceFolderValue !== undefined) { + target = vscode.ConfigurationTarget.WorkspaceFolder; + } + } + + // Update the setting, restart the extension host, and enable the TypeScript Go extension + await tsConfig.update('useTsgo', enable, target); + await vscode.commands.executeCommand('workbench.action.restartExtensionHost'); +} diff --git a/extensions/typescript-language-features/src/commands/index.ts b/extensions/typescript-language-features/src/commands/index.ts index 7130f201975..276e03533b2 100644 --- a/extensions/typescript-language-features/src/commands/index.ts +++ b/extensions/typescript-language-features/src/commands/index.ts @@ -9,6 +9,7 @@ import { ActiveJsTsEditorTracker } from '../ui/activeJsTsEditorTracker'; import { Lazy } from '../utils/lazy'; import { CommandManager } from './commandManager'; import { ConfigurePluginCommand } from './configurePlugin'; +import { EnableTsgoCommand, DisableTsgoCommand } from './disableExtension'; import { JavaScriptGoToProjectConfigCommand, TypeScriptGoToProjectConfigCommand } from './goToProjectConfiguration'; import { LearnMoreAboutRefactoringsCommand } from './learnMoreAboutRefactorings'; import { OpenJsDocLinkCommand } from './openJsDocLink'; @@ -35,4 +36,6 @@ export function registerBaseCommands( commandManager.register(new LearnMoreAboutRefactoringsCommand()); commandManager.register(new TSServerRequestCommand(lazyClientHost)); commandManager.register(new OpenJsDocLinkCommand()); + commandManager.register(new EnableTsgoCommand()); + commandManager.register(new DisableTsgoCommand()); } diff --git a/extensions/typescript-language-features/src/extension.ts b/extensions/typescript-language-features/src/extension.ts index 83bd22e3eca..fcf4484f023 100644 --- a/extensions/typescript-language-features/src/extension.ts +++ b/extensions/typescript-language-features/src/extension.ts @@ -8,6 +8,7 @@ import * as fs from 'fs'; import * as vscode from 'vscode'; import { Api, getExtensionApi } from './api'; import { CommandManager } from './commands/commandManager'; +import { DisableTsgoCommand } from './commands/disableExtension'; import { registerBaseCommands } from './commands/index'; import { ElectronServiceConfigurationProvider } from './configuration/configuration.electron'; import { ExperimentationTelemetryReporter, IExperimentationTelemetryReporter } from './experimentTelemetryReporter'; @@ -28,12 +29,26 @@ import * as temp from './utils/temp.electron'; export function activate( context: vscode.ExtensionContext ): Api { - const pluginManager = new PluginManager(); - context.subscriptions.push(pluginManager); - const commandManager = new CommandManager(); context.subscriptions.push(commandManager); + // Disable extension if using the experimental TypeScript Go extension + const config = vscode.workspace.getConfiguration('typescript'); + const useTsgo = config.get('unstable.useTsgo', false); + + if (useTsgo) { + commandManager.register(new DisableTsgoCommand()); + // Return a no-op API when disabled + return { + getAPI() { + return undefined; + } + }; + } + + const pluginManager = new PluginManager(); + context.subscriptions.push(pluginManager); + const onCompletionAccepted = new vscode.EventEmitter(); context.subscriptions.push(onCompletionAccepted);