Browse Source

SONAR-20877 Update naming to issueStatus

tags/10.4.0.87286
Léo Geoffroy 6 months ago
parent
commit
9f451cb3fb
75 changed files with 430 additions and 445 deletions
  1. 4
    4
      server/sonar-db-dao/src/main/java/org/sonar/db/issue/IndexedIssueDto.java
  2. 4
    4
      server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java
  3. 6
    6
      server/sonar-db-dao/src/test/java/org/sonar/db/issue/IndexedIssueDtoTest.java
  4. 8
    9
      server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueDtoTest.java
  5. 1
    1
      server/sonar-server-common/src/it/java/org/sonar/server/issue/index/IssueIndexerIT.java
  6. 2
    2
      server/sonar-server-common/src/it/java/org/sonar/server/issue/index/IssueIteratorFactoryIT.java
  7. 8
    8
      server/sonar-server-common/src/main/java/org/sonar/server/issue/IssueFieldsSetter.java
  8. 5
    5
      server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java
  9. 4
    4
      server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java
  10. 2
    2
      server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java
  11. 1
    1
      server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java
  12. 5
    5
      server/sonar-server-common/src/main/java/org/sonar/server/issue/workflow/IssueWorkflow.java
  13. 13
    13
      server/sonar-server-common/src/test/java/org/sonar/server/issue/IssueFieldsSetterTest.java
  14. 20
    21
      server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts
  15. 5
    5
      server/sonar-web/src/main/js/api/mocks/data/issues.ts
  16. 6
    4
      server/sonar-web/src/main/js/api/mocks/data/measures.ts
  17. 2
    2
      server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
  18. 5
    5
      server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx
  19. 2
    2
      server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-Filtering-it.tsx
  20. 36
    45
      server/sonar-web/src/main/js/apps/issues/__tests__/utils-test.ts
  21. 2
    2
      server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetGroupViewer.tsx
  22. 2
    2
      server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx
  23. 19
    20
      server/sonar-web/src/main/js/apps/issues/sidebar/IssueStatusFacet.tsx
  24. 6
    6
      server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx
  25. 3
    3
      server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx
  26. 4
    4
      server/sonar-web/src/main/js/apps/issues/test-utils.tsx
  27. 34
    33
      server/sonar-web/src/main/js/apps/issues/utils.ts
  28. 2
    2
      server/sonar-web/src/main/js/apps/overview/components/__tests__/BranchQualityGate-it.tsx
  29. 2
    2
      server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/__snapshots__/loadIssues-test.ts.snap
  30. 9
    9
      server/sonar-web/src/main/js/components/icons/IssueStatusIcon.tsx
  31. 7
    7
      server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx
  32. 4
    4
      server/sonar-web/src/main/js/components/issue/components/IssueTransition.tsx
  33. 5
    5
      server/sonar-web/src/main/js/components/shared/StatusHelper.tsx
  34. 2
    2
      server/sonar-web/src/main/js/components/shared/__tests__/utils-test.ts
  35. 6
    6
      server/sonar-web/src/main/js/components/shared/utils.ts
  36. 7
    7
      server/sonar-web/src/main/js/helpers/constants.ts
  37. 9
    9
      server/sonar-web/src/main/js/helpers/issues.ts
  38. 1
    1
      server/sonar-web/src/main/js/helpers/mocks/issues.ts
  39. 5
    5
      server/sonar-web/src/main/js/helpers/testMocks.ts
  40. 3
    3
      server/sonar-web/src/main/js/types/issues.ts
  41. 2
    2
      server/sonar-web/src/main/js/types/types.ts
  42. 7
    7
      server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java
  43. 7
    7
      server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java
  44. 1
    1
      server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java
  45. 14
    14
      server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFacetsTest.java
  46. 15
    15
      server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java
  47. 19
    19
      server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SearchActionIT.java
  48. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/AddCommentAction.java
  49. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/AssignAction.java
  50. 1
    1
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ChangelogAction.java
  51. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DeleteCommentAction.java
  52. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java
  53. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/EditCommentAction.java
  54. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ListAction.java
  55. 14
    14
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java
  56. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java
  57. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java
  58. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTagsAction.java
  59. 2
    2
      server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java
  60. 1
    1
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/add_comment-example.json
  61. 1
    1
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/assign-example.json
  62. 1
    1
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/delete_comment-example.json
  63. 1
    1
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/do_transition-example.json
  64. 1
    1
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/edit_comment-example.json
  65. 1
    1
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/search-example.json
  66. 1
    1
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/set_severity-example.json
  67. 1
    1
      server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/set_type-example.json
  68. 3
    3
      server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchResponseFormatFormatOperationTest.java
  69. 3
    3
      sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java
  70. 11
    11
      sonar-core/src/main/java/org/sonar/core/issue/status/IssueStatus.java
  71. 6
    12
      sonar-core/src/main/resources/org/sonar/l10n/core.properties
  72. 5
    5
      sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java
  73. 21
    21
      sonar-core/src/test/java/org/sonar/core/issue/status/IssueStatusTest.java
  74. 1
    1
      sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java
  75. 1
    1
      sonar-ws/src/main/protobuf/ws-issues.proto

+ 4
- 4
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IndexedIssueDto.java View File

@@ -28,7 +28,7 @@ import java.util.Set;
import javax.annotation.CheckForNull;
import org.sonar.api.issue.impact.Severity;
import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;

import static com.google.common.base.Preconditions.checkArgument;

@@ -123,9 +123,9 @@ public final class IndexedIssueDto {
}

