Skip to content

Commit c2c86ae

Browse files
committed
Add 'Always Save' to running unsaved query dialog
1 parent 2df512f commit c2c86ae

File tree

3 files changed

+46
-10
lines changed

3 files changed

+46
-10
lines changed

extensions/ql-vscode/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,11 @@
132132
"default": false,
133133
"description": "Enable debug logging and tuple counting when running CodeQL queries. This information is useful for debugging query performance."
134134
},
135+
"codeQL.runningQueries.autoSave": {
136+
"type": "boolean",
137+
"default": false,
138+
"description": "Enable automatically saving a modified query file when running a query."
139+
},
135140
"codeQL.queryHistory.format": {
136141
"type": "string",
137142
"default": "[%t] %q on %d - %s",

extensions/ql-vscode/src/config.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { DisposableObject } from 'semmle-vscode-utils';
2-
import { workspace, Event, EventEmitter, ConfigurationChangeEvent } from 'vscode';
2+
import { workspace, Event, EventEmitter, ConfigurationChangeEvent, ConfigurationTarget } from 'vscode';
33
import { DistributionManager } from './distribution';
44
import { logger } from './logging';
55

@@ -27,6 +27,14 @@ class Setting {
2727
}
2828
return workspace.getConfiguration(this.parent.qualifiedName).get<T>(this.name)!;
2929
}
30+
31+
updateValue<T>(value: T, target: ConfigurationTarget): Thenable<void> {
32+
if (this.parent === undefined) {
33+
throw new Error('Cannot update the value of a root setting.');
34+
}
35+
return workspace.getConfiguration(this.parent.qualifiedName).update(this.name, value, target);
36+
}
37+
3038
}
3139

3240
const ROOT_SETTING = new Setting('codeQL');
@@ -59,6 +67,7 @@ const NUMBER_OF_THREADS_SETTING = new Setting('numberOfThreads', RUNNING_QUERIES
5967
const TIMEOUT_SETTING = new Setting('timeout', RUNNING_QUERIES_SETTING);
6068
const MEMORY_SETTING = new Setting('memory', RUNNING_QUERIES_SETTING);
6169
const DEBUG_SETTING = new Setting('debug', RUNNING_QUERIES_SETTING);
70+
export const AUTOSAVE_SETTING = new Setting('autoSave', RUNNING_QUERIES_SETTING);
6271

6372
/** When these settings change, the running query server should be restarted. */
6473
const QUERY_SERVER_RESTARTING_SETTINGS = [NUMBER_OF_THREADS_SETTING, MEMORY_SETTING, DEBUG_SETTING];

extensions/ql-vscode/src/run-queries.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import * as vscode from 'vscode';
77
import { ErrorCodes, ResponseError } from 'vscode-languageclient';
88

99
import * as cli from './cli';
10+
import * as config from './config';
1011
import { DatabaseItem, getUpgradesDirectories } from './databases';
1112
import * as helpers from './helpers';
1213
import { DatabaseInfo, QueryMetadata, ResultsPaths } from './interface-types';
@@ -139,8 +140,8 @@ export class QueryInfo {
139140
target: this.quickEvalPosition ? {
140141
quickEval: { quickEvalPos: this.quickEvalPosition }
141142
} : {
142-
query: {}
143-
}
143+
query: {}
144+
}
144145
};
145146

146147
compiled = await helpers.withProgress({
@@ -259,7 +260,7 @@ async function checkDbschemeCompatibility(
259260

260261
if (query.dbItem.contents !== undefined && query.dbItem.contents.dbSchemeUri !== undefined) {
261262
const { scripts, finalDbscheme } = await cliServer.resolveUpgrades(query.dbItem.contents.dbSchemeUri.fsPath, searchPath);
262-
const hash = async function (filename: string): Promise<string> {
263+
const hash = async function(filename: string): Promise<string> {
263264
return crypto.createHash('sha256').update(await fs.readFile(filename)).digest('hex');
264265
}
265266

@@ -294,14 +295,33 @@ async function checkDbschemeCompatibility(
294295
}
295296
}
296297

297-
/** Prompts the user to save `document` if it has unsaved changes. */
298-
async function promptUserToSaveChanges(document: vscode.TextDocument): Promise<void> {
298+
/**
299+
* Prompts the user to save `document` if it has unsaved changes.
300+
* Returns true if we should save changes.
301+
*/
302+
async function promptUserToSaveChanges(document: vscode.TextDocument): Promise<boolean> {
299303
if (document.isDirty) {
300-
// TODO: add 'always save' button which records preference in configuration
301-
if (await helpers.showBinaryChoiceDialog('Query file has unsaved changes. Save now?')) {
302-
await document.save();
304+
if (config.AUTOSAVE_SETTING.getValue()) {
305+
return true;
306+
}
307+
else {
308+
const yesItem = { title: 'Yes', isCloseAffordance: false };
309+
const alwaysItem = { title: 'Always Save', isCloseAffordance: false };
310+
const noItem = { title: 'No', isCloseAffordance: true }
311+
const message = 'Query file has unsaved changes. Save now?';
312+
const chosenItem = await vscode.window.showInformationMessage(message, { modal: true }, yesItem, alwaysItem, noItem);
313+
314+
if (chosenItem === alwaysItem) {
315+
await config.AUTOSAVE_SETTING.updateValue(true, vscode.ConfigurationTarget.Workspace);
316+
return true;
317+
}
318+
319+
if (chosenItem === yesItem) {
320+
return true;
321+
}
303322
}
304323
}
324+
return false;
305325
}
306326

307327
type SelectedQuery = {
@@ -357,7 +377,9 @@ export async function determineSelectedQuery(selectedResourceUri: vscode.Uri | u
357377
// if the same file is open with unsaved changes in the active editor,
358378
// then prompt the user to save it first.
359379
if (editor !== undefined && editor.document.uri.fsPath === queryPath) {
360-
await promptUserToSaveChanges(editor.document);
380+
if (await promptUserToSaveChanges(editor.document)) {
381+
editor.document.save();
382+
}
361383
}
362384

363385
let quickEvalPosition: messages.Position | undefined = undefined;

0 commit comments

Comments
 (0)