Skip to content

Commit 26a524f

Browse files
committed
Create SPARK commands that ask for GNATprove options
1 parent c1c5001 commit 26a524f

File tree

11 files changed

+162
-87
lines changed

11 files changed

+162
-87
lines changed

integration/vscode/ada/package.json

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1183,30 +1183,66 @@
11831183
"icon": "$(run)",
11841184
"when": "ADA_PROJECT_CONTEXT"
11851185
},
1186+
{
1187+
"command": "ada.spark.tasks.cleanProject",
1188+
"title": "Clean project for proof",
1189+
"category": "SPARK",
1190+
"when": "ADA_PROJECT_CONTEXT"
1191+
},
1192+
{
1193+
"command": "ada.spark.tasks.examineProject",
1194+
"title": "Examine project",
1195+
"category": "SPARK",
1196+
"when": "ADA_PROJECT_CONTEXT"
1197+
},
1198+
{
1199+
"command": "ada.spark.tasks.examineFile",
1200+
"title": "Examine file",
1201+
"category": "SPARK",
1202+
"when": "editorLangId == ada && editorTextFocus"
1203+
},
1204+
{
1205+
"command": "ada.spark.tasks.examineSubprogram",
1206+
"title": "Examine subprogram",
1207+
"category": "SPARK",
1208+
"when": "editorLangId == ada && editorTextFocus"
1209+
},
1210+
{
1211+
"command": "ada.spark.tasks.proveProject",
1212+
"title": "Prove project",
1213+
"category": "SPARK",
1214+
"when": "ADA_PROJECT_CONTEXT"
1215+
},
11861216
{
11871217
"command": "ada.spark.tasks.proveFile",
1188-
"title": "Prove file (task wrapper)",
1218+
"title": "Prove file",
11891219
"category": "SPARK",
11901220
"when": "editorLangId == ada && editorTextFocus"
11911221
},
11921222
{
11931223
"command": "ada.spark.tasks.proveSubprogram",
1194-
"title": "Prove subprogram (task wrapper)",
1224+
"title": "Prove subprogram",
11951225
"category": "SPARK",
11961226
"when": "editorLangId == ada && editorTextFocus"
11971227
},
11981228
{
11991229
"command": "ada.spark.tasks.proveSelectedRegion",
1200-
"title": "Prove selected region (task wrapper)",
1230+
"title": "Prove selected region",
12011231
"category": "SPARK",
12021232
"when": "editorLangId == ada && editorTextFocus"
12031233
},
12041234
{
12051235
"command": "ada.spark.tasks.proveLine",
1206-
"title": "Prove line (task wrapper)",
1236+
"title": "Prove line",
12071237
"category": "SPARK",
12081238
"when": "editorLangId == ada && editorTextFocus"
12091239
},
1240+
{
1241+
"command": "ada.spark.askGNATproveOptions",
1242+
"title": "Select GNATprove options...",
1243+
"category": "SPARK",
1244+
"when": "ADA_PROJECT_CONTEXT"
1245+
},
12101246
{
12111247
"command": "ada.loadGnatCovXMLReport",
12121248
"category": "Ada",

integration/vscode/ada/src/AdaCodeLensProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
CMD_BUILD_AND_DEBUG_MAIN,
1717
CMD_BUILD_AND_RUN_GNATEMULATOR,
1818
CMD_BUILD_AND_RUN_MAIN,
19-
CMD_SPARK_PROVE_SUBP
19+
CMD_SPARK_PROVE_SUBP,
2020
} from './constants';
2121
import { envHasExec, getSymbols } from './helpers';
2222
import { adaExtState } from './extension';

integration/vscode/ada/src/ExtensionState.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
CMD_RESTART_LANG_SERVERS,
1414
CMD_SHOW_ADA_LS_OUTPUT,
1515
CMD_SHOW_EXTENSION_LOGS,
16-
CMD_SHOW_GPR_LS_OUTPUT
16+
CMD_SHOW_GPR_LS_OUTPUT,
1717
} from './constants';
1818
import { AdaInitialDebugConfigProvider, initializeDebugging } from './debugConfigProvider';
1919
import { logger } from './extension';

integration/vscode/ada/src/commands.ts

