Organize sort state for interpreted results
Rename existing sort state for raw results, and make some state for keeping track of sort state for interpreted results.
This commit is contained in:
Родитель
81a6b23e81
Коммит
d135507a77
|
@ -17,11 +17,11 @@ export interface DatabaseInfo {
|
|||
}
|
||||
|
||||
/** Arbitrary query metadata */
|
||||
export interface QueryMetadata {
|
||||
name?: string,
|
||||
description?: string,
|
||||
id?: string,
|
||||
kind?: string
|
||||
export interface QueryMetadata {
|
||||
name?: string,
|
||||
description?: string,
|
||||
id?: string,
|
||||
kind?: string
|
||||
}
|
||||
|
||||
export interface PreviousExecution {
|
||||
|
@ -34,6 +34,7 @@ export interface PreviousExecution {
|
|||
export interface Interpretation {
|
||||
sourceLocationPrefix: string;
|
||||
numTruncatedResults: number;
|
||||
sortState: InterpretedResultsSortState;
|
||||
sarif: sarif.Log;
|
||||
}
|
||||
|
||||
|
@ -44,7 +45,7 @@ export interface ResultsPaths {
|
|||
|
||||
export interface SortedResultSetInfo {
|
||||
resultsPath: string;
|
||||
sortState: SortState;
|
||||
sortState: RawResultsSortState;
|
||||
}
|
||||
|
||||
export type SortedResultsMap = { [resultSet: string]: SortedResultSetInfo };
|
||||
|
@ -84,7 +85,12 @@ export interface NavigatePathMsg {
|
|||
|
||||
export type IntoResultsViewMsg = ResultsUpdatingMsg | SetStateMsg | NavigatePathMsg;
|
||||
|
||||
export type FromResultsViewMsg = ViewSourceFileMsg | ToggleDiagnostics | ChangeSortMsg | ResultViewLoaded;
|
||||
export type FromResultsViewMsg =
|
||||
| ViewSourceFileMsg
|
||||
| ToggleDiagnostics
|
||||
| ChangeRawResultsSortMsg
|
||||
| ChangeInterpretedResultsSortMsg
|
||||
| ResultViewLoaded;
|
||||
|
||||
interface ViewSourceFileMsg {
|
||||
t: 'viewSourceFile';
|
||||
|
@ -109,13 +115,22 @@ export enum SortDirection {
|
|||
asc, desc
|
||||
}
|
||||
|
||||
export interface SortState {
|
||||
export interface RawResultsSortState {
|
||||
columnIndex: number;
|
||||
direction: SortDirection;
|
||||
}
|
||||
|
||||
interface ChangeSortMsg {
|
||||
export interface InterpretedResultsSortState {
|
||||
sortBy: 'file-position' | 'alert-message';
|
||||
}
|
||||
|
||||
interface ChangeRawResultsSortMsg {
|
||||
t: 'changeSort';
|
||||
resultSetName: string;
|
||||
sortState?: SortState;
|
||||
sortState?: RawResultsSortState;
|
||||
}
|
||||
|
||||
interface ChangeInterpretedResultsSortMsg {
|
||||
t: 'changeInterpretedSort';
|
||||
sortState?: InterpretedResultsSortState;
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ import { CodeQLCliServer } from './cli';
|
|||
import { DatabaseItem, DatabaseManager } from './databases';
|
||||
import { showAndLogErrorMessage } from './helpers';
|
||||
import { assertNever } from './helpers-pure';
|
||||
import { FromResultsViewMsg, Interpretation, INTERPRETED_RESULTS_PER_RUN_LIMIT, IntoResultsViewMsg, QueryMetadata, ResultsPaths, SortedResultSetInfo, SortedResultsMap } from './interface-types';
|
||||
import { FromResultsViewMsg, Interpretation, INTERPRETED_RESULTS_PER_RUN_LIMIT, IntoResultsViewMsg, QueryMetadata, ResultsPaths, SortedResultSetInfo, SortedResultsMap, InterpretedResultsSortState } from './interface-types';
|
||||
import { Logger } from './logging';
|
||||
import * as messages from './messages';
|
||||
import { CompletedQuery, interpretResults } from './query-results';
|
||||
|
@ -190,6 +190,17 @@ export class InterfaceManager extends DisposableObject {
|
|||
await this.showResults(this._displayedQuery, WebviewReveal.NotForced, true);
|
||||
break;
|
||||
}
|
||||
case 'changeInterpretedSort': {
|
||||
if (this._displayedQuery === undefined) {
|
||||
showAndLogErrorMessage("Failed to sort results since evaluation info was unknown.");
|
||||
break;
|
||||
}
|
||||
// Notify the webview that it should expect new results.
|
||||
await this.postMessage({ t: 'resultsUpdating' });
|
||||
await this._displayedQuery.updateInterpretedSortState(this.cliServer, msg.sortState);
|
||||
await this.showResults(this._displayedQuery, WebviewReveal.NotForced, true);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assertNever(msg);
|
||||
}
|
||||
|
@ -223,7 +234,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
return;
|
||||
}
|
||||
|
||||
const interpretation = await this.interpretResultsInfo(results.query);
|
||||
const interpretation = await this.interpretResultsInfo(results.query, results.interpretedResultsSortState);
|
||||
|
||||
const sortedResultsMap: SortedResultsMap = {};
|
||||
results.sortedResultsInfo.forEach((v, k) =>
|
||||
|
@ -268,7 +279,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
});
|
||||
}
|
||||
|
||||
private async getTruncatedResults(metadata: QueryMetadata | undefined, resultsPaths: ResultsPaths, sourceInfo: cli.SourceInfo | undefined, sourceLocationPrefix: string): Promise<Interpretation> {
|
||||
private async getTruncatedResults(metadata: QueryMetadata | undefined, resultsPaths: ResultsPaths, sourceInfo: cli.SourceInfo | undefined, sourceLocationPrefix: string, sortState: InterpretedResultsSortState): Promise<Interpretation> {
|
||||
const sarif = await interpretResults(this.cliServer, metadata, resultsPaths.resultsPath, sourceInfo);
|
||||
// For performance reasons, limit the number of results we try
|
||||
// to serialize and send to the webview. TODO: possibly also
|
||||
|
@ -285,11 +296,10 @@ export class InterfaceManager extends DisposableObject {
|
|||
}
|
||||
}
|
||||
});
|
||||
return { sarif, sourceLocationPrefix, numTruncatedResults };
|
||||
;
|
||||
return { sarif, sourceLocationPrefix, numTruncatedResults, sortState };
|
||||
}
|
||||
|
||||
private async interpretResultsInfo(query: QueryInfo): Promise<Interpretation | undefined> {
|
||||
private async interpretResultsInfo(query: QueryInfo, sortState: InterpretedResultsSortState): Promise<Interpretation | undefined> {
|
||||
let interpretation: Interpretation | undefined = undefined;
|
||||
if (await query.hasInterpretedResults()
|
||||
&& query.quickEvalPosition === undefined // never do results interpretation if quickEval
|
||||
|
@ -300,7 +310,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
const sourceInfo = sourceArchiveUri === undefined ?
|
||||
undefined :
|
||||
{ sourceArchive: sourceArchiveUri.fsPath, sourceLocationPrefix };
|
||||
interpretation = await this.getTruncatedResults(query.metadata, query.resultsPaths, sourceInfo, sourceLocationPrefix);
|
||||
interpretation = await this.getTruncatedResults(query.metadata, query.resultsPaths, sourceInfo, sourceLocationPrefix, sortState);
|
||||
}
|
||||
catch (e) {
|
||||
// If interpretation fails, accept the error and continue
|
||||
|
@ -318,7 +328,13 @@ export class InterfaceManager extends DisposableObject {
|
|||
const sourceInfo = sourceArchiveUri === undefined ?
|
||||
undefined :
|
||||
{ sourceArchive: sourceArchiveUri.fsPath, sourceLocationPrefix };
|
||||
const interpretation = await this.getTruncatedResults(metadata, resultsInfo, sourceInfo, sourceLocationPrefix);
|
||||
const interpretation = await this.getTruncatedResults(
|
||||
metadata,
|
||||
resultsInfo,
|
||||
sourceInfo,
|
||||
sourceLocationPrefix,
|
||||
{ sortBy: 'file-position' } // sort order doesn't matter for showing diagnostics in parallel
|
||||
);
|
||||
|
||||
try {
|
||||
await this.showProblemResultsAsDiagnostics(interpretation, database);
|
||||
|
|
|
@ -5,7 +5,7 @@ import * as cli from './cli';
|
|||
import * as sarif from 'sarif';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { SortState, SortedResultSetInfo, DatabaseInfo, QueryMetadata } from "./interface-types";
|
||||
import { RawResultsSortState, SortedResultSetInfo, DatabaseInfo, QueryMetadata, InterpretedResultsSortState } from "./interface-types";
|
||||
import { QueryHistoryConfig } from "./config";
|
||||
import { QueryHistoryItemOptions } from "./query-history";
|
||||
|
||||
|
@ -15,11 +15,19 @@ export class CompletedQuery implements QueryWithResults {
|
|||
readonly result: messages.EvaluationResult;
|
||||
readonly database: DatabaseInfo;
|
||||
options: QueryHistoryItemOptions;
|
||||
|
||||
/**
|
||||
* Map from result set name to SortedResultSetInfo.
|
||||
*/
|
||||
sortedResultsInfo: Map<string, SortedResultSetInfo>;
|
||||
|
||||
/*
|
||||
* How we're currently sorting alerts. This is not mere interface
|
||||
* state due to truncation; on re-sort, we want to read in the file
|
||||
* again, sort it, and only ship off a reasonable number of results
|
||||
* to the webview.
|
||||
*/
|
||||
interpretedResultsSortState: InterpretedResultsSortState = { sortBy: 'file-position' };
|
||||
|
||||
constructor(
|
||||
evalaution: QueryWithResults,
|
||||
|
@ -92,7 +100,8 @@ export class CompletedQuery implements QueryWithResults {
|
|||
toString(): string {
|
||||
return this.interpolate(this.getLabel());
|
||||
}
|
||||
async updateSortState(server: cli.CodeQLCliServer, resultSetName: string, sortState: SortState | undefined): Promise<void> {
|
||||
|
||||
async updateSortState(server: cli.CodeQLCliServer, resultSetName: string, sortState: RawResultsSortState | undefined): Promise<void> {
|
||||
if (sortState === undefined) {
|
||||
this.sortedResultsInfo.delete(resultSetName);
|
||||
return;
|
||||
|
@ -107,6 +116,9 @@ export class CompletedQuery implements QueryWithResults {
|
|||
this.sortedResultsInfo.set(resultSetName, sortedResultSetInfo);
|
||||
}
|
||||
|
||||
async updateInterpretedSortState(_server: cli.CodeQLCliServer, _sortState: InterpretedResultsSortState | undefined): Promise<void> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -2,11 +2,11 @@ import * as React from "react";
|
|||
import { renderLocation, ResultTableProps, zebraStripe, className } from "./result-table-utils";
|
||||
import { RawTableResultSet, ResultValue, vscode } from "./results";
|
||||
import { assertNever } from "../helpers-pure";
|
||||
import { SortDirection, SortState, RAW_RESULTS_LIMIT } from "../interface-types";
|
||||
import { SortDirection, RAW_RESULTS_LIMIT, RawResultsSortState } from "../interface-types";
|
||||
|
||||
export type RawTableProps = ResultTableProps & {
|
||||
resultSet: RawTableResultSet,
|
||||
sortState?: SortState;
|
||||
sortState?: RawResultsSortState;
|
||||
};
|
||||
|
||||
export class RawTable extends React.Component<RawTableProps, {}> {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as React from 'react';
|
||||
import { LocationValue, ResolvableLocationValue, tryGetResolvableLocation } from 'semmle-bqrs';
|
||||
import { SortState, QueryMetadata } from '../interface-types';
|
||||
import { RawResultsSortState, QueryMetadata } from '../interface-types';
|
||||
import { ResultSet, vscode } from './results';
|
||||
|
||||
export interface ResultTableProps {
|
||||
|
@ -8,7 +8,7 @@ export interface ResultTableProps {
|
|||
databaseUri: string;
|
||||
metadata?: QueryMetadata
|
||||
resultsPath: string | undefined;
|
||||
sortState?: SortState;
|
||||
sortState?: RawResultsSortState;
|
||||
}
|
||||
|
||||
export const className = 'vscode-codeql__result-table';
|
||||
|
@ -80,6 +80,6 @@ export function zebraStripe(index: number, ...otherClasses: string[]): { classNa
|
|||
*/
|
||||
export function selectableZebraStripe(isSelected: boolean, index: number, ...otherClasses: string[]): { className: string } {
|
||||
return isSelected
|
||||
? { className: [selectedRowClassName, ...otherClasses].join(' ') }
|
||||
: zebraStripe(index, ...otherClasses)
|
||||
? { className: [selectedRowClassName, ...otherClasses].join(' ') }
|
||||
: zebraStripe(index, ...otherClasses)
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import { DatabaseInfo, Interpretation, SortState, QueryMetadata, ResultsPaths } from '../interface-types';
|
||||
import { DatabaseInfo, Interpretation, RawResultsSortState, QueryMetadata, ResultsPaths } from '../interface-types';
|
||||
import { PathTable } from './alert-table';
|
||||
import { RawTable } from './raw-results-table';
|
||||
import { ResultTableProps, tableSelectionHeaderClassName, toggleDiagnosticsClassName } from './result-table-utils';
|
||||
|
@ -12,10 +12,10 @@ export interface ResultTablesProps {
|
|||
rawResultSets: readonly ResultSet[];
|
||||
interpretation: Interpretation | undefined;
|
||||
database: DatabaseInfo;
|
||||
metadata? : QueryMetadata
|
||||
resultsPath: string ;
|
||||
metadata?: QueryMetadata
|
||||
resultsPath: string;
|
||||
origResultsPaths: ResultsPaths;
|
||||
sortStates: Map<string, SortState>;
|
||||
sortStates: Map<string, RawResultsSortState>;
|
||||
isLoadingNewResults: boolean;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import * as Rdom from 'react-dom';
|
|||
import * as bqrs from 'semmle-bqrs';
|
||||
import { ElementBase, LocationValue, PrimitiveColumnValue, PrimitiveTypeKind, ResultSetSchema, tryGetResolvableLocation } from 'semmle-bqrs';
|
||||
import { assertNever } from '../helpers-pure';
|
||||
import { DatabaseInfo, FromResultsViewMsg, Interpretation, IntoResultsViewMsg, SortedResultSetInfo, SortState, NavigatePathMsg, QueryMetadata, ResultsPaths } from '../interface-types';
|
||||
import { DatabaseInfo, FromResultsViewMsg, Interpretation, IntoResultsViewMsg, SortedResultSetInfo, RawResultsSortState, NavigatePathMsg, QueryMetadata, ResultsPaths } from '../interface-types';
|
||||
import { ResultTables } from './result-tables';
|
||||
import { EventHandlers as EventHandlerList } from './event-handler-list';
|
||||
|
||||
|
@ -140,7 +140,7 @@ interface ResultsInfo {
|
|||
|
||||
interface Results {
|
||||
resultSets: readonly ResultSet[];
|
||||
sortStates: Map<string, SortState>;
|
||||
sortStates: Map<string, RawResultsSortState>;
|
||||
database: DatabaseInfo;
|
||||
}
|
||||
|
||||
|
@ -298,7 +298,7 @@ class App extends React.Component<{}, ResultsViewState> {
|
|||
}));
|
||||
}
|
||||
|
||||
private getSortStates(resultsInfo: ResultsInfo): Map<string, SortState> {
|
||||
private getSortStates(resultsInfo: ResultsInfo): Map<string, RawResultsSortState> {
|
||||
const entries = Array.from(resultsInfo.sortedResultsMap.entries());
|
||||
return new Map(entries.map(([key, sortedResultSetInfo]) =>
|
||||
[key, sortedResultSetInfo.sortState]));
|
||||
|
@ -340,4 +340,4 @@ Rdom.render(
|
|||
document.getElementById('root')
|
||||
);
|
||||
|
||||
vscode.postMessage({ t: "resultViewLoaded" })
|
||||
vscode.postMessage({ t: "resultViewLoaded" })
|
||||
|
|
Загрузка…
Ссылка в новой задаче