| // Copyright 2022 The ChromiumOS Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| /** |
| * This is the main entry point for the vsCode plugin. |
| * |
| * Keep this minimal - breakout GUI and App-Behavior to separate files. |
| */ |
| import * as vscode from 'vscode'; |
| import * as sourceMapSupport from 'source-map-support'; |
| import * as cipd from './common/cipd'; |
| import * as commonUtil from './common/common_util'; |
| import {vscodeRegisterCommand} from './common/vscode/commands'; |
| import * as features from './features'; |
| import * as boilerplate from './features/boilerplate'; |
| import * as codesearch from './features/codesearch'; |
| import * as crosLint from './features/cros_lint'; |
| import * as deviceManagement from './features/device_management'; |
| import * as gerrit from './features/gerrit'; |
| import * as gn from './features/gn'; |
| import * as hints from './features/hints'; |
| import * as feedback from './features/metrics/feedback'; |
| import * as metrics from './features/metrics/metrics'; |
| import * as metricsConfig from './features/metrics/metrics_config'; |
| import * as ownersLinks from './features/owners_links'; |
| import * as shortLinkProvider from './features/short_link_provider'; |
| import * as showHelp from './features/show_help'; |
| import * as suggestExtension from './features/suggest_extension'; |
| import * as upstart from './features/upstart'; |
| import * as ideUtil from './ide_util'; |
| import * as logs from './logs'; |
| import * as migrate from './migrate'; |
| import * as services from './services'; |
| import * as config from './services/config'; |
| import * as gitDocument from './services/git_document'; |
| import * as bgTaskStatus from './ui/bg_task_status'; |
| import {TaskStatus} from './ui/bg_task_status'; |
| |
| // Install source map if it's available so that error stacktraces show TS |
| // filepaths during our development. |
| sourceMapSupport.install({}); |
| |
| export interface ExtensionApi { |
| // ExtensionContext passed to the activation function. |
| // Available only when the extension is activated for testing. |
| context?: vscode.ExtensionContext; |
| } |
| |
| export async function activate( |
| context: vscode.ExtensionContext |
| ): Promise<ExtensionApi> { |
| // Migrate user configs if needed before anything else. |
| await migrate.migrate(); |
| |
| // Activate metrics so that other components can emit metrics on activation. |
| await metrics.activate(context); |
| |
| try { |
| return await postMetricsActivate(context); |
| } catch (err) { |
| metrics.send({ |
| category: 'error', |
| group: 'misc', |
| description: `activate failed: ${err}`, |
| name: 'extension_activation_failed', |
| }); |
| throw err; |
| } |
| } |
| |
| async function postMetricsActivate( |
| context: vscode.ExtensionContext |
| ): Promise<ExtensionApi> { |
| assertOutsideChroot(); |
| |
| const statusManager = bgTaskStatus.activate(context); |
| const cipdRepository = new cipd.CipdRepository(); |
| |
| const chromiumosServices = new services.chromiumos.ChromiumosServiceModule(); |
| |
| deviceManagement.activate( |
| context, |
| statusManager, |
| chromiumosServices, |
| cipdRepository |
| ); |
| |
| const boilerplateInserter = new boilerplate.BoilerplateInserter(); |
| context.subscriptions.push(boilerplateInserter); |
| |
| context.subscriptions.push( |
| new ChromiumActivation(context, statusManager, boilerplateInserter), |
| new ChromiumosActivation( |
| context, |
| statusManager, |
| boilerplateInserter, |
| cipdRepository, |
| chromiumosServices |
| ) |
| ); |
| |
| context.subscriptions.push( |
| vscodeRegisterCommand(ideUtil.SHOW_UI_LOG.command, () => { |
| ideUtil.getUiLogger().show(); |
| metrics.send({ |
| category: 'interactive', |
| group: 'idestatus', |
| description: 'show ui actions log', |
| name: 'show_ui_actions_log', |
| }); |
| }) |
| ); |
| |
| // The logger that should be used by linters/code-formatters. |
| const linterLogger = logs.createLinterLoggingBundle(context); |
| |
| // We need an item in the IDE status, which lets users discover the UI log. Since UI actions |
| // which result in an error should show a popup, we will not be changing the status |
| statusManager.setTask('UI Actions', { |
| status: TaskStatus.OK, |
| command: ideUtil.SHOW_UI_LOG, |
| }); |
| |
| crosLint.activate(context, statusManager, linterLogger); |
| gn.activate(context, statusManager, linterLogger); |
| shortLinkProvider.activate(context); |
| if (config.ownersFiles.links.get()) { |
| ownersLinks.activate(context); |
| } |
| codesearch.activate(context); |
| suggestExtension.activate(context); |
| feedback.activate(context); |
| upstart.activate(context); |
| hints.activate(context); |
| showHelp.activate(context); |
| |
| const gitDocumentProvider = new gitDocument.GitDocumentProvider(); |
| gitDocumentProvider.activate(); |
| |
| if (config.gerrit.enabled.get()) { |
| const gitDirsWatcher = new services.GitDirsWatcher('/'); |
| context.subscriptions.push( |
| gerrit.activate(statusManager, gitDirsWatcher), |
| gitDirsWatcher |
| ); |
| } |
| |
| // We want to know if some users flip enablement bit. |
| // If the feature is disabled it could mean that it's annoying. |
| if (!config.gerrit.enabled.hasDefaultValue()) { |
| metrics.send({ |
| category: 'background', |
| group: 'gerrit', |
| description: 'gerrit enablement', |
| name: 'gerrit_setting_toggled', |
| flag: String(config.gerrit.enabled.get()), |
| }); |
| } |
| |
| metrics.send({ |
| category: 'background', |
| group: 'misc', |
| description: 'activate', |
| name: 'extension_activated', |
| }); |
| |
| const age = await metricsConfig.getUserIdAgeInDays(); |
| metrics.send({ |
| category: 'background', |
| group: 'misc', |
| description: 'user ID age', |
| name: 'get_user_id_age', |
| age: age, |
| }); |
| |
| return { |
| context: |
| context.extensionMode === vscode.ExtensionMode.Test ? context : undefined, |
| }; |
| } |
| |
| /** |
| * Registers a handler to activate chromiumos features when the workspace |
| * contains chromiumos source code. |
| * |
| * TODO(oka): Remove this class, using ChromiumosServiceModule instead. |
| */ |
| class ChromiumosActivation implements vscode.Disposable { |
| private readonly watcher = new services.ProductWatcher('chromiumos'); |
| private chromiumosFeatures?: features.Chromiumos; |
| |
| private readonly subscriptions: vscode.Disposable[] = [this.watcher]; |
| |
| dispose(): void { |
| this.chromiumosFeatures?.dispose(); |
| vscode.Disposable.from(...this.subscriptions.reverse()).dispose(); |
| } |
| |
| constructor( |
| context: vscode.ExtensionContext, |
| statusManager: bgTaskStatus.StatusManager, |
| boilerplateInserter: boilerplate.BoilerplateInserter, |
| cipdRepository: cipd.CipdRepository, |
| chromiumosServices: services.chromiumos.ChromiumosServiceModule |
| ) { |
| this.subscriptions.push( |
| this.watcher.onDidChangeRoot(root => { |
| this.chromiumosFeatures?.dispose(); |
| this.chromiumosFeatures = root |
| ? new features.Chromiumos( |
| context, |
| root, |
| statusManager, |
| boilerplateInserter, |
| cipdRepository, |
| chromiumosServices |
| ) |
| : undefined; |
| }) |
| ); |
| } |
| } |
| |
| /** |
| * Registers a handler to activate chromium features when the workspace |
| * contains chromium source code. |
| */ |
| class ChromiumActivation implements vscode.Disposable { |
| private readonly watcher = new services.ProductWatcher('chromium'); |
| private chromiumFeatures?: features.Chromium; |
| |
| private readonly subscriptions: vscode.Disposable[] = [this.watcher]; |
| |
| dispose(): void { |
| this.chromiumFeatures?.dispose(); |
| vscode.Disposable.from(...this.subscriptions.reverse()).dispose(); |
| } |
| |
| constructor( |
| context: vscode.ExtensionContext, |
| statusManager: bgTaskStatus.StatusManager, |
| boilerplateInserter: boilerplate.BoilerplateInserter |
| ) { |
| this.subscriptions.push( |
| this.watcher.onDidChangeRoot(root => { |
| this.chromiumFeatures?.dispose(); |
| this.chromiumFeatures = root |
| ? new features.Chromium( |
| context, |
| root, |
| statusManager, |
| boilerplateInserter |
| ) |
| : undefined; |
| }) |
| ); |
| } |
| } |
| |
| function assertOutsideChroot() { |
| if (!commonUtil.isInsideChroot()) { |
| return; |
| } |
| void (async () => { |
| const openDocument = 'Open document'; |
| const choice = await vscode.window.showWarningMessage( |
| 'Support for running VSCode inside chroot is dropped in the next release that comes soon; please read go/chromiumide-quickstart and update your setup.', |
| {modal: true}, |
| openDocument |
| ); |
| if (choice === openDocument) { |
| void vscode.env.openExternal( |
| vscode.Uri.parse('http://go/chromiumide-quickstart') |
| ); |
| } |
| })(); |
| } |