チュートリアルを行う
https://code.visualstudio.com/api/extension-guides/tree-view
チュートリアルではサイドバーにnode dependenciesを表示し、各packageのpackage.jsonを表示するサンプルを作っている。 しかしチュートリアルをそのまま試してもEditorにpackage.jsonの内容が表示されなかった。
その理由が知りたくて色々と調査した
結果として、githubのサンプルを実行するとわかるが、クリック時に発火するコマンドを指定しないと行けなかった
コマンド発火のコードリーディング
TreeViewをみると、チュートリアルに加えてvscode.Commandを付与している
return new Dependency(moduleName, version, vscode.TreeItemCollapsibleState.None, {
command: 'extension.openPackageOnNpm',
title: '',
arguments: [moduleName]
});
併せてopenPackageOnNpmの登録もチュートリアルから追加されている
vscode.commands.registerCommand('extension.openPackageOnNpm', moduleName => vscode.commands.executeCommand('vscode.open', vscode.Uri.parse(`https://www.npmjs.com/package/${moduleName}`)));
実際、これらを実装するとクリックしたらNPMのwebpageに飛ぶ挙動が確認できた
TreeItemオブジェクトはcommandをフィールドに保存しているが、自クラスでフィールドを操作している形跡はない つまり、vscode本体でTreeItem.commandを呼び出していると考えられる
vscode本体をコードリーディング
TreeItemの定義はこちら
command自体は存在している
よって、vscode本体でTreeItem.commandを呼び出す仮説は正しそう
https://github.com/microsoft/vscode/blob/main/src/vs/vscode.d.ts#L9136
この説明を見るに、clickをフックしてcommandを呼んでいる模様。
async resolveTreeItem(treeItemHandle: string, token: vscode.CancellationToken): Promise<ITreeItem | undefined> {
if (!this.dataProvider.resolveTreeItem) {
return;
}
const element = this.elements.get(treeItemHandle);
if (element) {
const node = this.nodes.get(element);
if (node) {
const resolve = await this.dataProvider.resolveTreeItem(node.extensionItem, element, token) ?? node.extensionItem;
// Resolvable elements. Currently only tooltip and command.
node.item.tooltip = this.getTooltip(resolve.tooltip);
node.item.command = this.getCommand(node.disposableStore, resolve.command);
return node.item;
}
}
return;
}
TreeItemを取得するときにクリックハンドラをgetCommandで取得していた