]> source.dussan.org Git - sonarqube.git/commitdiff
ONAR-5132 Issues search WS should allow to search by language
authorJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 22 Apr 2014 10:06:38 +0000 (12:06 +0200)
committerJulien Lancelot <julien.lancelot@sonarsource.com>
Tue, 22 Apr 2014 10:06:38 +0000 (12:06 +0200)
sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml
sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java
sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/select_by_languages.xml [new file with mode: 0644]
sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/shared.xml
sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueQuery.java
sonar-plugin-api/src/test/java/org/sonar/api/issue/IssueQueryTest.java
sonar-server/src/main/java/org/sonar/server/issue/PublicRubyIssueService.java
sonar-server/src/main/java/org/sonar/server/issue/filter/IssueFilterParameters.java
sonar-server/src/test/java/org/sonar/server/issue/PublicRubyIssueServiceTest.java
sonar-ws-client/src/main/java/org/sonar/wsclient/issue/IssueQuery.java
sonar-ws-client/src/test/java/org/sonar/wsclient/issue/IssueQueryTest.java

index bd85afc93136c9d4ea01fa75a6cf60de827277ca..785410c1ae27a062469e5ab2b8e2d81c9a2d88d2 100644 (file)
       <foreach item="component" index="index" collection="query.components()" open="(" separator=" or " close=")">project_component.kee=#{component}
       </foreach>
     </if>
