Skip to content

Commit 1e0a755

Browse files
Merge branch 'main' into robertbrignull/data-view-jump
2 parents 23ddc83 + 2171147 commit 1e0a755

15 files changed

+400
-185
lines changed

extensions/ql-vscode/package-lock.json

Lines changed: 241 additions & 98 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extensions/ql-vscode/package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1759,7 +1759,7 @@
17591759
"prepare": "cd ../.. && husky install"
17601760
},
17611761
"dependencies": {
1762-
"@octokit/plugin-retry": "^6.0.0",
1762+
"@octokit/plugin-retry": "^4.1.6",
17631763
"@octokit/rest": "^19.0.4",
17641764
"@vscode/codicons": "^0.0.31",
17651765
"@vscode/debugadapter": "^1.59.0",
@@ -1851,13 +1851,13 @@
18511851
"@vscode/vsce": "^2.19.0",
18521852
"ansi-colors": "^4.1.1",
18531853
"applicationinsights": "^2.3.5",
1854-
"cosmiconfig": "^7.1.0",
1854+
"cosmiconfig": "^8.2.0",
18551855
"cross-env": "^7.0.3",
18561856
"css-loader": "^6.8.1",
18571857
"del": "^6.0.0",
18581858
"esbuild": "^0.15.15",
18591859
"eslint": "^8.23.1",
1860-
"eslint-config-prettier": "^8.5.0",
1860+
"eslint-config-prettier": "^9.0.0",
18611861
"eslint-plugin-etc": "^2.0.2",
18621862
"eslint-plugin-github": "^4.4.1",
18631863
"eslint-plugin-jest-dom": "^5.0.1",
@@ -1881,7 +1881,7 @@
18811881
"markdownlint-cli2-formatter-pretty": "^0.0.4",
18821882
"mini-css-extract-plugin": "^2.6.1",
18831883
"npm-run-all": "^4.1.5",
1884-
"patch-package": "^7.0.0",
1884+
"patch-package": "^8.0.0",
18851885
"prettier": "^3.0.0",
18861886
"storybook": "^7.1.0",
18871887
"tar-stream": "^3.0.0",
@@ -1890,7 +1890,7 @@
18901890
"ts-json-schema-generator": "^1.1.2",
18911891
"ts-loader": "^9.4.2",
18921892
"ts-node": "^10.7.0",
1893-
"ts-unused-exports": "^9.0.5",
1893+
"ts-unused-exports": "^10.0.0",
18941894
"typescript": "^5.0.2",
18951895
"webpack": "^5.76.0",
18961896
"webpack-cli": "^5.0.1"

extensions/ql-vscode/src/common/interface-types.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ interface AddModeledMethodsMessage {
515515

516516
interface SetInProgressMethodsMessage {
517517
t: "setInProgressMethods";
518+
packageName: string;
518519
inProgressMethods: string[];
519520
}
520521

extensions/ql-vscode/src/data-extensions-editor/auto-model-codeml-queries.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -177,9 +177,6 @@ export async function runAutoModelQueries({
177177
progress,
178178
cancellationTokenSource,
179179
}: AutoModelQueriesOptions): Promise<AutoModelQueriesResult | undefined> {
180-
// maxStep for this part is 1500
181-
const maxStep = 1500;
182-
183180
const qlpack = await qlpackOfDatabase(cliServer, databaseItem);
184181

185182
// CodeQL needs to have access to the database to be able to retrieve the
@@ -208,12 +205,6 @@ export async function runAutoModelQueries({
208205
await cliServer.resolveQlpacks(additionalPacks, true),
209206
);
210207

211-
progress({
212-
step: 0,
213-
maxStep,
214-
message: "Finding candidates and examples",
215-
});
216-
217208
const candidates = await runAutoModelQuery({
218209
mode,
219210
queryTag: "candidates",
@@ -225,13 +216,7 @@ export async function runAutoModelQueries({
225216
additionalPacks,
226217
extensionPacks,
227218
queryStorageDir,
228-
progress: (update) => {
229-
progress({
230-
step: update.step,
231-
maxStep,
232-
message: "Finding candidates and examples",
233-
});
234-
},
219+
progress,
235220
token: cancellationTokenSource.token,
236221
});
237222

extensions/ql-vscode/src/data-extensions-editor/auto-modeler.ts

Lines changed: 31 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,13 @@ import { CancellationTokenSource } from "vscode";
2222
// Note that the model may return fewer than this number of candidates.
2323
const candidateBatchSize = 20;
2424

25+
/**
26+
* The auto-modeler holds state around auto-modeling jobs and allows
27+
* starting and stopping them.
28+
*/
2529
export class AutoModeler {
30+
// Keep track of auto-modeling jobs that are in progress
31+
// so that we can stop them.
2632
private readonly jobs: Map<string, CancellationTokenSource>;
2733

2834
constructor(
@@ -32,6 +38,7 @@ export class AutoModeler {
3238
private readonly queryStorageDir: string,
3339
private readonly databaseItem: DatabaseItem,
3440
private readonly setInProgressMethods: (
41+
packageName: string,
3542
inProgressMethods: string[],
3643
) => Promise<void>,
3744
private readonly addModeledMethods: (
@@ -41,6 +48,14 @@ export class AutoModeler {
4148
this.jobs = new Map<string, CancellationTokenSource>();
4249
}
4350

51+
/**
52+
* Models the given package's external API usages, except
53+
* the ones that are already modeled.
54+
* @param packageName The name of the package to model.
55+
* @param externalApiUsages The external API usages.
56+
* @param modeledMethods The currently modeled methods.
57+
* @param mode The mode we are modeling in.
58+
*/
4459
public async startModeling(
4560
packageName: string,
4661
externalApiUsages: ExternalApiUsage[],
@@ -67,6 +82,10 @@ export class AutoModeler {
6782
}
6883
}
6984

85+
/**
86+
* Stops modeling the given package.
87+
* @param packageName The name of the package to stop modeling.
88+
*/
7089
public async stopModeling(packageName: string): Promise<void> {
7190
void extLogger.log(`Stopping modeling for package ${packageName}`);
7291
const cancellationTokenSource = this.jobs.get(packageName);
@@ -75,6 +94,9 @@ export class AutoModeler {
7594
}
7695
}
7796

97+
/**
98+
* Stops all in-progress modeling jobs.
99+
*/
78100
public async stopAllModeling(): Promise<void> {
79101
for (const cancellationTokenSource of this.jobs.values()) {
80102
cancellationTokenSource.cancel();
@@ -90,8 +112,6 @@ export class AutoModeler {
90112
): Promise<void> {
91113
void extLogger.log(`Modeling package ${packageName}`);
92114
await withProgress(async (progress) => {
93-
const maxStep = 3000;
94-
95115
// Fetch the candidates to send to the model
96116
const allCandidateMethods = getCandidates(
97117
mode,
@@ -111,6 +131,7 @@ export class AutoModeler {
111131
);
112132
try {
113133
for (let i = 0; i < batchNumber; i++) {
134+
// Check if we should stop
114135
if (cancellationTokenSource.token.isCancellationRequested) {
115136
break;
116137
}
@@ -119,29 +140,23 @@ export class AutoModeler {
119140
const end = start + candidateBatchSize;
120141
const candidatesToProcess = allCandidateMethods.slice(start, end);
121142

143+
// Let the UI know which candidates we are modeling
122144
await this.setInProgressMethods(
145+
packageName,
123146
candidatesToProcess.map((c) => c.signature),
124147
);
125148

126-
progress({
127-
step: 1800 + i * 100,
128-
maxStep,
129-
message: `Automodeling candidates, batch ${
130-
i + 1
131-
} of ${batchNumber}`,
132-
});
133-
149+
// Kick off the process to model the slice of candidates
134150
await this.modelCandidates(
135151
candidatesToProcess,
136152
mode,
137153
progress,
138-
maxStep,
139154
cancellationTokenSource,
140155
);
141156
}
142157
} finally {
143158
// Clear out in progress methods
144-
await this.setInProgressMethods([]);
159+
await this.setInProgressMethods(packageName, []);
145160
}
146161
});
147162
}
@@ -150,48 +165,33 @@ export class AutoModeler {
150165
candidateMethods: MethodSignature[],
151166
mode: Mode,
152167
progress: ProgressCallback,
153-
maxStep: number,
154168
cancellationTokenSource: CancellationTokenSource,
155169
): Promise<void> {
170+
void extLogger.log("Executing auto-model queries");
171+
156172
const usages = await runAutoModelQueries({
157173
mode,
158174
candidateMethods,
159175
cliServer: this.cliServer,
160176
queryRunner: this.queryRunner,
161177
queryStorageDir: this.queryStorageDir,
162178
databaseItem: this.databaseItem,
163-
progress: (update) => progress({ ...update, maxStep }),
179+
progress: (update) => progress({ ...update }),
164180
cancellationTokenSource,
165181
});
166182
if (!usages) {
167183
return;
168184
}
169185

170-
progress({
171-
step: 1800,
172-
maxStep,
173-
message: "Creating request",
174-
});
175-
176186
const request = await createAutoModelV2Request(mode, usages);
177187

178-
progress({
179-
step: 2000,
180-
maxStep,
181-
message: "Sending request",
182-
});
188+
void extLogger.log("Calling auto-model API");
183189

184190
const response = await this.callAutoModelApi(request);
185191
if (!response) {
186192
return;
187193
}
188194

189-
progress({
190-
step: 2500,
191-
maxStep,
192-
message: "Parsing response",
193-
});
194-
195195
const models = loadYaml(response.models, {
196196
filename: "auto-model.yml",
197197
});
@@ -222,12 +222,6 @@ export class AutoModeler {
222222
}
223223
}
224224

225-
progress({
226-
step: 2800,
227-
maxStep,
228-
message: "Applying results",
229-
});
230-
231225
await this.addModeledMethods(loadedMethods);
232226
}
233227

extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ export class DataExtensionsEditorModule extends DisposableObject {
4545
baseQueryStorageDir,
4646
"data-extensions-editor-results",
4747
);
48-
this.modelDetailsPanel = this.push(new ModelDetailsPanel());
48+
this.modelDetailsPanel = this.push(new ModelDetailsPanel(cliServer));
4949
}
5050

5151
public static async initialize(

extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-view.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
7272
private readonly updateModelDetailsPanelState: (
7373
externalApiUsages: ExternalApiUsage[],
7474
databaseItem: DatabaseItem,
75-
) => void,
75+
) => Promise<void>,
7676
private readonly revealItemInDetailsPanel: (usage: Usage) => Promise<void>,
7777
) {
7878
super(ctx);
@@ -83,9 +83,10 @@ export class DataExtensionsEditorView extends AbstractWebview<
8383
queryRunner,
8484
queryStorageDir,
8585
databaseItem,
86-
async (inProgressMethods) => {
86+
async (packageName, inProgressMethods) => {
8787
await this.postMessage({
8888
t: "setInProgressMethods",
89+
packageName,
8990
inProgressMethods,
9091
});
9192
},
@@ -300,7 +301,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
300301
t: "setExternalApiUsages",
301302
externalApiUsages,
302303
});
303-
this.updateModelDetailsPanelState(
304+
await this.updateModelDetailsPanelState(
304305
externalApiUsages,
305306
this.databaseItem,
306307
);

extensions/ql-vscode/src/data-extensions-editor/model-details/model-details-data-provider.ts

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,84 @@
11
import {
22
Event,
33
EventEmitter,
4+
ThemeColor,
5+
ThemeIcon,
46
TreeDataProvider,
57
TreeItem,
68
TreeItemCollapsibleState,
9+
Uri,
710
} from "vscode";
811
import { DisposableObject } from "../../common/disposable-object";
912
import { ExternalApiUsage, Usage } from "../external-api-usage";
1013
import { DatabaseItem } from "../../databases/local-databases";
14+
import { relative } from "path";
15+
import { CodeQLCliServer } from "../../codeql-cli/cli";
1116

1217
export class ModelDetailsDataProvider
1318
extends DisposableObject
1419
implements TreeDataProvider<ModelDetailsTreeViewItem>
1520
{
1621
private externalApiUsages: ExternalApiUsage[] = [];
1722
private databaseItem: DatabaseItem | undefined = undefined;
23+
private sourceLocationPrefix: string | undefined = undefined;
1824

1925
private readonly onDidChangeTreeDataEmitter = this.push(
2026
new EventEmitter<void>(),
2127
);
2228

29+
public constructor(private readonly cliServer: CodeQLCliServer) {
30+
super();
31+
}
32+
2333
public get onDidChangeTreeData(): Event<void> {
2434
return this.onDidChangeTreeDataEmitter.event;
2535
}
2636

27-
public setState(
37+
public async setState(
2838
externalApiUsages: ExternalApiUsage[],
2939
databaseItem: DatabaseItem,
30-
): void {
40+
): Promise<void> {
3141
this.externalApiUsages = externalApiUsages;
3242
this.databaseItem = databaseItem;
43+
this.sourceLocationPrefix = await this.databaseItem.getSourceLocationPrefix(
44+
this.cliServer,
45+
);
3346
this.onDidChangeTreeDataEmitter.fire();
3447
}
3548

3649
getTreeItem(item: ModelDetailsTreeViewItem): TreeItem {
3750
if (isExternalApiUsage(item)) {
3851
return {
39-
label: item.signature,
52+
label: `${item.packageName}.${item.typeName}.${item.methodName}${item.methodParameters}`,
4053
collapsibleState: TreeItemCollapsibleState.Collapsed,
54+
iconPath: new ThemeIcon("symbol-method"),
4155
};
4256
} else {
4357
return {
4458
label: item.label,
59+
description: `${this.relativePathWithinDatabase(item.url.uri)} [${
60+
item.url.startLine
61+
}, ${item.url.endLine}]`,
4562
collapsibleState: TreeItemCollapsibleState.None,
4663
command: {
4764
title: "Show usage",
4865
command: "codeQLDataExtensionsEditor.jumpToUsageLocation",
4966
arguments: [item, this.databaseItem],
5067
},
68+
iconPath: new ThemeIcon("error", new ThemeColor("errorForeground")),
5169
};
5270
}
5371
}
5472

73+
private relativePathWithinDatabase(uri: string): string {
74+
const parsedUri = Uri.parse(uri);
75+
if (this.sourceLocationPrefix) {
76+
return relative(this.sourceLocationPrefix, parsedUri.fsPath);
77+
} else {
78+
return parsedUri.fsPath;
79+
}
80+
}
81+
5582
getChildren(item?: ModelDetailsTreeViewItem): ModelDetailsTreeViewItem[] {
5683
if (item === undefined) {
5784
return this.externalApiUsages;

0 commit comments

Comments
 (0)