aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBelen Pruvost <belen.pruvost@sonarsource.com>2021-06-29 15:18:15 +0200
committersonartech <sonartech@sonarsource.com>2021-06-30 20:03:13 +0000
commit2b1e236fa390e079bb4277b93b2dc9be25a77c5b (patch)
treec8d1d423b0ab5675941a410046ed6ca52e2d1cf4
parent13737457f2588e71737ddbd5a5b3cb65e3dabb4c (diff)
downloadsonarqube-2b1e236fa390e079bb4277b93b2dc9be25a77c5b.tar.gz
sonarqube-2b1e236fa390e079bb4277b93b2dc9be25a77c5b.zip
SONAR-14605 - Make rule name consistent
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java7
-rw-r--r--server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java2
-rw-r--r--server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml26
-rw-r--r--server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java14
-rw-r--r--server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java1
-rw-r--r--server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java22
-rw-r--r--server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java19
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java8
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java26
-rw-r--r--server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java36
10 files changed, 156 insertions, 5 deletions
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java
index 10a40db90cb..59fab5899b4 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java
@@ -60,6 +60,13 @@ public class RuleDao implements Dao {
return ofNullable(mapper(session).selectMetadataByKey(key));
}
+ public List<RuleMetadataDto> selectMetadataByKeys(DbSession session, Collection<RuleKey> keys) {
+ if (keys.isEmpty()) {
+ return emptyList();
+ }
+ return executeLargeInputs(keys, mapper(session)::selectMetadataByKeys);
+ }
+
public RuleDto selectOrFailByKey(DbSession session, RuleKey key) {
RuleDto rule = mapper(session).selectByKey(key);
if (rule == null) {
diff --git a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java
index d4d61573244..a49cf2e22a5 100644
--- a/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java
+++ b/server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java
@@ -49,6 +49,8 @@ public interface RuleMapper {
RuleMetadataDto selectMetadataByKey(@Param("ruleKey") RuleKey ruleKey);
+ List<RuleMetadataDto> selectMetadataByKeys(@Param("ruleKeys") List<RuleKey> keys);
+
List<RuleDto> selectByKeys(@Param("ruleKeys") List<RuleKey> keys);
List<RuleDefinitionDto> selectDefinitionByKeys(@Param("ruleKeys") List<RuleKey> keys);
diff --git a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
index fb4c67409a8..ca8ee02db2e 100644
--- a/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
+++ b/server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
@@ -205,6 +205,32 @@
and r.plugin_rule_key=#{ruleKey.rule,jdbcType=VARCHAR}
</select>
+ <select id="selectMetadataByKeys" parameterType="map" resultType="org.sonar.db.rule.RuleMetadataDto">
+ select
+ rm.rule_uuid as "ruleUuid",
+ rm.note_data as "noteData",
+ rm.note_user_uuid as "noteUserUuid",
+ rm.note_created_at as "noteCreatedAt",
+ rm.note_updated_at as "noteUpdatedAt",
+ rm.remediation_function as "remediationFunction",
+ rm.remediation_gap_mult as "remediationGapMultiplier",
+ rm.remediation_base_effort as "remediationBaseEffort",
+ rm.tags as "tagsField",
+ rm.ad_hoc_name as "adHocName",
+ rm.ad_hoc_description as "adHocDescription",
+ rm.ad_hoc_severity as "adHocSeverity",
+ rm.ad_hoc_type as "adHocType",
+ rm.created_at as "createdAt",
+ rm.updated_at as "updatedAt"
+ from
+ rules_metadata rm
+ inner join rules r on rm.rule_uuid = r.uuid
+ where
+ <foreach collection="ruleKeys" index="index" item="ruleKey" open="" separator=" or " close="">
+ (r.plugin_name=#{ruleKey.repository,jdbcType=VARCHAR} and r.plugin_rule_key=#{ruleKey.rule,jdbcType=VARCHAR})
+ </foreach>
+ </select>
+
<select id="selectByKeys" parameterType="map" resultType="Rule">
select
<include refid="selectJoinedTablesColumns"/>
diff --git a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
index 5180c858067..13db09b0f52 100644
--- a/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
+++ b/server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
@@ -106,6 +106,20 @@ public class RuleDaoTest {
}
@Test
+ public void selectMetadataByKeys() {
+ RuleDefinitionDto rule1 = db.rules().insert();
+ db.rules().insertOrUpdateMetadata(rule1);
+
+ assertThat(underTest.selectMetadataByKeys(db.getSession(), Collections.emptyList())).isEmpty();
+ assertThat(underTest.selectMetadataByKeys(db.getSession(), singletonList(RuleKey.of("NOT", "FOUND")))).isEmpty();
+
+ List<RuleMetadataDto> rulesMetadata = underTest.selectMetadataByKeys(db.getSession(), asList(rule1.getKey(),
+ RuleKey.of("java", "OTHER")));
+ assertThat(rulesMetadata).hasSize(1);
+ assertThat(rulesMetadata.get(0).getRuleUuid()).isEqualTo(rule1.getUuid());
+ }
+
+ @Test
public void selectByUuid() {
RuleDefinitionDto ruleDefinition = db.rules().insert();
RuleMetadataDto metadata = newRuleMetadata(ruleDefinition);
diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java
index 36d0663fdfa..295c252659b 100644
--- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java
+++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java
@@ -71,7 +71,6 @@ import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.core.util.stream.MoreCollectors;
-import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.server.es.BaseDoc;
import org.sonar.server.es.EsClient;
import org.sonar.server.es.EsUtils;
diff --git a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java
index c238c58a6b5..60694e9231a 100644
--- a/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java
+++ b/server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java
@@ -40,7 +40,6 @@ import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
import org.apache.commons.lang.BooleanUtils;
import org.sonar.api.resources.Qualifiers;
@@ -54,6 +53,7 @@ import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.SnapshotDto;
import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.rule.RuleMetadataDto;
import org.sonar.server.issue.SearchRequest;
import org.sonar.server.issue.index.IssueQuery.PeriodStart;
import org.sonar.server.user.UserSession;
@@ -111,8 +111,11 @@ public class IssueQueryFactory {
final ZoneId timeZone = parseTimeZone(request.getTimeZone()).orElse(clock.getZone());
Collection<RuleDefinitionDto> ruleDefinitionDtos = ruleKeysToRuleId(dbSession, request.getRules());
+ Collection<RuleMetadataDto> ruleMetadataDtos = ruleKeysToRuleMetadata(dbSession, request.getRules());
Collection<String> ruleUuids = ruleDefinitionDtos.stream().map(RuleDefinitionDto::getUuid).collect(Collectors.toSet());
+ ruleDefinitionDtos.stream().forEach(rule -> getRuleName(ruleMetadataDtos, rule));
+
if (request.getRules() != null && request.getRules().stream().collect(toSet()).size() != ruleDefinitionDtos.size()) {
ruleUuids.add("non-existing-uuid");
}
@@ -383,6 +386,13 @@ public class IssueQueryFactory {
return Collections.emptyList();
}
+ private Collection<RuleMetadataDto> ruleKeysToRuleMetadata(DbSession dbSession, @Nullable Collection<String> rules) {
+ if (rules != null) {
+ return dbClient.ruleDao().selectMetadataByKeys(dbSession, transform(rules, RuleKey::parse));
+ }
+ return Collections.emptyList();
+ }
+
private static String toProjectUuid(ComponentDto componentDto) {
String mainBranchProjectUuid = componentDto.getMainBranchProjectUuid();
return mainBranchProjectUuid == null ? componentDto.projectUuid() : mainBranchProjectUuid;
@@ -395,4 +405,14 @@ public class IssueQueryFactory {
|| (branch != null && !branch.equals(component.getBranch()))
|| (pullRequest != null && !pullRequest.equals(component.getPullRequest())));
}
+
+ private static void getRuleName(Collection<RuleMetadataDto> ruleMetadataDtos, RuleDefinitionDto rule) {
+ if (rule.isAdHoc()) {
+ String name = ruleMetadataDtos.stream()
+ .filter(m -> m.getRuleUuid().equals(rule.getUuid())).findFirst()
+ .map(RuleMetadataDto::getAdHocName)
+ .orElse(null);
+ rule.setName(name);
+ }
+ }
}
diff --git a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java
index d2057956dd8..3d5fba1a828 100644
--- a/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java
+++ b/server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueQueryFactoryTest.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
+import java.util.Optional;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
@@ -73,13 +74,16 @@ public class IssueQueryFactoryTest {
@Test
public void create_from_parameters() {
+ String ruleAdHocName = "New Name";
UserDto user = db.users().insertUser(u -> u.setLogin("joanna"));
ComponentDto project = db.components().insertPrivateProject();
ComponentDto module = db.components().insertComponent(newModuleDto(project));
ComponentDto file = db.components().insertComponent(newFileDto(project));
- RuleDefinitionDto rule1 = ruleDbTester.insert();
+ RuleDefinitionDto rule1 = ruleDbTester.insert(r -> r.setIsAdHoc(true));
RuleDefinitionDto rule2 = ruleDbTester.insert();
+ ruleDbTester.insertOrUpdateMetadata(rule1, m -> m.setAdHocName(ruleAdHocName));
+ ruleDbTester.insertOrUpdateMetadata(rule2, m -> m.setAdHocName(ruleAdHocName));
newRule(RuleKey.of("findbugs", "NullReference"));
SearchRequest request = new SearchRequest()
.setIssues(asList("anIssueKey"))
@@ -126,6 +130,19 @@ public class IssueQueryFactoryTest {
assertThat(query.createdBefore()).isEqualTo(parseDateTime("2013-04-17T09:08:24+0200"));
assertThat(query.sort()).isEqualTo(IssueQuery.SORT_BY_CREATION_DATE);
assertThat(query.asc()).isTrue();
+
+ Optional<RuleDefinitionDto> ruleWithMetadata = query.rules().stream()
+ .filter(r -> r.getUuid().equals(rule1.getUuid())).findFirst();
+ assertThat(ruleWithMetadata).isPresent();
+ assertThat(ruleWithMetadata.get().getName()).isEqualTo(ruleAdHocName);
+ assertThat(ruleWithMetadata.get().getName()).isNotEqualTo(rule1.getName());
+
+ Optional<RuleDefinitionDto> ruleWithMetadata2 = query.rules().stream()
+ .filter(r -> r.getUuid().equals(rule2.getUuid())).findFirst();
+ assertThat(ruleWithMetadata2).isPresent();
+ assertThat(ruleWithMetadata2.get().getName()).isNotEqualTo(ruleAdHocName);
+ assertThat(ruleWithMetadata2.get().getName()).isEqualTo(rule2.getName());
+
}
@Test
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java
index b200d469384..8ed2457a9f6 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java
@@ -176,7 +176,13 @@ public class SearchResponseFormat {
issueBuilder.setSubProject(subProject.getKey());
}
}
- issueBuilder.setRule(dto.getRuleKey().toString());
+
+ String ruleName = data.getRules().stream()
+ .filter(r -> r.isAdHoc() && r.getName() != null && r.getUuid().equals(dto.getRuleUuid()))
+ .findFirst()
+ .map(RuleDefinitionDto::getName)
+ .orElse(dto.getRuleKey().toString());
+ issueBuilder.setRule(ruleName);
if (dto.isExternal()) {
issueBuilder.setExternalRuleEngine(engineNameFrom(dto.getRuleKey()));
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java
index f29b1befbbf..cddd95bc4c3 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseLoader.java
@@ -31,6 +31,7 @@ import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import javax.annotation.Nullable;
+import org.sonar.api.rule.RuleKey;
import org.sonar.api.rules.RuleType;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.util.stream.MoreCollectors;
@@ -41,6 +42,7 @@ import org.sonar.db.issue.IssueChangeDto;
import org.sonar.db.issue.IssueDto;
import org.sonar.db.protobuf.DbIssues;
import org.sonar.db.rule.RuleDefinitionDto;
+import org.sonar.db.rule.RuleMetadataDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.es.Facets;
import org.sonar.server.issue.TransitionService;
@@ -167,7 +169,11 @@ public class SearchResponseLoader {
result.addRules(preloadedRules);
Set<String> ruleUuidsToLoad = collector.getRuleUuids();
ruleUuidsToLoad.removeAll(preloadedRules.stream().map(RuleDefinitionDto::getUuid).collect(toList(preloadedRules.size())));
- result.addRules(dbClient.ruleDao().selectDefinitionByUuids(dbSession, ruleUuidsToLoad));
+ List<RuleDefinitionDto> rules = dbClient.ruleDao().selectDefinitionByUuids(dbSession, ruleUuidsToLoad);
+
+ getRulesMetadata(dbSession, rules);
+
+ result.addRules(rules);
}
private void loadComments(Collector collector, DbSession dbSession, Set<SearchAdditionalField> fields, SearchResponseData result) {
@@ -341,4 +347,22 @@ public class SearchResponseLoader {
return map.get(issueKey);
}
}
+
+ private void getRulesMetadata(DbSession dbSession, List<RuleDefinitionDto> rules) {
+ List<RuleKey> adHocRuleKeys = rules.stream().filter(RuleDefinitionDto::isAdHoc)
+ .map(r -> RuleKey.of(r.getRepositoryKey(), r.getRuleKey()))
+ .collect(toList());
+
+ List<RuleMetadataDto> adHocRulesMetadata = dbClient.ruleDao().selectMetadataByKeys(dbSession, adHocRuleKeys);
+
+ rules.stream().forEach(r -> {
+ if (r.isAdHoc()) {
+ String adHocName = adHocRulesMetadata.stream()
+ .filter(m -> m.getRuleUuid().equals(r.getUuid())).findFirst().
+ map(RuleMetadataDto::getAdHocName)
+ .orElse(null);
+ r.setName(adHocName);
+ }
+ });
+ }
}
diff --git a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
index d4f10af4b72..7b7e33030b3 100644
--- a/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
+++ b/server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchActionTest.java
@@ -56,6 +56,7 @@ import org.sonar.db.protobuf.DbCommons;
import org.sonar.db.protobuf.DbIssues;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.rule.RuleDto;
+import org.sonar.db.rule.RuleMetadataDto;
import org.sonar.db.rule.RuleTesting;
import org.sonar.db.user.UserDto;
import org.sonar.server.es.EsTester;
@@ -203,6 +204,41 @@ public class SearchActionTest {
}
@Test
+ public void issue_on_external_adhoc_rule_without_metadata() {
+ ComponentDto project = db.components().insertPublicProject();
+ indexPermissions();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ RuleDefinitionDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO, r -> r.setIsExternal(true).setLanguage("xoo").setIsAdHoc(true));
+ IssueDto issue = db.issues().insertIssue(rule, project, file);
+ indexIssues();
+
+ SearchWsResponse response = ws.newRequest()
+ .executeProtobuf(SearchWsResponse.class);
+
+ assertThat(response.getIssuesList())
+ .extracting(Issue::getKey, Issue::getRule, Issue::getExternalRuleEngine)
+ .containsExactlyInAnyOrder(tuple(issue.getKey(), rule.getKey().toString(), "xoo"));
+ }
+
+ @Test
+ public void issue_on_external_adhoc_rule_with_metadata() {
+ ComponentDto project = db.components().insertPublicProject();
+ indexPermissions();
+ ComponentDto file = db.components().insertComponent(newFileDto(project));
+ RuleDefinitionDto rule = db.rules().insertIssueRule(RuleTesting.EXTERNAL_XOO, r -> r.setIsExternal(true).setLanguage("xoo").setIsAdHoc(true));
+ RuleMetadataDto ruleMetadata = db.rules().insertOrUpdateMetadata(rule, m -> m.setAdHocName("different_rule_name"));
+ IssueDto issue = db.issues().insertIssue(rule, project, file);
+ indexIssues();
+
+ SearchWsResponse response = ws.newRequest()
+ .executeProtobuf(SearchWsResponse.class);
+
+ assertThat(response.getIssuesList())
+ .extracting(Issue::getKey, Issue::getRule, Issue::getExternalRuleEngine)
+ .containsExactlyInAnyOrder(tuple(issue.getKey(), ruleMetadata.getAdHocName(), "xoo"));
+ }
+
+ @Test
public void issue_with_cross_file_locations() {
ComponentDto project = db.components().insertPublicProject();
indexPermissions();