blob: 0ee40b0cfb10d44cc10907d77a2d8c5c3a5486fc [file] [log] [blame] [edit]
// 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.
import * as path from 'path';
import * as vscode from 'vscode';
import * as commonUtil from '../common/common_util';
import * as config from '../services/config';
import * as ideUtil from '../ide_util';
import * as metrics from './metrics/metrics';
export function activate(context: vscode.ExtensionContext) {
const openFileCmd = vscode.commands.registerTextEditorCommand(
'cros-ide.codeSearchOpenCurrentFile',
(textEditor: vscode.TextEditor) => void openCurrentFile(textEditor)
);
const copyFileCmd = vscode.commands.registerTextEditorCommand(
'cros-ide.codeSearchCopyCurrentFile',
(textEditor: vscode.TextEditor) => void copyCurrentFile(textEditor)
);
const searchSelectionCmd = vscode.commands.registerTextEditorCommand(
'cros-ide.codeSearchSearchForSelection',
(textEditor: vscode.TextEditor) => searchSelection(textEditor)
);
context.subscriptions.push(openFileCmd, searchSelectionCmd, copyFileCmd);
}
function getCodeSearchToolConfig(
fullpath: string
): {executable: string; cwd: string} | undefined {
const chroot = commonUtil.findChroot(fullpath);
if (!chroot) {
return undefined;
}
const source = commonUtil.sourceDir(chroot);
return {
executable: path.join(source, 'chromite/contrib/generate_cs_path'),
cwd: chroot,
};
}
async function openCurrentFile(textEditor: vscode.TextEditor) {
const result = await getCurrentFile(textEditor);
if (result) {
void vscode.env.openExternal(vscode.Uri.parse(result));
metrics.send({
category: 'interactive',
group: 'codesearch',
action: 'open current file',
});
}
}
async function copyCurrentFile(textEditor: vscode.TextEditor) {
const result = await getCurrentFile(textEditor);
if (result) {
void vscode.env.clipboard.writeText(result);
metrics.send({
category: 'interactive',
group: 'codesearch',
action: 'copy current file',
});
}
}
async function getCurrentFile(
textEditor: vscode.TextEditor
): Promise<string | undefined> {
const fullpath = textEditor.document.fileName;
// Which CodeSearch to use, options are public, internal, or gitiles.
const csInstance = config.codeSearch.instance.get();
const csHash = config.codeSearch.openWithRevision.get();
const line = textEditor.selection.active.line + 1;
const csConfig = getCodeSearchToolConfig(fullpath);
if (!csConfig) {
void vscode.window.showErrorMessage(
"Could not find 'generate_cs_path' script"
);
return;
}
const {executable, cwd} = csConfig;
const opts = [];
if (csHash) {
opts.push('--upstream-sha');
}
opts.push('--show', `--${csInstance}`, `--line=${line}`, fullpath);
const res = await commonUtil.exec(executable, opts, {
logger: ideUtil.getUiLogger(),
logStdout: true,
ignoreNonZeroExit: true,
cwd: cwd,
});
if (res instanceof Error) {
void vscode.window.showErrorMessage(
'Could not run generate_cs_path: ' + res
);
return;
}
const {exitStatus, stdout, stderr} = res;
if (exitStatus) {
void vscode.window.showErrorMessage(
`generate_cs_path returned an error: ${stderr}`
);
metrics.send({
category: 'error',
group: 'codesearch',
description: 'generate_cs_path failed',
});
return;
}
// trimEnd() to get rid of the newline.
return stdout.trimEnd();
}
// TODO: Figure out if the search should be limited to the current repo.
function searchSelection(textEditor: vscode.TextEditor) {
if (textEditor.selection.isEmpty) {
return;
}
// If the setting is gitiles, we use public CodeSearch
const csInstance = config.codeSearch.instance.get();
const csBase =
csInstance === 'internal'
? 'https://source.corp.google.com/'
: 'https://source.chromium.org/';
const selectedText = textEditor.document.getText(textEditor.selection);
const uri = vscode.Uri.parse(csBase).with({
path: '/search',
query: `q=${selectedText}`,
});
void vscode.env.openExternal(uri);
metrics.send({
category: 'interactive',
group: 'codesearch',
action: 'search selection',
label: selectedText,
});
}
export const TEST_ONLY = {
openCurrentFile,
searchSelection,
};