Introduce data models and refactor mapper
This commit is contained in:
@@ -172,10 +172,6 @@ async function runQuery(
|
||||
*/
|
||||
export class QueryInProgress {
|
||||
public queryEvalInfo: QueryEvaluationInfo;
|
||||
/**
|
||||
* Note that in the {@link readQueryHistoryFromFile} method, we create a QueryEvaluationInfo instance
|
||||
* by explicitly setting the prototype in order to avoid calling this constructor.
|
||||
*/
|
||||
constructor(
|
||||
readonly querySaveDir: string,
|
||||
readonly dbItemPath: string,
|
||||
|
||||
105
extensions/ql-vscode/src/query-history/store/data-mapper.ts
Normal file
105
extensions/ql-vscode/src/query-history/store/data-mapper.ts
Normal file
@@ -0,0 +1,105 @@
|
||||
import {
|
||||
LocalQueryInfo,
|
||||
CompletedQueryInfo,
|
||||
InitialQueryInfo,
|
||||
} from "../../query-results";
|
||||
import { QueryEvaluationInfo } from "../../run-queries-shared";
|
||||
import { QueryHistoryInfo } from "../query-history-info";
|
||||
import { VariantAnalysisHistoryItem } from "../variant-analysis-history-item";
|
||||
import {
|
||||
CompletedQueryInfoData,
|
||||
QueryEvaluationInfoData,
|
||||
InitialQueryInfoData,
|
||||
LocalQueryDataItem,
|
||||
} from "./local-query-data-item";
|
||||
import { QueryHistoryDataItem } from "./query-history-data";
|
||||
|
||||
// Maps Query History Data Models to Domain Models
|
||||
|
||||
export function mapQueryHistoryToDomainModels(
|
||||
queries: QueryHistoryDataItem[],
|
||||
): QueryHistoryInfo[] {
|
||||
return queries.map((d) => {
|
||||
if (d.t === "variant-analysis") {
|
||||
const query: VariantAnalysisHistoryItem = d;
|
||||
return query;
|
||||
} else if (d.t === "local") {
|
||||
return mapLocalQueryDataItemToDomainModel(d);
|
||||
}
|
||||
|
||||
throw Error(
|
||||
`Unexpected or corrupted query history file. Unknown query history item: ${JSON.stringify(
|
||||
d,
|
||||
)}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
function mapLocalQueryDataItemToDomainModel(
|
||||
localQuery: LocalQueryDataItem,
|
||||
): LocalQueryInfo {
|
||||
return new LocalQueryInfo(
|
||||
mapInitialQueryInfoDataToDomainModel(localQuery.initialInfo),
|
||||
undefined,
|
||||
localQuery.failureReason,
|
||||
localQuery.completedQuery &&
|
||||
mapCompletedQueryInfoDataToDomainModel(localQuery.completedQuery),
|
||||
localQuery.evalLogLocation,
|
||||
localQuery.evalLogSummaryLocation,
|
||||
localQuery.jsonEvalLogSummaryLocation,
|
||||
localQuery.evalLogSummarySymbolsLocation,
|
||||
);
|
||||
}
|
||||
|
||||
function mapCompletedQueryInfoDataToDomainModel(
|
||||
completedQuery: CompletedQueryInfoData,
|
||||
): CompletedQueryInfo {
|
||||
return new CompletedQueryInfo(
|
||||
mapQueryEvaluationInfoDataToDomainModel(completedQuery.query),
|
||||
{
|
||||
runId: completedQuery.result.runId,
|
||||
queryId: completedQuery.result.queryId,
|
||||
resultType: completedQuery.result.resultType,
|
||||
evaluationTime: completedQuery.result.evaluationTime,
|
||||
message: completedQuery.result.message,
|
||||
logFileLocation: completedQuery.result.logFileLocation,
|
||||
},
|
||||
completedQuery.logFileLocation,
|
||||
completedQuery.successful ?? completedQuery.sucessful,
|
||||
completedQuery.message,
|
||||
completedQuery.interpretedResultsSortState,
|
||||
completedQuery.resultCount,
|
||||
completedQuery.sortedResultsInfo,
|
||||
);
|
||||
}
|
||||
|
||||
function mapInitialQueryInfoDataToDomainModel(
|
||||
initialInfo: InitialQueryInfoData,
|
||||
): InitialQueryInfo {
|
||||
return {
|
||||
userSpecifiedLabel: initialInfo.userSpecifiedLabel,
|
||||
queryText: initialInfo.queryText,
|
||||
isQuickQuery: initialInfo.isQuickQuery,
|
||||
isQuickEval: initialInfo.isQuickEval,
|
||||
quickEvalPosition: initialInfo.quickEvalPosition,
|
||||
queryPath: initialInfo.queryPath,
|
||||
databaseInfo: {
|
||||
databaseUri: initialInfo.databaseInfo.databaseUri,
|
||||
name: initialInfo.databaseInfo.name,
|
||||
},
|
||||
start: new Date(initialInfo.start),
|
||||
id: initialInfo.id,
|
||||
};
|
||||
}
|
||||
|
||||
function mapQueryEvaluationInfoDataToDomainModel(
|
||||
evaluationInfo: QueryEvaluationInfoData,
|
||||
): QueryEvaluationInfo {
|
||||
return new QueryEvaluationInfo(
|
||||
evaluationInfo.querySaveDir,
|
||||
evaluationInfo.dbItemPath,
|
||||
evaluationInfo.databaseHasMetadataFile,
|
||||
evaluationInfo.quickEvalPosition,
|
||||
evaluationInfo.metadata,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
import { assertNever } from "../../pure/helpers-pure";
|
||||
import { LocalQueryInfo, InitialQueryInfo } from "../../query-results";
|
||||
import { QueryEvaluationInfo } from "../../run-queries-shared";
|
||||
import { QueryHistoryInfo } from "../query-history-info";
|
||||
import {
|
||||
LocalQueryDataItem,
|
||||
InitialQueryInfoData,
|
||||
QueryEvaluationInfoData,
|
||||
} from "./local-query-data-item";
|
||||
import { QueryHistoryDataItem } from "./query-history-data";
|
||||
import { VariantAnalysisDataItem } from "./variant-analysis-data-item";
|
||||
|
||||
// Maps Query History Domain Models to Data Models
|
||||
|
||||
export function mapQueryHistoryToDataModels(
|
||||
queries: QueryHistoryInfo[],
|
||||
): QueryHistoryDataItem[] {
|
||||
return queries.map((q) => {
|
||||
if (q.t === "variant-analysis") {
|
||||
const query: VariantAnalysisDataItem = q;
|
||||
return query;
|
||||
} else if (q.t === "local") {
|
||||
return mapLocalQueryInfoToDataModel(q);
|
||||
} else {
|
||||
assertNever(q);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function mapLocalQueryInfoToDataModel(
|
||||
query: LocalQueryInfo,
|
||||
): LocalQueryDataItem {
|
||||
return {
|
||||
initialInfo: mapInitialQueryInfoToDataModel(query.initialInfo),
|
||||
t: "local",
|
||||
evalLogLocation: query.evalLogLocation,
|
||||
evalLogSummaryLocation: query.evalLogSummaryLocation,
|
||||
jsonEvalLogSummaryLocation: query.jsonEvalLogSummaryLocation,
|
||||
evalLogSummarySymbolsLocation: query.evalLogSummarySymbolsLocation,
|
||||
failureReason: query.failureReason,
|
||||
completedQuery: query.completedQuery && {
|
||||
query: mapQueryEvaluationInfoToDataModel(query.completedQuery.query),
|
||||
result: {
|
||||
runId: query.completedQuery.result.runId,
|
||||
queryId: query.completedQuery.result.queryId,
|
||||
resultType: query.completedQuery.result.resultType,
|
||||
evaluationTime: query.completedQuery.result.evaluationTime,
|
||||
message: query.completedQuery.result.message,
|
||||
logFileLocation: query.completedQuery.result.logFileLocation,
|
||||
},
|
||||
logFileLocation: query.completedQuery.logFileLocation,
|
||||
successful: query.completedQuery.successful,
|
||||
message: query.completedQuery.message,
|
||||
resultCount: query.completedQuery.resultCount,
|
||||
sortedResultsInfo: query.completedQuery.sortedResultsInfo,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function mapInitialQueryInfoToDataModel(
|
||||
localQueryInitialInfo: InitialQueryInfo,
|
||||
): InitialQueryInfoData {
|
||||
return {
|
||||
userSpecifiedLabel: localQueryInitialInfo.userSpecifiedLabel,
|
||||
queryText: localQueryInitialInfo.queryText,
|
||||
isQuickQuery: localQueryInitialInfo.isQuickQuery,
|
||||
isQuickEval: localQueryInitialInfo.isQuickEval,
|
||||
quickEvalPosition: localQueryInitialInfo.quickEvalPosition,
|
||||
queryPath: localQueryInitialInfo.queryPath,
|
||||
databaseInfo: {
|
||||
databaseUri: localQueryInitialInfo.databaseInfo.databaseUri,
|
||||
name: localQueryInitialInfo.databaseInfo.name,
|
||||
},
|
||||
start: localQueryInitialInfo.start,
|
||||
id: localQueryInitialInfo.id,
|
||||
};
|
||||
}
|
||||
|
||||
function mapQueryEvaluationInfoToDataModel(
|
||||
queryEvaluationInfo: QueryEvaluationInfo,
|
||||
): QueryEvaluationInfoData {
|
||||
return {
|
||||
querySaveDir: queryEvaluationInfo.querySaveDir,
|
||||
dbItemPath: queryEvaluationInfo.dbItemPath,
|
||||
databaseHasMetadataFile: queryEvaluationInfo.databaseHasMetadataFile,
|
||||
quickEvalPosition: queryEvaluationInfo.quickEvalPosition,
|
||||
metadata: queryEvaluationInfo.metadata,
|
||||
resultsPaths: queryEvaluationInfo.resultsPaths,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
export interface LocalQueryDataItem {
|
||||
initialInfo: InitialQueryInfoData;
|
||||
t: "local";
|
||||
evalLogLocation?: string;
|
||||
evalLogSummaryLocation?: string;
|
||||
jsonEvalLogSummaryLocation?: string;
|
||||
evalLogSummarySymbolsLocation?: string;
|
||||
completedQuery?: CompletedQueryInfoData;
|
||||
failureReason?: string;
|
||||
}
|
||||
|
||||
export interface InitialQueryInfoData {
|
||||
userSpecifiedLabel?: string;
|
||||
queryText: string;
|
||||
isQuickQuery: boolean;
|
||||
isQuickEval: boolean;
|
||||
quickEvalPosition?: PositionData;
|
||||
queryPath: string;
|
||||
databaseInfo: DatabaseInfoData;
|
||||
start: Date;
|
||||
id: string;
|
||||
}
|
||||
|
||||
interface DatabaseInfoData {
|
||||
name: string;
|
||||
databaseUri: string;
|
||||
}
|
||||
|
||||
interface PositionData {
|
||||
line: number;
|
||||
column: number;
|
||||
endLine: number;
|
||||
endColumn: number;
|
||||
fileName: string;
|
||||
}
|
||||
|
||||
export interface CompletedQueryInfoData {
|
||||
query: QueryEvaluationInfoData;
|
||||
message?: string;
|
||||
successful?: boolean;
|
||||
|
||||
// There once was a typo in the data model, which is why we need to support both
|
||||
sucessful?: boolean;
|
||||
result: EvaluationResultData;
|
||||
logFileLocation?: string;
|
||||
resultCount: number;
|
||||
sortedResultsInfo: Record<string, SortedResultSetInfo>;
|
||||
interpretedResultsSortState?: InterpretedResultsSortState;
|
||||
}
|
||||
|
||||
interface InterpretedResultsSortState {
|
||||
sortBy: InterpretedResultsSortColumn;
|
||||
sortDirection: SortDirection;
|
||||
}
|
||||
|
||||
type InterpretedResultsSortColumn = "alert-message";
|
||||
|
||||
interface SortedResultSetInfo {
|
||||
resultsPath: string;
|
||||
sortState: RawResultsSortState;
|
||||
}
|
||||
|
||||
interface RawResultsSortState {
|
||||
columnIndex: number;
|
||||
sortDirection: SortDirection;
|
||||
}
|
||||
|
||||
enum SortDirection {
|
||||
asc,
|
||||
desc,
|
||||
}
|
||||
|
||||
interface EvaluationResultData {
|
||||
runId: number;
|
||||
queryId: number;
|
||||
resultType: number;
|
||||
evaluationTime: number;
|
||||
message?: string;
|
||||
logFileLocation?: string;
|
||||
}
|
||||
|
||||
export interface QueryEvaluationInfoData {
|
||||
querySaveDir: string;
|
||||
dbItemPath: string;
|
||||
databaseHasMetadataFile: boolean;
|
||||
quickEvalPosition?: PositionData;
|
||||
metadata?: QueryMetadataData;
|
||||
resultsPaths: {
|
||||
resultsPath: string;
|
||||
interpretedResultsPath: string;
|
||||
};
|
||||
}
|
||||
|
||||
interface QueryMetadataData {
|
||||
name?: string;
|
||||
description?: string;
|
||||
id?: string;
|
||||
kind?: string;
|
||||
scored?: string;
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Contains models and consts for the data we want to store in the query history store.
|
||||
// Changes to these models should be done carefully and account for backwards compatibility of data.
|
||||
|
||||
import { LocalQueryDataItem } from "./local-query-data-item";
|
||||
import { VariantAnalysisDataItem } from "./variant-analysis-data-item";
|
||||
|
||||
export const ALLOWED_QUERY_HISTORY_VERSIONS = [1, 2];
|
||||
|
||||
export interface QueryHistoryData {
|
||||
version: number;
|
||||
queries: QueryHistoryDataItem[];
|
||||
}
|
||||
|
||||
export type QueryHistoryDataItem = LocalQueryDataItem | VariantAnalysisDataItem;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { pathExists, readFile, remove, mkdir, writeFile } from "fs-extra";
|
||||
import { pathExists, remove, mkdir, writeFile, readJson } from "fs-extra";
|
||||
import { dirname } from "path";
|
||||
|
||||
import { showAndLogExceptionWithTelemetry } from "../../helpers";
|
||||
@@ -8,11 +8,15 @@ import {
|
||||
getErrorMessage,
|
||||
getErrorStack,
|
||||
} from "../../pure/helpers-pure";
|
||||
import { CompletedQueryInfo, LocalQueryInfo } from "../../query-results";
|
||||
import { QueryHistoryInfo } from "../query-history-info";
|
||||
import { QueryEvaluationInfo } from "../../run-queries-shared";
|
||||
import { QueryResultType } from "../../pure/legacy-messages";
|
||||
import { redactableError } from "../../pure/errors";
|
||||
import {
|
||||
ALLOWED_QUERY_HISTORY_VERSIONS,
|
||||
QueryHistoryData,
|
||||
QueryHistoryDataItem,
|
||||
} from "./query-history-data";
|
||||
import { mapQueryHistoryToDomainModels } from "./data-mapper";
|
||||
import { mapQueryHistoryToDataModels } from "./domain-mapper";
|
||||
|
||||
export async function readQueryHistoryFromFile(
|
||||
fsPath: string,
|
||||
@@ -22,9 +26,11 @@ export async function readQueryHistoryFromFile(
|
||||
return [];
|
||||
}
|
||||
|
||||
const data = await readFile(fsPath, "utf8");
|
||||
const obj = JSON.parse(data);
|
||||
if (![1, 2].includes(obj.version)) {
|
||||
const obj: QueryHistoryData = await readJson(fsPath, {
|
||||
encoding: "utf8",
|
||||
});
|
||||
|
||||
if (!ALLOWED_QUERY_HISTORY_VERSIONS.includes(obj.version)) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
redactableError`Can't parse query history. Unsupported query history format: v${obj.version}.`,
|
||||
);
|
||||
@@ -32,61 +38,33 @@ export async function readQueryHistoryFromFile(
|
||||
}
|
||||
|
||||
const queries = obj.queries;
|
||||
const parsedQueries = queries
|
||||
// Remove remote queries, which are not supported anymore.
|
||||
.filter((q: QueryHistoryInfo | { t: "remote" }) => q.t !== "remote")
|
||||
.map((q: QueryHistoryInfo) => {
|
||||
// Need to explicitly set prototype since reading in from JSON will not
|
||||
// do this automatically. Note that we can't call the constructor here since
|
||||
// the constructor invokes extra logic that we don't want to do.
|
||||
if (q.t === "local") {
|
||||
Object.setPrototypeOf(q, LocalQueryInfo.prototype);
|
||||
// Remove remote queries, which are not supported anymore.
|
||||
const parsedQueries = queries.filter(
|
||||
(q: QueryHistoryDataItem | { t: "remote" }) => q.t !== "remote",
|
||||
);
|
||||
|
||||
// Date instances are serialized as strings. Need to
|
||||
// convert them back to Date instances.
|
||||
(q.initialInfo as any).start = new Date(q.initialInfo.start);
|
||||
if (q.completedQuery) {
|
||||
// Again, need to explicitly set prototypes.
|
||||
Object.setPrototypeOf(
|
||||
q.completedQuery,
|
||||
CompletedQueryInfo.prototype,
|
||||
);
|
||||
Object.setPrototypeOf(
|
||||
q.completedQuery.query,
|
||||
QueryEvaluationInfo.prototype,
|
||||
);
|
||||
|
||||
// Previously, there was a typo in the completedQuery type. There was a field
|
||||
// `sucessful` and it was renamed to `successful`. We need to handle this case.
|
||||
if ("sucessful" in q.completedQuery) {
|
||||
(q.completedQuery as any).successful = (
|
||||
q.completedQuery as any
|
||||
).sucessful;
|
||||
delete (q.completedQuery as any).sucessful;
|
||||
}
|
||||
|
||||
if (!("successful" in q.completedQuery)) {
|
||||
(q.completedQuery as any).successful =
|
||||
q.completedQuery.result?.resultType === QueryResultType.SUCCESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
return q;
|
||||
});
|
||||
// Map the data models to the domain models.
|
||||
const domainModels: QueryHistoryInfo[] =
|
||||
mapQueryHistoryToDomainModels(parsedQueries);
|
||||
|
||||
// filter out queries that have been deleted on disk
|
||||
// most likely another workspace has deleted them because the
|
||||
// queries aged out.
|
||||
return asyncFilter(parsedQueries, async (q) => {
|
||||
if (q.t === "variant-analysis") {
|
||||
// the deserializer doesn't know where the remote queries are stored
|
||||
// so we need to assume here that they exist. Later, we check to
|
||||
// see if they exist on disk.
|
||||
return true;
|
||||
}
|
||||
const resultsPath = q.completedQuery?.query.resultsPaths.resultsPath;
|
||||
return !!resultsPath && (await pathExists(resultsPath));
|
||||
});
|
||||
const filteredDomainModels: Promise<QueryHistoryInfo[]> = asyncFilter(
|
||||
domainModels,
|
||||
async (q) => {
|
||||
if (q.t === "variant-analysis") {
|
||||
// the query history store doesn't know where variant analysises are
|
||||
// stored so we need to assume here that they exist. We check later
|
||||
// to see if they exist on disk.
|
||||
return true;
|
||||
}
|
||||
const resultsPath = q.completedQuery?.query.resultsPaths.resultsPath;
|
||||
return !!resultsPath && (await pathExists(resultsPath));
|
||||
},
|
||||
);
|
||||
|
||||
return filteredDomainModels;
|
||||
} catch (e) {
|
||||
void showAndLogExceptionWithTelemetry(
|
||||
redactableError(asError(e))`Error loading query history.`,
|
||||
@@ -121,13 +99,17 @@ export async function writeQueryHistoryToFile(
|
||||
const filteredQueries = queries.filter((q) =>
|
||||
q.t === "local" ? q.completedQuery !== undefined : true,
|
||||
);
|
||||
|
||||
// map domain model queries to data model
|
||||
const queryHistoryData = mapQueryHistoryToDataModels(filteredQueries);
|
||||
|
||||
const data = JSON.stringify(
|
||||
{
|
||||
// version 2:
|
||||
// - adds the `variant-analysis` type
|
||||
// - ensures a `successful` property exists on completedQuery
|
||||
version: 2,
|
||||
queries: filteredQueries,
|
||||
queries: queryHistoryData,
|
||||
},
|
||||
null,
|
||||
2,
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
import { QueryLanguage } from "../../common/query-language";
|
||||
import { QueryStatus } from "../../query-status";
|
||||
import {
|
||||
VariantAnalysisFailureReason,
|
||||
VariantAnalysisRepoStatus,
|
||||
VariantAnalysisStatus,
|
||||
} from "../../variant-analysis/shared/variant-analysis";
|
||||
|
||||
// Data Model for Variant Analysis Query History Items
|
||||
// All data points are modelled, except enums.
|
||||
|
||||
export interface VariantAnalysisDataItem {
|
||||
readonly t: "variant-analysis";
|
||||
failureReason?: string;
|
||||
resultCount?: number;
|
||||
status: QueryStatus;
|
||||
completed: boolean;
|
||||
variantAnalysis: VariantAnalysisQueryHistoryData;
|
||||
userSpecifiedLabel?: string;
|
||||
}
|
||||
|
||||
export interface VariantAnalysisQueryHistoryData {
|
||||
id: number;
|
||||
controllerRepo: {
|
||||
id: number;
|
||||
fullName: string;
|
||||
private: boolean;
|
||||
};
|
||||
query: {
|
||||
name: string;
|
||||
filePath: string;
|
||||
language: QueryLanguage;
|
||||
text: string;
|
||||
};
|
||||
databases: {
|
||||
repositories?: string[];
|
||||
repositoryLists?: string[];
|
||||
repositoryOwners?: string[];
|
||||
};
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
executionStartTime: number;
|
||||
status: VariantAnalysisStatus;
|
||||
completedAt?: string;
|
||||
actionsWorkflowRunId?: number;
|
||||
failureReason?: VariantAnalysisFailureReason;
|
||||
scannedRepos?: VariantAnalysisScannedRepositoryData[];
|
||||
skippedRepos?: VariantAnalysisSkippedRepositoriesData;
|
||||
}
|
||||
|
||||
export interface VariantAnalysisScannedRepositoryData {
|
||||
repository: {
|
||||
id: number;
|
||||
fullName: string;
|
||||
private: boolean;
|
||||
stargazersCount: number;
|
||||
updatedAt: string | null;
|
||||
};
|
||||
analysisStatus: VariantAnalysisRepoStatus;
|
||||
resultCount?: number;
|
||||
artifactSizeInBytes?: number;
|
||||
failureMessage?: string;
|
||||
}
|
||||
|
||||
export interface VariantAnalysisSkippedRepositoriesData {
|
||||
accessMismatchRepos?: VariantAnalysisSkippedRepositoryGroupData;
|
||||
notFoundRepos?: VariantAnalysisSkippedRepositoryGroupData;
|
||||
noCodeqlDbRepos?: VariantAnalysisSkippedRepositoryGroupData;
|
||||
overLimitRepos?: VariantAnalysisSkippedRepositoryGroupData;
|
||||
}
|
||||
|
||||
export interface VariantAnalysisSkippedRepositoryGroupData {
|
||||
repositoryCount: number;
|
||||
repositories: VariantAnalysisSkippedRepositoryData[];
|
||||
}
|
||||
|
||||
export interface VariantAnalysisSkippedRepositoryData {
|
||||
id?: number;
|
||||
fullName: string;
|
||||
private?: boolean;
|
||||
stargazersCount?: number;
|
||||
updatedAt?: string | null;
|
||||
}
|
||||
@@ -49,45 +49,31 @@ export interface InitialQueryInfo {
|
||||
}
|
||||
|
||||
export class CompletedQueryInfo implements QueryWithResults {
|
||||
readonly query: QueryEvaluationInfo;
|
||||
readonly message?: string;
|
||||
readonly successful?: boolean;
|
||||
/**
|
||||
* The legacy result. This is only set when loading from the query history.
|
||||
*/
|
||||
readonly result: legacyMessages.EvaluationResult;
|
||||
readonly logFileLocation?: string;
|
||||
resultCount: number;
|
||||
constructor(
|
||||
public readonly query: QueryEvaluationInfo,
|
||||
|
||||
/**
|
||||
* Map from result set name to SortedResultSetInfo.
|
||||
*/
|
||||
sortedResultsInfo: Record<string, SortedResultSetInfo>;
|
||||
/**
|
||||
* The legacy result. This is only set when loading from the query history.
|
||||
*/
|
||||
public readonly result: legacyMessages.EvaluationResult,
|
||||
public readonly logFileLocation: string | undefined,
|
||||
public readonly successful: boolean | undefined,
|
||||
public readonly message: string | undefined,
|
||||
/**
|
||||
* 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. Undefined means to use whatever order is in the
|
||||
* sarif file.
|
||||
*/
|
||||
public interpretedResultsSortState: InterpretedResultsSortState | undefined,
|
||||
public resultCount: number = 0,
|
||||
|
||||
/**
|
||||
* 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. Undefined means to use whatever order is in the
|
||||
* sarif file.
|
||||
*/
|
||||
interpretedResultsSortState: InterpretedResultsSortState | undefined;
|
||||
|
||||
/**
|
||||
* Note that in the {@link readQueryHistoryFromFile} method, we create a CompletedQueryInfo instance
|
||||
* by explicitly setting the prototype in order to avoid calling this constructor.
|
||||
*/
|
||||
constructor(evaluation: QueryWithResults) {
|
||||
this.query = evaluation.query;
|
||||
this.logFileLocation = evaluation.logFileLocation;
|
||||
this.result = evaluation.result;
|
||||
|
||||
this.message = evaluation.message;
|
||||
this.successful = evaluation.successful;
|
||||
|
||||
this.sortedResultsInfo = {};
|
||||
this.resultCount = 0;
|
||||
}
|
||||
/**
|
||||
* Map from result set name to SortedResultSetInfo.
|
||||
*/
|
||||
public sortedResultsInfo: Record<string, SortedResultSetInfo> = {},
|
||||
) {}
|
||||
|
||||
setResultCount(value: number) {
|
||||
this.resultCount = value;
|
||||
@@ -220,20 +206,15 @@ export type CompletedLocalQueryInfo = LocalQueryInfo & {
|
||||
export class LocalQueryInfo {
|
||||
readonly t = "local";
|
||||
|
||||
public failureReason: string | undefined;
|
||||
public completedQuery: CompletedQueryInfo | undefined;
|
||||
public evalLogLocation: string | undefined;
|
||||
public evalLogSummaryLocation: string | undefined;
|
||||
public jsonEvalLogSummaryLocation: string | undefined;
|
||||
public evalLogSummarySymbolsLocation: string | undefined;
|
||||
|
||||
/**
|
||||
* Note that in the {@link readQueryHistoryFromFile} method, we create a FullQueryInfo instance
|
||||
* by explicitly setting the prototype in order to avoid calling this constructor.
|
||||
*/
|
||||
constructor(
|
||||
public readonly initialInfo: InitialQueryInfo,
|
||||
private cancellationSource?: CancellationTokenSource, // used to cancel in progress queries
|
||||
public failureReason?: string,
|
||||
public completedQuery?: CompletedQueryInfo,
|
||||
public evalLogLocation?: string,
|
||||
public evalLogSummaryLocation?: string,
|
||||
public jsonEvalLogSummaryLocation?: string,
|
||||
public evalLogSummarySymbolsLocation?: string,
|
||||
) {
|
||||
/**/
|
||||
}
|
||||
@@ -301,7 +282,14 @@ export class LocalQueryInfo {
|
||||
}
|
||||
|
||||
completeThisQuery(info: QueryWithResults): void {
|
||||
this.completedQuery = new CompletedQueryInfo(info);
|
||||
this.completedQuery = new CompletedQueryInfo(
|
||||
info.query,
|
||||
info.result,
|
||||
info.logFileLocation,
|
||||
info.successful,
|
||||
info.message,
|
||||
undefined,
|
||||
);
|
||||
|
||||
// dispose of the cancellation token source and also ensure the source is not serialized as JSON
|
||||
this.cancellationSource?.dispose();
|
||||
|
||||
@@ -137,7 +137,7 @@ export class QueryEvaluationInfo extends QueryOutputDir {
|
||||
constructor(
|
||||
querySaveDir: string,
|
||||
public readonly dbItemPath: string,
|
||||
private readonly databaseHasMetadataFile: boolean,
|
||||
public readonly databaseHasMetadataFile: boolean,
|
||||
public readonly quickEvalPosition?: messages.Position,
|
||||
public readonly metadata?: QueryMetadata,
|
||||
) {
|
||||
@@ -382,10 +382,10 @@ export class QueryEvaluationInfo extends QueryOutputDir {
|
||||
|
||||
export interface QueryWithResults {
|
||||
readonly query: QueryEvaluationInfo;
|
||||
readonly result: legacyMessages.EvaluationResult;
|
||||
readonly logFileLocation?: string;
|
||||
readonly successful?: boolean;
|
||||
readonly message?: string;
|
||||
readonly result: legacyMessages.EvaluationResult;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user