Skip to content

Commit 66c6393

Browse files
authored
Fix peeked editor closing without reopening when triggered again at the same position in the same file (#1019)
1 parent d801d41 commit 66c6393

File tree

1 file changed

+76
-15
lines changed

1 file changed

+76
-15
lines changed

src/sourcekit-lsp/peekDocuments.ts

Lines changed: 76 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,88 @@ import * as vscode from "vscode";
1616
import * as langclient from "vscode-languageclient/node";
1717
import { PeekDocumentsParams, PeekDocumentsRequest } from "./lspExtensions";
1818

19+
/**
20+
* Opens a peeked editor in `uri` at `position` having contents from `locations`.
21+
*
22+
* **NOTE**:
23+
* - If the `uri` is not open in the editor, this opens the `uri` in the editor and then opens a peeked editor.
24+
* - This closes any previously displayed peeked editor in `uri` and then, reopens a peeked editor in `uri` at
25+
* the given `position` with contents from the new `locations`.
26+
*
27+
* @param uri The uri of the file in which a peeked editor is to be opened
28+
* @param position The position in the file in which a peeked editor is to be opened
29+
* @param locations The locations of the contents which has to be displayed by the peeked editor
30+
*/
31+
async function openPeekedEditorIn(
32+
uri: vscode.Uri,
33+
position: vscode.Position,
34+
locations: vscode.Location[]
35+
) {
36+
// #### NOTE - Undocumented behaviour of invoking VS Code's built-in "editor.action.peekLocations" command:
37+
// 1. If the `uri` is not open in the editor, it opens the `uri` in the editor and then opens a peeked editor.
38+
// 2. It always closes the previous peeked editor (If any)
39+
// 3. And after closing, It opens a new peeked editor having the contents of `locations` in `uri` **if and only
40+
// if** the previous peeked editor was displayed at a *different* `position` in `uri`.
41+
// 4. If it happens to be that the previous peeked editor was displayed at the *same* `position` in `uri`, then it
42+
// doesn't open the peeked editor window having the contents of new `locations` at all.
43+
44+
// As (4.) says above, if we invoke "editor.action.peekLocations" on a position in which another peeked editor
45+
// window is already being shown, it won't cause the new peeked editor window to show up at all. This is not the
46+
// ideal behaviour.
47+
//
48+
// For example:
49+
// If there's already a peeked editor window at the position (2, 2) in "main.swift", its impossible to close this
50+
// peeked editor window and open a new peeked editor window at the same position (2, 2) in "main.swift" by invoking
51+
// the "editor.action.peekLocations" command in a single call.
52+
//
53+
// *The ideal behaviour* is to close any previously opened peeked editor window and then open the new one without
54+
// any regard to its `position` in the `uri`.
55+
56+
// In order to achieve *the ideal behaviour*, we manually close the peeked editor window by ourselves before
57+
// opening a new peeked editor window.
58+
//
59+
// Since there isn't any API available to close the previous peeked editor, as a **workaround**, we open a dummy
60+
// peeked editor at a different position, causing the previous one to close irrespective of where it is. After
61+
// which we can invoke the command again to show the actual peeked window having the contents of the `locations`.
62+
await vscode.commands.executeCommand(
63+
"editor.action.peekLocations",
64+
uri,
65+
new vscode.Position(position.line, position.character !== 0 ? position.character - 1 : 1),
66+
[new vscode.Location(vscode.Uri.parse(""), new vscode.Position(0, 0))],
67+
"peek"
68+
);
69+
70+
// Opens the actual peeked editor window
71+
await vscode.commands.executeCommand(
72+
"editor.action.peekLocations",
73+
uri,
74+
position,
75+
locations,
76+
"peek"
77+
);
78+
}
79+
1980
export function activatePeekDocuments(client: langclient.LanguageClient): vscode.Disposable {
2081
const peekDocuments = client.onRequest(
2182
PeekDocumentsRequest.method,
2283
async (params: PeekDocumentsParams) => {
23-
const locations = params.locations.map(uri => {
24-
const location = new vscode.Location(
25-
client.protocol2CodeConverter.asUri(uri),
26-
new vscode.Position(0, 0)
27-
);
28-
29-
return location;
30-
});
31-
32-
await vscode.commands.executeCommand(
33-
"editor.action.peekLocations",
34-
client.protocol2CodeConverter.asUri(params.uri),
35-
new vscode.Position(params.position.line, params.position.character),
36-
locations,
37-
"peek"
84+
const peekURI = client.protocol2CodeConverter.asUri(params.uri);
85+
86+
const peekPosition = new vscode.Position(
87+
params.position.line,
88+
params.position.character
3889
);
3990

91+
const peekLocations = params.locations.map(
92+
location =>
93+
new vscode.Location(
94+
client.protocol2CodeConverter.asUri(location),
95+
new vscode.Position(0, 0)
96+
)
97+
);
98+
99+
openPeekedEditorIn(peekURI, peekPosition, peekLocations);
100+
40101
return { success: true };
41102
}
42103
);

0 commit comments

Comments
 (0)