diff --git a/README.md b/README.md index 61db0e6e..995e81b8 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ It supports: * [_PMD_](https://pmd.github.io/) * [_Findbugs_](http://findbugs.sourceforge.net/) * [_Checkstyle_](http://checkstyle.sourceforge.net/) + * [_CPPCheck_](http://cppcheck.sourceforge.net/) * [_CSSLint_](https://github.com/CSSLint/csslint) * [_JSHint_](http://jshint.com/) diff --git a/src/main/java/se/bjurr/violations/lib/parsers/CPPCheckParser.java b/src/main/java/se/bjurr/violations/lib/parsers/CPPCheckParser.java new file mode 100644 index 00000000..4fe7dde0 --- /dev/null +++ b/src/main/java/se/bjurr/violations/lib/parsers/CPPCheckParser.java @@ -0,0 +1,60 @@ +package se.bjurr.violations.lib.parsers; + +import static com.google.common.collect.Lists.newArrayList; +import static se.bjurr.violations.lib.model.SEVERITY.ERROR; +import static se.bjurr.violations.lib.model.SEVERITY.INFO; +import static se.bjurr.violations.lib.model.SEVERITY.WARN; +import static se.bjurr.violations.lib.model.Violation.violationBuilder; +import static se.bjurr.violations.lib.reports.Reporter.CPPCHECK; + +import java.io.File; +import java.util.List; + +import se.bjurr.violations.lib.model.SEVERITY; +import se.bjurr.violations.lib.model.Violation; + +import com.google.common.base.Charsets; +import com.google.common.io.Files; + +public class CPPCheckParser extends ViolationsParser { + + @Override + public List parseFile(File file) throws Exception { + String string = Files.toString(file, Charsets.UTF_8); + List violations = newArrayList(); + List errorChunks = getChunks(string, ""); + for (String errorChunk : errorChunks) { + String severity = getAttribute(errorChunk, "severity"); + String msg = getAttribute(errorChunk, "msg"); + String verbose = getAttribute(errorChunk, "verbose"); + String id = getAttribute(errorChunk, "id"); + List locationChunks = getChunks(errorChunk, ""); + for (String locationChunk : locationChunks) { + Integer line = getIntegerAttribute(locationChunk, "line"); + String fileString = getAttribute(errorChunk, "file"); + violations.add(// + violationBuilder()// + .setReporter(CPPCHECK)// + .setStartLine(line)// + .setFile(fileString)// + .setSeverity(toSeverity(severity))// + .setMessage(msg + ". " + verbose)// + .setRule(id)// + .build()// + ); + } + } + return violations; + } + + public SEVERITY toSeverity(String severity) { + if (severity.equalsIgnoreCase("error")) { + return ERROR; + } + if (severity.equalsIgnoreCase("warning")) { + return WARN; + } + return INFO; + } + +} diff --git a/src/main/java/se/bjurr/violations/lib/reports/Reporter.java b/src/main/java/se/bjurr/violations/lib/reports/Reporter.java index 46e8e295..14c7cfaf 100644 --- a/src/main/java/se/bjurr/violations/lib/reports/Reporter.java +++ b/src/main/java/se/bjurr/violations/lib/reports/Reporter.java @@ -8,6 +8,7 @@ import java.util.logging.Logger; import se.bjurr.violations.lib.model.Violation; +import se.bjurr.violations.lib.parsers.CPPCheckParser; import se.bjurr.violations.lib.parsers.CSSLintParser; import se.bjurr.violations.lib.parsers.CheckStyleParser; import se.bjurr.violations.lib.parsers.FindbugsParser; @@ -20,7 +21,8 @@ public enum Reporter { CSSLINT(new CSSLintParser()), // FINDBUGS(new FindbugsParser()), // JSHINT(new JSHintParser()), // - PMD(new PMDParser()); + PMD(new PMDParser()), // + CPPCHECK(new CPPCheckParser()); private static Logger LOG = Logger.getLogger(Reporter.class.getSimpleName()); private ViolationsParser violationsParser; diff --git a/src/test/java/se/bjurr/violations/lib/CPPCheckTest.java b/src/test/java/se/bjurr/violations/lib/CPPCheckTest.java new file mode 100644 index 00000000..2e7a3b20 --- /dev/null +++ b/src/test/java/se/bjurr/violations/lib/CPPCheckTest.java @@ -0,0 +1,55 @@ +package se.bjurr.violations.lib; + +import static org.assertj.core.api.Assertions.assertThat; +import static se.bjurr.violations.lib.TestUtils.getRootFolder; +import static se.bjurr.violations.lib.ViolationsReporterApi.violationsReporterApi; +import static se.bjurr.violations.lib.model.SEVERITY.ERROR; +import static se.bjurr.violations.lib.model.SEVERITY.INFO; +import static se.bjurr.violations.lib.model.Violation.violationBuilder; +import static se.bjurr.violations.lib.reports.Reporter.CPPCHECK; + +import java.util.List; + +import org.junit.Test; + +import se.bjurr.violations.lib.model.Violation; + +public class CPPCheckTest { + + private static final String MSG_1 = "The scope of the variable 'i' can be reduced. The scope of the variable 'i' can be reduced. Warning: It can be unsafe to fix this message. Be careful. Especially when there are inner loops. Here is an example where cppcheck will write that the scope for 'i' can be reduced: void f(int x) { int i = 0; if (x) { // it's safe to move 'int i = 0' here for (int n = 0; n < 10; ++n) { // it is possible but not safe to move 'int i = 0' here do_something(&i); } } } When you see this message it is always safe to reduce the variable scope 1 level."; + private static final String MSG_2 = "The scope of the variable 'i' can be reduced. The scope of the variable 'i' can be reduced. Warning: It can be unsafe to fix this message. Be careful. Especially when there are inner loops. Here is an example where cppcheck will write that the scope for 'i' can be reduced: void f(int x) { int i = 0; if (x) { // it's safe to move 'int i = 0' here for (int n = 0; n < 10; ++n) { // it is possible but not safe to move 'int i = 0' here do_something(&i); } } } When you see this message it is always safe to reduce the variable scope 1 level."; + + @Test + public void testThatViolationsCanBeParsed() { + String rootFolder = getRootFolder(); + + List actual = violationsReporterApi() // + .withPattern(".*/cppcheck/.*\\.xml$") // + .inFolder(rootFolder) // + .findAll(CPPCHECK) // + .violations(); + + assertThat(actual)// + .contains(// + violationBuilder()// + .setReporter(CPPCHECK)// + .setFile("api.c")// + .setStartLine(498)// + .setEndLine(498)// + .setRule("variableScope")// + .setMessage(MSG_1)// + .setSeverity(INFO)// + .build())// + .contains(// + violationBuilder()// + .setReporter(CPPCHECK)// + .setFile("api_storage.c")// + .setStartLine(104)// + .setEndLine(104)// + .setRule("variableScope")// + .setMessage(MSG_2)// + .setSeverity(ERROR)// + .build())// + .hasSize(3); + } +} diff --git a/src/test/resources/cppcheck/main.xml b/src/test/resources/cppcheck/main.xml new file mode 100644 index 00000000..b3cd783b --- /dev/null +++ b/src/test/resources/cppcheck/main.xml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + \ No newline at end of file