-    <if test="query.rules().size()>0">
-      inner join rules r on r.id=i.rule_id and (<foreach item="rule" index="index" collection="query.rules()" open="(" separator=" or " close=")">
-      r.plugin_name=#{rule.repository} and r.plugin_rule_key=#{rule.rule}</foreach>)
+    <if test="query.rules().size()>0 or query.languages().size()>0">
+      inner join rules r on r.id=i.rule_id
+      <if test="query.rules().size()>0">
+        and (<foreach item="rule" index="index" collection="query.rules()" open="(" separator=" or " close=")">
+        r.plugin_name=#{rule.repository} and r.plugin_rule_key=#{rule.rule}</foreach>)
+      </if>
+      <if test="query.languages().size()>0">
+        and (<foreach item="language" index="index" collection="query.languages()" open="(" separator=" or " close=")">
+        r.language=#{language}</foreach>)
+      </if>
     </if>
     <where>
       <if test="query.issueKeys().size()>0">
index 45790762a26466bd376eed3cad04b9b8d9b5cd39..196b10204e05b7833dc2c1879112c0f8e7c53275 100644 (file)
@@ -259,6 +259,20 @@ public class IssueDaoTest extends AbstractDaoTestCase {
     assertThat(dao.selectIssueIds(query)).isEmpty();
   }
 
+  @Test
+  public void select_by_languages() {
+    setupData("shared", "select_by_languages");
+
+    IssueQuery query = IssueQuery.builder().languages(newArrayList("java")).requiredRole("user").build();
+    assertThat(dao.selectIssueIds(query)).hasSize(2);
+
+    query = IssueQuery.builder().languages(newArrayList("java", "xoo")).requiredRole("user").build();
+    assertThat(dao.selectIssueIds(query)).hasSize(3);
+
+    query = IssueQuery.builder().languages(newArrayList("Other")).requiredRole("user").build();
+    assertThat(dao.selectIssueIds(query)).isEmpty();
+  }
+
   @Test
   public void should_select_issues_for_authorized_projects() {
     setupData("should_select_issues_for_authorized_projects");
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/select_by_languages.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/select_by_languages.xml
new file mode 100644 (file)
index 0000000..3162d27
--- /dev/null
@@ -0,0 +1,101 @@
+<!--
+  ~ SonarQube, open source software quality management tool.
+  ~ Copyright (C) 2008-2014 SonarSource
+  ~ mailto:contact AT sonarsource DOT com
+  ~
+  ~ SonarQube is free software; you can redistribute it and/or
+  ~ modify it under the terms of the GNU Lesser General Public
+  ~ License as published by the Free Software Foundation; either
+  ~ version 3 of the License, or (at your option) any later version.
+  ~
+  ~ SonarQube is distributed in the hope that it will be useful,
+  ~ but WITHOUT ANY WARRANTY; without even the implied warranty of
+  ~ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  ~ Lesser General Public License for more details.
+  ~
+  ~ You should have received a copy of the GNU Lesser General Public License
+  ~ along with this program; if not, write to the Free Software Foundation,
+  ~ Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+  -->
+
+<dataset>
+
+  <!-- language Java -->
+  <issues
+      id="100"
+      kee="ABCDE-1"
+      component_id="401"
+      root_component_id="399"
+      rule_id="500"
+      severity="BLOCKER"
+      manual_severity="[false]"
+      message="[null]"
+      line="200"
+      effort_to_fix="4.2"
+      status="OPEN"
+      resolution="FIXED"
+      checksum="XXX"
+      reporter="arthur"
+      assignee="perceval"
+      author_login="[null]"
+      issue_attributes="JIRA=FOO-1234"
+      issue_creation_date="2013-04-16"
+      issue_update_date="2013-04-16"
+      issue_close_date="2013-04-16"
+      created_at="2013-04-16"
+      updated_at="2013-04-16"
+      />
+
+  <issues
+      id="101"
+      kee="ABCDE-2"
+      component_id="401"
+      root_component_id="399"
+      rule_id="500"
+      severity="BLOCKER"
+      manual_severity="[false]"
+      message="[null]"
+      line="200"
+      effort_to_fix="4.2"
+      status="OPEN"
+      resolution="FIXED"
+      checksum="XXX"
+      reporter="arthur"
+      assignee="perceval"
+      author_login="[null]"
+      issue_attributes="JIRA=FOO-1234"
+      issue_creation_date="2013-04-16"
+      issue_update_date="2013-04-16"
+      issue_close_date="2013-04-16"
+      created_at="2013-04-16"
+      updated_at="2013-04-16"
+      />
+
+
+  <!-- language Xoo -->
+  <issues
+      id="102"
+      kee="ABCDE-3"
+      component_id="401"
+      root_component_id="399"
+      rule_id="501"
+      severity="BLOCKER"
+      manual_severity="[false]"
+      message="[null]"
+      line="200"
+      effort_to_fix="4.2"
+      status="OPEN"
+      resolution="FIXED"
+      checksum="XXX"
+      reporter="arthur"
+      assignee="perceval"
+      author_login="[null]"
+      issue_attributes="JIRA=FOO-1234"
+      issue_creation_date="2013-04-16"
+      issue_update_date="2013-04-16"
+      issue_close_date="2013-04-16"
+      created_at="2013-04-16"
+      updated_at="2013-04-16"
+      />
+
+</dataset>
index 49364f57eb62c932e9678d390af1eba9b3efc90e..89d4696e3673088051617783eaaca68cea023ca7 100644 (file)
@@ -12,7 +12,7 @@
   <snapshots id="102" project_id="401" root_snapshot_id="100" parent_snapshot_id="101" root_project_id="399" path="100.101." islast="[true]" />
   <snapshots id="103" project_id="402" root_snapshot_id="100" parent_snapshot_id="101" root_project_id="399" path="100.101." islast="[true]" />
 
-  <rules id="500" plugin_rule_key="AvoidCycle" plugin_name="squid" />
-  <rules id="501" plugin_rule_key="NullRef" plugin_name="squid" />
+  <rules id="500" plugin_rule_key="AvoidCycle" plugin_name="squid" language="java" />
+  <rules id="501" plugin_rule_key="NullRef" plugin_name="squid" language="xoo" />
 
 </dataset>
index 9d58e10a966867f85a1c175df21f6af35378aef8..fc4458e49a5d1a78d69cbb5e5e8679685e1000de 100644 (file)
@@ -67,6 +67,7 @@ public class IssueQuery {
   private final Collection<String> actionPlans;
   private final Collection<String> reporters;
   private final Collection<String> assignees;
+  private final Collection<String> languages;
   private final Boolean assigned;
   private final Boolean planned;
   private final Boolean resolved;
@@ -95,6 +96,7 @@ public class IssueQuery {
     this.actionPlans = defaultCollection(builder.actionPlans);
     this.reporters = defaultCollection(builder.reporters);
     this.assignees = defaultCollection(builder.assignees);
+    this.languages = defaultCollection(builder.languages);
     this.assigned = builder.assigned;
     this.planned = builder.planned;
     this.resolved = builder.resolved;
@@ -148,6 +150,9 @@ public class IssueQuery {
   public Collection<String> assignees() {
     return assignees;
   }
+  public Collection<String> languages() {
+    return languages;
+  }
 
   @CheckForNull
   public Boolean assigned() {
@@ -233,6 +238,7 @@ public class IssueQuery {
     private Collection<String> actionPlans;
     private Collection<String> reporters;
     private Collection<String> assignees;
+    private Collection<String> languages;
     private Boolean assigned = null;
     private Boolean planned = null;
     private Boolean resolved = null;
@@ -299,6 +305,11 @@ public class IssueQuery {
       return this;
     }
 
+    public Builder languages(@Nullable Collection<String> l) {
+      this.languages = l;
+      return this;
+    }
+
     /**
      * If true, it will return all issues assigned to someone
      * If false, it will return all issues not assigned to someone
index 75b12dedb05ce0dacacfa3b7f1a4c0a641d5fe8c..933934f838fffd5f4e0a94f57132eb4dc7eb2ae3 100644 (file)
@@ -47,6 +47,7 @@ public class IssueQueryTest {
       .actionPlans(newArrayList("AP1", "AP2"))
       .reporters(newArrayList("crunky"))
       .assignees(newArrayList("gargantua"))
+      .languages(newArrayList("xoo"))
       .assigned(true)
       .hideRules(true)
       .createdAfter(new Date())
@@ -68,6 +69,7 @@ public class IssueQueryTest {
     assertThat(query.componentRoots()).containsOnly("org.struts:core");
     assertThat(query.reporters()).containsOnly("crunky");
     assertThat(query.assignees()).containsOnly("gargantua");
+    assertThat(query.languages()).containsOnly("xoo");
     assertThat(query.assigned()).isTrue();
     assertThat(query.hideRules()).isTrue();
     assertThat(query.rules()).containsOnly(RuleKey.of("squid", "AvoidCycle"));
@@ -123,6 +125,7 @@ public class IssueQueryTest {
       .resolutions(null)
       .rules(null)
       .severities(null)
+      .languages(null)
       .build();
     assertThat(query.issueKeys()).isEmpty();
     assertThat(query.components()).isEmpty();
@@ -134,6 +137,7 @@ public class IssueQueryTest {
     assertThat(query.resolutions()).isEmpty();
     assertThat(query.rules()).isEmpty();
     assertThat(query.severities()).isEmpty();
+    assertThat(query.languages()).isEmpty();
   }
 
   @Test
@@ -149,6 +153,7 @@ public class IssueQueryTest {
     assertThat(query.resolutions()).isEmpty();
     assertThat(query.rules()).isEmpty();
     assertThat(query.severities()).isEmpty();
+    assertThat(query.languages()).isEmpty();
     assertThat(query.assigned()).isNull();
     assertThat(query.createdAfter()).isNull();
     assertThat(query.createdBefore()).isNull();
index dbe65d392e863cf9e87b256c390df182e3a79c64..cdf5a2fb24b5deee90771773b3d90136f66f1884 100644 (file)
@@ -87,6 +87,7 @@ public class PublicRubyIssueService implements RubyIssueService {
       .actionPlans(RubyUtils.toStrings(props.get(IssueFilterParameters.ACTION_PLANS)))
       .reporters(RubyUtils.toStrings(props.get(IssueFilterParameters.REPORTERS)))
       .assignees(RubyUtils.toStrings(props.get(IssueFilterParameters.ASSIGNEES)))
+      .languages(RubyUtils.toStrings(props.get(IssueFilterParameters.LANGUAGES)))
       .assigned(RubyUtils.toBoolean(props.get(IssueFilterParameters.ASSIGNED)))
       .planned(RubyUtils.toBoolean(props.get(IssueFilterParameters.PLANNED)))
       .hideRules(RubyUtils.toBoolean(props.get(IssueFilterParameters.HIDE_RULES)))
index 85f9299309daddd64b89c8d5a764b3f785e7187d..57eb83f5c9ef3f2e107fcfd5348f72d4623bd019 100644 (file)
@@ -44,6 +44,7 @@ public class IssueFilterParameters {
   public static final String ACTION_PLANS = "actionPlans";
   public static final String REPORTERS = "reporters";
   public static final String ASSIGNEES = "assignees";
+  public static final String LANGUAGES = "languages";
   public static final String ASSIGNED = "assigned";
   public static final String PLANNED = "planned";
   public static final String HIDE_RULES = "hideRules";
@@ -56,7 +57,7 @@ public class IssueFilterParameters {
   public static final String ASC = "asc";
 
   public static final List<String> ALL = ImmutableList.of(ISSUES, SEVERITIES, STATUSES, RESOLUTIONS, RESOLVED, COMPONENTS, COMPONENT_ROOTS, RULES, ACTION_PLANS, REPORTERS,
-    ASSIGNEES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, PAGE_SIZE, PAGE_INDEX, SORT, ASC);
+    ASSIGNEES, LANGUAGES, ASSIGNED, PLANNED, HIDE_RULES, CREATED_AT, CREATED_AFTER, CREATED_BEFORE, PAGE_SIZE, PAGE_INDEX, SORT, ASC);
 
   public static final List<String> ALL_WITHOUT_PAGINATION = newArrayList(Iterables.filter(ALL, new Predicate<String>() {
     @Override
index ab624835c09163340a33bc3bed284f2a26f97a92..95bc3a3fcf2a736cadf1ff899fa6b44872e53d61 100644 (file)
@@ -79,6 +79,7 @@ public class PublicRubyIssueServiceTest {
     map.put("componentRoots", newArrayList("org.sonar"));
     map.put("reporters", newArrayList("marilyn"));
     map.put("assignees", newArrayList("joanna"));
+    map.put("languages", newArrayList("xoo"));
     map.put("assigned", true);
     map.put("planned", true);
     map.put("hideRules", true);
@@ -100,6 +101,7 @@ public class PublicRubyIssueServiceTest {
     assertThat(query.componentRoots()).containsOnly("org.sonar");
     assertThat(query.reporters()).containsOnly("marilyn");
     assertThat(query.assignees()).containsOnly("joanna");
+    assertThat(query.languages()).containsOnly("xoo");
     assertThat(query.assigned()).isTrue();
     assertThat(query.planned()).isTrue();
     assertThat(query.hideRules()).isTrue();
@@ -113,7 +115,7 @@ public class PublicRubyIssueServiceTest {
   }
 
   @Test
-  public void should_parse_list_of_rules() {
+  public void parse_list_of_rules() {
     assertThat(PublicRubyIssueService.toRules(null)).isNull();
     assertThat(PublicRubyIssueService.toRules("")).isEmpty();
     assertThat(PublicRubyIssueService.toRules("squid:AvoidCycle")).containsOnly(RuleKey.of("squid", "AvoidCycle"));
@@ -122,7 +124,7 @@ public class PublicRubyIssueServiceTest {
   }
 
   @Test
-  public void should_start() throws Exception {
+  public void start() throws Exception {
     facade.start();
     // nothing is done
     verifyZeroInteractions(finder);
index e0d38ab0194d4962bb37e1f23f0011d4e11e6469..304fee715b984b8d70b1825d01e492f3bd02e1ec 100644 (file)
@@ -85,6 +85,9 @@ public class IssueQuery {
   public IssueQuery assignees(String... s) {
     return addParam("assignees", s);
   }
+  public IssueQuery languages(String... s) {
+    return addParam("languages", s);
+  }
 
   public IssueQuery assigned(Boolean assigned) {
     params.put("assigned", assigned);
index c27a732276d2135146a10b51967d92d186de3689..c4d0e209d1444418beff329d011251d407e26ec4 100644 (file)
@@ -52,6 +52,7 @@ public class IssueQueryTest {
       .statuses("OPEN", "CLOSED")
       .severities("BLOCKER", "INFO")
       .reporters("login1", "login2")
+      .languages("xoo", "java")
       .createdAt(df.parse("2015-01-02T05:59:50:50"))
       .createdBefore(df.parse("2015-12-13T05:59:50"))
       .createdAfter(df.parse("2012-01-23T13:40:50"))
@@ -60,7 +61,7 @@ public class IssueQueryTest {
       .pageSize(5)
       .pageIndex(4);
 
-    assertThat(query.urlParams()).hasSize(21);
+    assertThat(query.urlParams()).hasSize(22);
     assertThat(query.urlParams()).includes(entry("issues", "ABCDE,FGHIJ"));
     assertThat(query.urlParams()).includes(entry("assignees", "arthur,perceval"));
     assertThat(query.urlParams()).includes(entry("assigned", true));
@@ -75,6 +76,7 @@ public class IssueQueryTest {
     assertThat(query.urlParams()).includes(entry("statuses", "OPEN,CLOSED"));
     assertThat(query.urlParams()).includes(entry("severities", "BLOCKER,INFO"));
     assertThat(query.urlParams()).includes(entry("reporters", "login1,login2"));
+    assertThat(query.urlParams()).includes(entry("languages", "xoo,java"));
     assertThat((String)query.urlParams().get("createdBefore")).startsWith("2015-12-13T05:59:50");
     assertThat((String)query.urlParams().get("createdAfter")).startsWith("2012-01-23T13:40:50");
     assertThat((String)query.urlParams().get("createdAt")).startsWith("2015-01-02T05:59:50");