aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-core/src
diff options
context:
space:
mode:
authorJulien Lancelot <julien.lancelot@sonarsource.com>2014-04-18 12:15:13 +0200
committerJulien Lancelot <julien.lancelot@sonarsource.com>2014-04-18 14:09:18 +0200
commitbfeca720d3a702b77664b0164aa02ce89b353cec (patch)
treee68bad3f6151ed92c89667fa7e92e55cc8487401 /sonar-core/src
parent5857333fb71af4090a6b3dcb3e972d465873f98d (diff)
downloadsonarqube-bfeca720d3a702b77664b0164aa02ce89b353cec.tar.gz
sonarqube-bfeca720d3a702b77664b0164aa02ce89b353cec.zip
SONAR-5218 Once a module has been turned into a project, its issues are no more visible in the UI
Diffstat (limited to 'sonar-core/src')
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java9
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java16
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java3
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java2
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml8
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java4
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java31
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java28
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java6
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml127
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml2
13 files changed, 228 insertions, 12 deletions
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java
index 68284cb07ce..859ad804ad2 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java
@@ -35,6 +35,7 @@ import java.util.UUID;
public class DefaultIssueBuilder implements Issuable.IssueBuilder {
private String componentKey;
+ private String projectKey;
private RuleKey ruleKey;
private Integer line;
private String message;
@@ -52,6 +53,12 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder {
return this;
}
+
+ public DefaultIssueBuilder projectKey(String projectKey) {
+ this.projectKey = projectKey;
+ return this;
+ }
+
@Override
public Issuable.IssueBuilder ruleKey(RuleKey ruleKey) {
this.ruleKey = ruleKey;
@@ -99,6 +106,7 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder {
@Override
public DefaultIssue build() {
+ Preconditions.checkNotNull(projectKey, "Project key must be set");
Preconditions.checkNotNull(componentKey, "Component key must be set");
Preconditions.checkNotNull(ruleKey, "Rule key must be set");
@@ -107,6 +115,7 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder {
Preconditions.checkState(!Strings.isNullOrEmpty(key), "Fail to generate issue key");
issue.setKey(key);
issue.setComponentKey(componentKey);
+ issue.setProjectKey(projectKey);
issue.setRuleKey(ruleKey);
issue.setMessage(message);
issue.setSeverity(severity);
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java b/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java
index cdd3717f699..9ac381eeffd 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/IssueUpdater.java
@@ -247,4 +247,20 @@ public class IssueUpdater implements BatchComponent, ServerComponent {
return false;
}
+ public boolean setProject(DefaultIssue issue, String key, IssueChangeContext context) {
+ if (!Objects.equal(key, issue.projectKey())) {
+ issue.setProjectKey(key);
+ issue.setUpdateDate(context.date());
+ issue.setChanged(true);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean setPastProject(DefaultIssue issue, String previousKey, IssueChangeContext context) {
+ String currentProjectKey = issue.projectKey();
+ issue.setProjectKey(previousKey);
+ return setProject(issue, currentProjectKey, context);
+ }
+
}
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java
index 3b7aa30ccc4..be0d275f1cd 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueDto.java
@@ -390,7 +390,7 @@ public final class IssueDto implements Serializable {
.setUpdatedAt(now);
}
- public static IssueDto toDtoForUpdate(DefaultIssue issue, Date now) {
+ public static IssueDto toDtoForUpdate(DefaultIssue issue, Long rootComponentId, Date now) {
// Invariant fields, like key and rule, can't be updated
return new IssueDto()
.setKee(issue.key())
@@ -408,6 +408,7 @@ public final class IssueDto implements Serializable {
.setActionPlanKey(issue.actionPlanKey())
.setIssueAttributes(KeyValueFormat.format(issue.attributes()))
.setAuthorLogin(issue.authorLogin())
+ .setRootComponentId(rootComponentId)
.setIssueCreationDate(issue.creationDate())
.setIssueCloseDate(issue.closeDate())
.setIssueUpdateDate(issue.updateDate())
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java
index 3c3a8784891..600b5e4f8c2 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueMapper.java
@@ -31,8 +31,6 @@ public interface IssueMapper {
IssueDto selectByKey(String key);
- List<IssueDto> selectNonClosedIssuesByModule(int rootComponentId);
-
/**
* Return a paginated list of authorized issue ids for a user.
* If the role is null, then the authorisation check is disabled.
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java
index fad9862d7be..a52f728a5df 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/db/IssueStorage.java
@@ -119,7 +119,7 @@ public abstract class IssueStorage {
}
private void update(IssueMapper issueMapper, Date now, DefaultIssue issue) {
- IssueDto dto = IssueDto.toDtoForUpdate(issue, now);
+ IssueDto dto = IssueDto.toDtoForUpdate(issue, projectId(issue), now);
if (Issue.STATUS_CLOSED.equals(issue.status()) || issue.selectedAt() == null) {
// Issue is closed by scan or changed by end-user
issueMapper.update(dto);
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java b/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java
index 536667cae3f..73370a7face 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/db/UpdateConflictResolver.java
@@ -41,7 +41,7 @@ class UpdateConflictResolver {
IssueDto dbIssue = mapper.selectByKey(issue.key());
if (dbIssue != null) {
mergeFields(dbIssue, issue);
- mapper.update(IssueDto.toDtoForUpdate(issue, new Date()));
+ mapper.update(IssueDto.toDtoForUpdate(issue, dbIssue.getRootComponentId(), new Date()));
}
}
diff --git a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml
index a3e15378041..bd85afc9313 100644
--- a/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/issue/db/IssueMapper.xml
@@ -89,6 +89,7 @@
reporter=#{reporter},
assignee=#{assignee},
author_login=#{authorLogin},
+ root_component_id=#{rootComponentId},
issue_attributes=#{issueAttributes},
issue_creation_date=#{issueCreationDate},
issue_update_date=#{issueUpdateDate},
@@ -115,6 +116,7 @@
reporter=#{reporter},
assignee=#{assignee},
author_login=#{authorLogin},
+ root_component_id=#{rootComponentId},
issue_attributes=#{issueAttributes},
issue_creation_date=#{issueCreationDate},
issue_update_date=#{issueUpdateDate},
@@ -163,10 +165,12 @@
i.updated_at as updatedAt,
r.plugin_rule_key as ruleKey,
r.plugin_name as ruleRepo,
- p.kee as componentKey
+ p.kee as componentKey,
+ root.kee as rootComponentKey
from issues i
- inner join rules r on r.id=i.rule_id
inner join (select p.id,p.kee from projects p where (p.root_id=#{id} and p.qualifier &lt;&gt; 'BRC') or (p.id=#{id})) p on p.id=i.component_id
+ inner join rules r on r.id=i.rule_id
+ left outer join projects root on root.id=i.root_component_id
<where>
and i.status &lt;&gt; 'CLOSED'
</where>
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java
index 916be3ea6e1..30b34609c00 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueBuilderTest.java
@@ -32,8 +32,10 @@ public class DefaultIssueBuilderTest {
@Test
public void build_new_issue() throws Exception {
String componentKey = "org.apache.struts:struts-core:Action.java";
+ String projectKey = "org.apache.struts";
DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder()
.componentKey(componentKey)
+ .projectKey(projectKey)
.message("the message")
.line(123)
.effortToFix(10000.0)
@@ -47,6 +49,7 @@ public class DefaultIssueBuilderTest {
assertThat(issue.key()).isNotNull();
assertThat(issue.effortToFix()).isEqualTo(10000.0);
assertThat(issue.componentKey()).isEqualTo(componentKey);
+ assertThat(issue.projectKey()).isEqualTo(projectKey);
assertThat(issue.message()).isEqualTo("the message");
assertThat(issue.line()).isEqualTo(123);
assertThat(issue.ruleKey().repository()).isEqualTo("squid");
@@ -65,6 +68,7 @@ public class DefaultIssueBuilderTest {
public void not_set_default_severity() {
DefaultIssue issue = (DefaultIssue) new DefaultIssueBuilder()
.componentKey("Action.java")
+ .projectKey("org.apache.struts")
.ruleKey(RuleKey.of("squid", "NullDereference"))
.build();
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java b/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java
index c0dfa62ec32..5373ebef6eb 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/IssueUpdaterTest.java
@@ -447,4 +447,35 @@ public class IssueUpdaterTest {
assertThat(issue.mustSendNotifications()).isFalse();
}
+ @Test
+ public void set_project() throws Exception {
+ boolean updated = updater.setProject(issue, "sample", context);
+ assertThat(updated).isTrue();
+ assertThat(issue.projectKey()).isEqualTo("sample");
+
+ // do not save change
+ assertThat(issue.currentChange()).isNull();
+ assertThat(issue.mustSendNotifications()).isFalse();
+ }
+
+ @Test
+ public void set_past_project() throws Exception {
+ issue.setProjectKey("new project key");
+ boolean updated = updater.setPastProject(issue, "past project key", context);
+ assertThat(updated).isTrue();
+ assertThat(issue.projectKey()).isEqualTo("new project key");
+
+ // do not save change
+ assertThat(issue.currentChange()).isNull();
+ assertThat(issue.mustSendNotifications()).isFalse();
+ }
+
+ @Test
+ public void not_set_past_project_if_no_change() throws Exception {
+ issue.setProjectKey("key");
+ boolean updated = updater.setPastProject(issue, "key", context);
+ assertThat(updated).isFalse();
+ assertThat(issue.projectKey()).isEqualTo("key");
+ }
+
}
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java
index a8087a3d4d8..45790762a26 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueDaoTest.java
@@ -310,7 +310,7 @@ public class IssueDaoTest extends AbstractDaoTestCase {
}
@Test
- public void should_select_non_closed_issues_by_module() {
+ public void select_non_closed_issues_by_module() {
setupData("shared", "should_select_non_closed_issues_by_module");
// 400 is a non-root module, we should find 2 issues from classes and one on itself
@@ -322,11 +322,37 @@ public class IssueDaoTest extends AbstractDaoTestCase {
assertThat(issue.getRuleRepo()).isNotNull();
assertThat(issue.getRule()).isNotNull();
assertThat(issue.getComponentKey()).isNotNull();
+ assertThat(issue.getRootComponentKey()).isEqualTo("struts");
// 399 is the root module, we should only find 1 issue on itself
handler = new DefaultResultHandler();
dao.selectNonClosedIssuesByModule(399, handler);
assertThat(handler.getResultList()).hasSize(1);
+
+ issue = (IssueDto) handler.getResultList().get(0);
+ assertThat(issue.getComponentKey()).isEqualTo("struts");
+ assertThat(issue.getRootComponentKey()).isEqualTo("struts");
+ }
+
+ /**
+ * SONAR-5218
+ */
+ @Test
+ public void select_non_closed_issues_by_module_on_removed_project() {
+ // All issues are linked on a project that is not existing anymore
+
+ setupData("shared", "should_select_non_closed_issues_by_module_on_removed_project");
+
+ // 400 is a non-root module, we should find 2 issues from classes and one on itself
+ DefaultResultHandler handler = new DefaultResultHandler();
+ dao.selectNonClosedIssuesByModule(400, handler);
+ assertThat(handler.getResultList()).hasSize(3);
+
+ IssueDto issue = (IssueDto) handler.getResultList().get(0);
+ assertThat(issue.getRuleRepo()).isNotNull();
+ assertThat(issue.getRule()).isNotNull();
+ assertThat(issue.getComponentKey()).isNotNull();
+ assertThat(issue.getRootComponentKey()).isNull();
}
@Test
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java
index e3e074562ee..705c5358ea8 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/db/IssueMapperTest.java
@@ -84,7 +84,7 @@ public class IssueMapperTest extends AbstractDaoTestCase {
IssueDto dto = new IssueDto();
dto.setComponentId(123l);
- dto.setRootComponentId(100l);
+ dto.setRootComponentId(101l);
dto.setRuleId(200);
dto.setKee("ABCDE");
dto.setLine(500);
@@ -119,7 +119,7 @@ public class IssueMapperTest extends AbstractDaoTestCase {
IssueDto dto = new IssueDto();
dto.setComponentId(123l);
- dto.setRootComponentId(100l);
+ dto.setRootComponentId(101l);
dto.setRuleId(200);
dto.setKee("ABCDE");
dto.setLine(500);
@@ -157,7 +157,7 @@ public class IssueMapperTest extends AbstractDaoTestCase {
IssueDto dto = new IssueDto();
dto.setComponentId(123l);
- dto.setRootComponentId(100l);
+ dto.setRootComponentId(101l);
dto.setRuleId(200);
dto.setKee("ABCDE");
dto.setLine(500);
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml
new file mode 100644
index 00000000000..ec2c35e66d9
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueDaoTest/should_select_non_closed_issues_by_module_on_removed_project.xml
@@ -0,0 +1,127 @@
+<!--
+ ~ 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>
+
+ <!-- Open Issue on a file -->
+ <issues
+ id="100"
+ kee="100"
+ component_id="401"
+ root_component_id="111"
+ rule_id="500"
+ severity="BLOCKER"
+ manual_severity="[false]"
+ message="[null]"
+ line="200"
+ effort_to_fix="[null]"
+ status="OPEN"
+ resolution="[null]"
+ checksum="[null]"
+ reporter="user"
+ assignee="user"
+ author_login="[null]"
+ issue_attributes="[null]"
+ 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="[null]"
+ />
+
+ <!-- Open Issue on a file -->
+ <issues
+ id="101"
+ kee="101"
+ component_id="402"
+ root_component_id="111"
+ rule_id="501"
+ severity="MAJOR"
+ manual_severity="[false]"
+ message="[null]"
+ line="120"
+ effort_to_fix="[null]"
+ status="OPEN"
+ resolution="[null]"
+ checksum="[null]"
+ reporter="[null]"
+ assignee="user"
+ author_login="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="2013-04-16"
+ issue_update_date="2013-04-16"
+ issue_close_date="2013-04-16"
+ created_at="2013-04-10"
+ updated_at="[null]"
+ />
+
+ <!-- Closed Issue on a file -->
+ <issues
+ id="102"
+ kee="102"
+ component_id="402"
+ root_component_id="111"
+ rule_id="501"
+ severity="MAJOR"
+ manual_severity="[false]"
+ message="[null]"
+ line="120"
+ effort_to_fix="[null]"
+ status="CLOSED"
+ resolution="FIXED"
+ checksum="[null]"
+ reporter="[null]"
+ assignee="user"
+ author_login="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="2013-04-16"
+ issue_update_date="2013-04-16"
+ issue_close_date="2013-04-16"
+ created_at="2013-04-10"
+ updated_at="[null]"
+ />
+
+ <!-- Open Issue on a sub module -->
+ <issues
+ id="103"
+ kee="103"
+ component_id="400"
+ root_component_id="111"
+ rule_id="501"
+ severity="MAJOR"
+ manual_severity="[false]"
+ message="[null]"
+ line="[null]"
+ effort_to_fix="[null]"
+ status="OPEN"
+ resolution="[null]"
+ checksum="[null]"
+ reporter="[null]"
+ assignee="user"
+ author_login="[null]"
+ issue_attributes="[null]"
+ issue_creation_date="2013-04-16"
+ issue_update_date="2013-04-16"
+ issue_close_date="2013-04-16"
+ created_at="2013-04-10"
+ updated_at="[null]"
+ />
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml
index 8016cfac576..a923dfa54e0 100644
--- a/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/issue/db/IssueMapperTest/testUpdate-result.xml
@@ -3,7 +3,7 @@
id="100"
kee="ABCDE"
component_id="123"
- root_component_id="100"
+ root_component_id="101"
rule_id="200"
severity="BLOCKER"
manual_severity="[false]"