Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions extensions/ql-vscode/src/common/interface-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,13 +334,15 @@ interface ChangeCompareMessage {
newResultSetName: string;
}

export type ToCompareViewMessage = SetComparisonsMessage;
export type ToCompareViewMessage =
| SetComparisonQueryInfoMessage
| SetComparisonsMessage;

/**
* Message to the compare view that specifies the query results to compare.
* Message to the compare view that sets the metadata of the compared queries.
*/
export interface SetComparisonsMessage {
readonly t: "setComparisons";
export interface SetComparisonQueryInfoMessage {
readonly t: "setComparisonQueryInfo";
readonly stats: {
fromQuery?: {
name: string;
Expand All @@ -353,11 +355,18 @@ export interface SetComparisonsMessage {
time: string;
};
};
readonly databaseUri: string;
readonly commonResultSetNames: string[];
}

/**
* Message to the compare view that specifies the query results to compare.
*/
export interface SetComparisonsMessage {
readonly t: "setComparisons";
readonly currentResultSetName: string;
readonly result: QueryCompareResult | undefined;
readonly message: string | undefined;
readonly databaseUri: string;
}

type QueryCompareResult = RawQueryCompareResult | InterpretedQueryCompareResult;
Expand Down
87 changes: 50 additions & 37 deletions extensions/ql-vscode/src/compare/compare-view.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,18 @@ import {
import { telemetryListener } from "../common/vscode/telemetry";
import { redactableError } from "../common/errors";
import { App } from "../common/app";
import { findResultSetNames } from "./result-set-names";
import {
findCommonResultSetNames,
findResultSetNames,
} from "./result-set-names";

interface ComparePair {
from: CompletedLocalQueryInfo;
fromSchemas: BQRSInfo;
to: CompletedLocalQueryInfo;
toSchemas: BQRSInfo;

commonResultSetNames: readonly string[];
}

export class CompareView extends AbstractWebview<
Expand Down Expand Up @@ -62,13 +67,44 @@ export class CompareView extends AbstractWebview<
to.completedQuery.query.resultsPaths.resultsPath,
);

const commonResultSetNames = await findCommonResultSetNames(
fromSchemas,
toSchemas,
);

this.comparePair = {
from,
fromSchemas,
to,
toSchemas,
commonResultSetNames,
};

const panel = await this.getPanel();
panel.reveal(undefined, true);
await this.waitForPanelLoaded();

await this.postMessage({
t: "setComparisonQueryInfo",
stats: {
fromQuery: {
// since we split the description into several rows
// only run interpolation if the label is user-defined
// otherwise we will wind up with duplicated rows
name: this.labelProvider.getShortLabel(from),
status: from.completedQuery.statusString,
time: from.startTime,
},
toQuery: {
name: this.labelProvider.getShortLabel(to),
status: to.completedQuery.statusString,
time: to.startTime,
},
},
databaseUri: to.initialInfo.databaseInfo.databaseUri,
commonResultSetNames,
});

await this.showResultsInternal(selectedResultSetName);
}

Expand All @@ -77,21 +113,15 @@ export class CompareView extends AbstractWebview<
return;
}

const { from, to } = this.comparePair;

const panel = await this.getPanel();
panel.reveal(undefined, true);

await this.waitForPanelLoaded();
const {
commonResultSetNames,
currentResultSetDisplayName,
fromResultSet,
toResultSet,
} = await this.findResultSetsToCompare(
this.comparePair,
selectedResultSetName,
);
const { currentResultSetDisplayName, fromResultSet, toResultSet } =
await this.findResultSetsToCompare(
this.comparePair,
selectedResultSetName,
);
if (currentResultSetDisplayName) {
let result: RawQueryCompareResult | undefined;
let message: string | undefined;
Expand All @@ -103,26 +133,9 @@ export class CompareView extends AbstractWebview<

await this.postMessage({
t: "setComparisons",
stats: {
fromQuery: {
// since we split the description into several rows
// only run interpolation if the label is user-defined
// otherwise we will wind up with duplicated rows
name: this.labelProvider.getShortLabel(from),
status: from.completedQuery.statusString,
time: from.startTime,
},
toQuery: {
name: this.labelProvider.getShortLabel(to),
status: to.completedQuery.statusString,
time: to.startTime,
},
},
result,
commonResultSetNames,
currentResultSetName: currentResultSetDisplayName,
message,
databaseUri: to.initialInfo.databaseInfo.databaseUri,
});
}
}
Expand Down Expand Up @@ -190,15 +203,16 @@ export class CompareView extends AbstractWebview<
}

