Skip to content

Commit 7c3e32c

Browse files
committed
Fix peeked editor closing without reopening when triggered again at the same position in the same file
1 parent d801d41 commit 7c3e32c

File tree

1 file changed

+78
-15
lines changed

1 file changed

+78
-15
lines changed

src/sourcekit-lsp/peekDocuments.ts

Lines changed: 78 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,90 @@ 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+
position !== new vscode.Position(0, 0)
66+
? new vscode.Position(0, 0)
67+
: new vscode.Position(1, 1),
68+
[new vscode.Location(vscode.Uri.parse(""), new vscode.Position(0, 0))],
69+
"peek"
70+
);
71+
72+
// Opens the actual peeked editor window
73+
await vscode.commands.executeCommand(
74+
"editor.action.peekLocations",
75+
uri,
76+
position,
77+
locations,
78+
"peek"
79+
);
80+
}
81+
1982
export function activatePeekDocuments(client: langclient.LanguageClient): vscode.Disposable {
2083
const peekDocuments = client.onRequest(
2184
PeekDocumentsRequest.method,
2285
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"
86+
const peekURI = client.protocol2CodeConverter.asUri(params.uri);
87+
88+
const peekPosition = new vscode.Position(
89+
params.position.line,
90+
params.position.character
3891
);
3992

93+
const peekLocations = params.locations.map(
94+
location =>
95+
new vscode.Location(
96+
client.protocol2CodeConverter.asUri(location),
97+
new vscode.Position(0, 0)
98+
)
99+
);
100+
101+
openPeekedEditorIn(peekURI, peekPosition, peekLocations);
102+
40103
return { success: true };
41104
}
42105
);

0 commit comments

Comments
 (0)