Skip to content

Commit 67d342f

Browse files
author
Alexander Eyers-Taylor
authored
Give visibility information to the ide-server. (#2482)
* Add version constraint for Check errors * Refactor parts of the ideserver out of extension.ts * Give visibility information to the ide-server. This allows it to report errors on visible files eagerly.
1 parent 66d233d commit 67d342f

File tree

3 files changed

+90
-27
lines changed

3 files changed

+90
-27
lines changed

extensions/ql-vscode/src/codeql-cli/cli.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,13 @@ export class CliVersionConstraint {
18571857
*/
18581858
public static CLI_VERSION_WITH_QUICK_EVAL_COUNT = new SemVer("2.13.3");
18591859

1860+
/**
1861+
* CLI version where the langauge server supports visisbility change notifications.
1862+
*/
1863+
public static CLI_VERSION_WITH_VISIBILITY_NOTIFICATIONS = new SemVer(
1864+
"2.14.0",
1865+
);
1866+
18601867
constructor(private readonly cli: CodeQLCliServer) {
18611868
/**/
18621869
}
@@ -1931,6 +1938,12 @@ export class CliVersionConstraint {
19311938
return this.isVersionAtLeast(CliVersionConstraint.CLI_VERSION_GLOBAL_CACHE);
19321939
}
19331940

1941+
async supportsVisibilityNotifications() {
1942+
return this.isVersionAtLeast(
1943+
CliVersionConstraint.CLI_VERSION_WITH_VISIBILITY_NOTIFICATIONS,
1944+
);
1945+
}
1946+
19341947
async supportsQuickEvalCount() {
19351948
return this.isVersionAtLeast(
19361949
CliVersionConstraint.CLI_VERSION_WITH_QUICK_EVAL_COUNT,

extensions/ql-vscode/src/extension.ts

Lines changed: 16 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ import {
3636
import {
3737
AstViewer,
3838
install,
39-
spawnIdeServer,
4039
getQueryEditorCommands,
4140
TemplatePrintAstProvider,
4241
TemplatePrintCfgProvider,
4342
TemplateQueryDefinitionProvider,
4443
TemplateQueryReferenceProvider,
44+
createIDEServer,
4545
} from "./language-support";
4646
import { DatabaseManager } from "./databases/local-databases";
4747
import { DatabaseUI } from "./databases/local-databases-ui";
@@ -903,24 +903,7 @@ async function activateWithInstalledDistribution(
903903
ctx.subscriptions.push(tmpDirDisposal);
904904

905905
void extLogger.log("Initializing CodeQL language server.");
906-
const client = new LanguageClient(
907-
"codeQL.lsp",
908-
"CodeQL Language Server",
909-
() => spawnIdeServer(qlConfigurationListener),
910-
{
911-
documentSelector: [
912-
{ language: "ql", scheme: "file" },
913-
{ language: "yaml", scheme: "file", pattern: "**/qlpack.yml" },
914-
{ language: "yaml", scheme: "file", pattern: "**/codeql-pack.yml" },
915-
],
916-
synchronize: {
917-
configurationSection: "codeQL",
918-
},
919-
// Ensure that language server exceptions are logged to the same channel as its output.
920-
outputChannel: ideServerLogger.outputChannel,
921-
},
922-
true,
923-
);
906+
const ideServer = createIDEServer(qlConfigurationListener);
924907

925908
const localQueries = new LocalQueries(
926909
app,
@@ -1002,7 +985,7 @@ async function activateWithInstalledDistribution(
1002985
void extLogger.log("Registering top-level command palette commands.");
1003986

1004987
const allCommands: AllExtensionCommands = {
1005-
...getCommands(app, cliServer, qs, client),
988+
...getCommands(app, cliServer, qs, ideServer),
1006989
...getQueryEditorCommands({
1007990
commandManager: app.commands,
1008991
queryRunner: qs,
@@ -1048,12 +1031,23 @@ async function activateWithInstalledDistribution(
10481031
}
10491032

10501033
void extLogger.log("Starting language server.");
1051-
await client.start();
1034+
await ideServer.start();
10521035
ctx.subscriptions.push({
10531036
dispose: () => {
1054-
void client.stop();
1037+
void ideServer.stop();
10551038
},
10561039
});
1040+
1041+
// Handle visibility changes in the ideserver
1042+
if (await cliServer.cliConstraints.supportsVisibilityNotifications()) {
1043+
Window.onDidChangeVisibleTextEditors((editors) => {
1044+
ideServer.notifyVisibilityChange(editors);
1045+
});
1046+
// Send an inital notification to the language server
1047+
// to set the initial state of the visible editors.
1048+
ideServer.notifyVisibilityChange(Window.visibleTextEditors);
1049+
}
1050+
10571051
// Jump-to-definition and find-references
10581052
void extLogger.log("Registering jump-to-definition handlers.");
10591053

extensions/ql-vscode/src/language-support/ide-server.ts

Lines changed: 61 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1-
import { ProgressLocation, window } from "vscode";
2-
import { StreamInfo } from "vscode-languageclient/node";
1+
import { ProgressLocation, TextEditor, window } from "vscode";
2+
import {
3+
LanguageClient,
4+
NotificationType,
5+
StreamInfo,
6+
} from "vscode-languageclient/node";
37
import { shouldDebugIdeServer, spawnServer } from "../codeql-cli/cli";
48
import { QueryServerConfig } from "../config";
59
import { ideServerLogger } from "../common/logging/vscode";
@@ -8,10 +12,52 @@ import { ideServerLogger } from "../common/logging/vscode";
812
* Managing the language server for CodeQL.
913
*/
1014

11-
/** Starts a new CodeQL language server process, sending progress messages to the status bar. */
12-
export async function spawnIdeServer(
15+
/**
16+
* Create a new CodeQL language server.
17+
*/
18+
export function createIDEServer(
1319
config: QueryServerConfig,
14-
): Promise<StreamInfo> {
20+
): CodeQLLanguageClient {
21+
return new CodeQLLanguageClient(config);
22+
}
23+
24+
/**
25+
* CodeQL language server.
26+
*/
27+
export class CodeQLLanguageClient extends LanguageClient {
28+
constructor(config: QueryServerConfig) {
29+
super(
30+
"codeQL.lsp",
31+
"CodeQL Language Server",
32+
() => spawnIdeServer(config),
33+
{
34+
documentSelector: [
35+
{ language: "ql", scheme: "file" },
36+
{ language: "yaml", scheme: "file", pattern: "**/qlpack.yml" },
37+
{ language: "yaml", scheme: "file", pattern: "**/codeql-pack.yml" },
38+
],
39+
synchronize: {
40+
configurationSection: "codeQL",
41+
},
42+
// Ensure that language server exceptions are logged to the same channel as its output.
43+
outputChannel: ideServerLogger.outputChannel,
44+
},
45+
true,
46+
);
47+
}
48+
49+
notifyVisibilityChange(editors: readonly TextEditor[]) {
50+
const files = editors
51+
.filter((e) => e.document.uri.scheme === "file")
52+
.map((e) => e.document.uri.toString());
53+
void this.sendNotification(didChangeVisibileFiles, {
54+
visibleFiles: files,
55+
});
56+
}
57+
}
58+
59+
/** Starts a new CodeQL language server process, sending progress messages to the status bar. */
60+
async function spawnIdeServer(config: QueryServerConfig): Promise<StreamInfo> {
1561
return window.withProgress(
1662
{ title: "CodeQL language server", location: ProgressLocation.Window },
1763
async (progressReporter, _) => {
@@ -37,3 +83,13 @@ export async function spawnIdeServer(
3783
},
3884
);
3985
}
86+
87+
/**
88+
* Custom notification type for when the set of visible files changes.
89+
*/
90+
interface DidChangeVisibileFilesParams {
91+
visibleFiles: string[];
92+
}
93+
94+
const didChangeVisibileFiles: NotificationType<DidChangeVisibileFilesParams> =
95+
new NotificationType("textDocument/codeQLDidChangeVisibleFiles");

0 commit comments

Comments
 (0)