Skip to content

Commit 02af432

Browse files
authored
Merge pull request #2885 from github/aeisenberg/multi-token
Adds `MultiCancellationToken`
2 parents 17947fb + 76ec9e2 commit 02af432

File tree

4 files changed

+55
-13
lines changed

4 files changed

+55
-13
lines changed

extensions/ql-vscode/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
## [UNRELEASED]
44

5+
- Fix a bug where the query to Find Definitions in database source files would not be cancelled appropriately. [#2885](https://github.com/github/vscode-codeql/pull/2885)
56
- It is now possible to show the language of query history items using the `%l` specifier in the `codeQL.queryHistory.format` setting. Note that this only works for queries run after this upgrade, and older items will show `unknown` as a language. [#2892](https://github.com/github/vscode-codeql/pull/2892)
67
- Increase the required version of VS Code to 1.82.0. [#2877](https://github.com/github/vscode-codeql/pull/2877)
78
- Fix a bug where the query server was restarted twice after configuration changes. [#2884](https://github.com/github/vscode-codeql/pull/2884).

extensions/ql-vscode/src/common/disposable-object.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,16 @@ export type DisposeHandler = (disposable: Disposable) => void;
99
/**
1010
* Base class to make it easier to implement a `Disposable` that owns other disposable object.
1111
*/
12-
export abstract class DisposableObject implements Disposable {
12+
export class DisposableObject implements Disposable {
1313
private disposables: Disposable[] = [];
1414
private tracked?: Set<Disposable> = undefined;
1515

16+
constructor(...dispoables: Disposable[]) {
17+
for (const d of dispoables) {
18+
this.push(d);
19+
}
20+
}
21+
1622
/**
1723
* Adds `obj` to a list of objects to dispose when `this` is disposed. Objects added by `push` are
1824
* disposed in reverse order of being added.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { CancellationToken, Disposable } from "vscode";
2+
import { DisposableObject } from "../disposable-object";
3+
4+
/**
5+
* A cancellation token that cancels when any of its constituent
6+
* cancellation tokens are cancelled.
7+
*/
8+
export class MultiCancellationToken implements CancellationToken {
9+
private readonly tokens: CancellationToken[];
10+
11+
constructor(...tokens: CancellationToken[]) {
12+
this.tokens = tokens;
13+
}
14+
15+
get isCancellationRequested(): boolean {
16+
return this.tokens.some((t) => t.isCancellationRequested);
17+
}
18+
19+
onCancellationRequested<T>(listener: (e: T) => any): Disposable {
20+
return new DisposableObject(
21+
...this.tokens.map((t) => t.onCancellationRequested(listener)),
22+
);
23+
}
24+
}

extensions/ql-vscode/src/language-support/contextual/template-provider.ts

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@ import {
3636
import { CoreCompletedQuery, QueryRunner } from "../../query-server";
3737
import { AstBuilder } from "../ast-viewer/ast-builder";
3838
import { qlpackOfDatabase } from "../../local-queries";
39+
import { MultiCancellationToken } from "../../common/vscode/multi-cancellation-token";
3940

4041
/**
4142
* Runs templated CodeQL queries to find definitions in
4243
* source-language files. We may eventually want to find a way to
4344
* generalize this to other custom queries, e.g. showing dataflow to
4445
* or from a selected identifier.
4546
*/
47+
4648
export class TemplateQueryDefinitionProvider implements DefinitionProvider {
4749
private cache: CachedOperation<LocationLink[]>;
4850

@@ -60,11 +62,11 @@ export class TemplateQueryDefinitionProvider implements DefinitionProvider {
6062
async provideDefinition(
6163
document: TextDocument,
6264
position: Position,
63-
_token: CancellationToken,
65+
token: CancellationToken,
6466
): Promise<LocationLink[]> {
6567
const fileLinks = this.shouldUseCache()
66-
? await this.cache.get(document.uri.toString())
67-
: await this.getDefinitions(document.uri.toString());
68+
? await this.cache.get(document.uri.toString(), token)
69+
: await this.getDefinitions(document.uri.toString(), token);
6870

6971
const locLinks: LocationLink[] = [];
7072
for (const link of fileLinks) {
@@ -79,9 +81,13 @@ export class TemplateQueryDefinitionProvider implements DefinitionProvider {
7981
return !(isCanary() && NO_CACHE_CONTEXTUAL_QUERIES.getValue<boolean>());
8082
}
8183

82-
private async getDefinitions(uriString: string): Promise<LocationLink[]> {
84+
private async getDefinitions(
85+
uriString: string,
86+
token: CancellationToken,
87+
): Promise<LocationLink[]> {
8388
return withProgress(
84-
async (progress, token) => {
89+
async (progress, tokenInner) => {
90+
const multiToken = new MultiCancellationToken(token, tokenInner);
8591
return getLocationsForUriString(
8692
this.cli,
8793
this.qs,
@@ -90,7 +96,7 @@ export class TemplateQueryDefinitionProvider implements DefinitionProvider {
9096
KeyType.DefinitionQuery,
9197
this.queryStorageDir,
9298
progress,
93-
token,
99+
multiToken,
94100
(src, _dest) => src === uriString,
95101
);
96102
},
@@ -126,11 +132,11 @@ export class TemplateQueryReferenceProvider implements ReferenceProvider {
126132
document: TextDocument,
127133
position: Position,
128134
_context: ReferenceContext,
129-
_token: CancellationToken,
135+
token: CancellationToken,
130136
): Promise<Location[]> {
131137
const fileLinks = this.shouldUseCache()
132-
? await this.cache.get(document.uri.toString())
133-
: await this.getReferences(document.uri.toString());
138+
? await this.cache.get(document.uri.toString(), token)
139+
: await this.getReferences(document.uri.toString(), token);
134140

135141
const locLinks: Location[] = [];
136142
for (const link of fileLinks) {
@@ -148,9 +154,14 @@ export class TemplateQueryReferenceProvider implements ReferenceProvider {
148154
return !(isCanary() && NO_CACHE_CONTEXTUAL_QUERIES.getValue<boolean>());
149155
}
150156

151-
private async getReferences(uriString: string): Promise<FullLocationLink[]> {
157+
private async getReferences(
158+
uriString: string,
159+
token: CancellationToken,
160+
): Promise<FullLocationLink[]> {
152161
return withProgress(
153-
async (progress, token) => {
162+
async (progress, tokenInner) => {
163+
const multiToken = new MultiCancellationToken(token, tokenInner);
164+
154165
return getLocationsForUriString(
155166
this.cli,
156167
this.qs,
@@ -159,7 +170,7 @@ export class TemplateQueryReferenceProvider implements ReferenceProvider {
159170
KeyType.DefinitionQuery,
160171
this.queryStorageDir,
161172
progress,
162-
token,
173+
multiToken,
163174
(src, _dest) => src === uriString,
164175
);
165176
},

0 commit comments

Comments
 (0)