Switch back to computing the file names in one place.
This commit is contained in:
Родитель
29f6ec9996
Коммит
bd4f56e90f
|
@ -37,8 +37,9 @@ export interface Interpretation {
|
|||
sarif: sarif.Log;
|
||||
}
|
||||
|
||||
export interface ResultsInfo {
|
||||
export interface ResultsPaths {
|
||||
resultsPath: string;
|
||||
interpretedResultsPath: string;
|
||||
}
|
||||
|
||||
export interface SortedResultSetInfo {
|
||||
|
@ -60,6 +61,7 @@ export interface ResultsUpdatingMsg {
|
|||
export interface SetStateMsg {
|
||||
t: 'setState';
|
||||
resultsPath: string;
|
||||
origResultsPaths: ResultsPaths;
|
||||
sortedResultsMap: SortedResultsMap;
|
||||
interpretation: undefined | Interpretation;
|
||||
database: DatabaseInfo;
|
||||
|
@ -94,7 +96,7 @@ interface ToggleDiagnostics {
|
|||
t: 'toggleDiagnostics';
|
||||
databaseUri: string;
|
||||
metadata?: QueryMetadata
|
||||
resultsPath: string;
|
||||
origResultsPaths: ResultsPaths;
|
||||
visible: boolean;
|
||||
kind?: string;
|
||||
};
|
||||
|
|
|
@ -6,13 +6,13 @@ import { parseSarifLocation, parseSarifPlainTextMessage } from './sarif-utils';
|
|||
import { FivePartLocation, LocationValue, ResolvableLocationValue, WholeFileLocation, tryGetResolvableLocation, LocationStyle } from 'semmle-bqrs';
|
||||
import { DisposableObject } from 'semmle-vscode-utils';
|
||||
import * as vscode from 'vscode';
|
||||
import { Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, languages, Location, Position, Range, Uri, window as Window, workspace } from 'vscode';
|
||||
import { Diagnostic, DiagnosticRelatedInformation, DiagnosticSeverity, languages, Location, Range, Uri, window as Window, workspace } from 'vscode';
|
||||
import { CodeQLCliServer } from './cli';
|
||||
import { DatabaseItem, DatabaseManager } from './databases';
|
||||
import * as helpers from './helpers';
|
||||
import { showAndLogErrorMessage } from './helpers';
|
||||
import { assertNever } from './helpers-pure';
|
||||
import { FromResultsViewMsg, Interpretation, IntoResultsViewMsg, ResultsInfo, SortedResultSetInfo, SortedResultsMap, INTERPRETED_RESULTS_PER_RUN_LIMIT, QueryMetadata } from './interface-types';
|
||||
import { FromResultsViewMsg, Interpretation, IntoResultsViewMsg, ResultsPaths, SortedResultSetInfo, SortedResultsMap, INTERPRETED_RESULTS_PER_RUN_LIMIT, QueryMetadata } from './interface-types';
|
||||
import { Logger } from './logging';
|
||||
import * as messages from './messages';
|
||||
import { EvaluationInfo, interpretResults, QueryInfo, tmpDir } from './queries';
|
||||
|
@ -166,7 +166,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
if (msg.visible) {
|
||||
const databaseItem = this.databaseManager.findDatabaseItem(Uri.parse(msg.databaseUri));
|
||||
if (databaseItem !== undefined) {
|
||||
await this.showResultsAsDiagnostics(msg.resultsPath, msg.metadata, databaseItem);
|
||||
await this.showResultsAsDiagnostics(msg.origResultsPaths, msg.metadata, databaseItem);
|
||||
}
|
||||
} else {
|
||||
// TODO: Only clear diagnostics on the same database.
|
||||
|
@ -223,7 +223,7 @@ export class InterfaceManager extends DisposableObject {
|
|||
return;
|
||||
}
|
||||
|
||||
const interpretation = await this.interpretResultsInfo(info.query, info.query.resultsInfo);
|
||||
const interpretation = await this.interpretResultsInfo(info.query, info.query.resultsPaths);
|
||||
|
||||
const sortedResultsMap: SortedResultsMap = {};
|
||||
info.query.sortedResultsInfo.forEach((v, k) =>
|
||||
|
@ -259,7 +259,8 @@ export class InterfaceManager extends DisposableObject {
|
|||
await this.postMessage({
|
||||
t: 'setState',
|
||||
interpretation,
|
||||
resultsPath: this.convertPathToWebviewUri(info.query.resultsInfo.resultsPath),
|
||||
origResultsPaths: info.query.resultsPaths,
|
||||
resultsPath: this.convertPathToWebviewUri(info.query.resultsPaths.resultsPath),
|
||||
sortedResultsMap,
|
||||
database: info.database,
|
||||
shouldKeepOldResultsWhileRendering,
|
||||
|
@ -267,8 +268,8 @@ export class InterfaceManager extends DisposableObject {
|
|||
});
|
||||
}
|
||||
|
||||
private async getTruncatedResults(metadata : QueryMetadata | undefined ,resultsPathOnDisk: string, sourceInfo : cli.SourceInfo | undefined, sourceLocationPrefix : string ) : Promise<Interpretation> {
|
||||
const sarif = await interpretResults(this.cliServer, metadata, resultsPathOnDisk, sourceInfo);
|
||||
private async getTruncatedResults(metadata : QueryMetadata | undefined ,resultsInfo: ResultsPaths, sourceInfo : cli.SourceInfo | undefined, sourceLocationPrefix : string ) : Promise<Interpretation> {
|
||||
const sarif = await interpretResults(this.cliServer, metadata, resultsInfo, sourceInfo);
|
||||
// For performance reasons, limit the number of results we try
|
||||
// to serialize and send to the webview. TODO: possibly also
|
||||
// limit number of paths per result, number of steps per path,
|
||||
|
@ -288,7 +289,7 @@ private async getTruncatedResults(metadata : QueryMetadata | undefined ,resultsP
|
|||
;
|
||||
}
|
||||
|
||||
private async interpretResultsInfo(query: QueryInfo, resultsInfo: ResultsInfo): Promise<Interpretation | undefined> {
|
||||
private async interpretResultsInfo(query: QueryInfo, resultsInfo: ResultsPaths): Promise<Interpretation | undefined> {
|
||||
let interpretation: Interpretation | undefined = undefined;
|
||||
if (query.hasInterpretedResults()
|
||||
&& query.quickEvalPosition === undefined // never do results interpretation if quickEval
|
||||
|
@ -299,7 +300,7 @@ private async getTruncatedResults(metadata : QueryMetadata | undefined ,resultsP
|
|||
const sourceInfo = sourceArchiveUri === undefined ?
|
||||
undefined :
|
||||
{ sourceArchive: sourceArchiveUri.fsPath, sourceLocationPrefix };
|
||||
interpretation = await this.getTruncatedResults(query.metadata, resultsInfo.resultsPath, sourceInfo, sourceLocationPrefix);
|
||||
interpretation = await this.getTruncatedResults(query.metadata, resultsInfo, sourceInfo, sourceLocationPrefix);
|
||||
}
|
||||
catch (e) {
|
||||
// If interpretation fails, accept the error and continue
|
||||
|
@ -311,15 +312,13 @@ private async getTruncatedResults(metadata : QueryMetadata | undefined ,resultsP
|
|||
}
|
||||
|
||||
|
||||
private async showResultsAsDiagnostics(webviewResultsUri: string, metadata: QueryMetadata | undefined, database: DatabaseItem) {
|
||||
// URIs from the webview have the vscode-resource scheme, so convert into a filesystem URI first.
|
||||
const resultsPathOnDisk = webviewUriToFileUri(webviewResultsUri).fsPath;
|
||||
private async showResultsAsDiagnostics(resultsInfo: ResultsPaths, metadata: QueryMetadata | undefined, database: DatabaseItem) {
|
||||
const sourceLocationPrefix = await database.getSourceLocationPrefix(this.cliServer);
|
||||
const sourceArchiveUri = database.sourceArchive;
|
||||
const sourceInfo = sourceArchiveUri === undefined ?
|
||||
undefined :
|
||||
{ sourceArchive: sourceArchiveUri.fsPath, sourceLocationPrefix };
|
||||
const interpretation = await this.getTruncatedResults(metadata, resultsPathOnDisk, sourceInfo, sourceLocationPrefix);
|
||||
const interpretation = await this.getTruncatedResults(metadata, resultsInfo, sourceInfo, sourceLocationPrefix);
|
||||
|
||||
try {
|
||||
await this.showProblemResultsAsDiagnostics(interpretation, database);
|
||||
|
|
|
@ -7,7 +7,7 @@ import * as vscode from 'vscode';
|
|||
import * as cli from './cli';
|
||||
import { DatabaseItem, getUpgradesDirectories } from './databases';
|
||||
import * as helpers from './helpers';
|
||||
import { DatabaseInfo, SortState, ResultsInfo, SortedResultSetInfo, QueryMetadata } from './interface-types';
|
||||
import { DatabaseInfo, SortState, ResultsPaths, SortedResultSetInfo, QueryMetadata } from './interface-types';
|
||||
import { logger } from './logging';
|
||||
import * as messages from './messages';
|
||||
import * as qsClient from './queryserver-client';
|
||||
|
@ -50,7 +50,7 @@ export class UserCancellationException extends Error { }
|
|||
*/
|
||||
export class QueryInfo {
|
||||
compiledQueryPath: string;
|
||||
resultsInfo: ResultsInfo;
|
||||
resultsPaths: ResultsPaths;
|
||||
private static nextQueryId = 0;
|
||||
|
||||
/**
|
||||
|
@ -68,7 +68,8 @@ export class QueryInfo {
|
|||
) {
|
||||
this.queryId = QueryInfo.nextQueryId++;
|
||||
this.compiledQueryPath = path.join(tmpDir.name, `compiledQuery${this.queryId}.qlo`);
|
||||
this.resultsInfo = {
|
||||
this.resultsPaths = {
|
||||
interpretedResultsPath: path.join(tmpDir.name, `interpretedResults${this.queryId}.sarif`),
|
||||
resultsPath: path.join(tmpDir.name, `results${this.queryId}.bqrs`),
|
||||
};
|
||||
this.sortedResultsInfo = new Map();
|
||||
|
@ -86,7 +87,7 @@ export class QueryInfo {
|
|||
const callbackId = qs.registerCallback(res => { result = res });
|
||||
|
||||
const queryToRun: messages.QueryToRun = {
|
||||
resultsPath: this.resultsInfo.resultsPath,
|
||||
resultsPath: this.resultsPaths.resultsPath,
|
||||
qlo: vscode.Uri.file(this.compiledQueryPath).toString(),
|
||||
allowUnknownTemplates: true,
|
||||
id: callbackId,
|
||||
|
@ -177,7 +178,7 @@ export class QueryInfo {
|
|||
sortState
|
||||
};
|
||||
|
||||
await server.sortBqrs(this.resultsInfo.resultsPath, sortedResultSetInfo.resultsPath, resultSetName, [sortState.columnIndex], [sortState.direction]);
|
||||
await server.sortBqrs(this.resultsPaths.resultsPath, sortedResultSetInfo.resultsPath, resultSetName, [sortState.columnIndex], [sortState.direction]);
|
||||
this.sortedResultsInfo.set(resultSetName, sortedResultSetInfo);
|
||||
}
|
||||
}
|
||||
|
@ -185,11 +186,10 @@ export class QueryInfo {
|
|||
/**
|
||||
* Call cli command to interpret results.
|
||||
*/
|
||||
export async function interpretResults(server: cli.CodeQLCliServer, metadata: QueryMetadata | undefined, resultsPath: string, sourceInfo?: cli.SourceInfo): Promise<sarif.Log> {
|
||||
const interpretedResultsPath = resultsPath + ".interpreted.sarif"
|
||||
export async function interpretResults(server: cli.CodeQLCliServer, metadata: QueryMetadata | undefined, resultsInfo: ResultsPaths, sourceInfo?: cli.SourceInfo): Promise<sarif.Log> {
|
||||
|
||||
if (await fs.pathExists(interpretedResultsPath)) {
|
||||
return JSON.parse(await fs.readFile(interpretedResultsPath, 'utf8'));
|
||||
if (await fs.pathExists(resultsInfo.interpretedResultsPath)) {
|
||||
return JSON.parse(await fs.readFile(resultsInfo.interpretedResultsPath, 'utf8'));
|
||||
}
|
||||
if (metadata == undefined) {
|
||||
throw new Error('Can\'t interpret results without query metadata');
|
||||
|
@ -203,7 +203,7 @@ export async function interpretResults(server: cli.CodeQLCliServer, metadata: Qu
|
|||
// SARIF format does, so in the absence of one, we use a dummy id.
|
||||
id = "dummy-id";
|
||||
}
|
||||
return await server.interpretBqrs( { kind, id }, resultsPath, interpretedResultsPath, sourceInfo);
|
||||
return await server.interpretBqrs( { kind, id }, resultsInfo.resultsPath, resultsInfo.interpretedResultsPath, sourceInfo);
|
||||
}
|
||||
|
||||
export interface EvaluationInfo {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import * as React from 'react';
|
||||
import { DatabaseInfo, Interpretation, SortState, QueryMetadata } from '../interface-types';
|
||||
import { DatabaseInfo, Interpretation, SortState, QueryMetadata, ResultsPaths } from '../interface-types';
|
||||
import { PathTable } from './alert-table';
|
||||
import { RawTable } from './raw-results-table';
|
||||
import { ResultTableProps, tableSelectionHeaderClassName, toggleDiagnosticsClassName } from './result-table-utils';
|
||||
|
@ -13,7 +13,8 @@ export interface ResultTablesProps {
|
|||
interpretation: Interpretation | undefined;
|
||||
database: DatabaseInfo;
|
||||
metadata? : QueryMetadata
|
||||
resultsPath: string | undefined;
|
||||
resultsPath: string ;
|
||||
origResultsPaths: ResultsPaths;
|
||||
sortStates: Map<string, SortState>;
|
||||
isLoadingNewResults: boolean;
|
||||
}
|
||||
|
@ -95,7 +96,7 @@ export class ResultTables
|
|||
render(): React.ReactNode {
|
||||
const { selectedTable } = this.state;
|
||||
const resultSets = this.getResultSets();
|
||||
const { database, resultsPath, metadata } = this.props;
|
||||
const { database, resultsPath, metadata, origResultsPaths } = this.props;
|
||||
|
||||
// Only show the Problems view display checkbox for the alerts table.
|
||||
const diagnosticsCheckBox = selectedTable === ALERTS_TABLE_NAME ?
|
||||
|
@ -104,7 +105,7 @@ export class ResultTables
|
|||
if (resultsPath !== undefined) {
|
||||
vscode.postMessage({
|
||||
t: 'toggleDiagnostics',
|
||||
resultsPath: resultsPath,
|
||||
origResultsPaths: origResultsPaths,
|
||||
databaseUri: database.databaseUri,
|
||||
visible: e.target.checked,
|
||||
metadata: metadata
|
||||
|
|
|
@ -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 } from '../interface-types';
|
||||
import { DatabaseInfo, FromResultsViewMsg, Interpretation, IntoResultsViewMsg, SortedResultSetInfo, SortState, NavigatePathMsg, QueryMetadata, ResultsPaths } from '../interface-types';
|
||||
import { ResultTables } from './result-tables';
|
||||
import { EventHandlers as EventHandlerList } from './event-handler-list';
|
||||
|
||||
|
@ -127,6 +127,7 @@ async function parseResultSets(response: Response): Promise<readonly ResultSet[]
|
|||
|
||||
interface ResultsInfo {
|
||||
resultsPath: string;
|
||||
origResultsPaths: ResultsPaths;
|
||||
database: DatabaseInfo;
|
||||
interpretation: Interpretation | undefined;
|
||||
sortedResultsMap: Map<string, SortedResultSetInfo>;
|
||||
|
@ -186,6 +187,7 @@ class App extends React.Component<{}, ResultsViewState> {
|
|||
case 'setState':
|
||||
this.updateStateWithNewResultsInfo({
|
||||
resultsPath: msg.resultsPath,
|
||||
origResultsPaths: msg.origResultsPaths,
|
||||
sortedResultsMap: new Map(Object.entries(msg.sortedResultsMap)),
|
||||
database: msg.database,
|
||||
interpretation: msg.interpretation,
|
||||
|
@ -304,11 +306,12 @@ class App extends React.Component<{}, ResultsViewState> {
|
|||
|
||||
render() {
|
||||
const displayedResults = this.state.displayedResults;
|
||||
if (displayedResults.results !== null) {
|
||||
if (displayedResults.results !== null && displayedResults.resultsInfo !== null) {
|
||||
return <ResultTables rawResultSets={displayedResults.results.resultSets}
|
||||
interpretation={displayedResults.resultsInfo ? displayedResults.resultsInfo.interpretation : undefined}
|
||||
database={displayedResults.results.database}
|
||||
resultsPath={displayedResults.resultsInfo ? displayedResults.resultsInfo.resultsPath : undefined}
|
||||
origResultsPaths={displayedResults.resultsInfo.origResultsPaths}
|
||||
resultsPath={displayedResults.resultsInfo.resultsPath}
|
||||
metadata={displayedResults.resultsInfo ? displayedResults.resultsInfo.metadata : undefined}
|
||||
sortStates={displayedResults.results.sortStates}
|
||||
isLoadingNewResults={this.state.isExpectingResultsUpdate || this.state.nextResultsInfo !== null} />;
|
||||
|
|
Загрузка…
Ссылка в новой задаче