]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-14192 Add optional return field 'deprecatedKeys' to /api/rules/search
authorMichal Duda <michal.duda@sonarsource.com>
Thu, 11 Mar 2021 19:52:24 +0000 (20:52 +0100)
committersonartech <sonartech@sonarsource.com>
Wed, 17 Mar 2021 20:08:34 +0000 (20:08 +0000)
16 files changed:
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleDao.java
server/sonar-db-dao/src/main/java/org/sonar/db/rule/RuleMapper.java
server/sonar-db-dao/src/main/resources/org/sonar/db/rule/RuleMapper.xml
server/sonar-db-dao/src/test/java/org/sonar/db/rule/RuleDaoTest.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RuleMapper.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/RulesWsParameters.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/SearchAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/ShowAction.java
server/sonar-webserver-webapi/src/main/java/org/sonar/server/rule/ws/UpdateAction.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/SearchActionTest.java
server/sonar-webserver-webapi/src/test/java/org/sonar/server/rule/ws/ShowActionTest.java
sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/LoadedActiveRule.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/rule/DefaultActiveRulesLoader.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/ActiveRulesProviderTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/rule/DefaultActiveRulesLoaderTest.java
sonar-ws/src/main/protobuf/ws-rules.proto

index 4225bb87f4dc954224d4f437f08ce43679b591bc..10a40db90cb86d2c77eaa3ef30b8cffaf699d276 100644 (file)
@@ -224,6 +224,10 @@ public class RuleDao implements Dao {
     return mapper(session).selectAllDeprecatedRuleKeys();
   }
 
