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:
Jason Reed 2020-02-11 16:56:41 -05:00
Родитель 81a6b23e81
Коммит d135507a77
7 изменённых файлов: 77 добавлений и 34 удалений

Просмотреть файл

@ -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" })