From addb144f63fa95d77adf3416bff518dcb21102dc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:02:54 +0000 Subject: [PATCH 1/5] Initial plan From d38b8b37d0afd9b9953856c5a11e7a6c02e8e38d Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:11:54 +0000 Subject: [PATCH 2/5] Fix FindbugsParser to combine SrcDir with sourcepath for complete file paths Co-authored-by: tomasbjerre <439571+tomasbjerre@users.noreply.github.com> --- .../lib/parsers/FindbugsParser.java | 43 +++++++++++++++++-- .../se/bjurr/violations/lib/FindbugsTest.java | 24 ++++++++++- .../resources/findbugs/spotbugs-srcdir.xml | 18 ++++++++ 3 files changed, 80 insertions(+), 5 deletions(-) create mode 100644 violations-lib/src/test/resources/findbugs/spotbugs-srcdir.xml 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..08b46a23 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,27 @@ public Set parseReportOutput( return violations; } + /** + * Resolves the complete file path by combining a directory-type {@code SrcDir} with the + * {@code sourcepath}. Only the first directory-type entry (i.e. not ending with {@code .java}) + * is used. Returns {@code sourcepath} unchanged if no directory-type {@code SrcDir} is found. + */ + private String resolveFilePath(final String sourcepath, final List srcDirs) { + if (sourcepath == null || sourcepath.isEmpty() || srcDirs.isEmpty()) { + return sourcepath; + } + for (final String srcDir : srcDirs) { + final String normalized = srcDir.replace("\\", "/").trim(); + if (normalized.endsWith(".java")) { + continue; + } + final String trimmed = + normalized.endsWith("/") ? normalized.substring(0, normalized.length() - 1) : normalized; + return trimmed + "/" + sourcepath; + } + return 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..bd7a909f 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 @@ -131,6 +131,28 @@ public void testThatViolationsCanBeParsedFromSpotbugs2() { .hasSize(3); final Violation violation0 = new ArrayList<>(actual).get(0); assertThat(violation0.getFile()) // - .isEqualTo("se/bjurr/violations/lib/reports/ReportsFinder.java"); + .isEqualTo( + "/home/bjerre/workspace/violations/violations-lib/src/main/java/se/bjurr/violations/lib/reports/ReportsFinder.java"); + } + + @Test + public void testThatSrcDirIsCombinedWithSourcepath() { + final String rootFolder = getRootFolder(); + final Set actual = + violationsApi() // + .withPattern(".*/findbugs/spotbugs-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"); + assertThat(violation0.getStartLine()) // + .isEqualTo(42); + assertThat(violation0.getRule()) // + .isEqualTo("MS_EXPOSE_REP"); } } diff --git a/violations-lib/src/test/resources/findbugs/spotbugs-srcdir.xml b/violations-lib/src/test/resources/findbugs/spotbugs-srcdir.xml new file mode 100644 index 00000000..737e76ba --- /dev/null +++ b/violations-lib/src/test/resources/findbugs/spotbugs-srcdir.xml @@ -0,0 +1,18 @@ + + + + + /builds/my-project/module-a/build/classes/java/main + /builds/my-project/module-a/src/main/java + + + + + + + + + + + + From 8ee67601c928f8374358ec0a480ddfa4febd0fb0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:28:52 +0000 Subject: [PATCH 3/5] fix: only combine SrcDir with sourcepath when exactly one directory-type SrcDir exists Co-authored-by: tomasbjerre <439571+tomasbjerre@users.noreply.github.com> --- .../lib/parsers/FindbugsParser.java | 21 +++++++++++-------- .../se/bjurr/violations/lib/FindbugsTest.java | 21 +------------------ .../resources/findbugs/spotbugs-srcdir.xml | 18 ---------------- 3 files changed, 13 insertions(+), 47 deletions(-) delete mode 100644 violations-lib/src/test/resources/findbugs/spotbugs-srcdir.xml 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 08b46a23..79995f46 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 @@ -181,24 +181,27 @@ public Set parseReportOutput( } /** - * Resolves the complete file path by combining a directory-type {@code SrcDir} with the - * {@code sourcepath}. Only the first directory-type entry (i.e. not ending with {@code .java}) - * is used. Returns {@code sourcepath} unchanged if no directory-type {@code SrcDir} is found. + * Resolves the complete file path by combining a directory-type {@code SrcDir} with the {@code + * sourcepath}. Only applies if there is exactly one directory-type entry (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.isEmpty()) { return sourcepath; } + final List dirSrcDirs = new ArrayList<>(); for (final String srcDir : srcDirs) { final String normalized = srcDir.replace("\\", "/").trim(); - if (normalized.endsWith(".java")) { - continue; + if (!normalized.endsWith(".java")) { + dirSrcDirs.add(normalized); } - final String trimmed = - normalized.endsWith("/") ? normalized.substring(0, normalized.length() - 1) : normalized; - return trimmed + "/" + sourcepath; } - return sourcepath; + if (dirSrcDirs.size() != 1) { + return sourcepath; + } + final String dir = dirSrcDirs.get(0); + final String trimmed = dir.endsWith("/") ? dir.substring(0, dir.length() - 1) : dir; + return trimmed + "/" + sourcepath; } private String getMessagesXml(final String staticValue, final String messagesResourceFilename) 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 bd7a909f..e351377e 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 @@ -135,24 +135,5 @@ public void testThatViolationsCanBeParsedFromSpotbugs2() { "/home/bjerre/workspace/violations/violations-lib/src/main/java/se/bjurr/violations/lib/reports/ReportsFinder.java"); } - @Test - public void testThatSrcDirIsCombinedWithSourcepath() { - final String rootFolder = getRootFolder(); - final Set actual = - violationsApi() // - .withPattern(".*/findbugs/spotbugs-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"); - assertThat(violation0.getStartLine()) // - .isEqualTo(42); - assertThat(violation0.getRule()) // - .isEqualTo("MS_EXPOSE_REP"); - } } + diff --git a/violations-lib/src/test/resources/findbugs/spotbugs-srcdir.xml b/violations-lib/src/test/resources/findbugs/spotbugs-srcdir.xml deleted file mode 100644 index 737e76ba..00000000 --- a/violations-lib/src/test/resources/findbugs/spotbugs-srcdir.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - /builds/my-project/module-a/build/classes/java/main - /builds/my-project/module-a/src/main/java - - - - - - - - - - - - From 9d446d8edf7edf540023f2cc5c8286583ddd06b6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:34:20 +0000 Subject: [PATCH 4/5] fix: only combine SrcDir with sourcepath when total SrcDir count is exactly one Co-authored-by: tomasbjerre <439571+tomasbjerre@users.noreply.github.com> --- .../lib/parsers/FindbugsParser.java | 22 +++++++------------ .../se/bjurr/violations/lib/FindbugsTest.java | 3 +-- 2 files changed, 9 insertions(+), 16 deletions(-) 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 79995f46..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 @@ -181,26 +181,20 @@ public Set parseReportOutput( } /** - * Resolves the complete file path by combining a directory-type {@code SrcDir} with the {@code - * sourcepath}. Only applies if there is exactly one directory-type entry (i.e. not ending with - * {@code .java}); otherwise returns {@code sourcepath} unchanged. + * 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.isEmpty()) { + if (sourcepath == null || sourcepath.isEmpty() || srcDirs.size() != 1) { return sourcepath; } - final List dirSrcDirs = new ArrayList<>(); - for (final String srcDir : srcDirs) { - final String normalized = srcDir.replace("\\", "/").trim(); - if (!normalized.endsWith(".java")) { - dirSrcDirs.add(normalized); - } - } - if (dirSrcDirs.size() != 1) { + final String normalized = srcDirs.get(0).replace("\\", "/").trim(); + if (normalized.endsWith(".java")) { return sourcepath; } - final String dir = dirSrcDirs.get(0); - final String trimmed = dir.endsWith("/") ? dir.substring(0, dir.length() - 1) : dir; + final String trimmed = + normalized.endsWith("/") ? normalized.substring(0, normalized.length() - 1) : normalized; return trimmed + "/" + sourcepath; } 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 e351377e..bdf59bfb 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 @@ -131,8 +131,7 @@ public void testThatViolationsCanBeParsedFromSpotbugs2() { .hasSize(3); final Violation violation0 = new ArrayList<>(actual).get(0); assertThat(violation0.getFile()) // - .isEqualTo( - "/home/bjerre/workspace/violations/violations-lib/src/main/java/se/bjurr/violations/lib/reports/ReportsFinder.java"); + .isEqualTo("se/bjurr/violations/lib/reports/ReportsFinder.java"); } } From afb90be1270892258c772289b1230c228c55dcb4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Mar 2026 15:38:20 +0000 Subject: [PATCH 5/5] test: add test for SrcDir combined with sourcepath when exactly one SrcDir exists Co-authored-by: tomasbjerre <439571+tomasbjerre@users.noreply.github.com> --- .../se/bjurr/violations/lib/FindbugsTest.java | 19 +++++++++++++-- .../findbugs/spotbugs-one-srcdir.xml | 24 +++++++++++++++++++ 2 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 violations-lib/src/test/resources/findbugs/spotbugs-one-srcdir.xml 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 bdf59bfb..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(); @@ -133,6 +150,4 @@ public void testThatViolationsCanBeParsedFromSpotbugs2() { assertThat(violation0.getFile()) // .isEqualTo("se/bjurr/violations/lib/reports/ReportsFinder.java"); } - } - 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 + + + + + + + + + + + + + + + + + + +