Skip to content

Commit 44ce9a4

Browse files
committed
feature #45/ dynamic argument flags
1 parent f65c8c3 commit 44ce9a4

2 files changed

Lines changed: 48 additions & 1 deletion

File tree

src/extension.ts

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,17 @@ import * as path from "path";
44
import * as os from "os";
55
import * as xml2js from 'xml2js';
66

7+
import { runScript } from './util/scripts';
8+
79
enum SeverityNumber {
810
Info = 0,
911
Warning = 1,
1012
Error = 2
1113
}
1214

15+
// If a script generates arguments at extension activation they are saved in dynamicArgs
16+
const dynamicArgs : Array<string> = [];
17+
1318
const criticalWarningTypes = [
1419
'cppcheckError',
1520
'cppcheckLimit',
@@ -90,6 +95,20 @@ export function activate(context: vscode.ExtensionContext) {
9095
const diagnosticCollection = vscode.languages.createDiagnosticCollection("Cppcheck");
9196
context.subscriptions.push(diagnosticCollection);
9297

98+
// If an argument requires us to run any scripts we do it here
99+
const config = vscode.workspace.getConfiguration();
100+
const args = config.get<string>("cppcheck-official.arguments", "");
101+
const argsWithScripts = args.split(" ").filter((arg) => arg.includes('§{'));
102+
argsWithScripts.forEach(async (arg) => {
103+
// argType will look like e.g. --project
104+
const argType = arg.split("=")[0];
105+
const argValue = arg.split("=")[1];
106+
// Remove ${ from the beginning and slice } away from the end of argValue
107+
const scriptCommand = argValue.split("{")[1].slice(0, - 1);
108+
const scriptOutput = await runScript(scriptCommand);
109+
dynamicArgs.push(`${argType}=${scriptOutput}`);
110+
});
111+
93112
// set up a map of timers per document URI for debounce for continuous analysis triggers
94113
// I.e. document has been changed -> DEBOUNCE_MS time passed since last change -> run cppcheck
95114
const debounceTimers: Map<string, NodeJS.Timeout> = new Map();
@@ -198,8 +217,12 @@ async function runCppcheckOnFileXML(
198217
const filePath = document.fileName.replaceAll('\\', '/');
199218
const minSevNum = parseMinSeverity(minSevString);
200219

220+
// Arguments specified with scripts are replaced with script output (dynamicArgs)
221+
const staticArgs = extraArgs.split(" ").filter((arg) => !arg.includes("${"));
222+
const allArgs = staticArgs.concat(dynamicArgs);
223+
201224
// Resolve paths for arguments where applicable
202-
const extraArgsParsed = (extraArgs.split(" ")).map((arg) => {
225+
const extraArgsParsed = allArgs.map((arg) => {
203226
if (arg.startsWith('--project')) {
204227
const splitArg = arg.split('=');
205228
return `${splitArg[0]}=${resolvePath(splitArg[1])}`;

src/util/scripts.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { execFile } from "child_process";
2+
3+
function runScript(scriptCommand: string): Promise<string> {
4+
const commandSplit = scriptCommand.split(" ");
5+
const scriptLang = commandSplit[0];
6+
const scriptPath = commandSplit[1];
7+
// Additional args could be added here, i.e. name of output file if applicable
8+
return new Promise((resolve, reject) => {
9+
execFile(scriptLang, [scriptPath], (error, stdout, stderr) => {
10+
if (error) {
11+
reject(error);
12+
return;
13+
}
14+
if (stderr) {
15+
console.warn("Script stderr:", stderr);
16+
}
17+
const result = stdout.trim();
18+
resolve(result);
19+
});
20+
});
21+
}
22+
23+
24+
export { runScript };

0 commit comments

Comments
 (0)