Skip to content

Add ability to build extension VSIX and swap for built-in extension #805

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified .github/ls-screenshot.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 13 additions & 0 deletions Herebyfile.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ const { values: options } = parseArgs({
fix: { type: "boolean" },
debug: { type: "boolean" },

insiders: { type: "boolean" },

race: { type: "boolean", default: parseEnvBoolean("RACE") },
noembed: { type: "boolean", default: parseEnvBoolean("NOEMBED") },
concurrentTestPrograms: { type: "boolean", default: parseEnvBoolean("CONCURRENT_TEST_PROGRAMS") },
Expand Down Expand Up @@ -348,6 +350,17 @@ export const testAll = task({
},
});

export const installExtension = task({
name: "install-extension",
run: async () => {
await $({ cwd: path.join(__dirname, "_extension") })`npm run package`;
await $({ cwd: path.join(__dirname, "_extension") })`${options.insiders ? "code-insiders" : "code"} --install-extension typescript-lsp.vsix`;
console.log(pc.yellowBright("\nExtension installed. ") + "Add the following to your workspace or user settings.json:\n");
console.log(pc.whiteBright(` "typescript-go.executablePath": "${path.join(__dirname, "built", "local", process.platform === "win32" ? "tsgo.exe" : "tsgo")}"\n`));
console.log("Select 'TypeScript: Use TypeScript Go' in the command palette to enable the extension and disable built-in TypeScript support.\n");
},
});

const customLinterPath = "./_tools/custom-gcl";
const customLinterHashPath = customLinterPath + ".hash";

Expand Down
9 changes: 7 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,18 @@ This is mainly a testing entry point; for higher fidelity with regular `tsc`, ru

### Running LSP Prototype

To try the prototype LSP experience:
* Run `hereby build` to build the LSP server
* Run `hereby install-extension` to build and install the VS Code extension. (Use `--insiders` to target `code-insiders` instead of `code`.)
* Copy the `"typescript-go.executablePath"` setting printed by `hereby install-extension` to your VS Code settings.
* Select "TypeScript: Use TypeScript Go" from the VS Code command palette (or set `"typescript.useTsgo"` in your VS Code settings).

Alternatively, to debug and run the VS Code extension without installing it globally:

* Run VS Code in the repo workspace (`code .`)
* Copy `.vscode/launch.template.json` to `.vscode/launch.json`
* <kbd>F5</kbd> (or `Debug: Start Debugging` from the command palette)

This will launch a new VS Code instance which uses the Corsa LS as the backend. If correctly set up, you should see "typescript-go" as an option in the Output pane:
This will launch a new VS Code instance which uses the Corsa LS as the backend. If correctly set up, you should see "tsgo" in the status bar when a TypeScript or JavaScript file is open:

![LSP Prototype Screenshot](.github/ls-screenshot.png)

Expand Down
27 changes: 23 additions & 4 deletions _extension/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@
"private": true,
"version": "0.0.0",
"type": "commonjs",
"repository": {
"type": "git",
"url": "https://github.com/microsoft/typescript-go"
},
"engines": {
"vscode": "^1.91.0"
},
Expand Down Expand Up @@ -34,33 +38,48 @@
"typescript-go.pprofDir": {
"type": "string",
"description": "Directory to write pprof profiles to."
},
"typescript-go.executablePath": {
"type": "string",
"description": "Path to the tsgo binary. If not specified, the extension will look for it in the default location."
}
}
}
],
"commands": [
{
"command": "typescript-go.restart",
"title": "TypeScript Go: Restart Language Server"
"title": "TypeScript Go: Restart Language Server",
"enablement": "typescript-go.serverRunning"
}
],
"menus": {
"commandPalette": [
{
"command": "typescript-go.restart"
"command": "typescript-go.restart",
"when": "typescript-go.serverRunning"
}
]
}
},
"main": "./dist/extension.js",
"files": [
"dist"
],
"scripts": {
"build": "tsc",
"watch": "tsc --watch"
"watch": "tsc --watch",
"build:prod": "esbuild src/extension.ts --bundle --external:vscode --platform=node --format=cjs --outfile=dist/extension.js --minify",
"package": "vsce package --skip-license --no-dependencies --out typescript-lsp.vsix",
"install-extension": "code --install-extension typescript-lsp.vsix",
"vscode:prepublish": "npm run build:prod"
},
"dependencies": {
"vscode-languageclient": "^9.0.1"
},
"devDependencies": {
"@types/vscode": "^1.96.0"
"@types/vscode": "^1.91.0",
"@vscode/vsce": "^3.3.2",
"esbuild": "^0.25.2"
}
}
98 changes: 89 additions & 9 deletions _extension/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,30 @@ import {
} from "vscode-languageclient/node";

