diff --git a/extensions/ql-vscode/src/compare/compare-interface.ts b/extensions/ql-vscode/src/compare/compare-interface.ts
index 32c8d135a..37aeb2435 100644
--- a/extensions/ql-vscode/src/compare/compare-interface.ts
+++ b/extensions/ql-vscode/src/compare/compare-interface.ts
@@ -95,7 +95,7 @@ export class CompareInterfaceManager extends DisposableObject {
currentResultSetName: currentResultSetName,
rows,
message,
- datebaseUri: to.initialInfo.databaseInfo.databaseUri,
+ databaseUri: to.initialInfo.databaseInfo.databaseUri,
});
}
}
diff --git a/extensions/ql-vscode/src/compare/view/Compare.tsx b/extensions/ql-vscode/src/compare/view/Compare.tsx
index c880d7be3..b81356724 100644
--- a/extensions/ql-vscode/src/compare/view/Compare.tsx
+++ b/extensions/ql-vscode/src/compare/view/Compare.tsx
@@ -17,7 +17,7 @@ const emptyComparison: SetComparisonsMessage = {
columns: [],
commonResultSetNames: [],
currentResultSetName: '',
- datebaseUri: '',
+ databaseUri: '',
message: 'Empty comparison'
};
diff --git a/extensions/ql-vscode/src/compare/view/CompareTable.tsx b/extensions/ql-vscode/src/compare/view/CompareTable.tsx
index 3039b7cfe..ada4627b8 100644
--- a/extensions/ql-vscode/src/compare/view/CompareTable.tsx
+++ b/extensions/ql-vscode/src/compare/view/CompareTable.tsx
@@ -76,7 +76,7 @@ export default function CompareTable(props: Props) {
schemaName={comparison.currentResultSetName}
preventSort={true}
/>
- {createRows(rows.from, comparison.datebaseUri)}
+ {createRows(rows.from, comparison.databaseUri)}
@@ -86,7 +86,7 @@ export default function CompareTable(props: Props) {
schemaName={comparison.currentResultSetName}
preventSort={true}
/>
- {createRows(rows.to, comparison.datebaseUri)}
+ {createRows(rows.to, comparison.databaseUri)}
|
diff --git a/extensions/ql-vscode/src/extension.ts b/extensions/ql-vscode/src/extension.ts
index e859c121b..8232e652b 100644
--- a/extensions/ql-vscode/src/extension.ts
+++ b/extensions/ql-vscode/src/extension.ts
@@ -501,8 +501,6 @@ async function activateWithInstalledDistribution(
const initialInfo = await createInitialQueryInfo(selectedQuery, databaseInfo, quickEval, range);
const item = new FullQueryInfo(initialInfo, queryHistoryConfigurationListener);
qhm.addQuery(item);
- await qhm.refreshTreeView(item);
-
try {
const completedQueryInfo = await compileAndRunQueryAgainstDatabase(
cliServer,
@@ -520,7 +518,7 @@ async function activateWithInstalledDistribution(
item.failureReason = e.message;
throw e;
} finally {
- await qhm.refreshTreeView(item);
+ qhm.refreshTreeView();
}
}
}
diff --git a/extensions/ql-vscode/src/interface.ts b/extensions/ql-vscode/src/interface.ts
index 16b2a5a2f..78efd3a9f 100644
--- a/extensions/ql-vscode/src/interface.ts
+++ b/extensions/ql-vscode/src/interface.ts
@@ -33,7 +33,7 @@ import { Logger } from './logging';
import * as messages from './pure/messages';
import { commandRunner } from './commandRunner';
import { CompletedQueryInfo, interpretResults } from './query-results';
-import { QueryEvaluatonInfo, tmpDir } from './run-queries';
+import { QueryEvaluationInfo, tmpDir } from './run-queries';
import { parseSarifLocation, parseSarifPlainTextMessage } from './pure/sarif-utils';
import {
WebviewReveal,
@@ -644,7 +644,7 @@ export class InterfaceManager extends DisposableObject {
}
private async interpretResultsInfo(
- query: QueryEvaluatonInfo,
+ query: QueryEvaluationInfo,
sortState: InterpretedResultsSortState | undefined
): Promise {
if (
diff --git a/extensions/ql-vscode/src/pure/interface-types.ts b/extensions/ql-vscode/src/pure/interface-types.ts
index 9e9ce2aa5..bb75686ad 100644
--- a/extensions/ql-vscode/src/pure/interface-types.ts
+++ b/extensions/ql-vscode/src/pure/interface-types.ts
@@ -316,7 +316,7 @@ export interface SetComparisonsMessage {
readonly currentResultSetName: string;
readonly rows: QueryCompareResult | undefined;
readonly message: string | undefined;
- readonly datebaseUri: string;
+ readonly databaseUri: string;
}
export enum DiffKind {
diff --git a/extensions/ql-vscode/src/query-history.ts b/extensions/ql-vscode/src/query-history.ts
index 2c9bdd800..a91311d07 100644
--- a/extensions/ql-vscode/src/query-history.ts
+++ b/extensions/ql-vscode/src/query-history.ts
@@ -96,9 +96,6 @@ export class HistoryTreeDataProvider extends DisposableObject {
private localSuccessIconPath: string;
- /**
- * When not undefined, must be reference-equal to an item in `this.databases`.
- */
private current: FullQueryInfo | undefined;
constructor(extensionPath: string) {
@@ -152,8 +149,8 @@ export class HistoryTreeDataProvider extends DisposableObject {
element?: FullQueryInfo
): ProviderResult {
return element ? [] : this.history.sort((h1, h2) => {
- const q1 = h1.completedQuery;
- const q2 = h2.completedQuery;
+ const resultCount1 = h1.completedQuery?.resultCount ?? -1;
+ const resultCount2 = h2.completedQuery?.resultCount ?? -1;
switch (this.sortOrder) {
case SortOrder.NameAsc:
@@ -165,9 +162,15 @@ export class HistoryTreeDataProvider extends DisposableObject {
case SortOrder.DateDesc:
return h2.initialInfo.start.getTime() - h1.initialInfo.start.getTime();
case SortOrder.CountAsc:
- return (!q1 || !q2) ? 0 : q1.resultCount - q2.resultCount;
+ // If the result counts are equal, sort by name.
+ return resultCount1 - resultCount2 === 0
+ ? h1.label.localeCompare(h2.label, env.language)
+ : resultCount1 - resultCount2;
case SortOrder.CountDesc:
- return (!q1 || !q2) ? 0 : q2.resultCount - q1.resultCount;
+ // If the result counts are equal, sort by name.
+ return resultCount2 - resultCount1 === 0
+ ? h2.label.localeCompare(h1.label, env.language)
+ : resultCount2 - resultCount1;
default:
assertNever(this.sortOrder);
}
@@ -183,8 +186,8 @@ export class HistoryTreeDataProvider extends DisposableObject {
}
pushQuery(item: FullQueryInfo): void {
- this.current = item;
this.history.push(item);
+ this.setCurrentItem(item);
this.refresh();
}
@@ -193,16 +196,17 @@ export class HistoryTreeDataProvider extends DisposableObject {
}
remove(item: FullQueryInfo) {
- if (this.current === item) {
- this.current = undefined;
+ const isCurrent = this.current === item;
+ if (isCurrent) {
+ this.setCurrentItem();
}
const index = this.history.findIndex((i) => i === item);
if (index >= 0) {
this.history.splice(index, 1);
- if (this.current === undefined && this.history.length > 0) {
+ if (isCurrent && this.history.length > 0) {
// Try to keep a current item, near the deleted item if there
// are any available.
- this.current = this.history[Math.min(index, this.history.length - 1)];
+ this.setCurrentItem(this.history[Math.min(index, this.history.length - 1)]);
}
this.refresh();
}
@@ -212,8 +216,8 @@ export class HistoryTreeDataProvider extends DisposableObject {
return this.history;
}
- refresh(item?: FullQueryInfo) {
- this._onDidChangeTreeData.fire(item);
+ refresh() {
+ this._onDidChangeTreeData.fire(undefined);
}
public get sortOrder() {
@@ -267,11 +271,13 @@ export class QueryHistoryManager extends DisposableObject {
this.updateTreeViewSelectionIfVisible()
)
);
- // Don't allow the selection to become empty
this.push(
this.treeView.onDidChangeSelection(async (ev) => {
- if (ev.selection.length == 0) {
+ if (ev.selection.length === 0) {
+ // Don't allow the selection to become empty
this.updateTreeViewSelectionIfVisible();
+ } else {
+ this.treeDataProvider.setCurrentItem(ev.selection[0]);
}
this.updateCompareWith(ev.selection);
})
@@ -433,12 +439,15 @@ export class QueryHistoryManager extends DisposableObject {
const { finalSingleItem, finalMultiSelect } = this.determineSelection(singleItem, multiSelect);
(finalMultiSelect || [finalSingleItem]).forEach((item) => {
- this.treeDataProvider.remove(item);
- item.completedQuery?.dispose();
+ // TODO: Removing in progress queries is not supported yet
+ if (item.status !== QueryStatus.InProgress) {
+ this.treeDataProvider.remove(item);
+ item.completedQuery?.dispose();
+ }
});
const current = this.treeDataProvider.getCurrent();
if (current !== undefined) {
- await this.treeView.reveal(current);
+ await this.treeView.reveal(current, { select: true });
await this.invokeCallbackOn(current);
}
}
@@ -484,12 +493,7 @@ export class QueryHistoryManager extends DisposableObject {
if (response !== undefined) {
// Interpret empty string response as 'go back to using default'
singleItem.initialInfo.userSpecifiedLabel = response === '' ? undefined : response;
- if (this.treeDataProvider.sortOrder === SortOrder.NameAsc ||
- this.treeDataProvider.sortOrder === SortOrder.NameDesc) {
- this.treeDataProvider.refresh();
- } else {
- this.treeDataProvider.refresh(singleItem);
- }
+ this.treeDataProvider.refresh();
}
}
@@ -685,7 +689,7 @@ export class QueryHistoryManager extends DisposableObject {
// We must fire the onDidChangeTreeData event to ensure the current element can be selected
// using `reveal` if the tree view was not visible when the current element was added.
this.treeDataProvider.refresh();
- void this.treeView.reveal(current);
+ void this.treeView.reveal(current, { select: true });
}
}
}
@@ -826,13 +830,19 @@ the file in the file explorer and dragging it into the workspace.`
singleItem: FullQueryInfo,
multiSelect: FullQueryInfo[]
): { finalSingleItem: FullQueryInfo; finalMultiSelect: FullQueryInfo[] } {
- if (singleItem === undefined && (multiSelect === undefined || multiSelect.length === 0 || multiSelect[0] === undefined)) {
+ if (!singleItem && !multiSelect?.[0]) {
const selection = this.treeView.selection;
- if (selection) {
+ const current = this.treeDataProvider.getCurrent();
+ if (selection?.length) {
return {
finalSingleItem: selection[0],
finalMultiSelect: selection
};
+ } else if (current) {
+ return {
+ finalSingleItem: current,
+ finalMultiSelect: [current]
+ };
}
}
return {
@@ -841,7 +851,7 @@ the file in the file explorer and dragging it into the workspace.`
};
}
- async refreshTreeView(item: FullQueryInfo): Promise {
- this.treeDataProvider.refresh(item);
+ refreshTreeView(): void {
+ this.treeDataProvider.refresh();
}
}
diff --git a/extensions/ql-vscode/src/query-results.ts b/extensions/ql-vscode/src/query-results.ts
index 888282af3..ed7b324db 100644
--- a/extensions/ql-vscode/src/query-results.ts
+++ b/extensions/ql-vscode/src/query-results.ts
@@ -1,6 +1,6 @@
import { env } from 'vscode';
-import { QueryWithResults, tmpDir, QueryEvaluatonInfo } from './run-queries';
+import { QueryWithResults, tmpDir, QueryEvaluationInfo } from './run-queries';
import * as messages from './pure/messages';
import * as cli from './cli';
import * as sarif from 'sarif';
@@ -39,7 +39,7 @@ export enum QueryStatus {
}
export class CompletedQueryInfo implements QueryWithResults {
- readonly query: QueryEvaluatonInfo;
+ readonly query: QueryEvaluationInfo;
readonly result: messages.EvaluationResult;
readonly logFileLocation?: string;
resultCount: number;
diff --git a/extensions/ql-vscode/src/run-queries.ts b/extensions/ql-vscode/src/run-queries.ts
index 500740102..446ff3201 100644
--- a/extensions/ql-vscode/src/run-queries.ts
+++ b/extensions/ql-vscode/src/run-queries.ts
@@ -53,7 +53,7 @@ export const tmpDirDisposal = {
* temporary files associated with it, such as the compiled query
* output and results.
*/
-export class QueryEvaluatonInfo {
+export class QueryEvaluationInfo {
readonly compiledQueryPath: string;
readonly dilPath: string;
readonly csvPath: string;
@@ -266,7 +266,7 @@ export class QueryEvaluatonInfo {
export interface QueryWithResults {
- readonly query: QueryEvaluatonInfo;
+ readonly query: QueryEvaluationInfo;
readonly result: messages.EvaluationResult;
readonly logFileLocation?: string;
readonly dispose: () => void;
@@ -351,7 +351,7 @@ async function getSelectedPosition(editor: TextEditor, range?: Range): Promise {
@@ -393,7 +393,7 @@ async function checkDbschemeCompatibility(
}
}
-function reportNoUpgradePath(query: QueryEvaluatonInfo) {
+function reportNoUpgradePath(query: QueryEvaluationInfo) {
throw new Error(`Query ${query.program.queryPath} expects database scheme ${query.queryDbscheme}, but the current database has a different scheme, and no database upgrades are available. The current database scheme may be newer than the CodeQL query libraries in your workspace.\n\nPlease try using a newer version of the query libraries.`);
}
@@ -403,7 +403,7 @@ function reportNoUpgradePath(query: QueryEvaluatonInfo) {
async function compileNonDestructiveUpgrade(
qs: qsClient.QueryServerClient,
upgradeTemp: tmp.DirectoryResult,
- query: QueryEvaluatonInfo,
+ query: QueryEvaluationInfo,
progress: ProgressCallback,
token: CancellationToken,
): Promise {
@@ -614,7 +614,7 @@ export async function compileAndRunQueryAgainstDatabase(
}
}
- const query = new QueryEvaluatonInfo(initialInfo.id, qlProgram, db, packConfig.dbscheme, initialInfo.quickEvalPosition, metadata, templates);
+ const query = new QueryEvaluationInfo(initialInfo.id, qlProgram, db, packConfig.dbscheme, initialInfo.quickEvalPosition, metadata, templates);
const upgradeDir = await tmp.dir({ dir: upgradesTmpDir.name, unsafeCleanup: true });
try {
@@ -716,7 +716,7 @@ const compilationFailedErrorTail = ' compilation failed. Please make sure there
' and choose CodeQL Query Server from the dropdown.';
function createSyntheticResult(
- query: QueryEvaluatonInfo,
+ query: QueryEvaluationInfo,
message: string,
resultType: number
): QueryWithResults {
diff --git a/extensions/ql-vscode/src/vscode-tests/no-workspace/query-history.test.ts b/extensions/ql-vscode/src/vscode-tests/no-workspace/query-history.test.ts
index 84e1017d5..cb3fc3f6e 100644
--- a/extensions/ql-vscode/src/vscode-tests/no-workspace/query-history.test.ts
+++ b/extensions/ql-vscode/src/vscode-tests/no-workspace/query-history.test.ts
@@ -6,7 +6,7 @@ import * as sinon from 'sinon';
import * as chaiAsPromised from 'chai-as-promised';
import { logger } from '../../logging';
import { QueryHistoryManager, HistoryTreeDataProvider } from '../../query-history';
-import { QueryEvaluatonInfo, QueryWithResults } from '../../run-queries';
+import { QueryEvaluationInfo, QueryWithResults } from '../../run-queries';
import { QueryHistoryConfigListener } from '../../config';
import * as messages from '../../pure/messages';
import { QueryServerClient } from '../../queryserver-client';
@@ -379,7 +379,7 @@ describe('query-history', () => {
return {
query: {
hasInterpretedResults: () => Promise.resolve(hasInterpretedResults)
- } as QueryEvaluatonInfo,
+ } as QueryEvaluationInfo,
result: {
resultType: didRunSuccessfully
? messages.QueryResultType.SUCCESS
diff --git a/extensions/ql-vscode/src/vscode-tests/no-workspace/query-results.test.ts b/extensions/ql-vscode/src/vscode-tests/no-workspace/query-results.test.ts
index 757667ae9..20c7de766 100644
--- a/extensions/ql-vscode/src/vscode-tests/no-workspace/query-results.test.ts
+++ b/extensions/ql-vscode/src/vscode-tests/no-workspace/query-results.test.ts
@@ -6,7 +6,7 @@ import 'sinon-chai';
import * as sinon from 'sinon';
import * as chaiAsPromised from 'chai-as-promised';
import { FullQueryInfo, InitialQueryInfo, interpretResults } from '../../query-results';
-import { QueryEvaluatonInfo, QueryWithResults, tmpDir } from '../../run-queries';
+import { QueryEvaluationInfo, QueryWithResults, tmpDir } from '../../run-queries';
import { QueryHistoryConfig } from '../../config';
import { EvaluationResult, QueryResultType } from '../../pure/messages';
import { SortDirection, SortedResultSetInfo } from '../../pure/interface-types';
@@ -248,7 +248,7 @@ describe('query-results', () => {
resultsPath: '/a/b/c',
interpretedResultsPath: '/d/e/f'
}
- } as QueryEvaluatonInfo,
+ } as QueryEvaluationInfo,
result: {
evaluationTime: 12340,
resultType: didRunSuccessfully
diff --git a/extensions/ql-vscode/src/vscode-tests/no-workspace/run-queries.test.ts b/extensions/ql-vscode/src/vscode-tests/no-workspace/run-queries.test.ts
index 06df24c17..e75437045 100644
--- a/extensions/ql-vscode/src/vscode-tests/no-workspace/run-queries.test.ts
+++ b/extensions/ql-vscode/src/vscode-tests/no-workspace/run-queries.test.ts
@@ -5,7 +5,7 @@ import 'sinon-chai';
import * as sinon from 'sinon';
import * as chaiAsPromised from 'chai-as-promised';
-import { QueryEvaluatonInfo } from '../../run-queries';
+import { QueryEvaluationInfo } from '../../run-queries';
import { QlProgram, Severity, compileQuery } from '../../pure/messages';
import { DatabaseItem } from '../../databases';
@@ -13,7 +13,7 @@ chai.use(chaiAsPromised);
const expect = chai.expect;
describe('run-queries', () => {
- it('should create a QueryEvaluatonInfo', () => {
+ it('should create a QueryEvaluationInfo', () => {
const info = createMockQueryInfo();
const queryID = info.queryID;
@@ -86,7 +86,7 @@ describe('run-queries', () => {
let queryNum = 0;
function createMockQueryInfo() {
- return new QueryEvaluatonInfo(
+ return new QueryEvaluationInfo(
queryNum++,
'my-program' as unknown as QlProgram,
{