private async findResultSetsToCompare(
{ from, fromSchemas, to, toSchemas }: ComparePair,
{ from, fromSchemas, to, toSchemas, commonResultSetNames }: ComparePair,
selectedResultSetName: string | undefined,
) {
const {
commonResultSetNames,
currentResultSetDisplayName,
fromResultSetName,
toResultSetName,
} = await findResultSetNames(fromSchemas, toSchemas, selectedResultSetName);
const { currentResultSetDisplayName, fromResultSetName, toResultSetName } =
await findResultSetNames(
fromSchemas,
toSchemas,
commonResultSetNames,
selectedResultSetName,
);

const fromResultSet = await this.getResultSet(
fromSchemas,
Expand All @@ -211,7 +225,6 @@ export class CompareView extends AbstractWebview<
to.completedQuery.query.resultsPaths.resultsPath,
);
return {
commonResultSetNames,
currentResultSetDisplayName,
fromResultSet,
toResultSet,
Expand Down
17 changes: 13 additions & 4 deletions extensions/ql-vscode/src/compare/result-set-names.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,28 @@
import { BQRSInfo } from "../common/bqrs-cli-types";
import { getDefaultResultSetName } from "../common/interface-types";

export async function findCommonResultSetNames(
fromSchemas: BQRSInfo,
toSchemas: BQRSInfo,
): Promise<string[]> {
const fromSchemaNames = fromSchemas["result-sets"].map(
(schema) => schema.name,
);
const toSchemaNames = toSchemas["result-sets"].map((schema) => schema.name);

return fromSchemaNames.filter((name) => toSchemaNames.includes(name));
}

export async function findResultSetNames(
fromSchemas: BQRSInfo,
toSchemas: BQRSInfo,
commonResultSetNames: readonly string[],
selectedResultSetName: string | undefined,
) {
const fromSchemaNames = fromSchemas["result-sets"].map(
(schema) => schema.name,
);
const toSchemaNames = toSchemas["result-sets"].map((schema) => schema.name);
const commonResultSetNames = fromSchemaNames.filter((name) =>
toSchemaNames.includes(name),
);

// Fall back on the default result set names if there are no common ones.
const defaultFromResultSetName = fromSchemaNames.find((name) =>
Expand All @@ -37,7 +47,6 @@ export async function findResultSetNames(
const toResultSetName = currentResultSetName || defaultToResultSetName!;

return {
commonResultSetNames,
currentResultSetDisplayName:
currentResultSetName ||
`${defaultFromResultSetName} <-> ${defaultToResultSetName}`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ const Template: StoryFn<typeof CompareTableComponent> = (args) => (

export const CompareTable = Template.bind({});
CompareTable.args = {
comparison: {
t: "setComparisons",
queryInfo: {
t: "setComparisonQueryInfo",
stats: {
fromQuery: {
name: "Query built from user-controlled sources",
Expand All @@ -31,7 +31,11 @@ CompareTable.args = {
time: "8/16/2023, 3:07:21 PM",
},
},
databaseUri: "file:///java",
commonResultSetNames: ["edges", "nodes", "subpaths", "#select"],
},
comparison: {
t: "setComparisons",
currentResultSetName: "edges",
result: {
kind: "raw",
Expand Down Expand Up @@ -66,6 +70,5 @@ CompareTable.args = {
],
},
message: undefined,
databaseUri: "file:///java",
},
};
19 changes: 16 additions & 3 deletions extensions/ql-vscode/src/view/compare/Compare.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import { styled } from "styled-components";
import {
ToCompareViewMessage,
SetComparisonsMessage,
SetComparisonQueryInfoMessage,
} from "../../common/interface-types";
import CompareSelector from "./CompareSelector";
import { vscode } from "../vscode-api";
import CompareTable from "./CompareTable";

import "../results/resultsView.css";
import { assertNever } from "../../common/helpers-pure";

const Header = styled.div`
display: flex;
Expand All @@ -25,6 +27,8 @@ const Message = styled.div`
`;

export function Compare(_: Record<string, never>): JSX.Element {
const [queryInfo, setQueryInfo] =
useState<SetComparisonQueryInfoMessage | null>(null);
const [comparison, setComparison] = useState<SetComparisonsMessage | null>(
null,
);
Expand All @@ -39,8 +43,14 @@ export function Compare(_: Record<string, never>): JSX.Element {
if (evt.origin === window.origin) {
const msg: ToCompareViewMessage = evt.data;
switch (msg.t) {
case "setComparisonQueryInfo":
setQueryInfo(msg);
break;
case "setComparisons":
setComparison(msg);
break;
default:
assertNever(msg);
}
} else {
// sanitize origin
Expand All @@ -55,7 +65,7 @@ export function Compare(_: Record<string, never>): JSX.Element {
};
}, []);

if (!comparison) {
if (!queryInfo || !comparison) {
return <div>Waiting for results to load.</div>;
}

Expand All @@ -65,15 +75,18 @@ export function Compare(_: Record<string, never>): JSX.Element {
<Header>
<HeaderTitle>Comparing:</HeaderTitle>
<CompareSelector
availableResultSets={comparison.commonResultSetNames}
availableResultSets={queryInfo.commonResultSetNames}
currentResultSetName={comparison.currentResultSetName}
updateResultSet={(newResultSetName: string) =>
vscode.postMessage({ t: "changeCompare", newResultSetName })
}
/>
</Header>
{hasRows ? (
<CompareTable comparison={comparison}></CompareTable>
<CompareTable
queryInfo={queryInfo}
comparison={comparison}
></CompareTable>
) : (
<Message>{message}</Message>
)}
Expand Down
Loading