diff --git a/violations-lib/src/main/java/se/bjurr/violations/lib/parsers/FindbugsParser.java b/violations-lib/src/main/java/se/bjurr/violations/lib/parsers/FindbugsParser.java index f3aff65a..bc9ddae7 100644 --- a/violations-lib/src/main/java/se/bjurr/violations/lib/parsers/FindbugsParser.java +++ b/violations-lib/src/main/java/se/bjurr/violations/lib/parsers/FindbugsParser.java @@ -84,7 +84,8 @@ private Map getMessagesPerType( private void parseBugInstance( final XMLStreamReader xmlr, final Set violations, - final Map messagesPerType) + final Map messagesPerType, + final List srcDirs) throws XMLStreamException { final String type = getAttribute(xmlr, "type"); final Integer rank = getIntegerAttribute(xmlr, "rank"); @@ -105,7 +106,8 @@ private void parseBugInstance( if (!startLine.isPresent() || !endLine.isPresent()) { continue; } - final String filename = getAttribute(xmlr, "sourcepath"); + final String sourcepath = getAttribute(xmlr, "sourcepath"); + final String filename = resolveFilePath(sourcepath, srcDirs); final String classname = getAttribute(xmlr, "classname"); candidates.add( // violationBuilder() // @@ -152,13 +154,25 @@ public Set parseReportOutput( violationsLogger, this.getMessagesXml(findSecurityBugsMessagesXml, "/findbugs/fsb-messages.xml"))); + final List srcDirs = new ArrayList<>(); + try (InputStream input = new ByteArrayInputStream(string.getBytes(StandardCharsets.UTF_8))) { final XMLStreamReader xmlr = ViolationParserUtils.createXmlReader(input); + boolean inProject = false; while (xmlr.hasNext()) { final int eventType = xmlr.next(); if (eventType == XMLStreamConstants.START_ELEMENT) { - if (xmlr.getLocalName().equalsIgnoreCase("BugInstance")) { - this.parseBugInstance(xmlr, violations, messagesPerType); + if (xmlr.getLocalName().equalsIgnoreCase("Project")) { + inProject = true; + } else if (inProject && xmlr.getLocalName().equalsIgnoreCase("SrcDir")) { + srcDirs.add(xmlr.getElementText()); + } else if (xmlr.getLocalName().equalsIgnoreCase("BugInstance")) { + this.parseBugInstance(xmlr, violations, messagesPerType, srcDirs); + } + } + if (eventType == XMLStreamConstants.END_ELEMENT) { + if (xmlr.getLocalName().equalsIgnoreCase("Project")) { + inProject = false; } } } @@ -166,6 +180,24 @@ public Set parseReportOutput( return violations; } + /** + * Resolves the complete file path by combining the single {@code SrcDir} with the {@code + * sourcepath}. Only applies if there is exactly one {@code SrcDir} entry in total and it is a + * directory (i.e. not ending with {@code .java}); otherwise returns {@code sourcepath} unchanged. + */ + private String resolveFilePath(final String sourcepath, final List srcDirs) { + if (sourcepath == null || sourcepath.isEmpty() || srcDirs.size() != 1) { + return sourcepath; + } + final String normalized = srcDirs.get(0).replace("\\", "/").trim(); + if (normalized.endsWith(".java")) { + return sourcepath; + } + final String trimmed = + normalized.endsWith("/") ? normalized.substring(0, normalized.length() - 1) : normalized; + return trimmed + "/" + sourcepath; + } + private String getMessagesXml(final String staticValue, final String messagesResourceFilename) throws IOException { String messagesXml; diff --git a/violations-lib/src/test/java/se/bjurr/violations/lib/FindbugsTest.java b/violations-lib/src/test/java/se/bjurr/violations/lib/FindbugsTest.java index 401fa8ab..43a9fbc5 100644 --- a/violations-lib/src/test/java/se/bjurr/violations/lib/FindbugsTest.java +++ b/violations-lib/src/test/java/se/bjurr/violations/lib/FindbugsTest.java @@ -117,6 +117,23 @@ public void testThatViolationsCanBeParsedFromSpotbugs() { .isEqualTo("20"); } + @Test + public void testThatSrcDirIsCombinedWithSourcepathWhenExactlyOneSrcDir() { + final String rootFolder = getRootFolder(); + final Set actual = + violationsApi() // + .withPattern(".*/findbugs/spotbugs-one-srcdir\\.xml$") // + .inFolder(rootFolder) // + .findAll(FINDBUGS) // + .violations(); + + assertThat(actual) // + .hasSize(1); + final Violation violation0 = new ArrayList<>(actual).get(0); + assertThat(violation0.getFile()) // + .isEqualTo("/builds/my-project/module-a/src/main/java/com/example/Foo.java"); + } + @Test public void testThatViolationsCanBeParsedFromSpotbugs2() { final String rootFolder = getRootFolder(); diff --git a/violations-lib/src/test/resources/findbugs/spotbugs-one-srcdir.xml b/violations-lib/src/test/resources/findbugs/spotbugs-one-srcdir.xml new file mode 100644 index 00000000..699e99f5 --- /dev/null +++ b/violations-lib/src/test/resources/findbugs/spotbugs-one-srcdir.xml @@ -0,0 +1,24 @@ + + + + + /builds/my-project/module-a/src/main/java + + + + + + + + + + + + + + + + + + +