From 01b06e3a808277ab94681d8ebfe8f159646d1531 Mon Sep 17 00:00:00 2001 From: theKBro Date: Mon, 4 Nov 2024 19:05:14 +0100 Subject: [PATCH 1/7] handleFilePathsInFileURIschemeFormat --- .../violations/AbstractViolationAdapter.java | 49 ++-- .../parser/violations/SarifAdapter.java | 38 ++++ .../parser/violations/SarifAdapterTest.java | 20 ++ .../violations/filePathInFileUriScheme.sarif | 213 ++++++++++++++++++ 4 files changed, 286 insertions(+), 34 deletions(-) create mode 100644 src/test/resources/edu/hm/hafner/analysis/parser/violations/filePathInFileUriScheme.sarif diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/AbstractViolationAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/AbstractViolationAdapter.java index cfb0534c3..b867c8407 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/AbstractViolationAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/AbstractViolationAdapter.java @@ -38,8 +38,7 @@ public Report parse(final ReaderFactory readerFactory) Set violations = parser.parseReportOutput(readerFactory.readString(), new NullViolationsLogger()); return convertToReport(violations); - } - catch (Exception exception) { + } catch (Exception exception) { throw new ParsingException(exception); } } @@ -54,9 +53,7 @@ public Report parse(final ReaderFactory readerFactory) /** * Converts the list of violations to a corresponding report of issues. * - * @param violations - * the violations - * + * @param violations the violations * @return the report */ Report convertToReport(final Set violations) { @@ -77,10 +74,8 @@ Report convertToReport(final Set violations) { /** * Post processes the report. * - * @param report - * the report with all converted and valid issues - * @param violations - * the violations that have been converted + * @param report the report with all converted and valid issues + * @param violations the violations that have been converted */ void postProcess(final Report report, final Set violations) { // empty default implementation @@ -90,9 +85,7 @@ void postProcess(final Report report, final Set violations) { * Returns whether this violation is valid and should be converted to an {@link Issue}. Return {@code false} if the * specified violation is a false positive or should not be counted. * - * @param violation - * the violation to check - * + * @param violation the violation to check * @return {@code true} if the violation is valid, {@code false} otherwise */ boolean isValid(final Violation violation) { @@ -102,11 +95,8 @@ boolean isValid(final Violation violation) { /** * Converts the specified violation to a corresponding {@link Issue} instance. * - * @param violation - * the violation - * @param builder - * the issue builder to use - * + * @param violation the violation + * @param builder the issue builder to use * @return corresponding {@link Issue} */ Issue convertToIssue(final Violation violation, final IssueBuilder builder) { @@ -120,10 +110,8 @@ Issue convertToIssue(final Violation violation, final IssueBuilder builder) { * Converts the specified violation to a corresponding {@link Issue} instance by setting the properties in the * provided {@link IssueBuilder}. * - * @param violation - * the violation - * @param builder - * the issue builder to change + * @param violation the violation + * @param builder the issue builder to change */ void updateIssueBuilder(final Violation violation, final IssueBuilder builder) { builder.setSeverity(convertSeverity(violation.getSeverity(), violation)) @@ -140,12 +128,10 @@ void updateIssueBuilder(final Violation violation, final IssueBuilder builder) { /** * Creates a default Integer representation for undefined input parameters. * - * @param integer - * the integer to check - * + * @param integer the integer to check * @return the valid integer value or 0 if the specified {@link Integer} is {@code null} or less than 0 */ - private int toValidInt(@CheckForNull final Integer integer) { + protected int toValidInt(@CheckForNull final Integer integer) { if (integer == null) { return 0; } @@ -156,10 +142,8 @@ private int toValidInt(@CheckForNull final Integer integer) { * Subclasses may add additional {@link IssueBuilder} properties based on the content of the specified {@link * Violation}. This default implementation is empty. * - * @param builder - * the issue builder to change - * @param violation - * the violation instance + * @param builder the issue builder to change + * @param violation the violation instance */ void extractAdditionalProperties(final IssueBuilder builder, final Violation violation) { // default implementation is empty @@ -169,11 +153,8 @@ void extractAdditionalProperties(final IssueBuilder builder, final Violation vio * Computes the {@link Severity} from the specified {@link SEVERITY}. Subclasses may override and use any of the * properties of the provided violation. * - * @param severity - * the severity - * @param violation - * the violation instance - * + * @param severity the severity + * @param violation the violation instance * @return the {@link Severity} */ Severity convertSeverity(final SEVERITY severity, final Violation violation) { diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java index b8faf2c9d..d76aec375 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java @@ -1,7 +1,15 @@ package edu.hm.hafner.analysis.parser.violations; +import edu.hm.hafner.analysis.Issue; +import edu.hm.hafner.analysis.IssueBuilder; +import edu.hm.hafner.util.PathUtil; +import se.bjurr.violations.lib.model.Violation; import se.bjurr.violations.lib.parsers.SarifParser; +import java.net.URI; +import java.nio.file.Path; +import java.nio.file.Paths; + /** * Parses SARIF files. * @@ -14,4 +22,34 @@ public class SarifAdapter extends AbstractViolationAdapter { SarifParser createParser() { return new SarifParser(); } + + private static final PathUtil PATH_UTIL = new PathUtil(); + + @Override + void updateIssueBuilder(final Violation violation, final IssueBuilder builder) { + builder.setSeverity(convertSeverity(violation.getSeverity(), violation)) + .setFileName(convertFileUriSchemeToPath(violation.getFile())) + .setMessage(violation.getMessage()) + .setLineStart(toValidInt(violation.getStartLine())) + .setLineEnd(toValidInt(violation.getEndLine())) + .setColumnStart(toValidInt(violation.getColumn())) + .setColumnEnd(toValidInt(violation.getEndColumn())) + .setType(violation.getRule()) + .setCategory(violation.getCategory()); + } + + String convertFileUriSchemeToPath(final String fileName) { + if (!fileName.startsWith("file:")) { + return fileName; + } + + try { + Path path = Paths.get(new URI(fileName)); + return path.toString(); + } catch (Exception e) { + // ignore + } + return fileName; + } + } diff --git a/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java b/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java index 4878f7243..4d69c2c6b 100644 --- a/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java +++ b/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java @@ -46,6 +46,26 @@ void shouldReportDifferentSeverities() { assertThat(report.getSizeOf(Severity.WARNING_LOW)).isEqualTo(3); } + @Test + void handleFilePathsInFileURIschemeFormat() { + Report report = parse("filePathInFileUriScheme.sarif"); + try (SoftAssertions softly = new SoftAssertions()) { + softly.assertThat(report).hasSize(2); + assertThatReportHasSeverities(report, 0, 0, 2, 0); + softly.assertThat(report.get(0)) + .hasSeverity(Severity.WARNING_NORMAL) + .hasLineStart(6) + .hasLineEnd(6) + .hasFileName("C:/my/workspace/project/this/dir/file.cs"); + softly.assertThat(report.get(1)) + .hasSeverity(Severity.WARNING_NORMAL) + .hasLineStart(5) + .hasLineEnd(5) + .hasFileName("C:/my/workspace/project/whatever/path.cs"); + } + } + + @Override protected SarifAdapter createParser() { return new SarifAdapter(); diff --git a/src/test/resources/edu/hm/hafner/analysis/parser/violations/filePathInFileUriScheme.sarif b/src/test/resources/edu/hm/hafner/analysis/parser/violations/filePathInFileUriScheme.sarif new file mode 100644 index 000000000..bbaa4feb2 --- /dev/null +++ b/src/test/resources/edu/hm/hafner/analysis/parser/violations/filePathInFileUriScheme.sarif @@ -0,0 +1,213 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.6.json", + "version": "2.1.0", + "runs": [ + { + "results": [ + { + "ruleId": "FirstRule", + "ruleIndex": 0, + "level": "warning", + "message": { + "text": "You should keep an eye on this code" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "whatever/path.cs", + "uriBaseId": "solutionDir", + "index": 0 + }, + "region": { + "startLine": 5, + "startColumn": 1, + "endLine": 5, + "endColumn": 23, + "charOffset": 143, + "charLength": 22 + } + } + } + ], + "partialFingerprints": { + }, + "properties": { + "tags": [ + "C#", + ".NET 8.0" + ] + } + }, + { + "ruleId": "secondRule", + "ruleIndex": 0, + "level": "warning", + "message": { + "text": "This is bad code!" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "this/dir/file.cs", + "uriBaseId": "solutionDir", + "index": 1 + }, + "region": { + "startLine": 6, + "startColumn": 1, + "endLine": 6, + "endColumn": 23, + "charOffset": 192, + "charLength": 22 + } + } + } + ], + "partialFingerprints": { + }, + "properties": { + "tags": [ + "C#", + ".NET 8.0" + ] + } + } + ], + "tool": { + "driver": { + "name": "InspectCode", + "organization": "JetBrains, Inc", + "fullName": "JetBrains Inspect Code 2024.2", + "semanticVersion": "242.0.20240814.114127", + "informationUri": "http://www.jetbrains.com/resharper/features/command-line.html", + "rules": [ + { + "id": "RedundantUsingDirective", + "fullDescription": { + "text": "Using directive is not required by the code and can be safely removed" + }, + "help": { + "text": "https://www.jetbrains.com/help/resharper/RedundantUsingDirective.html" + }, + "shortDescription": { + "text": "Redundant using directive" + }, + "defaultConfiguration": { + "level": "warning" + }, + "helpUri": "https://www.jetbrains.com/help/resharper/RedundantUsingDirective.html", + "relationships": [ + { + "target": { + "id": "CSHARP.CodeRedundancy", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + }, + { + "target": { + "id": "ASPX.CodeRedundancy", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + } + ], + "taxa": [ + { + "id": "ASPX", + "name": "Aspx" + }, + { + "id": "ASPX.CodeRedundancy", + "name": "Redundancies in Code", + "relationships": [ + { + "target": { + "id": "ASPX", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + }, + { + "id": "CSHARP", + "name": "C#" + }, + { + "id": "CSHARP.CodeRedundancy", + "name": "Redundancies in Code", + "relationships": [ + { + "target": { + "id": "CSHARP", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + } + ] + } + }, + "invocations": [ + { + "executionSuccessful": true + } + ], + "versionControlProvenance": [ + { + "repositoryUri": "https://gitlab.com/ourRepo.git", + "revisionId": "970f02980ede09609791feca6bf8cdcd72bbe217", + "branch": "HEAD", + "mappedTo": { + "uriBaseId": "solutionDir" + } + } + ], + "originalUriBaseIds": { + "solutionDir": { + "uri": "file:///C:/my/workspace/project/", + "description": { + "text": "Solution Directory" + } + } + }, + "artifacts": [ + { + "location": { + "uri": "whatever/path.cs", + "uriBaseId": "solutionDir" + } + }, + { + "location": { + "uri": "this/dir/file.cs", + "uriBaseId": "solutionDir" + } + } + ], + "columnKind": "utf16CodeUnits" + } + ] + } \ No newline at end of file From a78a4a034b493943f0ac6a8c24522abf24d81d95 Mon Sep 17 00:00:00 2001 From: theKBro Date: Mon, 4 Nov 2024 19:59:35 +0100 Subject: [PATCH 2/7] - revert unnecessary changes - adapt code accordingly --- .../violations/AbstractViolationAdapter.java | 49 +++++++++++++------ .../parser/violations/SarifAdapter.java | 20 ++------ .../parser/violations/SarifAdapterTest.java | 1 - 3 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/AbstractViolationAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/AbstractViolationAdapter.java index b867c8407..cfb0534c3 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/AbstractViolationAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/AbstractViolationAdapter.java @@ -38,7 +38,8 @@ public Report parse(final ReaderFactory readerFactory) Set violations = parser.parseReportOutput(readerFactory.readString(), new NullViolationsLogger()); return convertToReport(violations); - } catch (Exception exception) { + } + catch (Exception exception) { throw new ParsingException(exception); } } @@ -53,7 +54,9 @@ public Report parse(final ReaderFactory readerFactory) /** * Converts the list of violations to a corresponding report of issues. * - * @param violations the violations + * @param violations + * the violations + * * @return the report */ Report convertToReport(final Set violations) { @@ -74,8 +77,10 @@ Report convertToReport(final Set violations) { /** * Post processes the report. * - * @param report the report with all converted and valid issues - * @param violations the violations that have been converted + * @param report + * the report with all converted and valid issues + * @param violations + * the violations that have been converted */ void postProcess(final Report report, final Set violations) { // empty default implementation @@ -85,7 +90,9 @@ void postProcess(final Report report, final Set violations) { * Returns whether this violation is valid and should be converted to an {@link Issue}. Return {@code false} if the * specified violation is a false positive or should not be counted. * - * @param violation the violation to check + * @param violation + * the violation to check + * * @return {@code true} if the violation is valid, {@code false} otherwise */ boolean isValid(final Violation violation) { @@ -95,8 +102,11 @@ boolean isValid(final Violation violation) { /** * Converts the specified violation to a corresponding {@link Issue} instance. * - * @param violation the violation - * @param builder the issue builder to use + * @param violation + * the violation + * @param builder + * the issue builder to use + * * @return corresponding {@link Issue} */ Issue convertToIssue(final Violation violation, final IssueBuilder builder) { @@ -110,8 +120,10 @@ Issue convertToIssue(final Violation violation, final IssueBuilder builder) { * Converts the specified violation to a corresponding {@link Issue} instance by setting the properties in the * provided {@link IssueBuilder}. * - * @param violation the violation - * @param builder the issue builder to change + * @param violation + * the violation + * @param builder + * the issue builder to change */ void updateIssueBuilder(final Violation violation, final IssueBuilder builder) { builder.setSeverity(convertSeverity(violation.getSeverity(), violation)) @@ -128,10 +140,12 @@ void updateIssueBuilder(final Violation violation, final IssueBuilder builder) { /** * Creates a default Integer representation for undefined input parameters. * - * @param integer the integer to check + * @param integer + * the integer to check + * * @return the valid integer value or 0 if the specified {@link Integer} is {@code null} or less than 0 */ - protected int toValidInt(@CheckForNull final Integer integer) { + private int toValidInt(@CheckForNull final Integer integer) { if (integer == null) { return 0; } @@ -142,8 +156,10 @@ protected int toValidInt(@CheckForNull final Integer integer) { * Subclasses may add additional {@link IssueBuilder} properties based on the content of the specified {@link * Violation}. This default implementation is empty. * - * @param builder the issue builder to change - * @param violation the violation instance + * @param builder + * the issue builder to change + * @param violation + * the violation instance */ void extractAdditionalProperties(final IssueBuilder builder, final Violation violation) { // default implementation is empty @@ -153,8 +169,11 @@ void extractAdditionalProperties(final IssueBuilder builder, final Violation vio * Computes the {@link Severity} from the specified {@link SEVERITY}. Subclasses may override and use any of the * properties of the provided violation. * - * @param severity the severity - * @param violation the violation instance + * @param severity + * the severity + * @param violation + * the violation instance + * * @return the {@link Severity} */ Severity convertSeverity(final SEVERITY severity, final Violation violation) { diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java index d76aec375..c128007e2 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java @@ -1,8 +1,6 @@ package edu.hm.hafner.analysis.parser.violations; -import edu.hm.hafner.analysis.Issue; import edu.hm.hafner.analysis.IssueBuilder; -import edu.hm.hafner.util.PathUtil; import se.bjurr.violations.lib.model.Violation; import se.bjurr.violations.lib.parsers.SarifParser; @@ -23,19 +21,10 @@ SarifParser createParser() { return new SarifParser(); } - private static final PathUtil PATH_UTIL = new PathUtil(); - @Override void updateIssueBuilder(final Violation violation, final IssueBuilder builder) { - builder.setSeverity(convertSeverity(violation.getSeverity(), violation)) - .setFileName(convertFileUriSchemeToPath(violation.getFile())) - .setMessage(violation.getMessage()) - .setLineStart(toValidInt(violation.getStartLine())) - .setLineEnd(toValidInt(violation.getEndLine())) - .setColumnStart(toValidInt(violation.getColumn())) - .setColumnEnd(toValidInt(violation.getEndColumn())) - .setType(violation.getRule()) - .setCategory(violation.getCategory()); + super.updateIssueBuilder(violation, builder); + builder.setFileName(convertFileUriSchemeToPath(violation.getFile())); } String convertFileUriSchemeToPath(final String fileName) { @@ -46,10 +35,11 @@ String convertFileUriSchemeToPath(final String fileName) { try { Path path = Paths.get(new URI(fileName)); return path.toString(); - } catch (Exception e) { + } + catch (Exception e) + { // ignore } return fileName; } - } diff --git a/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java b/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java index 4d69c2c6b..4e2336a3b 100644 --- a/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java +++ b/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java @@ -65,7 +65,6 @@ void handleFilePathsInFileURIschemeFormat() { } } - @Override protected SarifAdapter createParser() { return new SarifAdapter(); From a7ff4b599fcca8951f9a346dc1eed0ba8fc89727 Mon Sep 17 00:00:00 2001 From: theKBro Date: Mon, 4 Nov 2024 20:12:15 +0100 Subject: [PATCH 3/7] - add test data to clarify that % encoding in file is also getting translated --- .../hm/hafner/analysis/parser/violations/SarifAdapter.java | 4 +++- .../hafner/analysis/parser/violations/SarifAdapterTest.java | 2 +- .../analysis/parser/violations/filePathInFileUriScheme.sarif | 4 ++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java index c128007e2..509343d7e 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java @@ -5,6 +5,8 @@ import se.bjurr.violations.lib.parsers.SarifParser; import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.InvalidPathException; import java.nio.file.Path; import java.nio.file.Paths; @@ -36,7 +38,7 @@ String convertFileUriSchemeToPath(final String fileName) { Path path = Paths.get(new URI(fileName)); return path.toString(); } - catch (Exception e) + catch (URISyntaxException | InvalidPathException e) { // ignore } diff --git a/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java b/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java index 4e2336a3b..229d925bc 100644 --- a/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java +++ b/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java @@ -61,7 +61,7 @@ void handleFilePathsInFileURIschemeFormat() { .hasSeverity(Severity.WARNING_NORMAL) .hasLineStart(5) .hasLineEnd(5) - .hasFileName("C:/my/workspace/project/whatever/path.cs"); + .hasFileName("C:/my/workspace/project/whatever/€path.cs"); } } diff --git a/src/test/resources/edu/hm/hafner/analysis/parser/violations/filePathInFileUriScheme.sarif b/src/test/resources/edu/hm/hafner/analysis/parser/violations/filePathInFileUriScheme.sarif index bbaa4feb2..6ea210e55 100644 --- a/src/test/resources/edu/hm/hafner/analysis/parser/violations/filePathInFileUriScheme.sarif +++ b/src/test/resources/edu/hm/hafner/analysis/parser/violations/filePathInFileUriScheme.sarif @@ -15,7 +15,7 @@ { "physicalLocation": { "artifactLocation": { - "uri": "whatever/path.cs", + "uri": "whatever/%E2%82%ACpath.cs", "uriBaseId": "solutionDir", "index": 0 }, @@ -196,7 +196,7 @@ "artifacts": [ { "location": { - "uri": "whatever/path.cs", + "uri": "whatever/%E2%82%ACpath.cs", "uriBaseId": "solutionDir" } }, From 26e6452436b26e75611b5a6e3d160f7700e4103c Mon Sep 17 00:00:00 2001 From: theKBro Date: Mon, 4 Nov 2024 20:29:19 +0100 Subject: [PATCH 4/7] - fix problem with absolute paths --- .../hm/hafner/analysis/parser/violations/SarifAdapter.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java index 509343d7e..d4b48a479 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java @@ -4,11 +4,10 @@ import se.bjurr.violations.lib.model.Violation; import se.bjurr.violations.lib.parsers.SarifParser; +import java.io.File; import java.net.URI; import java.net.URISyntaxException; import java.nio.file.InvalidPathException; -import java.nio.file.Path; -import java.nio.file.Paths; /** * Parses SARIF files. @@ -35,8 +34,8 @@ String convertFileUriSchemeToPath(final String fileName) { } try { - Path path = Paths.get(new URI(fileName)); - return path.toString(); + File file = new File(new URI(fileName)); + return file.toPath().toString(); } catch (URISyntaxException | InvalidPathException e) { From 4cb69c16fa065e7b625dbc0428d9bcb56f6b7c38 Mon Sep 17 00:00:00 2001 From: theKBro Date: Mon, 4 Nov 2024 20:05:46 +0000 Subject: [PATCH 5/7] fix check warning --- .../edu/hm/hafner/analysis/parser/violations/SarifAdapter.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java index d4b48a479..8c39662c2 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java @@ -37,8 +37,7 @@ String convertFileUriSchemeToPath(final String fileName) { File file = new File(new URI(fileName)); return file.toPath().toString(); } - catch (URISyntaxException | InvalidPathException e) - { + catch (URISyntaxException | InvalidPathException ignored) { // ignore } return fileName; From 8dfcf3c9f817de56263c0f5313833759e2d46b80 Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Thu, 7 Nov 2024 11:08:22 +0100 Subject: [PATCH 6/7] Fix handling of Windows paths on unix. --- .../parser/violations/SarifAdapter.java | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java index 8c39662c2..2404a62e6 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java @@ -1,14 +1,14 @@ package edu.hm.hafner.analysis.parser.violations; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.regex.Pattern; + import edu.hm.hafner.analysis.IssueBuilder; + import se.bjurr.violations.lib.model.Violation; import se.bjurr.violations.lib.parsers.SarifParser; -import java.io.File; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.InvalidPathException; - /** * Parses SARIF files. * @@ -17,29 +17,29 @@ public class SarifAdapter extends AbstractViolationAdapter { private static final long serialVersionUID = -5699747899173867285L; + private static final Pattern WINDOWS_PATH_ON_UNIX = Pattern.compile("^/[a-zA-Z]:.*"); + @Override SarifParser createParser() { return new SarifParser(); } @Override - void updateIssueBuilder(final Violation violation, final IssueBuilder builder) { - super.updateIssueBuilder(violation, builder); - builder.setFileName(convertFileUriSchemeToPath(violation.getFile())); - } - - String convertFileUriSchemeToPath(final String fileName) { - if (!fileName.startsWith("file:")) { - return fileName; - } - + void extractAdditionalProperties(final IssueBuilder builder, final Violation violation) { try { - File file = new File(new URI(fileName)); - return file.toPath().toString(); - } - catch (URISyntaxException | InvalidPathException ignored) { + var fileName = violation.getFile(); + var uri = new URI(fileName); + builder.setFileName(removePrefix(uri.getPath())); + } + catch (URISyntaxException exception) { // ignore } + } + + private String removePrefix(final String fileName) { + if (WINDOWS_PATH_ON_UNIX.matcher(fileName).matches()) { + return fileName.substring(1); + } return fileName; } } From 7df6f4d51315ccd4d34f1b6d3b897269816d757e Mon Sep 17 00:00:00 2001 From: Ulli Hafner Date: Fri, 8 Nov 2024 07:10:37 +0100 Subject: [PATCH 7/7] Add test with invalid or empty URIs. --- .../parser/violations/SarifAdapter.java | 8 +- .../parser/violations/SarifAdapterTest.java | 14 ++ .../parser/violations/brokenfilePath.sarif | 213 ++++++++++++++++++ .../parser/violations/emptyfilePath.sarif | 213 ++++++++++++++++++ 4 files changed, 445 insertions(+), 3 deletions(-) create mode 100644 src/test/resources/edu/hm/hafner/analysis/parser/violations/brokenfilePath.sarif create mode 100644 src/test/resources/edu/hm/hafner/analysis/parser/violations/emptyfilePath.sarif diff --git a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java index 2404a62e6..8d1e6d21f 100644 --- a/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java +++ b/src/main/java/edu/hm/hafner/analysis/parser/violations/SarifAdapter.java @@ -27,9 +27,11 @@ SarifParser createParser() { @Override void extractAdditionalProperties(final IssueBuilder builder, final Violation violation) { try { - var fileName = violation.getFile(); - var uri = new URI(fileName); - builder.setFileName(removePrefix(uri.getPath())); + var uri = new URI(violation.getFile()); + var path = uri.getPath(); + if (path != null) { + builder.setFileName(removePrefix(path)); + } } catch (URISyntaxException exception) { // ignore diff --git a/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java b/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java index 229d925bc..937238e3e 100644 --- a/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java +++ b/src/test/java/edu/hm/hafner/analysis/parser/violations/SarifAdapterTest.java @@ -1,6 +1,8 @@ package edu.hm.hafner.analysis.parser.violations; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; import edu.hm.hafner.analysis.Report; import edu.hm.hafner.analysis.Severity; @@ -65,6 +67,18 @@ void handleFilePathsInFileURIschemeFormat() { } } + @ParameterizedTest(name = "[{index}] Filename with invalid path: {0}") + @ValueSource(strings = {"brokenfilePath.sarif", "emptyfilePath.sarif"}) + void handleBrokenPathsInFileURIschemeFormat(final String fileName) { + Report report = parse(fileName); + try (SoftAssertions softly = new SoftAssertions()) { + softly.assertThat(report).hasSize(2); + assertThatReportHasSeverities(report, 0, 0, 2, 0); + softly.assertThat(report.get(0).getFileName()).endsWith("this/dir/file.cs"); + softly.assertThat(report.get(1).getFileName()).endsWith("path.cs"); + } + } + @Override protected SarifAdapter createParser() { return new SarifAdapter(); diff --git a/src/test/resources/edu/hm/hafner/analysis/parser/violations/brokenfilePath.sarif b/src/test/resources/edu/hm/hafner/analysis/parser/violations/brokenfilePath.sarif new file mode 100644 index 000000000..0db72f270 --- /dev/null +++ b/src/test/resources/edu/hm/hafner/analysis/parser/violations/brokenfilePath.sarif @@ -0,0 +1,213 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.6.json", + "version": "2.1.0", + "runs": [ + { + "results": [ + { + "ruleId": "FirstRule", + "ruleIndex": 0, + "level": "warning", + "message": { + "text": "You should keep an eye on this code" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "whatever/%E2%82%ACpath.cs", + "uriBaseId": "solutionDir", + "index": 0 + }, + "region": { + "startLine": 5, + "startColumn": 1, + "endLine": 5, + "endColumn": 23, + "charOffset": 143, + "charLength": 22 + } + } + } + ], + "partialFingerprints": { + }, + "properties": { + "tags": [ + "C#", + ".NET 8.0" + ] + } + }, + { + "ruleId": "secondRule", + "ruleIndex": 0, + "level": "warning", + "message": { + "text": "This is bad code!" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "this/dir/file.cs", + "uriBaseId": "solutionDir", + "index": 1 + }, + "region": { + "startLine": 6, + "startColumn": 1, + "endLine": 6, + "endColumn": 23, + "charOffset": 192, + "charLength": 22 + } + } + } + ], + "partialFingerprints": { + }, + "properties": { + "tags": [ + "C#", + ".NET 8.0" + ] + } + } + ], + "tool": { + "driver": { + "name": "InspectCode", + "organization": "JetBrains, Inc", + "fullName": "JetBrains Inspect Code 2024.2", + "semanticVersion": "242.0.20240814.114127", + "informationUri": "http://www.jetbrains.com/resharper/features/command-line.html", + "rules": [ + { + "id": "RedundantUsingDirective", + "fullDescription": { + "text": "Using directive is not required by the code and can be safely removed" + }, + "help": { + "text": "https://www.jetbrains.com/help/resharper/RedundantUsingDirective.html" + }, + "shortDescription": { + "text": "Redundant using directive" + }, + "defaultConfiguration": { + "level": "warning" + }, + "helpUri": "https://www.jetbrains.com/help/resharper/RedundantUsingDirective.html", + "relationships": [ + { + "target": { + "id": "CSHARP.CodeRedundancy", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + }, + { + "target": { + "id": "ASPX.CodeRedundancy", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + } + ], + "taxa": [ + { + "id": "ASPX", + "name": "Aspx" + }, + { + "id": "ASPX.CodeRedundancy", + "name": "Redundancies in Code", + "relationships": [ + { + "target": { + "id": "ASPX", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + }, + { + "id": "CSHARP", + "name": "C#" + }, + { + "id": "CSHARP.CodeRedundancy", + "name": "Redundancies in Code", + "relationships": [ + { + "target": { + "id": "CSHARP", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + } + ] + } + }, + "invocations": [ + { + "executionSuccessful": true + } + ], + "versionControlProvenance": [ + { + "repositoryUri": "https://gitlab.com/ourRepo.git", + "revisionId": "970f02980ede09609791feca6bf8cdcd72bbe217", + "branch": "HEAD", + "mappedTo": { + "uriBaseId": "solutionDir" + } + } + ], + "originalUriBaseIds": { + "solutionDir": { + "uri": "::::::/", + "description": { + "text": "Solution Directory" + } + } + }, + "artifacts": [ + { + "location": { + "uri": "whatever/%E2%82%ACpath.cs", + "uriBaseId": "solutionDir" + } + }, + { + "location": { + "uri": "this/dir/file.cs", + "uriBaseId": "solutionDir" + } + } + ], + "columnKind": "utf16CodeUnits" + } + ] + } diff --git a/src/test/resources/edu/hm/hafner/analysis/parser/violations/emptyfilePath.sarif b/src/test/resources/edu/hm/hafner/analysis/parser/violations/emptyfilePath.sarif new file mode 100644 index 000000000..79efa5729 --- /dev/null +++ b/src/test/resources/edu/hm/hafner/analysis/parser/violations/emptyfilePath.sarif @@ -0,0 +1,213 @@ +{ + "$schema": "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.6.json", + "version": "2.1.0", + "runs": [ + { + "results": [ + { + "ruleId": "FirstRule", + "ruleIndex": 0, + "level": "warning", + "message": { + "text": "You should keep an eye on this code" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "whatever/%E2%82%ACpath.cs", + "uriBaseId": "solutionDir", + "index": 0 + }, + "region": { + "startLine": 5, + "startColumn": 1, + "endLine": 5, + "endColumn": 23, + "charOffset": 143, + "charLength": 22 + } + } + } + ], + "partialFingerprints": { + }, + "properties": { + "tags": [ + "C#", + ".NET 8.0" + ] + } + }, + { + "ruleId": "secondRule", + "ruleIndex": 0, + "level": "warning", + "message": { + "text": "This is bad code!" + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "uri": "this/dir/file.cs", + "uriBaseId": "solutionDir", + "index": 1 + }, + "region": { + "startLine": 6, + "startColumn": 1, + "endLine": 6, + "endColumn": 23, + "charOffset": 192, + "charLength": 22 + } + } + } + ], + "partialFingerprints": { + }, + "properties": { + "tags": [ + "C#", + ".NET 8.0" + ] + } + } + ], + "tool": { + "driver": { + "name": "InspectCode", + "organization": "JetBrains, Inc", + "fullName": "JetBrains Inspect Code 2024.2", + "semanticVersion": "242.0.20240814.114127", + "informationUri": "http://www.jetbrains.com/resharper/features/command-line.html", + "rules": [ + { + "id": "RedundantUsingDirective", + "fullDescription": { + "text": "Using directive is not required by the code and can be safely removed" + }, + "help": { + "text": "https://www.jetbrains.com/help/resharper/RedundantUsingDirective.html" + }, + "shortDescription": { + "text": "Redundant using directive" + }, + "defaultConfiguration": { + "level": "warning" + }, + "helpUri": "https://www.jetbrains.com/help/resharper/RedundantUsingDirective.html", + "relationships": [ + { + "target": { + "id": "CSHARP.CodeRedundancy", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + }, + { + "target": { + "id": "ASPX.CodeRedundancy", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + } + ], + "taxa": [ + { + "id": "ASPX", + "name": "Aspx" + }, + { + "id": "ASPX.CodeRedundancy", + "name": "Redundancies in Code", + "relationships": [ + { + "target": { + "id": "ASPX", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + }, + { + "id": "CSHARP", + "name": "C#" + }, + { + "id": "CSHARP.CodeRedundancy", + "name": "Redundancies in Code", + "relationships": [ + { + "target": { + "id": "CSHARP", + "toolComponent": { + "name": "InspectCode" + } + }, + "kinds": [ + "superset" + ] + } + ] + } + ] + } + }, + "invocations": [ + { + "executionSuccessful": true + } + ], + "versionControlProvenance": [ + { + "repositoryUri": "https://gitlab.com/ourRepo.git", + "revisionId": "970f02980ede09609791feca6bf8cdcd72bbe217", + "branch": "HEAD", + "mappedTo": { + "uriBaseId": "solutionDir" + } + } + ], + "originalUriBaseIds": { + "solutionDir": { + "uri": "empty:", + "description": { + "text": "Solution Directory" + } + } + }, + "artifacts": [ + { + "location": { + "uri": "whatever/%E2%82%ACpath.cs", + "uriBaseId": "solutionDir" + } + }, + { + "location": { + "uri": "this/dir/file.cs", + "uriBaseId": "solutionDir" + } + } + ], + "columnKind": "utf16CodeUnits" + } + ] + }