Add cancellation from query history view
And tweak the commands visible from the view.
This commit is contained in:
@@ -496,6 +496,10 @@
|
||||
"command": "codeQLQueryHistory.showQueryLog",
|
||||
"title": "Show Query Log"
|
||||
},
|
||||
{
|
||||
"command": "codeQLQueryHistory.cancel",
|
||||
"title": "Cancel"
|
||||
},
|
||||
{
|
||||
"command": "codeQLQueryHistory.showQueryText",
|
||||
"title": "Show Query Text"
|
||||
@@ -664,7 +668,7 @@
|
||||
{
|
||||
"command": "codeQLQueryHistory.removeHistoryItem",
|
||||
"group": "9_qlCommands",
|
||||
"when": "view == codeQLQueryHistory"
|
||||
"when": "view == codeQLQueryHistory && viewItem != inProgressResultsItem"
|
||||
},
|
||||
{
|
||||
"command": "codeQLQueryHistory.setLabel",
|
||||
@@ -674,12 +678,12 @@
|
||||
{
|
||||
"command": "codeQLQueryHistory.compareWith",
|
||||
"group": "9_qlCommands",
|
||||
"when": "view == codeQLQueryHistory"
|
||||
"when": "view == codeQLQueryHistory && (viewItem == rawResultsItem || viewItem == interpretedResultsItem)"
|
||||
},
|
||||
{
|
||||
"command": "codeQLQueryHistory.showQueryLog",
|
||||
"group": "9_qlCommands",
|
||||
"when": "view == codeQLQueryHistory"
|
||||
"when": "view == codeQLQueryHistory && (viewItem == rawResultsItem || viewItem == interpretedResultsItem)"
|
||||
},
|
||||
{
|
||||
"command": "codeQLQueryHistory.showQueryText",
|
||||
@@ -689,7 +693,7 @@
|
||||
{
|
||||
"command": "codeQLQueryHistory.viewCsvResults",
|
||||
"group": "9_qlCommands",
|
||||
"when": "view == codeQLQueryHistory && viewItem != interpretedResultsItem"
|
||||
"when": "view == codeQLQueryHistory && viewItem == rawResultsItem"
|
||||
},
|
||||
{
|
||||
"command": "codeQLQueryHistory.viewCsvAlerts",
|
||||
@@ -704,12 +708,12 @@
|
||||
{
|
||||
"command": "codeQLQueryHistory.viewDil",
|
||||
"group": "9_qlCommands",
|
||||
"when": "view == codeQLQueryHistory"
|
||||
"when": "view == codeQLQueryHistory && (viewItem == rawResultsItem || viewItem == interpretedResultsItem)"
|
||||
},
|
||||
{
|
||||
"command": "codeQL.previewQueryHelp",
|
||||
"command": "codeQLQueryHistory.cancel",
|
||||
"group": "9_qlCommands",
|
||||
"when": "view == codeQLQueryHistory && resourceScheme == .qhelp && isWorkspaceTrusted"
|
||||
"when": "view == codeQLQueryHistory && viewItem == inProgressResultsItem"
|
||||
},
|
||||
{
|
||||
"command": "codeQLTests.showOutputDifferences",
|
||||
@@ -862,6 +866,10 @@
|
||||
"command": "codeQLQueryHistory.showQueryLog",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "codeQLQueryHistory.cancel",
|
||||
"when": "false"
|
||||
},
|
||||
{
|
||||
"command": "codeQLQueryHistory.showQueryText",
|
||||
"when": "false"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
CancellationToken,
|
||||
CancellationTokenSource,
|
||||
commands,
|
||||
Disposable,
|
||||
ExtensionContext,
|
||||
@@ -498,8 +499,12 @@ async function activateWithInstalledDistribution(
|
||||
databaseUri: databaseItem.databaseUri.toString(),
|
||||
};
|
||||
|
||||
// handle cancellation from the history view.
|
||||
const source = new CancellationTokenSource();
|
||||
token.onCancellationRequested(() => source.cancel());
|
||||
|
||||
const initialInfo = await createInitialQueryInfo(selectedQuery, databaseInfo, quickEval, range);
|
||||
const item = new FullQueryInfo(initialInfo, queryHistoryConfigurationListener);
|
||||
const item = new FullQueryInfo(initialInfo, queryHistoryConfigurationListener, source);
|
||||
qhm.addQuery(item);
|
||||
try {
|
||||
const completedQueryInfo = await compileAndRunQueryAgainstDatabase(
|
||||
@@ -508,7 +513,7 @@ async function activateWithInstalledDistribution(
|
||||
databaseItem,
|
||||
initialInfo,
|
||||
progress,
|
||||
token,
|
||||
source.token,
|
||||
);
|
||||
item.completeThisQuery(completedQueryInfo);
|
||||
await showResultsForCompletedQuery(item as FullCompletedQueryInfo, WebviewReveal.NotForced);
|
||||
@@ -519,6 +524,7 @@ async function activateWithInstalledDistribution(
|
||||
throw e;
|
||||
} finally {
|
||||
qhm.refreshTreeView();
|
||||
source.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,24 +119,24 @@ export class HistoryTreeDataProvider extends DisposableObject {
|
||||
arguments: [element],
|
||||
};
|
||||
|
||||
// Mark this query history item according to whether it has a
|
||||
// SARIF file so that we can make context menu items conditionally
|
||||
// available.
|
||||
const hasResults = await element.completedQuery?.query.hasInterpretedResults();
|
||||
treeItem.contextValue = hasResults
|
||||
? 'interpretedResultsItem'
|
||||
: 'rawResultsItem';
|
||||
|
||||
// Populate the icon and the context value. We use the context value to
|
||||
// control which commands are visible in the context menu.
|
||||
let hasResults;
|
||||
switch (element.status) {
|
||||
case QueryStatus.InProgress:
|
||||
// TODO this is not a good icon.
|
||||
treeItem.iconPath = new ThemeIcon('sync~spin');
|
||||
treeItem.contextValue = 'inProgressResultsItem';
|
||||
break;
|
||||
case QueryStatus.Completed:
|
||||
hasResults = await element.completedQuery?.query.hasInterpretedResults();
|
||||
treeItem.iconPath = this.localSuccessIconPath;
|
||||
treeItem.contextValue = hasResults
|
||||
? 'interpretedResultsItem'
|
||||
: 'rawResultsItem';
|
||||
break;
|
||||
case QueryStatus.Failed:
|
||||
treeItem.iconPath = this.failedIconPath;
|
||||
treeItem.contextValue = 'cancelledResultsItem';
|
||||
break;
|
||||
default:
|
||||
assertNever(element.status);
|
||||
@@ -332,6 +332,12 @@ export class QueryHistoryManager extends DisposableObject {
|
||||
this.handleShowQueryLog.bind(this)
|
||||
)
|
||||
);
|
||||
this.push(
|
||||
commandRunner(
|
||||
'codeQLQueryHistory.cancel',
|
||||
this.handleCancel.bind(this)
|
||||
)
|
||||
);
|
||||
this.push(
|
||||
commandRunner(
|
||||
'codeQLQueryHistory.showQueryText',
|
||||
@@ -439,7 +445,7 @@ export class QueryHistoryManager extends DisposableObject {
|
||||
const { finalSingleItem, finalMultiSelect } = this.determineSelection(singleItem, multiSelect);
|
||||
|
||||
(finalMultiSelect || [finalSingleItem]).forEach((item) => {
|
||||
// TODO: Removing in progress queries is not supported yet
|
||||
// Removing in progress queries is not supported yet
|
||||
if (item.status !== QueryStatus.InProgress) {
|
||||
this.treeDataProvider.remove(item);
|
||||
item.completedQuery?.dispose();
|
||||
@@ -568,6 +574,19 @@ export class QueryHistoryManager extends DisposableObject {
|
||||
}
|
||||
}
|
||||
|
||||
async handleCancel(
|
||||
singleItem: FullQueryInfo,
|
||||
multiSelect: FullQueryInfo[]
|
||||
) {
|
||||
const { finalSingleItem, finalMultiSelect } = this.determineSelection(singleItem, multiSelect);
|
||||
|
||||
(finalMultiSelect || [finalSingleItem]).forEach((item) => {
|
||||
if (item.status === QueryStatus.InProgress) {
|
||||
item.cancel();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async handleShowQueryText(
|
||||
singleItem: FullQueryInfo,
|
||||
multiSelect: FullQueryInfo[]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { env } from 'vscode';
|
||||
import { CancellationTokenSource, env } from 'vscode';
|
||||
|
||||
import { QueryWithResults, tmpDir, QueryEvaluationInfo } from './run-queries';
|
||||
import * as messages from './pure/messages';
|
||||
@@ -180,10 +180,15 @@ export class FullQueryInfo {
|
||||
constructor(
|
||||
public readonly initialInfo: InitialQueryInfo,
|
||||
private readonly config: QueryHistoryConfig,
|
||||
private readonly source: CancellationTokenSource
|
||||
) {
|
||||
/**/
|
||||
}
|
||||
|
||||
cancel() {
|
||||
this.source.cancel();
|
||||
}
|
||||
|
||||
get startTime() {
|
||||
return this.initialInfo.start.toLocaleString(env.language);
|
||||
}
|
||||
|
||||
@@ -695,7 +695,8 @@ let queryId = 0;
|
||||
export async function createInitialQueryInfo(
|
||||
selectedQueryUri: Uri | undefined,
|
||||
databaseInfo: DatabaseInfo,
|
||||
isQuickEval: boolean, range?: Range
|
||||
isQuickEval: boolean,
|
||||
range?: Range
|
||||
): Promise<InitialQueryInfo> {
|
||||
// Determine which query to run, based on the selection and the active editor.
|
||||
const { queryPath, quickEvalPosition, quickEvalText } = await determineSelectedQuery(selectedQueryUri, isQuickEval, range);
|
||||
|
||||
@@ -515,7 +515,8 @@ describe('query-history', () => {
|
||||
start: new Date(),
|
||||
queryPath: 'hucairz'
|
||||
} as InitialQueryInfo,
|
||||
configListener
|
||||
configListener,
|
||||
{} as vscode.CancellationTokenSource
|
||||
);
|
||||
|
||||
if (queryWitbResults) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import { EvaluationResult, QueryResultType } from '../../pure/messages';
|
||||
import { SortDirection, SortedResultSetInfo } from '../../pure/interface-types';
|
||||
import { CodeQLCliServer, SourceInfo } from '../../cli';
|
||||
import { env } from 'process';
|
||||
import { CancellationTokenSource } from 'vscode';
|
||||
|
||||
chai.use(chaiAsPromised);
|
||||
const expect = chai.expect;
|
||||
@@ -266,7 +267,8 @@ describe('query-results', () => {
|
||||
start: new Date(),
|
||||
queryPath: 'path/to/hucairz'
|
||||
} as InitialQueryInfo,
|
||||
mockQueryHistoryConfig()
|
||||
mockQueryHistoryConfig(),
|
||||
{} as CancellationTokenSource
|
||||
);
|
||||
|
||||
if (queryWitbResults) {
|
||||
|
||||
Reference in New Issue
Block a user