Skip to content
Merged
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
50 changes: 50 additions & 0 deletions editors/vscode/client/StatusBarItemHandler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { MarkdownString, StatusBarAlignment, StatusBarItem, ThemeColor, window } from 'vscode';

type StatusBarTool = 'linter' | 'formatter';

export default class StatusBarItemHandler {
private tooltipSections: Map<StatusBarTool, string> = new Map();

private statusBarItem: StatusBarItem = window.createStatusBarItem(StatusBarAlignment.Right, 100);

private extensionVersion: string = '<unknown>';

constructor(extensionVersion?: string) {
if (extensionVersion) {
this.extensionVersion = extensionVersion;
}
}

public show(): void {
this.statusBarItem.show();
}

public setColorAndIcon(bgColor: string, icon: string): void {
this.statusBarItem.backgroundColor = new ThemeColor(bgColor);
this.statusBarItem.text = `$(${icon}) oxc`;
}

/**
* Updates the tooltip text for a specific tool section.
* The tooltip can use markdown syntax and VSCode icons.
*/
public updateToolTooltip(toolId: StatusBarTool, text: string): void {
this.tooltipSections.set(toolId, text);
this.updateFullTooltip();
}

private updateFullTooltip(): void {
const text = Array.from(this.tooltipSections.values()).join('\n\n');

if (!(this.statusBarItem.tooltip instanceof MarkdownString)) {
this.statusBarItem.tooltip = new MarkdownString('', true);
this.statusBarItem.tooltip.isTrusted = true;
}

this.statusBarItem.tooltip.value = `VSCode Extension v${this.extensionVersion}\n\n---\n\n${text}`;
}

public dispose(): void {
this.statusBarItem.dispose();
}
}
10 changes: 8 additions & 2 deletions editors/vscode/client/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
restartClient,
toggleClient,
} from './linter';
import StatusBarItemHandler from './StatusBarItemHandler';

const outputChannelName = 'Oxc';

Expand Down Expand Up @@ -42,20 +43,25 @@ export async function activate(context: ExtensionContext) {
}
});

const statusBarItemHandler = new StatusBarItemHandler(context.extension.packageJSON?.version);

context.subscriptions.push(
restartCommand,
showOutputCommand,
toggleEnable,
configService,
outputChannel,
onDidChangeWorkspaceFoldersDispose,
statusBarItemHandler,
);

configService.onConfigChange = async function onConfigChange(event) {
await onConfigChangeLinter(context, event, configService);
await onConfigChangeLinter(event, configService, statusBarItemHandler);
};

await activateLinter(context, outputChannel, configService);
await activateLinter(context, outputChannel, configService, statusBarItemHandler);
// Show status bar item after activation
statusBarItemHandler.show();
}

