diff --git a/src/extension.ts b/src/extension.ts index 5a88690..ad88dfd 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -8,7 +8,7 @@ import { runCommand } from './util/scripts'; import { looksLikePath, resolvePath, findWorkspaceRoot } from './util/path'; import { diagnosticsUnion } from './util/diagnostics'; import { CodeActionProvider } from './util/codeActions'; -import { writeSuppressionToProjectFile } from './util/files'; +import { parseSuppressionsFromProjectFile, writeSuppressionToProjectFile } from './util/files'; // To keep track of document changes we save hashed versions of their content to this record let documentHashMemory : Record = {}; @@ -466,12 +466,16 @@ async function runCppcheckOnFileXML( let usingProjectFile = false; cppcheckProjectFileUri = undefined; - const args = [ + // Cast to Set and back to array to filter out duplicate arguments + const args = [...new Set([ '--enable=all', '--inline-suppr', '--xml', + '--suppress=unusedFunction', + '--suppress=missingInclude', + '--suppress=missingIncludeSystem', ...argsParsed, - ].filter(Boolean); + ])].filter(Boolean); if (processedArgs.includes("--project=")) { usingProjectFile = true; @@ -481,12 +485,16 @@ async function runCppcheckOnFileXML( var projectFileType = projectFilePath.split('.')[1]; if (projectFileType.toLowerCase() === 'cppcheck') { cppcheckProjectFileUri = vscode.Uri.file(projectFilePath); + // Duplicate suppressions returns an error from cppcheck, so for ease of use we filter these out + const projectFileSuppressions = await parseSuppressionsFromProjectFile(cppcheckProjectFileUri); + for (const projectFileSuppression of projectFileSuppressions) { + const duplicateSuppressionIndex = args.findIndex((a) => a === `--suppress=${projectFileSuppression}`); + if (duplicateSuppressionIndex !== -1) { + args.splice(duplicateSuppressionIndex, 1); + } + } } } else { - args.push( - '--suppress=unusedFunction', - '--suppress=missingInclude', - '--suppress=missingIncludeSystem'); args.push(filePath); } diff --git a/src/util/files.ts b/src/util/files.ts index 00e0e2d..ba1e644 100644 --- a/src/util/files.ts +++ b/src/util/files.ts @@ -1,5 +1,29 @@ import * as vscode from 'vscode'; +export async function parseSuppressionsFromProjectFile(projectFileUri: vscode.Uri) : Promise { + const fileType = projectFileUri.toString().split('.')[1]; + if (fileType !== 'cppcheck') { + throw new Error(`Function parseSuppressionsFromProjectFile only supports parsing .cppcheck project files! Recieved file is of type .${fileType}`); + } + + // Open project file with vscode workspace API + const document = await vscode.workspace.openTextDocument(projectFileUri); + const text = document.getText(); + + // Parse suppression lines and map to an array of error codes, e.g. ['unusedFunction', 'missingInclude'] + const match = /]*>([\s\S]*?)<\/suppressions>/m.exec(text); + if (!match) { + return []; + } else { + const suppressionsRegex = /]*>([\s\S]*?)<\/suppression>/gm; + const suppressions = match[0].matchAll(suppressionsRegex); + if (!suppressions) { + return []; + } + return [...suppressions].map(m => m[1]); + } +} + export async function writeSuppressionToProjectFile(projectFileUri : vscode.Uri, warningType : String) : Promise { const fileType = projectFileUri.toString().split('.')[1]; if (fileType !== 'cppcheck') {