Skip to content

Commit 778f839

Browse files
Merge pull request #2623 from github/robertbrignull/data-model-dependency
Implement "model dependency" button in application mode
2 parents d8687b5 + 19ad237 commit 778f839

6 files changed

Lines changed: 103 additions & 25 deletions

File tree

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

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,10 @@ export interface GenerateExternalApiFromLlmMessage {
553553
modeledMethods: Record<string, ModeledMethod>;
554554
}
555555

556+
export interface ModelDependencyMessage {
557+
t: "modelDependency";
558+
}
559+
556560
export type ToDataExtensionsEditorMessage =
557561
| SetExtensionPackStateMessage
558562
| SetExternalApiUsagesMessage
@@ -568,4 +572,5 @@ export type FromDataExtensionsEditorMessage =
568572
| JumpToUsageMessage
569573
| SaveModeledMethods
570574
| GenerateExternalApiMessage
571-
| GenerateExternalApiFromLlmMessage;
575+
| GenerateExternalApiFromLlmMessage
576+
| ModelDependencyMessage;

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

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,11 @@ import {
1414
FromDataExtensionsEditorMessage,
1515
ToDataExtensionsEditorMessage,
1616
} from "../common/interface-types";
17-
import { ProgressUpdate } from "../common/vscode/progress";
17+
import {
18+
ProgressCallback,
19+
ProgressUpdate,
20+
withProgress,
21+
} from "../common/vscode/progress";
1822
import { QueryRunner } from "../query-server";
1923
import {
2024
showAndLogExceptionWithTelemetry,
@@ -44,6 +48,7 @@ import { getAutoModelUsages } from "./auto-model-usages-query";
4448
import { Mode } from "./shared/mode";
4549
import { loadModeledMethods, saveModeledMethods } from "./modeled-method-fs";
4650
import { join } from "path";
51+
import { pickExtensionPack } from "./extension-pack-picker";
4752

4853
export class DataExtensionsEditorView extends AbstractWebview<
4954
ToDataExtensionsEditorMessage,
@@ -139,6 +144,10 @@ export class DataExtensionsEditorView extends AbstractWebview<
139144
msg.modeledMethods,
140145
);
141146

