aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java4
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java24
-rw-r--r--plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties2
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java7
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java23
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/DefaultIssueBuilder.java3
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/workflow/IsEndOfLife.java (renamed from sonar-core/src/main/java/org/sonar/core/issue/workflow/IsAlive.java)10
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/workflow/IssueWorkflow.java26
-rw-r--r--sonar-core/src/main/java/org/sonar/core/issue/workflow/SetEndOfLifeResolution.java38
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/workflow/IsEndOfLifeTest.java (renamed from sonar-core/src/test/java/org/sonar/core/issue/workflow/IsAliveTest.java)18
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/workflow/IssueWorkflowTest.java10
-rw-r--r--sonar-core/src/test/java/org/sonar/core/issue/workflow/SetEndOfLifeResolutionTest.java63
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java3
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueHandler.java3
14 files changed, 178 insertions, 56 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java
index 035f0d05958..a34185a8d29 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueHandlers.java
@@ -73,8 +73,8 @@ public class IssueHandlers implements BatchExtension {
}
@Override
- public boolean isAlive() {
- return issue.isAlive();
+ public boolean isEndOfLife() {
+ return issue.isEndOfLife();
}
@Override
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java
index 007c6589230..8e071fba49e 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/IssueTrackingDecorator.java
@@ -26,9 +26,11 @@ import org.sonar.api.batch.*;
import org.sonar.api.component.ResourcePerspectives;
import org.sonar.api.issue.Issuable;
import org.sonar.api.issue.Issue;
+import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.api.resources.ResourceUtils;
+import org.sonar.api.rules.ActiveRule;
import org.sonar.api.rules.Rule;
import org.sonar.api.rules.RuleFinder;
import org.sonar.api.utils.KeyValueFormat;
@@ -55,13 +57,13 @@ public class IssueTrackingDecorator implements Decorator {
private final IssueUpdater updater;
private final IssueChangeContext changeContext;
private final ResourcePerspectives perspectives;
- private final RuleFinder ruleFinder;
+ private final RulesProfile rulesProfile;
public IssueTrackingDecorator(IssueCache issueCache, InitialOpenIssuesStack initialOpenIssues, IssueTracking tracking,
IssueFilters filters, IssueHandlers handlers, IssueWorkflow workflow,
IssueUpdater updater,
Project project, ResourcePerspectives perspectives,
- RuleFinder ruleFinder) {
+ RulesProfile rulesProfile) {
this.issueCache = issueCache;
this.initialOpenIssues = initialOpenIssues;
this.tracking = tracking;
@@ -71,7 +73,7 @@ public class IssueTrackingDecorator implements Decorator {
this.updater = updater;
this.changeContext = IssueChangeContext.createScan(project.getAnalysisDate());
this.perspectives = perspectives;
- this.ruleFinder = ruleFinder;
+ this.rulesProfile = rulesProfile;
}
public boolean shouldExecuteOnProject(Project project) {
@@ -131,7 +133,8 @@ public class IssueTrackingDecorator implements Decorator {
// non-persisted fields
issue.setNew(false);
- issue.setAlive(true);
+ issue.setEndOfLife(false);
+ issue.setOnDisabledRule(false);
// fields to update with old values
issue.setActionPlanKey(ref.getActionPlanKey());
@@ -162,13 +165,14 @@ public class IssueTrackingDecorator implements Decorator {
private void addUnmatched(Collection<IssueDto> unmatchedIssues, Collection<DefaultIssue> issues) {
for (IssueDto unmatchedDto : unmatchedIssues) {
DefaultIssue unmatched = unmatchedDto.toDefaultIssue();
- unmatched.setNew(false);
- Rule rule = ruleFinder.findByKey(unmatched.ruleKey());
+ ActiveRule activeRule = rulesProfile.getActiveRule(unmatchedDto.getRuleRepo(), unmatchedDto.getRule());
boolean manualIssue = !Strings.isNullOrEmpty(unmatched.reporter());
- boolean onExistingRule = (rule != null && !Rule.STATUS_REMOVED.equals(rule.getStatus()));
- unmatched.setAlive(manualIssue && onExistingRule);
+ boolean onDisabledRule = (activeRule==null);
+ unmatched.setNew(false);
+ unmatched.setEndOfLife(!manualIssue);
+ unmatched.setOnDisabledRule(onDisabledRule);
issues.add(unmatched);
}
}
@@ -176,8 +180,10 @@ public class IssueTrackingDecorator implements Decorator {
private void addDead(Collection<DefaultIssue> issues) {
for (IssueDto deadDto : initialOpenIssues.getAllIssues()) {
DefaultIssue dead = deadDto.toDefaultIssue();
- dead.setAlive(false);
+ ActiveRule activeRule = rulesProfile.getActiveRule(deadDto.getRuleRepo(), deadDto.getRule());
dead.setNew(false);
+ dead.setEndOfLife(true);
+ dead.setOnDisabledRule(activeRule==null);
issues.add(dead);
}
}
diff --git a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
index 82a60c4ce95..5f443c280ef 100644
--- a/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
+++ b/plugins/sonar-core-plugin/src/main/resources/org/sonar/l10n/core.properties
@@ -553,9 +553,9 @@ issue.status.RESOLVED=Resolved
issue.status.OPEN=Open
issue.status.CONFIRMED=Confirmed
issue.status.CLOSED=Closed
-issue.resolution.OPEN=Open
issue.resolution.FALSE-POSITIVE=False-positive
issue.resolution.FIXED=Fixed
+issue.resolution.REMOVED=Removed
issue.planned_for_x=Planned for {0}
issue.planned_for=Planned for
issue.manual.missing_rule=Missing rule
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java
index 8df79fd5c3a..bc062f6a0ce 100644
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java
+++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/IssueTrackingDecoratorTest.java
@@ -24,6 +24,7 @@ import org.junit.Test;
import org.mockito.ArgumentMatcher;
import org.sonar.api.batch.DecoratorContext;
import org.sonar.api.component.ResourcePerspectives;
+import org.sonar.api.profiles.RulesProfile;
import org.sonar.api.resources.File;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
@@ -54,7 +55,7 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase {
IssueUpdater updater = mock(IssueUpdater.class);
ResourcePerspectives perspectives = mock(ResourcePerspectives.class);
Date loadedDate = new Date();
- RuleFinder ruleFinder = mock(RuleFinder.class);
+ RulesProfile profile = mock(RulesProfile.class);
@Before
public void init() {
@@ -68,7 +69,7 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase {
updater,
mock(Project.class),
perspectives,
- ruleFinder);
+ profile);
}
@Test
@@ -170,7 +171,7 @@ public class IssueTrackingDecoratorTest extends AbstractDaoTestCase {
@Override
public boolean matches(Object o) {
DefaultIssue dead = (DefaultIssue) o;
- return "ABCDE".equals(dead.key()) && !dead.isNew() && !dead.isAlive();
+ return "ABCDE".equals(dead.key()) && !dead.isNew() && dead.isEndOfLife();
}
}));
}
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
index a020f13445b..56fb83bebe4 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
@@ -74,9 +74,11 @@ public class DefaultIssue implements Issue {
// true if the the issue did not exist in the previous scan.
private boolean isNew = true;
- // true if the the issue did exist in the previous scan but not in the current one. That means
+ // True if the the issue did exist in the previous scan but not in the current one. That means
// that this issue should be closed.
- private boolean isAlive = true;
+ private boolean endOfLife = false;
+
+ private boolean onDisabledRule = false;
// true if some fields have been changed since the previous scan
private boolean isChanged = false;
@@ -257,12 +259,21 @@ public class DefaultIssue implements Issue {
return this;
}
- public boolean isAlive() {
- return isAlive;
+ public boolean isEndOfLife() {
+ return endOfLife;
+ }
+
+ public DefaultIssue setEndOfLife(boolean b) {
+ endOfLife = b;
+ return this;
+ }
+
+ public boolean isOnDisabledRule() {
+ return onDisabledRule;
}
- public DefaultIssue setAlive(boolean b) {
- isAlive = b;
+ public DefaultIssue setOnDisabledRule(boolean b) {
+ onDisabledRule = b;
return this;
}
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 0546585f7aa..e3ec577a3ca 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
@@ -139,6 +139,9 @@ public class DefaultIssueBuilder implements Issuable.IssueBuilder {
issue.setAttributes(attributes);
issue.setResolution(null);
issue.setStatus(Issue.STATUS_OPEN);
+ issue.setNew(true);
+ issue.setEndOfLife(false);
+ issue.setOnDisabledRule(false);
return issue;
}
}
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/workflow/IsAlive.java b/sonar-core/src/main/java/org/sonar/core/issue/workflow/IsEndOfLife.java
index 7a3179c5cd0..741f7dbbd40 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/workflow/IsAlive.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/workflow/IsEndOfLife.java
@@ -22,16 +22,16 @@ package org.sonar.core.issue.workflow;
import org.sonar.api.issue.Issue;
import org.sonar.core.issue.DefaultIssue;
-class IsAlive implements Condition {
+class IsEndOfLife implements Condition {
- private final boolean alive;
+ private final boolean endOfLife;
- IsAlive(boolean alive) {
- this.alive = alive;
+ IsEndOfLife(boolean endOfLife) {
+ this.endOfLife = endOfLife;
}
@Override
public boolean matches(Issue issue) {
- return ((DefaultIssue) issue).isAlive() == alive;
+ return ((DefaultIssue) issue).isEndOfLife() == endOfLife;
}
}
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/workflow/IssueWorkflow.java b/sonar-core/src/main/java/org/sonar/core/issue/workflow/IssueWorkflow.java
index 4b4780f4122..f6b8dc2511d 100644
--- a/sonar-core/src/main/java/org/sonar/core/issue/workflow/IssueWorkflow.java
+++ b/sonar-core/src/main/java/org/sonar/core/issue/workflow/IssueWorkflow.java
@@ -81,7 +81,7 @@ public class IssueWorkflow implements BatchComponent, ServerComponent, Startable
.functions(new SetResolution(null), new SetCloseDate(false))
.build())
- // resolve as false-positive
+ // resolve as false-positive
.transition(Transition.builder(DefaultTransitions.FALSE_POSITIVE)
.from(Issue.STATUS_OPEN).to(Issue.STATUS_RESOLVED)
.conditions(new IsManual(false))
@@ -100,37 +100,37 @@ public class IssueWorkflow implements BatchComponent, ServerComponent, Startable
// automatic transitions
- // Close the issues that do not exist anymore. Note that isAlive() is true on manual issues
+ // Close the issues that do not exist anymore. Note that isEndOfLife() is false on manual issues
.transition(Transition.builder("automaticclose")
.from(Issue.STATUS_OPEN).to(Issue.STATUS_CLOSED)
- .conditions(new IsAlive(false))
- .functions(new SetResolution(Issue.RESOLUTION_FIXED), new SetCloseDate(true))
+ .conditions(new IsEndOfLife(true))
+ .functions(new SetEndOfLifeResolution(), new SetCloseDate(true))
.automatic()
.build())
.transition(Transition.builder("automaticclose")
.from(Issue.STATUS_REOPENED).to(Issue.STATUS_CLOSED)
- .conditions(new IsAlive(false))
- .functions(new SetResolution(Issue.RESOLUTION_FIXED), new SetCloseDate(true))
+ .conditions(new IsEndOfLife(true))
+ .functions(new SetEndOfLifeResolution(), new SetCloseDate(true))
.automatic()
.build())
.transition(Transition.builder("automaticclose")
.from(Issue.STATUS_CONFIRMED).to(Issue.STATUS_CLOSED)
- .conditions(new IsAlive(false))
- .functions(new SetResolution(Issue.RESOLUTION_FIXED), new SetCloseDate(true))
+ .conditions(new IsEndOfLife(true))
+ .functions(new SetEndOfLifeResolution(), new SetCloseDate(true))
.automatic()
.build())
// Close the issues marked as resolved and that do not exist anymore.
// Note that false-positives are kept resolved and are not closed.
.transition(Transition.builder("automaticclose")
.from(Issue.STATUS_RESOLVED).to(Issue.STATUS_CLOSED)
- .conditions(new IsAlive(false))
- .functions(new SetCloseDate(true))
+ .conditions(new IsEndOfLife(true))
+ .functions(new SetEndOfLifeResolution(), new SetCloseDate(true))
.automatic()
.build())
.transition(Transition.builder("automaticreopen")
.from(Issue.STATUS_RESOLVED).to(Issue.STATUS_REOPENED)
- .conditions(new IsAlive(true), new HasResolution(Issue.RESOLUTION_FIXED))
- .functions(new SetResolution(null))
+ .conditions(new IsEndOfLife(false), new HasResolution(Issue.RESOLUTION_FIXED))
+ .functions(new SetResolution(null), new SetCloseDate(false))
.automatic()
.build())
.build();
@@ -168,7 +168,7 @@ public class IssueWorkflow implements BatchComponent, ServerComponent, Startable
private State stateOf(DefaultIssue issue) {
State state = machine.state(issue.status());
- if (state==null) {
+ if (state == null) {
throw new IllegalStateException("Unknown status: " + issue.status() + " [issue=" + issue.key() + "]");
}
return state;
diff --git a/sonar-core/src/main/java/org/sonar/core/issue/workflow/SetEndOfLifeResolution.java b/sonar-core/src/main/java/org/sonar/core/issue/workflow/SetEndOfLifeResolution.java
new file mode 100644
index 00000000000..387e69f6aea
--- /dev/null
+++ b/sonar-core/src/main/java/org/sonar/core/issue/workflow/SetEndOfLifeResolution.java
@@ -0,0 +1,38 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.
+ */
+package org.sonar.core.issue.workflow;
+
+import org.sonar.api.issue.Issue;
+import org.sonar.core.issue.DefaultIssue;
+
+public class SetEndOfLifeResolution implements Function {
+ @Override
+ public void execute(Context context) {
+ DefaultIssue issue = (DefaultIssue) context.issue();
+ if (!issue.isEndOfLife()) {
+ throw new IllegalStateException("Issue is still alive: " + issue);
+ }
+ if (issue.isOnDisabledRule()) {
+ context.setResolution(Issue.RESOLUTION_REMOVED);
+ } else {
+ context.setResolution(Issue.RESOLUTION_FIXED);
+ }
+ }
+}
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/workflow/IsAliveTest.java b/sonar-core/src/test/java/org/sonar/core/issue/workflow/IsEndOfLifeTest.java
index 6bc1b4197e8..bcddc94c565 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/workflow/IsAliveTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/workflow/IsEndOfLifeTest.java
@@ -24,20 +24,20 @@ import org.sonar.core.issue.DefaultIssue;
import static org.fest.assertions.Assertions.assertThat;
-public class IsAliveTest {
+public class IsEndOfLifeTest {
DefaultIssue issue = new DefaultIssue();
@Test
- public void should_match_alive() throws Exception {
- IsAlive condition = new IsAlive(true);
- assertThat(condition.matches(issue.setAlive(true))).isTrue();
- assertThat(condition.matches(issue.setAlive(false))).isFalse();
+ public void should_be_end_of_life() throws Exception {
+ IsEndOfLife condition = new IsEndOfLife(true);
+ assertThat(condition.matches(issue.setEndOfLife(true))).isTrue();
+ assertThat(condition.matches(issue.setEndOfLife(false))).isFalse();
}
@Test
- public void should_match_dead() throws Exception {
- IsAlive condition = new IsAlive(false);
- assertThat(condition.matches(issue.setAlive(true))).isFalse();
- assertThat(condition.matches(issue.setAlive(false))).isTrue();
+ public void should_not_be_end_of_life() throws Exception {
+ IsEndOfLife condition = new IsEndOfLife(false);
+ assertThat(condition.matches(issue.setEndOfLife(true))).isFalse();
+ assertThat(condition.matches(issue.setEndOfLife(false))).isTrue();
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/workflow/IssueWorkflowTest.java b/sonar-core/src/test/java/org/sonar/core/issue/workflow/IssueWorkflowTest.java
index ae976307c3c..ec9375826b1 100644
--- a/sonar-core/src/test/java/org/sonar/core/issue/workflow/IssueWorkflowTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/issue/workflow/IssueWorkflowTest.java
@@ -114,7 +114,7 @@ public class IssueWorkflowTest {
.setResolution(Issue.RESOLUTION_FIXED)
.setStatus(Issue.STATUS_RESOLVED)
.setNew(false)
- .setAlive(false);
+ .setEndOfLife(true);
Date now = new Date();
workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FIXED);
@@ -132,7 +132,7 @@ public class IssueWorkflowTest {
.setResolution(null)
.setStatus(Issue.STATUS_OPEN)
.setNew(false)
- .setAlive(false);
+ .setEndOfLife(true);
Date now = new Date();
workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FIXED);
@@ -150,7 +150,7 @@ public class IssueWorkflowTest {
.setResolution(null)
.setStatus(Issue.STATUS_REOPENED)
.setNew(false)
- .setAlive(false);
+ .setEndOfLife(true);
Date now = new Date();
workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FIXED);
@@ -168,7 +168,7 @@ public class IssueWorkflowTest {
.setResolution(null)
.setStatus(Issue.STATUS_CONFIRMED)
.setNew(false)
- .setAlive(false);
+ .setEndOfLife(true);
Date now = new Date();
workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(now));
assertThat(issue.resolution()).isEqualTo(Issue.RESOLUTION_FIXED);
@@ -187,7 +187,7 @@ public class IssueWorkflowTest {
.setResolution(Issue.RESOLUTION_FIXED)
.setStatus("xxx")
.setNew(false)
- .setAlive(false);
+ .setEndOfLife(true);
try {
workflow.doAutomaticTransition(issue, IssueChangeContext.createScan(new Date()));
fail();
diff --git a/sonar-core/src/test/java/org/sonar/core/issue/workflow/SetEndOfLifeResolutionTest.java b/sonar-core/src/test/java/org/sonar/core/issue/workflow/SetEndOfLifeResolutionTest.java
new file mode 100644
index 00000000000..85268ab285d
--- /dev/null
+++ b/sonar-core/src/test/java/org/sonar/core/issue/workflow/SetEndOfLifeResolutionTest.java
@@ -0,0 +1,63 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 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.
+ */
+package org.sonar.core.issue.workflow;
+
+import org.junit.Test;
+import org.sonar.api.issue.Issue;
+import org.sonar.core.issue.DefaultIssue;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+import static org.mockito.Mockito.*;
+
+public class SetEndOfLifeResolutionTest {
+
+ Function.Context context = mock(Function.Context.class);
+ SetEndOfLifeResolution function = new SetEndOfLifeResolution();
+
+ @Test
+ public void should_resolve_as_fixed() throws Exception {
+ Issue issue = new DefaultIssue().setEndOfLife(true).setOnDisabledRule(false);
+ when(context.issue()).thenReturn(issue);
+ function.execute(context);
+ verify(context, times(1)).setResolution(Issue.RESOLUTION_FIXED);
+ }
+
+ @Test
+ public void should_resolve_as_removed_when_rule_is_disabled() throws Exception {
+ Issue issue = new DefaultIssue().setEndOfLife(true).setOnDisabledRule(true);
+ when(context.issue()).thenReturn(issue);
+ function.execute(context);
+ verify(context, times(1)).setResolution(Issue.RESOLUTION_REMOVED);
+ }
+
+ @Test
+ public void should_fail_if_issue_is_not_resolved() throws Exception {
+ Issue issue = new DefaultIssue().setEndOfLife(false);
+ when(context.issue()).thenReturn(issue);
+ try {
+ function.execute(context);
+ fail();
+ } catch (IllegalStateException e) {
+ assertThat(e.getMessage()).contains("Issue is still alive");
+ verify(context, never()).setResolution(anyString());
+ }
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java
index a517eaa7111..7f0fab7d2d2 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/Issue.java
@@ -44,8 +44,9 @@ public interface Issue extends Serializable {
String RESOLUTION_FIXED = "FIXED";
String RESOLUTION_FALSE_POSITIVE = "FALSE-POSITIVE";
+ String RESOLUTION_REMOVED = "REMOVED";
- List<String> RESOLUTIONS = ImmutableList.of(RESOLUTION_FALSE_POSITIVE, RESOLUTION_FIXED);
+ List<String> RESOLUTIONS = ImmutableList.of(RESOLUTION_FALSE_POSITIVE, RESOLUTION_FIXED, RESOLUTION_REMOVED);
/**
* Unique generated key
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueHandler.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueHandler.java
index 8835ddfba8f..12f4a5c3fdd 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueHandler.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueHandler.java
@@ -33,8 +33,7 @@ public interface IssueHandler extends BatchExtension {
boolean isNew();
- // TODO rename isClosed()
- boolean isAlive();
+ boolean isEndOfLife();
Context setLine(@Nullable Integer i);