Skip to content

Commit

Permalink
Implement sorting of query history by name, date, and result count
Browse files Browse the repository at this point in the history
  • Loading branch information
edoardopirovano committed Mar 15, 2021
1 parent a86c1ce commit 719d5c9
Show file tree
Hide file tree
Showing 8 changed files with 193 additions and 14 deletions.
1 change: 1 addition & 0 deletions extensions/ql-vscode/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- Respect the `codeQL.runningQueries.numberOfThreads` setting when creating SARIF files during result interpretation. [#771](https://github.com/github/vscode-codeql/pull/771)
- Allow using raw LGTM project slugs for fetching LGTM databases. [#769](https://github.com/github/vscode-codeql/pull/769)
- Better error messages when BQRS interpretation fails to produce SARIF. [#770](https://github.com/github/vscode-codeql/pull/770)
- Implement sorting of the query history view by name, date, and results count. [#777](https://github.com/github/vscode-codeql/pull/777)

## 1.4.3 - 22 February 2021

Expand Down
15 changes: 15 additions & 0 deletions extensions/ql-vscode/media/dark/sort-num.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
15 changes: 15 additions & 0 deletions extensions/ql-vscode/media/light/sort-num.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
55 changes: 53 additions & 2 deletions extensions/ql-vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,8 @@
},
"codeQL.queryHistory.format": {
"type": "string",
"default": "[%t] %q on %d - %s",
"description": "Default string for how to label query history items. %t is the time of the query, %q is the query name, %d is the database name, and %s is a status string."
"default": "%q on %d - %s, %r result count [%t]",
"description": "Default string for how to label query history items. %t is the time of the query, %q is the query name, %d is the database name, %r is the number of results, and %s is a status string."
},
"codeQL.runningTests.numberOfThreads": {
"scope": "window",
Expand Down Expand Up @@ -357,6 +357,30 @@
"dark": "media/dark/trash.svg"
}
},
{
"command": "codeQLQueryHistory.sortByName",
"title": "Sort by Name",
"icon": {
"light": "media/light/sort-alpha.svg",
"dark": "media/dark/sort-alpha.svg"
}
},
{
"command": "codeQLQueryHistory.sortByDate",
"title": "Sort by Query Date",
"icon": {
"light": "media/light/sort-date.svg",
"dark": "media/dark/sort-date.svg"
}
},
{
"command": "codeQLQueryHistory.sortByCount",
"title": "Sort by Results Count",
"icon": {
"light": "media/light/sort-num.svg",
"dark": "media/dark/sort-num.svg"
}
},
{
"command": "codeQLQueryHistory.showQueryLog",
"title": "Show Query Log"
Expand Down Expand Up @@ -461,6 +485,21 @@
"when": "view == codeQLQueryHistory",
"group": "navigation"
},
{
"command": "codeQLQueryHistory.sortByName",
"when": "view == codeQLQueryHistory",
"group": "navigation"
},
{
"command": "codeQLQueryHistory.sortByDate",
"when": "view == codeQLQueryHistory",
"group": "navigation"
},
{
"command": "codeQLQueryHistory.sortByCount",
"when": "view == codeQLQueryHistory",
"group": "navigation"
},
{
"command": "codeQLAstViewer.clear",
"when": "view == codeQLAstViewer",
Expand Down Expand Up @@ -666,6 +705,18 @@
"command": "codeQLQueryHistory.compareWith",
"when": "false"
},
{
"command": "codeQLQueryHistory.sortByName",
"when": "false"
},
{
"command": "codeQLQueryHistory.sortByDate",
"when": "false"
},
{
"command": "codeQLQueryHistory.sortByCount",
"when": "false"
},
{
"command": "codeQLAstViewer.gotoCode",
"when": "false"
Expand Down
9 changes: 4 additions & 5 deletions extensions/ql-vscode/src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -472,12 +472,11 @@ async function activateWithInstalledDistribution(
progress,
token
);
const item = qhm.addQuery(info);
const item = qhm.buildCompletedQuery(info);
await showResultsForCompletedQuery(item, WebviewReveal.NotForced);
// The call to showResults potentially creates SARIF file;
// Update the tree item context value to allow viewing that
// SARIF file from context menu.
await qhm.refreshTreeView(item);
// Note we must update the query history view after showing results as the
// display and sorting might depend on the number of results
await qhm.addCompletedQuery(item);
}
}

Expand Down
1 change: 1 addition & 0 deletions extensions/ql-vscode/src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -400,6 +400,7 @@ export class InterfaceManager extends DisposableObject {
}
);
const resultSet = transformBqrsResultSet(schema, chunk);
results.setResultCount(interpretationPage?.numTotalResults || resultSet.schema.rows);
const parsedResultSets: ParsedResultSets = {
pageNumber: 0,
pageSize,
Expand Down
98 changes: 93 additions & 5 deletions extensions/ql-vscode/src/query-history.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as path from 'path';
import * as vscode from 'vscode';
import { window as Window } from 'vscode';
import { window as Window, env } from 'vscode';
import { CompletedQuery } from './query-results';
import { QueryHistoryConfig } from './config';
import { QueryWithResults } from './run-queries';
Expand All @@ -15,6 +15,7 @@ import { URLSearchParams } from 'url';
import { QueryServerClient } from './queryserver-client';
import { DisposableObject } from './pure/disposable-object';
import { commandRunner } from './commandRunner';
import { assertNever } from './pure/helpers-pure';

/**
* query-history.ts
Expand Down Expand Up @@ -58,10 +59,21 @@ const SHOW_QUERY_TEXT_QUICK_EVAL_MSG = `\
*/
const FAILED_QUERY_HISTORY_ITEM_ICON = 'media/red-x.svg';

enum SortOrder {
NameAsc = 'NameAsc',
NameDesc = 'NameDesc',
DateAsc = 'DateAsc',
DateDesc = 'DateDesc',
CountAsc = 'CountAsc',
CountDesc = 'CountDesc',
}

/**
* Tree data provider for the query history view.
*/
export class HistoryTreeDataProvider extends DisposableObject {
private _sortOrder = SortOrder.DateAsc;

private _onDidChangeTreeData = super.push(new vscode.EventEmitter<CompletedQuery | undefined>());

readonly onDidChangeTreeData: vscode.Event<CompletedQuery | undefined> = this
Expand Down Expand Up @@ -111,7 +123,24 @@ export class HistoryTreeDataProvider extends DisposableObject {
getChildren(
element?: CompletedQuery
): vscode.ProviderResult<CompletedQuery[]> {
return element ? [] : this.history;
return element ? [] : this.history.sort((q1, q2) => {
switch (this.sortOrder) {
case SortOrder.NameAsc:
return q1.toString().localeCompare(q2.toString(), env.language);
case SortOrder.NameDesc:
return q2.toString().localeCompare(q1.toString(), env.language);
case SortOrder.DateAsc:
return q1.date.getTime() - q2.date.getTime();
case SortOrder.DateDesc:
return q2.date.getTime() - q1.date.getTime();
case SortOrder.CountAsc:
return q1.resultCount - q2.resultCount;
case SortOrder.CountDesc:
return q2.resultCount - q1.resultCount;
default:
assertNever(this.sortOrder);
}
});
}

getParent(_element: CompletedQuery): vscode.ProviderResult<CompletedQuery> {
Expand Down Expand Up @@ -157,6 +186,15 @@ export class HistoryTreeDataProvider extends DisposableObject {
find(queryId: number): CompletedQuery | undefined {
return this.allHistory.find((query) => query.query.queryID === queryId);
}

public get sortOrder() {
return this._sortOrder;
}

public set sortOrder(newSortOrder: SortOrder) {
this._sortOrder = newSortOrder;
this._onDidChangeTreeData.fire();
}
}

/**
Expand Down Expand Up @@ -224,6 +262,24 @@ export class QueryHistoryManager extends DisposableObject {
this.handleRemoveHistoryItem.bind(this)
)
);
this.push(
commandRunner(
'codeQLQueryHistory.sortByName',
this.handleSortByName.bind(this)
)
);
this.push(
commandRunner(
'codeQLQueryHistory.sortByDate',
this.handleSortByDate.bind(this)
)
);
this.push(
commandRunner(
'codeQLQueryHistory.sortByCount',
this.handleSortByCount.bind(this)
)
);
this.push(
commandRunner(
'codeQLQueryHistory.setLabel',
Expand Down Expand Up @@ -345,6 +401,30 @@ export class QueryHistoryManager extends DisposableObject {
}
}

async handleSortByName() {
if (this.treeDataProvider.sortOrder === SortOrder.NameAsc) {
this.treeDataProvider.sortOrder = SortOrder.NameDesc;
} else {
this.treeDataProvider.sortOrder = SortOrder.NameAsc;
}
}

async handleSortByDate() {
if (this.treeDataProvider.sortOrder === SortOrder.DateAsc) {
this.treeDataProvider.sortOrder = SortOrder.DateDesc;
} else {
this.treeDataProvider.sortOrder = SortOrder.DateAsc;
}
}

async handleSortByCount() {
if (this.treeDataProvider.sortOrder === SortOrder.CountAsc) {
this.treeDataProvider.sortOrder = SortOrder.CountDesc;
} else {
this.treeDataProvider.sortOrder = SortOrder.CountAsc;
}
}

async handleSetLabel(
singleItem: CompletedQuery,
multiSelect: CompletedQuery[]
Expand All @@ -362,7 +442,12 @@ export class QueryHistoryManager extends DisposableObject {
if (response !== undefined) {
// Interpret empty string response as 'go back to using default'
singleItem.options.label = response === '' ? undefined : response;
this.treeDataProvider.refresh(singleItem);
if (this.treeDataProvider.sortOrder === SortOrder.NameAsc ||
this.treeDataProvider.sortOrder === SortOrder.NameDesc) {
this.treeDataProvider.refresh();
} else {
this.treeDataProvider.refresh(singleItem);
}
}
}

Expand Down Expand Up @@ -511,11 +596,14 @@ export class QueryHistoryManager extends DisposableObject {
}
}

addQuery(info: QueryWithResults): CompletedQuery {
buildCompletedQuery(info: QueryWithResults): CompletedQuery {
const item = new CompletedQuery(info, this.queryHistoryConfigListener);
return item;
}

addCompletedQuery(item: CompletedQuery) {
this.treeDataProvider.pushQuery(item);
this.updateTreeViewSelectionIfVisible();
return item;
}

find(queryId: number): CompletedQuery | undefined {
Expand Down
13 changes: 11 additions & 2 deletions extensions/ql-vscode/src/query-results.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import { QueryHistoryConfig } from './config';
import { QueryHistoryItemOptions } from './query-history';

export class CompletedQuery implements QueryWithResults {
readonly date: Date;
readonly time: string;
readonly query: QueryInfo;
readonly result: messages.EvaluationResult;
readonly database: DatabaseInfo;
readonly logFileLocation?: string;
options: QueryHistoryItemOptions;
resultCount: number;
dispose: () => void;

/**
Expand Down Expand Up @@ -44,8 +46,14 @@ export class CompletedQuery implements QueryWithResults {
this.options = evaluation.options;
this.dispose = evaluation.dispose;

this.time = new Date().toLocaleString(env.language);
this.date = new Date();
this.time = this.date.toLocaleString(env.language);
this.sortedResultsInfo = new Map();
this.resultCount = 0;
}

setResultCount(value: number) {
this.resultCount = value;
}

get databaseName(): string {
Expand Down Expand Up @@ -80,11 +88,12 @@ export class CompletedQuery implements QueryWithResults {
}

interpolate(template: string): string {
const { databaseName, queryName, time, statusString } = this;
const { databaseName, queryName, time, resultCount, statusString } = this;
const replacements: { [k: string]: string } = {
t: time,
q: queryName,
d: databaseName,
r: resultCount.toString(),
s: statusString,
'%': '%',
};
Expand Down

0 comments on commit 719d5c9

Please sign in to comment.