import java.util.Collection;
-@DependsUpon({DecoratorBarriers.END_OF_VIOLATIONS_GENERATION, DecoratorBarriers.START_VIOLATION_TRACKING})
-@DependedUpon(DecoratorBarriers.END_OF_VIOLATION_TRACKING)
+@DependsUpon(DecoratorBarriers.ISSUES_ADDED)
+@DependedUpon(DecoratorBarriers.ISSUES_TRACKED)
public class IssueTrackingDecorator implements Decorator {
private final IssueCache issueCache;
/**
* Barriers are used to define the order of execution of Decorators. Decorators must be annotated with the following :
- *
+ * <p/>
* <ul>
- * <li>{@code @DependsUpon(BARRIER)} in order to be executed after BARRIER</li>
- * <li>{@code @DependedUpon(BARRIER)} in order to be executed before BARRIER</li>
+ * <li>{@code @DependsUpon(BARRIER)} in order to be executed after BARRIER</li>
+ * <li>{@code @DependedUpon(BARRIER)} in order to be executed before BARRIER</li>
* </ul>
*
* @since 2.3
*/
public interface DecoratorBarriers {
+ /**
+ * This barrier is before {@link #ISSUES_TRACKED}. The decorators that register issues must be declared before this
+ * barrier : {@code @DependedUpon(value=DecoratorBarriers.ISSUES_ADDED)}
+ *
+ * @since 3.6
+ */
+ String ISSUES_ADDED = "END_OF_VIOLATIONS_GENERATION";
+
+ /**
+ * This barrier is after {@link #ISSUES_ADDED}. The decorators that need to list all issues must be declared
+ * after this barrier : {@code @DependsUpon(value=DecoratorBarriers.ISSUES_TRACKED)}
+ *
+ * @since 3.6
+ */
+ String ISSUES_TRACKED = "END_OF_VIOLATION_TRACKING";
+
+
+ /**
+ * @deprecated in 3.6. Not required anymore.
+ */
+ @Deprecated
String START_VIOLATIONS_GENERATION = "START_VIOLATIONS_GENERATION";
/**
* {@code @DependsUpon(value=DecoratorBarriers.END_OF_VIOLATIONS_GENERATION}</li>
* <li>declare that it generates violations : {@code @DependedUpon(value=DecoratorBarriers.END_OF_VIOLATIONS_GENERATION}</li>
* </ul>
+ *
+ * @deprecated in 3.6. Replaced by {@link #ISSUES_ADDED}
*/
- String END_OF_VIOLATIONS_GENERATION = "END_OF_VIOLATIONS_GENERATION";
+ @Deprecated
+ String END_OF_VIOLATIONS_GENERATION = ISSUES_ADDED;
/**
* Extensions which call the method {@code Violation#setSwitchedOff} must be executed before this barrier
* ({@code @DependedUpon(value=DecoratorBarriers.VIOLATION_TRACKING})
- *
+ * <p/>
* This barrier is after {@code END_OF_VIOLATIONS_GENERATION}
*
* @since 2.8
+ * @deprecated in 3.6. Not required anymore.
*/
+ @Deprecated
String START_VIOLATION_TRACKING = "START_VIOLATION_TRACKING";
/**
* Decorators executed after this barrier ({@code @DependsUpon(value=DecoratorBarriers.END_OF_VIOLATION_TRACKING})
* can benefit from all the features of violation tracking :
* <ul>
- * <li>{@code Violation#getCreatedAt()}</li>
- * <li>{@code Violation#isSwitchedOff()}, usually to know if a violation has been flagged as false-positives in UI</li>
+ * <li>{@code Violation#getCreatedAt()}</li>
+ * <li>{@code Violation#isSwitchedOff()}, usually to know if a violation has been flagged as false-positives in UI</li>
* </ul>
*
* @since 2.8
+ * @deprecated in 3.6. Replaced by {@link #ISSUES_TRACKED}
*/
- String END_OF_VIOLATION_TRACKING = "END_OF_VIOLATION_TRACKING";
+ @Deprecated
+ String END_OF_VIOLATION_TRACKING = ISSUES_TRACKED;
/**
* @since 2.13
import java.util.List;
/**
+ * This perspective allows to add and get issues related to the selected component. It can be used from
+ * {@link org.sonar.api.batch.Sensor}s and {@link org.sonar.api.batch.Decorator}s. Web extensions
+ * must use {@link RubyIssueService}.
+ * <p/>
+ * Example:
+ * <pre>
+ * import org.sonar.api.component.ResourcePerspectives;
+ * public class MySensor extends Sensor {
+ * private final ResourcePerspectives perspectives;
+ *
+ * public MySensor(ResourcePerspectives p) {
+ * this.perspectives = p;
+ * }
+ *
+ * public void analyse(Project project, SensorContext context) {
+ * Resource myResource; // to be set
+ * Issuable issuable = perspectives.as(Issuable.class, myResource);
+ * if (issuable != null) {
+ * // can be used
+ * Issue issue = issuable.newIssueBuilder()
+ * .setRuleKey(RuleKey.of("pmd", "AvoidArrayLoops")
+ * .setLine(10)
+ * .build();
+ * issuable.addIssue(issue);
+ * }
+ * }
+ * }
+ * </pre>
* @since 3.6
*/
public interface Issuable extends Perspective {
interface IssueBuilder {
+ /**
+ * The rule key is mandatory. Example: {@code RuleKey.of("pmd", "AvoidArrayLoops")}
+ */
IssueBuilder ruleKey(RuleKey ruleKey);
+ /**
+ * Optional line index, starting from 1. It must not be zero or negative.
+ */
IssueBuilder line(@Nullable Integer line);
+ /**
+ * Optional, but recommended, plain-text message.
+ * <p/>
+ * Formats like Markdown or HTML are not supported. Size must not be greater than {@link Issue#MESSAGE_MAX_SIZE} characters.
+ */
IssueBuilder message(@Nullable String message);
+ /**
+ * Overrides the severity declared in Quality profile. Do not execute in standard use-cases.
+ */
IssueBuilder severity(@Nullable String severity);
+ /**
+ * Login of the user who reported the issue. Optional.
+ */
IssueBuilder reporter(@Nullable String reporter);
IssueBuilder effortToFix(@Nullable Double d);
Issue build();
}
+ /**
+ * Builder is used to create the issue to be passed to {@link #addIssue(Issue)}
+ */
IssueBuilder newIssueBuilder();
/**
- * @return true if the new issue is registered, false if the related rule does not exist or is disabled in the Quality profile
+ * Register an issue created with {@link #newIssueBuilder()}.
+ * <p/>
+ * This method is usually called from {@link org.sonar.api.batch.Sensor}s. {@link org.sonar.api.batch.Decorator}s calling this
+ * method must be annotated with {@code @DependedUpon(DecoratorBarriers.ISSUES_ADDED)}.
+ *
+ * @return true if the new issue is registered, false if the related rule does not exist or is disabled in the Quality profile.
*/
boolean addIssue(Issue issue);
/**
- * The issues that are not resolved (=open). They include the manual issues reported by end-users.
+ * Unresolved issues, including the issues reported by end-users.
+ * <p/>
+ * {@link org.sonar.api.batch.Decorator}s calling this method must be annotated with {@code @DependsUpon(DecoratorBarriers.ISSUES_TRACKED)}.
*/
List<Issue> issues();
/**
- * The issues marked as resolved during this scan.
+ * Issues marked as resolved during this scan.
+ * <p/>
+ * {@link org.sonar.api.batch.Decorator}s calling this method must be annotated with {@code @DependsUpon(DecoratorBarriers.ISSUES_TRACKED)}.
*/
List<Issue> resolvedIssues();
}
*/
public interface Issue extends Serializable {
+ /**
+ * Maximum number of characters in the message.
+ */
int MESSAGE_MAX_SIZE = 4000;
+ /**
+ * Default status when creating an issue.
+ */
String STATUS_OPEN = "OPEN";
String STATUS_CONFIRMED = "CONFIRMED";
String STATUS_REOPENED = "REOPENED";
String STATUS_CLOSED = "CLOSED";
String RESOLUTION_FIXED = "FIXED";
+
+ /**
+ * Resolution when issue is flagged as false positive.
+ */
String RESOLUTION_FALSE_POSITIVE = "FALSE-POSITIVE";
+
+ /**
+ * Resolution when rule has been uninstalled or disabled in the Quality profile.
+ */
String RESOLUTION_REMOVED = "REMOVED";
List<String> RESOLUTIONS = ImmutableList.of(RESOLUTION_FALSE_POSITIVE, RESOLUTION_FIXED, RESOLUTION_REMOVED);
/**
- * Unique generated key
+ * Unique generated key. It looks like "d2de809c-1512-4ae2-9f34-f5345c9f1a13".
*/
String key();
String actionPlanKey();
/**
- * Non-null list of comments, ordered by chronological order
+ * Non-null list of comments, ordered by chronological order.
+ * <p/>
+ * IMPORTANT: existing comments are not loaded when this method is called when analyzing project
+ * (from {@link org.sonar.api.BatchExtension}).
*/
List<IssueComment> comments();
}