Skip to content

Commit

Permalink
Merge pull request #31 from oyvindlr/master
Browse files Browse the repository at this point in the history
Added PC-lint parser
  • Loading branch information
tomasbjerre authored Feb 13, 2018
2 parents 02355e0 + 5e3d49f commit 2b6a5e6
Show file tree
Hide file tree
Showing 7 changed files with 262 additions and 4 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ It supports:
* [_JCReport_](https://github.com/jCoderZ/fawkez/wiki/JcReport)
* [_Klocwork_](http://www.klocwork.com/products-services/klocwork/static-code-analysis)
* [_MyPy_](https://pypi.python.org/pypi/mypy-lang)
* [_PCLint_](http://www.gimpel.com/html/pcl.htm) PC-Lint using the same output format as the Jenkins warnings plugin, [_details here_](https://wiki.jenkins.io/display/JENKINS/PcLint+options)
* [_PerlCritic_](https://github.com/Perl-Critic)
* [_PiTest_](http://pitest.org/)
* [_PyDocStyle_](https://pypi.python.org/pypi/pydocstyle)
Expand Down
6 changes: 5 additions & 1 deletion src/main/java/se/bjurr/violations/lib/ViolationsApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,12 @@ public List<Violation> violations() {
return foundViolations;
}

private String makeWindowsFriendly(String regularExpression) {
return regularExpression.replace("/", "(?:/|\\\\)");
}

public ViolationsApi withPattern(String regularExpression) {
pattern = regularExpression;
pattern = makeWindowsFriendly(regularExpression);
return this;
}
}
116 changes: 116 additions & 0 deletions src/main/java/se/bjurr/violations/lib/parsers/PCLintParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package se.bjurr.violations.lib.parsers;

import static java.lang.Integer.parseInt;
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.Parser.PCLINT;
import static se.bjurr.violations.lib.util.ViolationParserUtils.getLines;
import static se.bjurr.violations.lib.util.ViolationParserUtils.getParts;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.*;
import se.bjurr.violations.lib.model.SEVERITY;
import se.bjurr.violations.lib.model.Violation;

public class PCLintParser implements ViolationsParser {

@Override
public List<Violation> parseReportOutput(String string) throws Exception {
List<Violation> violations = new ArrayList<>();
List<String> lines = getLines(string);
Pattern misraPattern = Pattern.compile("\\[MISRA.*\\]");
for (String line : lines) {
Matcher misraMatcher = misraPattern.matcher(line);
if (misraMatcher.find()) {
parseMisraViolation(line, violations);
} else {
parseGeneralViolation(line, violations);
}
}
return violations;
}

private void parseMisraViolation(String line, List<Violation> violations) {
List<String> parts =
getParts(
line,
"^([^\\(]+)\\(",
"^([\\d]+)\\): ",
"^(?:Error|Warning|Info|Note) [\\d]+: ([^\\[]*)",
"^\\[(.*),",
"(mandatory|required|advisory)\\]",
"^(.*)$");
if (parts.isEmpty()) {
return;
}
String filename = parts.get(0);
Integer lineNumber = parseInt(parts.get(1));

String severityString = parts.get(4);
SEVERITY severity = toMisraSeverity(severityString);
String rule = parts.get(3) + ", " + severityString;
String message = parts.get(2) + " " + parts.get(5);
violations.add( //
violationBuilder() //
.setParser(PCLINT) //
.setStartLine(lineNumber) //
.setFile(filename) //
.setRule(rule) //
.setSeverity(severity) //
.setMessage(message) //
.build() //
);
}

private void parseGeneralViolation(String line, List<Violation> violations) {
List<String> parts =
getParts(
line,
"^([^\\(]+)\\(",
"^([\\d]+)\\): ",
"^(Error|Warning|Info|Note) ",
"^([\\d]+): ",
"^(.*)$");
if (parts.isEmpty()) {
return;
}
String filename = parts.get(0);
Integer lineNumber = parseInt(parts.get(1));
SEVERITY severity = toSeverity(parts.get(2));
String rule = parts.get(3);
String message = parts.get(4);
violations.add( //
violationBuilder() //
.setParser(PCLINT) //
.setStartLine(lineNumber) //
.setFile(filename) //
.setRule(rule) //
.setSeverity(severity) //
.setMessage(message) //
.build() //
);
}

private SEVERITY toSeverity(String severity) {
if (severity.equals("Error")) {
return ERROR;
}
if (severity.equals("Warning")) {
return WARN;
}
return INFO;
}

private SEVERITY toMisraSeverity(String severity) {
if (severity.equals("mandatory")) {
return ERROR;
}
if (severity.equals("required")) {
return WARN;
}
return INFO;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
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.Parser.CPPLINT;
import static se.bjurr.violations.lib.reports.Parser.PERLCRITIC;
import static se.bjurr.violations.lib.util.ViolationParserUtils.getLines;
import static se.bjurr.violations.lib.util.ViolationParserUtils.getParts;

Expand Down Expand Up @@ -41,7 +41,7 @@ public List<Violation> parseReportOutput(String string) throws Exception {

violations.add( //
violationBuilder() //
.setParser(CPPLINT) //
.setParser(PERLCRITIC) //
.setStartLine(lineNumber) //
.setColumn(columnNumber) //
.setFile(filename) //
Expand Down
4 changes: 3 additions & 1 deletion src/main/java/se/bjurr/violations/lib/reports/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import se.bjurr.violations.lib.parsers.KlocworkParser;
import se.bjurr.violations.lib.parsers.LintParser;
import se.bjurr.violations.lib.parsers.MyPyParser;
import se.bjurr.violations.lib.parsers.PCLintParser;
import se.bjurr.violations.lib.parsers.PMDParser;
import se.bjurr.violations.lib.parsers.PerlCriticParser;
import se.bjurr.violations.lib.parsers.PiTestParser;
Expand Down Expand Up @@ -73,7 +74,8 @@ public enum Parser {
STYLECOP(new StyleCopParser()), //
XMLLINT(new XMLLintParser()), //
ZPTLINT(new ZPTLintParser()), //
DOCFX(new DocFXParser());
DOCFX(new DocFXParser()), //
PCLINT(new PCLintParser());

private static Logger LOG = Logger.getLogger(Parser.class.getSimpleName());
private transient ViolationsParser violationsParser;
Expand Down
109 changes: 109 additions & 0 deletions src/test/java/se/bjurr/violations/lib/PCLintTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
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.ViolationsApi.violationsApi;
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.Parser.PCLINT;

import java.util.List;
import org.junit.Test;
import se.bjurr.violations.lib.model.Violation;

public class PCLintTest {

@Test
public void testThatViolationsCanBeParsed() {
String rootFolder = getRootFolder();

List<Violation> actual =
violationsApi() //
.withPattern(".*/pclint/.*\\.txt$") //
.inFolder(rootFolder) //
.findAll(PCLINT) //
.violations();

assertThat(actual) //
.hasSize(8);

assertThat(actual.get(0)) //
.isEqualTo( //
violationBuilder() //
.setParser(PCLINT) //
.setFile("C:\\UST3\\qse30\\Drivers\\drvADC.c") //
.setStartLine(84) //
.setRule("9029") //
.setMessage("Mismatched essential type categories for binary operator") //
.setSeverity(INFO) //
.build() //
);

assertThat(actual.get(3)) //
.isEqualTo( //
violationBuilder() //
.setParser(PCLINT) //
.setFile("C:\\UST3\\qse30\\Drivers\\drvCAN.c") //
.setStartLine(73) //
.setRule("534") //
.setMessage(
"Ignoring return value of function 'PIC_CAN_Transmit(can_frame_t *)' (compare with line 68, file C:\\UST3\\qse30\\HAL\\hal_ext.h, module C:\\UST3\\qse30\\Drivers\\drvADC.c)") //
.setSeverity(WARN) //
.build() //
);
assertThat(actual.get(5)) //
.isEqualTo( //
violationBuilder() //
.setParser(PCLINT) //
.setFile("C:\\UST3\\qse30\\Drivers\\drvCAN.c") //
.setStartLine(134) //
.setRule("818") //
.setMessage(
"Pointer parameter 'txFrame' (line 100) could be declared as pointing to const") //
.setSeverity(INFO) //
.build() //
);
assertThat(actual.get(6)) //
.isEqualTo( //
violationBuilder() //
.setParser(PCLINT) //
.setFile("C:\\UST3\\qse30\\Modules\\COMM\\J1939\\Broadcast\\dm13.c") //
.setStartLine(123) //
.setRule("48") //
.setMessage("Bad type") //
.setSeverity(ERROR) //
.build() //
);
}

@Test
public void testThatSeverityAndRulenumberFromMisraTakesPrecedence() {
String rootFolder = getRootFolder();

List<Violation> actual =
violationsApi() //
.withPattern(".*/pclint/.*\\.txt$") //
.inFolder(rootFolder) //
.findAll(PCLINT) //
.violations();

Violation violation = actual.get(1);

assertThat(violation.getRule().get()).isEqualTo("MISRA 2012 Rule 10.4, mandatory");
assertThat(violation.getSeverity()).isEqualTo(ERROR);

violation = actual.get(2);

assertThat(violation.getRule().get()).isEqualTo("MISRA 2012 Rule 1.3, required");
assertThat(violation.getSeverity()).isEqualTo(WARN);

violation = actual.get(7);

assertThat(violation.getRule().get()).isEqualTo("MISRA 2012 Rule 10.1, advisory");
assertThat(violation.getSeverity()).isEqualTo(INFO);
assertThat(violation.getMessage())
.isEqualTo("Bad type (Error <a href=\"/userContent/LintMsgRef.html#48\">48</a>)");
}
}
26 changes: 26 additions & 0 deletions src/test/resources/pclint/pclint.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
PC-lint for C/C++ (NT) Vers. 9.00L, Copyright Gimpel Software 1985-2014

--- Module: C:\UST3\qse30\Drivers\drvADC.c (C)
C:\UST3\qse30\Drivers\drvADC.c(84): Note 9029: Mismatched essential type categories for binary operator

--- Module: C:\UST3\qse30\Drivers\drvCAN.c (C)
C:\UST3\qse30\Drivers\drvCAN.c(68): Note 9029: Mismatched essential type categories for binary operator [MISRA 2012 Rule 10.4, mandatory] (Note <a href="/userContent/LintMsgRef.html#9029">9029</a>)
C:\UST3\qse30\Drivers\drvCAN.c(72): Note 931: Both sides have side effects [MISRA 2012 Rule 1.3, required]
C:\UST3\qse30\Drivers\drvCAN.c(73): Warning 534: Ignoring return value of function 'PIC_CAN_Transmit(can_frame_t *)' (compare with line 68, file C:\UST3\qse30\HAL\hal_ext.h, module C:\UST3\qse30\Drivers\drvADC.c)
C:\UST3\qse30\Drivers\drvCAN.c(128): Warning 534: Ignoring return value of function 'PIC_CAN_Transmit(can_frame_t *)' (compare with line 68, file C:\UST3\qse30\HAL\hal_ext.h, module C:\UST3\qse30\Drivers\drvADC.c)
C:\UST3\qse30\Drivers\drvCAN.c(134): Info 818: Pointer parameter 'txFrame' (line 100) could be declared as pointing to const


--- Module: C:\UST3\qse30\Drivers\drvNTC.c (C)

--- Module: C:\UST3\qse30\Drivers\drvPWM.c (C)
(0): Info 766: Header file 'C:\UST3\qse30\Kernel\Common\common_types.h' not used in module 'C:\UST3\qse30\Drivers\drvPWM.c' (Info <a href="/userContent/LintMsgRef.html#766">766</a>)


--- Module: C:\UST3\qse30\Modules\COMM\J1939\Broadcast\dm13.c (C)
C:\UST3\qse30\Modules\COMM\J1939\Broadcast\dm13.c(123): Error 48: Bad type
C:\UST3\qse30\Modules\COMM\J1939\Broadcast\dm13.c(123): Error 48: Bad type [MISRA 2012 Rule 10.1, advisory] (Error <a href="/userContent/LintMsgRef.html#48">48</a>)




0 comments on commit 2b6a5e6

Please sign in to comment.