Lines changed: 15 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@ import {
1212
CMD_BUILD_AND_DEBUG_MAIN,
1313
CMD_BUILD_AND_RUN_GNATEMULATOR,
1414
CMD_BUILD_AND_RUN_MAIN,
15-
CMD_GET_PROJECT_FILE,
1615
CMD_GPR_PROJECT_ARGS,
1716
CMD_RESTART_LANG_SERVERS,
1817
CMD_SHOW_ADA_LS_OUTPUT,
1918
CMD_SHOW_EXTENSION_LOGS,
2019
CMD_SHOW_GPR_LS_OUTPUT,
2120
CMD_SPARK_ASK_OPTIONS,
21+
CMD_SPARK_CURRENT_GNATPROVE_OPTIONS,
2222
CMD_SPARK_LIMIT_REGION_ARG,
2323
CMD_SPARK_LIMIT_SUBP_ARG,
2424
CMD_SPARK_PROVE_SUBP,
@@ -27,13 +27,11 @@ import { AdaConfig, getOrAskForProgram, initializeConfig } from './debugConfigPr
2727
import { adaExtState, logger, mainOutputChannel } from './extension';
2828
import { loadGnatCoverageReport } from './gnattest';
2929
import { findAdaMain, getProjectFileRelPath, getSymbols } from './helpers';
30-
import { askSPARKOptions } from './sparkOptionsPicker';
30+
import { registerSPARKTaskWrappers } from './sparkCommands';
31+
import { askSPARKOptions, getLastSPARKOptions } from './sparkOptionsPicker';
3132
import {
3233
DEFAULT_PROBLEM_MATCHERS,
3334
SimpleTaskDef,
34-
TASK_PROVE_FILE_PLAIN_NAME,
35-
TASK_PROVE_LINE_PLAIN_NAME,
36-
TASK_PROVE_REGION_PLAIN_NAME,
3735
TASK_PROVE_SUPB_PLAIN_NAME,
3836
TASK_TYPE_SPARK,
3937
findBuildAndRunTask,
@@ -168,9 +166,6 @@ export function registerCommands(context: vscode.ExtensionContext, clients: Exte
168166
context.subscriptions.push(
169167
vscode.commands.registerCommand(CMD_GPR_PROJECT_ARGS, gprProjectArgs),
170168
);
171-
context.subscriptions.push(
172-
vscode.commands.registerCommand(CMD_GET_PROJECT_FILE, getProjectFromConfigOrALS),
173-
);
174169
context.subscriptions.push(
175170
vscode.commands.registerCommand(CMD_SPARK_LIMIT_SUBP_ARG, sparkLimitSubpArg),
176171
);
@@ -182,6 +177,9 @@ export function registerCommands(context: vscode.ExtensionContext, clients: Exte
182177
);
183178

184179
context.subscriptions.push(commands.registerCommand(CMD_SPARK_ASK_OPTIONS, askSPARKOptions));
180+
context.subscriptions.push(
181+
commands.registerCommand(CMD_SPARK_CURRENT_GNATPROVE_OPTIONS, getLastSPARKOptions),
182+
);
185183

186184
context.subscriptions.push(
187185
commands.registerCommand('ada.loadGnatCovXMLReport', loadGnatCovXMLReport),
@@ -191,36 +189,7 @@ export function registerCommands(context: vscode.ExtensionContext, clients: Exte
191189
vscode.commands.registerCommand('ada.issueReporter', openReportIssue),
192190
);
193191

194-
registerTaskWrappers(context);
195-
}
196-
197-
/**
198-
* The following commands are wrappers around VS Code tasks that allow setting
199-
* key shortcuts to the wrapped tasks. Technically it is possible to set
200-
* shortcuts directly on the `workbench.action.tasks.runTask` command with the
201-
* target task as a command argument, however in several places the UI doesn't
202-
* take into consideration the command argument, and thus it becomes impossible
203-
* to distinguish the different tasks, and worse, our shortcut becomes
204-
* displayed for the vanilla `Run Task` command.
205-
*
206-
* To avoid all that, we provide these commands as wrappers.
207-
*/
208-
function registerTaskWrappers(context: vscode.ExtensionContext) {
209-
const sparkTaskWrappers: { [cmdId: string]: string } = {
210-
'ada.spark.tasks.proveFile': `${TASK_TYPE_SPARK}: ${TASK_PROVE_FILE_PLAIN_NAME}`,
211-
'ada.spark.tasks.proveSubprogram': `${TASK_TYPE_SPARK}: ${TASK_PROVE_SUPB_PLAIN_NAME}`,
212-
// eslint-disable-next-line max-len
213-
'ada.spark.tasks.proveSelectedRegion': `${TASK_TYPE_SPARK}: ${TASK_PROVE_REGION_PLAIN_NAME}`,
214-
'ada.spark.tasks.proveLine': `${TASK_TYPE_SPARK}: ${TASK_PROVE_LINE_PLAIN_NAME}`,
215-
};
216-
for (const cmdId of Object.keys(sparkTaskWrappers)) {
217-
const taskId = sparkTaskWrappers[cmdId];
218-
context.subscriptions.push(
219-
commands.registerCommand(cmdId, () =>
220-
commands.executeCommand('workbench.action.tasks.runTask', taskId),
221-
),
222-
);
223-
}
192+
registerSPARKTaskWrappers(context);
224193
}
225194

226195
/**
@@ -823,7 +792,6 @@ async function buildAndDebugSpecifiedMainWithGNATemulator(main: vscode.Uri): Pro
823792
*/
824793
export async function gprProjectArgs(): Promise<string[]> {
825794
const scenarioArgs = gprScenarioArgs();
826-
827795
return ['-P', await getProjectFromConfigOrALS()].concat(scenarioArgs);
828796
}
829797

@@ -892,7 +860,7 @@ export async function sparkLimitSubpArg(): Promise<string[]> {
892860
* zero-based while the `gnatprove` convention is one-based. This function does
893861
* the conversion.
894862
*/
895-
function getLimitSubpArg(filename: string, range: vscode.Range) {
863+
function getLimitSubpArg(filename: string, range: vscode.Range): string {
896864
return `--limit-subp=${filename}:${range.start.line + 1}`;
897865
}
898866

@@ -1021,8 +989,8 @@ async function sparkProveSubprogram(
1021989
);
1022990

1023991
/**
1024-
* Replace the subp-region argument based on the parameter given to the
1025-
* command.
992+
* Replace the subp-region command argument with the --limit-subp argument
993+
* pointing to the place where this command was triggered.
1026994
*/
1027995
const taskDef = newTask.definition as SimpleTaskDef;
1028996
assert(taskDef.args);
@@ -1036,17 +1004,6 @@ async function sparkProveSubprogram(
10361004
* with the same name in the task history.
10371005
*/
10381006
newTask.name = `${task.name} - ${fileBasename}:${range.start.line + 1}`;
1039-
1040-
/**
1041-
* Add a command to ask the User for options. We do this instead of
1042-
* pre-evaluating the options so that all invocations on the same
1043-
* subprogram have the same set of (unevaluated) arguments, which means
1044-
* that only one task shows up in the task history for each subprogram.
1045-
* If we pre-evaluated the options, then each different set of User
1046-
* choices would yield a different entry in the task history which is
1047-
* noisy.
1048-
*/
1049-
taskDef.args.splice(regionArgIdx + 1, 0, `\${command:${CMD_SPARK_ASK_OPTIONS}}`);
10501007
} else {
10511008
throw Error(
10521009
`Task '${getConventionalTaskLabel(task)}' is missing a '${regionArg}' argument`,
@@ -1059,6 +1016,11 @@ async function sparkProveSubprogram(
10591016
const resolvedTask = await adaExtState.getSparkTaskProvider()?.resolveTask(newTask);
10601017
assert(resolvedTask);
10611018

1019+
/**
1020+
* Ask for GNATprove options
1021+
*/
1022+
await commands.executeCommand(CMD_SPARK_ASK_OPTIONS);
1023+
10621024
/**
10631025
* Execute the task.
10641026
*/

integration/vscode/ada/src/constants.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ export const CMD_SPARK_LIMIT_SUBP_ARG = 'ada.spark.limitSubpArg';
5555
export const CMD_SPARK_LIMIT_REGION_ARG = 'ada.spark.limitRegionArg';
5656
export const CMD_SPARK_PROVE_SUBP = 'ada.spark.proveSubprogram';
5757
export const CMD_SPARK_ASK_OPTIONS = 'ada.spark.askGNATproveOptions';
58+
export const CMD_SPARK_CURRENT_GNATPROVE_OPTIONS = 'ada.spark.gnatproveOptions';
59+
5860
/**
5961
* Identifier for the command that shows the extension's output in the Output panel.
6062
*/

integration/vscode/ada/src/e3Testsuite.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,7 +560,7 @@ function getRootItemId(ts: Testsuite): string {
560560
* If no path is configured, it automatically searches through predefined candidate locations
561561
* and uses the first existing file. It also retrieves the Python executable configuration.
562562
*
563-
* @returns {Testsuite} An object containing the testsuite URI and Python executable path
563+
* @returns An object containing the testsuite URI and Python executable path
564564
*
565565
* @remarks
566566
* The function searches for testsuite files in the following order:

integration/vscode/ada/src/gnatTaskProvider.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { DEFAULT_PROBLEM_MATCHERS, WarningMessageExecution } from './taskProvide
2323
/**
2424
* Callback to provide an extra argument for a tool
2525
*/
26-
type ExtraArgCallback = () => Promise<string[]>;
26+
type ExtraArgCallback = () => Promise<string[] | string>;
2727

2828
/**
2929
* Tool description

integration/vscode/ada/src/helpers.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,6 @@ export function setTerminalEnvironment(
203203
}
204204
}
205205
}
206-
207-
logger.debug(`New process environment after update:`);
208-
for (const key in targetEnv) {
209-
const value = targetEnv[key];
210-
if (value) {
211-
logger.debug(`${key}=${value}`);
212-
}
213-
}
214206
}
215207

216208
export function assertSupportedEnvironments(mainChannel: winston.Logger) {
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
import * as vscode from 'vscode';
2+
import { commands } from 'vscode';
3+
import { CMD_SPARK_ASK_OPTIONS } from './constants';
4+
import { sparkTasks, TASK_TYPE_SPARK } from './taskProviders';
5+
6+
/**
7+
* The following commands are wrappers around VS Code tasks that allow setting
8+
* key shortcuts to the wrapped tasks. Technically it is possible to set
9+
* shortcuts directly on the `workbench.action.tasks.runTask` command with the
10+
* target task as a command argument, however in several places the UI doesn't
11+
* take into consideration the command argument, and thus it becomes impossible
12+
* to distinguish the different tasks, and worse, our shortcut becomes
13+
* displayed for the vanilla `Run Task` command.
14+
*
15+
* To avoid all that, we provide these commands as wrappers.
16+
*
17+
* In addition, these wrappers also prompt for GNATprove options before running
18+
* the task.
19+
*/
20+
export function registerSPARKTaskWrappers(context: vscode.ExtensionContext) {
21+
for (const task of sparkTasks) {
22+
if (task.commandId) {
23+
context.subscriptions.push(
24+
commands.registerCommand(
25+
task.commandId,
26+
sparkTaskWrapper(task.label, !task.noOptionPicker),
27+
),
28+
);
29+
}
30+
}
31+
}
32+
33+
function sparkTaskWrapper(taskPlainName: string, optionPicker = true) {
34+
return async () => {
35+
if (optionPicker) {
36+
await commands.executeCommand(CMD_SPARK_ASK_OPTIONS);
37+
}
38+
await commands.executeCommand(
39+
'workbench.action.tasks.runTask',
40+
`${TASK_TYPE_SPARK}: ${taskPlainName}`,
41+
);
42+
};
43+
}

integration/vscode/ada/src/sparkOptionsPicker.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,3 +129,14 @@ function toCLIArgs(choices: Partial<PickerState>): string[] {
129129

130130
return args;
131131
}
132+
133+
export function getLastSPARKOptions(): string[] {
134+
const savedState =
135+
adaExtState.context.workspaceState.get<Partial<SavedPickerState>>(WS_STATE_KEY_PICKER) ??
136+
{};
137+
const pickerState: Partial<PickerState> = {
138+
proofLevel: proofLevels.find((v) => v.label == savedState?.proofLevelLabel),
139+
options: options.filter((o) => savedState?.optionLabels?.find((v) => v == o.label)),
140+
};
141+
return toCLIArgs(pickerState);
142+
}

0 commit comments

Comments
 (0)