Skip to content

Commit e4df717

Browse files
authored
Merge pull request #324 from jcreedcmu/jcreed/always-save
Add 'Always Save' to running unsaved query dialog
2 parents 9ea4b39 + e5305ab commit e4df717

File tree

3 files changed

+48
-13
lines changed

3 files changed

+48
-13
lines changed

extensions/ql-vscode/package.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,11 @@
141141
"default": false,
142142
"description": "Enable debug logging and tuple counting when running CodeQL queries. This information is useful for debugging query performance."
143143
},
144+
"codeQL.runningQueries.autoSave": {
145+
"type": "boolean",
146+
"default": false,
147+
"description": "Enable automatically saving a modified query file when running a query."
148+
},
144149
"codeQL.queryHistory.format": {
145150
"type": "string",
146151
"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: 33 additions & 12 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';
@@ -121,6 +122,9 @@ export class QueryInfo {
121122
): Promise<messages.CompilationMessage[]> {
122123
let compiled: messages.CheckQueryResult | undefined;
123124
try {
125+
const target = this.quickEvalPosition ? {
126+
quickEval: { quickEvalPos: this.quickEvalPosition }
127+
} : { query: {} };
124128
const params: messages.CompileQueryParams = {
125129
compilationOptions: {
126130
computeNoLocationUrls: true,
@@ -136,11 +140,7 @@ export class QueryInfo {
136140
},
137141
queryToCheck: this.program,
138142
resultPath: this.compiledQueryPath,
139-
target: this.quickEvalPosition ? {
140-
quickEval: { quickEvalPos: this.quickEvalPosition }
141-
} : {
142-
query: {}
143-
}
143+
target,
144144
};
145145

146146
compiled = await helpers.withProgress({
@@ -259,7 +259,7 @@ async function checkDbschemeCompatibility(
259259

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

@@ -294,14 +294,33 @@ async function checkDbschemeCompatibility(
294294
}
295295
}
296296

297-
/** Prompts the user to save `document` if it has unsaved changes. */
298-
async function promptUserToSaveChanges(document: vscode.TextDocument): Promise<void> {
297+
/**
298+
* Prompts the user to save `document` if it has unsaved changes.
299+
* Returns true if we should save changes.
300+
*/
301+
async function promptUserToSaveChanges(document: vscode.TextDocument): Promise<boolean> {
299302
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();
303+
if (config.AUTOSAVE_SETTING.getValue()) {
304+
return true;
305+
}
306+
else {
307+
const yesItem = { title: 'Yes', isCloseAffordance: false };
308+
const alwaysItem = { title: 'Always Save', isCloseAffordance: false };
309+
const noItem = { title: 'No', isCloseAffordance: true }
310+
const message = 'Query file has unsaved changes. Save now?';
311+
const chosenItem = await vscode.window.showInformationMessage(message, { modal: true }, yesItem, alwaysItem, noItem);
312+
313+
if (chosenItem === alwaysItem) {
314+
await config.AUTOSAVE_SETTING.updateValue(true, vscode.ConfigurationTarget.Workspace);
315+
return true;
316+
}
317+
318+
if (chosenItem === yesItem) {
319+
return true;
320+
}
303321
}
304322
}
323+
return false;
305324
}
306325

307326
type SelectedQuery = {
@@ -357,7 +376,9 @@ export async function determineSelectedQuery(selectedResourceUri: vscode.Uri | u
357376
// if the same file is open with unsaved changes in the active editor,
358377
// then prompt the user to save it first.
359378
if (editor !== undefined && editor.document.uri.fsPath === queryPath) {
360-
await promptUserToSaveChanges(editor.document);
379+
if (await promptUserToSaveChanges(editor.document)) {
380+
editor.document.save();
381+
}
361382
}
362383

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

0 commit comments

Comments
 (0)