147+
break;
148+
case "modelDependency":
149+
await this.modelDependency();
150+
142151
break;
143152
case "switchMode":
144153
this.mode = msg.mode;
@@ -284,29 +293,12 @@ export class DataExtensionsEditorView extends AbstractWebview<
284293
// In application mode, we need the database of a specific library to generate
285294
// the modeled methods. In framework mode, we'll use the current database.
286295
if (this.mode === Mode.Application) {
287-
const selectedDatabase = this.databaseManager.currentDatabaseItem;
288-
289-
// The external API methods are in the library source code, so we need to ask
290-
// the user to import the library database. We need to have the database
291-
// imported to the query server, so we need to register it to our workspace.
292-
addedDatabase = await promptImportGithubDatabase(
293-
this.app.commands,
294-
this.databaseManager,
295-
this.app.workspaceStoragePath ?? this.app.globalStoragePath,
296-
this.app.credentials,
297-
(update) => this.showProgress(update),
298-
this.cliServer,
296+
addedDatabase = await this.promptImportAndResetDatabase((update) =>
297+
this.showProgress(update),
299298
);
300299
if (!addedDatabase) {
301-
await this.clearProgress();
302-
void this.app.logger.log("No database chosen");
303-
304300
return;
305301
}
306-
307-
// The library database was set as the current database by importing it,
308-
// but we need to set it back to the originally selected database.
309-
await this.databaseManager.setCurrentDatabaseItem(selectedDatabase);
310302
}
311303

312304
await this.showProgress({
@@ -429,6 +421,68 @@ export class DataExtensionsEditorView extends AbstractWebview<
429421
await this.clearProgress();
430422
}
431423

424+
private async modelDependency(): Promise<void> {
425+
return withProgress(async (progress, token) => {
426+
const addedDatabase = await this.promptImportAndResetDatabase(progress);
427+
if (!addedDatabase || token.isCancellationRequested) {
428+
return;
429+
}
430+
431+
const modelFile = await pickExtensionPack(
432+
this.cliServer,
433+
addedDatabase,
434+
this.app.logger,
435+
progress,
436+
token,
437+
);
438+
if (!modelFile) {
439+
return;
440+
}
441+
442+
const view = new DataExtensionsEditorView(
443+
this.ctx,
444+
this.app,
445+
this.databaseManager,
446+
this.cliServer,
447+
this.queryRunner,
448+
this.queryStorageDir,
449+
addedDatabase,
450+
modelFile,
451+
Mode.Framework,
452+
);
453+
await view.openView();
454+
});
455+
}
456+
457+
private async promptImportAndResetDatabase(
458+
progress: ProgressCallback,
459+
): Promise<DatabaseItem | undefined> {
460+
const selectedDatabase = this.databaseManager.currentDatabaseItem;
461+
462+
// The external API methods are in the library source code, so we need to ask
463+
// the user to import the library database. We need to have the database
464+
// imported to the query server, so we need to register it to our workspace.
465+
const addedDatabase = await promptImportGithubDatabase(
466+
this.app.commands,
467+
this.databaseManager,
468+
this.app.workspaceStoragePath ?? this.app.globalStoragePath,
469+
this.app.credentials,
470+
progress,
471+
this.cliServer,
472+
this.databaseItem.language,
473+
);
474+
if (!addedDatabase) {
475+
void this.app.logger.log("No database chosen");
476+
return undefined;
477+
}
478+
479+
// The library database was set as the current database by importing it,
480+
// but we need to set it back to the originally selected database.
481+
await this.databaseManager.setCurrentDatabaseItem(selectedDatabase);
482+
483+
return addedDatabase;
484+
}
485+
432486
/*
433487
* Progress in this class is a bit weird. Most of the progress is based on running the query.
434488
* Query progress is always between 0 and 1000. However, we still have some steps that need

extensions/ql-vscode/src/databases/database-fetcher.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ export async function promptImportInternetDatabase(
8585
* @param credentials the credentials to use to authenticate with GitHub
8686
* @param progress the progress callback
8787
* @param cli the CodeQL CLI server
88+
* @param language the language to download. If undefined, the user will be prompted to choose a language.
8889
*/
8990
export async function promptImportGithubDatabase(
9091
commandManager: AppCommandManager,
@@ -93,6 +94,7 @@ export async function promptImportGithubDatabase(
9394
credentials: Credentials | undefined,
9495
progress: ProgressCallback,
9596
cli?: CodeQLCliServer,
97+
language?: string,
9698
): Promise<DatabaseItem | undefined> {
9799
const githubRepo = await askForGitHubRepo(progress);
98100
if (!githubRepo) {
@@ -106,6 +108,7 @@ export async function promptImportGithubDatabase(
106108
credentials,
107109
progress,
108110
cli,
111+
language,
109112
);
110113

111114
if (databaseItem) {

extensions/ql-vscode/src/view/data-extensions-editor/DataExtensionsEditor.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,12 @@ export function DataExtensionsEditor({
215215
});
216216
}, [externalApiUsages, modeledMethods]);
217217

218+
const onModelDependencyClick = useCallback(() => {
219+
vscode.postMessage({
220+
t: "modelDependency",
221+
});
222+
}, []);
223+
218224
const onGenerateFromLlmClick = useCallback(
219225
(
220226
externalApiUsages: ExternalApiUsage[],
@@ -323,6 +329,7 @@ export function DataExtensionsEditor({
323329
onSaveModelClick={onSaveModelClick}
324330
onGenerateFromLlmClick={onGenerateFromLlmClick}
325331
onGenerateFromSourceClick={onGenerateFromSourceClick}
332+
onModelDependencyClick={onModelDependencyClick}
326333
/>
327334
</EditorContainer>
328335
</>

extensions/ql-vscode/src/view/data-extensions-editor/LibraryRow.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ type Props = {
8787
modeledMethods: Record<string, ModeledMethod>,
8888
) => void;
8989
onGenerateFromSourceClick: () => void;
90+
onModelDependencyClick: () => void;
9091
};
9192

9293
export const LibraryRow = ({
@@ -100,6 +101,7 @@ export const LibraryRow = ({
100101
onSaveModelClick,
101102
onGenerateFromLlmClick,
102103
onGenerateFromSourceClick,
104+
onModelDependencyClick,
103105
}: Props) => {
104106
const modeledPercentage = useMemo(() => {
105107
return calculateModeledPercentage(externalApiUsages);
@@ -129,10 +131,14 @@ export const LibraryRow = ({
129131
[onGenerateFromSourceClick],
130132
);
131133

132-
const handleModelDependency = useCallback(async (e: React.MouseEvent) => {
133-
e.stopPropagation();
134-
e.preventDefault();
135-
}, []);
134+
const handleModelDependency = useCallback(
135+
async (e: React.MouseEvent) => {
136+
onModelDependencyClick();
137+
e.stopPropagation();
138+
e.preventDefault();
139+
},
140+
[onModelDependencyClick],
141+
);
136142

137143
const handleSave = useCallback(
138144
async (e: React.MouseEvent) => {

extensions/ql-vscode/src/view/data-extensions-editor/ModeledMethodsList.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Props = {
2929
modeledMethods: Record<string, ModeledMethod>,
3030
) => void;
3131
onGenerateFromSourceClick: () => void;
32+
onModelDependencyClick: () => void;
3233
};
3334

3435
const libraryNameOverrides: Record<string, string> = {
@@ -44,6 +45,7 @@ export const ModeledMethodsList = ({
4445
onSaveModelClick,
4546
onGenerateFromLlmClick,
4647
onGenerateFromSourceClick,
48+
onModelDependencyClick,
4749
}: Props) => {
4850
const grouped = useMemo(
4951
() => groupMethods(externalApiUsages, viewState.mode),
@@ -85,6 +87,7 @@ export const ModeledMethodsList = ({
8587
onSaveModelClick={onSaveModelClick}
8688
onGenerateFromLlmClick={onGenerateFromLlmClick}
8789
onGenerateFromSourceClick={onGenerateFromSourceClick}
90+
onModelDependencyClick={onModelDependencyClick}
8891
/>
8992
))}
9093
</>

0 commit comments

Comments
 (0)