From c2ccfd79f6ae65c003cb1d385dc3406a8d12aade Mon Sep 17 00:00:00 2001 From: Maksym Kupchenko Date: Sun, 30 Nov 2025 22:31:54 +0100 Subject: [PATCH 1/3] add status --- extension/package.json | 8 + extension/src/commands.ts | 52 ++++++ extension/src/detectors/detectorsManager.ts | 55 +++++- extension/src/extensionFeatureManagers.ts | 21 ++- extension/src/statusBar/commands.ts | 8 + extension/src/statusBar/statusBarManager.ts | 193 ++++++++++++++++++++ 6 files changed, 335 insertions(+), 2 deletions(-) create mode 100644 extension/src/statusBar/commands.ts create mode 100644 extension/src/statusBar/statusBarManager.ts diff --git a/extension/package.json b/extension/package.json index a346483..33102ad 100644 --- a/extension/package.json +++ b/extension/package.json @@ -55,6 +55,14 @@ { "command": "solana.reloadDetectors", "title": "solana: Reload Security Detectors" + }, + { + "command": "solana.showStatusDetails", + "title": "solana: Show Status Details" + }, + { + "command": "solana.installNightly", + "title": "solana: Install Nightly Rust Toolchain" } ], "keybindings": [ diff --git a/extension/src/commands.ts b/extension/src/commands.ts index b177513..9da6002 100644 --- a/extension/src/commands.ts +++ b/extension/src/commands.ts @@ -2,6 +2,8 @@ import * as vscode from "vscode"; import { ExtensionFeatureManagers } from "./extensionFeatureManagers"; import { CLOSE_COVERAGE, SHOW_COVERAGE } from "./coverage/commands"; import { RELOAD_DETECTORS, SCAN_WORKSPACE, SHOW_SCAN_OUTPUT } from "./detectors/commands"; +import { INSTALL_NIGHTLY, SHOW_STATUS_DETAILS } from "./statusBar/commands"; +import { StatusBarState } from "./statusBar/statusBarManager"; function registerCommands( context: vscode.ExtensionContext, @@ -39,6 +41,56 @@ function registerCommands( await extensionFeatureManagers.detectorsManager.reloadDetectors(); }) ); + + // Add command to show status details + context.subscriptions.push( + vscode.commands.registerCommand(SHOW_STATUS_DETAILS, async () => { + const state = extensionFeatureManagers.statusBarManager.getCurrentState(); + const isNightly = extensionFeatureManagers.statusBarManager.isNightlyRustAvailable(); + + let message = `Solana Extension Status\n\n`; + message += `State: ${state}\n`; + message += `Nightly Rust: ${isNightly ? 'Available' : 'Not available'}\n`; + + if (state === 'error') { + message += `\nThe language server encountered an error. Check the output channel for details.`; + extensionFeatureManagers.detectorsManager.showOutput(); + } + + vscode.window.showInformationMessage(message); + }) + ); + + // Add command to install nightly Rust + context.subscriptions.push( + vscode.commands.registerCommand(INSTALL_NIGHTLY, async () => { + const action = await vscode.window.showInformationMessage( + 'Install nightly Rust toolchain? This will run: rustup toolchain install nightly', + 'Install', + 'Cancel' + ); + + if (action === 'Install') { + const terminal = vscode.window.createTerminal('Install Nightly Rust'); + terminal.sendText('rustup toolchain install nightly'); + terminal.show(); + + // Recheck toolchain after a delay + setTimeout(async () => { + await extensionFeatureManagers.statusBarManager.recheckRustToolchain(); + if (extensionFeatureManagers.statusBarManager.isNightlyRustAvailable()) { + const currentState = extensionFeatureManagers.statusBarManager.getCurrentState(); + extensionFeatureManagers.statusBarManager.updateStatus( + currentState === StatusBarState.Warn + ? StatusBarState.Chill + : currentState, + 'Nightly Rust is now available' + ); + } + }, 5000); + } + }) + ); } export default registerCommands; diff --git a/extension/src/detectors/detectorsManager.ts b/extension/src/detectors/detectorsManager.ts index 8839a87..9023cff 100644 --- a/extension/src/detectors/detectorsManager.ts +++ b/extension/src/detectors/detectorsManager.ts @@ -1,10 +1,11 @@ import { OutputChannel, window, workspace } from 'vscode'; -import { LanguageClient, LanguageClientOptions, RevealOutputChannelOn, ServerOptions, StateChangeEvent, TransportKind } from 'vscode-languageclient/node'; +import { LanguageClient, LanguageClientOptions, RevealOutputChannelOn, ServerOptions, StateChangeEvent, TransportKind, State } from 'vscode-languageclient/node'; import * as path from 'path'; import * as fs from 'fs'; import * as os from 'os'; import * as vscode from 'vscode'; import { SOLANA_OUTPUT_CHANNEL } from '../output'; +import { StatusBarState } from '../statusBar/statusBarManager'; // Interface for scan summary data from language server interface ScanSummary { @@ -28,6 +29,7 @@ interface FileIssueInfo { export class DetectorsManager { private client?: LanguageClient; private outputChannel: OutputChannel; + private statusBarUpdateCallback?: (state: StatusBarState, message?: string) => void; constructor() { console.log('Security Server initialized'); @@ -38,6 +40,7 @@ export class DetectorsManager { if (!serverPath) { this.handleServerNotFound(); + this.updateStatusBar(StatusBarState.Error, 'Language server binary not found'); return; } @@ -186,6 +189,7 @@ export class DetectorsManager { this.client.onDidChangeState((e: StateChangeEvent) => { this.outputChannel.appendLine(`Server state changed: ${e.newState}`); + this.updateStatusBarFromServerState(e.newState); }); this.client.onNotification('window/logMessage', (params) => { @@ -195,6 +199,10 @@ export class DetectorsManager { // Listen for scan complete notifications this.client.onNotification('solana/scanComplete', (scanSummary: ScanSummary) => { this.handleScanComplete(scanSummary); + // Update status bar after scan completes (unless it was an error) + if (this.statusBarUpdateCallback && this.client?.state === State.Running) { + this.statusBarUpdateCallback(StatusBarState.Chill, 'Scan completed'); + } }); } @@ -252,10 +260,12 @@ export class DetectorsManager { async scanWorkspace(): Promise { if (!this.client) { window.showErrorMessage('Language server not running'); + this.updateStatusBar(StatusBarState.Error, 'Language server not running'); return; } this.outputChannel.appendLine('Manually triggering workspace scan...'); + this.updateStatusBar(StatusBarState.Running, 'Scanning workspace...'); try { const result = await this.client.sendRequest('workspace/executeCommand', { @@ -264,9 +274,11 @@ export class DetectorsManager { }); this.outputChannel.appendLine(`Scan request result: ${JSON.stringify(result)}`); + this.updateStatusBar(StatusBarState.Chill, 'Workspace scan completed'); } catch (error) { this.outputChannel.appendLine(`Error triggering scan: ${error}`); window.showErrorMessage(`Failed to scan workspace: ${error}`); + this.updateStatusBar(StatusBarState.Error, `Failed to scan workspace: ${error}`); } } @@ -274,10 +286,12 @@ export class DetectorsManager { async reloadDetectors(): Promise { if (!this.client) { window.showErrorMessage('Language server not running'); + this.updateStatusBar(StatusBarState.Error, 'Language server not running'); return; } this.outputChannel.appendLine('Reloading security detectors...'); + this.updateStatusBar(StatusBarState.Running, 'Reloading security detectors...'); try { const result = await this.client.sendRequest('workspace/executeCommand', { @@ -286,9 +300,48 @@ export class DetectorsManager { }); this.outputChannel.appendLine(`Reload detectors result: ${JSON.stringify(result)}`); + this.updateStatusBar(StatusBarState.Chill, 'Detectors reloaded successfully'); } catch (error) { this.outputChannel.appendLine(`Error reloading detectors: ${error}`); window.showErrorMessage(`Failed to reload detectors: ${error}`); + this.updateStatusBar(StatusBarState.Error, `Failed to reload detectors: ${error}`); + } + } + + /** + * Set callback for status bar updates + */ + setStatusBarUpdateCallback(callback: (state: StatusBarState, message?: string) => void): void { + this.statusBarUpdateCallback = callback; + } + + /** + * Update status bar based on server state + */ + private updateStatusBarFromServerState(state: State): void { + if (!this.statusBarUpdateCallback) { + return; + } + + switch (state) { + case State.Starting: + this.statusBarUpdateCallback(StatusBarState.Running, 'Starting language server...'); + break; + case State.Running: + this.statusBarUpdateCallback(StatusBarState.Chill, 'Language server is ready'); + break; + case State.Stopped: + this.statusBarUpdateCallback(StatusBarState.Error, 'Language server stopped'); + break; + } + } + + /** + * Update status bar + */ + private updateStatusBar(state: StatusBarState, message?: string): void { + if (this.statusBarUpdateCallback) { + this.statusBarUpdateCallback(state, message); } } } diff --git a/extension/src/extensionFeatureManagers.ts b/extension/src/extensionFeatureManagers.ts index bee3910..1f7deab 100644 --- a/extension/src/extensionFeatureManagers.ts +++ b/extension/src/extensionFeatureManagers.ts @@ -1,11 +1,29 @@ import { CoverageManager } from "./coverage/coverageManager"; import { DetectorsManager } from "./detectors/detectorsManager"; +import { StatusBarManager, StatusBarState } from "./statusBar/statusBarManager"; function initExtensionFeatureManagers(): ExtensionFeatureManagers { console.log('Initializing extension feature managers'); + + // Create status bar manager first + const statusBarManager = new StatusBarManager(); + + // Create detectors manager + const detectorsManager = new DetectorsManager(); + + // Connect status bar manager to detectors manager + detectorsManager.setStatusBarUpdateCallback((state: StatusBarState, message?: string) => { + statusBarManager.updateStatus(state, message); + }); + + // After connecting, check if we need to update status based on current state + // This handles the case where DetectorsManager set an error state before callback was connected + // The server state will be updated via onDidChangeState event, so we don't need to manually check here + let extensionFeatureManagers: ExtensionFeatureManagers = { coverageManager: new CoverageManager(), - detectorsManager: new DetectorsManager(), + detectorsManager: detectorsManager, + statusBarManager: statusBarManager, // add other managers here ... }; @@ -15,6 +33,7 @@ function initExtensionFeatureManagers(): ExtensionFeatureManagers { interface ExtensionFeatureManagers { coverageManager: CoverageManager; detectorsManager: DetectorsManager; + statusBarManager: StatusBarManager; // add other managers here ... } diff --git a/extension/src/statusBar/commands.ts b/extension/src/statusBar/commands.ts new file mode 100644 index 0000000..8bc488d --- /dev/null +++ b/extension/src/statusBar/commands.ts @@ -0,0 +1,8 @@ +/** + * Status bar command identifiers + * These constants define all available commands for status bar interactions + */ + +// Status bar-related commands +export const SHOW_STATUS_DETAILS = "solana.showStatusDetails"; +export const INSTALL_NIGHTLY = "solana.installNightly"; diff --git a/extension/src/statusBar/statusBarManager.ts b/extension/src/statusBar/statusBarManager.ts new file mode 100644 index 0000000..8796583 --- /dev/null +++ b/extension/src/statusBar/statusBarManager.ts @@ -0,0 +1,193 @@ +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as fs from 'fs'; +import { exec } from 'child_process'; +import { promisify } from 'util'; + +const execAsync = promisify(exec); + +export enum StatusBarState { + Chill = 'chill', + Running = 'running', + Warn = 'warn', + Error = 'error', +} + +export class StatusBarManager implements vscode.Disposable { + private statusBarItem: vscode.StatusBarItem; + private currentState: StatusBarState = StatusBarState.Chill; + private rustToolchainChecked: boolean = false; + private isNightlyAvailable: boolean = false; + + constructor() { + // Create status bar item with priority 100 (default) + this.statusBarItem = vscode.window.createStatusBarItem( + vscode.StatusBarAlignment.Left, + 100 + ); + this.statusBarItem.name = 'Solana'; + + // Set initial state to running (will be updated after toolchain check and server connection) + this.updateStatus(StatusBarState.Running, 'Initializing...'); + this.statusBarItem.show(); + + // Check Rust toolchain on initialization (async, will update status when done) + this.checkRustToolchain().then(() => { + // After toolchain check, if still in initial state, update to chill or warn + if (this.currentState === StatusBarState.Running) { + if (!this.isNightlyAvailable) { + this.updateStatus(StatusBarState.Warn, 'Nightly Rust version not used. Click to install nightly.'); + } else { + this.updateStatus(StatusBarState.Chill, 'Solana extension is ready'); + } + } + }); + } + + /** + * Update the status bar badge based on the current state + */ + updateStatus(state: StatusBarState, message?: string): void { + this.currentState = state; + + switch (state) { + case StatusBarState.Chill: + // Check nightly status when transitioning to chill + // If nightly is not available, show warning instead + if (!this.isNightlyAvailable && this.rustToolchainChecked) { + this.statusBarItem.text = '$(warning) Solana'; + this.statusBarItem.tooltip = message || 'Nightly Rust version not used. Click to install nightly.'; + this.statusBarItem.color = new vscode.ThemeColor('statusBarItem.warningForeground'); + this.statusBarItem.command = 'solana.installNightly'; + } else { + this.statusBarItem.text = '$(check) Solana'; + this.statusBarItem.tooltip = message || 'Solana extension is ready'; + this.statusBarItem.color = undefined; // Use default color + this.statusBarItem.command = 'solana.reloadDetectors'; + } + break; + + case StatusBarState.Running: + this.statusBarItem.text = '$(sync~spin) Solana'; + this.statusBarItem.tooltip = message || 'Solana extension is running...'; + this.statusBarItem.color = undefined; + this.statusBarItem.command = undefined; // Disable click during running + break; + + case StatusBarState.Warn: + this.statusBarItem.text = '$(warning) Solana'; + this.statusBarItem.tooltip = message || 'Nightly Rust version not used. Click to install nightly.'; + this.statusBarItem.color = new vscode.ThemeColor('statusBarItem.warningForeground'); + this.statusBarItem.command = 'solana.installNightly'; + break; + + case StatusBarState.Error: + this.statusBarItem.text = '$(error) Solana'; + this.statusBarItem.tooltip = message || 'Solana extension error'; + this.statusBarItem.color = new vscode.ThemeColor('statusBarItem.errorForeground'); + this.statusBarItem.command = 'solana.showStatusDetails'; + break; + } + + this.statusBarItem.show(); + } + + /** + * Check if nightly Rust toolchain is available/configured + */ + private async checkRustToolchain(): Promise { + if (this.rustToolchainChecked) { + return; + } + + try { + // First, check workspace toolchain files + const workspaceFolders = vscode.workspace.workspaceFolders; + if (workspaceFolders && workspaceFolders.length > 0) { + const workspaceRoot = workspaceFolders[0].uri.fsPath; + + // Check for rust-toolchain.toml + const rustToolchainToml = path.join(workspaceRoot, 'rust-toolchain.toml'); + if (fs.existsSync(rustToolchainToml)) { + const content = fs.readFileSync(rustToolchainToml, 'utf-8'); + if (content.includes('channel = "nightly"') || content.includes('channel="nightly"')) { + this.isNightlyAvailable = true; + this.rustToolchainChecked = true; + return; + } + } + + // Check for rust-toolchain file (without .toml extension) + const rustToolchain = path.join(workspaceRoot, 'rust-toolchain'); + if (fs.existsSync(rustToolchain)) { + const content = fs.readFileSync(rustToolchain, 'utf-8'); + if (content.includes('nightly')) { + this.isNightlyAvailable = true; + this.rustToolchainChecked = true; + return; + } + } + } + + // Fallback: check if nightly is installed (regardless of whether it's active) + try { + const { stdout } = await execAsync('rustup toolchain list'); + // Check if any nightly toolchain is installed + // Format: "nightly-YYYY-MM-DD-x86_64-apple-darwin (default)" or "nightly-YYYY-MM-DD-x86_64-apple-darwin" + if (stdout.includes('nightly')) { + this.isNightlyAvailable = true; + this.rustToolchainChecked = true; + return; + } + } catch { + // rustup might not be available + } + + // No nightly found + this.isNightlyAvailable = false; + this.rustToolchainChecked = true; + + // Update status if we're in chill state and nightly is not available + // Only update to warn if we're currently in chill state (not running or error) + if (this.currentState === StatusBarState.Chill) { + this.updateStatus(StatusBarState.Warn, 'Nightly Rust version not used. Click to install nightly.'); + } + } catch (error) { + console.error('Error checking Rust toolchain:', error); + this.rustToolchainChecked = true; + } + } + + /** + * Get current state + */ + getCurrentState(): StatusBarState { + return this.currentState; + } + + /** + * Check if nightly is available + */ + isNightlyRustAvailable(): boolean { + return this.isNightlyAvailable; + } + + /** + * Re-check Rust toolchain (useful after installing nightly) + */ + async recheckRustToolchain(): Promise { + this.rustToolchainChecked = false; + await this.checkRustToolchain(); + + // Update status based on new toolchain check + if (this.currentState === StatusBarState.Warn && this.isNightlyAvailable) { + this.updateStatus(StatusBarState.Chill, 'Nightly Rust is now available'); + } else if (this.currentState === StatusBarState.Chill && !this.isNightlyAvailable) { + this.updateStatus(StatusBarState.Warn, 'Nightly Rust version not used. Click to install nightly.'); + } + } + + dispose(): void { + this.statusBarItem.dispose(); + } +} From 20475a622e5d210afc72a118b5ccd2d8e4bc166d Mon Sep 17 00:00:00 2001 From: Maksym Kupchenko Date: Sun, 30 Nov 2025 23:24:40 +0100 Subject: [PATCH 2/3] UPD --- extension/package.json | 4 ++ extension/src/commands.ts | 27 +++++++- extension/src/statusBar/commands.ts | 1 + extension/src/statusBar/statusBarManager.ts | 70 ++++++++++++++++++--- 4 files changed, 92 insertions(+), 10 deletions(-) diff --git a/extension/package.json b/extension/package.json index 33102ad..8340ef0 100644 --- a/extension/package.json +++ b/extension/package.json @@ -63,6 +63,10 @@ { "command": "solana.installNightly", "title": "solana: Install Nightly Rust Toolchain" + }, + { + "command": "solana.showStatusMenu", + "title": "solana: Show Status Menu" } ], "keybindings": [ diff --git a/extension/src/commands.ts b/extension/src/commands.ts index 9da6002..13279d3 100644 --- a/extension/src/commands.ts +++ b/extension/src/commands.ts @@ -2,7 +2,7 @@ import * as vscode from "vscode"; import { ExtensionFeatureManagers } from "./extensionFeatureManagers"; import { CLOSE_COVERAGE, SHOW_COVERAGE } from "./coverage/commands"; import { RELOAD_DETECTORS, SCAN_WORKSPACE, SHOW_SCAN_OUTPUT } from "./detectors/commands"; -import { INSTALL_NIGHTLY, SHOW_STATUS_DETAILS } from "./statusBar/commands"; +import { INSTALL_NIGHTLY, SHOW_STATUS_DETAILS, SHOW_STATUS_MENU } from "./statusBar/commands"; import { StatusBarState } from "./statusBar/statusBarManager"; function registerCommands( @@ -42,6 +42,31 @@ function registerCommands( }) ); + // Add command to show status menu (quick pick overlay) - rust-analyzer style + context.subscriptions.push( + vscode.commands.registerCommand(SHOW_STATUS_MENU, async () => { + const items: vscode.QuickPickItem[] = [ + { + label: '$(sync) Reload Detectors', + description: 'Reload all security detectors', + detail: 'Restart the detector system and rescan the workspace' + } + ]; + + const selected = await vscode.window.showQuickPick(items, { + placeHolder: 'Select an action...', + matchOnDescription: true, + matchOnDetail: true + }); + + if (selected) { + if (selected.label.includes('Reload Detectors')) { + await vscode.commands.executeCommand(RELOAD_DETECTORS); + } + } + }) + ); + // Add command to show status details context.subscriptions.push( vscode.commands.registerCommand(SHOW_STATUS_DETAILS, async () => { diff --git a/extension/src/statusBar/commands.ts b/extension/src/statusBar/commands.ts index 8bc488d..c4ab308 100644 --- a/extension/src/statusBar/commands.ts +++ b/extension/src/statusBar/commands.ts @@ -6,3 +6,4 @@ // Status bar-related commands export const SHOW_STATUS_DETAILS = "solana.showStatusDetails"; export const INSTALL_NIGHTLY = "solana.installNightly"; +export const SHOW_STATUS_MENU = "solana.showStatusMenu"; diff --git a/extension/src/statusBar/statusBarManager.ts b/extension/src/statusBar/statusBarManager.ts index 8796583..1e7c07a 100644 --- a/extension/src/statusBar/statusBarManager.ts +++ b/extension/src/statusBar/statusBarManager.ts @@ -18,8 +18,14 @@ export class StatusBarManager implements vscode.Disposable { private currentState: StatusBarState = StatusBarState.Chill; private rustToolchainChecked: boolean = false; private isNightlyAvailable: boolean = false; + private extensionVersion: string = 'unknown'; constructor() { + // Get extension version + const extension = vscode.extensions.getExtension('AckeeBlockchain.solana'); + if (extension) { + this.extensionVersion = extension.packageJSON.version || 'unknown'; + } // Create status bar item with priority 100 (default) this.statusBarItem = vscode.window.createStatusBarItem( vscode.StatusBarAlignment.Left, @@ -44,6 +50,52 @@ export class StatusBarManager implements vscode.Disposable { }); } + /** + * Create a rich tooltip with clickable actions (rust-analyzer style) + * Actions are directly clickable in the tooltip using command links + */ + private createRichTooltip(state: StatusBarState, message?: string): vscode.MarkdownString { + const tooltip = new vscode.MarkdownString(); + tooltip.isTrusted = true; + + // Header with version info (rust-analyzer style) + tooltip.appendMarkdown('### Solana Language Server\n\n'); + tooltip.appendMarkdown(`**Extension:** v${this.extensionVersion}\n`); + tooltip.appendMarkdown('\n---\n\n'); + + switch (state) { + case StatusBarState.Chill: + tooltip.appendMarkdown(message || 'Ready'); + if (this.isNightlyAvailable) { + tooltip.appendMarkdown('\n\n✅ Nightly Rust toolchain available'); + } + tooltip.appendMarkdown('\n\n---\n\n'); + tooltip.appendMarkdown('**Actions:**\n\n'); + tooltip.appendMarkdown(`🔄 [Reload Detectors](command:solana.reloadDetectors "Reload all security detectors")\n`); + break; + + case StatusBarState.Running: + tooltip.appendMarkdown(message || 'Running...'); + break; + + case StatusBarState.Warn: + tooltip.appendMarkdown('âš ī¸ ' + (message || 'Nightly Rust version not used')); + tooltip.appendMarkdown('\n\n---\n\n'); + tooltip.appendMarkdown('**Actions:**\n\n'); + tooltip.appendMarkdown(`âŦ‡ī¸ [Install Nightly Rust](command:solana.installNightly "Install nightly Rust toolchain")\n`); + break; + + case StatusBarState.Error: + tooltip.appendMarkdown('❌ ' + (message || 'Error occurred')); + tooltip.appendMarkdown('\n\n---\n\n'); + tooltip.appendMarkdown('**Actions:**\n\n'); + tooltip.appendMarkdown(`â„šī¸ [Show Details](command:solana.showStatusDetails "View error details")\n`); + break; + } + + return tooltip; + } + /** * Update the status bar badge based on the current state */ @@ -56,36 +108,36 @@ export class StatusBarManager implements vscode.Disposable { // If nightly is not available, show warning instead if (!this.isNightlyAvailable && this.rustToolchainChecked) { this.statusBarItem.text = '$(warning) Solana'; - this.statusBarItem.tooltip = message || 'Nightly Rust version not used. Click to install nightly.'; + this.statusBarItem.tooltip = this.createRichTooltip(StatusBarState.Warn, message); this.statusBarItem.color = new vscode.ThemeColor('statusBarItem.warningForeground'); this.statusBarItem.command = 'solana.installNightly'; } else { - this.statusBarItem.text = '$(check) Solana'; - this.statusBarItem.tooltip = message || 'Solana extension is ready'; + this.statusBarItem.text = 'Solana'; + this.statusBarItem.tooltip = this.createRichTooltip(StatusBarState.Chill, message); this.statusBarItem.color = undefined; // Use default color - this.statusBarItem.command = 'solana.reloadDetectors'; + this.statusBarItem.command = undefined; // Actions are in tooltip, no click needed } break; case StatusBarState.Running: this.statusBarItem.text = '$(sync~spin) Solana'; - this.statusBarItem.tooltip = message || 'Solana extension is running...'; + this.statusBarItem.tooltip = this.createRichTooltip(StatusBarState.Running, message); this.statusBarItem.color = undefined; this.statusBarItem.command = undefined; // Disable click during running break; case StatusBarState.Warn: this.statusBarItem.text = '$(warning) Solana'; - this.statusBarItem.tooltip = message || 'Nightly Rust version not used. Click to install nightly.'; + this.statusBarItem.tooltip = this.createRichTooltip(StatusBarState.Warn, message); this.statusBarItem.color = new vscode.ThemeColor('statusBarItem.warningForeground'); - this.statusBarItem.command = 'solana.installNightly'; + this.statusBarItem.command = undefined; // Actions are in tooltip break; case StatusBarState.Error: this.statusBarItem.text = '$(error) Solana'; - this.statusBarItem.tooltip = message || 'Solana extension error'; + this.statusBarItem.tooltip = this.createRichTooltip(StatusBarState.Error, message); this.statusBarItem.color = new vscode.ThemeColor('statusBarItem.errorForeground'); - this.statusBarItem.command = 'solana.showStatusDetails'; + this.statusBarItem.command = undefined; // Actions are in tooltip break; } From 4f4f3fa1613eee7f056a6d73fe22f6d6b216c773 Mon Sep 17 00:00:00 2001 From: Maksym Kupchenko Date: Sun, 30 Nov 2025 23:25:56 +0100 Subject: [PATCH 3/3] clear code --- extension/package.json | 4 ---- extension/src/commands.ts | 27 +-------------------------- extension/src/statusBar/commands.ts | 1 - 3 files changed, 1 insertion(+), 31 deletions(-) diff --git a/extension/package.json b/extension/package.json index 8340ef0..33102ad 100644 --- a/extension/package.json +++ b/extension/package.json @@ -63,10 +63,6 @@ { "command": "solana.installNightly", "title": "solana: Install Nightly Rust Toolchain" - }, - { - "command": "solana.showStatusMenu", - "title": "solana: Show Status Menu" } ], "keybindings": [ diff --git a/extension/src/commands.ts b/extension/src/commands.ts index 13279d3..9da6002 100644 --- a/extension/src/commands.ts +++ b/extension/src/commands.ts @@ -2,7 +2,7 @@ import * as vscode from "vscode"; import { ExtensionFeatureManagers } from "./extensionFeatureManagers"; import { CLOSE_COVERAGE, SHOW_COVERAGE } from "./coverage/commands"; import { RELOAD_DETECTORS, SCAN_WORKSPACE, SHOW_SCAN_OUTPUT } from "./detectors/commands"; -import { INSTALL_NIGHTLY, SHOW_STATUS_DETAILS, SHOW_STATUS_MENU } from "./statusBar/commands"; +import { INSTALL_NIGHTLY, SHOW_STATUS_DETAILS } from "./statusBar/commands"; import { StatusBarState } from "./statusBar/statusBarManager"; function registerCommands( @@ -42,31 +42,6 @@ function registerCommands( }) ); - // Add command to show status menu (quick pick overlay) - rust-analyzer style - context.subscriptions.push( - vscode.commands.registerCommand(SHOW_STATUS_MENU, async () => { - const items: vscode.QuickPickItem[] = [ - { - label: '$(sync) Reload Detectors', - description: 'Reload all security detectors', - detail: 'Restart the detector system and rescan the workspace' - } - ]; - - const selected = await vscode.window.showQuickPick(items, { - placeHolder: 'Select an action...', - matchOnDescription: true, - matchOnDetail: true - }); - - if (selected) { - if (selected.label.includes('Reload Detectors')) { - await vscode.commands.executeCommand(RELOAD_DETECTORS); - } - } - }) - ); - // Add command to show status details context.subscriptions.push( vscode.commands.registerCommand(SHOW_STATUS_DETAILS, async () => { diff --git a/extension/src/statusBar/commands.ts b/extension/src/statusBar/commands.ts index c4ab308..8bc488d 100644 --- a/extension/src/statusBar/commands.ts +++ b/extension/src/statusBar/commands.ts @@ -6,4 +6,3 @@ // Status bar-related commands export const SHOW_STATUS_DETAILS = "solana.showStatusDetails"; export const INSTALL_NIGHTLY = "solana.installNightly"; -export const SHOW_STATUS_MENU = "solana.showStatusMenu";