Skip to content

Commit c3aa058

Browse files
authored
fix/ avoid overwriting existing diagnostics of included files when opening a new file (#85)
* fix/ avoid overwriting existing diagnostics of included files when opening a new file * fix checking line length in wrong file
1 parent cdf8b1a commit c3aa058

2 files changed

Lines changed: 38 additions & 7 deletions

File tree

src/extension.ts

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import * as crypto from 'crypto';
66
import { documentationLinkMap, getPremiumCertLink } from './util/documentation';
77
import { runCommand } from './util/scripts';
88
import { looksLikePath, resolvePath, findWorkspaceRoot } from './util/path';
9+
import { diagnosticsUnion } from './util/diagnostics';
910

1011
// To keep track of document changes we save hashed versions of their content to this record
1112
let documentHashMemory : Record<string, string> = {};
@@ -349,7 +350,6 @@ async function runCppcheckOnFileXML(
349350

350351
const errors = result.results?.errors?.[0]?.error || [];
351352
const diagnostics: Record<string, vscode.Diagnostic[]> = {};
352-
353353
for (const e of errors) {
354354
const isCriticalError = criticalWarningTypes.includes(e.$.id);
355355
const locations = e.location || [];
@@ -358,12 +358,13 @@ async function runCppcheckOnFileXML(
358358
}
359359

360360
const mainLoc = locations[locations.length - 1].$;
361-
362361
// If main location is not current file, we are not using a project file and warning is not critical then skip displaying warning
363362
if (!isCriticalError && usingProjectFile && !filePath.endsWith(mainLoc.file)) {
364363
continue;
365364
}
366365

366+
const mainLocDocument = await vscode.workspace.openTextDocument(mainLoc.file);
367+
367368
// Cppcheck line number is 1-indexed, while VS Code uses 0-indexing
368369
let line = Number(mainLoc.line) - 1;
369370
// Invalid line number usually means non-analysis output
@@ -377,7 +378,7 @@ async function runCppcheckOnFileXML(
377378

378379
// Cppcheck col number is 1-indexed, while VS Code uses 0-indexing
379380
let col = Number(mainLoc.column) - 1;
380-
if (isNaN(col) || col < 0 || col > document.lineAt(line).text.length) {
381+
if (isNaN(col) || col < 0 || col > mainLocDocument.lineAt(line).text.length) {
381382
col = 0;
382383
}
383384

@@ -386,7 +387,7 @@ async function runCppcheckOnFileXML(
386387
continue;
387388
}
388389

389-
const range = new vscode.Range(line, col, line, document.lineAt(line).text.length);
390+
const range = new vscode.Range(line, col, line, mainLocDocument.lineAt(line).text.length);
390391
const diagnostic = new vscode.Diagnostic(range, e.$.msg, severity);
391392
diagnostic.source = "cppcheck";
392393
// If we have a link to documentation, include it
@@ -411,18 +412,19 @@ async function runCppcheckOnFileXML(
411412
continue;
412413
}
413414

415+
const relatedDocument = await vscode.workspace.openTextDocument(loc.file);
414416
const relatedRange = new vscode.Range(
415417
lLine, lCol,
416-
lLine, document.lineAt(lLine).text.length
418+
lLine, relatedDocument.lineAt(lLine).text.length
417419
);
418-
const relatedDocument = await vscode.workspace.openTextDocument(loc.file);
419420
relatedInfos.push(
420421
new vscode.DiagnosticRelatedInformation(
421422
new vscode.Location(relatedDocument?.uri ?? '', relatedRange),
422423
msg
423424
)
424425
);
425426
}
427+
426428
if (relatedInfos.length > 0) {
427429
diagnostic.relatedInformation = relatedInfos;
428430
}
@@ -444,7 +446,13 @@ async function runCppcheckOnFileXML(
444446
}
445447
const sourceDocumentUri = document.uri.toString();
446448
for (const uri of Object.keys(diagnostics)) {
447-
diagnosticCollection.set(vscode.Uri.parse(uri), diagnostics[uri]);
449+
var newDiagnostics = diagnostics[uri];
450+
// If file has existing diagnostics from analyzing other files we do not want to overwrite those
451+
const existingDiagnostics = diagnosticCollection.get(vscode.Uri.parse(uri));
452+
if (existingDiagnostics) {
453+
newDiagnostics = diagnosticsUnion(newDiagnostics, existingDiagnostics.flat());
454+
}
455+
diagnosticCollection.set(vscode.Uri.parse(uri), newDiagnostics);
448456
if (fileRelationMap[uri] === null ||fileRelationMap[uri] === undefined) {
449457
fileRelationMap[uri] = new Set;
450458
}

src/util/diagnostics.ts

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import * as vscode from 'vscode';
2+
3+
export function diagnosticsUnion(diagnosticsA : vscode.Diagnostic[], diagnosticB : vscode.Diagnostic[]) : vscode.Diagnostic[] {
4+
const diagnosticsUnion = new Array<vscode.Diagnostic>;
5+
// Add all elements from diagnosticsA to result array
6+
diagnosticsUnion.push(...diagnosticsA);
7+
8+
// Add all elements present in diagnosticsB but not in diagnosticsA to result array
9+
for (const diagnostic of diagnosticB) {
10+
if (!diagnosticsA.some((d) => {
11+
if (typeof(diagnostic?.code) === "object" && typeof(diagnostic?.code) !== null && typeof(d?.code) === "object" && typeof(d?.code) !== null) {
12+
return diagnostic.code.value === d.code.value && diagnostic.range.isEqual(d.range);
13+
} else {
14+
return diagnostic.code === d.code && diagnostic.range.isEqual(d.range);
15+
}
16+
})) {
17+
diagnosticsUnion.push(diagnostic);
18+
}
19+
}
20+
21+
// Return result
22+
return diagnosticsUnion;
23+
}

0 commit comments

Comments
 (0)