let client: LanguageClient;
let statusBarItem: vscode.StatusBarItem;

const BUILTIN_TS_EXTENSION_ID = "vscode.typescript-language-features";

export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(vscode.commands.registerCommand("typescript-go.restart", () => {
client.restart();
}));
const tsExtension = vscode.extensions.getExtension(BUILTIN_TS_EXTENSION_ID);
if (tsExtension?.isActive && !vscode.workspace.getConfiguration("typescript").get<boolean>("useTsgo")) {
return;
}

const output = vscode.window.createOutputChannel("typescript-go", "log");
const traceOutput = vscode.window.createOutputChannel("typescript-go (LSP)");

const exe = context.asAbsolutePath(
setupStatusBar(context);
registerCommands(context, output, traceOutput);

const config = vscode.workspace.getConfiguration("typescript-go");

const exe = config.get<string>("executablePath") || context.asAbsolutePath(
path.join("../", "built", "local", `tsgo${process.platform === "win32" ? ".exe" : ""}`),
);

output.appendLine(`Resolved to ${exe}`);

const config = vscode.workspace.getConfiguration("typescript-go");

// Get pprofDir
const pprofDir = config.get<string>("pprofDir");
const pprofArgs = pprofDir ? ["-pprofDir", pprofDir] : [];
Expand Down Expand Up @@ -115,13 +122,86 @@ export function activate(context: vscode.ExtensionContext) {

output.appendLine(`Starting language server...`);
client.start();
vscode.commands.executeCommand("setContext", "typescript-go.serverRunning", true);
}

/**
* Sets up the status bar item for TypeScript Go
* @param context Extension context
*/
function setupStatusBar(context: vscode.ExtensionContext): void {
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right, 100);
statusBarItem.text = "$(beaker) tsgo";
statusBarItem.tooltip = "TypeScript Go Language Server";
statusBarItem.command = "typescript-go.showMenu";
statusBarItem.backgroundColor = new vscode.ThemeColor("statusBarItem.warningBackground");
statusBarItem.show();
context.subscriptions.push(statusBarItem);
}

/**
* Registers all commands for the extension
* @param context Extension context
*/
function registerCommands(context: vscode.ExtensionContext, outputChannel: vscode.OutputChannel, traceOutputChannel: vscode.OutputChannel): void {
context.subscriptions.push(vscode.commands.registerCommand("typescript-go.restart", async () => {
await client.restart();
}));

context.subscriptions.push(vscode.commands.registerCommand("typescript-go.output.focus", () => {
outputChannel.show();
}));

context.subscriptions.push(vscode.commands.registerCommand("typescript-go.lsp-trace.focus", () => {
traceOutputChannel.show();
}));

context.subscriptions.push(vscode.commands.registerCommand("typescript-go.showMenu", showQuickPickMenu));
}

export function deactivate(): Thenable<void> | undefined {
/**
* Shows the quick pick menu for TypeScript Go options
*/
async function showQuickPickMenu(): Promise<void> {
const selected = await vscode.window.showQuickPick([
{ label: "$(refresh) Restart Server", description: "Restart the TypeScript Go language server" },
{ label: "$(output) Show TS Server Log", description: "Show the TypeScript Go server log" },
{ label: "$(debug-console) Show LSP Messages", description: "Show the LSP communication trace" },
{ label: "$(stop-circle) Disable TypeScript Go", description: "Switch back to the built-in TypeScript extension" },
], {
placeHolder: "TypeScript Go Options",
});

if (selected) {
if (selected.label.includes("Restart Server")) {
await vscode.commands.executeCommand("typescript-go.restart");
}
else if (selected.label.includes("Show TS Server Log")) {
await vscode.commands.executeCommand("typescript-go.output.focus");
}
else if (selected.label.includes("Show LSP Messages")) {
await vscode.commands.executeCommand("typescript-go.lsp-trace.focus");
}
else if (selected.label.includes("Disable TypeScript Go")) {
// Fire and forget, because this command will restart the whole extension host
// and awaiting it shows a weird cancellation error.
vscode.commands.executeCommand("typescript.disableTsgo");
}
}
}

export async function deactivate(): Promise<void> {
// Dispose of status bar item
if (statusBarItem) {
statusBarItem.dispose();
}

if (!client) {
return undefined;
return;
}
return client.stop();

await client.stop();
return vscode.commands.executeCommand("setContext", "typescript-go.serverRunning", false);
}

function getLanguageForUri(uri: vscode.Uri): string | undefined {
Expand Down
Loading