Skip to content

Commit 744a516

Browse files
committed
Show extension pack name in data extensions editor
This will add the extension pack name to the data extensions editor and allow the user to click on it to go to the folder of the extension pack in the explorer panel.
1 parent fe2f37f commit 744a516

File tree

6 files changed

+76
-19
lines changed

6 files changed

+76
-19
lines changed

extensions/ql-vscode/src/common/commands.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ export type BuiltInVsCodeCommands = {
8787
) => Promise<void>;
8888
"vscode.open": (uri: Uri) => Promise<void>;
8989
"vscode.openFolder": (uri: Uri) => Promise<void>;
90+
revealInExplorer: (uri: Uri) => Promise<void>;
9091
};
9192

9293
// Commands that are available before the extension is fully activated.

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

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
CancellationTokenSource,
33
ExtensionContext,
4+
Uri,
45
ViewColumn,
56
window,
67
workspace,
@@ -34,6 +35,7 @@ import { readQueryResults, runQuery } from "./external-api-usage-query";
3435
import { createDataExtensionYaml, loadDataExtensionYaml } from "./yaml";
3536
import { ExternalApiUsage } from "./external-api-usage";
3637
import { ModeledMethod } from "./modeled-method";
38+
import { ExtensionPackModelFile } from "./extension-pack-picker";
3739

