Display error message when can't compare queries
* The error message will be displayed instead of the empty results tables. * Also, uncomment onEnterRules. That should never have been committed. * Also, extract CompareTable to its own component.
This commit is contained in:
Родитель
15d65b308c
Коммит
75fe8fb040
|
@ -66,6 +66,14 @@ export class CompareInterfaceManager extends DisposableObject {
|
|||
selectedResultSetName
|
||||
);
|
||||
if (currentResultSetName) {
|
||||
let rows: QueryCompareResult | undefined;
|
||||
let message: string | undefined;
|
||||
try {
|
||||
rows = this.compareResults(fromResultSet, toResultSet);
|
||||
} catch (e) {
|
||||
message = e.message;
|
||||
}
|
||||
|
||||
await this.postMessage({
|
||||
t: 'setComparisons',
|
||||
stats: {
|
||||
|
@ -81,7 +89,7 @@ export class CompareInterfaceManager extends DisposableObject {
|
|||
},
|
||||
toQuery: {
|
||||
name: to.options.label
|
||||
? to.interpolate(from.getLabel())
|
||||
? to.interpolate(to.getLabel())
|
||||
: to.queryName,
|
||||
status: to.statusString,
|
||||
time: to.time,
|
||||
|
@ -90,7 +98,8 @@ export class CompareInterfaceManager extends DisposableObject {
|
|||
columns: fromResultSet.schema.columns,
|
||||
commonResultSetNames,
|
||||
currentResultSetName: currentResultSetName,
|
||||
rows: this.compareResults(fromResultSet, toResultSet),
|
||||
rows,
|
||||
message,
|
||||
datebaseUri: to.database.databaseUri,
|
||||
});
|
||||
}
|
||||
|
|
|
@ -2,35 +2,33 @@ import * as React from 'react';
|
|||
import { useState, useEffect } from 'react';
|
||||
import * as Rdom from 'react-dom';
|
||||
|
||||
import RawTableHeader from '../../view/RawTableHeader';
|
||||
import {
|
||||
ToCompareViewMessage,
|
||||
SetComparisonsMessage,
|
||||
} from '../../interface-types';
|
||||
import CompareSelector from './CompareSelector';
|
||||
import { vscode } from '../../view/vscode-api';
|
||||
import RawTableRow from '../../view/RawTableRow';
|
||||
import { ResultRow } from '../../adapt';
|
||||
import { className } from '../../view/result-table-utils';
|
||||
import CompareTable from './CompareTable';
|
||||
|
||||
const emptyComparison: SetComparisonsMessage = {
|
||||
t: 'setComparisons',
|
||||
stats: {},
|
||||
rows: {
|
||||
from: [],
|
||||
to: [],
|
||||
},
|
||||
rows: undefined,
|
||||
columns: [],
|
||||
commonResultSetNames: [],
|
||||
currentResultSetName: '',
|
||||
datebaseUri: '',
|
||||
message: 'Empty comparison'
|
||||
};
|
||||
|
||||
export function Compare(props: {}): JSX.Element {
|
||||
export function Compare(_: {}): JSX.Element {
|
||||
const [comparison, setComparison] = useState<SetComparisonsMessage>(
|
||||
emptyComparison
|
||||
);
|
||||
|
||||
const message = comparison.message || 'Empty comparison';
|
||||
const hasRows = comparison.rows && (comparison.rows.to.length || comparison.rows.from.length);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener('message', (evt: MessageEvent) => {
|
||||
const msg: ToCompareViewMessage = evt.data;
|
||||
|
@ -48,7 +46,9 @@ export function Compare(props: {}): JSX.Element {
|
|||
return (
|
||||
<>
|
||||
<div className="vscode-codeql__compare-header">
|
||||
<div>Table to compare:</div>
|
||||
<div className="vscode-codeql__compare-header-item">
|
||||
Table to compare:
|
||||
</div>
|
||||
<CompareSelector
|
||||
availableResultSets={comparison.commonResultSetNames}
|
||||
currentResultSetName={comparison.currentResultSetName}
|
||||
|
@ -57,60 +57,11 @@ export function Compare(props: {}): JSX.Element {
|
|||
}
|
||||
/>
|
||||
</div>
|
||||
<table className="vscode-codeql__compare-body">
|
||||
<thead>
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
onClick={() => openQuery('from')}
|
||||
className="vscode-codeql__compare-open"
|
||||
>
|
||||
{comparison.stats.fromQuery?.name}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a
|
||||
onClick={() => openQuery('to')}
|
||||
className="vscode-codeql__compare-open"
|
||||
>
|
||||
{comparison.stats.toQuery?.name}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{comparison.stats.fromQuery?.time}</td>
|
||||
<td>{comparison.stats.toQuery?.time}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{comparison.rows.from.length} rows removed</th>
|
||||
<th>{comparison.rows.to.length} rows added</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table className={className}>
|
||||
<RawTableHeader
|
||||
columns={comparison.columns}
|
||||
schemaName={comparison.currentResultSetName}
|
||||
preventSort={true}
|
||||
/>
|
||||
{createRows(comparison.rows.from, comparison.datebaseUri)}
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table className={className}>
|
||||
<RawTableHeader
|
||||
columns={comparison.columns}
|
||||
schemaName={comparison.currentResultSetName}
|
||||
preventSort={true}
|
||||
/>
|
||||
{createRows(comparison.rows.to, comparison.datebaseUri)}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{hasRows ? (
|
||||
<CompareTable comparison={comparison}></CompareTable>
|
||||
) : (
|
||||
<div className="vscode-codeql__compare-message">{message}</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
} catch (err) {
|
||||
|
@ -119,28 +70,6 @@ export function Compare(props: {}): JSX.Element {
|
|||
}
|
||||
}
|
||||
|
||||
async function openQuery(kind: 'from' | 'to') {
|
||||
vscode.postMessage({
|
||||
t: 'openQuery',
|
||||
kind,
|
||||
});
|
||||
}
|
||||
|
||||
function createRows(rows: ResultRow[], databaseUri: string) {
|
||||
return (
|
||||
<tbody>
|
||||
{rows.map((row, rowIndex) => (
|
||||
<RawTableRow
|
||||
key={rowIndex}
|
||||
rowIndex={rowIndex}
|
||||
row={row}
|
||||
databaseUri={databaseUri}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
|
||||
Rdom.render(
|
||||
<Compare />,
|
||||
document.getElementById('root'),
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
import * as React from 'react';
|
||||
|
||||
import { SetComparisonsMessage } from '../../interface-types';
|
||||
import RawTableHeader from '../../view/RawTableHeader';
|
||||
import { className } from '../../view/result-table-utils';
|
||||
import { ResultRow } from '../../adapt';
|
||||
import RawTableRow from '../../view/RawTableRow';
|
||||
import { vscode } from '../../view/vscode-api';
|
||||
|
||||
interface Props {
|
||||
comparison: SetComparisonsMessage;
|
||||
}
|
||||
|
||||
export default function CompareTable(props: Props) {
|
||||
const comparison = props.comparison;
|
||||
const rows = props.comparison.rows!;
|
||||
|
||||
async function openQuery(kind: 'from' | 'to') {
|
||||
vscode.postMessage({
|
||||
t: 'openQuery',
|
||||
kind,
|
||||
});
|
||||
}
|
||||
|
||||
function createRows(rows: ResultRow[], databaseUri: string) {
|
||||
return (
|
||||
<tbody>
|
||||
{rows.map((row, rowIndex) => (
|
||||
<RawTableRow
|
||||
key={rowIndex}
|
||||
rowIndex={rowIndex}
|
||||
row={row}
|
||||
databaseUri={databaseUri}
|
||||
/>
|
||||
))}
|
||||
</tbody>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<table className='vscode-codeql__compare-body'>
|
||||
<thead>
|
||||
<tr>
|
||||
<td>
|
||||
<a
|
||||
onClick={() => openQuery('from')}
|
||||
className='vscode-codeql__compare-open'
|
||||
>
|
||||
{comparison.stats.fromQuery?.name}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<a
|
||||
onClick={() => openQuery('to')}
|
||||
className='vscode-codeql__compare-open'
|
||||
>
|
||||
{comparison.stats.toQuery?.name}
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{comparison.stats.fromQuery?.time}</td>
|
||||
<td>{comparison.stats.toQuery?.time}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>{rows.from.length} rows removed</th>
|
||||
<th>{rows.to.length} rows added</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>
|
||||
<table className={className}>
|
||||
<RawTableHeader
|
||||
columns={comparison.columns}
|
||||
schemaName={comparison.currentResultSetName}
|
||||
preventSort={true}
|
||||
/>
|
||||
{createRows(rows.from, comparison.datebaseUri)}
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<table className={className}>
|
||||
<RawTableHeader
|
||||
columns={comparison.columns}
|
||||
schemaName={comparison.currentResultSetName}
|
||||
preventSort={true}
|
||||
/>
|
||||
{createRows(rows.to, comparison.datebaseUri)}
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
);
|
||||
}
|
|
@ -234,7 +234,8 @@ export interface SetComparisonsMessage {
|
|||
readonly columns: readonly ColumnSchema[];
|
||||
readonly commonResultSetNames: string[];
|
||||
readonly currentResultSetName: string;
|
||||
readonly rows: QueryCompareResult;
|
||||
readonly rows: QueryCompareResult | undefined;
|
||||
readonly message: string | undefined;
|
||||
readonly datebaseUri: string;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { languages } from 'vscode';
|
||||
|
||||
import { languages, IndentAction, OnEnterRule } from 'vscode';
|
||||
|
||||
/**
|
||||
* OnEnterRules are available in language-configurations, but you cannot specify them in the language-configuration.json.
|
||||
|
@ -27,29 +26,32 @@ export function install() {
|
|||
languages.setLanguageConfiguration('dbscheme', langConfig);
|
||||
}
|
||||
|
||||
const onEnterRules: string[] = [
|
||||
// {
|
||||
// // e.g. /** | */
|
||||
// beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
|
||||
// afterText: /^\s*\*\/$/,
|
||||
// action: { indentAction: IndentAction.IndentOutdent, appendText: ' * ' }
|
||||
// }, {
|
||||
// // e.g. /** ...|
|
||||
// beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
|
||||
// action: { indentAction: IndentAction.None, appendText: ' * ' }
|
||||
// }, {
|
||||
// // e.g. * ...|
|
||||
// beforeText: /^(\t|[ ])*[ ]\*([ ]([^\*]|\*(?!\/))*)?$/,
|
||||
// oneLineAboveText: /^(\s*(\/\*\*|\*)).*/,
|
||||
// action: { indentAction: IndentAction.None, appendText: '* ' }
|
||||
// }, {
|
||||
// // e.g. */|
|
||||
// beforeText: /^(\t|[ ])*[ ]\*\/\s*$/,
|
||||
// action: { indentAction: IndentAction.None, removeText: 1 }
|
||||
// },
|
||||
// {
|
||||
// // e.g. *-----*/|
|
||||
// beforeText: /^(\t|[ ])*[ ]\*[^/]*\*\/\s*$/,
|
||||
// action: { indentAction: IndentAction.None, removeText: 1 }
|
||||
// }
|
||||
const onEnterRules: OnEnterRule[] = [
|
||||
{
|
||||
// e.g. /** | */
|
||||
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
|
||||
afterText: /^\s*\*\/$/,
|
||||
action: { indentAction: IndentAction.IndentOutdent, appendText: ' * ' },
|
||||
},
|
||||
{
|
||||
// e.g. /** ...|
|
||||
beforeText: /^\s*\/\*\*(?!\/)([^\*]|\*(?!\/))*$/,
|
||||
action: { indentAction: IndentAction.None, appendText: ' * ' },
|
||||
},
|
||||
{
|
||||
// e.g. * ...|
|
||||
beforeText: /^(\t|[ ])*[ ]\*([ ]([^\*]|\*(?!\/))*)?$/,
|
||||
// oneLineAboveText: /^(\s*(\/\*\*|\*)).*/,
|
||||
action: { indentAction: IndentAction.None, appendText: '* ' },
|
||||
},
|
||||
{
|
||||
// e.g. */|
|
||||
beforeText: /^(\t|[ ])*[ ]\*\/\s*$/,
|
||||
action: { indentAction: IndentAction.None, removeText: 1 },
|
||||
},
|
||||
{
|
||||
// e.g. *-----*/|
|
||||
beforeText: /^(\t|[ ])*[ ]\*[^/]*\*\/\s*$/,
|
||||
action: { indentAction: IndentAction.None, removeText: 1 },
|
||||
},
|
||||
];
|
||||
|
|
|
@ -159,7 +159,6 @@ const DOUBLE_CLICK_TIME = 500;
|
|||
|
||||
export class QueryHistoryManager {
|
||||
treeDataProvider: HistoryTreeDataProvider;
|
||||
ctx: ExtensionContext;
|
||||
treeView: vscode.TreeView<CompletedQuery>;
|
||||
lastItemClick: { time: Date; item: CompletedQuery } | undefined;
|
||||
|
||||
|
@ -304,7 +303,6 @@ export class QueryHistoryManager {
|
|||
private selectedCallback: (item: CompletedQuery) => Promise<void>,
|
||||
private doCompareCallback: (from: CompletedQuery, to: CompletedQuery) => Promise<void>,
|
||||
) {
|
||||
this.ctx = ctx;
|
||||
const treeDataProvider = this.treeDataProvider = new HistoryTreeDataProvider(ctx);
|
||||
this.treeView = Window.createTreeView('codeQLQueryHistory', { treeDataProvider });
|
||||
// Lazily update the tree view selection due to limitations of TreeView API (see
|
||||
|
|
|
@ -72,7 +72,9 @@ export class ResultTables
|
|||
|
||||
private getResultSets(): ResultSet[] {
|
||||
const resultSets: ResultSet[] =
|
||||
this.props.rawResultSets.map(rs => ({ t: 'RawResultSet', ...rs }));
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
|
||||
// @ts-ignore 2783
|
||||
this.props.rawResultSets.map((rs) => ({ t: 'RawResultSet', ...rs }));
|
||||
|
||||
if (this.props.interpretation != undefined) {
|
||||
resultSets.push({
|
||||
|
@ -286,8 +288,6 @@ class ResultTable extends React.Component<ResultTableProps, {}> {
|
|||
{...this.props} resultSet={resultSet} />;
|
||||
case 'SarifResultSet': return <PathTable
|
||||
{...this.props} resultSet={resultSet} />;
|
||||
default:
|
||||
throw new Error('Invalid type');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -161,6 +161,14 @@ td.vscode-codeql__path-index-cell {
|
|||
display: flex;
|
||||
}
|
||||
|
||||
.vscode-codeql__compare-header-item {
|
||||
margin: 0 1.5rem;
|
||||
}
|
||||
|
||||
.vscode-codeql__compare-message {
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
||||
.vscode-codeql__compare-body {
|
||||
margin: 20px 0;
|
||||
width: 100%;
|
||||
|
|
Загрузка…
Ссылка в новой задаче