Skip to content
Open
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
26 changes: 12 additions & 14 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,22 @@ import { runCommand } from './util/scripts';
import { looksLikePath, resolvePath, findWorkspaceRoot } from './util/path';
import { DiagnosticMetadataStore, diagnosticsUnion } from './util/diagnostics';
import { CodeActionProvider } from './util/codeActions';
import { writeSuppressionToProjectFile } from './util/files';
import { ProjectFileStore, 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> = {};
// To keep track of warnings for files created from analysis of other files we save their relations to fileRelationMap
let fileRelationMap: Record<string, Set<string>> = {};
// Some diagnostics have symbol names associated with them, which we keep track of in diagnosticMetadataStore
const diagnosticMetadataStore = new DiagnosticMetadataStore();
// The ProjectFileStore is usd to keep track of the users project file through different context
const projectFileStore = new ProjectFileStore();

let previewAnalysisTimer: NodeJS.Timeout | undefined;
let previewedDocument: vscode.TextDocument | undefined;
let cppcheckProgressIndicator: vscode.StatusBarItem;
let severityOption: vscode.StatusBarItem;
let checksRunning = false;
let cppcheckProjectFileUri: vscode.Uri | undefined;

enum SeverityNumber {
Info = 0,
Expand Down Expand Up @@ -131,7 +132,7 @@ export async function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.languages.registerCodeActionsProvider(
{ pattern: "**/*" },
new CodeActionProvider(diagnosticMetadataStore),
new CodeActionProvider(diagnosticMetadataStore, projectFileStore),
{
providedCodeActionKinds: [
vscode.CodeActionKind.QuickFix
Expand All @@ -158,25 +159,26 @@ export async function activate(context: vscode.ExtensionContext) {
vscode.commands.registerCommand(
"cppcheck-official.suppressWarningAll",
async (diagnosticCode : string, file? : string, symbolName? : string) => {
if (cppcheckProjectFileUri) {
const success = await writeSuppressionToProjectFile(cppcheckProjectFileUri, diagnosticCode, file, symbolName);
const projectFileUri = projectFileStore.getUri();
if (projectFileUri && projectFileStore.hasCppcheckProjectFile()) {
const success = await writeSuppressionToProjectFile(projectFileUri, diagnosticCode, file, symbolName);
if (success) {
// Construct information message to display to the user
const fileMessagePart = file ? ` for file ${file}` : '';
const symbolNameMessagePart = symbolName ? ` for symbol name ${symbolName}` : '';
const fileOrSymbolExtraMessage = file || symbolName ? '. Note: you have to re-analyze the file for the suppression to take effect.' : '';
const completeInformationMessageText = `Suppression of ${diagnosticCode} added to project file ${cppcheckProjectFileUri.toString()}${fileMessagePart}${symbolNameMessagePart}${fileOrSymbolExtraMessage}`;
const completeInformationMessageText = `Suppression of ${diagnosticCode} added to project file ${projectFileStore.getUri()?.toString()}${fileMessagePart}${symbolNameMessagePart}${fileOrSymbolExtraMessage}`;
vscode.window.showInformationMessage(completeInformationMessageText);

// Only hide warnings if suppression is global, since hide command does not support file or symbol filter for now
if (!file && !symbolName) {
await vscode.commands.executeCommand('cppcheck-official.hideWarningType', diagnosticCode);
}
} else {
vscode.window.showErrorMessage(`Failed to add suppression of ${diagnosticCode} to project file ${cppcheckProjectFileUri.toString()}`);
vscode.window.showErrorMessage(`Failed to add suppression of ${diagnosticCode} to project file ${projectFileStore.getUri()?.toString()}`);
}
} else {
vscode.window.showInformationMessage(`Adding suppression is currently only supported for .cppcheck project files`);
throw new Error(`Cppcheck Official error: Command 'cppcheck-official.suppressWarningAll' for project file level suppression called without project file present!`);
}
}
)
Expand Down Expand Up @@ -520,7 +522,7 @@ async function runCppcheckOnFileXML(
});

let usingProjectFile = false;
cppcheckProjectFileUri = undefined;
projectFileStore.clear();

const args = [
'--enable=all',
Expand All @@ -532,12 +534,8 @@ async function runCppcheckOnFileXML(
if (processedArgs.includes("--project=")) {
usingProjectFile = true;
args.push(`--file-filter=${filePath}`);
// If project file is of type .cppcheck we keep track of it
var projectFilePath = processedArgs.split('--project=')[1].split(' ')[0];
var projectFileType = projectFilePath.split('.')[1];
if (projectFileType.toLowerCase() === 'cppcheck') {
cppcheckProjectFileUri = vscode.Uri.file(projectFilePath);
}
projectFileStore.setUri(vscode.Uri.file(projectFilePath));
} else {
args.push(
'--suppress=unusedFunction',
Expand Down
75 changes: 41 additions & 34 deletions src/util/codeActions.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import * as vscode from 'vscode';
import { DiagnosticMetadataStore } from './diagnostics';
import { ProjectFileStore } from './files';
export class CodeActionProvider implements vscode.CodeActionProvider {
constructor(
private readonly metadataStore: DiagnosticMetadataStore
private readonly metadataStore: DiagnosticMetadataStore,
private readonly projectFileStore: ProjectFileStore
) {}
provideCodeActions(
document: vscode.TextDocument,
Expand Down Expand Up @@ -55,39 +57,6 @@ export class CodeActionProvider implements vscode.CodeActionProvider {
suppressAction.diagnostics = [diagnostic];
actions.push(suppressAction);

// Set up an action for suppressing warning of a given type universally
const suppressTypeAction = new vscode.CodeAction(
`Suppress warning type ${diagnosticCode} universally (in project file)`,
vscode.CodeActionKind.QuickFix
);

suppressTypeAction.command = {
command: "cppcheck-official.suppressWarningAll",
title: "Suppress warning universally",
arguments: [diagnosticCode]
};

suppressTypeAction.diagnostics = [diagnostic];
actions.push(suppressTypeAction);

// Set up an action for suppressing warning based on file or symbol name
const symbol = this.metadataStore.get(diagnostic)?.symbolName;
const suppressAdvancedAction = new vscode.CodeAction(
symbol
? `Suppress warning ${diagnosticCode} based on file and / or symbol`
:`Suppress warning ${diagnosticCode} based on file`,
vscode.CodeActionKind.QuickFix
);

suppressAdvancedAction.command = {
command: "cppcheck-official.suppressWarningAdvanced",
title: "Suppress warning advanced",
arguments: [diagnosticCode, document, diagnostic]
};

suppressAdvancedAction.diagnostics = [diagnostic];
actions.push(suppressAdvancedAction);

// Set up an action for hiding a warning
const hideAction = new vscode.CodeAction(
`Hide this ${diagnosticCode} warning`,
Expand Down Expand Up @@ -117,6 +86,44 @@ export class CodeActionProvider implements vscode.CodeActionProvider {

hideTypeAction.diagnostics = [diagnostic];
actions.push(hideTypeAction);

/*
* Actions only applicable if project file is used
*/
if (this.projectFileStore.hasCppcheckProjectFile()) {
// Set up an action for suppressing warning of a given type universally
const suppressTypeAction = new vscode.CodeAction(
`Suppress warning type ${diagnosticCode} universally (in project file)`,
vscode.CodeActionKind.QuickFix
);

suppressTypeAction.command = {
command: "cppcheck-official.suppressWarningAll",
title: "Suppress warning universally",
arguments: [diagnosticCode]
};

suppressTypeAction.diagnostics = [diagnostic];
actions.push(suppressTypeAction);

// Set up an action for suppressing warning based on file or symbol name
const symbol = this.metadataStore.get(diagnostic)?.symbolName;
const suppressAdvancedAction = new vscode.CodeAction(
symbol
? `Suppress warning ${diagnosticCode} based on file and / or symbol`
:`Suppress warning ${diagnosticCode} based on file`,
vscode.CodeActionKind.QuickFix
);

suppressAdvancedAction.command = {
command: "cppcheck-official.suppressWarningAdvanced",
title: "Suppress warning advanced",
arguments: [diagnosticCode, document, diagnostic]
};

suppressAdvancedAction.diagnostics = [diagnostic];
actions.push(suppressAdvancedAction);
}
}

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

export class ProjectFileStore {
private projectFileUri : vscode.Uri | undefined;

setUri(newProjectFileUri: vscode.Uri) {
this.projectFileUri = newProjectFileUri;
}

getUri() {
return this.projectFileUri;
}

hasCppcheckProjectFile() {
const uri = this.getUri();
if (!uri) {
return false;
}
var projectFileType = uri.path.split('.')[1];
return projectFileType.toLowerCase() === 'cppcheck';
}

clear() {
this.projectFileUri = undefined;
}
}

export async function writeSuppressionToProjectFile(projectFileUri : vscode.Uri, warningType : String, file? : String, symbolName? : String) : Promise<boolean> {
const fileType = projectFileUri.toString().split('.')[1];
if (fileType !== 'cppcheck') {
Expand Down
Loading