export async function deactivate(): Promise<void> {
Expand Down
64 changes: 30 additions & 34 deletions editors/vscode/client/linter.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,17 @@
import { promises as fsPromises } from 'node:fs';

import {
commands,
ConfigurationChangeEvent,
ExtensionContext,
LogOutputChannel,
StatusBarAlignment,
StatusBarItem,
ThemeColor,
Uri,
window,
workspace,
} from 'vscode';
import { commands, ConfigurationChangeEvent, ExtensionContext, LogOutputChannel, Uri, window, workspace } from 'vscode';

import { ConfigurationParams, ExecuteCommandRequest, ShowMessageNotification } from 'vscode-languageclient';

import { Executable, LanguageClient, LanguageClientOptions, ServerOptions } from 'vscode-languageclient/node';

import { join } from 'node:path';
import { ConfigService } from './ConfigService';
import { VSCodeConfig } from './VSCodeConfig';
import { OxcCommands } from './commands';
import { ConfigService } from './ConfigService';
import { onClientNotification, runExecutable } from './lsp_helper';
import StatusBarItemHandler from './StatusBarItemHandler';
import { VSCodeConfig } from './VSCodeConfig';

const languageClientName = 'oxc';

Expand All @@ -31,8 +21,6 @@ const enum LspCommands {

let client: LanguageClient | undefined;

let oxcStatusBarItem: StatusBarItem;

// Global flag to check if the user allows us to start the server.
// When `oxc.requireConfig` is `true`, make sure one `.oxlintrc.json` file is present.
let allowedToStartServer: boolean;
Expand All @@ -41,6 +29,7 @@ export async function activate(
context: ExtensionContext,
outputChannel: LogOutputChannel,
configService: ConfigService,
statusBarItemHandler: StatusBarItemHandler,
) {
allowedToStartServer = configService.vsCodeConfig.requireConfig
? (await workspace.findFiles(`**/.oxlintrc.json`, '**/node_modules/**', 1)).length > 0
Expand Down Expand Up @@ -157,13 +146,13 @@ export async function activate(

context.subscriptions.push(onDeleteFilesDispose);

updateStatusBar(context, configService.vsCodeConfig.enable);
updateStatusBar(statusBarItemHandler, configService.vsCodeConfig.enable);
if (allowedToStartServer) {
if (configService.vsCodeConfig.enable) {
await client.start();
}
} else {
generateActivatorByConfig(configService.vsCodeConfig, context);
generateActivatorByConfig(configService.vsCodeConfig, context, statusBarItemHandler);
}
}

Expand Down Expand Up @@ -192,26 +181,33 @@ function getStatusBarState(enable: boolean): { bgColor: string; icon: string; to
}
}

function updateStatusBar(context: ExtensionContext, enable: boolean) {
if (!oxcStatusBarItem) {
oxcStatusBarItem = window.createStatusBarItem(StatusBarAlignment.Right, 100);
oxcStatusBarItem.command = OxcCommands.ToggleEnable;
context.subscriptions.push(oxcStatusBarItem);
oxcStatusBarItem.show();
}

function updateStatusBar(statusBarItemHandler: StatusBarItemHandler, enable: boolean) {
const { bgColor, icon, tooltipText } = getStatusBarState(enable);

oxcStatusBarItem.text = `$(${icon}) oxc`;
oxcStatusBarItem.backgroundColor = new ThemeColor(bgColor);
oxcStatusBarItem.tooltip = tooltipText;
let text =
`**${tooltipText}**\n\n` +
`[$(terminal) Open Output](command:${OxcCommands.ShowOutputChannel})\n\n` +
`[$(refresh) Restart Server](command:${OxcCommands.RestartServer})\n\n`;

if (enable) {
text += `[$(stop) Stop Server](command:${OxcCommands.ToggleEnable})\n\n`;
} else {
text += `[$(play) Start Server](command:${OxcCommands.ToggleEnable})\n\n`;
}

statusBarItemHandler.setColorAndIcon(bgColor, icon);
statusBarItemHandler.updateToolTooltip('linter', text);
}

function generateActivatorByConfig(config: VSCodeConfig, context: ExtensionContext): void {
function generateActivatorByConfig(
config: VSCodeConfig,
context: ExtensionContext,
statusBarItemHandler: StatusBarItemHandler,
): void {
const watcher = workspace.createFileSystemWatcher('**/.oxlintrc.json', false, true, !config.requireConfig);
watcher.onDidCreate(async () => {
allowedToStartServer = true;
updateStatusBar(context, config.enable);
updateStatusBar(statusBarItemHandler, config.enable);
if (client && !client.isRunning() && config.enable) {
await client.start();
}
Expand All @@ -221,7 +217,7 @@ function generateActivatorByConfig(config: VSCodeConfig, context: ExtensionConte
// only can be called when config.requireConfig
allowedToStartServer = (await workspace.findFiles(`**/.oxlintrc.json`, '**/node_modules/**', 1)).length > 0;
if (!allowedToStartServer) {
updateStatusBar(context, false);
updateStatusBar(statusBarItemHandler, false);
if (client && client.isRunning()) {
await client.stop();
}
Expand Down Expand Up @@ -266,11 +262,11 @@ export async function toggleClient(configService: ConfigService): Promise<void>
}

export async function onConfigChange(
context: ExtensionContext,
event: ConfigurationChangeEvent,
configService: ConfigService,
statusBarItemHandler: StatusBarItemHandler,
): Promise<void> {
updateStatusBar(context, configService.vsCodeConfig.enable);
updateStatusBar(statusBarItemHandler, configService.vsCodeConfig.enable);

if (client === undefined) {
return;
Expand Down
Loading