Skip to content

Commit 3fb805e

Browse files
PLUGINAPI-72 Deprecate 'status' and 'resolution' in favor of 'issueStatus'
1 parent 4b414a9 commit 3fb805e

File tree

7 files changed

+260
-5
lines changed

7 files changed

+260
-5
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Changelog
22

3+
## 10.5
4+
5+
* Introduce `org.sonar.api.issue.IssueStatus` to simplify `status` and `resolution` on issues.
6+
* Deprecate `org.sonar.api.ce.measure.Issue.status()` and `org.sonar.api.ce.measure.Issue.resolution()`. Use `org.sonar.api.ce.measure.Issue.issueStatus()` method instead.
7+
* Deprecate `org.sonar.api.issue.Issue.status()` and `org.sonar.api.issue.Issue.resolution()`. No replacement.
8+
* Deprecate `STATUS_OPEN`, `STATUS_CONFIRMED`, `STATUS_REOPENED`, `STATUS_RESOLVED`, `STATUS_CLOSED`,
9+
`RESOLUTION_FIXED`, `RESOLUTION_FALSE_POSITIVE`, `RESOLUTION_REMOVED`, `RESOLUTION_WONT_FIX`, use `org.sonar.api.issue.IssueStatus` enum instead
10+
* Deprecate `RESOLUTION_SAFE`, `RESOLUTION_ACKNOWLEDGED`, `STATUS_TO_REVIEW`, `STATUS_REVIEWED`. No replacement.
11+
312
## 10.4
413

514
* Add new metrics `org.sonar.api.measures.CoreMetrics.NEW_ACCEPTED_ISSUES` and `org.sonar.api.measures.CoreMetrics.HIGH_IMPACT_ACCEPTED_ISSUES`.

