From 3554bceac0fd889ae3859b2801bf421e0bba0b46 Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Wed, 6 Dec 2023 16:02:08 +0100 Subject: [PATCH 1/3] Split compare view messages This splits the compare view messages into two different messages. One contains the metadata that doesn't change when the user selects a different result set, and the other contains the actual results. --- .../ql-vscode/src/common/interface-types.ts | 19 +++++++--- .../ql-vscode/src/compare/compare-view.ts | 38 ++++++++++--------- .../stories/compare/CompareTable.stories.tsx | 9 +++-- .../ql-vscode/src/view/compare/Compare.tsx | 17 ++++++++- .../src/view/compare/CompareTable.tsx | 23 ++++++----- 5 files changed, 68 insertions(+), 38 deletions(-) diff --git a/extensions/ql-vscode/src/common/interface-types.ts b/extensions/ql-vscode/src/common/interface-types.ts index 3aeb37a6447..5a8f1f27eeb 100644 --- a/extensions/ql-vscode/src/common/interface-types.ts +++ b/extensions/ql-vscode/src/common/interface-types.ts @@ -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; @@ -353,11 +355,18 @@ export interface SetComparisonsMessage { time: string; }; }; + readonly databaseUri: string; +} + +/** + * Message to the compare view that specifies the query results to compare. + */ +export interface SetComparisonsMessage { + readonly t: "setComparisons"; readonly commonResultSetNames: string[]; readonly currentResultSetName: string; readonly result: RawQueryCompareResult | undefined; readonly message: string | undefined; - readonly databaseUri: string; } /** diff --git a/extensions/ql-vscode/src/compare/compare-view.ts b/extensions/ql-vscode/src/compare/compare-view.ts index 971f29f005b..f5cac632a42 100644 --- a/extensions/ql-vscode/src/compare/compare-view.ts +++ b/extensions/ql-vscode/src/compare/compare-view.ts @@ -69,6 +69,26 @@ export class CompareView extends AbstractWebview< toSchemas, }; + 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, + }); + await this.showResultsInternal(selectedResultSetName); } @@ -77,8 +97,6 @@ export class CompareView extends AbstractWebview< return; } - const { from, to } = this.comparePair; - const panel = await this.getPanel(); panel.reveal(undefined, true); @@ -103,26 +121,10 @@ 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, }); } } diff --git a/extensions/ql-vscode/src/stories/compare/CompareTable.stories.tsx b/extensions/ql-vscode/src/stories/compare/CompareTable.stories.tsx index 2bf41cd2207..221e012a544 100644 --- a/extensions/ql-vscode/src/stories/compare/CompareTable.stories.tsx +++ b/extensions/ql-vscode/src/stories/compare/CompareTable.stories.tsx @@ -17,8 +17,8 @@ const Template: StoryFn = (args) => ( export const CompareTable = Template.bind({}); CompareTable.args = { - comparison: { - t: "setComparisons", + queryInfo: { + t: "setComparisonQueryInfo", stats: { fromQuery: { name: "Query built from user-controlled sources", @@ -31,6 +31,10 @@ CompareTable.args = { time: "8/16/2023, 3:07:21 PM", }, }, + databaseUri: "file:///java", + }, + comparison: { + t: "setComparisons", commonResultSetNames: ["edges", "nodes", "subpaths", "#select"], currentResultSetName: "edges", result: { @@ -65,6 +69,5 @@ CompareTable.args = { ], }, message: undefined, - databaseUri: "file:///java", }, }; diff --git a/extensions/ql-vscode/src/view/compare/Compare.tsx b/extensions/ql-vscode/src/view/compare/Compare.tsx index 65e0a8ef3fe..313f43f8536 100644 --- a/extensions/ql-vscode/src/view/compare/Compare.tsx +++ b/extensions/ql-vscode/src/view/compare/Compare.tsx @@ -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; @@ -25,6 +27,8 @@ const Message = styled.div` `; export function Compare(_: Record): JSX.Element { + const [queryInfo, setQueryInfo] = + useState(null); const [comparison, setComparison] = useState( null, ); @@ -39,8 +43,14 @@ export function Compare(_: Record): 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 @@ -55,7 +65,7 @@ export function Compare(_: Record): JSX.Element { }; }, []); - if (!comparison) { + if (!queryInfo || !comparison) { return
Waiting for results to load.
; } @@ -73,7 +83,10 @@ export function Compare(_: Record): JSX.Element { /> {hasRows ? ( - + ) : ( {message} )} diff --git a/extensions/ql-vscode/src/view/compare/CompareTable.tsx b/extensions/ql-vscode/src/view/compare/CompareTable.tsx index 29c1a79daa1..46074d9a30b 100644 --- a/extensions/ql-vscode/src/view/compare/CompareTable.tsx +++ b/extensions/ql-vscode/src/view/compare/CompareTable.tsx @@ -1,6 +1,9 @@ import * as React from "react"; -import { SetComparisonsMessage } from "../../common/interface-types"; +import { + SetComparisonQueryInfoMessage, + SetComparisonsMessage, +} from "../../common/interface-types"; import { className } from "../results/result-table-utils"; import { vscode } from "../vscode-api"; import TextButton from "../common/TextButton"; @@ -8,6 +11,7 @@ import { styled } from "styled-components"; import { RawCompareResultTable } from "./RawCompareResultTable"; interface Props { + queryInfo: SetComparisonQueryInfoMessage; comparison: SetComparisonsMessage; } @@ -26,9 +30,8 @@ const Table = styled.table` } `; -export default function CompareTable(props: Props) { - const comparison = props.comparison; - const result = props.comparison.result!; +export default function CompareTable({ queryInfo, comparison }: Props) { + const result = comparison.result!; async function openQuery(kind: "from" | "to") { vscode.postMessage({ @@ -43,18 +46,18 @@ export default function CompareTable(props: Props) { openQuery("from")}> - {comparison.stats.fromQuery?.name} + {queryInfo.stats.fromQuery?.name} openQuery("to")}> - {comparison.stats.toQuery?.name} + {queryInfo.stats.toQuery?.name} - {comparison.stats.fromQuery?.time} - {comparison.stats.toQuery?.time} + {queryInfo.stats.fromQuery?.time} + {queryInfo.stats.toQuery?.time} {result.from.length} rows removed @@ -68,7 +71,7 @@ export default function CompareTable(props: Props) { columns={result.columns} schemaName={comparison.currentResultSetName} rows={result.from} - databaseUri={comparison.databaseUri} + databaseUri={queryInfo.databaseUri} className={className} /> @@ -77,7 +80,7 @@ export default function CompareTable(props: Props) { columns={result.columns} schemaName={comparison.currentResultSetName} rows={result.to} - databaseUri={comparison.databaseUri} + databaseUri={queryInfo.databaseUri} className={className} /> From 27418898b09a7802e98958fb59d3dabbea56ca77 Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Wed, 6 Dec 2023 16:08:16 +0100 Subject: [PATCH 2/3] Cache common result set names This caches the common result set names and moves the common result set names from the `SetComparisonsMessage` to the `SetComparisonQueryInfoMessage`. --- .../ql-vscode/src/common/interface-types.ts | 2 +- .../ql-vscode/src/compare/compare-view.ts | 45 +++++++++++-------- .../ql-vscode/src/compare/result-set-names.ts | 17 +++++-- .../stories/compare/CompareTable.stories.tsx | 2 +- .../ql-vscode/src/view/compare/Compare.tsx | 2 +- 5 files changed, 42 insertions(+), 26 deletions(-) diff --git a/extensions/ql-vscode/src/common/interface-types.ts b/extensions/ql-vscode/src/common/interface-types.ts index 5a8f1f27eeb..8255e3893aa 100644 --- a/extensions/ql-vscode/src/common/interface-types.ts +++ b/extensions/ql-vscode/src/common/interface-types.ts @@ -356,6 +356,7 @@ export interface SetComparisonQueryInfoMessage { }; }; readonly databaseUri: string; + readonly commonResultSetNames: string[]; } /** @@ -363,7 +364,6 @@ export interface SetComparisonQueryInfoMessage { */ export interface SetComparisonsMessage { readonly t: "setComparisons"; - readonly commonResultSetNames: string[]; readonly currentResultSetName: string; readonly result: RawQueryCompareResult | undefined; readonly message: string | undefined; diff --git a/extensions/ql-vscode/src/compare/compare-view.ts b/extensions/ql-vscode/src/compare/compare-view.ts index f5cac632a42..2eba8b103b5 100644 --- a/extensions/ql-vscode/src/compare/compare-view.ts +++ b/extensions/ql-vscode/src/compare/compare-view.ts @@ -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< @@ -62,11 +67,17 @@ export class CompareView extends AbstractWebview< to.completedQuery.query.resultsPaths.resultsPath, ); + const commonResultSetNames = await findCommonResultSetNames( + fromSchemas, + toSchemas, + ); + this.comparePair = { from, fromSchemas, to, toSchemas, + commonResultSetNames, }; await this.postMessage({ @@ -87,6 +98,7 @@ export class CompareView extends AbstractWebview< }, }, databaseUri: to.initialInfo.databaseInfo.databaseUri, + commonResultSetNames, }); await this.showResultsInternal(selectedResultSetName); @@ -101,15 +113,11 @@ export class CompareView extends AbstractWebview< 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; @@ -122,7 +130,6 @@ export class CompareView extends AbstractWebview< await this.postMessage({ t: "setComparisons", result, - commonResultSetNames, currentResultSetName: currentResultSetDisplayName, message, }); @@ -192,15 +199,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, @@ -213,7 +221,6 @@ export class CompareView extends AbstractWebview< to.completedQuery.query.resultsPaths.resultsPath, ); return { - commonResultSetNames, currentResultSetDisplayName, fromResultSet, toResultSet, diff --git a/extensions/ql-vscode/src/compare/result-set-names.ts b/extensions/ql-vscode/src/compare/result-set-names.ts index 2430a39d7cd..545b0468c4a 100644 --- a/extensions/ql-vscode/src/compare/result-set-names.ts +++ b/extensions/ql-vscode/src/compare/result-set-names.ts @@ -1,17 +1,27 @@ import { BQRSInfo } from "../common/bqrs-cli-types"; +export async function findCommonResultSetNames( + fromSchemas: BQRSInfo, + toSchemas: BQRSInfo, +): Promise { + 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) => @@ -35,7 +45,6 @@ export async function findResultSetNames( const toResultSetName = currentResultSetName || defaultToResultSetName!; return { - commonResultSetNames, currentResultSetDisplayName: currentResultSetName || `${defaultFromResultSetName} <-> ${defaultToResultSetName}`, diff --git a/extensions/ql-vscode/src/stories/compare/CompareTable.stories.tsx b/extensions/ql-vscode/src/stories/compare/CompareTable.stories.tsx index 221e012a544..bf994173ae4 100644 --- a/extensions/ql-vscode/src/stories/compare/CompareTable.stories.tsx +++ b/extensions/ql-vscode/src/stories/compare/CompareTable.stories.tsx @@ -32,10 +32,10 @@ CompareTable.args = { }, }, databaseUri: "file:///java", + commonResultSetNames: ["edges", "nodes", "subpaths", "#select"], }, comparison: { t: "setComparisons", - commonResultSetNames: ["edges", "nodes", "subpaths", "#select"], currentResultSetName: "edges", result: { columns: [ diff --git a/extensions/ql-vscode/src/view/compare/Compare.tsx b/extensions/ql-vscode/src/view/compare/Compare.tsx index 313f43f8536..e335c966373 100644 --- a/extensions/ql-vscode/src/view/compare/Compare.tsx +++ b/extensions/ql-vscode/src/view/compare/Compare.tsx @@ -75,7 +75,7 @@ export function Compare(_: Record): JSX.Element {
Comparing: vscode.postMessage({ t: "changeCompare", newResultSetName }) From 4873d7eb120a35726fdd8194404d65a81230d7a8 Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Wed, 6 Dec 2023 16:21:16 +0100 Subject: [PATCH 3/3] Fix postMessage beint sent before webview is loaded --- extensions/ql-vscode/src/compare/compare-view.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/extensions/ql-vscode/src/compare/compare-view.ts b/extensions/ql-vscode/src/compare/compare-view.ts index 2eba8b103b5..61c467b241e 100644 --- a/extensions/ql-vscode/src/compare/compare-view.ts +++ b/extensions/ql-vscode/src/compare/compare-view.ts @@ -80,6 +80,10 @@ export class CompareView extends AbstractWebview< commonResultSetNames, }; + const panel = await this.getPanel(); + panel.reveal(undefined, true); + await this.waitForPanelLoaded(); + await this.postMessage({ t: "setComparisonQueryInfo", stats: {