if (issues != null && !issues.isEmpty()) {
return issues.get(0);
}
- throw new IllegalArgumentException("No issue");
+ throw new IllegalStateException("No issue");
}
@Override
public class DefaultIssueQueryResultTest {
- @Test(expected = IllegalArgumentException.class)
- public void should_first_throw_exception_if_no_issue() {
+ @Test(expected = IllegalStateException.class)
+ public void first_should_throw_exception_if_no_issues() {
DefaultIssueQueryResult result = new DefaultIssueQueryResult(Collections.<Issue>emptyList());
result.first();
}
@CheckForNull
String message();
+ /**
+ * Optional line number. If set, then it's greater than or equal 1.
+ */
@CheckForNull
Integer line();
@CheckForNull
Double effortToFix();
+ /**
+ * See constant values in {@link Issue}.
+ */
String status();
/**
- * The type of resolution, or null if the issue is not resolved.
+ * The type of resolution, or null if the issue is not resolved. See constant values in {@link Issue}.
*/
@CheckForNull
String resolution();
+ /**
+ * Login of the user who reported this issue. Null if the issue is reported by a rule engine.
+ */
@CheckForNull
String reporter();
+ /**
+ * Login of the user who is assigned to this issue. Null if the issue is not assigned.
+ */
@CheckForNull
String assignee();
Date updateDate();
+ /**
+ * Date when status was set to {@link Issue#STATUS_CLOSED}, else null.
+ */
@CheckForNull
Date closeDate();
Map<String, String> attributes();
+ /**
+ * Login of the SCM account that introduced this issue. Requires the
+ * <a href="http://www.sonarsource.com/products/plugins/developer-tools/developer-cockpit/">Developer Cockpit Plugin</a> to be installed.
+ */
@CheckForNull
String authorLogin();
* @since 3.6
*/
public interface IssueQueryResult {
+ /**
+ * Non-null paginated list of issues.
+ */
List<Issue> issues();
/**
- * Return first issue in the list.
- * It will throws IllegalArgumentException if no issue found.
+ * Returns the first issue in the list.
+ * @throws IllegalStateException if the list is empty.
*/
Issue first();
+ /**
+ * Returns the rule associated to the given issue.
+ */
Rule rule(Issue issue);
/**
*/
Collection<Component> projects();
-
@CheckForNull
ActionPlan actionPlan(Issue issue);
+ /**
+ * The action plans involved in the paginated {@link #issues()}.
+ */
Collection<ActionPlan> actionPlans();
/**
- * The users involved in the paginated {@link #issues()}, for example people who added a comment, created an issue
+ * The users involved in the paginated {@link #issues()}, for example people who added a comment, reported an issue
* or are assigned to issues.
*/
Collection<User> users();
+ /**
+ * Returns the user with the given login. Users that are not returned by {@link #users()} are ignored.
+ */
@CheckForNull
User user(String login);
+ /**
+ * Non-null data about paging of issues
+ */
Paging paging();
+ /**
+ * True if too many issues have been found. In this case results are truncated.
+ */
boolean maxResultsReached();
}
/**
* Search for an issue by its key.
* <p/>
- * Ruby example: {@code Api.issues.find('ABCDE-12345')}
+ * Ruby example: <code>result = Api.issues.find('ABCDE-12345')</code>
*/
IssueQueryResult find(String issueKey);
/**
* Search for issues.
* <p/>
- * Ruby example: {@code Api.issues.find({'statuses' => ['OPEN', 'RESOLVED'], 'assignees' => 'john,carla')}.
+ * Ruby example: <code>Api.issues.find({'statuses' => ['OPEN', 'RESOLVED'], 'assignees' => 'john,carla')}</code>
* <p/>
- * <b>Keys of parameters must be Ruby strings but not symbols</b>. Multi-value parameters can be arrays ({@code ['OPEN', 'RESOLVED']}) or
- * comma-separated list of strings ({@code 'OPEN,RESOLVED'}).
+ * <b>Keys of parameters must be Ruby strings but not symbols</b>. Multi-value parameters can be arrays (<code>['OPEN', 'RESOLVED']</code>) or
+ * comma-separated list of strings (<code>'OPEN,RESOLVED'</code>).
* <p/>
* Optional parameters are:
* <ul>
import static com.google.common.collect.Lists.newArrayList;
+/**
+ * @since 3.6
+ */
public class Action {
private final String key;
private final List<Condition> conditions;
private final List<Function> functions;
- public Action(String key) {
+ Action(String key) {
+ Preconditions.checkArgument(!Strings.isNullOrEmpty(key), "Action key must be set");
this.key = key;
this.conditions = newArrayList();
this.functions = newArrayList();
-
- Preconditions.checkArgument(!Strings.isNullOrEmpty(key), "Action key must be set");
}
public String key() {
import static com.google.common.collect.Lists.newArrayList;
+/**
+ * @since 3.6
+ */
public class Actions implements ServerExtension {
private final List<Action> actions;
*/
package org.sonar.api.issue.condition;
-import com.google.common.annotations.Beta;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
import org.sonar.api.issue.Issue;
/**
- * @since 3.1
+ * @since 3.6
*/
-@Beta
public final class HasIssuePropertyCondition implements Condition {
private final String propertyKey;
import com.google.common.base.Objects;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-
import java.io.Serializable;
import java.util.Collections;
import java.util.Date;
import java.util.Map;
/**
+ * PLUGINS MUST NOT BE USED THIS CLASS, EXCEPT FOR UNIT TESTING.
+ *
* @since 3.6
*/
public class DefaultIssue implements Issue {
/**
* True when one of the following conditions is true :
* <ul>
- * <li>the related component has been deleted or renamed</li>
- * <li>the rule has been deleted (eg. on plugin uninstall)</li>
- * <li>the rule has been disabled in the Quality profile</li>
+ * <li>the related component has been deleted or renamed</li>
+ * <li>the rule has been deleted (eg. on plugin uninstall)</li>
+ * <li>the rule has been disabled in the Quality profile</li>
* </ul>
*/
public boolean isEndOfLife() {
@SuppressWarnings("unchcked")
public List<IssueComment> comments() {
- return Objects.firstNonNull(comments, Collections.<IssueComment>emptyList());
+ if (comments == null) {
+ return Collections.emptyList();
+ }
+ return ImmutableList.copyOf(comments);
}
@CheckForNull
import java.util.UUID;
/**
+ * PLUGINS MUST NOT BE USED THIS CLASS, EXCEPT FOR UNIT TESTING.
+ *
* @since 3.6
*/
public class DefaultIssueComment implements Serializable, IssueComment {
import java.util.Map;
/**
+ * PLUGINS MUST NOT BE USED THIS CLASS, EXCEPT FOR UNIT TESTING.
+ *
* @since 3.6
*/
public class FieldDiffs implements Serializable {
import java.util.Date;
/**
+ * PLUGINS MUST NOT BE USED THIS CLASS, EXCEPT FOR UNIT TESTING.
+ *
* @since 3.6
*/
public class IssueChangeContext implements Serializable {
- private String login;
- private Date date;
- private boolean scan;
+ private final String login;
+ private final Date date;
+ private final boolean scan;
private IssueChangeContext(@Nullable String login, Date date, boolean scan) {
this.login = login;
import com.google.common.collect.ImmutableMap;
import org.apache.commons.lang.StringUtils;
import org.junit.Test;
+import org.sonar.api.issue.IssueComment;
+
+import java.util.List;
import static org.fest.assertions.Assertions.assertThat;
import static org.fest.assertions.Fail.fail;
assertThat(a1).isNotEqualTo(b);
assertThat(a1.hashCode()).isEqualTo(a1.hashCode());
}
+
+ @Test
+ public void comments_should_not_be_modifiable() throws Exception {
+ DefaultIssue issue = new DefaultIssue().setKey("AAA");
+
+ List<IssueComment> comments = issue.comments();
+ assertThat(comments).isEmpty();
+
+ try {
+ comments.add(new DefaultIssueComment());
+ fail();
+ } catch (UnsupportedOperationException e) {
+ // ok
+ } catch (Exception e) {
+ fail("Unexpected exception: " + e);
+ }
+ }
}
public class ActionServiceTest {
- private DefaultIssueFinder finder;
- private IssueStorage issueStorage;
- private IssueUpdater updater;
- private PropertiesDao propertiesDao;
- private Settings settings;
- private Actions actions;
- private ActionService actionService;
+ DefaultIssueFinder finder;
+ IssueStorage issueStorage;
+ IssueUpdater updater;
+ PropertiesDao propertiesDao;
+ Settings settings;
+ Actions actions;
+ ActionService actionService;
@Before
public void before() {
actionService.execute("ABCD", "link-to-jira", mock(UserSession.class));
fail();
} catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("No issue");
+ assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("No issue");
}
verifyZeroInteractions(function);
}
actionService.listAvailableActions("ABCD");
fail();
} catch (Exception e) {
- assertThat(e).isInstanceOf(IllegalArgumentException.class).hasMessage("No issue");
+ assertThat(e).isInstanceOf(IllegalStateException.class).hasMessage("No issue");
}
}