diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2015-11-17 11:35:28 +0100 |
---|---|---|
committer | Duarte Meneses <duarte.meneses@sonarsource.com> | 2015-11-18 17:20:42 +0100 |
commit | 6c30b79fcdb15e16c440976f47b4f5725f45a91f (patch) | |
tree | b847a78b02ced5fc595bdddb41e518b1bb68a2ef | |
parent | 2d74e2414836ee0b9c8db3e3239dece7ff7c7af6 (diff) | |
download | sonarqube-6c30b79fcdb15e16c440976f47b4f5725f45a91f.tar.gz sonarqube-6c30b79fcdb15e16c440976f47b4f5725f45a91f.zip |
SONAR-6752 Deprecate org.sonar.batch.issue.IssueFilters extension point and add new one
32 files changed, 779 insertions, 327 deletions
diff --git a/it/it-plugins/issue-filter-plugin/src/main/java/IssueFilterBeforeLine5.java b/it/it-plugins/issue-filter-plugin/src/main/java/IssueFilterBeforeLine5.java index aaea16c5b69..3e6975b9208 100644 --- a/it/it-plugins/issue-filter-plugin/src/main/java/IssueFilterBeforeLine5.java +++ b/it/it-plugins/issue-filter-plugin/src/main/java/IssueFilterBeforeLine5.java @@ -1,6 +1,8 @@ +import org.sonar.api.scan.issue.filter.IssueFilterChain; + +import org.sonar.api.scan.issue.filter.FilterableIssue; import org.sonar.api.config.Settings; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.IssueFilter; +import org.sonar.api.scan.issue.filter.IssueFilter; /** * This filter removes the issues that are on line < 5 @@ -16,7 +18,7 @@ public class IssueFilterBeforeLine5 implements IssueFilter { } @Override - public boolean accept(Issue issue) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { if (issue.componentKey() == null) { throw new IllegalStateException("Issue component is not set"); } @@ -24,6 +26,11 @@ public class IssueFilterBeforeLine5 implements IssueFilter { throw new IllegalStateException("Issue rule is not set"); } - return !settings.getBoolean("enableIssueFilters") || issue.line() == null || issue.line() >= 5; + boolean b = !settings.getBoolean("enableIssueFilters") || issue.line() == null || issue.line() >= 5; + if (!b) { + return false; + } + + return chain.accept(issue); } } diff --git a/it/it-plugins/issue-filter-plugin/src/main/java/ModuleIssueFilter.java b/it/it-plugins/issue-filter-plugin/src/main/java/ModuleIssueFilter.java index de0de20cf32..ed5e9cbaf4f 100644 --- a/it/it-plugins/issue-filter-plugin/src/main/java/ModuleIssueFilter.java +++ b/it/it-plugins/issue-filter-plugin/src/main/java/ModuleIssueFilter.java @@ -1,6 +1,8 @@ +import org.sonar.api.scan.issue.filter.FilterableIssue; + +import org.sonar.api.scan.issue.filter.IssueFilterChain; import org.sonar.api.config.Settings; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.IssueFilter; +import org.sonar.api.scan.issue.filter.IssueFilter; import org.sonar.api.rule.RuleKey; /** @@ -19,7 +21,7 @@ public class ModuleIssueFilter implements IssueFilter { } @Override - public boolean accept(Issue issue) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { if (issue.componentKey() == null) { throw new IllegalStateException("Issue component is not set"); } @@ -27,6 +29,12 @@ public class ModuleIssueFilter implements IssueFilter { throw new IllegalStateException("Issue rule is not set"); } - return !settings.getBoolean("enableIssueFilters") || !ONE_ISSUE_PER_MODULE_RULEKEY.equals(issue.ruleKey()); + boolean b = !settings.getBoolean("enableIssueFilters") || !ONE_ISSUE_PER_MODULE_RULEKEY.equals(issue.ruleKey()); + + if (!b) { + return false; + } + + return chain.accept(issue); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultFilterableIssue.java b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultFilterableIssue.java new file mode 100644 index 00000000000..2baa0250e4b --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultFilterableIssue.java @@ -0,0 +1,90 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue; + +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; + +import org.sonar.api.resources.Project; +import org.sonar.api.rule.RuleKey; + +import java.util.Date; + +import org.sonar.batch.protocol.output.BatchReport.Issue; +import org.sonar.api.scan.issue.filter.FilterableIssue; + +public class DefaultFilterableIssue implements FilterableIssue { + private final Issue rawIssue; + private final Project project; + private final String componentKey; + + public DefaultFilterableIssue(Project project, Issue rawIssue, String componentKey) { + this.project = project; + this.rawIssue = rawIssue; + this.componentKey = componentKey; + + } + + @Override + public String componentKey() { + return componentKey; + } + + @Override + public RuleKey ruleKey() { + return RuleKey.of(rawIssue.getRuleRepository(), rawIssue.getRuleKey()); + } + + @Override + public String severity() { + return rawIssue.getSeverity().name(); + } + + @Override + public String message() { + return rawIssue.getMsg(); + } + + @Override + public Integer line() { + return rawIssue.hasLine() ? rawIssue.getLine() : null; + } + + @Override + public Double effortToFix() { + return rawIssue.hasEffortToFix() ? rawIssue.getEffortToFix() : null; + } + + @Override + public Date creationDate() { + return project.getAnalysisDate(); + } + + @Override + public String projectKey() { + return project.getEffectiveKey(); + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssueFilterChain.java b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssueFilterChain.java index 707c5bacad1..cfccaa1e7c2 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssueFilterChain.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/DefaultIssueFilterChain.java @@ -20,14 +20,14 @@ package org.sonar.batch.issue; import com.google.common.collect.ImmutableList; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilter; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilter; import java.util.List; -public class DefaultIssueFilterChain implements IssueFilterChain { +import org.sonar.api.scan.issue.filter.FilterableIssue; +import org.sonar.api.scan.issue.filter.IssueFilterChain; +public class DefaultIssueFilterChain implements IssueFilterChain { private final List<IssueFilter> filters; public DefaultIssueFilterChain(IssueFilter... filters) { @@ -43,11 +43,12 @@ public class DefaultIssueFilterChain implements IssueFilterChain { } @Override - public boolean accept(Issue issue) { + public boolean accept(FilterableIssue issue) { if (filters.isEmpty()) { return true; } else { return filters.get(0).accept(issue, new DefaultIssueFilterChain(filters.subList(1, filters.size()))); } } + } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/DeprecatedIssueAdapterForFilter.java b/sonar-batch/src/main/java/org/sonar/batch/issue/DeprecatedIssueAdapterForFilter.java new file mode 100644 index 00000000000..55bb90e879a --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/DeprecatedIssueAdapterForFilter.java @@ -0,0 +1,182 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue; + +import org.sonar.api.issue.Issue; +import org.sonar.api.issue.IssueComment; +import org.sonar.api.resources.Project; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.utils.Duration; + +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; + +/** + * @deprecated since 5.3 + */ +@Deprecated +class DeprecatedIssueAdapterForFilter implements Issue { + private final Project project; + private final org.sonar.batch.protocol.output.BatchReport.Issue rawIssue; + private final String componentKey; + + DeprecatedIssueAdapterForFilter(Project project, org.sonar.batch.protocol.output.BatchReport.Issue rawIssue, String componentKey) { + this.project = project; + this.rawIssue = rawIssue; + this.componentKey = componentKey; + } + + @Override + public String key() { + throw unsupported(); + } + + @Override + public String componentKey() { + return componentKey; + } + + @Override + public RuleKey ruleKey() { + return RuleKey.of(rawIssue.getRuleRepository(), rawIssue.getRuleKey()); + } + + @Override + public String language() { + throw unsupported(); + } + + @Override + public String severity() { + return rawIssue.getSeverity().name(); + } + + @Override + public String message() { + return rawIssue.getMsg(); + } + + @Override + public Integer line() { + return rawIssue.hasLine() ? rawIssue.getLine() : null; + } + + @Override + public Double effortToFix() { + return rawIssue.hasEffortToFix() ? rawIssue.getEffortToFix() : null; + } + + @Override + public String status() { + return Issue.STATUS_OPEN; + } + + @Override + public String resolution() { + return null; + } + + @Override + public String reporter() { + throw unsupported(); + } + + @Override + public String assignee() { + return null; + } + + @Override + public Date creationDate() { + return project.getAnalysisDate(); + } + + @Override + public Date updateDate() { + return null; + } + + @Override + public Date closeDate() { + return null; + } + + @Override + public String attribute(String key) { + return attributes().get(key); + } + + @Override + public Map<String, String> attributes() { + return Collections.emptyMap(); + } + + @Override + public String authorLogin() { + throw unsupported(); + } + + @Override + public String actionPlanKey() { + throw unsupported(); + } + + @Override + public List<IssueComment> comments() { + throw unsupported(); + } + + @Override + public boolean isNew() { + throw unsupported(); + } + + @Override + public Duration debt() { + throw unsupported(); + } + + @Override + public String projectKey() { + return project.getEffectiveKey(); + } + + @Override + public String projectUuid() { + throw unsupported(); + } + + @Override + public String componentUuid() { + throw unsupported(); + } + + @Override + public Collection<String> tags() { + throw unsupported(); + } + + private static UnsupportedOperationException unsupported() { + return new UnsupportedOperationException("Not available for issues filters"); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/DeprecatedIssueFilterChain.java b/sonar-batch/src/main/java/org/sonar/batch/issue/DeprecatedIssueFilterChain.java new file mode 100644 index 00000000000..65b569ee1a7 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/DeprecatedIssueFilterChain.java @@ -0,0 +1,57 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue; + +import com.google.common.collect.ImmutableList; +import org.sonar.api.issue.Issue; +import org.sonar.api.issue.batch.IssueFilter; +import org.sonar.api.issue.batch.IssueFilterChain; + +import java.util.List; + +/** + * @deprecated since 5.3 + */ +@Deprecated +public class DeprecatedIssueFilterChain implements IssueFilterChain { + + private final List<IssueFilter> filters; + + public DeprecatedIssueFilterChain(IssueFilter... filters) { + this.filters = ImmutableList.copyOf(filters); + } + + public DeprecatedIssueFilterChain() { + this.filters = ImmutableList.of(); + } + + private DeprecatedIssueFilterChain(List<IssueFilter> filters) { + this.filters = filters; + } + + @Override + public boolean accept(Issue issue) { + if (filters.isEmpty()) { + return true; + } else { + return filters.get(0).accept(issue, new DeprecatedIssueFilterChain(filters.subList(1, filters.size()))); + } + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java index 430c2ceb089..46c3e6e5edc 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/IssueFilters.java @@ -19,203 +19,51 @@ */ package org.sonar.batch.issue; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; +import org.sonar.api.scan.issue.filter.FilterableIssue; + +import org.sonar.api.scan.issue.filter.IssueFilterChain; import org.sonar.api.batch.BatchSide; import org.sonar.api.issue.Issue; -import org.sonar.api.issue.IssueComment; -import org.sonar.api.issue.batch.IssueFilter; +import org.sonar.api.scan.issue.filter.IssueFilter; import org.sonar.api.resources.Project; -import org.sonar.api.rule.RuleKey; -import org.sonar.api.utils.Duration; import org.sonar.batch.protocol.output.BatchReport; @BatchSide public class IssueFilters { - - private static final class IssueAdapterForFilter implements Issue { - private final Project project; - private final org.sonar.batch.protocol.output.BatchReport.Issue rawIssue; - private final String componentKey; - - private IssueAdapterForFilter(Project project, org.sonar.batch.protocol.output.BatchReport.Issue rawIssue, String componentKey) { - this.project = project; - this.rawIssue = rawIssue; - this.componentKey = componentKey; - } - - @Override - public String key() { - throw unsupported(); - } - - @Override - public String componentKey() { - return componentKey; - } - - @Override - public RuleKey ruleKey() { - return RuleKey.of(rawIssue.getRuleRepository(), rawIssue.getRuleKey()); - } - - @Override - public String language() { - throw unsupported(); - } - - @Override - public String severity() { - return rawIssue.getSeverity().name(); - } - - @Override - public String message() { - return rawIssue.getMsg(); - } - - @Override - public Integer line() { - return rawIssue.hasLine() ? rawIssue.getLine() : null; - } - - @Override - public Double effortToFix() { - return rawIssue.hasEffortToFix() ? rawIssue.getEffortToFix() : null; - } - - @Override - public String status() { - return Issue.STATUS_OPEN; - } - - @Override - public String resolution() { - return null; - } - - @Override - public String reporter() { - throw unsupported(); - } - - @Override - public String assignee() { - return null; - } - - @Override - public Date creationDate() { - return project.getAnalysisDate(); - } - - @Override - public Date updateDate() { - return null; - } - - @Override - public Date closeDate() { - return null; - } - - @Override - public String attribute(String key) { - return attributes().get(key); - } - - @Override - public Map<String, String> attributes() { - return Collections.emptyMap(); - } - - @Override - public String authorLogin() { - throw unsupported(); - } - - @Override - public String actionPlanKey() { - throw unsupported(); - } - - @Override - public List<IssueComment> comments() { - throw unsupported(); - } - - @Override - public boolean isNew() { - throw unsupported(); - } - - @Override - public Duration debt() { - throw unsupported(); - } - - @Override - public String projectKey() { - return project.getEffectiveKey(); - } - - @Override - public String projectUuid() { - throw unsupported(); - } - - @Override - public String componentUuid() { - throw unsupported(); - } - - @Override - public Collection<String> tags() { - throw unsupported(); - } - - private static UnsupportedOperationException unsupported() { - return new UnsupportedOperationException("Not available for issues filters"); - } - } - - private final org.sonar.api.issue.IssueFilter[] exclusionFilters; private final IssueFilter[] filters; + private final org.sonar.api.issue.batch.IssueFilter[] deprecatedFilters; private final Project project; - public IssueFilters(Project project, org.sonar.api.issue.IssueFilter[] exclusionFilters, IssueFilter[] filters) { + public IssueFilters(Project project, IssueFilter[] exclusionFilters, org.sonar.api.issue.batch.IssueFilter[] filters) { this.project = project; - this.exclusionFilters = exclusionFilters; - this.filters = filters; + this.filters = exclusionFilters; + this.deprecatedFilters = filters; } - public IssueFilters(Project project, org.sonar.api.issue.IssueFilter[] exclusionFilters) { - this(project, exclusionFilters, new IssueFilter[0]); + public IssueFilters(Project project, IssueFilter[] filters) { + this(project, filters, new org.sonar.api.issue.batch.IssueFilter[0]); } - public IssueFilters(Project project, IssueFilter[] filters) { - this(project, new org.sonar.api.issue.IssueFilter[0], filters); + public IssueFilters(Project project, org.sonar.api.issue.batch.IssueFilter[] deprecatedFilters) { + this(project, new IssueFilter[0], deprecatedFilters); } public IssueFilters(Project project) { - this(project, new org.sonar.api.issue.IssueFilter[0], new IssueFilter[0]); + this(project, new IssueFilter[0], new org.sonar.api.issue.batch.IssueFilter[0]); } public boolean accept(String componentKey, BatchReport.Issue rawIssue) { - Issue issue = new IssueAdapterForFilter(project, rawIssue, componentKey); - if (new DefaultIssueFilterChain(filters).accept(issue)) { - // Apply deprecated rules only if filter chain accepts the current issue - for (org.sonar.api.issue.IssueFilter filter : exclusionFilters) { - if (!filter.accept(issue)) { - return false; - } - } - return true; - } else { - return false; + IssueFilterChain filterChain = new DefaultIssueFilterChain(filters); + FilterableIssue fIssue = new DefaultFilterableIssue(project, rawIssue, componentKey); + if (filterChain.accept(fIssue)) { + return acceptDeprecated(componentKey, rawIssue); } + + return false; + } + + public boolean acceptDeprecated(String componentKey, BatchReport.Issue rawIssue) { + Issue issue = new DeprecatedIssueAdapterForFilter(project, rawIssue, componentKey); + return new DeprecatedIssueFilterChain(deprecatedFilters).accept(issue); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/EnforceIssuesFilter.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/EnforceIssuesFilter.java index 50f263fbfac..3c486469084 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/EnforceIssuesFilter.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/EnforceIssuesFilter.java @@ -19,14 +19,14 @@ */ package org.sonar.batch.issue.ignore; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.IssuePattern; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilter; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilter; +import org.sonar.api.scan.issue.filter.IssueFilterChain; public class EnforceIssuesFilter implements IssueFilter { @@ -39,7 +39,7 @@ public class EnforceIssuesFilter implements IssueFilter { } @Override - public boolean accept(Issue issue, IssueFilterChain chain) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { boolean atLeastOneRuleMatched = false; boolean atLeastOnePatternFullyMatched = false; IssuePattern matchingPattern = null; diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilter.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilter.java index 95c6f3dbcd6..07e1401ffa1 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilter.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilter.java @@ -19,15 +19,15 @@ */ package org.sonar.batch.issue.ignore; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.IssuePattern; import org.sonar.batch.issue.ignore.pattern.PatternMatcher; - import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilter; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilter; +import org.sonar.api.scan.issue.filter.IssueFilterChain; public class IgnoreIssuesFilter implements IssueFilter { @@ -40,7 +40,7 @@ public class IgnoreIssuesFilter implements IssueFilter { } @Override - public boolean accept(Issue issue, IssueFilterChain chain) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { if (hasMatchFor(issue)) { return false; } else { @@ -48,7 +48,7 @@ public class IgnoreIssuesFilter implements IssueFilter { } } - private boolean hasMatchFor(Issue issue) { + private boolean hasMatchFor(FilterableIssue issue) { IssuePattern pattern = patternMatcher.getMatchingPattern(issue); if (pattern != null) { logExclusion(issue, pattern); @@ -57,7 +57,7 @@ public class IgnoreIssuesFilter implements IssueFilter { return false; } - private void logExclusion(Issue issue, IssuePattern pattern) { + private static void logExclusion(FilterableIssue issue, IssuePattern pattern) { LOG.debug("Issue {} ignored by exclusion pattern {}", issue, pattern); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssuePattern.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssuePattern.java index a17347a809b..2125861f668 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssuePattern.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssuePattern.java @@ -20,10 +20,11 @@ package org.sonar.batch.issue.ignore.pattern; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import com.google.common.collect.Sets; import org.apache.commons.lang.builder.ToStringBuilder; import org.apache.commons.lang.builder.ToStringStyle; -import org.sonar.api.issue.Issue; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.WildcardPattern; @@ -115,7 +116,7 @@ public class IssuePattern { return allLines; } - public boolean match(Issue issue) { + public boolean match(FilterableIssue issue) { boolean match = matchResource(issue.componentKey()) && matchRule(issue.ruleKey()); if (checkLines) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/PatternMatcher.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/PatternMatcher.java index 855521ab916..97fd98b888b 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/PatternMatcher.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/PatternMatcher.java @@ -19,9 +19,10 @@ */ package org.sonar.batch.issue.ignore.pattern; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import com.google.common.collect.LinkedHashMultimap; import com.google.common.collect.Multimap; -import org.sonar.api.issue.Issue; import java.util.Collection; import java.util.Iterator; @@ -31,7 +32,7 @@ public class PatternMatcher { private Multimap<String, IssuePattern> patternByComponent = LinkedHashMultimap.create(); - public IssuePattern getMatchingPattern(Issue issue) { + public IssuePattern getMatchingPattern(FilterableIssue issue) { IssuePattern matchingPattern = null; Iterator<IssuePattern> patternIterator = getPatternsForComponent(issue.componentKey()).iterator(); while(matchingPattern == null && patternIterator.hasNext()) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java index 1dad68550bb..921c4b963ea 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java @@ -24,7 +24,6 @@ import org.sonar.api.batch.fs.FileSystem; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputFile; import org.sonar.api.resources.Project; -import org.sonar.api.utils.SonarException; import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; @@ -69,7 +68,7 @@ public final class IssueExclusionsLoader { } } } catch (Exception e) { - throw new SonarException("Unable to read the source file : '" + inputFile.absolutePath() + "' with the charset : '" + throw new IllegalStateException("Unable to read the source file : '" + inputFile.absolutePath() + "' with the charset : '" + sourcesEncoding.name() + "'.", e); } } diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/TrackedIssue.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/TrackedIssue.java index dcbc8385774..c7938b6359a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/TrackedIssue.java +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/TrackedIssue.java @@ -19,6 +19,8 @@ */ package org.sonar.batch.issue.tracking; +import org.apache.commons.lang.builder.ToStringBuilder; +import org.apache.commons.lang.builder.ToStringStyle; import com.google.common.base.Preconditions; import javax.annotation.CheckForNull; @@ -240,4 +242,9 @@ public class TrackedIssue implements Trackable, Serializable { return true; } + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } + } diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultFilterableIssueTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultFilterableIssueTest.java new file mode 100644 index 00000000000..480c09aa276 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultFilterableIssueTest.java @@ -0,0 +1,86 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.when; +import org.sonar.batch.protocol.Constants.Severity; + +import java.util.Date; + +import static org.mockito.Mockito.mock; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.resources.Project; +import org.sonar.batch.protocol.output.BatchReport.Issue; + +public class DefaultFilterableIssueTest { + private DefaultFilterableIssue issue; + private Project mockedProject; + private String componentKey; + private Issue rawIssue; + + @Before + public void setUp() { + mockedProject = mock(Project.class); + componentKey = "component"; + } + + private Issue createIssue() { + Issue.Builder builder = Issue.newBuilder(); + + builder.setEffortToFix(3.0); + builder.setLine(30); + builder.setSeverity(Severity.MAJOR); + return builder.build(); + } + + private Issue createIssueWithoutFields() { + Issue.Builder builder = Issue.newBuilder(); + builder.setSeverity(Severity.MAJOR); + return builder.build(); + } + + @Test + public void testRoundTrip() { + rawIssue = createIssue(); + issue = new DefaultFilterableIssue(mockedProject, rawIssue, componentKey); + + when(mockedProject.getAnalysisDate()).thenReturn(new Date(10_000)); + when(mockedProject.getEffectiveKey()).thenReturn("projectKey"); + + assertThat(issue.componentKey()).isEqualTo(componentKey); + assertThat(issue.creationDate()).isEqualTo(new Date(10_000)); + assertThat(issue.line()).isEqualTo(30); + assertThat(issue.projectKey()).isEqualTo("projectKey"); + assertThat(issue.effortToFix()).isEqualTo(3.0); + assertThat(issue.severity()).isEqualTo("MAJOR"); + } + + @Test + public void nullValues() { + rawIssue = createIssueWithoutFields(); + issue = new DefaultFilterableIssue(mockedProject, rawIssue, componentKey); + + assertThat(issue.line()).isNull(); + assertThat(issue.effortToFix()).isNull(); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssueFilterChainTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssueFilterChainTest.java index 25dc340fe30..e0aa7d15e31 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssueFilterChainTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/DefaultIssueFilterChainTest.java @@ -19,18 +19,17 @@ */ package org.sonar.batch.issue; -import org.junit.Test; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilter; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.FilterableIssue; +import org.junit.Test; +import org.sonar.api.scan.issue.filter.IssueFilter; +import org.sonar.api.scan.issue.filter.IssueFilterChain; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import static org.mockito.Mockito.mock; public class DefaultIssueFilterChainTest { - - private final Issue issue = mock(Issue.class); + private final FilterableIssue issue = mock(FilterableIssue.class); @Test public void should_accept_when_no_filter() { @@ -39,28 +38,28 @@ public class DefaultIssueFilterChainTest { class PassingFilter implements IssueFilter { @Override - public boolean accept(Issue issue, IssueFilterChain chain) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { return chain.accept(issue); } } class AcceptingFilter implements IssueFilter { @Override - public boolean accept(Issue issue, IssueFilterChain chain) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { return true; } } class RefusingFilter implements IssueFilter { @Override - public boolean accept(Issue issue, IssueFilterChain chain) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { return false; } } class FailingFilter implements IssueFilter { @Override - public boolean accept(Issue issue, IssueFilterChain chain) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { fail(); return false; } diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/DeprecatedIssueFilterChainTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/DeprecatedIssueFilterChainTest.java new file mode 100644 index 00000000000..400b306101d --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/DeprecatedIssueFilterChainTest.java @@ -0,0 +1,96 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.batch.issue; + +import org.junit.Test; +import org.sonar.api.issue.Issue; +import org.sonar.api.issue.batch.IssueFilter; +import org.sonar.api.issue.batch.IssueFilterChain; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.Assert.fail; +import static org.mockito.Mockito.mock; + +public class DeprecatedIssueFilterChainTest { + + private final Issue issue = mock(Issue.class); + + @Test + public void should_accept_when_no_filter() { + assertThat(new DeprecatedIssueFilterChain().accept(issue)).isTrue(); + } + + class PassingFilter implements IssueFilter { + @Override + public boolean accept(Issue issue, IssueFilterChain chain) { + return chain.accept(issue); + } + } + + class AcceptingFilter implements IssueFilter { + @Override + public boolean accept(Issue issue, IssueFilterChain chain) { + return true; + } + } + + class RefusingFilter implements IssueFilter { + @Override + public boolean accept(Issue issue, IssueFilterChain chain) { + return false; + } + } + + class FailingFilter implements IssueFilter { + @Override + public boolean accept(Issue issue, IssueFilterChain chain) { + fail(); + return false; + } + + } + + @Test + public void should_accept_if_all_filters_pass() { + assertThat(new DeprecatedIssueFilterChain( + new PassingFilter(), + new PassingFilter(), + new PassingFilter() + ).accept(issue)).isTrue(); + } + + @Test + public void should_accept_and_not_go_further_if_filter_accepts() { + assertThat(new DeprecatedIssueFilterChain( + new PassingFilter(), + new AcceptingFilter(), + new FailingFilter() + ).accept(issue)).isTrue(); + } + + @Test + public void should_refuse_and_not_go_further_if_filter_refuses() { + assertThat(new DeprecatedIssueFilterChain( + new PassingFilter(), + new RefusingFilter(), + new FailingFilter() + ).accept(issue)).isFalse(); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueFiltersTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueFiltersTest.java deleted file mode 100644 index e83ce83d157..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueFiltersTest.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2014 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * SonarQube is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.issue; - -import org.junit.Test; -import org.sonar.api.issue.Issue; -import org.sonar.api.resources.Project; -import org.sonar.batch.protocol.output.BatchReport; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class IssueFiltersTest { - - @Test - public void accept_when_filter_chain_is_empty() { - org.sonar.api.issue.IssueFilter ok = mock(org.sonar.api.issue.IssueFilter.class); - when(ok.accept(any(Issue.class))).thenReturn(true); - - org.sonar.api.issue.IssueFilter ko = mock(org.sonar.api.issue.IssueFilter.class); - when(ko.accept(any(Issue.class))).thenReturn(false); - - IssueFilters filters = new IssueFilters(new Project("foo"), new org.sonar.api.issue.IssueFilter[] {ok, ko}); - assertThat(filters.accept("foo:src/Foo.java", BatchReport.Issue.newBuilder().build())).isFalse(); - - filters = new IssueFilters(new Project("foo"), new org.sonar.api.issue.IssueFilter[] {ok}); - assertThat(filters.accept("foo:src/Foo.java", BatchReport.Issue.newBuilder().build())).isTrue(); - - filters = new IssueFilters(new Project("foo"), new org.sonar.api.issue.IssueFilter[] {ko}); - assertThat(filters.accept("foo:src/Foo.java", BatchReport.Issue.newBuilder().build())).isFalse(); - } - - @Test - public void should_always_accept_if_no_filters() { - IssueFilters filters = new IssueFilters(new Project("foo")); - assertThat(filters.accept("foo:src/Foo.java", BatchReport.Issue.newBuilder().build())).isTrue(); - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java index 5996ca78d36..fc1886957e8 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java @@ -20,16 +20,16 @@ package org.sonar.batch.issue.ignore; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import com.google.common.collect.ImmutableList; import org.junit.Before; import org.junit.Test; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilterChain; import org.sonar.api.rule.RuleKey; import org.sonar.api.utils.WildcardPattern; import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.IssuePattern; - import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; @@ -40,13 +40,13 @@ public class EnforceIssuesFilterTest { private IssueInclusionPatternInitializer exclusionPatternInitializer; private EnforceIssuesFilter ignoreFilter; - private Issue issue; + private FilterableIssue issue; private IssueFilterChain chain; @Before public void init() { exclusionPatternInitializer = mock(IssueInclusionPatternInitializer.class); - issue = mock(Issue.class); + issue = mock(FilterableIssue.class); chain = mock(IssueFilterChain.class); when(chain.accept(issue)).thenReturn(true); diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java index 13b1ec042de..e7e06728d54 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java @@ -20,14 +20,14 @@ package org.sonar.batch.issue.ignore; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import org.junit.Before; import org.junit.Test; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilterChain; import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.IssuePattern; import org.sonar.batch.issue.ignore.pattern.PatternMatcher; - import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -37,7 +37,7 @@ public class IgnoreIssuesFilterTest { private IssueExclusionPatternInitializer exclusionPatternInitializer; private PatternMatcher exclusionPatternMatcher; private IgnoreIssuesFilter ignoreFilter; - private Issue issue; + private FilterableIssue issue; private IssueFilterChain chain; @Before @@ -45,7 +45,7 @@ public class IgnoreIssuesFilterTest { exclusionPatternMatcher = mock(PatternMatcher.class); exclusionPatternInitializer = mock(IssueExclusionPatternInitializer.class); when(exclusionPatternInitializer.getPatternMatcher()).thenReturn(exclusionPatternMatcher); - issue = mock(Issue.class); + issue = mock(FilterableIssue.class); chain = mock(IssueFilterChain.class); when(chain.accept(issue)).thenReturn(true); diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java index bf42b241300..dfbf6f2591b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java @@ -20,11 +20,11 @@ package org.sonar.batch.issue.ignore.pattern; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import org.junit.Test; -import org.sonar.api.issue.Issue; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; - import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @@ -88,8 +88,8 @@ public class IssuePatternTest { assertThat(pattern.match(create((Rule) null, null, null))).isFalse(); } - private Issue create(Rule rule, String component, Integer line) { - Issue mockIssue = mock(Issue.class); + private FilterableIssue create(Rule rule, String component, Integer line) { + FilterableIssue mockIssue = mock(FilterableIssue.class); RuleKey ruleKey = null; if (rule != null) { ruleKey = rule.ruleKey(); @@ -109,6 +109,7 @@ public class IssuePatternTest { public void shouldPrintPatternToString() { IssuePattern pattern = new IssuePattern("*", "checkstyle:*"); - assertThat(pattern.toString()).isEqualTo("IssuePattern[resourcePattern=*,rulePattern=checkstyle:*,lines=[],lineRanges=[],beginBlockRegexp=<null>,endBlockRegexp=<null>,allFileRegexp=<null>,checkLines=true]"); + assertThat(pattern.toString()).isEqualTo( + "IssuePattern[resourcePattern=*,rulePattern=checkstyle:*,lines=[],lineRanges=[],beginBlockRegexp=<null>,endBlockRegexp=<null>,allFileRegexp=<null>,checkLines=true]"); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java index 3d0acd15b5b..fa5135d9c0b 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java @@ -19,10 +19,11 @@ */ package org.sonar.batch.issue.ignore.pattern; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import com.google.common.collect.Sets; import org.junit.Before; import org.junit.Test; -import org.sonar.api.issue.Issue; import org.sonar.api.rule.RuleKey; import org.sonar.api.rules.Rule; @@ -99,8 +100,8 @@ public class PatternMatcherTest { assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull(); } - private Issue create(Rule rule, String component, Integer line) { - Issue mockIssue = mock(Issue.class); + private FilterableIssue create(Rule rule, String component, Integer line) { + FilterableIssue mockIssue = mock(FilterableIssue.class); RuleKey ruleKey = null; if (rule != null) { ruleKey = rule.ruleKey(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java index 4963cd13b30..b93a767f92d 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java @@ -30,7 +30,6 @@ import org.mockito.MockitoAnnotations; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultFileSystem; import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.utils.SonarException; import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; import org.sonar.batch.issue.ignore.pattern.PatternMatcher; @@ -151,7 +150,7 @@ public class IssueExclusionsLoaderTest { when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); doThrow(new IOException("BUG")).when(regexpScanner).scan("polop:src/Foo.php", phpFile1, UTF_8); - thrown.expect(SonarException.class); + thrown.expect(IllegalStateException.class); thrown.expectMessage("Unable to read the source file"); scanner.execute(); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/checks/NoSonarFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/checks/NoSonarFilter.java index 16aa183e3a5..b8e4401d7f5 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/checks/NoSonarFilter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/checks/NoSonarFilter.java @@ -19,11 +19,13 @@ */ package org.sonar.api.checks; +import org.sonar.api.scan.issue.filter.FilterableIssue; + +import org.sonar.api.scan.issue.filter.IssueFilter; import com.google.common.collect.Maps; import org.apache.commons.lang.StringUtils; import org.sonar.api.batch.SonarIndex; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilterChain; import org.sonar.api.resources.Resource; import java.util.Map; @@ -34,7 +36,7 @@ import java.util.Set; * @deprecated in 3.6. Replaced by {@link org.sonar.api.issue.NoSonarFilter} */ @Deprecated -public class NoSonarFilter implements org.sonar.api.issue.batch.IssueFilter { +public class NoSonarFilter implements IssueFilter { private final Map<String, Set<Integer>> noSonarLinesByKey = Maps.newHashMap(); private SonarIndex sonarIndex; @@ -54,7 +56,7 @@ public class NoSonarFilter implements org.sonar.api.issue.batch.IssueFilter { } @Override - public boolean accept(Issue issue, IssueFilterChain chain) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { boolean accepted = true; if (issue.line() != null) { Set<Integer> noSonarLines = noSonarLinesByKey.get(issue.componentKey()); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/NoSonarFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/NoSonarFilter.java index b7005431501..21195ce870f 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/NoSonarFilter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/NoSonarFilter.java @@ -19,12 +19,15 @@ */ package org.sonar.api.issue; +import org.sonar.api.scan.issue.filter.FilterableIssue; + +import org.sonar.api.scan.issue.filter.IssueFilter; import com.google.common.collect.Maps; import org.apache.commons.lang.StringUtils; import org.sonar.api.batch.BatchSide; import org.sonar.api.batch.fs.InputFile; import org.sonar.api.batch.fs.internal.DefaultInputFile; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilterChain; import java.util.Map; import java.util.Set; @@ -38,7 +41,7 @@ import java.util.Set; * * @since 3.6 */ -public class NoSonarFilter implements org.sonar.api.issue.batch.IssueFilter { +public class NoSonarFilter implements IssueFilter { private final Map<String, Set<Integer>> noSonarLinesByResource = Maps.newHashMap(); @@ -63,7 +66,7 @@ public class NoSonarFilter implements org.sonar.api.issue.batch.IssueFilter { } @Override - public boolean accept(Issue issue, IssueFilterChain chain) { + public boolean accept(FilterableIssue issue, IssueFilterChain chain) { boolean accepted = true; if (issue.line() != null) { Set<Integer> noSonarLines = noSonarLinesByResource.get(issue.componentKey()); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/batch/IssueFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/batch/IssueFilter.java index 24f07290154..6b1f91b1e79 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/batch/IssueFilter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/batch/IssueFilter.java @@ -26,10 +26,12 @@ import org.sonar.api.issue.Issue; /** * <p>An issue filter is an object that allows filtering of {@link Issue}s on batch side, preventing them from being persisted.</p> * @since 4.0 + * @deprecated since 5.3. Use {@link org.sonar.api.issue.filter.IssueFilter} instead. * */ @BatchSide @ExtensionPoint +@Deprecated public interface IssueFilter { /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/batch/IssueFilterChain.java b/sonar-plugin-api/src/main/java/org/sonar/api/issue/batch/IssueFilterChain.java index a72f35efffb..91b2877bd06 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/batch/IssueFilterChain.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/issue/batch/IssueFilterChain.java @@ -29,7 +29,9 @@ import org.sonar.api.issue.Issue; * <li>Let downstream filters decide by passing the issue to the rest of the chain</li> * </ul> * @since 4.0 + * @deprecated since 5.3. Use {@link org.sonar.api.issue.filter.IssueFilterChain} instead. */ +@Deprecated public interface IssueFilterChain { /** diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/FilterableIssue.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/FilterableIssue.java new file mode 100644 index 00000000000..da789194f73 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/FilterableIssue.java @@ -0,0 +1,46 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.scan.issue.filter; + +import org.sonar.api.rule.RuleKey; + +import java.util.Date; + +/** + * @since 5.3 + */ +public interface FilterableIssue { + + String componentKey(); + + RuleKey ruleKey(); + + String severity(); + + String message(); + + Integer line(); + + Double effortToFix(); + + Date creationDate(); + + String projectKey(); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/IssueFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/IssueFilter.java new file mode 100644 index 00000000000..38c50af480c --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/IssueFilter.java @@ -0,0 +1,45 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.scan.issue.filter; + +import org.sonar.api.ExtensionPoint; +import org.sonar.api.batch.BatchSide; + +@BatchSide +@ExtensionPoint +/** + * @since 5.3 + */ +public interface IssueFilter { + + /** + * The <code>accept</code> method is called for each {@link FilterableIssue} created during analysis, to check if it has to be persisted. Examples of use cases are: + * <ul> + * <li>Ignoring or enforcing rules on specific resources</li> + * <li>Switching-off an issue based on its context (<code>//NOSONAR</code> comments, semantic annotations)</li> + * </ul> + * The <code>chain</code> parameter allows for fine control of the filtering logic: it is each filter's duty to either pass the issue to the next filter, by calling + * the {@link IssueFilterChain#accept} method, or return directly if the issue has to be accepted or not + * @param issue the issue being filtered + * @param chain the rest of the filters + * @return <code>true</code> to accept the issue, <code>false</code> to reject it, {@link IssueFilterChain#accept} to let the other filters decide. + */ + boolean accept(FilterableIssue issue, IssueFilterChain chain); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/IssueFilterChain.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/IssueFilterChain.java new file mode 100644 index 00000000000..7ecce587504 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/IssueFilterChain.java @@ -0,0 +1,37 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * SonarQube is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.api.scan.issue.filter; + +/** + * A filter chain is an object provided to issues filters for fine control over the filtering logic. Each filter has the choice to: + * <ul> + * <li>Accept the issue</li> + * <li>Reject the issue</li> + * <li>Let downstream filters decide by passing the issue to the rest of the chain</li> + * </ul> + * + * @since 5.3 + */ +public interface IssueFilterChain { + /** + * Called by a filter to let downstream filters decide the fate of the issue + */ + boolean accept(FilterableIssue issue); +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueFilter.java b/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/package-info.java index 654d40e3a31..571b605c7bf 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/issue/IssueFilter.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/scan/issue/filter/package-info.java @@ -17,20 +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. */ -package org.sonar.api.issue; +@ParametersAreNonnullByDefault +package org.sonar.api.scan.issue.filter; -import org.sonar.api.ExtensionPoint; -import org.sonar.api.batch.BatchSide; - -/** - * @since 3.6 - * @deprecated since 4.0 use {@link org.sonar.api.issue.batch.IssueFilter} - */ -@Deprecated -@BatchSide -@ExtensionPoint -public interface IssueFilter { - - boolean accept(Issue issue); - -} +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java index 8656fa5d48a..64581c1e859 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/checks/NoSonarFilterTest.java @@ -19,11 +19,12 @@ */ package org.sonar.api.checks; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import org.junit.Before; import org.junit.Test; import org.sonar.api.batch.SonarIndex; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilterChain; import org.sonar.api.resources.File; import org.sonar.api.rule.RuleKey; @@ -44,7 +45,7 @@ public class NoSonarFilterTest { @Before public void prepare() { - when(chain.accept(isA(Issue.class))).thenReturn(true); + when(chain.accept(isA(FilterableIssue.class))).thenReturn(true); javaFile = File.create("org/foo/Bar.java"); javaFile.setEffectiveKey("struts:org/foo/Bar.java"); when(sonarIndex.getResource(javaFile)).thenReturn(javaFile); @@ -57,7 +58,7 @@ public class NoSonarFilterTest { noSonarLines.add(55); filter.addResource(javaFile, noSonarLines); - Issue issue = mock(Issue.class); + FilterableIssue issue = mock(FilterableIssue.class); when(issue.componentKey()).thenReturn("struts:org/foo/Bar.java"); when(issue.ruleKey()).thenReturn(RuleKey.of("squid", "Foo")); @@ -79,7 +80,7 @@ public class NoSonarFilterTest { noSonarLines.add(31); filter.addResource(javaFile, noSonarLines); - Issue issue = mock(Issue.class); + FilterableIssue issue = mock(FilterableIssue.class); when(issue.componentKey()).thenReturn("struts:org.apache.Action"); when(issue.ruleKey()).thenReturn(RuleKey.of("squid", "NoSonarCheck")); diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/issue/NoSonarFilterTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/issue/NoSonarFilterTest.java index 230826a8b87..4f6c2b3c48b 100644 --- a/sonar-plugin-api/src/test/java/org/sonar/api/issue/NoSonarFilterTest.java +++ b/sonar-plugin-api/src/test/java/org/sonar/api/issue/NoSonarFilterTest.java @@ -19,16 +19,17 @@ */ package org.sonar.api.issue; +import org.sonar.api.scan.issue.filter.FilterableIssue; + import com.google.common.collect.ImmutableSet; import org.junit.Before; import org.junit.Test; -import org.sonar.api.issue.batch.IssueFilterChain; +import org.sonar.api.scan.issue.filter.IssueFilterChain; import org.sonar.api.rule.RuleKey; import java.util.Set; import static org.mockito.Mockito.times; - import static org.mockito.Mockito.verify; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.isA; @@ -42,12 +43,12 @@ public class NoSonarFilterTest { @Before public void setupChain() { - when(chain.accept(isA(Issue.class))).thenReturn(true); + when(chain.accept(isA(FilterableIssue.class))).thenReturn(true); } @Test public void should_ignore_lines_commented_with_nosonar() { - Issue issue = mock(Issue.class); + FilterableIssue issue = mock(FilterableIssue.class); when(issue.componentKey()).thenReturn("struts:org.apache.Action"); when(issue.ruleKey()).thenReturn(RuleKey.of("squid", "AvoidCycles")); @@ -71,7 +72,7 @@ public class NoSonarFilterTest { @Test public void should_accept_issues_on_no_sonar_rules() { // The "No Sonar" rule logs violations on the lines that are flagged with "NOSONAR" !! - Issue issue = mock(Issue.class); + FilterableIssue issue = mock(FilterableIssue.class); when(issue.componentKey()).thenReturn("struts:org.apache.Action"); when(issue.ruleKey()).thenReturn(RuleKey.of("squid", "NoSonarCheck")); |