From f3028f632704711d23bd27ce35bb04bd56f0b984 Mon Sep 17 00:00:00 2001 From: lukasz-jarocki-sonarsource Date: Wed, 2 Aug 2023 12:07:25 +0200 Subject: [PATCH] SONAR-20021 passing overriden impacts from analyzer to scanner report --- .../batch/sensor/issue/internal/DefaultIssue.java | 8 ++++++-- .../sensor/issue/internal/DefaultIssueTest.java | 8 ++++++++ .../java/org/sonar/scanner/issue/IssuePublisher.java | 10 ++++++++++ .../org/sonar/scanner/issue/IssuePublisherTest.java | 12 ++++++++++-- .../src/main/protobuf/scanner_report.proto | 7 +++++++ 5 files changed, 41 insertions(+), 4 deletions(-) diff --git a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java index 4790c3f80a6..38c0d61e041 100644 --- a/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java +++ b/sonar-plugin-api-impl/src/main/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssue.java @@ -21,6 +21,8 @@ package org.sonar.api.batch.sensor.issue.internal; import java.util.ArrayList; import java.util.Collections; +import java.util.EnumMap; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; @@ -42,6 +44,7 @@ import static org.sonar.api.utils.Preconditions.checkArgument; import static org.sonar.api.utils.Preconditions.checkState; public class DefaultIssue extends AbstractDefaultIssue implements Issue, NewIssue { + private final Map overridenImpacts = new EnumMap<>(SoftwareQuality.class); private RuleKey ruleKey; private Double gap; private Severity overriddenSeverity; @@ -81,7 +84,8 @@ public class DefaultIssue extends AbstractDefaultIssue implements @Override public DefaultIssue overrideImpact(SoftwareQuality softwareQuality, org.sonar.api.issue.impact.Severity severity) { - return null; + overridenImpacts.put(softwareQuality, severity); + return this; } @Override @@ -144,7 +148,7 @@ public class DefaultIssue extends AbstractDefaultIssue implements @Override public Map overridenImpacts() { - return Collections.emptyMap(); + return overridenImpacts; } @Override diff --git a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java index f35583825ca..ba3e9e48b94 100644 --- a/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java +++ b/sonar-plugin-api-impl/src/test/java/org/sonar/api/batch/sensor/issue/internal/DefaultIssueTest.java @@ -41,6 +41,7 @@ import org.sonar.api.batch.sensor.issue.Issue.Flow; import org.sonar.api.batch.sensor.issue.MessageFormatting; import org.sonar.api.batch.sensor.issue.NewIssue.FlowType; import org.sonar.api.batch.sensor.issue.fix.NewQuickFix; +import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.rule.RuleKey; import static org.assertj.core.api.Assertions.assertThat; @@ -234,6 +235,13 @@ public class DefaultIssueTest { assertThat(issue.isQuickFixAvailable()).isTrue(); } + @Test + public void issue_can_override_impacts() { + DefaultIssue issue = new DefaultIssue(project, storage).overrideImpact(SoftwareQuality.RELIABILITY, org.sonar.api.issue.impact.Severity.LOW); + + assertThat(issue.overridenImpacts()).containsEntry(SoftwareQuality.RELIABILITY, org.sonar.api.issue.impact.Severity.LOW); + } + @Test public void quickfix_only_sets_flag_to_true() { DefaultIssue issue = new DefaultIssue(project); diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssuePublisher.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssuePublisher.java index 5e3b7a6d254..3b2f99fecaf 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssuePublisher.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/issue/IssuePublisher.java @@ -19,8 +19,10 @@ */ package org.sonar.scanner.issue; +import java.util.ArrayList; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.function.Consumer; import java.util.stream.Collectors; import javax.annotation.Nullable; @@ -37,6 +39,7 @@ import org.sonar.api.batch.sensor.issue.Issue.Flow; import org.sonar.api.batch.sensor.issue.MessageFormatting; import org.sonar.api.batch.sensor.issue.NewIssue.FlowType; import org.sonar.api.batch.sensor.issue.internal.DefaultIssueFlow; +import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.scanner.protocol.Constants.Severity; import org.sonar.scanner.protocol.output.ScannerReport; import org.sonar.scanner.protocol.output.ScannerReport.IssueLocation; @@ -116,6 +119,7 @@ public class IssuePublisher { builder.setRuleKey(issue.ruleKey().rule()); builder.setMsg(primaryMessage); builder.addAllMsgFormatting(toProtobufMessageFormattings(issue.primaryLocation().messageFormattings())); + builder.addAllOverridenImpacts(toProtobufImpacts(issue.overridenImpacts())); locationBuilder.setMsg(primaryMessage); locationBuilder.addAllMsgFormatting(toProtobufMessageFormattings(issue.primaryLocation().messageFormattings())); @@ -138,6 +142,12 @@ public class IssuePublisher { return builder.build(); } + private static List toProtobufImpacts(Map softwareQualitySeverityMap) { + List impacts = new ArrayList<>(); + softwareQualitySeverityMap.forEach((q, s) -> impacts.add(ScannerReport.Impact.newBuilder().setSoftwareQuality(q.name()).setSeverity(s.name()).build())); + return impacts; + } + private static List toProtobufMessageFormattings(List messageFormattings) { return messageFormattings.stream() .map(m -> ScannerReport.MessageFormatting.newBuilder() diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java index faaea60e599..c8bc5f78445 100644 --- a/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java +++ b/sonar-scanner-engine/src/test/java/org/sonar/scanner/issue/IssuePublisherTest.java @@ -42,6 +42,7 @@ import org.sonar.api.batch.sensor.issue.internal.DefaultExternalIssue; import org.sonar.api.batch.sensor.issue.internal.DefaultIssue; import org.sonar.api.batch.sensor.issue.internal.DefaultIssueLocation; import org.sonar.api.batch.sensor.issue.internal.DefaultMessageFormatting; +import org.sonar.api.issue.impact.SoftwareQuality; import org.sonar.api.rule.RuleKey; import org.sonar.api.rule.Severity; import org.sonar.api.rules.RuleType; @@ -59,10 +60,11 @@ import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoInteractions; import static org.mockito.Mockito.when; import static org.sonar.api.batch.sensor.issue.MessageFormatting.Type.CODE; +import static org.sonar.api.issue.impact.SoftwareQuality.*; @RunWith(MockitoJUnitRunner.class) public class IssuePublisherTest { - static final RuleKey JAVA_RULE_KEY = RuleKey.of("java", "AvoidCycle"); + private static final RuleKey JAVA_RULE_KEY = RuleKey.of("java", "AvoidCycle"); private static final RuleKey NOSONAR_RULE_KEY = RuleKey.of("java", "NoSonarCheck"); private DefaultInputProject project; @@ -128,7 +130,9 @@ public class IssuePublisherTest { .overrideSeverity(org.sonar.api.batch.rule.Severity.CRITICAL) .setQuickFixAvailable(true) .setRuleDescriptionContextKey(ruleDescriptionContextKey) - .setCodeVariants(List.of("variant1", "variant2")); + .setCodeVariants(List.of("variant1", "variant2")) + .overrideImpact(MAINTAINABILITY, org.sonar.api.issue.impact.Severity.HIGH) + .overrideImpact(RELIABILITY, org.sonar.api.issue.impact.Severity.LOW); when(filters.accept(any(InputComponent.class), any(ScannerReport.Issue.class))).thenReturn(true); @@ -141,6 +145,10 @@ public class IssuePublisherTest { assertThat(argument.getValue().getQuickFixAvailable()).isTrue(); assertThat(argument.getValue().getRuleDescriptionContextKey()).isEqualTo(ruleDescriptionContextKey); assertThat(argument.getValue().getCodeVariantsList()).containsExactly("variant1", "variant2"); + + ScannerReport.Impact impact1 = ScannerReport.Impact.newBuilder().setSoftwareQuality(MAINTAINABILITY.name()).setSeverity("HIGH").build(); + ScannerReport.Impact impact2 = ScannerReport.Impact.newBuilder().setSoftwareQuality(RELIABILITY.name()).setSeverity("LOW").build(); + assertThat(argument.getValue().getOverridenImpactsList()).containsExactly(impact1, impact2); } @Test diff --git a/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto b/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto index 335df02507f..5de3e742b21 100644 --- a/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto +++ b/sonar-scanner-protocol/src/main/protobuf/scanner_report.proto @@ -201,6 +201,7 @@ message Issue { optional string ruleDescriptionContextKey = 9; repeated MessageFormatting msgFormatting = 10; repeated string codeVariants = 11; + repeated Impact overridenImpacts = 12; } message ExternalIssue { @@ -213,6 +214,7 @@ message ExternalIssue { repeated Flow flow = 7; IssueType type = 8; repeated MessageFormatting msgFormatting = 9; + repeated Impact overridenImpacts = 10; } message AdHocRule { @@ -361,3 +363,8 @@ message AnalysisWarning { string text = 1; int64 timestamp = 2; } + +message Impact { + string software_quality = 1; + string severity = 2; +} \ No newline at end of file -- 2.39.5