diff --git a/src/main/java/edu/hm/hafner/analysis/registry/ClairDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/ClairDescriptor.java index 353e87b95..e1e128f1b 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/ClairDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/ClairDescriptor.java @@ -33,4 +33,9 @@ public String getHelp() { public String getUrl() { return "https://github.com/arminc/clair-scanner"; } + + @Override + public Type getType() { + return Type.VULNERABILITY; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/CodeCheckerDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/CodeCheckerDescriptor.java index 6c0ec4487..c3026f00b 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/CodeCheckerDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/CodeCheckerDescriptor.java @@ -4,7 +4,7 @@ import edu.hm.hafner.analysis.parser.CodeCheckerParser; /** - * A descriptor for the Codechecker parser. + * A descriptor for the CodeChecker parser. * */ class CodeCheckerDescriptor extends ParserDescriptor { diff --git a/src/main/java/edu/hm/hafner/analysis/registry/DryDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/DryDescriptor.java index d32580231..36391449d 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/DryDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/DryDescriptor.java @@ -67,4 +67,9 @@ private static String getCodeFragment(final DuplicationGroup duplicationGroup) { public String getDescription(final Issue issue) { return getDuplicateCode(issue.getAdditionalProperties()); } + + @Override + public Type getType() { + return Type.DUPLICATION; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/ErrorProneDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/ErrorProneDescriptor.java index 031b20094..6f3858bc6 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/ErrorProneDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/ErrorProneDescriptor.java @@ -28,4 +28,9 @@ protected Collection createParsers() { public String getUrl() { return "https://errorprone.info"; } + + @Override + public Type getType() { + return Type.BUG; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/FindBugsDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/FindBugsDescriptor.java index e8dd45ee6..e771e89b9 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/FindBugsDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/FindBugsDescriptor.java @@ -49,4 +49,9 @@ public String getPattern() { public String getDescription(final Issue issue) { return messages.get().getMessage(issue.getType()); } + + @Override + public Type getType() { + return Type.BUG; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/FlawfinderDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/FlawfinderDescriptor.java index 4bbb56ce1..2ec09e581 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/FlawfinderDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/FlawfinderDescriptor.java @@ -30,4 +30,9 @@ public String getHelp() { public String getUrl() { return "https://dwheeler.com/flawfinder/"; } + + @Override + public Type getType() { + return Type.VULNERABILITY; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/OwaspDependencyCheckDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/OwaspDependencyCheckDescriptor.java index a29b3690e..364ff02d1 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/OwaspDependencyCheckDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/OwaspDependencyCheckDescriptor.java @@ -33,4 +33,9 @@ public String getUrl() { public String getIconUrl() { return "https://raw.githubusercontent.com/jeremylong/DependencyCheck/main/src/site/resources/images/logo.svg"; } + + @Override + public Type getType() { + return Type.VULNERABILITY; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/ParserDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/ParserDescriptor.java index 1011bcdd2..40efb8989 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/ParserDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/ParserDescriptor.java @@ -47,6 +47,17 @@ public String getName() { return name; } + /** + * Returns the type of the parser. The type is used to customize parsers in the UI. + * This default implementation returns {@link Type#WARNING}. + * Override this method if your parser is of a different type. + * + * @return the type of the parser + */ + public Type getType() { + return Type.WARNING; + } + /** * Creates a new {@link IssueParser} instance. * @@ -129,6 +140,20 @@ public String getDescription(final Issue issue) { return issue.getDescription(); } + /** + * Returns the type of the parser. The type is used to customize parsers in the UI. + */ + public enum Type { + /** A parser that scans the output of a build tool to find warnings. */ + WARNING, + /** A parser that scans the output of a build tool to find bugs. */ + BUG, + /** A parser that scans the output of a build tool to find vulnerabilities. */ + VULNERABILITY, + /** A parser that scans the output of a build tool to find vulnerabilities. */ + DUPLICATION + } + /** * A parser configuration option. Basically an immutable key and value pair. */ diff --git a/src/main/java/edu/hm/hafner/analysis/registry/ParserRegistry.java b/src/main/java/edu/hm/hafner/analysis/registry/ParserRegistry.java index 155a851d5..ae6fe93b1 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/ParserRegistry.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/ParserRegistry.java @@ -265,11 +265,11 @@ public static void main(final String... unused) throws IOException { + "\n" + "The static analysis model supports the following report formats.\n" + "\n" - + "If your tool is not yet supported you can\n" + + "If your tool is not yet supported, you can\n" + "1. export the issues of your tool to the native XML or JSON format (or any other format).\n" + "2. provide a [pull request](https://github.com/jenkinsci/analysis-model/pulls) with a new parser.\n" + "\n" - + "If your tool is supported, but some properties are missing (icon, URL, etc.), please file a\n" + + "If your tool is supported, but some properties are missing (icon, URL, etc.), please file a " + "[pull request](https://github.com/jenkinsci/analysis-model/pulls).\n" + "\n"); diff --git a/src/main/java/edu/hm/hafner/analysis/registry/PnpmAuditDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/PnpmAuditDescriptor.java index 1dca770e4..1984bf270 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/PnpmAuditDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/PnpmAuditDescriptor.java @@ -41,4 +41,9 @@ public String getUrl() { public String getIconUrl() { return "https://pnpm.io/img/pnpm-no-name-with-frame.svg"; } + + @Override + public Type getType() { + return Type.VULNERABILITY; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/SemgrepDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/SemgrepDescriptor.java index 288ca9a5d..0e6433863 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/SemgrepDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/SemgrepDescriptor.java @@ -35,4 +35,9 @@ public String getUrl() { public String getIconUrl() { return "https://raw.githubusercontent.com/returntocorp/semgrep/develop/semgrep.svg"; } + + @Override + public Type getType() { + return Type.VULNERABILITY; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/SpotBugsDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/SpotBugsDescriptor.java index e150954ca..0667dee5a 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/SpotBugsDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/SpotBugsDescriptor.java @@ -27,4 +27,9 @@ public String getUrl() { public String getIconUrl() { return "https://raw.githubusercontent.com/spotbugs/spotbugs.github.io/master/images/logos/spotbugs_icon_only_zoom_256px.png"; } + + @Override + public Type getType() { + return Type.BUG; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/TrivyDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/TrivyDescriptor.java index 336394f33..a6eea4ea5 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/TrivyDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/TrivyDescriptor.java @@ -41,4 +41,9 @@ public String getUrl() { public String getIconUrl() { return "https://github.com/aquasecurity/trivy/blob/main/docs/imgs/logo.png?raw=true"; } + + @Override + public Type getType() { + return Type.VULNERABILITY; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/YoctoScannerDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/YoctoScannerDescriptor.java index f7d426068..a5bef4f54 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/YoctoScannerDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/YoctoScannerDescriptor.java @@ -41,4 +41,9 @@ public String getUrl() { public String getIconUrl() { return "https://upload.wikimedia.org/wikipedia/commons/0/00/Yocto_Project_logo.svg"; } + + @Override + public Type getType() { + return Type.VULNERABILITY; + } } diff --git a/src/main/java/edu/hm/hafner/analysis/registry/ZptLintDescriptor.java b/src/main/java/edu/hm/hafner/analysis/registry/ZptLintDescriptor.java index edc059292..e4cdee560 100644 --- a/src/main/java/edu/hm/hafner/analysis/registry/ZptLintDescriptor.java +++ b/src/main/java/edu/hm/hafner/analysis/registry/ZptLintDescriptor.java @@ -4,7 +4,7 @@ import edu.hm.hafner.analysis.parser.violations.ZptLintAdapter; /** - * A descriptor for the Yui Compressor parser. + * A descriptor for the ZPT Lint parser. * * @author Lorenz Munsch */ diff --git a/src/test/java/edu/hm/hafner/analysis/registry/ParserRegistryTest.java b/src/test/java/edu/hm/hafner/analysis/registry/ParserRegistryTest.java index a4c58ae2c..19bff637a 100644 --- a/src/test/java/edu/hm/hafner/analysis/registry/ParserRegistryTest.java +++ b/src/test/java/edu/hm/hafner/analysis/registry/ParserRegistryTest.java @@ -2,6 +2,7 @@ import java.util.List; import java.util.NoSuchElementException; +import java.util.stream.Collectors; import org.junit.jupiter.api.Test; @@ -20,6 +21,13 @@ * @author Ullrich Hafner */ class ParserRegistryTest extends ResourceTest { + // Note for parser developers: if you add a new parser, + // please check if you are using the correct type and increment the corresponding count + private static final long WARNING_PARSERS_COUNT = 127L; + private static final long BUG_PARSERS_COUNT = 3L; + private static final long VULNERABILITY_PARSERS_COUNT = 7L; + private static final long DUPLICATION_PARSERS_COUNT = 3L; + public static final String SPOTBUGS = "spotbugs"; public static final String CHECKSTYLE = "checkstyle"; public static final String PMD = "pmd"; @@ -32,12 +40,28 @@ void shouldThrowExceptionIfParserNotFound() { .isThrownBy(() -> parserRegistry.get("-")); } + /** + * Ensures that new parsers have the correct type assigned. + */ + @Test + void shouldAssignCorrectParserType() { + var parserRegistry = new ParserRegistry(); + var typeCountMap = parserRegistry.getAllDescriptors().stream() + .collect(Collectors.groupingBy(ParserDescriptor::getType, Collectors.counting())); + assertThat(typeCountMap) + .containsEntry(ParserDescriptor.Type.WARNING, WARNING_PARSERS_COUNT) + .containsEntry(ParserDescriptor.Type.BUG, BUG_PARSERS_COUNT) + .containsEntry(ParserDescriptor.Type.VULNERABILITY, VULNERABILITY_PARSERS_COUNT) + .containsEntry(ParserDescriptor.Type.DUPLICATION, DUPLICATION_PARSERS_COUNT); + } + @Test void shouldFindSomeParsers() { var parserRegistry = new ParserRegistry(); assertThat(parserRegistry).hasIds(SPOTBUGS, CHECKSTYLE, PMD).hasNames("SpotBugs", "CheckStyle", "PMD"); - assertThat(parserRegistry.get(SPOTBUGS)).hasId(SPOTBUGS).hasName("SpotBugs"); + assertThat(parserRegistry.get(SPOTBUGS)).hasId(SPOTBUGS).hasName("SpotBugs").hasType(ParserDescriptor.Type.BUG); + assertThat(parserRegistry.get("owasp-dependency-check")).hasName("OWASP Dependency Check").hasType(ParserDescriptor.Type.VULNERABILITY); assertThat(parserRegistry.contains(SPOTBUGS)).isTrue(); assertThat(parserRegistry.contains("nothing")).isFalse(); List descriptors = parserRegistry.getAllDescriptors(); @@ -49,6 +73,7 @@ void shouldFindSomeParsers() { void shouldConfigureCpdParser() { var parserRegistry = new ParserRegistry(); var cpdDescriptor = parserRegistry.get("cpd"); + assertThat(cpdDescriptor).hasType(ParserDescriptor.Type.DUPLICATION).hasName("CPD"); IssueParser parser = cpdDescriptor.createParser();