3840
function getQlSubmoduleFolder(): WorkspaceFolder | undefined {
3941
const workspaceFolder = workspace.workspaceFolders?.find(
@@ -60,7 +62,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
6062
private readonly queryRunner: QueryRunner,
6163
private readonly queryStorageDir: string,
6264
private readonly databaseItem: DatabaseItem,
63-
private readonly modelFilename: string,
65+
private readonly modelFile: ExtensionPackModelFile,
6466
) {
6567
super(ctx);
6668
}
@@ -93,10 +95,17 @@ export class DataExtensionsEditorView extends AbstractWebview<
9395
case "viewLoaded":
9496
await this.onWebViewLoaded();
9597

98+
break;
99+
case "openExtensionPack":
100+
await this.app.commands.execute(
101+
"revealInExplorer",
102+
Uri.file(this.modelFile.extensionPack.path),
103+
);
104+
96105
break;
97106
case "openModelFile":
98107
await window.showTextDocument(
99-
await workspace.openTextDocument(this.modelFilename),
108+
await workspace.openTextDocument(this.modelFile.filename),
100109
);
101110

102111
break;
@@ -127,7 +136,8 @@ export class DataExtensionsEditorView extends AbstractWebview<
127136
await Promise.all([
128137
this.postMessage({
129138
t: "setDataExtensionEditorInitialData",
130-
modelFilename: this.modelFilename,
139+
extensionPackName: this.modelFile.extensionPack.name,
140+
modelFilename: this.modelFile.filename,
131141
}),
132142
this.loadExternalApiUsages(),
133143
this.loadExistingModeledMethods(),
@@ -164,24 +174,26 @@ export class DataExtensionsEditorView extends AbstractWebview<
164174
modeledMethods,
165175
);
166176

167-
await outputFile(this.modelFilename, yaml);
177+
await outputFile(this.modelFile.filename, yaml);
168178

169-
void extLogger.log(`Saved data extension YAML to ${this.modelFilename}`);
179+
void extLogger.log(
180+
`Saved data extension YAML to ${this.modelFile.filename}`,
181+
);
170182
}
171183

172184
protected async loadExistingModeledMethods(): Promise<void> {
173185
try {
174-
const yaml = await readFile(this.modelFilename, "utf8");
186+
const yaml = await readFile(this.modelFile.filename, "utf8");
175187

176188
const data = loadYaml(yaml, {
177-
filename: this.modelFilename,
189+
filename: this.modelFile.filename,
178190
});
179191

180192
const existingModeledMethods = loadDataExtensionYaml(data);
181193

182194
if (!existingModeledMethods) {
183195
void showAndLogErrorMessage(
184-
`Failed to parse data extension YAML ${this.modelFilename}.`,
196+
`Failed to parse data extension YAML ${this.modelFile.filename}.`,
185197
);
186198
return;
187199
}
@@ -193,7 +205,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
193205
} catch (e: unknown) {
194206
void showAndLogErrorMessage(
195207
`Unable to read data extension YAML ${
196-
this.modelFilename
208+
this.modelFile.filename
197209
}: ${getErrorMessage(e)}`,
198210
);
199211
}

extensions/ql-vscode/src/data-extensions-editor/extension-pack-picker.ts

Lines changed: 29 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,42 +21,55 @@ const packNameRegex = new RegExp(
2121
);
2222
const packNameLength = 128;
2323

24+
export interface ExtensionPack {
25+
name: string;
26+
path: string;
27+
}
28+
29+
export interface ExtensionPackModelFile {
30+
filename: string;
31+
extensionPack: ExtensionPack;
32+
}
33+
2434
export async function pickExtensionPackModelFile(
2535
cliServer: Pick<CodeQLCliServer, "resolveQlpacks" | "resolveExtensions">,
2636
databaseItem: Pick<DatabaseItem, "name" | "language">,
2737
progress: ProgressCallback,
2838
token: CancellationToken,
29-
): Promise<string | undefined> {
30-
const extensionPackPath = await pickExtensionPack(
39+
): Promise<ExtensionPackModelFile | undefined> {
40+
const extensionPack = await pickExtensionPack(
3141
cliServer,
3242
databaseItem,
3343
progress,
3444
token,
3545
);
36-
if (!extensionPackPath) {
37-
return;
46+
if (!extensionPack) {
47+
return undefined;
3848
}
3949

4050
const modelFile = await pickModelFile(
4151
cliServer,
4252
databaseItem,
43-
extensionPackPath,
53+
extensionPack.path,
4454
progress,
4555
token,
4656
);
4757
if (!modelFile) {
4858
return;
4959
}
5060

51-
return modelFile;
61+
return {
62+
filename: modelFile,
63+
extensionPack,
64+
};
5265
}
5366

5467
async function pickExtensionPack(
5568
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">,
5669
databaseItem: Pick<DatabaseItem, "name" | "language">,
5770
progress: ProgressCallback,
5871
token: CancellationToken,
59-
): Promise<string | undefined> {
72+
): Promise<ExtensionPack | undefined> {
6073
progress({
6174
message: "Resolving extension packs...",
6275
step: 1,
@@ -117,7 +130,10 @@ async function pickExtensionPack(
117130
return undefined;
118131
}
119132

120-
return extensionPackPaths[0];
133+
return {
134+
name: extensionPackOption.extensionPack,
135+
path: extensionPackPaths[0],
136+
};
121137
}
122138

123139
async function pickModelFile(
@@ -186,7 +202,7 @@ async function pickModelFile(
186202
async function pickNewExtensionPack(
187203
databaseItem: Pick<DatabaseItem, "name" | "language">,
188204
token: CancellationToken,
189-
): Promise<string | undefined> {
205+
): Promise<ExtensionPack | undefined> {
190206
const workspaceFolders = getOnDiskWorkspaceFoldersObjects();
191207
const workspaceFolderOptions = workspaceFolders.map((folder) => ({
192208
label: folder.name,
@@ -263,7 +279,10 @@ async function pickNewExtensionPack(
263279
}),
264280
);
265281

266-
return packPath;
282+
return {
283+
name: packName,
284+
path: packPath,
285+
};
267286
}
268287

269288
async function pickNewModelFile(

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ export type FromDataFlowPathsMessage = CommonFromViewMessages;
483483

484484
export interface SetDataExtensionEditorInitialDataMessage {
485485
t: "setDataExtensionEditorInitialData";
486+
extensionPackName: string;
486487
modelFilename: string;
487488
}
488489

@@ -516,6 +517,10 @@ export interface JumpToUsageMessage {
516517
location: ResolvableLocationValue;
517518
}
518519

520+
export interface OpenExtensionPackMessage {
521+
t: "openExtensionPack";
522+
}
523+
519524
export interface OpenModelFileMessage {
520525
t: "openModelFile";
521526
}
@@ -539,6 +544,7 @@ export type ToDataExtensionsEditorMessage =
539544
export type FromDataExtensionsEditorMessage =
540545
| ViewLoadedMsg
541546
| OpenModelFileMessage
547+
| OpenExtensionPackMessage
542548
| JumpToUsageMessage
543549
| SaveModeledMethods
544550
| GenerateExternalApiMessage;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ const Template: ComponentStory<typeof DataExtensionsEditorComponent> = (
1515

1616
export const DataExtensionsEditor = Template.bind({});
1717
DataExtensionsEditor.args = {
18+
initialExtensionPackName: "codeql/sql2o-models",
1819
initialModelFilename:
1920
"/home/user/vscode-codeql-starter/codeql-custom-queries-java/sql2o/models/sql2o.yml",
2021
initialExternalApiUsages: [

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,21 @@ const ProgressBar = styled.div<ProgressBarProps>`
4747
`;
4848

4949
type Props = {
50+
initialExtensionPackName?: string;
5051
initialModelFilename?: string;
5152
initialExternalApiUsages?: ExternalApiUsage[];
5253
initialModeledMethods?: Record<string, ModeledMethod>;
5354
};
5455

5556
export function DataExtensionsEditor({
57+
initialExtensionPackName,
5658
initialModelFilename,
5759
initialExternalApiUsages = [],
5860
initialModeledMethods = {},
5961
}: Props): JSX.Element {
62+
const [extensionPackName, setExtensionPackName] = useState<
63+
string | undefined
64+
>(initialExtensionPackName);
6065
const [modelFilename, setModelFilename] = useState<string | undefined>(
6166
initialModelFilename,
6267
);
@@ -79,6 +84,7 @@ export function DataExtensionsEditor({
7984
const msg: ToDataExtensionsEditorMessage = evt.data;
8085
switch (msg.t) {
8186
case "setDataExtensionEditorInitialData":
87+
setExtensionPackName(msg.extensionPackName);
8288
setModelFilename(msg.modelFilename);
8389
break;
8490
case "setExternalApiUsages":
@@ -150,6 +156,12 @@ export function DataExtensionsEditor({
150156
});
151157
}, []);
152158

159+
const onOpenExtensionPackClick = useCallback(() => {
160+
vscode.postMessage({
161+
t: "openExtensionPack",
162+
});
163+
}, []);
164+
153165
const onOpenModelFileClick = useCallback(() => {
154166
vscode.postMessage({
155167
t: "openModelFile",
@@ -169,6 +181,12 @@ export function DataExtensionsEditor({
169181
<>
170182
<ViewTitle>Data extensions editor</ViewTitle>
171183
<DetailsContainer>
184+
{extensionPackName && (
185+
<LinkIconButton onClick={onOpenExtensionPackClick}>
186+
<span slot="start" className="codicon codicon-package"></span>
187+
{extensionPackName}
188+
</LinkIconButton>
189+
)}
172190
{modelFilename && (
173191
<LinkIconButton onClick={onOpenModelFileClick}>
174192
<span slot="start" className="codicon codicon-file-code"></span>

0 commit comments

Comments
 (0)