Skip to content

Commit a893bf7

Browse files
Merge pull request #2688 from github/robertbrignull/data-view-jump
Implementing expanding/selecting item in details view when clicking "view"
2 parents dd0534b + 5bf56ba commit a893bf7

File tree

7 files changed

+61
-25
lines changed

7 files changed

+61
-25
lines changed

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ export type ExplorerSelectionCommandFunction<Item> = (
5959
type BuiltInVsCodeCommands = {
6060
// The codeQLDatabases.focus command is provided by VS Code because we've registered the custom view
6161
"codeQLDatabases.focus": () => Promise<void>;
62-
"codeQLModelDetails.focus": () => Promise<void>;
6362
"markdown.showPreviewToSide": (uri: Uri) => Promise<void>;
6463
"workbench.action.closeActiveEditor": () => Promise<void>;
6564
revealFileInOS: (uri: Uri) => Promise<void>;

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

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@ import {
1717
} from "../variant-analysis/shared/variant-analysis-filter-sort";
1818
import { ErrorLike } from "../common/errors";
1919
import { DataFlowPaths } from "../variant-analysis/shared/data-flow-paths";
20-
import { ExternalApiUsage } from "../data-extensions-editor/external-api-usage";
20+
import {
21+
ExternalApiUsage,
22+
Usage,
23+
} from "../data-extensions-editor/external-api-usage";
2124
import { ModeledMethod } from "../data-extensions-editor/modeled-method";
2225
import { DataExtensionEditorViewState } from "../data-extensions-editor/shared/view-state";
2326
import { Mode } from "../data-extensions-editor/shared/mode";
@@ -523,7 +526,7 @@ interface SwitchModeMessage {
523526

524527
interface JumpToUsageMessage {
525528
t: "jumpToUsage";
526-
location: ResolvableLocationValue;
529+
usage: Usage;
527530
}
528531

529532
interface OpenDatabaseMessage {

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ export class DataExtensionsEditorModule extends DisposableObject {
148148
modelFile,
149149
Mode.Application,
150150
this.modelDetailsPanel.setState.bind(this.modelDetailsPanel),
151+
this.modelDetailsPanel.revealItem.bind(this.modelDetailsPanel),
151152
);
152153
await view.openView();
153154
},

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

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,11 @@ import { asError, assertNever, getErrorMessage } from "../common/helpers-pure";
2525
import { generateFlowModel } from "./generate-flow-model";
2626
import { promptImportGithubDatabase } from "../databases/database-fetcher";
2727
import { App } from "../common/app";
28-
import { ResolvableLocationValue } from "../common/bqrs-cli-types";
2928
import { showResolvableLocation } from "../databases/local-databases/locations";
3029
import { decodeBqrsToExternalApiUsages } from "./bqrs";
3130
import { redactableError } from "../common/errors";
3231
import { readQueryResults, runQuery } from "./external-api-usage-query";
33-
import { ExternalApiUsage } from "./external-api-usage";
32+
import { ExternalApiUsage, Usage } from "./external-api-usage";
3433
import { ModeledMethod } from "./modeled-method";
3534
import { ExtensionPack } from "./shared/extension-pack";
3635
import {
@@ -66,6 +65,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
6665
externalApiUsages: ExternalApiUsage[],
6766
databaseItem: DatabaseItem,
6867
) => Promise<void>,
68+
private readonly revealItemInDetailsPanel: (usage: Usage) => Promise<void>,
6969
) {
7070
super(ctx);
7171

@@ -146,7 +146,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
146146

147147
break;
148148
case "jumpToUsage":
149-
await this.handleJumpToUsage(msg.location);
149+
await this.handleJumpToUsage(msg.usage);
150150

151151
break;
152152
case "saveModeledMethods":
@@ -216,22 +216,11 @@ export class DataExtensionsEditorView extends AbstractWebview<
216216
});
217217
}
218218