plugin-api/src/main/java/org/sonar/api/ce/measure/Issue.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import java.util.Map;
2323
import javax.annotation.CheckForNull;
24+
import org.sonar.api.issue.IssueStatus;
2425
import org.sonar.api.issue.impact.Severity;
2526
import org.sonar.api.issue.impact.SoftwareQuality;
2627
import org.sonar.api.rule.RuleKey;
@@ -40,15 +41,27 @@ public interface Issue {
4041

4142
/**
4243
* Available list of status can be found in {@link org.sonar.api.issue.Issue#STATUSES}
44+
*
45+
* @deprecated since 10.4 in favor of {@link Issue#issueStatus()}
4346
*/
47+
@Deprecated(since = "10.4")
4448
String status();
4549

4650
/**
4751
* Available list of resolutions can be found in {@link org.sonar.api.issue.Issue#RESOLUTIONS}
52+
*
53+
* @deprecated since 10.4 in favor of {@link Issue#issueStatus()}
4854
*/
4955
@CheckForNull
56+
@Deprecated(since = "10.4")
5057
String resolution();
5158

59+
/**
60+
* @since 10.4
61+
* Available list of status can be found in {@link IssueStatus#values()}
62+
*/
63+
IssueStatus issueStatus();
64+
5265
/**
5366
* See constants in {@link org.sonar.api.rule.Severity}.
5467
* @deprecated since 10.1, use {@link #impacts()} instead

plugin-api/src/main/java/org/sonar/api/issue/Issue.java

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -46,69 +46,114 @@ public interface Issue extends Serializable {
4646

4747
/**
4848
* Default status when creating an issue.
49+
*
50+
* @deprecated since 10.4 in favor of {@link IssueStatus}
4951
*/
52+
@Deprecated(since = "10.4")
5053
String STATUS_OPEN = "OPEN";
54+
/**
55+
* @deprecated since 10.4 in favor of {@link IssueStatus}
56+
*/
57+
@Deprecated(since = "10.4")
5158
String STATUS_CONFIRMED = "CONFIRMED";
59+
/**
60+
* @deprecated since 10.4 in favor of {@link IssueStatus}
61+
*/
62+
@Deprecated(since = "10.4")
5263
String STATUS_REOPENED = "REOPENED";
64+
/**
65+
* @deprecated since 10.4 in favor of {@link IssueStatus}
66+
*/
67+
@Deprecated(since = "10.4")
5368
String STATUS_RESOLVED = "RESOLVED";
69+
/**
70+
* @deprecated since 10.4 in favor of {@link IssueStatus}
71+
*/
5472
String STATUS_CLOSED = "CLOSED";
55-
73+
/**
74+
* @deprecated since 10.4 in favor of {@link IssueStatus}
75+
*/
76+
@Deprecated(since = "10.4")
5677
String RESOLUTION_FIXED = "FIXED";
5778

5879
/**
5980
* Resolution when issue is flagged as false positive.
6081
*/
82+
/**
83+
* @deprecated since 10.4 in favor of {@link IssueStatus}
84+
*/
85+
@Deprecated(since = "10.4")
6186
String RESOLUTION_FALSE_POSITIVE = "FALSE-POSITIVE";
6287

6388
/**
6489
* Resolution when rule has been uninstalled or disabled in the Quality profile.
65-
*/
90+
* @deprecated since 10.4 in favor of {@link IssueStatus}
91+
*/
92+
@Deprecated(since = "10.4")
6693
String RESOLUTION_REMOVED = "REMOVED";
6794

6895
/**
6996
* Issue is irrelevant in the context and was muted by user.
97+
* @deprecated since 10.4 in favor of {@link IssueStatus}
7098
* @since 5.1
7199
*/
100+
@Deprecated(since = "10.4")
72101
String RESOLUTION_WONT_FIX = "WONTFIX";
73102

74103
/**
75104
* Security Hotspot has been reviewed and resolved as safe.
105+
* @deprecated since 10.4 as Security Hotspot are deprecated.
76106
* @since 8.1
77107
*/
108+
@Deprecated(since = "10.4")
78109
String RESOLUTION_SAFE = "SAFE";
79110

80111
/**
81112
* Security Hotspot has been reviewed and acknowledged that it poses a risk.
113+
* @deprecated since 10.4 as Security Hotspot are deprecated.
82114
* @since 9.4
83115
*/
116+
@Deprecated(since = "10.4")
84117
String RESOLUTION_ACKNOWLEDGED = "ACKNOWLEDGED";
85118

119+
/**
120+
* @deprecated since 10.4 in favor of {@link IssueStatus}
121+
*/
122+
@Deprecated(since = "10.4")
86123
List<String> RESOLUTIONS = List.of(RESOLUTION_FALSE_POSITIVE, RESOLUTION_WONT_FIX, RESOLUTION_FIXED,
87124
RESOLUTION_REMOVED);
88125

126+
/**
127+
* @deprecated since 10.4 as Security Hotspot are deprecated
128+
*/
129+
@Deprecated(since = "10.4")
89130
List<String> SECURITY_HOTSPOT_RESOLUTIONS = List.of(RESOLUTION_FIXED, RESOLUTION_SAFE, RESOLUTION_ACKNOWLEDGED);
90131

91132
/**
92-
* @since 7.8
133+
* @deprecated since 10.4 as Security Hotspot are deprecated
93134
*/
135+
@Deprecated(since = "10.4")
94136
String STATUS_TO_REVIEW = "TO_REVIEW";
95137

96138
/**
97139
* @deprecated since 8.1, status has been mapped as `TO_REVIEW`
98140
*/
99-
@Deprecated
141+
@Deprecated(since = "8.1")
100142
String STATUS_IN_REVIEW = "IN_REVIEW";
101143

102144
/**
103-
* @since 7.8
145+
* @deprecated since 10.4 as Security Hotspot are deprecated
104146
*/
147+
@Deprecated(since = "10.4")
105148
String STATUS_REVIEWED = "REVIEWED";
106149

107150
/**
108151
* Return all available statuses
109152
*
110153
* @since 4.4
154+
* @deprecated since 10.4 in favor of {@link IssueStatus}
111155
*/
156+
@Deprecated(since = "10.4")
112157
List<String> STATUSES = List.of(STATUS_OPEN, STATUS_CONFIRMED, STATUS_REOPENED, STATUS_RESOLVED, STATUS_CLOSED,
113158
STATUS_TO_REVIEW, STATUS_REVIEWED);
114159

@@ -161,13 +206,17 @@ public interface Issue extends Serializable {
161206

162207
/**
163208
* See constant values in {@link Issue}.
209+
* @deprecated since 10.4 in favor of {@link IssueStatus}
164210
*/
211+
@Deprecated(since = "10.4")
165212
String status();
166213

167214
/**
168215
* The type of resolution, or null if the issue is not resolved. See constant values in {@link Issue}.
216+
* @deprecated since 10.4 in favor of {@link IssueStatus}
169217
*/
170218
@CheckForNull
219+
@Deprecated(since = "10.4")
171220
String resolution();
172221

173222
/**
@@ -212,13 +261,15 @@ public interface Issue extends Serializable {
212261

213262
/**
214263
* During a scan return if the current issue is a new one.
264+
*
215265
* @return always false on server side
216266
* @since 4.0
217267
*/
218268
boolean isNew();
219269

220270
/**
221271
* During a scan returns true if the issue is copied from another branch.
272+
*
222273
* @since 6.6
223274
*/
224275
boolean isCopied();
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Sonar Plugin API
3+
* Copyright (C) 2009-2024 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.api.issue;
21+
22+
import javax.annotation.CheckForNull;
23+
import javax.annotation.Nullable;
24+
import org.slf4j.Logger;
25+
import org.slf4j.LoggerFactory;
26+
27+
/**
28+
* @since 10.4
29+
*/
30+
public enum IssueStatus {
31+
32+
33+
OPEN,
34+
35+
@Deprecated(since = "10.4")
36+
/**
37+
* @deprecated use {@link IssueStatus#ACCEPTED} instead
38+
*/
39+
CONFIRMED,
40+
FALSE_POSITIVE,
41+
ACCEPTED,
42+
FIXED;
43+
44+
private static final Logger LOGGER = LoggerFactory.getLogger(IssueStatus.class);
45+
46+
@CheckForNull
47+
public static IssueStatus of(@Nullable String status, @Nullable String resolution) {
48+
49+
//null status is not supposed to happen, but since it is nullable in products, we want the mapping to be resilient.
50+
if (status == null) {
51+
LOGGER.warn("Missing status, falling back to {}", IssueStatus.OPEN);
52+
return IssueStatus.OPEN;
53+
}
54+
55+
switch (status) {
56+
case Issue.STATUS_OPEN:
57+
case Issue.STATUS_REOPENED:
58+
return IssueStatus.OPEN;
59+
case Issue.STATUS_CONFIRMED:
60+
return IssueStatus.CONFIRMED;
61+
case Issue.STATUS_CLOSED:
62+
return IssueStatus.FIXED;
63+
// Security hotspot should not return issue status as they are deprecated.
64+
case Issue.STATUS_REVIEWED:
65+
case Issue.STATUS_TO_REVIEW:
66+
return null;
67+
default:
68+
}
69+
if (Issue.STATUS_RESOLVED.equals(status) && resolution != null) {
70+
switch (resolution) {
71+
case Issue.RESOLUTION_FALSE_POSITIVE:
72+
return IssueStatus.FALSE_POSITIVE;
73+
case Issue.RESOLUTION_WONT_FIX:
74+
return IssueStatus.ACCEPTED;
75+
case Issue.RESOLUTION_FIXED:
76+
return IssueStatus.FIXED;
77+
default:
78+
}
79+
}
80+
81+
82+
LOGGER.warn("Can't find mapped issue status for status '{}' and resolution '{}'", status, resolution);
83+
return null;
84+
}
85+
}
86+
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
/*
2+
* Sonar Plugin API
3+
* Copyright (C) 2009-2024 SonarSource SA
4+
* mailto:info AT sonarsource DOT com
5+
*
6+
* This program is free software; you can redistribute it and/or
7+
* modify it under the terms of the GNU Lesser General Public
8+
* License as published by the Free Software Foundation; either
9+
* version 3 of the License, or (at your option) any later version.
10+
*
11+
* This program is distributed in the hope that it will be useful,
12+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14+
* Lesser General Public License for more details.
15+
*
16+
* You should have received a copy of the GNU Lesser General Public License
17+
* along with this program; if not, write to the Free Software Foundation,
18+
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19+
*/
20+
package org.sonar.api.issue;
21+
22+
import org.junit.Rule;
23+
import org.junit.Test;
24+
import org.sonar.api.testfixtures.log.LogAndArguments;
25+
import org.sonar.api.testfixtures.log.LogTester;
26+
27+
import static org.assertj.core.api.Assertions.assertThat;
28+
29+
public class IssueStatusTest {
30+
@Rule
31+
public LogTester logTester = new LogTester();
32+
33+
@Test
34+
public void of_shouldMapToCorrectIssueStatus() {
35+
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_FIXED))
36+
.isEqualTo(IssueStatus.FIXED);
37+
38+
assertThat(IssueStatus.of(Issue.STATUS_CONFIRMED, null))
39+
.isEqualTo(IssueStatus.CONFIRMED);
40+
41+
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_FALSE_POSITIVE))
42+
.isEqualTo(IssueStatus.FALSE_POSITIVE);
43+
44+
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX))
45+
.isEqualTo(IssueStatus.ACCEPTED);
46+
47+
assertThat(IssueStatus.of(Issue.STATUS_REOPENED, null))
48+
.isEqualTo(IssueStatus.OPEN);
49+
50+
assertThat(IssueStatus.of(Issue.STATUS_CLOSED, null))
51+
.isEqualTo(IssueStatus.FIXED);
52+
}
53+
54+
@Test
55+
public void of_shouldReturnNull_whenStatusBelongsToHotspot() {
56+
assertThat(IssueStatus.of(Issue.STATUS_TO_REVIEW, null))
57+
.isNull();
58+
59+
assertThat(IssueStatus.of(Issue.STATUS_REVIEWED, Issue.RESOLUTION_SAFE))
60+
.isNull();
61+
62+
assertThat(IssueStatus.of(Issue.STATUS_REVIEWED, Issue.RESOLUTION_ACKNOWLEDGED))
63+
.isNull();
64+
}
65+
66+
@Test
67+
public void of_shouldLogWarning_whenUnknownMapping() {
68+
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, null)).isNull();
69+
assertThat(logTester.getLogs()).extracting(LogAndArguments::getFormattedMsg).contains("Can't find mapped issue status for status 'RESOLVED' and resolution 'null'");
70+
71+
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_SAFE)).isNull();
72+
assertThat(logTester.getLogs()).extracting(LogAndArguments::getFormattedMsg).contains("Can't find mapped issue status for status 'RESOLVED' and resolution 'SAFE'");
73+
}
74+
75+
@Test
76+
public void of_shouldLogWarning_whenStatusIsNull() {
77+
assertThat(IssueStatus.of(null, null)).isEqualTo(IssueStatus.OPEN);
78+
assertThat(logTester.getLogs()).extracting(LogAndArguments::getFormattedMsg).contains("Missing status, falling back to OPEN");
79+
}
80+
81+
}

0 commit comments

Comments
 (0)