Dock the results table in the bottom panel

createWebviewPanel only ever lives in the editor area, so the table could
not be dragged next to Terminal / Problems. A WebviewView can, and it can
also be dragged to either side bar.

- Extract ResultsView: the table's html, messaging, row building and
  navigation, independent of what hosts the webview. ReferencePanel keeps
  hosting it in an editor group; ReferenceViewProvider hosts it in a
  contributed panel view container. Results that arrive before the docked
  view has been resolved are queued and applied on resolve.
- coloredReferences.panelLocation selects the placement: bottom (default),
  beside, or below. "below" makes the editor row first so the table is wide
  and short, which suits the column layout better than a tall narrow group.
- sourceColumn() now ignores editors with no view column, so opening a
  reference from the docked view lands in a real editor group.
- toggleView and the refresh button work from either host.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
max
2026-09-07 16:23:02 +02:00
co-authored by Claude Opus 5
parent 2398b6b2ce
commit 92ff02f7ff
5 changed files with 312 additions and 81 deletions
+65 -4
View File
@@ -57,6 +57,20 @@ async function search(relativeFile: string, declaration: string, symbol: string)
return { results, position, uri };
}
function coloredEditorTabs(): vscode.Tab[] {
return vscode.window.tabGroups.all.flatMap(g => g.tabs).filter(tab => {
const input = tab.input as { uri?: vscode.Uri } | undefined;
return input?.uri?.scheme === 'colored-refs';
});
}
async function setPlacement(placement: string): Promise<void> {
await vscode.workspace.getConfiguration('coloredReferences')
.update('panelLocation', placement, vscode.ConfigurationTarget.Workspace);
assert.strictEqual(
vscode.workspace.getConfiguration('coloredReferences').get('panelLocation'), placement);
}
suite('Results panel', () => {
let results: ReferenceResults;
@@ -64,6 +78,8 @@ suite('Results panel', () => {
const ext = vscode.extensions.getExtension('local.colored-references');
assert.ok(ext);
await ext.activate();
// These tests cover the editor-area placement; the docked view has its own suite.
await setPlacement('beside');
results = (await search(TARGET_FILE, TARGET_DECL, TARGET_SYMBOL)).results;
});
@@ -138,12 +154,57 @@ suite('Results panel', () => {
await vscode.commands.executeCommand('coloredReferences.toggleView');
await sleep(1500);
const editorTabs = vscode.window.tabGroups.all.flatMap(g => g.tabs).filter(tab => {
const input = tab.input as { uri?: vscode.Uri } | undefined;
return input?.uri?.scheme === 'colored-refs';
});
const editorTabs = coloredEditorTabs();
assert.strictEqual(editorTabs.length, 1, 'expected the results to open in an editor tab');
assert.ok(editorTabs[0].label.startsWith(`References to ${SECOND_SYMBOL}`),
`unexpected tab label: ${editorTabs[0].label}`);
});
});
suite('Results panel docked in the bottom panel', () => {
suiteSetup(async () => {
const ext = vscode.extensions.getExtension('local.colored-references');
assert.ok(ext);
await ext.activate();
await setPlacement('bottom');
// Close the editor-area panels the previous suite left behind.
for (const tab of panelTabs()) {
await vscode.window.tabGroups.close(tab, true);
}
for (const tab of coloredEditorTabs()) {
await vscode.window.tabGroups.close(tab, true);
}
await sleep(500);
});
test('the docked view is contributed and focusable', async () => {
const commands = await vscode.commands.getCommands(true);
assert.ok(commands.includes(`${PANEL_VIEW_TYPE}View.focus`) ||
commands.includes('coloredReferences.resultsView.focus'),
'the webview view did not contribute a focus command');
});
test('a search fills the docked view instead of opening an editor tab', async () => {
await search(TARGET_FILE, TARGET_DECL, TARGET_SYMBOL);
await vscode.commands.executeCommand('coloredReferences.findInPanel');
await sleep(2000);
assert.strictEqual(panelTabs().length, 0,
'panelLocation is "bottom" but a webview opened in the editor area');
assert.strictEqual(coloredEditorTabs().length, 0,
'no results document should have been opened');
});
test('toggleView reaches the results held by the docked view', async () => {
// Only possible if the docked view actually received the results.
await vscode.commands.executeCommand('coloredReferences.toggleView');
await sleep(1500);
const editorTabs = coloredEditorTabs();
assert.strictEqual(editorTabs.length, 1,
'toggleView could not find the results shown in the docked view');
assert.ok(editorTabs[0].label.startsWith(`References to ${TARGET_SYMBOL}`),
`unexpected tab label: ${editorTabs[0].label}`);
});
});