From 7ab8cee5c0551d96cacda12d4df3d3a17c0ac2d2 Mon Sep 17 00:00:00 2001 From: Aurelien Poscia Date: Tue, 5 Jul 2022 11:13:23 +0200 Subject: [PATCH] SONAR-16614 add ruleDescriptionContextKey to IssueDto and adapt mybatis mapping --- .../java/org/sonar/db/issue/IssueDto.java | 10 +++ .../java/org/sonar/db/issue/IssueTesting.java | 1 + .../org/sonar/db/issue/IssueMapper.xml | 10 ++- .../java/org/sonar/db/issue/IssueDaoTest.java | 88 +++++++++++++++++-- .../org/sonar/core/issue/DefaultIssue.java | 62 +++++++------ 5 files changed, 138 insertions(+), 33 deletions(-) diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java index ef374054f55..8e6ad9f5a36 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java @@ -75,6 +75,7 @@ public final class IssueDto implements Serializable { private long updatedAt; private boolean quickFixAvailable; private boolean isNewCodeReferenceIssue; + private String ruleDescriptionContextKey; // functional dates stored as Long private Long issueCreationDate; @@ -698,6 +699,15 @@ public final class IssueDto implements Serializable { return Optional.ofNullable(closedChangeData); } + public Optional getOptionalRuleDescriptionContextKey() { + return Optional.ofNullable(ruleDescriptionContextKey); + } + + public IssueDto setRuleDescriptionContextKey(@Nullable String ruleDescriptionContextKey) { + this.ruleDescriptionContextKey = ruleDescriptionContextKey; + return this; + } + @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java index 0577ae6452b..056a1651b2d 100644 --- a/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java +++ b/server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueTesting.java @@ -75,6 +75,7 @@ public class IssueTesting { .setMessage("message_" + randomAlphabetic(5)) .setChecksum("checksum_" + randomAlphabetic(5)) .setTags(newHashSet("tag_" + randomAlphanumeric(5), "tag_" + randomAlphanumeric(5))) + .setRuleDescriptionContextKey("context_" + randomAlphabetic(5)) .setIssueCreationDate(new Date(System.currentTimeMillis() - 2_000)) .setIssueUpdateDate(new Date(System.currentTimeMillis() - 1_500)) .setCreatedAt(System.currentTimeMillis() - 1_000) diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml index 7cd7edc76f6..d78ed8ec0b1 100644 --- a/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml +++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/issue/IssueMapper.xml @@ -20,6 +20,7 @@ i.assignee as assigneeUuid, i.author_login as authorLogin, i.tags as tagsString, + i.rule_description_context_key as ruleDescriptionContextKey, i.issue_creation_date as issueCreationTime, i.issue_update_date as issueUpdateTime, i.issue_close_date as issueCloseTime, @@ -57,6 +58,7 @@ i.assignee, i.author_login, i.tags, + i.rule_description_context_key, i.issue_creation_date, i.issue_update_date, i.issue_close_date, @@ -105,7 +107,7 @@ INSERT INTO issues (kee, rule_uuid, severity, manual_severity, - message, line, locations, gap, effort, status, tags, + message, line, locations, gap, effort, status, tags, rule_description_context_key, resolution, checksum, assignee, author_login, issue_creation_date, issue_update_date, issue_close_date, created_at, updated_at, component_uuid, project_uuid, issue_type, quick_fix_available) VALUES ( @@ -115,7 +117,9 @@ #{manualSeverity,jdbcType=BOOLEAN}, #{message,jdbcType=VARCHAR}, #{line,jdbcType=INTEGER}, #{locations,jdbcType=BINARY}, #{gap,jdbcType=DOUBLE}, #{effort,jdbcType=INTEGER}, #{status,jdbcType=VARCHAR}, - #{tagsString,jdbcType=VARCHAR}, #{resolution,jdbcType=VARCHAR}, + #{tagsString,jdbcType=VARCHAR}, + #{ruleDescriptionContextKey,jdbcType=VARCHAR}, + #{resolution,jdbcType=VARCHAR}, #{checksum,jdbcType=VARCHAR}, #{assigneeUuid,jdbcType=VARCHAR}, #{authorLogin,jdbcType=VARCHAR}, @@ -156,6 +160,7 @@ assignee=#{assigneeUuid,jdbcType=VARCHAR}, author_login=#{authorLogin,jdbcType=VARCHAR}, tags=#{tagsString,jdbcType=VARCHAR}, + rule_description_context_key=#{ruleDescriptionContextKey,jdbcType=VARCHAR}, project_uuid=#{projectUuid,jdbcType=VARCHAR}, issue_creation_date=#{issueCreationTime,jdbcType=BIGINT}, issue_update_date=#{issueUpdateTime,jdbcType=BIGINT}, @@ -183,6 +188,7 @@ assignee=#{assigneeUuid,jdbcType=VARCHAR}, author_login=#{authorLogin,jdbcType=VARCHAR}, tags=#{tagsString,jdbcType=VARCHAR}, + rule_description_context_key=#{ruleDescriptionContextKey,jdbcType=VARCHAR}, component_uuid=#{componentUuid,jdbcType=VARCHAR}, project_uuid=#{projectUuid,jdbcType=VARCHAR}, issue_creation_date=#{issueCreationTime,jdbcType=BIGINT}, diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueDaoTest.java index 607df35387a..c74730f99a4 100644 --- a/server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueDaoTest.java +++ b/server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueDaoTest.java @@ -71,6 +71,7 @@ public class IssueDaoTest { private static final RuleDto RULE = RuleTesting.newXooX1(); private static final String ISSUE_KEY1 = "I1"; private static final String ISSUE_KEY2 = "I2"; + private static final String TEST_CONTEXT_KEY = "test_context_key"; private static final RuleType[] RULE_TYPES_EXCEPT_HOTSPOT = Stream.of(RuleType.values()) .filter(r -> r != RuleType.SECURITY_HOTSPOT) @@ -95,6 +96,7 @@ public class IssueDaoTest { assertThat(issue.getType()).isEqualTo(2); assertThat(issue.isManualSeverity()).isFalse(); assertThat(issue.getMessage()).isEqualTo("the message"); + assertThat(issue.getOptionalRuleDescriptionContextKey()).contains(TEST_CONTEXT_KEY); assertThat(issue.getLine()).isEqualTo(500); assertThat(issue.getEffort()).isEqualTo(10L); assertThat(issue.getGap()).isEqualTo(3.14); @@ -376,12 +378,8 @@ public class IssueDaoTest { @Test public void selectByKey_givenOneIssueWithoutQuickFix_selectOneIssueWithoutQuickFix() { prepareIssuesComponent(); - underTest.insert(db.getSession(), newIssueDto(ISSUE_KEY1) - .setMessage("the message") - .setRuleUuid(RULE.getUuid()) - .setComponentUuid(FILE_UUID) - .setProjectUuid(PROJECT_UUID) - .setQuickFixAvailable(false)); + String issueKey = ISSUE_KEY1; + underTest.insert(db.getSession(), createIssueWithKey(issueKey)); IssueDto issue = underTest.selectOrFailByKey(db.getSession(), ISSUE_KEY1); @@ -670,6 +668,83 @@ public class IssueDaoTest { assertThat(underTest.selectOrFailByKey(db.getSession(), ISSUE_KEY1).isNewCodeReferenceIssue()).isFalse(); } + @Test + public void selectByKey_givenOneIssueWithoutRuleDescriptionContextKey_returnsEmptyOptional() { + prepareIssuesComponent(); + underTest.insert(db.getSession(), createIssueWithKey(ISSUE_KEY1) + .setRuleDescriptionContextKey(null) + ); + IssueDto issue1 = underTest.selectOrFailByKey(db.getSession(), ISSUE_KEY1); + + assertThat(issue1.getOptionalRuleDescriptionContextKey()).isEmpty(); + } + + @Test + public void selectByKey_givenOneIssueWithRuleDescriptionContextKey_returnsContextKey() { + prepareIssuesComponent(); + underTest.insert(db.getSession(), createIssueWithKey(ISSUE_KEY1) + .setRuleDescriptionContextKey(TEST_CONTEXT_KEY) + ); + + IssueDto issue1 = underTest.selectOrFailByKey(db.getSession(), ISSUE_KEY1); + + assertThat(issue1.getOptionalRuleDescriptionContextKey()).contains(TEST_CONTEXT_KEY); + } + + @Test + public void update_whenUpdatingRuleDescriptionContextKeyToNull_returnsEmptyContextKey() { + prepareIssuesComponent(); + IssueDto issue = createIssueWithKey(ISSUE_KEY1).setRuleDescriptionContextKey(TEST_CONTEXT_KEY); + underTest.insert(db.getSession(), issue); + + issue.setRuleDescriptionContextKey(null); + underTest.update(db.getSession(), issue); + + issue = underTest.selectOrFailByKey(db.getSession(), ISSUE_KEY1); + assertThat(issue.getOptionalRuleDescriptionContextKey()).isEmpty(); + } + + @Test + public void update_whenUpdatingRuleDescriptionContextKeyToNotNull_returnsContextKey() { + prepareIssuesComponent(); + IssueDto issue = createIssueWithKey(ISSUE_KEY1).setRuleDescriptionContextKey(null); + underTest.insert(db.getSession(), issue); + + issue.setRuleDescriptionContextKey(TEST_CONTEXT_KEY); + underTest.update(db.getSession(), issue); + + issue = underTest.selectOrFailByKey(db.getSession(), ISSUE_KEY1); + assertThat(issue.getOptionalRuleDescriptionContextKey()).contains(TEST_CONTEXT_KEY); + } + + @Test + public void update_givenOneIssueWithoutRuleDescriptionContextKey_returnsContextKey() { + prepareIssuesComponent(); + IssueDto issue = createIssueWithKey(ISSUE_KEY1).setRuleDescriptionContextKey(TEST_CONTEXT_KEY); + underTest.insert(db.getSession(), issue); + + issue.setRuleDescriptionContextKey(null); + underTest.update(db.getSession(), issue); + + issue = underTest.selectOrFailByKey(db.getSession(), ISSUE_KEY1); + assertThat(issue.getOptionalRuleDescriptionContextKey()).isEmpty(); + + issue.setRuleDescriptionContextKey(TEST_CONTEXT_KEY); + underTest.update(db.getSession(), issue); + + issue = underTest.selectOrFailByKey(db.getSession(), ISSUE_KEY1); + assertThat(issue.getOptionalRuleDescriptionContextKey()).contains(TEST_CONTEXT_KEY); + } + + private static IssueDto createIssueWithKey(String issueKey) { + return newIssueDto(issueKey) + .setMessage("the message") + .setRuleUuid(RULE.getUuid()) + .setComponentUuid(FILE_UUID) + .setProjectUuid(PROJECT_UUID) + .setQuickFixAvailable(false); + } + private static IssueDto newIssueDto(String key) { IssueDto dto = new IssueDto(); dto.setComponent(new ComponentDto().setDbKey("struts:Action").setUuid("component-uuid")); @@ -687,6 +762,7 @@ public class IssueDaoTest { dto.setAssigneeUuid("karadoc"); dto.setChecksum("123456789"); dto.setMessage("the message"); + dto.setRuleDescriptionContextKey(TEST_CONTEXT_KEY); dto.setCreatedAt(1_440_000_000_000L); dto.setUpdatedAt(1_440_000_000_000L); dto.setIssueCreationTime(1_450_000_000_000L); diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java index 69cdd39962f..dde978b82c3 100644 --- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java +++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java @@ -33,6 +33,7 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Optional; import java.util.Set; import javax.annotation.CheckForNull; import javax.annotation.Nullable; @@ -51,40 +52,40 @@ import static org.sonar.api.utils.DateUtils.truncateToSeconds; public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.Issue { - private String key; - private RuleType type; - private String componentUuid; - private String componentKey; + private String key = null; + private RuleType type = null; + private String componentUuid = null; + private String componentKey = null; - private String moduleUuidPath; + private String moduleUuidPath = null; - private String projectUuid; - private String projectKey; + private String projectUuid = null; + private String projectKey = null; - private RuleKey ruleKey; - private String language; - private String severity; + private RuleKey ruleKey = null; + private String language = null; + private String severity = null; private boolean manualSeverity = false; - private String message; - private Integer line; - private Double gap; - private Duration effort; - private String status; - private String resolution; - private String assigneeUuid; - private String checksum; + private String message = null; + private Integer line = null; + private Double gap = null; + private Duration effort = null; + private String status = null; + private String resolution = null; + private String assigneeUuid = null; + private String checksum = null; private String authorLogin = null; private List comments = null; private Set tags = null; // temporarily an Object as long as DefaultIssue is used by sonar-batch private Object locations = null; - private boolean isFromExternalRuleEngine; + private boolean isFromExternalRuleEngine = false; // FUNCTIONAL DATES - private Date creationDate; - private Date updateDate; - private Date closeDate; + private Date creationDate = null; + private Date updateDate = null; + private Date closeDate = null; // Current changes private FieldDiffs currentChange = null; @@ -116,14 +117,16 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure. private boolean sendNotifications = false; // Date when issue was loaded from db (only when isNew=false) - private Long selectedAt; + private Long selectedAt = null; - private boolean quickFixAvailable; - private boolean isNewCodeReferenceIssue; + private boolean quickFixAvailable = false; + private boolean isNewCodeReferenceIssue = false; // true if the issue is no longer new in its branch private boolean isNoLongerNewCodeReferenceIssue = false; + private String ruleDescriptionContextKey = null; + @Override public String key() { return key; @@ -640,6 +643,15 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure. return this; } + public Optional getRuleDescriptionContextKey() { + return Optional.ofNullable(ruleDescriptionContextKey); + } + + public DefaultIssue setRuleDescriptionContextKey(@Nullable String ruleDescriptionContextKey) { + this.ruleDescriptionContextKey = ruleDescriptionContextKey; + return this; + } + @Override public Integer getLine() { return line; -- 2.39.5