-
Notifications
You must be signed in to change notification settings - Fork 363
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix CppcheckParserV2; allow multiple NewIssueLocations #1436
Changes from 5 commits
d0934a8
452f640
c886539
4a640d4
e04cb27
6a9347e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/* | ||
* Sonar C++ Plugin (Community) | ||
* Copyright (C) 2010-2018 SonarOpenCommunity | ||
* http://github.com/SonarOpenCommunity/sonar-cxx | ||
* | ||
* This program is free software; you can redistribute it and/or | ||
* modify it under the terms of the GNU Lesser General Public | ||
* License as published by the Free Software Foundation; either | ||
* version 3 of the License, or (at your option) any later version. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* Lesser General Public License for more details. | ||
* | ||
* You should have received a copy of the GNU Lesser General Public License | ||
* along with this program; if not, write to the Free Software Foundation, | ||
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | ||
*/ | ||
package org.sonar.cxx.sensors.utils; | ||
|
||
/** | ||
* Each issues in SonarQube might have multiple locations; Encapsulate its | ||
* properties in this structure | ||
*/ | ||
public class CxxReportLocation { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unit test for CxxReportLocation missing |
||
final String file; | ||
final String line; | ||
final String msg; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should be info |
||
|
||
public CxxReportLocation(String file, String line, String msg) { | ||
super(); | ||
this.file = file; | ||
this.line = line; | ||
this.msg = msg; | ||
} | ||
|
||
public String getFile() { | ||
return file; | ||
} | ||
|
||
public String getLine() { | ||
return line; | ||
} | ||
|
||
public String getMsg() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should be info |
||
return msg; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,6 +25,7 @@ | |
import java.io.File; | ||
import java.util.ArrayList; | ||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.HashSet; | ||
import java.util.List; | ||
|
@@ -44,6 +45,7 @@ | |
import org.sonar.api.utils.log.Logger; | ||
import org.sonar.api.utils.log.Loggers; | ||
import org.sonar.cxx.CxxLanguage; | ||
import org.sonar.cxx.sensors.utils.CxxReportLocation; | ||
|
||
/** | ||
* This class is used as base for all sensors which import reports. It hosts common logic such as finding the reports | ||
|
@@ -267,70 +269,104 @@ private static List<String> normalizeReportPaths(final File moduleBaseDir, List< | |
* @param ruleId | ||
* @param msg | ||
*/ | ||
public void saveUniqueViolation(SensorContext sensorContext, String ruleRepoKey, | ||
@Nullable String file, @Nullable String line, String ruleId, String msg) { | ||
public void saveUniqueViolation(SensorContext sensorContext, String ruleRepoKey, @Nullable String file, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would remove this function |
||
@Nullable String line, String ruleId, String msg) { | ||
CxxReportLocation location = new CxxReportLocation(file, line, msg); | ||
saveUniqueViolation(sensorContext, ruleRepoKey, ruleId, Collections.singletonList(location)); | ||
} | ||
|
||
/** | ||
* Saves code violation only if unique. Compares file, line, ruleId and msg or the first given location | ||
* | ||
* @param sensorContext | ||
* @param ruleRepoKey | ||
* @param ruleId | ||
* @param locations | ||
*/ | ||
public void saveUniqueViolation(SensorContext sensorContext, String ruleRepoKey, String ruleId, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would call always this function from sensors. |
||
List<CxxReportLocation> locations) { | ||
CxxReportLocation firstLocation = locations.get(0); | ||
// StringBuilder is slower | ||
if (uniqueIssues.add(file + line + ruleId + msg)) { | ||
saveViolation(sensorContext, ruleRepoKey, file, line, ruleId, msg); | ||
if (uniqueIssues.add(firstLocation.getFile() + firstLocation.getLine() + ruleId + firstLocation.getMsg())) { | ||
saveViolation(sensorContext, ruleRepoKey, ruleId, locations); | ||
} | ||
} | ||
|
||
private NewIssueLocation createNewIssueLocationFile(SensorContext sensorContext, NewIssue newIssue, | ||
CxxReportLocation location, Map<InputFile, Integer> tmpViolationsPerFileCount) { | ||
String root = sensorContext.fileSystem().baseDir().getAbsolutePath(); | ||
String normalPath = CxxUtils.normalizePathFull(location.getFile(), root); | ||
if (normalPath != null && !notFoundFiles.contains(normalPath)) { | ||
InputFile inputFile = sensorContext.fileSystem() | ||
.inputFile(sensorContext.fileSystem().predicates().hasAbsolutePath(normalPath)); | ||
if (inputFile != null) { | ||
int lines = inputFile.lines(); | ||
int lineNr = getLineAsInt(location.getLine(), lines); | ||
NewIssueLocation newIssueLocation = newIssue.newLocation().on(inputFile) | ||
.at(inputFile.selectLine(lineNr > 0 ? lineNr : 1)).message(location.getMsg()); | ||
|
||
tmpViolationsPerFileCount.merge(inputFile, 1, Integer::sum); | ||
|
||
return newIssueLocation; | ||
} else { | ||
LOG.warn("Cannot find the file '{}', skipping violations", normalPath); | ||
notFoundFiles.add(normalPath); | ||
} | ||
} | ||
return null; | ||
} | ||
|
||
private NewIssueLocation createNewIssueLocationModule(SensorContext sensorContext, NewIssue newIssue, | ||
CxxReportLocation location) { | ||
NewIssueLocation newIssueLocation = newIssue.newLocation().on(sensorContext.module()).message(location.getMsg()); | ||
return newIssueLocation; | ||
} | ||
|
||
/** | ||
* Saves a code violation which is detected in the given file/line and has given ruleId and message. Saves it to the | ||
* given project and context. Project or file-level violations can be saved by passing null for the according | ||
* parameters ('file' = null for project level, 'line' = null for file-level) | ||
*/ | ||
private void saveViolation(SensorContext sensorContext, String ruleRepoKey, | ||
@Nullable String filename, @Nullable String line, String ruleId, String msg) { | ||
// handles file="" situation -- file level | ||
if ((filename != null) && (!filename.isEmpty())) { | ||
String root = sensorContext.fileSystem().baseDir().getAbsolutePath(); | ||
String normalPath = CxxUtils.normalizePathFull(filename, root); | ||
if (normalPath != null && !notFoundFiles.contains(normalPath)) { | ||
InputFile inputFile = sensorContext.fileSystem().inputFile(sensorContext.fileSystem() | ||
.predicates().hasAbsolutePath(normalPath)); | ||
if (inputFile != null) { | ||
try { | ||
int lines = inputFile.lines(); | ||
int lineNr = getLineAsInt(line, lines); | ||
String repoKey = ruleRepoKey + this.language.getRepositorySuffix(); | ||
NewIssue newIssue = sensorContext | ||
.newIssue() | ||
.forRule(RuleKey.of(repoKey, ruleId)); | ||
NewIssueLocation location = newIssue.newLocation() | ||
.on(inputFile) | ||
.at(inputFile.selectLine(lineNr > 0 ? lineNr : 1)) | ||
.message(msg); | ||
|
||
newIssue.at(location); | ||
newIssue.save(); | ||
|
||
violationsPerFileCount.merge(inputFile, 1, Integer::sum); | ||
violationsPerModuleCount++; | ||
} catch (RuntimeException ex) { | ||
LOG.error("Could not add the issue '{}', skipping issue", ex.getMessage()); | ||
CxxUtils.validateRecovery(ex, this.language); | ||
} | ||
} else { | ||
LOG.warn("Cannot find the file '{}', skipping violations", normalPath); | ||
notFoundFiles.add(normalPath); | ||
private void saveViolation(SensorContext sensorContext, String ruleRepoKey, String ruleId, | ||
List<CxxReportLocation> locations) { | ||
|
||
String repoKey = ruleRepoKey + this.language.getRepositorySuffix(); | ||
NewIssue newIssue = sensorContext.newIssue().forRule(RuleKey.of(repoKey, ruleId)); | ||
|
||
int tmpViolationPerModuleCount = 0; | ||
Map<InputFile, Integer> tmpViolationsPerFileCount = new HashMap<>(); | ||
List<NewIssueLocation> newIssueLocations = new ArrayList<>(); | ||
|
||
for (CxxReportLocation location : locations) { | ||
if (location.getFile() != null && !location.getFile().isEmpty()) { | ||
NewIssueLocation newIssueLocation = createNewIssueLocationFile(sensorContext, newIssue, location, | ||
tmpViolationsPerFileCount); | ||
if (newIssueLocation != null) { | ||
newIssueLocations.add(newIssueLocation); | ||
tmpViolationPerModuleCount++; | ||
} | ||
} else { | ||
NewIssueLocation newIssueLocation = createNewIssueLocationModule(sensorContext, newIssue, location); | ||
newIssueLocations.add(newIssueLocation); | ||
tmpViolationPerModuleCount++; | ||
} | ||
} else { | ||
// project level | ||
try { | ||
NewIssue newIssue = sensorContext.newIssue().forRule( | ||
RuleKey.of(ruleRepoKey + this.language.getRepositorySuffix(), ruleId)); | ||
NewIssueLocation location = newIssue.newLocation() | ||
.on(sensorContext.module()) | ||
.message(msg); | ||
} | ||
|
||
newIssue.at(location); | ||
if (!newIssueLocations.isEmpty()) { | ||
try { | ||
newIssue.at(newIssueLocations.get(0)); | ||
for (int i = 1; i < newIssueLocations.size(); i++) { | ||
newIssue.addLocation(newIssueLocations.get(i)); | ||
} | ||
newIssue.save(); | ||
violationsPerModuleCount++; | ||
|
||
for (Map.Entry<InputFile, Integer> entry : tmpViolationsPerFileCount.entrySet()) { | ||
violationsPerFileCount.merge(entry.getKey(), entry.getValue(), Integer::sum); | ||
} | ||
violationsPerModuleCount += tmpViolationPerModuleCount; | ||
} catch (RuntimeException ex) { | ||
LOG.error("Could not add the issue '{}' for rule '{}:{}', skipping issue", | ||
ex.getMessage(), ruleRepoKey, ruleId); | ||
LOG.error("Could not add the issue '{}' for rule '{}:{}', skipping issue", ex.getMessage(), ruleRepoKey, | ||
ruleId); | ||
CxxUtils.validateRecovery(ex, this.language); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would try to handle this always with locations