Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<string, string> = {};
Expand Down Expand Up @@ -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;
Expand All @@ -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}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately it's not enough to look at the id, here is the code to detect duplicates in cppcheck:

        bool isSameParameters(const Suppression &other) const {
            return errorId == other.errorId &&
                   fileName == other.fileName &&
                   lineNumber == other.lineNumber &&
                   symbolName == other.symbolName &&
                   hash == other.hash &&
                   thisAndNextLine == other.thisAndNextLine;
        }

Only id, file and line number can be supplied on the command line though, so should be enough to check those.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are the possible formats for --suppress=:

[error id]:[filename]:[line]
[error id]:[filename2]
[error id]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's maybe a bit unnecessary to have this logic in both places though, I think it would be good to have a --ignore-duplicate-suppressions option instead. I can create a ticket.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay makes sense, I'll close this PR for now then

if (duplicateSuppressionIndex !== -1) {
args.splice(duplicateSuppressionIndex, 1);
}
}
}
} else {
args.push(
'--suppress=unusedFunction',
'--suppress=missingInclude',
'--suppress=missingIncludeSystem');
args.push(filePath);
}

Expand Down
24 changes: 24 additions & 0 deletions src/util/files.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
import * as vscode from 'vscode';

export async function parseSuppressionsFromProjectFile(projectFileUri: vscode.Uri) : Promise<String[]> {
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 = /<suppressions\b[^>]*>([\s\S]*?)<\/suppressions>/m.exec(text);
if (!match) {
return [];
} else {
const suppressionsRegex = /<suppression\b[^>]*>([\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<boolean> {
const fileType = projectFileUri.toString().split('.')[1];
if (fileType !== 'cppcheck') {
Expand Down
Loading