]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-6153 Show rule tags in issue tag suggestions 107/head
authorJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 19 Feb 2015 09:41:36 +0000 (10:41 +0100)
committerJean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com>
Thu, 19 Feb 2015 12:52:47 +0000 (13:52 +0100)
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java
server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java

index 5878c7a6f4612bde2b64207ab8e707b5b5fb7537..eb1a6f9b7c726bae0aae92b699e29b9f60938e10 100644 (file)
@@ -24,6 +24,7 @@ import com.google.common.base.Preconditions;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
+import com.google.common.collect.Sets;
 import org.apache.commons.lang.BooleanUtils;
 import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
@@ -32,6 +33,8 @@ import org.elasticsearch.index.query.*;
 import org.elasticsearch.search.aggregations.AggregationBuilder;
 import org.elasticsearch.search.aggregations.AggregationBuilders;
 import org.elasticsearch.search.aggregations.bucket.filter.FilterAggregationBuilder;
+import org.elasticsearch.search.aggregations.bucket.global.Global;
+import org.elasticsearch.search.aggregations.bucket.global.GlobalBuilder;
 import org.elasticsearch.search.aggregations.bucket.histogram.DateHistogram;
 import org.elasticsearch.search.aggregations.bucket.missing.InternalMissing;
 import org.elasticsearch.search.aggregations.bucket.terms.Terms;
@@ -46,6 +49,8 @@ import org.sonar.server.es.*;
 import org.sonar.server.exceptions.NotFoundException;
 import org.sonar.server.issue.IssueQuery;
 import org.sonar.server.issue.filter.IssueFilterParameters;
+import org.sonar.server.rule.index.RuleNormalizer;
+import org.sonar.server.search.IndexDefinition;
 import org.sonar.server.search.StickyFacetBuilder;
 import org.sonar.server.user.UserSession;
 import org.sonar.server.view.index.ViewIndexDefinition;
@@ -64,6 +69,8 @@ import static com.google.common.collect.Lists.newArrayList;
  */
 public class IssueIndex extends BaseIndex {
 
+  private static final String SUBSTRING_MATCH_REGEXP = ".*%s.*";
+
   public static final List<String> SUPPORTED_FACETS = ImmutableList.of(
     IssueFilterParameters.SEVERITIES,
     IssueFilterParameters.STATUSES,
@@ -542,8 +549,39 @@ public class IssueIndex extends BaseIndex {
   }
 
   public List<String> listTags(IssueQuery query, @Nullable String textQuery, int maxNumberOfTags) {
-    Terms terms = listTermsMatching(IssueIndexDefinition.FIELD_ISSUE_TAGS, query, textQuery, Terms.Order.term(true), maxNumberOfTags);
-    return EsUtils.termsKeys(terms);
+    SearchRequestBuilder requestBuilder = getClient()
+      .prepareSearch(IssueIndexDefinition.INDEX, IndexDefinition.RULE.getIndexName())
+      .setTypes(IssueIndexDefinition.TYPE_ISSUE, IndexDefinition.RULE.getIndexType());
+
+    requestBuilder.setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(),
+      createBoolFilter(query)));
+    GlobalBuilder topAggreg = AggregationBuilders.global("tags");
+    TermsBuilder issueTags = AggregationBuilders.terms("tags__issues")
+      .field(IssueIndexDefinition.FIELD_ISSUE_TAGS)
+      .size(maxNumberOfTags)
+      .order(Terms.Order.term(true))
+      .minDocCount(1L);
+    if (textQuery != null) {
+      issueTags.include(String.format(SUBSTRING_MATCH_REGEXP, textQuery));
+    }
+    TermsBuilder ruleTags = AggregationBuilders.terms("tags__rules")
+      .field(RuleNormalizer.RuleField.ALL_TAGS.field())
+      .size(maxNumberOfTags)
+      .order(Terms.Order.term(true))
+      .minDocCount(1L);
+    if (textQuery != null) {
+      ruleTags.include(String.format(SUBSTRING_MATCH_REGEXP, textQuery));
+    }
+
+    SearchResponse searchResponse = requestBuilder.addAggregation(topAggreg.subAggregation(issueTags).subAggregation(ruleTags)).get();
+    Global allTags = searchResponse.getAggregations().get("tags");
+    SortedSet<String> result = Sets.newTreeSet();
+    Terms issuesResult = allTags.getAggregations().get("tags__issues");
+    Terms rulesResult = allTags.getAggregations().get("tags__rules");
+    result.addAll(EsUtils.termsKeys(issuesResult));
+    result.addAll(EsUtils.termsKeys(rulesResult));
+    List<String> resultAsList = Lists.newArrayList(result);
+    return resultAsList.size() > maxNumberOfTags ? resultAsList.subList(0, maxNumberOfTags) : resultAsList;
   }
 
   public Map<String, Long> countTags(IssueQuery query, int maxNumberOfTags) {
@@ -572,7 +610,7 @@ public class IssueIndex extends BaseIndex {
       .order(termsOrder)
       .minDocCount(1L);
     if (textQuery != null) {
-      aggreg.include(String.format(".*%s.*", textQuery));
+      aggreg.include(String.format(SUBSTRING_MATCH_REGEXP, textQuery));
     }
 
     SearchResponse searchResponse = requestBuilder.addAggregation(aggreg).get();
index 44223ac2208eea067d94fbbe9756e3cf41f97926..3023ae60034e22aad233145668f6a100c457b789 100644 (file)
@@ -532,11 +532,12 @@ public class IssueServiceMediumTest {
     saveIssue(IssueTesting.newDto(rule, file, project));
     saveIssue(IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention")));
 
-    assertThat(service.listTags(null, 5)).containsOnly("convention", "java8", "bug");
+    assertThat(service.listTags(null, 5)).containsOnly("convention", "java8", "bug" /* from issues */, "systag1", "systag2" /* from rules */);
     assertThat(service.listTags(null, 2)).containsOnly("bug", "convention");
     assertThat(service.listTags("vent", 5)).containsOnly("convention");
+    assertThat(service.listTags("sys", 5)).containsOnly("systag1", "systag2");
     assertThat(service.listTags(null, 1)).containsOnly("bug");
-    assertThat(service.listTags(null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug");
+    assertThat(service.listTags(null, Integer.MAX_VALUE)).containsOnly("convention", "java8", "bug", "systag1", "systag2", "tag1", "tag2");
   }
 
   @Test