@CheckForNull
public String getSimpleStatus() {
checkArgument(status != null, "Status must be initialized to retrieve simple status");
return Optional.ofNullable(SimpleStatus.of(status, resolution)).map(SimpleStatus::name).orElse(null);
public String getIssueStatus() {
checkArgument(status != null, "Status must be initialized to retrieve issue status");
return Optional.ofNullable(IssueStatus.of(status, resolution)).map(IssueStatus::name).orElse(null);
}

public Long getEffort() {

+ 4
- 4
server/sonar-db-dao/src/main/java/org/sonar/db/issue/IssueDto.java View File

@@ -44,7 +44,7 @@ import org.sonar.api.rules.CleanCodeAttribute;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.core.util.Uuids;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.protobuf.DbIssues;
@@ -363,9 +363,9 @@ public final class IssueDto implements Serializable {
return status;
}

public SimpleStatus getSimpleStatus() {
checkArgument(status != null, "Status must be initialized to retrieve simple status");
return SimpleStatus.of(status, resolution);
public IssueStatus getIssueStatus() {
checkArgument(status != null, "Status must be initialized to retrieve issue status");
return IssueStatus.of(status, resolution);
}

public IssueDto setStatus(@Nullable String s) {

+ 6
- 6
server/sonar-db-dao/src/test/java/org/sonar/db/issue/IndexedIssueDtoTest.java View File

@@ -24,7 +24,7 @@ import org.junit.Test;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.impact.Severity;
import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -92,17 +92,17 @@ public class IndexedIssueDtoTest {
}

@Test
public void getSimpleStatus_shouldReturnSimpleStatusFromStatusAndResolution() {
public void getIssueStatus_shouldReturnIssueStatusFromStatusAndResolution() {
IndexedIssueDto issue1 = new IndexedIssueDto().setStatus(Issue.STATUS_OPEN);
IndexedIssueDto issue2 = new IndexedIssueDto().setStatus(Issue.STATUS_RESOLVED).setResolution(Issue.RESOLUTION_WONT_FIX);
IndexedIssueDto issue3 = new IndexedIssueDto().setStatus(Issue.STATUS_CLOSED).setResolution(Issue.RESOLUTION_FIXED);

assertThat(Set.of(issue1, issue2, issue3)).extracting(IndexedIssueDto::getSimpleStatus)
.containsExactlyInAnyOrder(SimpleStatus.OPEN.name(), SimpleStatus.ACCEPTED.name(), SimpleStatus.FIXED.name());
assertThat(Set.of(issue1, issue2, issue3)).extracting(IndexedIssueDto::getIssueStatus)
.containsExactlyInAnyOrder(IssueStatus.OPEN.name(), IssueStatus.ACCEPTED.name(), IssueStatus.FIXED.name());
IndexedIssueDto issueWithStatusNull = new IndexedIssueDto();
assertThatThrownBy(issueWithStatusNull::getSimpleStatus)
assertThatThrownBy(issueWithStatusNull::getIssueStatus)
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Status must be initialized to retrieve simple status");
.hasMessage("Status must be initialized to retrieve issue status");
}

}

+ 8
- 9
server/sonar-db-dao/src/test/java/org/sonar/db/issue/IssueDtoTest.java View File

@@ -27,7 +27,6 @@ import java.util.Date;
import java.util.List;
import java.util.Set;
import org.apache.commons.lang.time.DateUtils;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import org.sonar.api.issue.Issue;
import org.sonar.api.issue.impact.Severity;
@@ -37,7 +36,7 @@ import org.sonar.api.rules.CleanCodeAttribute;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.db.protobuf.DbIssues;
import org.sonar.db.rule.RuleDto;
@@ -345,26 +344,26 @@ public class IssueDtoTest {
}

@Test
public void getSimpleStatus_shouldReturnExpectedValueFromStatusAndResolution(){
public void getIssueStatus_shouldReturnExpectedValueFromStatusAndResolution() {
IssueDto dto = new IssueDto();
dto.setStatus(Issue.STATUS_CLOSED);
assertThat(dto.getSimpleStatus()).isEqualTo(SimpleStatus.FIXED);
assertThat(dto.getIssueStatus()).isEqualTo(IssueStatus.FIXED);

dto.setStatus(Issue.STATUS_RESOLVED);
dto.setResolution(Issue.RESOLUTION_FALSE_POSITIVE);
assertThat(dto.getSimpleStatus()).isEqualTo(SimpleStatus.FALSE_POSITIVE);
assertThat(dto.getIssueStatus()).isEqualTo(IssueStatus.FALSE_POSITIVE);

dto.setStatus(Issue.STATUS_RESOLVED);
dto.setResolution(Issue.RESOLUTION_WONT_FIX);
assertThat(dto.getSimpleStatus()).isEqualTo(SimpleStatus.ACCEPTED);
assertThat(dto.getIssueStatus()).isEqualTo(IssueStatus.ACCEPTED);
}

@Test
public void getSimpleStatus_shouldThrowException_whenStatusIsNotInitialized(){
public void getIssueStatus_shouldThrowException_whenStatusIsNotInitialized() {
IssueDto dto = new IssueDto();
assertThatThrownBy(dto::getSimpleStatus)
assertThatThrownBy(dto::getIssueStatus)
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Status must be initialized to retrieve simple status");
.hasMessage("Status must be initialized to retrieve issue status");
}

private DefaultIssue createExampleDefaultIssue(Date dateNow) {

+ 1
- 1
server/sonar-server-common/src/it/java/org/sonar/server/issue/index/IssueIndexerIT.java View File

@@ -153,7 +153,7 @@ public class IssueIndexerIT {
.containsExactlyInAnyOrder(Map.of(
SUB_FIELD_SOFTWARE_QUALITY, SoftwareQuality.MAINTAINABILITY.name(),
SUB_FIELD_SEVERITY, Severity.HIGH.name()));
assertThat(doc.simpleStatus()).isEqualTo(issue.getSimpleStatus().name());
assertThat(doc.issueStatus()).isEqualTo(issue.getIssueStatus().name());
}

@Test

+ 2
- 2
server/sonar-server-common/src/it/java/org/sonar/server/issue/index/IssueIteratorFactoryIT.java View File

@@ -28,7 +28,7 @@ import java.util.stream.Stream;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.utils.System2;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ProjectData;
@@ -82,7 +82,7 @@ public class IssueIteratorFactoryIT {
assertThat(issue.key()).isEqualTo(expected.getKey());
assertThat(issue.resolution()).isEqualTo("FIXED");
assertThat(issue.status()).isEqualTo("RESOLVED");
assertThat(issue.simpleStatus()).isEqualTo(SimpleStatus.FIXED.name());
assertThat(issue.issueStatus()).isEqualTo(IssueStatus.FIXED.name());
assertThat(issue.severity()).isEqualTo("BLOCKER");
assertThat(issue.assigneeUuid()).isEqualTo("uuid-of-guy1");
assertThat(issue.authorLogin()).isEqualTo("guy2");

+ 8
- 8
server/sonar-server-common/src/main/java/org/sonar/server/issue/IssueFieldsSetter.java View File

@@ -41,7 +41,7 @@ import org.sonar.api.utils.Duration;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.DefaultIssueComment;
import org.sonar.core.issue.IssueChangeContext;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.db.protobuf.DbIssues;
import org.sonar.db.user.UserDto;
import org.sonar.db.user.UserIdDto;
@@ -64,16 +64,16 @@ public class IssueFieldsSetter {
public static final String ASSIGNEE = "assignee";

/**
* @deprecated use {@link IssueFieldsSetter#SIMPLE_STATUS} instead
* @deprecated use {@link IssueFieldsSetter#ISSUE_STATUS} instead
*/
@Deprecated(since = "10.4")
public static final String RESOLUTION = "resolution";
/**
* @deprecated use {@link IssueFieldsSetter#SIMPLE_STATUS} instead
* @deprecated use {@link IssueFieldsSetter#ISSUE_STATUS} instead
*/
@Deprecated(since = "10.4")
public static final String STATUS = "status";
public static final String SIMPLE_STATUS = "simpleStatus";
public static final String ISSUE_STATUS = "issueStatus";
public static final String AUTHOR = "author";
public static final String FILE = "file";
public static final String FROM_BRANCH = "from_branch";
@@ -260,10 +260,10 @@ public class IssueFieldsSetter {
return false;
}

public boolean setSimpleStatus(DefaultIssue issue, @Nullable SimpleStatus previousSimpleStatus, @Nullable SimpleStatus newSimpleStatus, IssueChangeContext context) {
if (!Objects.equals(newSimpleStatus, previousSimpleStatus)) {
//Currently, simple status is not persisted in database, but is considered as an issue change
issue.setFieldChange(context, SIMPLE_STATUS, previousSimpleStatus, issue.getSimpleStatus());
public boolean setIssueStatus(DefaultIssue issue, @Nullable IssueStatus previousIssueStatus, @Nullable IssueStatus newIssueStatus, IssueChangeContext context) {
if (!Objects.equals(newIssueStatus, previousIssueStatus)) {
//Currently, issue status is not persisted in database, but is considered as an issue change
issue.setFieldChange(context, ISSUE_STATUS, previousIssueStatus, issue.getIssueStatus());
return true;
}
return false;

+ 5
- 5
server/sonar-server-common/src/main/java/org/sonar/server/issue/SearchRequest.java View File

@@ -61,7 +61,7 @@ public class SearchRequest {
private List<String> impactSoftwareQualities;
private List<String> cleanCodeAttributesCategories;
private List<String> statuses;
private List<String> simpleStatuses;
private List<String> issueStatuses;
private List<String> tags;
private Set<String> types;
private List<String> pciDss32;
@@ -338,14 +338,14 @@ public class SearchRequest {
return this;
}

public SearchRequest setSimpleStatuses(@Nullable List<String> simpleStatuses) {
this.simpleStatuses = simpleStatuses;
public SearchRequest setIssueStatuses(@Nullable List<String> issueStatuses) {
this.issueStatuses = issueStatuses;
return this;
}

@CheckForNull
public List<String> getSimpleStatuses() {
return simpleStatuses;
public List<String> getIssueStatuses() {
return issueStatuses;
}

@CheckForNull

+ 4
- 4
server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueDoc.java View File

@@ -113,8 +113,8 @@ public class IssueDoc extends BaseDoc {
}

@CheckForNull
public String simpleStatus() {
return getNullableField(IssueIndexDefinition.FIELD_ISSUE_SIMPLE_STATUS);
public String issueStatus() {
return getNullableField(IssueIndexDefinition.FIELD_ISSUE_NEW_STATUS);
}

@CheckForNull
@@ -241,8 +241,8 @@ public class IssueDoc extends BaseDoc {
return this;
}

public IssueDoc setSimpleStatus(String s) {
setField(IssueIndexDefinition.FIELD_ISSUE_SIMPLE_STATUS, s);
public IssueDoc setIssueStatus(String s) {
setField(IssueIndexDefinition.FIELD_ISSUE_NEW_STATUS, s);
return this;
}


+ 2
- 2
server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIndexDefinition.java View File

@@ -86,7 +86,7 @@ public class IssueIndexDefinition implements IndexDefinition {
public static final String FIELD_ISSUE_SEVERITY = "severity";
public static final String FIELD_ISSUE_SEVERITY_VALUE = "severityValue";
public static final String FIELD_ISSUE_STATUS = "status";
public static final String FIELD_ISSUE_SIMPLE_STATUS = "simpleStatus";
public static final String FIELD_ISSUE_NEW_STATUS = "issueStatus";
public static final String FIELD_ISSUE_TAGS = "tags";
public static final String FIELD_ISSUE_TYPE = "type";
public static final String FIELD_ISSUE_PCI_DSS_32 = "pciDss-3.2";
@@ -161,7 +161,7 @@ public class IssueIndexDefinition implements IndexDefinition {
mapping.createBooleanField(FIELD_ISSUE_IS_MAIN_BRANCH);
mapping.keywordFieldBuilder(FIELD_ISSUE_DIRECTORY_PATH).disableNorms().build();
mapping.keywordFieldBuilder(FIELD_ISSUE_RESOLUTION).disableNorms().build();
mapping.keywordFieldBuilder(FIELD_ISSUE_SIMPLE_STATUS).disableNorms().build();
mapping.keywordFieldBuilder(FIELD_ISSUE_NEW_STATUS).disableNorms().build();
mapping.keywordFieldBuilder(FIELD_ISSUE_RULE_UUID).disableNorms().build();
mapping.keywordFieldBuilder(FIELD_ISSUE_SEVERITY).disableNorms().build();
mapping.createByteField(FIELD_ISSUE_SEVERITY_VALUE);

+ 1
- 1
server/sonar-server-common/src/main/java/org/sonar/server/issue/index/IssueIteratorForSingleChunk.java View File

@@ -96,7 +96,7 @@ class IssueIteratorForSingleChunk implements IssueIterator {
.orElse(null);
doc.setCleanCodeAttributeCategory(cleanCodeAttributeCategory);
doc.setStatus(indexedIssueDto.getStatus());
doc.setSimpleStatus(indexedIssueDto.getSimpleStatus());
doc.setIssueStatus(indexedIssueDto.getIssueStatus());
doc.setEffort(indexedIssueDto.getEffort());
doc.setAuthorLogin(indexedIssueDto.getAuthorLogin());


+ 5
- 5
server/sonar-server-common/src/main/java/org/sonar/server/issue/workflow/IssueWorkflow.java View File

@@ -29,7 +29,7 @@ import org.sonar.api.server.ServerSide;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.IssueChangeContext;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.server.issue.IssueFieldsSetter;

import static com.google.common.base.Preconditions.checkArgument;
@@ -331,10 +331,10 @@ public class IssueWorkflow implements Startable {
public boolean doManualTransition(DefaultIssue issue, String transitionKey, IssueChangeContext issueChangeContext) {
Transition transition = stateOf(issue).transition(transitionKey);
if (transition.supports(issue) && !transition.automatic()) {
SimpleStatus previousSimpleStatus = issue.getSimpleStatus();
IssueStatus previousIssueStatus = issue.getIssueStatus();
functionExecutor.execute(transition.functions(), issue, issueChangeContext);
updater.setStatus(issue, transition.to(), issueChangeContext);
updater.setSimpleStatus(issue, previousSimpleStatus, issue.getSimpleStatus(), issueChangeContext);
updater.setIssueStatus(issue, previousIssueStatus, issue.getIssueStatus(), issueChangeContext);
return true;
}
return false;
@@ -350,10 +350,10 @@ public class IssueWorkflow implements Startable {
public void doAutomaticTransition(DefaultIssue issue, IssueChangeContext issueChangeContext) {
Transition transition = stateOf(issue).outAutomaticTransition(issue);
if (transition != null) {
SimpleStatus previousSimpleStatus = issue.getSimpleStatus();
IssueStatus previousIssueStatus = issue.getIssueStatus();
functionExecutor.execute(transition.functions(), issue, issueChangeContext);
updater.setStatus(issue, transition.to(), issueChangeContext);
updater.setSimpleStatus(issue, previousSimpleStatus, issue.getSimpleStatus(), issueChangeContext);
updater.setIssueStatus(issue, previousIssueStatus, issue.getIssueStatus(), issueChangeContext);
}
}


+ 13
- 13
server/sonar-server-common/src/test/java/org/sonar/server/issue/IssueFieldsSetterTest.java View File

@@ -38,7 +38,7 @@ import org.sonar.api.utils.Duration;
import org.sonar.core.issue.DefaultIssue;
import org.sonar.core.issue.FieldDiffs;
import org.sonar.core.issue.IssueChangeContext;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.db.protobuf.DbCommons;
import org.sonar.db.protobuf.DbIssues;
import org.sonar.db.protobuf.DbIssues.MessageFormattingType;
@@ -435,42 +435,42 @@ public class IssueFieldsSetterTest {
}

@Test
public void setSimpleStatus_shouldTriggerFieldChange() {
public void setIssueStatus_shouldTriggerFieldChange() {
issue.setResolution(null);
issue.setStatus(Issue.STATUS_OPEN);

SimpleStatus simpleStatus = issue.getSimpleStatus();
IssueStatus issueStatus = issue.getIssueStatus();

underTest.setResolution(issue, Issue.RESOLUTION_WONT_FIX, context);
underTest.setStatus(issue, Issue.STATUS_RESOLVED, context);
underTest.setSimpleStatus(issue, simpleStatus, issue.getSimpleStatus(), context);
underTest.setIssueStatus(issue, issueStatus, issue.getIssueStatus(), context);

FieldDiffs.Diff diff = issue.currentChange().diffs().get(IssueFieldsSetter.SIMPLE_STATUS);
assertThat(diff.oldValue()).isEqualTo(SimpleStatus.OPEN);
assertThat(diff.newValue()).isEqualTo(SimpleStatus.ACCEPTED);
FieldDiffs.Diff diff = issue.currentChange().diffs().get(IssueFieldsSetter.ISSUE_STATUS);
assertThat(diff.oldValue()).isEqualTo(IssueStatus.OPEN);
assertThat(diff.newValue()).isEqualTo(IssueStatus.ACCEPTED);
}

@Test
public void setSimpleStatus_shouldNotTriggerFieldChange_whenNoChanges() {
public void setIssueStatus_shouldNotTriggerFieldChange_whenNoChanges() {
issue.setResolution(null);
issue.setStatus(Issue.STATUS_OPEN);

SimpleStatus simpleStatus = issue.getSimpleStatus();
underTest.setSimpleStatus(issue, simpleStatus, issue.getSimpleStatus(), context);
IssueStatus issueStatus = issue.getIssueStatus();
underTest.setIssueStatus(issue, issueStatus, issue.getIssueStatus(), context);

assertThat(issue.currentChange()).isNull();
}

@Test
public void setSimpleStatus_shouldNotTriggerFieldChange_whenSecurityHotspot() {
public void setIssueStatus_shouldNotTriggerFieldChange_whenSecurityHotspot() {
issue.setResolution(null);
issue.setStatus(Issue.STATUS_TO_REVIEW);

SimpleStatus simpleStatus = issue.getSimpleStatus();
IssueStatus issueStatus = issue.getIssueStatus();

issue.setResolution(Issue.RESOLUTION_SAFE);
issue.setStatus(Issue.STATUS_REVIEWED);
underTest.setSimpleStatus(issue, simpleStatus, issue.getSimpleStatus(), context);
underTest.setIssueStatus(issue, issueStatus, issue.getIssueStatus(), context);

assertThat(issue.currentChange()).isNull();
}

+ 20
- 21
server/sonar-web/src/main/js/api/mocks/IssuesServiceMock.ts View File

@@ -20,7 +20,7 @@
import { cloneDeep, uniqueId } from 'lodash';
import { RuleDescriptionSections } from '../../apps/coding-rules/rule';

import { ISSUE_TYPES, SEVERITIES, SIMPLE_STATUSES, SOURCE_SCOPES } from '../../helpers/constants';
import { ISSUE_STATUSES, ISSUE_TYPES, SEVERITIES, SOURCE_SCOPES } from '../../helpers/constants';
import { mockIssueAuthors, mockIssueChangelog } from '../../helpers/mocks/issues';
import { RequestData } from '../../helpers/request';
import { getStandards } from '../../helpers/security-standard';
@@ -33,7 +33,7 @@ import {
import { SearchRulesResponse } from '../../types/coding-rules';
import {
ASSIGNEE_ME,
IssueSimpleStatus,
IssueDeprecatedStatus,
IssueStatus,
IssueTransition,
IssueType,
@@ -331,7 +331,7 @@ export default class IssuesServiceMock {
values: (
{
severities: SEVERITIES,
simpleStatuses: SIMPLE_STATUSES,
issueStatuses: ISSUE_STATUSES,
types: ISSUE_TYPES,
scopes: SOURCE_SCOPES.map(({ scope }) => scope),
projects: ['org.project1', 'org.project2'],
@@ -384,8 +384,7 @@ export default class IssuesServiceMock {
const filteredList = this.list
.filter(
(item) =>
!query.simpleStatuses ||
query.simpleStatuses.split(',').includes(item.issue.simpleStatus),
!query.issueStatuses || query.issueStatuses.split(',').includes(item.issue.issueStatus),
)
.filter((item) => {
if (!query.cleanCodeAttributeCategories) {
@@ -518,39 +517,39 @@ export default class IssuesServiceMock {
};

handleSetIssueTransition = (data: { issue: string; transition: string }) => {
const simpleStatusMap: { [key: string]: IssueSimpleStatus } = {
[IssueTransition.Accept]: IssueSimpleStatus.Accepted,
[IssueTransition.Confirm]: IssueSimpleStatus.Confirmed,
[IssueTransition.UnConfirm]: IssueSimpleStatus.Open,
[IssueTransition.Resolve]: IssueSimpleStatus.Fixed,
[IssueTransition.WontFix]: IssueSimpleStatus.Accepted,
[IssueTransition.FalsePositive]: IssueSimpleStatus.FalsePositive,
const issueStatusMap: { [key: string]: IssueStatus } = {
[IssueTransition.Accept]: IssueStatus.Accepted,
[IssueTransition.Confirm]: IssueStatus.Confirmed,
[IssueTransition.UnConfirm]: IssueStatus.Open,
[IssueTransition.Resolve]: IssueStatus.Fixed,
[IssueTransition.WontFix]: IssueStatus.Accepted,
[IssueTransition.FalsePositive]: IssueStatus.FalsePositive,
};

const transitionMap: Dict<IssueTransition[]> = {
[IssueSimpleStatus.Open]: [
[IssueStatus.Open]: [
IssueTransition.Accept,
IssueTransition.Confirm,
IssueTransition.Resolve,
IssueTransition.FalsePositive,
IssueTransition.WontFix,
],
[IssueSimpleStatus.Confirmed]: [
[IssueStatus.Confirmed]: [
IssueTransition.Accept,
IssueTransition.Resolve,
IssueTransition.UnConfirm,
IssueTransition.FalsePositive,
IssueTransition.WontFix,
],
[IssueSimpleStatus.FalsePositive]: [IssueTransition.Reopen],
[IssueSimpleStatus.Accepted]: [IssueTransition.Reopen],
[IssueSimpleStatus.Fixed]: [IssueTransition.Reopen],
[IssueStatus.FalsePositive]: [IssueTransition.Reopen],
[IssueStatus.Accepted]: [IssueTransition.Reopen],
[IssueStatus.Fixed]: [IssueTransition.Reopen],
};

return this.getActionsResponse(
{
simpleStatus: simpleStatusMap[data.transition],
transitions: transitionMap[simpleStatusMap[data.transition]],
issueStatus: issueStatusMap[data.transition],
transitions: transitionMap[issueStatusMap[data.transition]],
},
data.issue,
);
@@ -639,8 +638,8 @@ export default class IssuesServiceMock {
diffs: [
{
key: 'status',
newValue: IssueStatus.Reopened,
oldValue: IssueStatus.Confirmed,
newValue: IssueDeprecatedStatus.Reopened,
oldValue: IssueDeprecatedStatus.Confirmed,
},
],
}),

+ 5
- 5
server/sonar-web/src/main/js/api/mocks/data/issues.ts View File

@@ -28,10 +28,10 @@ import {
} from '../../../types/clean-code-taxonomy';
import {
IssueActions,
IssueDeprecatedStatus,
IssueResolution,
IssueScope,
IssueSeverity,
IssueSimpleStatus,
IssueStatus,
IssueTransition,
IssueType,
@@ -318,8 +318,8 @@ export function mockIssuesList(baseComponentKey = PARENT_COMPONENT_KEY): IssueDa
{ softwareQuality: SoftwareQuality.Security, severity: SoftwareImpactSeverity.High },
],
resolution: IssueResolution.Unresolved,
status: IssueStatus.Open,
simpleStatus: IssueSimpleStatus.Open,
status: IssueDeprecatedStatus.Open,
issueStatus: IssueStatus.Open,
ruleDescriptionContextKey: 'spring',
}),
snippets: keyBy(
@@ -346,8 +346,8 @@ export function mockIssuesList(baseComponentKey = PARENT_COMPONENT_KEY): IssueDa
endOffset: 1,
},
resolution: IssueResolution.Fixed,
status: IssueStatus.Confirmed,
simpleStatus: IssueSimpleStatus.Confirmed,
status: IssueDeprecatedStatus.Confirmed,
issueStatus: IssueStatus.Confirmed,
}),
snippets: keyBy(
[

+ 6
- 4
server/sonar-web/src/main/js/api/mocks/data/measures.ts View File

@@ -21,7 +21,7 @@
import { keyBy } from 'lodash';
import { isDiffMetric } from '../../../helpers/measures';
import { mockMeasure } from '../../../helpers/testMocks';
import { IssueStatus, IssueType, RawIssue } from '../../../types/issues';
import { IssueDeprecatedStatus, IssueType, RawIssue } from '../../../types/issues';
import { MetricKey } from '../../../types/metrics';
import { Measure } from '../../../types/types';
import { ComponentTree } from './components';
@@ -62,9 +62,11 @@ function mockComponentMeasure(tree: ComponentTree, issueList: IssueData[], metri
.map(({ issue }) => issue)
.filter(({ component }) => componentKeys.includes(component))
.filter(({ status }) =>
[IssueStatus.Open, IssueStatus.Reopened, IssueStatus.Confirmed].includes(
status as IssueStatus,
),
[
IssueDeprecatedStatus.Open,
IssueDeprecatedStatus.Reopened,
IssueDeprecatedStatus.Confirmed,
].includes(status as IssueDeprecatedStatus),
);

if (isIssueType(metricKey)) {

+ 2
- 2
server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx View File

@@ -87,7 +87,7 @@ it('should render the component nav correctly for portfolio', async () => {
expect(await ui.portfolioTitle.find()).toHaveAttribute('href', '/portfolio?id=portfolioKey');
expect(ui.issuesPageLink.get()).toHaveAttribute(
'href',
'/project/issues?id=portfolioKey&simpleStatuses=OPEN%2CCONFIRMED',
'/project/issues?id=portfolioKey&issueStatuses=OPEN%2CCONFIRMED',
);
expect(ui.measuresPageLink.get()).toHaveAttribute('href', '/component_measures?id=portfolioKey');
expect(ui.activityPageLink.get()).toHaveAttribute('href', '/project/activity?id=portfolioKey');
@@ -119,7 +119,7 @@ it('should render the component nav correctly for projects', async () => {
expect(ui.overviewPageLink.get()).toHaveAttribute('href', '/dashboard?id=project-key');
expect(ui.issuesPageLink.get()).toHaveAttribute(
'href',
'/project/issues?id=project-key&simpleStatuses=OPEN%2CCONFIRMED',
'/project/issues?id=project-key&issueStatuses=OPEN%2CCONFIRMED',
);
expect(ui.hotspotsPageLink.get()).toHaveAttribute('href', '/security_hotspots?id=project-key');
expect(ui.measuresPageLink.get()).toHaveAttribute('href', '/component_measures?id=project-key');

+ 5
- 5
server/sonar-web/src/main/js/apps/issues/__tests__/IssueApp-it.tsx View File

@@ -154,10 +154,10 @@ describe('issue app', () => {
// Get a specific issue list item
const listItem = within(await screen.findByRole('region', { name: 'Fix that' }));

expect(listItem.getByText('issue.simple_status.OPEN')).toBeInTheDocument();
expect(listItem.getByText('issue.issue_status.OPEN')).toBeInTheDocument();

await act(async () => {
await user.click(listItem.getByText('issue.simple_status.OPEN'));
await user.click(listItem.getByText('issue.issue_status.OPEN'));
});
expect(listItem.getByText('issue.transition.accept')).toBeInTheDocument();
expect(listItem.getByText('issue.transition.confirm')).toBeInTheDocument();
@@ -175,20 +175,20 @@ describe('issue app', () => {

expect(
listItem.getByLabelText(
'issue.transition.status_x_click_to_change.issue.simple_status.CONFIRMED',
'issue.transition.status_x_click_to_change.issue.issue_status.CONFIRMED',
),
).toBeInTheDocument();

// Change status again
await act(async () => {
await user.click(listItem.getByText('issue.simple_status.CONFIRMED'));
await user.click(listItem.getByText('issue.issue_status.CONFIRMED'));
await user.click(listItem.getByText('issue.transition.accept'));
await user.click(listItem.getByText('resolve'));
});

expect(
listItem.getByLabelText(
'issue.transition.status_x_click_to_change.issue.simple_status.ACCEPTED',
'issue.transition.status_x_click_to_change.issue.issue_status.ACCEPTED',
),
).toBeInTheDocument();


+ 2
- 2
server/sonar-web/src/main/js/apps/issues/__tests__/IssuesApp-Filtering-it.tsx View File

@@ -90,7 +90,7 @@ describe('issues app filtering', () => {
expect(ui.issueItem6.get()).toBeInTheDocument();

// Status
await user.click(ui.simpleStatusFacet.get());
await user.click(ui.issueStatusFacet.get());
await user.click(ui.openStatusFilter.get());
expect(ui.issueItem6.query()).not.toBeInTheDocument(); // Issue 6 should vanish

@@ -350,7 +350,7 @@ describe('issues app when reindexing', () => {
expect(ui.resolutionFacet.query()).not.toBeInTheDocument();
expect(ui.ruleFacet.query()).not.toBeInTheDocument();
expect(ui.scopeFacet.query()).not.toBeInTheDocument();
expect(ui.simpleStatusFacet.query()).not.toBeInTheDocument();
expect(ui.issueStatusFacet.query()).not.toBeInTheDocument();
expect(ui.tagFacet.query()).not.toBeInTheDocument();

// Indexation message

+ 36
- 45
server/sonar-web/src/main/js/apps/issues/__tests__/utils-test.ts View File

@@ -22,7 +22,7 @@ import {
SoftwareImpactSeverity,
SoftwareQuality,
} from '../../../types/clean-code-taxonomy';
import { IssueSimpleStatus } from '../../../types/issues';
import { IssueStatus } from '../../../types/issues';
import { SecurityStandard } from '../../../types/security';
import {
parseQuery,
@@ -69,7 +69,7 @@ describe('serialize/deserialize', () => {
severities: ['a', 'b'],
inNewCodePeriod: true,
sonarsourceSecurity: ['a', 'b'],
simpleStatuses: [IssueSimpleStatus.Accepted, IssueSimpleStatus.Confirmed],
issueStatuses: [IssueStatus.Accepted, IssueStatus.Confirmed],
tags: ['a', 'b'],
types: ['a', 'b'],
}),
@@ -102,7 +102,7 @@ describe('serialize/deserialize', () => {
inNewCodePeriod: 'true',
severities: 'a,b',
sonarsourceSecurity: 'a,b',
simpleStatuses: 'ACCEPTED,CONFIRMED',
issueStatuses: 'ACCEPTED,CONFIRMED',
tags: 'a,b',
types: 'a,b',
});
@@ -149,73 +149,64 @@ describe('serialize/deserialize', () => {
severities: ['CRITICAL', 'MAJOR'],
sonarsourceSecurity: [],
sort: '',
simpleStatuses: [],
issueStatuses: [],
tags: [],
types: [],
});
});

it('should map deprecated status and resolution query to new simple statuses', () => {
expect(parseQuery({ statuses: 'OPEN' }).simpleStatuses).toEqual([IssueSimpleStatus.Open]);
expect(parseQuery({ statuses: 'REOPENED' }).simpleStatuses).toEqual([IssueSimpleStatus.Open]);
expect(parseQuery({ statuses: 'CONFIRMED' }).simpleStatuses).toEqual([
IssueSimpleStatus.Confirmed,
it('should map deprecated status and resolution query to new issue statuses', () => {
expect(parseQuery({ statuses: 'OPEN' }).issueStatuses).toEqual([IssueStatus.Open]);
expect(parseQuery({ statuses: 'REOPENED' }).issueStatuses).toEqual([IssueStatus.Open]);
expect(parseQuery({ statuses: 'CONFIRMED' }).issueStatuses).toEqual([IssueStatus.Confirmed]);
expect(parseQuery({ statuses: 'RESOLVED' }).issueStatuses).toEqual([
IssueStatus.Fixed,
IssueStatus.Accepted,
IssueStatus.FalsePositive,
]);
expect(parseQuery({ statuses: 'RESOLVED' }).simpleStatuses).toEqual([
IssueSimpleStatus.Fixed,
IssueSimpleStatus.Accepted,
IssueSimpleStatus.FalsePositive,
]);
expect(parseQuery({ statuses: 'OPEN,REOPENED' }).simpleStatuses).toEqual([
IssueSimpleStatus.Open,
]);
expect(parseQuery({ statuses: 'OPEN,CONFIRMED' }).simpleStatuses).toEqual([
IssueSimpleStatus.Open,
IssueSimpleStatus.Confirmed,
expect(parseQuery({ statuses: 'OPEN,REOPENED' }).issueStatuses).toEqual([IssueStatus.Open]);
expect(parseQuery({ statuses: 'OPEN,CONFIRMED' }).issueStatuses).toEqual([
IssueStatus.Open,
IssueStatus.Confirmed,
]);

// Resolutions
expect(parseQuery({ resolutions: 'FALSE-POSITIVE' }).simpleStatuses).toEqual([
IssueSimpleStatus.FalsePositive,
]);
expect(parseQuery({ resolutions: 'WONTFIX' }).simpleStatuses).toEqual([
IssueSimpleStatus.Accepted,
]);
expect(parseQuery({ resolutions: 'REMOVED' }).simpleStatuses).toEqual([
IssueSimpleStatus.Fixed,
expect(parseQuery({ resolutions: 'FALSE-POSITIVE' }).issueStatuses).toEqual([
IssueStatus.FalsePositive,
]);
expect(parseQuery({ resolutions: 'REMOVED,WONTFIX,FALSE-POSITIVE' }).simpleStatuses).toEqual([
IssueSimpleStatus.Fixed,
IssueSimpleStatus.Accepted,
IssueSimpleStatus.FalsePositive,
expect(parseQuery({ resolutions: 'WONTFIX' }).issueStatuses).toEqual([IssueStatus.Accepted]);
expect(parseQuery({ resolutions: 'REMOVED' }).issueStatuses).toEqual([IssueStatus.Fixed]);
expect(parseQuery({ resolutions: 'REMOVED,WONTFIX,FALSE-POSITIVE' }).issueStatuses).toEqual([
IssueStatus.Fixed,
IssueStatus.Accepted,
IssueStatus.FalsePositive,
]);

// Both statuses and resolutions
expect(
parseQuery({ resolutions: 'FALSE-POSITIVE', statuses: 'RESOLVED' }).simpleStatuses,
).toEqual([IssueSimpleStatus.FalsePositive]);
expect(parseQuery({ resolutions: 'WONTFIX', statuses: 'RESOLVED' }).simpleStatuses).toEqual([
IssueSimpleStatus.Accepted,
parseQuery({ resolutions: 'FALSE-POSITIVE', statuses: 'RESOLVED' }).issueStatuses,
).toEqual([IssueStatus.FalsePositive]);
expect(parseQuery({ resolutions: 'WONTFIX', statuses: 'RESOLVED' }).issueStatuses).toEqual([
IssueStatus.Accepted,
]);

// With resolved=false
expect(
parseQuery({ resolutions: 'WONTFIX', statuses: 'RESOLVED', resolved: 'false' })
.simpleStatuses,
).toEqual([IssueSimpleStatus.Accepted, IssueSimpleStatus.Open, IssueSimpleStatus.Confirmed]);
expect(parseQuery({ statuses: 'OPEN', resolved: 'false' }).simpleStatuses).toEqual([
IssueSimpleStatus.Open,
parseQuery({ resolutions: 'WONTFIX', statuses: 'RESOLVED', resolved: 'false' }).issueStatuses,
).toEqual([IssueStatus.Accepted, IssueStatus.Open, IssueStatus.Confirmed]);
expect(parseQuery({ statuses: 'OPEN', resolved: 'false' }).issueStatuses).toEqual([
IssueStatus.Open,
]);

// With simple status
// With new status
expect(
parseQuery({
resolutions: 'WONTFIX',
statuses: 'RESOLVED',
resolved: 'false',
simpleStatuses: 'FIXED',
}).simpleStatuses,
).toEqual([IssueSimpleStatus.Fixed]);
issueStatuses: 'FIXED',
}).issueStatuses,
).toEqual([IssueStatus.Fixed]);
});
});


+ 2
- 2
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/ComponentSourceSnippetGroupViewer.tsx View File

@@ -29,7 +29,7 @@ import { getBranchLikeQuery } from '../../../helpers/branch-like';
import { translate } from '../../../helpers/l10n';
import { BranchLike } from '../../../types/branch-like';
import { isFile } from '../../../types/component';
import { IssueStatus } from '../../../types/issues';
import { IssueDeprecatedStatus } from '../../../types/issues';
import {
Dict,
Duplication,
@@ -272,7 +272,7 @@ export default class ComponentSourceSnippetGroupViewer extends React.PureCompone
...additionalLines,
});

const issueIsClosed = issue.status === IssueStatus.Closed;
const issueIsClosed = issue.status === IssueDeprecatedStatus.Closed;
const issueIsFileLevel = isFile(issue.componentQualifier) && issue.componentEnabled;
const closedIssueMessageKey = issueIsFileLevel
? 'issue.closed.file_level'

+ 2
- 2
server/sonar-web/src/main/js/apps/issues/crossComponentSourceViewer/CrossComponentSourceViewer.tsx View File

@@ -41,7 +41,7 @@ import { translate } from '../../../helpers/l10n';
import { HttpStatus } from '../../../helpers/request';
import { BranchLike } from '../../../types/branch-like';
import { isFile } from '../../../types/component';
import { IssueStatus } from '../../../types/issues';
import { IssueDeprecatedStatus } from '../../../types/issues';
import {
Dict,
DuplicatedFile,
@@ -124,7 +124,7 @@ export default class CrossComponentSourceViewer extends React.PureComponent<Prop

try {
const components =
issue.status === IssueStatus.Closed ? {} : await getIssueFlowSnippets(issue.key);
issue.status === IssueDeprecatedStatus.Closed ? {} : await getIssueFlowSnippets(issue.key);
if (components[issue.component] === undefined) {
const issueComponent = await getComponentForSourceViewer({
// If the issue's component doesn't exist anymore (typically a deleted file), use the project

server/sonar-web/src/main/js/apps/issues/sidebar/SimpleStatusFacet.tsx → server/sonar-web/src/main/js/apps/issues/sidebar/IssueStatusFacet.tsx View File

@@ -19,36 +19,35 @@
*/

import { FacetBox, FacetItem } from 'design-system';
import { FacetItemsList } from './FacetItemsList';

import { isEqual, sortBy, without } from 'lodash';
import * as React from 'react';
import { useIntl } from 'react-intl';
import { DEFAULT_ISSUES_QUERY } from '../../../components/shared/utils';
import { SIMPLE_STATUSES } from '../../../helpers/constants';
import { IssueSimpleStatus } from '../../../types/issues';
import { ISSUE_STATUSES } from '../../../helpers/constants';
import { IssueStatus } from '../../../types/issues';
import { formatFacetStat } from '../utils';
import { FacetItemsList } from './FacetItemsList';
import { MultipleSelectionHint } from './MultipleSelectionHint';
import { CommonProps } from './SimpleListStyleFacet';

interface Props extends CommonProps {
simpleStatuses: Array<IssueSimpleStatus>;
issueStatuses: Array<IssueStatus>;
}

const property = 'simpleStatuses';
const property = 'issueStatuses';
const headerId = `facet_${property}`;

const defaultStatuses = DEFAULT_ISSUES_QUERY.simpleStatuses.split(',') as IssueSimpleStatus[];
const defaultStatuses = DEFAULT_ISSUES_QUERY.issueStatuses.split(',') as IssueStatus[];

export function SimpleStatusFacet(props: Readonly<Props>) {
const { simpleStatuses = [], stats = {}, fetching, open, help, needIssueSync } = props;
export function IssueStatusFacet(props: Readonly<Props>) {
const { issueStatuses = [], stats = {}, fetching, open, help, needIssueSync } = props;
const intl = useIntl();

const nbSelectableItems = SIMPLE_STATUSES.filter(
const nbSelectableItems = ISSUE_STATUSES.filter(
(item) => !defaultStatuses.includes(item) && stats[item],
).length;
const hasDefaultSelection = isEqual(sortBy(simpleStatuses), sortBy(defaultStatuses));
const nbSelectedItems = hasDefaultSelection ? 0 : simpleStatuses.length;
const hasDefaultSelection = isEqual(sortBy(issueStatuses), sortBy(defaultStatuses));
const nbSelectedItems = hasDefaultSelection ? 0 : issueStatuses.length;

return (
<FacetBox
@@ -70,8 +69,8 @@ export function SimpleStatusFacet(props: Readonly<Props>) {
help={help}
>
<FacetItemsList labelledby={headerId}>
{SIMPLE_STATUSES.map((item) => {
const active = simpleStatuses.includes(item);
{ISSUE_STATUSES.map((item) => {
const active = issueStatuses.includes(item);
const stat = stats[item];

return (
@@ -79,17 +78,17 @@ export function SimpleStatusFacet(props: Readonly<Props>) {
active={active}
className="it__search-navigator-facet"
key={item}
name={intl.formatMessage({ id: `issue.simple_status.${item}` })}
onClick={(itemValue: IssueSimpleStatus, multiple) => {
name={intl.formatMessage({ id: `issue.issue_status.${item}` })}
onClick={(itemValue: IssueStatus, multiple) => {
if (multiple) {
props.onChange({
[property]: active
? without(simpleStatuses, itemValue)
: [...simpleStatuses, itemValue],
? without(issueStatuses, itemValue)
: [...issueStatuses, itemValue],
});
} else {
props.onChange({
[property]: active && simpleStatuses.length === 1 ? [] : [itemValue],
[property]: active && issueStatuses.length === 1 ? [] : [itemValue],
});
}
}}
@@ -102,7 +101,7 @@ export function SimpleStatusFacet(props: Readonly<Props>) {

<MultipleSelectionHint
nbSelectableItems={nbSelectableItems}
nbSelectedItems={simpleStatuses.length}
nbSelectedItems={issueStatuses.length}
/>
</FacetBox>
);

+ 6
- 6
server/sonar-web/src/main/js/apps/issues/sidebar/Sidebar.tsx View File

@@ -49,13 +49,13 @@ import { AuthorFacet } from './AuthorFacet';
import { CreationDateFacet } from './CreationDateFacet';
import { DirectoryFacet } from './DirectoryFacet';
import { FileFacet } from './FileFacet';
import { IssueStatusFacet } from './IssueStatusFacet';
import { LanguageFacet } from './LanguageFacet';
import { PeriodFilter } from './PeriodFilter';
import { ProjectFacet } from './ProjectFacet';
import { RuleFacet } from './RuleFacet';
import { ScopeFacet } from './ScopeFacet';
import { SeverityFacet } from './SeverityFacet';
import { SimpleStatusFacet } from './SimpleStatusFacet';
import { SoftwareQualityFacet } from './SoftwareQualityFacet';
import { StandardFacet } from './StandardFacet';
import { TagFacet } from './TagFacet';
@@ -245,13 +245,13 @@ export class SidebarClass extends React.PureComponent<Props> {

<BasicSeparator className="sw-my-4" />

<SimpleStatusFacet
fetching={this.props.loadingFacets.simpleStatuses === true}
<IssueStatusFacet
fetching={this.props.loadingFacets.issueStatuses === true}
onChange={this.props.onFilterChange}
onToggle={this.props.onFacetToggle}
open={!!openFacets.simpleStatuses}
simpleStatuses={query.simpleStatuses}
stats={facets.simpleStatuses}
open={!!openFacets.issueStatuses}
issueStatuses={query.issueStatuses}
stats={facets.issueStatuses}
/>

<BasicSeparator className="sw-my-4" />

+ 3
- 3
server/sonar-web/src/main/js/apps/issues/sidebar/__tests__/Sidebar-it.tsx View File

@@ -51,7 +51,7 @@ it('should render correct facets for Application', () => {
'issues.facet.impactSeverities',
'issues.facet.types',
'issues.facet.scopes',
'issues.facet.simpleStatuses',
'issues.facet.issueStatuses',
'issues.facet.standards',
'issues.facet.createdAt',
'issues.facet.languages',
@@ -73,7 +73,7 @@ it('should render correct facets for Portfolio', () => {
'issues.facet.impactSeverities',
'issues.facet.types',
'issues.facet.scopes',
'issues.facet.simpleStatuses',
'issues.facet.issueStatuses',
'issues.facet.standards',
'issues.facet.createdAt',
'issues.facet.languages',
@@ -95,7 +95,7 @@ it('should render correct facets for SubPortfolio', () => {
'issues.facet.impactSeverities',
'issues.facet.types',
'issues.facet.scopes',
'issues.facet.simpleStatuses',
'issues.facet.issueStatuses',
'issues.facet.standards',
'issues.facet.createdAt',
'issues.facet.languages',

+ 4
- 4
server/sonar-web/src/main/js/apps/issues/test-utils.tsx View File

@@ -74,7 +74,7 @@ export const ui = {
resolutionFacet: byRole('button', { name: 'issues.facet.resolutions' }),
ruleFacet: byRole('button', { name: 'issues.facet.rules' }),
scopeFacet: byRole('button', { name: 'issues.facet.scopes' }),
simpleStatusFacet: byRole('button', { name: 'issues.facet.simpleStatuses' }),
issueStatusFacet: byRole('button', { name: 'issues.facet.issueStatuses' }),
tagFacet: byRole('button', { name: 'issues.facet.tags' }),
typeFacet: byRole('button', { name: 'issues.facet.types' }),
cleanCodeAttributeCategoryFacet: byRole('button', {
@@ -97,7 +97,7 @@ export const ui = {
clearRuleFacet: byTestId('clear-issues.facet.rules'),
clearScopeFacet: byTestId('clear-issues.facet.scopes'),
clearSeverityFacet: byTestId('clear-issues.facet.impactSeverities'),
clearSimpleStatusFacet: byTestId('clear-issues.facet.simpleStatuses'),
clearIssueStatusFacet: byTestId('clear-issues.facet.issueStatuses'),
clearTagFacet: byTestId('clear-issues.facet.tags'),

responsibleCategoryFilter: byRole('checkbox', {
@@ -110,11 +110,11 @@ export const ui = {
name: `software_quality.${SoftwareQuality.Maintainability}`,
}),
codeSmellIssueTypeFilter: byRole('checkbox', { name: 'issue.type.CODE_SMELL' }),
confirmedStatusFilter: byRole('checkbox', { name: 'issue.simple_status.CONFIRMED' }),
confirmedStatusFilter: byRole('checkbox', { name: 'issue.issue_status.CONFIRMED' }),
fixedResolutionFilter: byRole('checkbox', { name: 'issue.resolution.FIXED' }),
mainScopeFilter: byRole('checkbox', { name: 'issue.scope.MAIN' }),
mediumSeverityFilter: byRole('checkbox', { name: `severity.${SoftwareImpactSeverity.Medium}` }),
openStatusFilter: byRole('checkbox', { name: 'issue.simple_status.OPEN' }),
openStatusFilter: byRole('checkbox', { name: 'issue.issue_status.OPEN' }),
vulnerabilityIssueTypeFilter: byRole('checkbox', { name: 'issue.type.VULNERABILITY' }),

bulkChangeComment: byRole('textbox', { name: /issue_bulk_change.resolution_comment/ }),

+ 34
- 33
server/sonar-web/src/main/js/apps/issues/utils.ts View File

@@ -41,8 +41,8 @@ import {
} from '../../types/clean-code-taxonomy';
import {
Facet,
IssueDeprecatedStatus,
IssueResolution,
IssueSimpleStatus,
IssueStatus,
RawFacet,
} from '../../types/issues';
@@ -83,7 +83,7 @@ export interface Query {
inNewCodePeriod: boolean;
sonarsourceSecurity: string[];
sort: string;
simpleStatuses: IssueSimpleStatus[];
issueStatuses: IssueStatus[];
tags: string[];
types: string[];
}
@@ -130,44 +130,47 @@ export function parseQuery(query: RawQuery): Query {
severities: parseAsArray(query.severities, parseAsString),
sonarsourceSecurity: parseAsArray(query.sonarsourceSecurity, parseAsString),
sort: parseAsSort(query.s),
simpleStatuses: parseSimpleStatuses(query),
issueStatuses: parseIssueStatuses(query),
tags: parseAsArray(query.tags, parseAsString),
types: parseAsArray(query.types, parseAsString),
codeVariants: parseAsArray(query.codeVariants, parseAsString),
};
}

function parseSimpleStatuses(query: RawQuery) {
let result: Array<IssueSimpleStatus> = [];
function parseIssueStatuses(query: RawQuery) {
let result: Array<IssueStatus> = [];

if (query.simpleStatuses) {
return parseAsArray<IssueSimpleStatus>(query.simpleStatuses, parseAsString);
if (query.issueStatuses) {
return parseAsArray<IssueStatus>(query.issueStatuses, parseAsString);
}

const deprecatedStatusesMap = {
[IssueStatus.Open]: [IssueSimpleStatus.Open],
[IssueStatus.Confirmed]: [IssueSimpleStatus.Confirmed],
[IssueStatus.Reopened]: [IssueSimpleStatus.Open],
[IssueStatus.Resolved]: [
IssueSimpleStatus.Fixed,
IssueSimpleStatus.Accepted,
IssueSimpleStatus.FalsePositive,
[IssueDeprecatedStatus.Open]: [IssueStatus.Open],
[IssueDeprecatedStatus.Confirmed]: [IssueStatus.Confirmed],
[IssueDeprecatedStatus.Reopened]: [IssueStatus.Open],
[IssueDeprecatedStatus.Resolved]: [
IssueStatus.Fixed,
IssueStatus.Accepted,
IssueStatus.FalsePositive,
],
[IssueStatus.Closed]: [IssueSimpleStatus.Fixed],
[IssueDeprecatedStatus.Closed]: [IssueStatus.Fixed],
};
const deprecatedResolutionsMap = {
[IssueResolution.FalsePositive]: [IssueSimpleStatus.FalsePositive],
[IssueResolution.WontFix]: [IssueSimpleStatus.Accepted],
[IssueResolution.Fixed]: [IssueSimpleStatus.Fixed],
[IssueResolution.Removed]: [IssueSimpleStatus.Fixed],
[IssueResolution.Unresolved]: [IssueSimpleStatus.Open, IssueSimpleStatus.Confirmed],
[IssueResolution.FalsePositive]: [IssueStatus.FalsePositive],
[IssueResolution.WontFix]: [IssueStatus.Accepted],
[IssueResolution.Fixed]: [IssueStatus.Fixed],
[IssueResolution.Removed]: [IssueStatus.Fixed],
[IssueResolution.Unresolved]: [IssueStatus.Open, IssueStatus.Confirmed],
};

const simpleStatusesFromStatuses = parseAsArray<IssueStatus>(query.statuses, parseAsString)
const issuesStatusesFromDeprecatedStatuses = parseAsArray<IssueDeprecatedStatus>(
query.statuses,
parseAsString,
)
.map((status) => deprecatedStatusesMap[status])
.filter(Boolean)
.flat();
const simpleStatusesFromResolutions = parseAsArray<IssueResolution>(
const issueStatusesFromResolutions = parseAsArray<IssueResolution>(
query.resolutions,
parseAsString,
)
@@ -175,22 +178,20 @@ function parseSimpleStatuses(query: RawQuery) {
.filter(Boolean)
.flat();

const intesectedSimpleStatuses = intersection(
simpleStatusesFromStatuses,
simpleStatusesFromResolutions,
const intesectedIssueStatuses = intersection(
issuesStatusesFromDeprecatedStatuses,
issueStatusesFromResolutions,
);
result = intesectedSimpleStatuses.length
? intesectedSimpleStatuses
: simpleStatusesFromResolutions.concat(simpleStatusesFromStatuses);
result = intesectedIssueStatuses.length
? intesectedIssueStatuses
: issueStatusesFromResolutions.concat(issuesStatusesFromDeprecatedStatuses);

if (
query.resolved === 'false' &&
[IssueSimpleStatus.Open, IssueSimpleStatus.Confirmed].every(
(status) => !result.includes(status),
)
[IssueStatus.Open, IssueStatus.Confirmed].every((status) => !result.includes(status))
) {
result = result.concat(
parseAsArray<IssueSimpleStatus>(DEFAULT_ISSUES_QUERY.simpleStatuses, parseAsString),
parseAsArray<IssueStatus>(DEFAULT_ISSUES_QUERY.issueStatuses, parseAsString),
);
}

@@ -238,7 +239,7 @@ export function serializeQuery(query: Query): RawQuery {
impactSoftwareQualities: serializeStringArray(query.impactSoftwareQualities),
inNewCodePeriod: query.inNewCodePeriod ? 'true' : undefined,
sonarsourceSecurity: serializeStringArray(query.sonarsourceSecurity),
simpleStatuses: serializeStringArray(query.simpleStatuses),
issueStatuses: serializeStringArray(query.issueStatuses),
tags: serializeStringArray(query.tags),
types: serializeStringArray(query.types),
codeVariants: serializeStringArray(query.codeVariants),

+ 2
- 2
server/sonar-web/src/main/js/apps/overview/components/__tests__/BranchQualityGate-it.tsx View File

@@ -39,7 +39,7 @@ it('renders failed QG', () => {
expect(maintainabilityRatingLink).toBeInTheDocument();
expect(maintainabilityRatingLink).toHaveAttribute(
'href',
'/project/issues?simpleStatuses=OPEN%2CCONFIRMED&types=CODE_SMELL&pullRequest=1001&sinceLeakPeriod=true&id=my-project',
'/project/issues?issueStatuses=OPEN%2CCONFIRMED&types=CODE_SMELL&pullRequest=1001&sinceLeakPeriod=true&id=my-project',
);

// Security Hotspots rating condition
@@ -59,7 +59,7 @@ it('renders failed QG', () => {
expect(codeSmellsLink).toBeInTheDocument();
expect(codeSmellsLink).toHaveAttribute(
'href',
'/project/issues?simpleStatuses=OPEN%2CCONFIRMED&types=CODE_SMELL&pullRequest=1001&id=my-project',
'/project/issues?issueStatuses=OPEN%2CCONFIRMED&types=CODE_SMELL&pullRequest=1001&id=my-project',
);

// Conditions to cover

+ 2
- 2
server/sonar-web/src/main/js/components/SourceViewer/helpers/__tests__/__snapshots__/loadIssues-test.ts.snap View File

@@ -22,6 +22,7 @@ exports[`loadIssues should load issues with listIssues if re-indexing 1`] = `
"flows": [],
"flowsWithType": [],
"hash": "78417dcee7ba927b7e7c9161e29e02b8",
"issueStatus": "OPEN",
"key": "AWaqVGl3tut9VbnJvk6M",
"line": 62,
"message": "Make sure this file handling is safe here.",
@@ -33,7 +34,6 @@ exports[`loadIssues should load issues with listIssues if re-indexing 1`] = `
"projectQualifier": "TRK",
"rule": "squid:S4797",
"secondaryLocations": [],
"simpleStatus": "OPEN",
"status": "OPEN",
"tags": [
"cert",
@@ -80,6 +80,7 @@ exports[`loadIssues should load issues with searchIssues if not re-indexing 1`]
"flows": [],
"flowsWithType": [],
"hash": "78417dcee7ba927b7e7c9161e29e02b8",
"issueStatus": "OPEN",
"key": "AWaqVGl3tut9VbnJvk6M",
"line": 62,
"message": "Make sure this file handling is safe here.",
@@ -96,7 +97,6 @@ exports[`loadIssues should load issues with searchIssues if not re-indexing 1`]
"ruleName": "Handling files is security-sensitive",
"ruleStatus": "READY",
"secondaryLocations": [],
"simpleStatus": "OPEN",
"status": "OPEN",
"tags": [
"cert",

server/sonar-web/src/main/js/components/icons/SimpleStatusIcon.tsx → server/sonar-web/src/main/js/components/icons/IssueStatusIcon.tsx View File

@@ -25,20 +25,20 @@ import {
StatusResolvedIcon,
} from 'design-system';
import * as React from 'react';
import { IssueSimpleStatus } from '../../types/issues';
import { IssueStatus } from '../../types/issues';
import { Dict } from '../../types/types';
import { IconProps } from './Icon';

interface Props extends IconProps {
simpleStatus: IssueSimpleStatus;
issueStatus: IssueStatus;
}

const statusIcons: Dict<(props: IconProps) => React.ReactElement> = {
[IssueSimpleStatus.Accepted]: StatusConfirmedIcon,
[IssueSimpleStatus.Confirmed]: StatusConfirmedIcon,
[IssueSimpleStatus.FalsePositive]: StatusResolvedIcon,
[IssueSimpleStatus.Fixed]: StatusResolvedIcon,
[IssueSimpleStatus.Open]: StatusOpenIcon,
[IssueStatus.Accepted]: StatusConfirmedIcon,
[IssueStatus.Confirmed]: StatusConfirmedIcon,
[IssueStatus.FalsePositive]: StatusResolvedIcon,
[IssueStatus.Fixed]: StatusResolvedIcon,
[IssueStatus.Open]: StatusOpenIcon,
closed: StatusResolvedIcon,
confirm: StatusConfirmedIcon,
confirmed: StatusConfirmedIcon,
@@ -55,8 +55,8 @@ const statusIcons: Dict<(props: IconProps) => React.ReactElement> = {
wontfix: StatusResolvedIcon,
};

export default function SimpleStatusIcon({ simpleStatus, ...iconProps }: Props) {
const DesiredStatusIcon = statusIcons[simpleStatus.toLowerCase()];
export default function IssueStatusIcon({ issueStatus, ...iconProps }: Props) {
const DesiredStatusIcon = statusIcons[issueStatus.toLowerCase()];

return DesiredStatusIcon ? <DesiredStatusIcon {...iconProps} /> : null;
}

+ 7
- 7
server/sonar-web/src/main/js/components/issue/__tests__/Issue-it.tsx View File

@@ -32,7 +32,7 @@ import { ComponentPropsType } from '../../../helpers/testUtils';
import {
IssueActions,
IssueSeverity,
IssueSimpleStatus,
IssueStatus,
IssueTransition,
IssueType,
} from '../../../types/issues';
@@ -97,7 +97,7 @@ describe('updating', () => {
it('should allow updating the status', async () => {
const { ui } = getPageObject();
const issue = mockRawIssue(false, {
simpleStatus: IssueSimpleStatus.Open,
issueStatus: IssueStatus.Open,
transitions: [IssueTransition.Confirm, IssueTransition.UnConfirm],
});
issuesHandler.setIssueList([{ issue, snippets: {} }]);
@@ -105,8 +105,8 @@ describe('updating', () => {
issue: mockIssue(false, { ...pick(issue, 'key', 'status', 'transitions') }),
});

await ui.updateStatus(IssueSimpleStatus.Open, IssueTransition.Confirm);
expect(ui.updateStatusBtn(IssueSimpleStatus.Confirmed).get()).toBeInTheDocument();
await ui.updateStatus(IssueStatus.Open, IssueTransition.Confirm);
expect(ui.updateStatusBtn(IssueStatus.Confirmed).get()).toBeInTheDocument();
});

it('should allow assigning', async () => {
@@ -244,8 +244,8 @@ function getPageObject() {
setSeverityBtn: (severity: IssueSeverity) => byText(`severity.${severity}`),

// Status
updateStatusBtn: (currentStatus: IssueSimpleStatus) =>
byLabelText(`issue.transition.status_x_click_to_change.issue.simple_status.${currentStatus}`),
updateStatusBtn: (currentStatus: IssueStatus) =>
byLabelText(`issue.transition.status_x_click_to_change.issue.issue_status.${currentStatus}`),
setStatusBtn: (transition: IssueTransition) => byText(`issue.transition.${transition}`),

// Assignee
@@ -297,7 +297,7 @@ function getPageObject() {
await user.click(selectors.setSeverityBtn(newSeverity).get());
});
},
async updateStatus(currentStatus: IssueSimpleStatus, transition: IssueTransition) {
async updateStatus(currentStatus: IssueStatus, transition: IssueTransition) {
await user.click(selectors.updateStatusBtn(currentStatus).get());
await act(async () => {
await user.click(selectors.setStatusBtn(transition).get());

+ 4
- 4
server/sonar-web/src/main/js/components/issue/components/IssueTransition.tsx View File

@@ -29,7 +29,7 @@ import { IssueTransitionOverlay } from './IssueTransitionOverlay';

interface Props {
isOpen: boolean;
issue: Pick<Issue, 'key' | 'resolution' | 'simpleStatus' | 'transitions' | 'type' | 'actions'>;
issue: Pick<Issue, 'key' | 'resolution' | 'issueStatus' | 'transitions' | 'type' | 'actions'>;
onChange: (issue: Issue) => void;
togglePopup: (popup: string, show?: boolean) => void;
}
@@ -91,11 +91,11 @@ export default function IssueTransition(props: Readonly<Props>) {
isDiscreet
className="it__issue-transition sw-px-1"
label={
<StatusHelper className="sw-flex sw-items-center" simpleStatus={issue.simpleStatus} />
<StatusHelper className="sw-flex sw-items-center" issueStatus={issue.issueStatus} />
}
ariaLabel={translateWithParameters(
'issue.transition.status_x_click_to_change',
translate('issue.simple_status', issue.simpleStatus),
translate('issue.issue_status', issue.issueStatus),
)}
/>
)}
@@ -103,5 +103,5 @@ export default function IssueTransition(props: Readonly<Props>) {
);
}

return <StatusHelper simpleStatus={issue.simpleStatus} />;
return <StatusHelper issueStatus={issue.issueStatus} />;
}

+ 5
- 5
server/sonar-web/src/main/js/components/shared/StatusHelper.tsx View File

@@ -19,19 +19,19 @@
*/
import * as React from 'react';
import { translate } from '../../helpers/l10n';
import { IssueSimpleStatus } from '../../types/issues';
import SimpleStatusIcon from '../icons/SimpleStatusIcon';
import { IssueStatus } from '../../types/issues';
import IssueStatusIcon from '../icons/IssueStatusIcon';

interface Props {
className?: string;
simpleStatus: IssueSimpleStatus;
issueStatus: IssueStatus;
}

export default function StatusHelper(props: Props) {
return (
<span className={props.className}>
<SimpleStatusIcon className="sw-mr-1" simpleStatus={props.simpleStatus} />
{translate('issue.simple_status', props.simpleStatus)}
<IssueStatusIcon className="sw-mr-1" issueStatus={props.issueStatus} />
{translate('issue.issue_status', props.issueStatus)}
</span>
);
}

+ 2
- 2
server/sonar-web/src/main/js/components/shared/__tests__/utils-test.ts View File

@@ -23,13 +23,13 @@ import { propsToIssueParams } from '../utils';

describe('propsToIssueParams', () => {
it('should render correct default parameters', () => {
expect(propsToIssueParams('other')).toEqual({ simpleStatuses: 'OPEN,CONFIRMED' });
expect(propsToIssueParams('other')).toEqual({ issueStatuses: 'OPEN,CONFIRMED' });
});

it(`should render correct params`, () => {
expect(propsToIssueParams(MetricKey.false_positive_issues, true)).toEqual({
inNewCodePeriod: true,
simpleStatuses: 'FALSE_POSITIVE',
issueStatuses: 'FALSE_POSITIVE',
});
});
});

+ 6
- 6
server/sonar-web/src/main/js/components/shared/utils.ts View File

@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import { IssueSimpleStatus } from '../../types/issues';
import { IssueStatus } from '../../types/issues';
import { MetricKey } from '../../types/metrics';
import { Dict } from '../../types/types';

@@ -47,7 +47,7 @@ const ISSUE_MEASURES = [
];

export const DEFAULT_ISSUES_QUERY = {
simpleStatuses: `${IssueSimpleStatus.Open},${IssueSimpleStatus.Confirmed}`,
issueStatuses: `${IssueStatus.Open},${IssueStatus.Confirmed}`,
};

const issueParamsPerMetric: Dict<Dict<string>> = {
@@ -61,10 +61,10 @@ const issueParamsPerMetric: Dict<Dict<string>> = {
[MetricKey.new_minor_violations]: { severities: 'MINOR' },
[MetricKey.info_violations]: { severities: 'INFO' },
[MetricKey.new_info_violations]: { severities: 'INFO' },
[MetricKey.open_issues]: { simpleStatuses: IssueSimpleStatus.Open },
[MetricKey.reopened_issues]: { simpleStatuses: IssueSimpleStatus.Open },
[MetricKey.confirmed_issues]: { simpleStatuses: IssueSimpleStatus.Confirmed },
[MetricKey.false_positive_issues]: { simpleStatuses: IssueSimpleStatus.FalsePositive },
[MetricKey.open_issues]: { issueStatuses: IssueStatus.Open },
[MetricKey.reopened_issues]: { issueStatuses: IssueStatus.Open },
[MetricKey.confirmed_issues]: { issueStatuses: IssueStatus.Confirmed },
[MetricKey.false_positive_issues]: { issueStatuses: IssueStatus.FalsePositive },
[MetricKey.code_smells]: { types: 'CODE_SMELL' },
[MetricKey.new_code_smells]: { types: 'CODE_SMELL' },
[MetricKey.bugs]: { types: 'BUG' },

+ 7
- 7
server/sonar-web/src/main/js/helpers/constants.ts View File

@@ -29,7 +29,7 @@ import {
IssueResolution,
IssueScope,
IssueSeverity,
IssueSimpleStatus,
IssueStatus,
IssueType,
} from '../types/issues';
import { RuleType } from '../types/types';
@@ -44,12 +44,12 @@ export const SOFTWARE_QUALITIES = Object.values(SoftwareQuality);

export const STATUSES = ['OPEN', 'CONFIRMED', 'REOPENED', 'RESOLVED', 'CLOSED'];

export const SIMPLE_STATUSES = [
IssueSimpleStatus.Open,
IssueSimpleStatus.Accepted,
IssueSimpleStatus.FalsePositive,
IssueSimpleStatus.Confirmed,
IssueSimpleStatus.Fixed,
export const ISSUE_STATUSES = [
IssueStatus.Open,
IssueStatus.Accepted,
IssueStatus.FalsePositive,
IssueStatus.Confirmed,
IssueStatus.Fixed,
];

export const ISSUE_TYPES: IssueType[] = [

+ 9
- 9
server/sonar-web/src/main/js/helpers/issues.ts View File

@@ -19,7 +19,7 @@
*/
import { BugIcon, CodeSmellIcon, SecurityHotspotIcon, VulnerabilityIcon } from 'design-system';
import { flatten, sortBy } from 'lodash';
import { IssueSimpleStatus, IssueStatus, IssueType, RawIssue } from '../types/issues';
import { IssueDeprecatedStatus, IssueStatus, IssueType, RawIssue } from '../types/issues';
import { MetricKey } from '../types/metrics';
import { Dict, Flow, FlowLocation, FlowType, Issue, TextRange } from '../types/types';
import { UserBase } from '../types/users';
@@ -160,16 +160,16 @@ export function parseIssueFromResponse(
...splitFlows(issue, components),
...prepareClosed(issue),
...ensureTextRange(issue),
simpleStatus:
issue.simpleStatus ??
issueStatus:
issue.issueStatus ??
{
[IssueStatus.Open]: IssueSimpleStatus.Open,
[IssueStatus.Reopened]: IssueSimpleStatus.Open,
[IssueStatus.Closed]: IssueSimpleStatus.Fixed,
[IssueStatus.Resolved]: IssueSimpleStatus.Fixed,
[IssueStatus.Confirmed]: IssueSimpleStatus.Confirmed,
[IssueDeprecatedStatus.Open]: IssueStatus.Open,
[IssueDeprecatedStatus.Reopened]: IssueStatus.Open,
[IssueDeprecatedStatus.Closed]: IssueStatus.Fixed,
[IssueDeprecatedStatus.Resolved]: IssueStatus.Fixed,
[IssueDeprecatedStatus.Confirmed]: IssueStatus.Confirmed,
}[issue.status] ??
IssueSimpleStatus.Open,
IssueStatus.Open,
} as Issue;
}


+ 1
- 1
server/sonar-web/src/main/js/helpers/mocks/issues.ts View File

@@ -82,7 +82,7 @@ export function mockQuery(overrides: Partial<Query> = {}): Query {
impactSoftwareQualities: [],
inNewCodePeriod: false,
sonarsourceSecurity: [],
simpleStatuses: [],
issueStatuses: [],
sort: '',
tags: [],
types: [],

+ 5
- 5
server/sonar-web/src/main/js/helpers/testMocks.ts View File

@@ -33,9 +33,9 @@ import {
import { RuleRepository } from '../types/coding-rules';
import { EditionKey } from '../types/editions';
import {
IssueDeprecatedStatus,
IssueScope,
IssueSeverity,
IssueSimpleStatus,
IssueStatus,
IssueType,
RawIssue,
@@ -312,8 +312,8 @@ export function mockRawIssue(withLocations = false, overrides: Partial<RawIssue>
severity: IssueSeverity.Major,
textRange: { startLine: 25, endLine: 26, startOffset: 0, endOffset: 15 },
type: IssueType.CodeSmell,
status: IssueStatus.Open,
simpleStatus: IssueSimpleStatus.Open,
status: IssueDeprecatedStatus.Open,
issueStatus: IssueStatus.Open,
transitions: [],
scope: IssueScope.Main,
cleanCodeAttributeCategory: CleanCodeAttributeCategory.Responsible,
@@ -365,8 +365,8 @@ export function mockIssue(withLocations = false, overrides: Partial<Issue> = {})
scope: IssueScope.Main,
secondaryLocations: [],
severity: IssueSeverity.Major,
status: IssueStatus.Open,
simpleStatus: IssueSimpleStatus.Open,
status: IssueDeprecatedStatus.Open,
issueStatus: IssueStatus.Open,
textRange: { startLine: 25, endLine: 26, startOffset: 0, endOffset: 15 },
transitions: [],
type: 'BUG',

+ 3
- 3
server/sonar-web/src/main/js/types/issues.ts View File

@@ -58,7 +58,7 @@ export enum IssueResolution {
WontFix = 'WONTFIX',
}

export enum IssueStatus {
export enum IssueDeprecatedStatus {
Open = 'OPEN',
Confirmed = 'CONFIRMED',
Reopened = 'REOPENED',
@@ -66,7 +66,7 @@ export enum IssueStatus {
Closed = 'CLOSED',
}

export enum IssueSimpleStatus {
export enum IssueStatus {
Open = 'OPEN',
Fixed = 'FIXED',
Confirmed = 'CONFIRMED',
@@ -149,7 +149,7 @@ export interface RawIssue {
message?: string;
severity: string;
status: string;
simpleStatus: IssueSimpleStatus;
issueStatus: IssueStatus;
textRange?: TextRange;
type: IssueType;
scope: string;

+ 2
- 2
server/sonar-web/src/main/js/types/types.ts View File

@@ -25,7 +25,7 @@ import {
SoftwareQuality,
} from './clean-code-taxonomy';
import { ComponentQualifier, Visibility } from './component';
import { IssueSimpleStatus, IssueTransition, MessageFormatting } from './issues';
import { IssueStatus, IssueTransition, MessageFormatting } from './issues';
import { NewCodeDefinitionType } from './new-code-definition';
import { UserActive, UserBase } from './users';

@@ -291,7 +291,7 @@ export interface Issue {
secondaryLocations: FlowLocation[];
severity: string;
status: string;
simpleStatus: IssueSimpleStatus;
issueStatus: IssueStatus;
tags?: string[];
textRange?: TextRange;
transitions: IssueTransition[];

+ 7
- 7
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueIndex.java View File

@@ -77,7 +77,7 @@ import org.sonar.api.server.rule.RulesDefinition.OwaspTop10Version;
import org.sonar.api.server.rule.RulesDefinition.PciDssVersion;
import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.System2;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.server.es.EsClient;
import org.sonar.server.es.EsUtils;
import org.sonar.server.es.SearchOptions;
@@ -145,7 +145,7 @@ import static org.sonar.server.issue.index.IssueIndex.Facet.RULES;
import static org.sonar.server.issue.index.IssueIndex.Facet.SANS_TOP_25;
import static org.sonar.server.issue.index.IssueIndex.Facet.SCOPES;
import static org.sonar.server.issue.index.IssueIndex.Facet.SEVERITIES;
import static org.sonar.server.issue.index.IssueIndex.Facet.SIMPLE_STATUSES;
import static org.sonar.server.issue.index.IssueIndex.Facet.ISSUE_STATUSES;
import static org.sonar.server.issue.index.IssueIndex.Facet.SONARSOURCE_SECURITY;
import static org.sonar.server.issue.index.IssueIndex.Facet.STATUSES;
import static org.sonar.server.issue.index.IssueIndex.Facet.TAGS;
@@ -183,7 +183,7 @@ import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_SANS
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_SCOPE;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_SEVERITY;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_SEVERITY_VALUE;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_SIMPLE_STATUS;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_NEW_STATUS;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_SQ_SECURITY_CATEGORY;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_STATUS;
import static org.sonar.server.issue.index.IssueIndexDefinition.FIELD_ISSUE_TAGS;
@@ -217,7 +217,7 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SANS_TOP_25;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SCOPES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SEVERITIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SIMPLE_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SONARSOURCE_SECURITY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TAGS;
@@ -267,7 +267,7 @@ public class IssueIndex {
STATUSES(PARAM_STATUSES, FIELD_ISSUE_STATUS, STICKY, Issue.STATUSES.size()),
// Resolutions facet returns one more element than the number of resolutions to take into account unresolved issues
RESOLUTIONS(PARAM_RESOLUTIONS, FIELD_ISSUE_RESOLUTION, STICKY, Issue.RESOLUTIONS.size() + 1),
SIMPLE_STATUSES(PARAM_SIMPLE_STATUSES, FIELD_ISSUE_SIMPLE_STATUS, STICKY, SimpleStatus.values().length),
ISSUE_STATUSES(PARAM_ISSUE_STATUSES, FIELD_ISSUE_NEW_STATUS, STICKY, IssueStatus.values().length),
TYPES(PARAM_TYPES, FIELD_ISSUE_TYPE, STICKY, RuleType.values().length),
SCOPES(PARAM_SCOPES, FIELD_ISSUE_SCOPE, STICKY, MAX_FACET_SIZE),
LANGUAGES(PARAM_LANGUAGES, FIELD_ISSUE_LANGUAGE, STICKY, MAX_FACET_SIZE),
@@ -486,7 +486,7 @@ public class IssueIndex {
FIELD_ISSUE_RULE_UUID,
query.ruleUuids()));
filters.addFilter(FIELD_ISSUE_STATUS, STATUSES.getFilterScope(), createTermsFilter(FIELD_ISSUE_STATUS, query.statuses()));
filters.addFilter(FIELD_ISSUE_SIMPLE_STATUS, SIMPLE_STATUSES.getFilterScope(), createTermsFilter(FIELD_ISSUE_SIMPLE_STATUS, query.simpleStatuses()));
filters.addFilter(FIELD_ISSUE_NEW_STATUS, ISSUE_STATUSES.getFilterScope(), createTermsFilter(FIELD_ISSUE_NEW_STATUS, query.issueStatuses()));
filters.addFilter(FIELD_ISSUE_CODE_VARIANTS, CODE_VARIANTS.getFilterScope(), createTermsFilter(FIELD_ISSUE_CODE_VARIANTS, query.codeVariants()));

// security category
@@ -845,7 +845,7 @@ public class IssueIndex {
private void configureTopAggregations(TopAggregationHelper aggregationHelper, IssueQuery query, SearchOptions options,
AllFilters queryFilters, SearchSourceBuilder esRequest) {
addFacetIfNeeded(options, aggregationHelper, esRequest, STATUSES, NO_SELECTED_VALUES);
addFacetIfNeeded(options, aggregationHelper, esRequest, SIMPLE_STATUSES, query.simpleStatuses().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, ISSUE_STATUSES, query.issueStatuses().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, PROJECT_UUIDS, query.projectUuids().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, DIRECTORIES, query.directories().toArray());
addFacetIfNeeded(options, aggregationHelper, esRequest, FILES, query.files().toArray());

+ 7
- 7
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQuery.java View File

@@ -62,7 +62,7 @@ public class IssueQuery {
private final Collection<String> impactSeverities;
private final Collection<String> impactSoftwareQualities;
private final Collection<String> statuses;
private final Collection<String> simpleStatuses;
private final Collection<String> issueStatuses;
private final Collection<String> resolutions;
private final Collection<String> components;
private final Collection<String> projects;
@@ -111,7 +111,7 @@ public class IssueQuery {
this.impactSoftwareQualities = defaultCollection(builder.impactSoftwareQualities);
this.statuses = defaultCollection(builder.statuses);
this.resolutions = defaultCollection(builder.resolutions);
this.simpleStatuses = defaultCollection(builder.simpleStatuses);
this.issueStatuses = defaultCollection(builder.issueStatuses);
this.components = defaultCollection(builder.components);
this.projects = defaultCollection(builder.projects);
this.directories = defaultCollection(builder.directories);
@@ -173,8 +173,8 @@ public class IssueQuery {
return statuses;
}

public Collection<String> simpleStatuses() {
return simpleStatuses;
public Collection<String> issueStatuses() {
return issueStatuses;
}

public Collection<String> resolutions() {
@@ -368,7 +368,7 @@ public class IssueQuery {
private Collection<String> impactSoftwareQualities;
private Collection<String> statuses;
private Collection<String> resolutions;
private Collection<String> simpleStatuses;
private Collection<String> issueStatuses;
private Collection<String> components;
private Collection<String> projects;
private Collection<String> directories;
@@ -433,8 +433,8 @@ public class IssueQuery {
return this;
}

public Builder simpleStatuses(@Nullable Collection<String> l) {
this.simpleStatuses = l;
public Builder issueStatuses(@Nullable Collection<String> l) {
this.issueStatuses = l;
return this;
}


+ 1
- 1
server/sonar-webserver-es/src/main/java/org/sonar/server/issue/index/IssueQueryFactory.java View File

@@ -129,7 +129,7 @@ public class IssueQueryFactory {
.impactSeverities(request.getImpactSeverities())
.statuses(request.getStatuses())
.resolutions(request.getResolutions())
.simpleStatuses(request.getSimpleStatuses())
.issueStatuses(request.getIssueStatuses())
.resolved(request.getResolved())
.rules(ruleDtos)
.ruleUuids(ruleUuids)

+ 14
- 14
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFacetsTest.java View File

@@ -29,7 +29,7 @@ import org.junit.Test;
import org.sonar.api.issue.impact.Severity;
import org.sonar.api.rules.RuleType;
import org.sonar.api.server.rule.RulesDefinition.OwaspAsvsVersion;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.server.es.Facets;
@@ -372,23 +372,23 @@ public class IssueIndexFacetsTest extends IssueIndexTestCommon {
}

@Test
public void search_shouldReturnSimpleStatusesFacet() {
public void search_shouldReturnIssueStatusesFacet() {
ComponentDto mainBranch = newPrivateProjectDto();
ComponentDto file = newFileDto(mainBranch);

indexIssues(
newDoc("I1", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.CONFIRMED.name()),
newDoc("I2", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.FIXED.name()),
newDoc("I3", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.OPEN.name()),
newDoc("I4", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.OPEN.name()),
newDoc("I5", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.ACCEPTED.name()),
newDoc("I6", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.ACCEPTED.name()),
newDoc("I7", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.ACCEPTED.name()),
newDoc("I8", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.FALSE_POSITIVE.name()),
newDoc("I9", mainBranch.uuid(), file).setSimpleStatus(SimpleStatus.FALSE_POSITIVE.name()));
assertThatFacetHasSize(IssueQuery.builder().build(), "simpleStatuses", 5);
assertThatFacetHasOnly(IssueQuery.builder(), "simpleStatuses",
newDoc("I1", mainBranch.uuid(), file).setIssueStatus(IssueStatus.CONFIRMED.name()),
newDoc("I2", mainBranch.uuid(), file).setIssueStatus(IssueStatus.FIXED.name()),
newDoc("I3", mainBranch.uuid(), file).setIssueStatus(IssueStatus.OPEN.name()),
newDoc("I4", mainBranch.uuid(), file).setIssueStatus(IssueStatus.OPEN.name()),
newDoc("I5", mainBranch.uuid(), file).setIssueStatus(IssueStatus.ACCEPTED.name()),
newDoc("I6", mainBranch.uuid(), file).setIssueStatus(IssueStatus.ACCEPTED.name()),
newDoc("I7", mainBranch.uuid(), file).setIssueStatus(IssueStatus.ACCEPTED.name()),
newDoc("I8", mainBranch.uuid(), file).setIssueStatus(IssueStatus.FALSE_POSITIVE.name()),
newDoc("I9", mainBranch.uuid(), file).setIssueStatus(IssueStatus.FALSE_POSITIVE.name()));
assertThatFacetHasSize(IssueQuery.builder().build(), "issueStatuses", 5);
assertThatFacetHasOnly(IssueQuery.builder(), "issueStatuses",
entry("OPEN", 2L),
entry("CONFIRMED", 1L),
entry("FALSE_POSITIVE", 2L),

+ 15
- 15
server/sonar-webserver-es/src/test/java/org/sonar/server/issue/index/IssueIndexFiltersTest.java View File

@@ -28,7 +28,7 @@ import org.junit.Test;
import org.sonar.api.issue.Issue;
import org.sonar.api.rule.Severity;
import org.sonar.api.rules.RuleType;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.rule.RuleDto;
import org.sonar.server.es.SearchOptions;
@@ -925,28 +925,28 @@ public class IssueIndexFiltersTest extends IssueIndexTestCommon {
}

@Test
public void search_whenFilteringBySimpleStatus_shouldReturnRelevantIssues() {
public void search_whenFilteringByIssueStatus_shouldReturnRelevantIssues() {
ComponentDto project = newPrivateProjectDto();
ComponentDto file = newFileDto(project);

indexIssues(
newDoc("I1", project.uuid(), file).setSimpleStatus(SimpleStatus.CONFIRMED.name()),
newDoc("I2", project.uuid(), file).setSimpleStatus(SimpleStatus.FIXED.name()),
newDoc("I3", project.uuid(), file).setSimpleStatus(SimpleStatus.OPEN.name()),
newDoc("I4", project.uuid(), file).setSimpleStatus(SimpleStatus.OPEN.name()),
newDoc("I5", project.uuid(), file).setSimpleStatus(SimpleStatus.ACCEPTED.name()),
newDoc("I6", project.uuid(), file).setSimpleStatus(SimpleStatus.ACCEPTED.name()),
newDoc("I7", project.uuid(), file).setSimpleStatus(SimpleStatus.ACCEPTED.name()),
newDoc("I8", project.uuid(), file).setSimpleStatus(SimpleStatus.FALSE_POSITIVE.name()),
newDoc("I9", project.uuid(), file).setSimpleStatus(SimpleStatus.FALSE_POSITIVE.name()));
assertThatSearchReturnsOnly(IssueQuery.builder().simpleStatuses(Set.of(SimpleStatus.CONFIRMED.name(), SimpleStatus.OPEN.name())),
newDoc("I1", project.uuid(), file).setIssueStatus(IssueStatus.CONFIRMED.name()),
newDoc("I2", project.uuid(), file).setIssueStatus(IssueStatus.FIXED.name()),
newDoc("I3", project.uuid(), file).setIssueStatus(IssueStatus.OPEN.name()),
newDoc("I4", project.uuid(), file).setIssueStatus(IssueStatus.OPEN.name()),
newDoc("I5", project.uuid(), file).setIssueStatus(IssueStatus.ACCEPTED.name()),
newDoc("I6", project.uuid(), file).setIssueStatus(IssueStatus.ACCEPTED.name()),
newDoc("I7", project.uuid(), file).setIssueStatus(IssueStatus.ACCEPTED.name()),
newDoc("I8", project.uuid(), file).setIssueStatus(IssueStatus.FALSE_POSITIVE.name()),
newDoc("I9", project.uuid(), file).setIssueStatus(IssueStatus.FALSE_POSITIVE.name()));
assertThatSearchReturnsOnly(IssueQuery.builder().issueStatuses(Set.of(IssueStatus.CONFIRMED.name(), IssueStatus.OPEN.name())),
"I1", "I3", "I4");

assertThatSearchReturnsOnly(IssueQuery.builder().simpleStatuses(Set.of(SimpleStatus.FALSE_POSITIVE.name(), SimpleStatus.ACCEPTED.name())),
assertThatSearchReturnsOnly(IssueQuery.builder().issueStatuses(Set.of(IssueStatus.FALSE_POSITIVE.name(), IssueStatus.ACCEPTED.name())),
"I5", "I6", "I7", "I8", "I9");

assertThatSearchReturnsOnly(IssueQuery.builder().simpleStatuses(Set.of(SimpleStatus.FIXED.name())),
assertThatSearchReturnsOnly(IssueQuery.builder().issueStatuses(Set.of(IssueStatus.FIXED.name())),
"I2");
}


+ 19
- 19
server/sonar-webserver-webapi/src/it/java/org/sonar/server/issue/ws/SearchActionIT.java View File

@@ -48,7 +48,7 @@ import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.Durations;
import org.sonar.api.utils.System2;
import org.sonar.api.web.UserRole;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.core.util.UuidFactoryFast;
import org.sonar.core.util.Uuids;
import org.sonar.db.DbClient;
@@ -145,7 +145,7 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_IMPACT_SOFT
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_IN_NEW_CODE_PERIOD;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_PULL_REQUEST;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SIMPLE_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_STATUSES;

public class SearchActionIT {
@@ -605,7 +605,7 @@ public class SearchActionIT {
}

@Test
public void search_whenFilteringBySimpleStatuses_shouldReturnSimpleStatusesFacet() {
public void search_whenFilteringByIssueStatuses_shouldReturnIssueStatusesFacet() {
RuleDto rule = newIssueRule();
ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID").setLanguage("java")).getMainBranchComponent();
@@ -620,8 +620,8 @@ public class SearchActionIT {
indexPermissionsAndIssues();

SearchWsResponse response = ws.newRequest()
.setParam(PARAM_SIMPLE_STATUSES, SimpleStatus.ACCEPTED.name())
.setParam(FACETS, PARAM_SIMPLE_STATUSES)
.setParam(PARAM_ISSUE_STATUSES, IssueStatus.ACCEPTED.name())
.setParam(FACETS, PARAM_ISSUE_STATUSES)
.executeProtobuf(SearchWsResponse.class);

List<Issue> issuesList = response.getIssuesList();
@@ -630,19 +630,19 @@ public class SearchActionIT {
.containsExactlyInAnyOrder(expectedIssue.getKey());

Optional<Common.Facet> first = response.getFacets().getFacetsList()
.stream().filter(facet -> facet.getProperty().equals(PARAM_SIMPLE_STATUSES))
.stream().filter(facet -> facet.getProperty().equals(PARAM_ISSUE_STATUSES))
.findFirst();
assertThat(first.get().getValuesList())
.extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
.containsExactlyInAnyOrder(
tuple(SimpleStatus.OPEN.name(), 1L),
tuple(SimpleStatus.ACCEPTED.name(), 1L),
tuple(SimpleStatus.FIXED.name(), 2L),
tuple(SimpleStatus.FALSE_POSITIVE.name(), 1L));
tuple(IssueStatus.OPEN.name(), 1L),
tuple(IssueStatus.ACCEPTED.name(), 1L),
tuple(IssueStatus.FIXED.name(), 2L),
tuple(IssueStatus.FALSE_POSITIVE.name(), 1L));
}

@Test
public void search_whenSimpleStatusesFacetRequested_shouldReturnFacet() {
public void search_whenIssueStatusesFacetRequested_shouldReturnFacet() {
RuleDto rule = newIssueRule();
ComponentDto project = db.components().insertPublicProject("PROJECT_ID",
c -> c.setKey("PROJECT_KEY").setName("NAME_PROJECT_ID").setLongName("LONG_NAME_PROJECT_ID").setLanguage("java")).getMainBranchComponent();
@@ -660,20 +660,20 @@ public class SearchActionIT {
indexPermissionsAndIssues();

SearchWsResponse response = ws.newRequest()
.setParam(FACETS, PARAM_SIMPLE_STATUSES)
.setParam(FACETS, PARAM_ISSUE_STATUSES)
.executeProtobuf(SearchWsResponse.class);

Optional<Common.Facet> first = response.getFacets().getFacetsList()
.stream().filter(facet -> facet.getProperty().equals(PARAM_SIMPLE_STATUSES))
.stream().filter(facet -> facet.getProperty().equals(PARAM_ISSUE_STATUSES))
.findFirst();
assertThat(first.get().getValuesList())
.extracting(Common.FacetValue::getVal, Common.FacetValue::getCount)
.containsExactlyInAnyOrder(
tuple(SimpleStatus.OPEN.name(), 2L),
tuple(SimpleStatus.ACCEPTED.name(), 1L),
tuple(SimpleStatus.CONFIRMED.name(), 1L),
tuple(SimpleStatus.FIXED.name(), 3L),
tuple(SimpleStatus.FALSE_POSITIVE.name(), 1L));
tuple(IssueStatus.OPEN.name(), 2L),
tuple(IssueStatus.ACCEPTED.name(), 1L),
tuple(IssueStatus.CONFIRMED.name(), 1L),
tuple(IssueStatus.FIXED.name(), 3L),
tuple(IssueStatus.FALSE_POSITIVE.name(), 1L));

}

@@ -2082,7 +2082,7 @@ public class SearchActionIT {
"createdBefore", "createdInLast", "directories", "facets", "files", "issues", "scopes", "languages", "onComponentOnly",
"p", "projects", "ps", "resolutions", "resolved", "rules", "s", "severities", "statuses", "tags", "types", "pciDss-3.2", "pciDss-4.0", "owaspAsvs-4.0",
"owaspAsvsLevel", "owaspTop10", "owaspTop10-2021", "sansTop25", "cwe", "sonarsourceSecurity", "timeZone", "inNewCodePeriod", "codeVariants",
"cleanCodeAttributeCategories", "impactSeverities", "impactSoftwareQualities", "simpleStatuses");
"cleanCodeAttributeCategories", "impactSeverities", "impactSoftwareQualities", "issueStatuses");

WebService.Param branch = def.param(PARAM_BRANCH);
assertThat(branch.isInternal()).isFalse();

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/AddCommentAction.java View File

@@ -72,8 +72,8 @@ public class AddCommentAction implements IssuesWsAction {
"Requires authentication and the following permission: 'Browse' on the project of the specified issue.")
.setSince("3.6")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response."),
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response."),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("9.6", "Response field 'ruleDescriptionContextKey' added"),
new Change("8.8", "The response field components.uuid is removed"),

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/AssignAction.java View File

@@ -75,8 +75,8 @@ public class AssignAction implements IssuesWsAction {
.setDescription("Assign/Unassign an issue. Requires authentication and Browse permission on project")
.setSince("3.6")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response."),
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response."),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("9.6", "Response field 'ruleDescriptionContextKey' added"),
new Change("8.8", "The response field components.uuid is removed"),

+ 1
- 1
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ChangelogAction.java View File

@@ -56,7 +56,7 @@ public class ChangelogAction implements IssuesWsAction {
"Requires the 'Browse' permission on the project of the specified issue.")
.setSince("4.1")
.setChangelog(
new Change("10.4", "'simpleStatus' key is added in the differences"),
new Change("10.4", "'issueStatus' key is added in the differences"),
new Change("10.4", "'status' and 'resolution' keys are now deprecated in the differences"),
new Change("9.7", "'externalUser' and 'webhookSource' information added to the answer"),
new Change("6.3", "changes on effort is expressed with the raw value in minutes (instead of the duration previously)"))

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DeleteCommentAction.java View File

@@ -60,8 +60,8 @@ public class DeleteCommentAction implements IssuesWsAction {
"Requires authentication and the following permission: 'Browse' on the project of the specified issue.")
.setSince("3.6")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response."),
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response."),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("9.6", "Response field 'ruleDescriptionContextKey' added"),
new Change("8.8", "The response field components.uuid is removed"),

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/DoTransitionAction.java View File

@@ -82,8 +82,8 @@ public class DoTransitionAction implements IssuesWsAction {
"The transitions involving security hotspots require the permission 'Administer Security Hotspot'.")
.setSince("3.6")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response."),
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response."),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("9.6", "Response field 'ruleDescriptionContextKey' added"),
new Change("8.8", "The response field components.uuid is removed"),

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/EditCommentAction.java View File

@@ -66,8 +66,8 @@ public class EditCommentAction implements IssuesWsAction {
"Requires authentication and the following permission: 'Browse' on the project of the specified issue.")
.setSince("3.6")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response."),
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response."),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("9.6", "Response field 'ruleDescriptionContextKey' added"),
new Change("8.8", "The response field components.uuid is removed"),

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/ListAction.java View File

@@ -96,8 +96,8 @@ public class ListAction implements IssuesWsAction {
"<br>Requires the 'Browse' permission on the specified project. ")
.setSince("10.2")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response.")
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response.")
)
.setResponseExample(getClass().getResource("list-example.json"));


+ 14
- 14
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchAction.java View File

@@ -44,7 +44,7 @@ import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.Paging;
import org.sonar.api.utils.System2;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.user.UserDto;
@@ -129,7 +129,7 @@ import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_RULES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SANS_TOP_25;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SCOPES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SEVERITIES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SIMPLE_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_ISSUE_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_SONARSOURCE_SECURITY;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_STATUSES;
import static org.sonarqube.ws.client.issue.IssuesWsParameters.PARAM_TAGS;
@@ -169,7 +169,7 @@ public class SearchAction implements IssuesWsAction {
PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES,
PARAM_IMPACT_SOFTWARE_QUALITIES,
PARAM_IMPACT_SEVERITIES,
PARAM_SIMPLE_STATUSES);
PARAM_ISSUE_STATUSES);

private static final String INTERNAL_PARAMETER_DISCLAIMER = "This parameter is mostly used by the Issues page, please prefer usage of the componentKeys parameter. ";
private static final String NEW_FACET_ADDED_MESSAGE = "Facet '%s' has been added";
@@ -207,14 +207,14 @@ public class SearchAction implements IssuesWsAction {
+ "<br/>When issue indexation is in progress returns 503 service unavailable HTTP code.")
.setSince("3.6")
.setChangelog(
new Change("10.4", format(NEW_PARAM_ADDED_MESSAGE, PARAM_SIMPLE_STATUSES)),
new Change("10.4", format("Parameters '%s' and '%s' are deprecated in favor of '%s'.", PARAM_RESOLUTIONS, PARAM_STATUSES, PARAM_SIMPLE_STATUSES)),
new Change("10.4", format(NEW_PARAM_ADDED_MESSAGE, PARAM_ISSUE_STATUSES)),
new Change("10.4", format("Parameters '%s' and '%s' are deprecated in favor of '%s'.", PARAM_RESOLUTIONS, PARAM_STATUSES, PARAM_ISSUE_STATUSES)),
new Change("10.4", format("Parameter '%s' is deprecated.", PARAM_SEVERITIES)),
new Change("10.4", format(NEW_FACET_ADDED_MESSAGE, PARAM_SIMPLE_STATUSES)),
new Change("10.4", format("Facets '%s' and '%s' are deprecated in favor of '%s'", PARAM_RESOLUTIONS, PARAM_STATUSES, PARAM_SIMPLE_STATUSES)),
new Change("10.4", "Response field 'simpleStatus' added"),
new Change("10.4", "Response fields 'status' and 'resolutions' are deprecated, in favor of 'simpleStatus'"),
new Change("10.4", format("Possible value '%s' for 'simpleStatus' field is deprecated.", SimpleStatus.CONFIRMED)),
new Change("10.4", format(NEW_FACET_ADDED_MESSAGE, PARAM_ISSUE_STATUSES)),
new Change("10.4", format("Facets '%s' and '%s' are deprecated in favor of '%s'", PARAM_RESOLUTIONS, PARAM_STATUSES, PARAM_ISSUE_STATUSES)),
new Change("10.4", "Response field 'issueStatus' added"),
new Change("10.4", "Response fields 'status' and 'resolutions' are deprecated, in favor of 'issueStatus'"),
new Change("10.4", format("Possible value '%s' for 'issueStatus' field is deprecated.", IssueStatus.CONFIRMED)),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("10.2", format(NEW_PARAM_ADDED_MESSAGE, PARAM_IMPACT_SOFTWARE_QUALITIES)),
new Change("10.2", format(NEW_PARAM_ADDED_MESSAGE, PARAM_IMPACT_SEVERITIES)),
@@ -409,10 +409,10 @@ public class SearchAction implements IssuesWsAction {
.setDescription("Comma-separated list of code variants.")
.setExampleValue("windows,linux")
.setSince("10.1");
action.createParam(PARAM_SIMPLE_STATUSES)
action.createParam(PARAM_ISSUE_STATUSES)
.setDescription("")
.setPossibleValues(SimpleStatus.values())
.setExampleValue("%s,%S".formatted(SimpleStatus.ACCEPTED, SimpleStatus.FIXED))
.setPossibleValues(IssueStatus.values())
.setExampleValue("%s,%S".formatted(IssueStatus.ACCEPTED, IssueStatus.FIXED))
.setSince("10.4");
}

@@ -638,7 +638,7 @@ public class SearchAction implements IssuesWsAction {
.setImpactSoftwareQualities(request.paramAsStrings(PARAM_IMPACT_SOFTWARE_QUALITIES))
.setCleanCodeAttributesCategories(request.paramAsStrings(PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES))
.setStatuses(request.paramAsStrings(PARAM_STATUSES))
.setSimpleStatuses(request.paramAsStrings(PARAM_SIMPLE_STATUSES))
.setIssueStatuses(request.paramAsStrings(PARAM_ISSUE_STATUSES))
.setTags(request.paramAsStrings(PARAM_TAGS))
.setTypes(allRuleTypesExceptHotspotsIfEmpty(request.paramAsStrings(PARAM_TYPES)))
.setPciDss32(request.paramAsStrings(PARAM_PCI_DSS_32))

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SearchResponseFormat.java View File

@@ -37,7 +37,7 @@ import org.sonar.api.utils.DateUtils;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.Durations;
import org.sonar.api.utils.Paging;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
import org.sonar.db.component.ComponentDto;
@@ -205,7 +205,7 @@ public class SearchResponseFormat {
ofNullable(data.getUserByUuid(dto.getAssigneeUuid())).ifPresent(assignee -> issueBuilder.setAssignee(assignee.getLogin()));
ofNullable(emptyToNull(dto.getResolution())).ifPresent(issueBuilder::setResolution);
issueBuilder.setStatus(dto.getStatus());
Optional.ofNullable(SimpleStatus.of(dto.getStatus(), dto.getResolution())).map(SimpleStatus::name).ifPresent(issueBuilder::setSimpleStatus);
Optional.ofNullable(IssueStatus.of(dto.getStatus(), dto.getResolution())).map(IssueStatus::name).ifPresent(issueBuilder::setIssueStatus);
issueBuilder.setMessage(nullToEmpty(dto.getMessage()));
issueBuilder.addAllMessageFormattings(MessageFormattingUtils.dbMessageFormattingToWs(dto.parseMessageFormattings()));
issueBuilder.addAllTags(dto.getTags());

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetSeverityAction.java View File

@@ -79,8 +79,8 @@ public class SetSeverityAction implements IssuesWsAction {
"</ul>")
.setSince("3.6")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response."),
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response."),
new Change("10.2", "This endpoint is now deprecated."),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("9.6", "Response field 'ruleDescriptionContextKey' added"),

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTagsAction.java View File

@@ -74,8 +74,8 @@ public class SetTagsAction implements IssuesWsAction {
.setDescription("Set tags on an issue. <br/>" +
"Requires authentication and Browse permission on project")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response."),
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response."),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("9.6", "Response field 'ruleDescriptionContextKey' added"),
new Change("8.8", "The response field components.uuid is removed"),

+ 2
- 2
server/sonar-webserver-webapi/src/main/java/org/sonar/server/issue/ws/SetTypeAction.java View File

@@ -83,8 +83,8 @@ public class SetTypeAction implements IssuesWsAction {
"</ul>")
.setSince("5.5")
.setChangelog(
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'simpleStatus' instead."),
new Change("10.4", "Add 'simpleStatus' field to the response."),
new Change("10.4", "The response fields 'status' and 'resolution' are deprecated. Please use 'issueStatus' instead."),
new Change("10.4", "Add 'issueStatus' field to the response."),
new Change("10.2", "Add 'impacts', 'cleanCodeAttribute', 'cleanCodeAttributeCategory' fields to the response"),
new Change("10.2", "This endpoint is now deprecated."),
new Change("9.6", "Response field 'ruleDescriptionContextKey' added"),

+ 1
- 1
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/add_comment-example.json View File

@@ -22,7 +22,7 @@
},
"flows": [],
"status": "CONFIRMED",
"simpleStatus": "CONFIRMED",
"issueStatus": "CONFIRMED",
"message": "Provide multiple methods instead of using \"modal\" to determine which action to take.",
"effort": "15min",
"debt": "15min",

+ 1
- 1
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/assign-example.json View File

@@ -22,7 +22,7 @@
},
"flows": [],
"status": "CONFIRMED",
"simpleStatus": "CONFIRMED",
"issueStatus": "CONFIRMED",
"message": "Provide multiple methods instead of using \"modal\" to determine which action to take.",
"effort": "15min",
"debt": "15min",

+ 1
- 1
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/delete_comment-example.json View File

@@ -22,7 +22,7 @@
},
"flows": [],
"status": "CONFIRMED",
"simpleStatus": "CONFIRMED",
"issueStatus": "CONFIRMED",
"message": "Provide multiple methods instead of using \"modal\" to determine which action to take.",
"effort": "15min",
"debt": "15min",

+ 1
- 1
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/do_transition-example.json View File

@@ -22,7 +22,7 @@
},
"flows": [],
"status": "CONFIRMED",
"simpleStatus": "CONFIRMED",
"issueStatus": "CONFIRMED",
"message": "Provide multiple methods instead of using \"modal\" to determine which action to take.",
"effort": "15min",
"debt": "15min",

+ 1
- 1
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/edit_comment-example.json View File

@@ -22,7 +22,7 @@
},
"flows": [],
"status": "CONFIRMED",
"simpleStatus": "CONFIRMED",
"issueStatus": "CONFIRMED",
"message": "Provide multiple methods instead of using \"modal\" to determine which action to take.",
"effort": "15min",
"debt": "15min",

+ 1
- 1
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/search-example.json View File

@@ -15,7 +15,7 @@
"severity": "MAJOR",
"cleanCodeAttribute": "CLEAR",
"cleanCodeAttributeCategory": "INTENTIONAL",
"simpleStatus": "ACCEPTED",
"issueStatus": "ACCEPTED",
"impacts": [
{
"softwareQuality": "SECURITY",

+ 1
- 1
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/set_severity-example.json View File

@@ -22,7 +22,7 @@
},
"flows": [],
"status": "CONFIRMED",
"simpleStatus": "CONFIRMED",
"issueStatus": "CONFIRMED",
"message": "Provide multiple methods instead of using \"modal\" to determine which action to take.",
"effort": "15min",
"debt": "15min",

+ 1
- 1
server/sonar-webserver-webapi/src/main/resources/org/sonar/server/issue/ws/set_type-example.json View File

@@ -22,7 +22,7 @@
},
"flows": [],
"status": "CONFIRMED",
"simpleStatus": "CONFIRMED",
"issueStatus": "CONFIRMED",
"message": "Provide multiple methods instead of using \"modal\" to determine which action to take.",
"effort": "15min",
"debt": "15min",

+ 3
- 3
server/sonar-webserver-webapi/src/test/java/org/sonar/server/issue/ws/SearchResponseFormatFormatOperationTest.java View File

@@ -33,7 +33,7 @@ import org.sonar.api.resources.Languages;
import org.sonar.api.rules.CleanCodeAttribute;
import org.sonar.api.utils.Duration;
import org.sonar.api.utils.Durations;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.db.DbTester;
import org.sonar.db.component.BranchDto;
import org.sonar.db.component.BranchType;
@@ -282,13 +282,13 @@ public class SearchResponseFormatFormatOperationTest {
}

@Test
public void formatOperation_shouldReturnExpectedSimpleStatus() {
public void formatOperation_shouldReturnExpectedIssueStatus() {
issueDto.setStatus(org.sonar.api.issue.Issue.STATUS_RESOLVED);
issueDto.setResolution(org.sonar.api.issue.Issue.RESOLUTION_WONT_FIX);

Operation result = searchResponseFormat.formatOperation(searchResponseData);

assertThat(result.getIssue().getSimpleStatus()).isEqualTo(SimpleStatus.ACCEPTED.name());
assertThat(result.getIssue().getIssueStatus()).isEqualTo(IssueStatus.ACCEPTED.name());
}

private SearchResponseData newSearchResponseDataMainBranch() {

+ 3
- 3
sonar-core/src/main/java/org/sonar/core/issue/DefaultIssue.java View File

@@ -48,7 +48,7 @@ import org.sonar.api.rule.Severity;
import org.sonar.api.rules.CleanCodeAttribute;
import org.sonar.api.rules.RuleType;
import org.sonar.api.utils.Duration;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;
import org.sonar.core.issue.tracking.Trackable;

import static org.sonar.api.utils.DateUtils.truncateToSeconds;
@@ -345,9 +345,9 @@ public class DefaultIssue implements Issue, Trackable, org.sonar.api.ce.measure.
}

@Nullable
public SimpleStatus getSimpleStatus() {
public IssueStatus getIssueStatus() {
Preconditions.checkArgument(!Strings.isNullOrEmpty(status), "Status must be set");
return SimpleStatus.of(status, resolution);
return IssueStatus.of(status, resolution);
}

@Override

sonar-core/src/main/java/org/sonar/core/issue/status/SimpleStatus.java → sonar-core/src/main/java/org/sonar/core/issue/status/IssueStatus.java View File

@@ -25,7 +25,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.issue.Issue;

public enum SimpleStatus {
public enum IssueStatus {


OPEN,
@@ -34,19 +34,19 @@ public enum SimpleStatus {
ACCEPTED,
FIXED;

private static final Logger LOGGER = LoggerFactory.getLogger(SimpleStatus.class);
private static final Logger LOGGER = LoggerFactory.getLogger(IssueStatus.class);

@CheckForNull
public static SimpleStatus of(String status, @Nullable String resolution) {
public static IssueStatus of(String status, @Nullable String resolution) {
switch (status) {
case Issue.STATUS_OPEN:
case Issue.STATUS_REOPENED:
return SimpleStatus.OPEN;
return IssueStatus.OPEN;
case Issue.STATUS_CONFIRMED:
return SimpleStatus.CONFIRMED;
return IssueStatus.CONFIRMED;
case Issue.STATUS_CLOSED:
return SimpleStatus.FIXED;
// Security hotspot should not return simple status as they are deprecated.
return IssueStatus.FIXED;
// Security hotspot should not return issue status as they are deprecated.
case Issue.STATUS_REVIEWED:
case Issue.STATUS_TO_REVIEW:
return null;
@@ -55,15 +55,15 @@ public enum SimpleStatus {
if (Issue.STATUS_RESOLVED.equals(status) && resolution != null) {
switch (resolution) {
case Issue.RESOLUTION_FALSE_POSITIVE:
return SimpleStatus.FALSE_POSITIVE;
return IssueStatus.FALSE_POSITIVE;
case Issue.RESOLUTION_WONT_FIX:
return SimpleStatus.ACCEPTED;
return IssueStatus.ACCEPTED;
case Issue.RESOLUTION_FIXED:
return SimpleStatus.FIXED;
return IssueStatus.FIXED;
default:
}
}
LOGGER.warn("Can't find mapped simple status for status '{}' and resolution '{}'", status, resolution);
LOGGER.warn("Can't find mapped issue status for status '{}' and resolution '{}'", status, resolution);
return null;
}
}

+ 6
- 12
sonar-core/src/main/resources/org/sonar/l10n/core.properties View File

@@ -1054,11 +1054,11 @@ issue.clean_code_attribute.TRUSTWORTHY=Not trustworthy
issue.clean_code_attribute.TRUSTWORTHY.title=This is a responsibility issue, the code is not trustworthy enough.
issue.clean_code_attribute.TRUSTWORTHY.advice=To be trustworthy, the code needs to abstain from revealing or hard-coding private information.

issue.simple_status.OPEN=Open
issue.simple_status.ACCEPTED=Accepted
issue.simple_status.CONFIRMED=Confirmed
issue.simple_status.FIXED=Fixed
issue.simple_status.FALSE_POSITIVE=False Positive
issue.issue_status.OPEN=Open
issue.issue_status.ACCEPTED=Accepted
issue.issue_status.CONFIRMED=Confirmed
issue.issue_status.FIXED=Fixed
issue.issue_status.FALSE_POSITIVE=False Positive

issue.status.ACCEPTED=Accepted
issue.status.REOPENED=Reopened
@@ -1070,12 +1070,6 @@ issue.status.TO_REVIEW=To Review
issue.status.IN_REVIEW=In Review
issue.status.REVIEWED=Reviewed

issue.simple_status.OPEN=Open
issue.simple_status.ACCEPTED=Accepted
issue.simple_status.CONFIRMED=Confirmed
issue.simple_status.FIXED=Fixed
issue.simple_status.FALSE_POSITIVE=False Positive

issue.scope.MAIN=Main code
issue.scope.TEST=Test code

@@ -1180,7 +1174,7 @@ issues.facet.types=Type
issues.facet.severities=Severity
issues.facet.scopes=Scope
issues.facet.projects=Project
issues.facet.simpleStatuses=Status
issues.facet.issueStatuses=Status
issues.facet.hotspotStatuses=Hotspot Status
issues.facet.assignees=Assignee
issues.facet.files=File

+ 5
- 5
sonar-core/src/test/java/org/sonar/core/issue/DefaultIssueTest.java View File

@@ -27,7 +27,7 @@ import org.sonar.api.issue.Issue;
import org.sonar.api.issue.impact.Severity;
import org.sonar.api.issue.impact.SoftwareQuality;
import org.sonar.api.utils.Duration;
import org.sonar.core.issue.status.SimpleStatus;
import org.sonar.core.issue.status.IssueStatus;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
@@ -305,18 +305,18 @@ public class DefaultIssueTest {
}

@Test
public void getSimpleStatus_shouldReturnExpectedStatus() {
public void getIssueStatus_shouldReturnExpectedStatus() {
issue.setStatus(Issue.STATUS_RESOLVED);
issue.setResolution(Issue.RESOLUTION_FIXED);

assertThat(issue.getSimpleStatus()).isEqualTo(SimpleStatus.FIXED);
assertThat(issue.getIssueStatus()).isEqualTo(IssueStatus.FIXED);
}

@Test
public void getSimpleStatus_shouldThrowException_whenStatusNotSet() {
public void getIssueStatus_shouldThrowException_whenStatusNotSet() {
issue.setResolution(Issue.RESOLUTION_FIXED);

assertThatThrownBy(issue::getSimpleStatus)
assertThatThrownBy(issue::getIssueStatus)
.hasMessage("Status must be set")
.isInstanceOf(IllegalArgumentException.class);
}

sonar-core/src/test/java/org/sonar/core/issue/status/SimpleStatusTest.java → sonar-core/src/test/java/org/sonar/core/issue/status/IssueStatusTest.java View File

@@ -27,51 +27,51 @@ import org.sonar.api.testfixtures.log.LogTester;

import static org.assertj.core.api.Assertions.assertThat;

public class SimpleStatusTest {
public class IssueStatusTest {

@Rule
public LogTester logTester = new LogTester();

@Test
public void of_shouldMapToCorrectSimpleStatus() {
assertThat(SimpleStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_FIXED))
.isEqualTo(SimpleStatus.FIXED);
public void of_shouldMapToCorrectIssueStatus() {
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_FIXED))
.isEqualTo(IssueStatus.FIXED);

assertThat(SimpleStatus.of(Issue.STATUS_CONFIRMED, null))
.isEqualTo(SimpleStatus.CONFIRMED);
assertThat(IssueStatus.of(Issue.STATUS_CONFIRMED, null))
.isEqualTo(IssueStatus.CONFIRMED);

assertThat(SimpleStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_FALSE_POSITIVE))
.isEqualTo(SimpleStatus.FALSE_POSITIVE);
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_FALSE_POSITIVE))
.isEqualTo(IssueStatus.FALSE_POSITIVE);

assertThat(SimpleStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX))
.isEqualTo(SimpleStatus.ACCEPTED);
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_WONT_FIX))
.isEqualTo(IssueStatus.ACCEPTED);

assertThat(SimpleStatus.of(Issue.STATUS_REOPENED, null))
.isEqualTo(SimpleStatus.OPEN);
assertThat(IssueStatus.of(Issue.STATUS_REOPENED, null))
.isEqualTo(IssueStatus.OPEN);

assertThat(SimpleStatus.of(Issue.STATUS_CLOSED, null))
.isEqualTo(SimpleStatus.FIXED);
assertThat(IssueStatus.of(Issue.STATUS_CLOSED, null))
.isEqualTo(IssueStatus.FIXED);
}

@Test
public void of_shouldReturnNull_WhenStatusBelongsToHotspot() {
assertThat(SimpleStatus.of(Issue.STATUS_TO_REVIEW, null))
assertThat(IssueStatus.of(Issue.STATUS_TO_REVIEW, null))
.isNull();

assertThat(SimpleStatus.of(Issue.STATUS_REVIEWED, Issue.RESOLUTION_SAFE))
assertThat(IssueStatus.of(Issue.STATUS_REVIEWED, Issue.RESOLUTION_SAFE))
.isNull();

assertThat(SimpleStatus.of(Issue.STATUS_REVIEWED, Issue.RESOLUTION_ACKNOWLEDGED))
assertThat(IssueStatus.of(Issue.STATUS_REVIEWED, Issue.RESOLUTION_ACKNOWLEDGED))
.isNull();
}

@Test
public void of_shouldThrowExceptionWhenUnknownMapping() {
assertThat(SimpleStatus.of(Issue.STATUS_RESOLVED, null)).isNull();
assertThat(logTester.getLogs()).extracting(LogAndArguments::getFormattedMsg).contains("Can't find mapped simple status for status 'RESOLVED' and resolution 'null'");
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, null)).isNull();
assertThat(logTester.getLogs()).extracting(LogAndArguments::getFormattedMsg).contains("Can't find mapped issue status for status 'RESOLVED' and resolution 'null'");

assertThat(SimpleStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_SAFE)).isNull();
assertThat(logTester.getLogs()).extracting(LogAndArguments::getFormattedMsg).contains("Can't find mapped simple status for status 'RESOLVED' and resolution 'SAFE'");
assertThat(IssueStatus.of(Issue.STATUS_RESOLVED, Issue.RESOLUTION_SAFE)).isNull();
assertThat(logTester.getLogs()).extracting(LogAndArguments::getFormattedMsg).contains("Can't find mapped issue status for status 'RESOLVED' and resolution 'SAFE'");
}

}

+ 1
- 1
sonar-ws/src/main/java/org/sonarqube/ws/client/issue/IssuesWsParameters.java View File

@@ -59,7 +59,7 @@ public class IssuesWsParameters {
public static final String PARAM_CLEAN_CODE_ATTRIBUTE_CATEGORIES = "cleanCodeAttributeCategories";
public static final String PARAM_STATUSES = "statuses";
public static final String PARAM_RESOLUTIONS = "resolutions";
public static final String PARAM_SIMPLE_STATUSES = "simpleStatuses";
public static final String PARAM_ISSUE_STATUSES = "issueStatuses";
public static final String PARAM_RESOLVED = "resolved";
public static final String PARAM_COMPONENTS = "components";
public static final String PARAM_COMPONENT_KEYS = "componentKeys";

+ 1
- 1
sonar-ws/src/main/protobuf/ws-issues.proto View File

@@ -166,7 +166,7 @@ message Issue {
optional sonarqube.ws.commons.CleanCodeAttribute cleanCodeAttribute = 40;
optional sonarqube.ws.commons.CleanCodeAttributeCategory cleanCodeAttributeCategory = 41;
repeated sonarqube.ws.commons.Impact impacts = 42;
optional string simpleStatus = 43;
optional string issueStatus = 43;
}

message Transitions {

Loading…
Cancel
Save