diff --git a/extensions/typescript-language-features/package.json b/extensions/typescript-language-features/package.json index acd17e52490..7613cfdb88b 100644 --- a/extensions/typescript-language-features/package.json +++ b/extensions/typescript-language-features/package.json @@ -203,6 +203,13 @@ "description": "%typescript.implementationsCodeLens.enabled%", "scope": "window" }, + "typescript.experimental.useTsgo": { + "type": "boolean", + "default": false, + "markdownDescription": "%typescript.useTsgo%", + "scope": "window", + "tags": ["experimental"] + }, "typescript.implementationsCodeLens.showOnInterfaceMethods": { "type": "boolean", "default": false, @@ -1615,6 +1622,18 @@ "command": "javascript.removeUnusedImports", "title": "%typescript.removeUnusedImports%", "category": "JavaScript" + }, + { + "command": "typescript.experimental.enableTsgo", + "title": "Use TypeScript Go (Experimental)", + "category": "TypeScript", + "enablement": "!config.typescript.experimental.useTsgo && config.typescript-go.executablePath" + }, + { + "command": "typescript.experimental.disableTsgo", + "title": "Stop using TypeScript Go (Experimental)", + "category": "TypeScript", + "enablement": "config.typescript.experimental.useTsgo" } ], "menus": { diff --git a/extensions/typescript-language-features/package.nls.json b/extensions/typescript-language-features/package.nls.json index 222f9bcb987..21d70e4a2e7 100644 --- a/extensions/typescript-language-features/package.nls.json +++ b/extensions/typescript-language-features/package.nls.json @@ -12,6 +12,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/index.ts b/extensions/typescript-language-features/src/commands/index.ts index 7130f201975..6131d9b985f 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 './useTsgo'; 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/commands/useTsgo.ts b/extensions/typescript-language-features/src/commands/useTsgo.ts new file mode 100644 index 00000000000..aedf28e54b0 --- /dev/null +++ b/extensions/typescript-language-features/src/commands/useTsgo.ts @@ -0,0 +1,74 @@ +/*--------------------------------------------------------------------------------------------- + * 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'; + +export class EnableTsgoCommand implements Command { + public readonly id = 'typescript.experimental.enableTsgo'; + + public async execute(): Promise { + await updateTsgoSetting(true); + } +} + +export class DisableTsgoCommand implements Command { + public readonly id = 'typescript.experimental.disableTsgo'; + + public async execute(): Promise { + await updateTsgoSetting(false); + } +} + +/** + * Updates the TypeScript Go setting and reloads extension host. + * @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) { + const selection = await vscode.window.showErrorMessage( + vscode.l10n.t('The TypeScript Go extension is not installed.'), + { + title: vscode.l10n.t('Open on GitHub'), + isCloseAffordance: true, + } + ); + + 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('experimental.useTsgo', false); + if (currentValue === enable) { + return; + } + + // Determine the target scope for the configuration update + let target = vscode.ConfigurationTarget.Global; + const inspect = tsConfig.inspect('experimental.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('experimental.useTsgo', enable, target); + await vscode.commands.executeCommand('workbench.action.restartExtensionHost'); +} diff --git a/extensions/typescript-language-features/src/extension.ts b/extensions/typescript-language-features/src/extension.ts index 83bd22e3eca..29f809bd653 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/useTsgo'; 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('experimental.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);