+  public Set<DeprecatedRuleKeyDto> selectDeprecatedRuleKeysByRuleUuids(DbSession session, Collection<String> ruleUuids) {
+    return mapper(session).selectDeprecatedRuleKeysByRuleUuids(ruleUuids);
+  }
+
   public void deleteDeprecatedRuleKeys(DbSession dbSession, Collection<String> uuids) {
     if (uuids.isEmpty()) {
       return;
index 31a0ef9be7bb8ec5b5712e1827dace7acd3d2f26..d4d61573244c3160621f89ff108cb7d715366687 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.db.rule;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Set;
 import org.apache.ibatis.annotations.Param;
@@ -86,6 +87,8 @@ public interface RuleMapper {
 
   Set<DeprecatedRuleKeyDto> selectAllDeprecatedRuleKeys();
 
+  Set<DeprecatedRuleKeyDto> selectDeprecatedRuleKeysByRuleUuids(@Param("ruleUuids") Collection<String> ruleUuids);
+
   void deleteDeprecatedRuleKeys(@Param("uuids") List<String> uuids);
 
   void insertDeprecatedRuleKey(DeprecatedRuleKeyDto deprecatedRuleKeyDto);
index e8967deffaa176f731cdbe116fa232c65fb19c13..fb4c67409a8114e11f291f248abea74a1cf77a4b 100644 (file)
     LEFT OUTER JOIN rules r on r.uuid = drk.rule_uuid
   </select>
 
+  <select id="selectDeprecatedRuleKeysByRuleUuids" resultType="org.sonar.db.rule.DeprecatedRuleKeyDto">
+    SELECT
+      drk.uuid,
+      drk.rule_uuid as "ruleUuid",
+      drk.old_repository_key as "oldRepositoryKey",
+      drk.old_rule_key as "oldRuleKey",
+      r.plugin_rule_key as "newRuleKey",
+      r.plugin_name as "newRepositoryKey",
+      drk.created_at as "createdAt"
+    FROM
+      deprecated_rule_keys drk
+    LEFT OUTER JOIN rules r on r.uuid = drk.rule_uuid
+    WHERE
+      <foreach item="uuid" index="index" collection="ruleUuids" open="(" separator=" or " close=")">
+        drk.rule_uuid=#{uuid,jdbcType=VARCHAR}
+      </foreach>
+  </select>
+
   <delete id="deleteDeprecatedRuleKeys">
     DELETE FROM
       deprecated_rule_keys
index 3a2d3fe768ffec797e027c2e1ebbf2442e4a8855..5180c858067f2b0b98069cb786c4a75eaacf6021 100644 (file)
@@ -19,6 +19,7 @@
  */
 package org.sonar.db.rule;
 
+import com.google.common.collect.ImmutableSet;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -62,7 +63,7 @@ public class RuleDaoTest {
   @Rule
   public DbTester db = DbTester.create(System2.INSTANCE);
 
-  private RuleDao underTest = db.getDbClient().ruleDao();
+  private final RuleDao underTest = db.getDbClient().ruleDao();
 
   @Test
   public void selectByKey() {
@@ -388,8 +389,8 @@ public class RuleDaoTest {
         .setLanguage("java"));
     db.rules().insertOrUpdateMetadata(rule1);
 
-    assertThat(underTest.selectByTypeAndLanguages(db.getSession(),singletonList(RuleType.VULNERABILITY.getDbConstant()), singletonList("java")))
-      .extracting( RuleDto::getUuid, RuleDto::getLanguage, RuleDto::getType)
+    assertThat(underTest.selectByTypeAndLanguages(db.getSession(), singletonList(RuleType.VULNERABILITY.getDbConstant()), singletonList("java")))
+      .extracting(RuleDto::getUuid, RuleDto::getLanguage, RuleDto::getType)
       .isEmpty();
   }
 
@@ -903,6 +904,27 @@ public class RuleDaoTest {
     assertThat(deprecatedRuleKeyDtos).hasSize(2);
   }
 
+  @Test
+  public void selectDeprecatedRuleKeysByRuleUuids() {
+    RuleDefinitionDto r1 = db.rules().insert();
+    RuleDefinitionDto r2 = db.rules().insert();
+    RuleDefinitionDto r3 = db.rules().insert();
+    RuleDefinitionDto r4 = db.rules().insert();
+
+    DeprecatedRuleKeyDto drk1 = db.rules().insertDeprecatedKey(r -> r.setRuleUuid(r1.getUuid()));
+    DeprecatedRuleKeyDto drk2 = db.rules().insertDeprecatedKey(r -> r.setRuleUuid(r1.getUuid()));
+    DeprecatedRuleKeyDto drk3 = db.rules().insertDeprecatedKey(r -> r.setRuleUuid(r2.getUuid()));
+    db.rules().insertDeprecatedKey(r -> r.setRuleUuid(r4.getUuid()));
+
+    db.getSession().commit();
+
+    Set<DeprecatedRuleKeyDto> deprecatedRuleKeyDtos = underTest.selectDeprecatedRuleKeysByRuleUuids(
+      db.getSession(), ImmutableSet.of(r1.getUuid(), r2.getUuid(), r3.getUuid()));
+    assertThat(deprecatedRuleKeyDtos)
+      .extracting(DeprecatedRuleKeyDto::getUuid)
+      .containsExactlyInAnyOrder(drk1.getUuid(), drk2.getUuid(), drk3.getUuid());
+  }
+
   @Test
   public void selectAllDeprecatedRuleKeys_return_values_even_if_there_is_no_rule() {
     db.rules().insertDeprecatedKey();
index c72f2de15f36f3863ed59111978dd34819f71aec..8209c953c78e22d8002aea85e2aab1b3a6687d0d 100644 (file)
 package org.sonar.server.rule.ws;
 
 import com.google.common.base.Function;
+import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 import org.sonar.api.resources.Language;
 import org.sonar.api.resources.Languages;
+import org.sonar.api.rule.RuleKey;
 import org.sonar.api.server.debt.DebtRemediationFunction;
 import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction;
+import org.sonar.db.rule.DeprecatedRuleKeyDto;
 import org.sonar.db.rule.RuleDefinitionDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.db.rule.RuleDto.Scope;
@@ -44,7 +48,6 @@ import org.sonarqube.ws.Common;
 import org.sonarqube.ws.Common.RuleScope;
 import org.sonarqube.ws.Rules;
 
-import static java.lang.String.format;
 import static org.sonar.api.utils.DateUtils.formatDateTime;
 import static org.sonar.core.util.stream.MoreCollectors.toList;
 import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_CREATED_AT;
@@ -52,6 +55,7 @@ import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEBT_OVERLOADED;
 import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEBT_REM_FUNCTION;
 import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEFAULT_DEBT_REM_FUNCTION;
 import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEFAULT_REM_FUNCTION;
+import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEPRECATED_KEYS;
 import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_EFFORT_TO_FIX_DESCRIPTION;
 import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_GAP_DESCRIPTION;
 import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_HTML_DESCRIPTION;
@@ -89,19 +93,21 @@ public class RuleMapper {
 
   public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn) {
     Rules.Rule.Builder ruleResponse = Rules.Rule.newBuilder();
-    applyRuleDefinition(ruleResponse, ruleDefinitionDto, result, fieldsToReturn);
+    applyRuleDefinition(ruleResponse, ruleDefinitionDto, result, fieldsToReturn, Collections.emptyMap());
     return ruleResponse.build();
   }
 
-  public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinition, SearchResult result, Set<String> fieldsToReturn, RuleMetadataDto metadata, Map<String, UserDto> usersByUuid) {
+  public Rules.Rule toWsRule(RuleDefinitionDto ruleDefinition, SearchResult result, Set<String> fieldsToReturn, RuleMetadataDto metadata,
+    Map<String, UserDto> usersByUuid, Map<String, List<DeprecatedRuleKeyDto>> deprecatedRuleKeysByRuleUuid) {
     Rules.Rule.Builder ruleResponse = Rules.Rule.newBuilder();
-    applyRuleDefinition(ruleResponse, ruleDefinition, result, fieldsToReturn);
+    applyRuleDefinition(ruleResponse, ruleDefinition, result, fieldsToReturn, deprecatedRuleKeysByRuleUuid);
     applyRuleMetadata(ruleResponse, ruleDefinition, metadata, usersByUuid, fieldsToReturn);
     setDebtRemediationFunctionFields(ruleResponse, ruleDefinition, metadata, fieldsToReturn);
     return ruleResponse.build();
   }
 
-  private Rules.Rule.Builder applyRuleDefinition(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDefinitionDto, SearchResult result, Set<String> fieldsToReturn) {
+  private Rules.Rule.Builder applyRuleDefinition(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDefinitionDto, SearchResult result,
+    Set<String> fieldsToReturn, Map<String, List<DeprecatedRuleKeyDto>> deprecatedRuleKeysByRuleUuid) {
 
     // Mandatory fields
     ruleResponse.setKey(ruleDefinitionDto.getKey().toString());
@@ -125,6 +131,7 @@ public class RuleMapper {
     setDefaultDebtRemediationFunctionFields(ruleResponse, ruleDefinitionDto, fieldsToReturn);
     setEffortToFixDescription(ruleResponse, ruleDefinitionDto, fieldsToReturn);
     setScope(ruleResponse, ruleDefinitionDto, fieldsToReturn);
+    setDeprecatedKeys(ruleResponse, ruleDefinitionDto, fieldsToReturn, deprecatedRuleKeysByRuleUuid);
     return ruleResponse;
   }
 
@@ -181,6 +188,23 @@ public class RuleMapper {
     }
   }
 
+  private static void setDeprecatedKeys(Rules.Rule.Builder ruleResponse, RuleDefinitionDto ruleDto, Set<String> fieldsToReturn,
+    Map<String, List<DeprecatedRuleKeyDto>> deprecatedRuleKeysByRuleUuid) {
+    if (shouldReturnField(fieldsToReturn, FIELD_DEPRECATED_KEYS)) {
+      List<DeprecatedRuleKeyDto> deprecatedRuleKeyDtos = deprecatedRuleKeysByRuleUuid.get(ruleDto.getUuid());
+      if (deprecatedRuleKeyDtos == null) {
+        return;
+      }
+
+      List<String> deprecatedKeys = deprecatedRuleKeyDtos.stream()
+        .map(r -> RuleKey.of(r.getOldRepositoryKey(), r.getOldRuleKey()).toString())
+        .collect(Collectors.toList());
+      if (!deprecatedKeys.isEmpty()) {
+        ruleResponse.setDeprecatedKeys(Rules.DeprecatedKeys.newBuilder().addAllDeprecatedKey(deprecatedKeys).build());
+      }
+    }
+  }
+
   private static RuleScope toWsRuleScope(Scope scope) {
     switch (scope) {
       case ALL:
@@ -375,7 +399,7 @@ public class RuleMapper {
     }
   }
 
-  private static boolean shouldReturnField(Set<String> fieldsToReturn, String fieldName) {
+  public static boolean shouldReturnField(Set<String> fieldsToReturn, String fieldName) {
     return fieldsToReturn.isEmpty() || fieldsToReturn.contains(fieldName);
   }
 
index abcedd10cd2bc4b0263e364ba4c2f60bc6d69b2b..b301e0d6fafcaa4512194ae5f07ee3e80b39f515 100644 (file)
@@ -100,12 +100,14 @@ public class RulesWsParameters {
   public static final String FIELD_PARAMS = "params";
   public static final String FIELD_ACTIVES = "actives";
 
+  public static final String FIELD_DEPRECATED_KEYS = "deprecatedKeys";
+
   public static final Set<String> OPTIONAL_FIELDS = ImmutableSet.of(FIELD_REPO, FIELD_NAME, FIELD_CREATED_AT, FIELD_UPDATED_AT, FIELD_SEVERITY, FIELD_STATUS, FIELD_INTERNAL_KEY,
     FIELD_IS_EXTERNAL, FIELD_IS_TEMPLATE, FIELD_TEMPLATE_KEY, FIELD_TAGS, FIELD_SYSTEM_TAGS, FIELD_LANGUAGE, FIELD_LANGUAGE_NAME, FIELD_HTML_DESCRIPTION,
     FIELD_MARKDOWN_DESCRIPTION, FIELD_NOTE_LOGIN, FIELD_MARKDOWN_NOTE, FIELD_HTML_NOTE,
     FIELD_DEFAULT_DEBT_REM_FUNCTION, FIELD_EFFORT_TO_FIX_DESCRIPTION, FIELD_DEBT_OVERLOADED, FIELD_DEBT_REM_FUNCTION,
     FIELD_DEFAULT_REM_FUNCTION, FIELD_GAP_DESCRIPTION, FIELD_REM_FUNCTION_OVERLOADED, FIELD_REM_FUNCTION,
-    FIELD_PARAMS, FIELD_ACTIVES, FIELD_SCOPE);
+    FIELD_PARAMS, FIELD_ACTIVES, FIELD_SCOPE, FIELD_DEPRECATED_KEYS);
 
   private RulesWsParameters() {
     // prevent instantiation
index 22e2025522b9547be4fd94300c5adce57ffd04fd..63f67a97384b683830acb736c5db8c7c502caa26 100644 (file)
@@ -27,6 +27,7 @@ import com.google.common.collect.Maps;
 import com.google.common.collect.Ordering;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -46,6 +47,7 @@ import org.sonar.api.server.ws.WebService;
 import org.sonar.core.util.stream.MoreCollectors;
 import org.sonar.db.DbClient;
 import org.sonar.db.DbSession;
+import org.sonar.db.rule.DeprecatedRuleKeyDto;
 import org.sonar.db.rule.RuleDefinitionDto;
 import org.sonar.db.rule.RuleDto;
 import org.sonar.db.rule.RuleParamDto;
@@ -78,6 +80,7 @@ import static org.sonar.server.rule.index.RuleIndex.FACET_SONARSOURCE_SECURITY;
 import static org.sonar.server.rule.index.RuleIndex.FACET_STATUSES;
 import static org.sonar.server.rule.index.RuleIndex.FACET_TAGS;
 import static org.sonar.server.rule.index.RuleIndex.FACET_TYPES;
+import static org.sonar.server.rule.ws.RulesWsParameters.FIELD_DEPRECATED_KEYS;
 import static org.sonar.server.rule.ws.RulesWsParameters.OPTIONAL_FIELDS;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_ACTIVE_SEVERITIES;
 import static org.sonar.server.rule.ws.RulesWsParameters.PARAM_CWE;
@@ -205,7 +208,25 @@ public class SearchAction implements RulesWsAction {
 
   private void writeRules(DbSession dbSession, SearchResponse.Builder response, SearchResult result, SearchOptions context) {
     Map<String, UserDto> usersByUuid = ruleWsSupport.getUsersByUuid(dbSession, result.rules);
-    result.rules.forEach(rule -> response.addRules(mapper.toWsRule(rule.getDefinition(), result, context.getFields(), rule.getMetadata(), usersByUuid)));
+    Map<String, List<DeprecatedRuleKeyDto>> deprecatedRuleKeysByRuleUuid = getDeprecatedRuleKeysByRuleUuid(dbSession, result.rules, context);
+    result.rules.forEach(rule -> response.addRules(mapper.toWsRule(rule.getDefinition(), result, context.getFields(), rule.getMetadata(), usersByUuid,
+      deprecatedRuleKeysByRuleUuid)));
+  }
+
+  private Map<String, List<DeprecatedRuleKeyDto>> getDeprecatedRuleKeysByRuleUuid(DbSession dbSession, List<RuleDto> rules, SearchOptions context) {
+    if (!RuleMapper.shouldReturnField(context.getFields(), FIELD_DEPRECATED_KEYS)) {
+      return Collections.emptyMap();
+    }
+
+    Set<String> ruleUuidsSet = rules.stream()
+      .map(RuleDto::getUuid)
+      .collect(Collectors.toSet());
+    if (ruleUuidsSet.isEmpty()) {
+      return Collections.emptyMap();
+    } else {
+      return dbClient.ruleDao().selectDeprecatedRuleKeysByRuleUuids(dbSession, ruleUuidsSet).stream()
+        .collect(Collectors.groupingBy(DeprecatedRuleKeyDto::getRuleUuid));
+    }
   }
 
   private static SearchOptions buildSearchOptions(SearchRequest request) {
index c4e89e6df481d9ff2a78f2178a452ac47b4ced8c..d5fa9c9cf543786a28914ddf30cf6c7f74f5084b 100644 (file)
@@ -35,6 +35,7 @@ import org.sonar.server.exceptions.NotFoundException;
 import org.sonarqube.ws.Rules.ShowResponse;
 
 import static java.lang.String.format;
+import static java.util.Collections.emptyMap;
 import static java.util.Collections.singletonList;
 import static java.util.Optional.ofNullable;
 import static org.sonar.server.ws.WsUtils.writeProtobuf;
@@ -117,7 +118,7 @@ public class ShowAction implements RulesWsAction {
     ShowResponse.Builder responseBuilder = ShowResponse.newBuilder();
     RuleDto rule = searchResult.getRules().get(0);
     responseBuilder.setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata(),
-      ruleWsSupport.getUsersByUuid(dbSession, searchResult.getRules())));
+      ruleWsSupport.getUsersByUuid(dbSession, searchResult.getRules()), emptyMap()));
     if (request.mandatoryParamAsBoolean(PARAM_ACTIVES)) {
       activeRuleCompleter.completeShow(dbSession, rule.getDefinition()).forEach(responseBuilder::addActives);
     }
index 65e86bab8bd91dc5a8a04bdeae12cf0b4df0d790..4439524e04c6e728a667d5eb444b4069b55096d6 100644 (file)
@@ -47,6 +47,7 @@ import org.sonarqube.ws.Rules.UpdateResponse;
 
 import static com.google.common.collect.Sets.newHashSet;
 import static java.lang.String.format;
+import static java.util.Collections.emptyMap;
 import static java.util.Collections.singletonList;
 import static java.util.Optional.ofNullable;
 import static org.sonar.server.rule.ws.CreateAction.KEY_MAXIMUM_LENGTH;
@@ -249,7 +250,8 @@ public class UpdateAction implements RulesWsAction {
       .setRuleParameters(ruleParameters)
       .setTotal(1L);
     responseBuilder
-      .setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata(), ruleWsSupport.getUsersByUuid(dbSession, singletonList(rule))));
+      .setRule(mapper.toWsRule(rule.getDefinition(), searchResult, Collections.emptySet(), rule.getMetadata(),
+        ruleWsSupport.getUsersByUuid(dbSession, singletonList(rule)), emptyMap()));
 
     return responseBuilder.build();
   }
index a6b34dc482bc52a5164a2fb3bf0a865df179b00c..162ddbc1456c3feb18afb366d71331671c0df1a4 100644 (file)
@@ -297,6 +297,39 @@ public class SearchActionTest {
     assertThat(result.hasRepo()).isFalse();
   }
 
+  @Test
+  public void return_deprecatedKeys_in_response_on_demand() {
+    RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("java"));
+    db.rules().insertDeprecatedKey(r -> r.setRuleUuid(rule1.getUuid()).setOldRuleKey("oldrulekey").setOldRepositoryKey("oldrepositorykey"));
+    db.rules().insertDeprecatedKey(r -> r.setRuleUuid(rule1.getUuid()).setOldRuleKey("oldrulekey2").setOldRepositoryKey("oldrepositorykey2"));
+    RuleDefinitionDto rule2 = db.rules().insert(r -> r.setLanguage("javascript"));
+
+    indexRules();
+
+    Rules.SearchResponse response = ws.newRequest()
+      .setParam(WebService.Param.FIELDS, "deprecatedKeys")
+      .executeProtobuf(Rules.SearchResponse.class);
+
+    System.err.println(response.getRulesList());
+
+    assertThat(response.getRulesList()).satisfies(l -> {
+      assertThat(l).hasSize(2);
+
+      assertThat(l).anySatisfy(e -> {
+        assertThat(e.getKey()).isEqualTo(rule1.getKey().toString());
+        assertThat(e.getType().getNumber()).isEqualTo(rule1.getType());
+        assertThat(e.getDeprecatedKeys()).isNotNull();
+        assertThat(e.getDeprecatedKeys().getDeprecatedKeyList()).contains("oldrepositorykey:oldrulekey", "oldrepositorykey2:oldrulekey2");
+      });
+      assertThat(l).anySatisfy(e -> {
+        assertThat(e.getKey()).isEqualTo(rule2.getKey().toString());
+        assertThat(e.getType().getNumber()).isEqualTo(rule2.getType());
+        assertThat(e.getDeprecatedKeys()).isNotNull();
+        assertThat(e.getDeprecatedKeys().getDeprecatedKeyList()).isEmpty();
+      });
+    });
+  }
+
   @Test
   public void should_filter_on_specific_tags() {
     RuleDefinitionDto rule1 = db.rules().insert(r -> r.setLanguage("java"));
index 07c800955e0dd2429d6616f93ea96f76a0e38e57..05873d8f742f3be627dda4863578486fccb13c3a 100644 (file)
@@ -22,7 +22,6 @@ package org.sonar.server.rule.ws;
 import java.util.List;
 import org.junit.Before;
 import org.junit.Test;
-import org.junit.rules.ExpectedException;
 import org.sonar.api.resources.Languages;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.rule.Severity;
@@ -69,13 +68,10 @@ public class ShowActionTest {
   public UserSessionRule userSession = UserSessionRule.standalone();
   @org.junit.Rule
   public DbTester db = DbTester.create();
-  @org.junit.Rule
-  public ExpectedException thrown = ExpectedException.none();
-
-  private MacroInterpreter macroInterpreter = mock(MacroInterpreter.class);
-  private Languages languages = new Languages(newLanguage("xoo", "Xoo"));
 
-  private WsActionTester ws = new WsActionTester(
+  private final MacroInterpreter macroInterpreter = mock(MacroInterpreter.class);
+  private final Languages languages = new Languages(newLanguage("xoo", "Xoo"));
+  private final WsActionTester ws = new WsActionTester(
     new ShowAction(db.getDbClient(), new RuleMapper(languages, macroInterpreter),
       new ActiveRuleCompleter(db.getDbClient(), languages),
       new RuleWsSupport(db.getDbClient(), userSession)));
@@ -110,7 +106,7 @@ public class ShowActionTest {
     assertThat(resultRule.getRepo()).isEqualTo(rule.getRepositoryKey());
     assertThat(resultRule.getName()).isEqualTo(rule.getName());
     assertThat(resultRule.getSeverity()).isEqualTo(rule.getSeverityString());
-    assertThat(resultRule.getStatus().toString()).isEqualTo(rule.getStatus().toString());
+    assertThat(resultRule.getStatus()).hasToString(rule.getStatus().toString());
     assertThat(resultRule.getInternalKey()).isEqualTo(rule.getConfigKey());
     assertThat(resultRule.getIsTemplate()).isEqualTo(rule.isTemplate());
     assertThat(resultRule.getLang()).isEqualTo(rule.getLanguage());
@@ -166,6 +162,7 @@ public class ShowActionTest {
     assertThat(resultRule.getRemFnGapMultiplier()).isEqualTo("5d");
     assertThat(resultRule.getRemFnBaseEffort()).isEqualTo("10h");
     assertThat(resultRule.getRemFnOverloaded()).isFalse();
+    assertThat(resultRule.hasDeprecatedKeys()).isFalse();
   }
 
   @Test
@@ -193,6 +190,7 @@ public class ShowActionTest {
     assertThat(resultRule.getRemFnGapMultiplier()).isEqualTo("5d");
     assertThat(resultRule.getRemFnBaseEffort()).isEqualTo("10h");
     assertThat(resultRule.getRemFnOverloaded()).isTrue();
+    assertThat(resultRule.hasDeprecatedKeys()).isFalse();
   }
 
   @Test
@@ -220,6 +218,7 @@ public class ShowActionTest {
     assertThat(resultRule.hasRemFnGapMultiplier()).isFalse();
     assertThat(resultRule.getRemFnBaseEffort()).isEqualTo("15h");
     assertThat(resultRule.getRemFnOverloaded()).isTrue();
+    assertThat(resultRule.hasDeprecatedKeys()).isFalse();
   }
 
   @Test
@@ -246,6 +245,7 @@ public class ShowActionTest {
     assertThat(resultRule.hasRemFnGapMultiplier()).isFalse();
     assertThat(resultRule.hasRemFnBaseEffort()).isFalse();
     assertThat(resultRule.getRemFnOverloaded()).isFalse();
+    assertThat(resultRule.hasDeprecatedKeys()).isFalse();
   }
 
   @Test
@@ -274,6 +274,7 @@ public class ShowActionTest {
     assertThat(resultRule.hasDebtRemFnCoeff()).isFalse();
     assertThat(resultRule.getDebtRemFnOffset()).isEqualTo("15h");
     assertThat(resultRule.getDebtOverloaded()).isTrue();
+    assertThat(resultRule.hasDeprecatedKeys()).isFalse();
   }
 
   @Test
@@ -388,7 +389,7 @@ public class ShowActionTest {
   public void show_rule_with_activation() {
     RuleDefinitionDto rule = db.rules().insert();
     RuleParamDto ruleParam = db.rules().insertRuleParam(rule, p -> p.setType("STRING").setDescription("Reg *exp*").setDefaultValue(".*"));
-    RuleMetadataDto ruleMetadata = db.rules().insertOrUpdateMetadata(rule, m -> m.setNoteData(null).setNoteUserUuid(null));
+    db.rules().insertOrUpdateMetadata(rule, m -> m.setNoteData(null).setNoteUserUuid(null));
     QProfileDto qProfile = db.qualityProfiles().insert();
     ActiveRuleDto activeRule = db.qualityProfiles().activateRule(qProfile, rule);
     db.getDbClient().activeRuleDao().insertParam(db.getSession(), activeRule, new ActiveRuleParamDto()
@@ -414,9 +415,9 @@ public class ShowActionTest {
   @Test
   public void show_rule_without_activation() {
     RuleDefinitionDto rule = db.rules().insert();
-    RuleMetadataDto ruleMetadata = db.rules().insertOrUpdateMetadata(rule, m -> m.setNoteData(null).setNoteUserUuid(null));
+    db.rules().insertOrUpdateMetadata(rule, m -> m.setNoteData(null).setNoteUserUuid(null));
     QProfileDto qProfile = db.qualityProfiles().insert();
-    ActiveRuleDto activeRule = db.qualityProfiles().activateRule(qProfile, rule);
+    db.qualityProfiles().activateRule(qProfile, rule);
 
     ShowResponse result = ws.newRequest()
       .setParam(PARAM_KEY, rule.getKey().toString())
index 6545401f0836c80ddb6d65bdf2effeb198bbcb16..ba8b8bb7edaf67b5c6c7a74885126de2115adfdf 100644 (file)
@@ -20,6 +20,7 @@
 package org.sonar.api.batch.rule;
 
 import java.util.Map;
+import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 import org.sonar.api.rule.RuleKey;
@@ -34,6 +35,11 @@ public class LoadedActiveRule {
   private long updatedAt;
   private String templateRuleKey;
   private String internalKey;
+  private Set<RuleKey> deprecatedKeys;
+
+  public LoadedActiveRule() {
+    // nothing to do here
+  }
 
   public RuleKey getRuleKey() {
     return ruleKey;
@@ -108,4 +114,11 @@ public class LoadedActiveRule {
     this.internalKey = internalKey;
   }
 
+  public Set<RuleKey> getDeprecatedKeys() {
+    return deprecatedKeys;
+  }
+
+  public void setDeprecatedKeys(Set<RuleKey> deprecatedKeys) {
+    this.deprecatedKeys = deprecatedKeys;
+  }
 }
index 192ddf208adec425c97ecdeae1ade3e06bb98f59..6404d8184dc1b8cb4ce1d31652979b686d349237 100644 (file)
@@ -25,12 +25,13 @@ import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
 import org.apache.commons.io.IOUtils;
-import org.sonar.scanner.bootstrap.ScannerWsClient;
-import org.sonar.api.impl.utils.ScannerUtils;
 import org.sonar.api.batch.rule.LoadedActiveRule;
+import org.sonar.api.impl.utils.ScannerUtils;
 import org.sonar.api.rule.RuleKey;
 import org.sonar.api.utils.DateUtils;
+import org.sonar.scanner.bootstrap.ScannerWsClient;
 import org.sonarqube.ws.Rules;
 import org.sonarqube.ws.Rules.Active;
 import org.sonarqube.ws.Rules.Active.Param;
@@ -40,7 +41,8 @@ import org.sonarqube.ws.Rules.SearchResponse;
 import org.sonarqube.ws.client.GetRequest;
 
 public class DefaultActiveRulesLoader implements ActiveRulesLoader {
-  private static final String RULES_SEARCH_URL = "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt,updatedAt&activation=true";
+  private static final String RULES_SEARCH_URL = "/api/rules/search.protobuf?" +
+    "f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt,updatedAt,deprecatedKeys&activation=true";
 
   private final ScannerWsClient wsClient;
 
@@ -125,6 +127,10 @@ public class DefaultActiveRulesLoader implements ActiveRulesLoader {
         params.put(param.getKey(), param.getValue());
       }
       loadedRule.setParams(params);
+      loadedRule.setDeprecatedKeys(r.getDeprecatedKeys().getDeprecatedKeyList()
+        .stream()
+        .map(RuleKey::parse)
+        .collect(Collectors.toSet()));
       loadedRules.add(loadedRule);
     }
 
index 77536daacaacbc156970bb5b470e8bd57f2eae5c..0f1aef9124d490641203a8d1ca70e03fe41c175c 100644 (file)
@@ -21,6 +21,7 @@ package org.sonar.scanner.rule;
 
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import java.util.Date;
 import java.util.LinkedList;
 import java.util.List;
@@ -116,6 +117,7 @@ public class ActiveRulesProviderTest {
     LoadedActiveRule r = new LoadedActiveRule();
     r.setName(name);
     r.setRuleKey(RuleKey.of(name, name));
+    r.setDeprecatedKeys(ImmutableSet.of(RuleKey.of(name + "old", name + "old")));
     return r;
   }
 }
index cdc3211440216ce3cdee168b3c3234f313e0fa64..e823ddf3bfaf6db514a3c64e6c524778a03f16ba 100644 (file)
@@ -91,7 +91,7 @@ public class DefaultActiveRulesLoaderTest {
   }
 
   private String urlOfPage(int page) {
-    return "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt,updatedAt&activation=true"
+    return "/api/rules/search.protobuf?f=repo,name,severity,lang,internalKey,templateKey,params,actives,createdAt,updatedAt,deprecatedKeys&activation=true"
       + ("") + "&qprofile=c%2B-test_c%2B-values-17445&ps=500&p=" + page + "";
   }
 
index 4ef4ccb8886205ac317c122b89f4889cd4b8049f..719e7b7e3266538e24d7995fe393b5ce3bed02c3 100644 (file)
@@ -82,7 +82,7 @@ message Rule {
   optional bool isTemplate = 13;
   optional string templateKey = 14;
   optional Tags tags = 15;
-  optional SysTags sysTags = 16; 
+  optional SysTags sysTags = 16;
   optional string lang = 19;
   optional string langName = 20;
   optional Params params = 21;
@@ -110,7 +110,7 @@ message Rule {
   optional string debtRemFnCoeff = 35;
   // Deprecated since 5.5, replaced by remFnBaseEffort
   optional string debtRemFnOffset = 36;
-
+  optional sonarqube.ws.commons.RuleType type = 37;
   optional string defaultRemFnType = 38;
   optional string defaultRemFnGapMultiplier = 39;
   optional string defaultRemFnBaseEffort = 40;
@@ -121,13 +121,12 @@ message Rule {
   optional string gapDescription = 44;
   optional sonarqube.ws.commons.RuleScope scope = 46;
   optional bool isExternal = 47;
-
-  optional sonarqube.ws.commons.RuleType type = 37;
+  optional DeprecatedKeys deprecatedKeys = 48;
 
   message Params {
     repeated Param params = 1;
   }
-  
+
   message Param {
     optional string key = 1;
     optional string htmlDesc = 2;
@@ -136,6 +135,10 @@ message Rule {
   }
 }
 
+message DeprecatedKeys {
+  repeated string deprecatedKey = 1;
+}
+
 message SysTags {
   repeated string sysTags = 1;
 }
@@ -169,7 +172,7 @@ message Active {
 }
 
 message QProfiles {
-  map<string,QProfile> qProfiles = 1;
+  map<string, QProfile> qProfiles = 1;
 }
 
 message QProfile {