219-
protected async handleJumpToUsage(location: ResolvableLocationValue) {
219+
protected async handleJumpToUsage(usage: Usage) {
220220
if (showModelDetailsView()) {
221-
await this.openModelDetailsView();
222-
} else {
223-
await this.jumpToUsage(location);
221+
await this.revealItemInDetailsPanel(usage);
224222
}
225-
}
226-
227-
protected async openModelDetailsView() {
228-
await this.app.commands.execute("codeQLModelDetails.focus");
229-
}
230-
231-
protected async jumpToUsage(
232-
location: ResolvableLocationValue,
233-
): Promise<void> {
234-
await showResolvableLocation(location, this.databaseItem, this.app.logger);
223+
await showResolvableLocation(usage.url, this.databaseItem, this.app.logger);
235224
}
236225

237226
protected async loadExistingModeledMethods(): Promise<void> {
@@ -419,6 +408,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
419408
modelFile,
420409
Mode.Framework,
421410
this.updateModelDetailsPanelState,
411+
this.revealItemInDetailsPanel,
422412
);
423413
await view.openView();
424414
});

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

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,45 @@ export class ModelDetailsDataProvider
8888
return [];
8989
}
9090
}
91+
92+
getParent(
93+
item: ModelDetailsTreeViewItem,
94+
): ModelDetailsTreeViewItem | undefined {
95+
if (isExternalApiUsage(item)) {
96+
return undefined;
97+
} else {
98+
return this.externalApiUsages.find((e) => e.usages.includes(item));
99+
}
100+
}
101+
102+
public resolveCanonicalUsage(usage: Usage): Usage | undefined {
103+
for (const externalApiUsage of this.externalApiUsages) {
104+
for (const u of externalApiUsage.usages) {
105+
if (usagesAreEqual(u, usage)) {
106+
return u;
107+
}
108+
}
109+
}
110+
return undefined;
111+
}
91112
}
92113

93-
type ModelDetailsTreeViewItem = ExternalApiUsage | Usage;
114+
export type ModelDetailsTreeViewItem = ExternalApiUsage | Usage;
94115

95116
function isExternalApiUsage(
96117
item: ModelDetailsTreeViewItem,
97118
): item is ExternalApiUsage {
98119
return (item as any).usages !== undefined;
99120
}
121+
122+
function usagesAreEqual(u1: Usage, u2: Usage): boolean {
123+
return (
124+
u1.label === u2.label &&
125+
u1.classification === u2.classification &&
126+
u1.url.uri === u2.url.uri &&
127+
u1.url.startLine === u2.url.startLine &&
128+
u1.url.startColumn === u2.url.startColumn &&
129+
u1.url.endLine === u2.url.endLine &&
130+
u1.url.endColumn === u2.url.endColumn
131+
);
132+
}

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

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
import { TreeView, window } from "vscode";
22
import { DisposableObject } from "../../common/disposable-object";
3-
import { ModelDetailsDataProvider } from "./model-details-data-provider";
4-
import { DatabaseItem } from "../../databases/local-databases";
3+
import {
4+
ModelDetailsDataProvider,
5+
ModelDetailsTreeViewItem,
6+
} from "./model-details-data-provider";
57
import { ExternalApiUsage, Usage } from "../external-api-usage";
8+
import { DatabaseItem } from "../../databases/local-databases";
69
import { CodeQLCliServer } from "../../codeql-cli/cli";
710

811
export class ModelDetailsPanel extends DisposableObject {
912
private readonly dataProvider: ModelDetailsDataProvider;
10-
private readonly treeView: TreeView<ExternalApiUsage | Usage>;
13+
private readonly treeView: TreeView<ModelDetailsTreeViewItem>;
1114

1215
public constructor(cliServer: CodeQLCliServer) {
1316
super();
@@ -30,4 +33,11 @@ export class ModelDetailsPanel extends DisposableObject {
3033
tooltip: "Number of external APIs",
3134
};
3235
}
36+
37+
public async revealItem(usage: Usage): Promise<void> {
38+
const canonicalUsage = this.dataProvider.resolveCanonicalUsage(usage);
39+
if (canonicalUsage !== undefined) {
40+
await this.treeView.reveal(canonicalUsage);
41+
}
42+
}
3343
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ function sendJumpToUsageMessage(externalApiUsage: ExternalApiUsage) {
326326
vscode.postMessage({
327327
t: "jumpToUsage",
328328
// In framework mode, the first and only usage is the definition of the method
329-
location: externalApiUsage.usages[0].url,
329+
usage: externalApiUsage.usages[0],
330330
});
331331
}
332332

0 commit comments

Comments
 (0)