| // Copyright 2022 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // The module 'vscode' contains the VS Code extensibility API |
| // Import the module and reference it with the alias vscode in your code below |
| import * as vscode from 'vscode'; |
| |
| import { spawn } from 'child_process'; |
| import { disposeAnalytics, initAnalytics, setUpAnalyticsEvents } from './analytics/setup'; |
| import { LoggingViewProvider } from './logging/view_provider'; |
| import { ToolFinder } from './tool_finder'; |
| import { Ffx } from './ffx'; |
| import * as logger from './logger'; |
| import { TargetStatusBarItem } from './target_status_bar_item'; |
| import { FuchsiaDevice } from './ffx'; |
| import { setUpZxdb } from './zxdb/zxdb'; |
| import * as flags from './feature-flags'; |
| |
| /** |
| * contains common bits needed by the various setup functions below |
| */ |
| export class Setup { |
| |
| /** |
| * a handle to interact with ffx |
| */ |
| ffx: Ffx; |
| |
| constructor(ctx: vscode.ExtensionContext) { |
| |
| const toolFinder = new ToolFinder(); |
| this.ffx = toolFinder.ffx; |
| } |
| } |
| |
| /** |
| * called automatically by vscode when activating the plugin |
| * (see package.json for activation points) |
| */ |
| export async function activate(ctx: vscode.ExtensionContext) { |
| flags.activate(ctx.extension.packageJSON.version); |
| |
| // Initialize the logging first so it can be used by all other code. |
| const log = vscode.window.createOutputChannel('Fuchsia SDK'); |
| logger.initLogger(log); |
| |
| // Init analytics before possible calls to other Fuchsia tools (e.g. ffx), |
| // such that the extension could display the analytics notices properly. |
| try { |
| await initAnalytics(ctx); |
| } catch (err) { |
| // if analytics fails to initialize, it's not catastrophic, |
| // so just continue on after logging |
| logger.error('Unable to set up analytics, boldly continuing', undefined, err); |
| }; |
| let setup = new Setup(ctx); |
| |
| // TODO(fxbug.dev/98651): we're currently doing this every program |
| // start -- we should find a better activation point |
| ctx.subscriptions.push( |
| vscode.commands.registerCommand('fuchsia.sendFeedback', () => { |
| // The code you place here will be executed every time your command is executed |
| void /* in bg */ vscode.env.openExternal(vscode.Uri.parse( |
| 'https://bugs.fuchsia.dev/p/fuchsia/issues/entry?template=Fuchsia+Editor+Tooling')); |
| }), |
| ); |
| |
| setUpLoggingView(ctx, setup); |
| setUpEmulatorInteraction(ctx, setup); |
| setUpTargetInteraction(ctx, setup); |
| setUpZxdb(ctx, setup); |
| |
| // Set up analytics events as the last step, as ffx calls in the activation process should not be |
| // considered as user initiated actions. |
| setUpAnalyticsEvents(setup.ffx); |
| } |
| |
| /** |
| * called automatically by vscode when deactivating the plugin |
| */ |
| export function deactivate() { |
| disposeAnalytics(); |
| flags.deactivate(); |
| } |
| |
| /** |
| * initialize the logging view & related commands |
| */ |
| function setUpLoggingView(ctx: vscode.ExtensionContext, setup: Setup) { |
| // initialize the view |
| const loggingProvider = new LoggingViewProvider(ctx.extensionUri, setup.ffx); |
| ctx.subscriptions.push( |
| vscode.window.registerWebviewViewProvider(LoggingViewProvider.viewType, loggingProvider)); |
| |
| // set up command-palette commands |
| ctx.subscriptions.push( |
| vscode.commands.registerCommand('fuchsia.viewLogs', (device?: FuchsiaDevice) => { |
| void /* in bg */ loggingProvider.resetAndShowView(device); |
| }) |
| ); |
| } |
| |
| /** |
| * initialize the target interaction commands (reboot, set target, etc) |
| * and status bar item. |
| */ |
| function setUpEmulatorInteraction(ctx: vscode.ExtensionContext, setup: Setup) { |
| let registerSimpleEmulatorCommand = (commandName: string, |
| command: () => Promise<string>) => { |
| ctx.subscriptions.push( |
| vscode.commands.registerCommand(commandName, |
| async () => { |
| try { |
| let output = await command(); |
| logger.info(output, 'fuchsia'); |
| } catch (err: any) { |
| void vscode.window.showErrorMessage(err); |
| } |
| }) |
| ); |
| }; |
| |
| registerSimpleEmulatorCommand('fuchsia.emu.start', |
| setup.ffx.startEmulator.bind(setup.ffx)); |
| registerSimpleEmulatorCommand('fuchsia.emu.stop', |
| setup.ffx.stopEmulator.bind(setup.ffx)); |
| } |
| |
| /** |
| * initialize the target interaction commands (reboot, set target, etc) |
| * and status bar item. |
| */ |
| function setUpTargetInteraction(ctx: vscode.ExtensionContext, setup: Setup) { |
| let registerSimpleTargetCommand = (commandName: string, |
| command: (device?: FuchsiaDevice) => Promise<string>) => { |
| ctx.subscriptions.push( |
| vscode.commands.registerCommand(commandName, |
| async (device?: FuchsiaDevice) => { |
| try { |
| let output = await command(device); |
| logger.info(output, 'fuchsia'); |
| } catch (err: any) { |
| void vscode.window.showErrorMessage(err); |
| } |
| }) |
| ); |
| }; |
| // set up commands... |
| registerSimpleTargetCommand('fuchsia.target.reboot', |
| setup.ffx.rebootTarget.bind(setup.ffx)); |
| registerSimpleTargetCommand('fuchsia.target.show', |
| setup.ffx.showTarget.bind(setup.ffx)); |
| registerSimpleTargetCommand('fuchsia.target.powerOff', |
| setup.ffx.poweroffTarget.bind(setup.ffx)); |
| |
| ctx.subscriptions.push( |
| vscode.commands.registerCommand('fuchsia.target.snapshot', |
| async (device?: FuchsiaDevice) => { |
| let path = await setup.ffx.exportSnapshotToCWD(device); |
| let msg = `snapshot exported to ${path}`; |
| logger.info(msg, 'fuchsia'); |
| |
| if (await vscode.window.showInformationMessage(msg, 'Open folder')) { |
| spawn('xdg-open', [path]); |
| } |
| }) |
| ); |
| |
| ctx.subscriptions.push( |
| vscode.commands.registerCommand('fuchsia.internal.target.setDefault', |
| async (device?: FuchsiaDevice) => { |
| if (!device) { |
| void vscode.window.showErrorMessage('A device must be selected to set as the default target.'); |
| return; |
| } |
| |
| try { |
| let output = await setup.ffx.defaultTarget(device); |
| logger.debug(`Result from setting default target: ${output}`); |
| } catch (err: any) { |
| void vscode.window.showErrorMessage(err); |
| } |
| }) |
| ); |
| |
| // ...and the status bar item |
| new TargetStatusBarItem(ctx.subscriptions, setup.ffx); |
| } |
| |