vscode extensionのTreeViewを触ってみる

チュートリアルを行う 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; } https://github.com/microsoft/vscode/blob/8aff878db2542eea2dfb571c8bb485118bbb3113/src/vs/workbench/api/common/extHostTreeViews.ts#L376-L392 TreeItemを取得するときにクリックハンドラをgetCommandで取得していた

April 19, 2021 · 1 min · motoki yoan