From: Julien HENRY Date: Tue, 18 Feb 2014 14:00:19 +0000 (+0100) Subject: Issue exclusions patterns are now initialized prior to sensor phase X-Git-Tag: 4.2~97 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=c128fb65044ab2664b459e741d2e793112f540e4;p=sonarqube.git Issue exclusions patterns are now initialized prior to sensor phase --- diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java index 57f1b91037b..0d2bd21ac5e 100644 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java +++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java @@ -19,8 +19,14 @@ */ package org.sonar.plugins.core; +import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration; + import com.google.common.collect.ImmutableList; -import org.sonar.api.*; +import org.sonar.api.CoreProperties; +import org.sonar.api.Properties; +import org.sonar.api.Property; +import org.sonar.api.PropertyType; +import org.sonar.api.SonarPlugin; import org.sonar.api.checks.NoSonarFilter; import org.sonar.api.config.PropertyDefinition; import org.sonar.api.resources.Qualifiers; @@ -33,22 +39,92 @@ import org.sonar.plugins.core.charts.DistributionAreaChart; import org.sonar.plugins.core.charts.DistributionBarChart; import org.sonar.plugins.core.charts.XradarChart; import org.sonar.plugins.core.colorizers.JavaColorizerFormat; -import org.sonar.plugins.core.dashboards.*; -import org.sonar.plugins.core.issue.*; -import org.sonar.plugins.core.issue.ignore.IgnoreIssuesPlugin; -import org.sonar.plugins.core.issue.notification.*; +import org.sonar.plugins.core.dashboards.GlobalDefaultDashboard; +import org.sonar.plugins.core.dashboards.ProjectDefaultDashboard; +import org.sonar.plugins.core.dashboards.ProjectHotspotDashboard; +import org.sonar.plugins.core.dashboards.ProjectIssuesDashboard; +import org.sonar.plugins.core.dashboards.ProjectTimeMachineDashboard; +import org.sonar.plugins.core.issue.CountFalsePositivesDecorator; +import org.sonar.plugins.core.issue.CountUnresolvedIssuesDecorator; +import org.sonar.plugins.core.issue.InitialOpenIssuesSensor; +import org.sonar.plugins.core.issue.InitialOpenIssuesStack; +import org.sonar.plugins.core.issue.IssueHandlers; +import org.sonar.plugins.core.issue.IssueTracking; +import org.sonar.plugins.core.issue.IssueTrackingDecorator; +import org.sonar.plugins.core.issue.IssuesDensityDecorator; +import org.sonar.plugins.core.issue.WeightedIssuesDecorator; +import org.sonar.plugins.core.issue.notification.ChangesOnMyIssueNotificationDispatcher; +import org.sonar.plugins.core.issue.notification.IssueChangesEmailTemplate; +import org.sonar.plugins.core.issue.notification.NewFalsePositiveNotificationDispatcher; +import org.sonar.plugins.core.issue.notification.NewIssuesEmailTemplate; +import org.sonar.plugins.core.issue.notification.NewIssuesNotificationDispatcher; +import org.sonar.plugins.core.issue.notification.SendIssueNotificationsPostJob; import org.sonar.plugins.core.measurefilters.MyFavouritesFilter; import org.sonar.plugins.core.measurefilters.ProjectFilter; import org.sonar.plugins.core.notifications.alerts.NewAlerts; import org.sonar.plugins.core.security.ApplyProjectRolesDecorator; -import org.sonar.plugins.core.sensors.*; +import org.sonar.plugins.core.sensors.BranchCoverageDecorator; +import org.sonar.plugins.core.sensors.CheckAlertThresholds; +import org.sonar.plugins.core.sensors.CommentDensityDecorator; +import org.sonar.plugins.core.sensors.CoverageDecorator; +import org.sonar.plugins.core.sensors.CoverageMeasurementFilter; +import org.sonar.plugins.core.sensors.DirectoriesDecorator; +import org.sonar.plugins.core.sensors.FileHashSensor; +import org.sonar.plugins.core.sensors.FilesDecorator; +import org.sonar.plugins.core.sensors.GenerateAlertEvents; +import org.sonar.plugins.core.sensors.ItBranchCoverageDecorator; +import org.sonar.plugins.core.sensors.ItCoverageDecorator; +import org.sonar.plugins.core.sensors.ItLineCoverageDecorator; +import org.sonar.plugins.core.sensors.LineCoverageDecorator; +import org.sonar.plugins.core.sensors.ManualMeasureDecorator; +import org.sonar.plugins.core.sensors.OverallBranchCoverageDecorator; +import org.sonar.plugins.core.sensors.OverallCoverageDecorator; +import org.sonar.plugins.core.sensors.OverallLineCoverageDecorator; +import org.sonar.plugins.core.sensors.ProfileEventsSensor; +import org.sonar.plugins.core.sensors.ProjectLinksSensor; +import org.sonar.plugins.core.sensors.UnitTestDecorator; +import org.sonar.plugins.core.sensors.VersionEventsSensor; import org.sonar.plugins.core.technicaldebt.NewTechnicalDebtDecorator; import org.sonar.plugins.core.technicaldebt.TechnicalDebtDecorator; -import org.sonar.plugins.core.timemachine.*; +import org.sonar.plugins.core.timemachine.NewCoverageAggregator; +import org.sonar.plugins.core.timemachine.NewCoverageFileAnalyzer; +import org.sonar.plugins.core.timemachine.NewItCoverageFileAnalyzer; +import org.sonar.plugins.core.timemachine.NewOverallCoverageFileAnalyzer; +import org.sonar.plugins.core.timemachine.TendencyDecorator; +import org.sonar.plugins.core.timemachine.TimeMachineConfigurationPersister; +import org.sonar.plugins.core.timemachine.VariationDecorator; import org.sonar.plugins.core.web.TestsViewer; -import org.sonar.plugins.core.widgets.*; -import org.sonar.plugins.core.widgets.issues.*; -import org.sonar.plugins.core.widgets.measures.*; +import org.sonar.plugins.core.widgets.AlertsWidget; +import org.sonar.plugins.core.widgets.BubbleChartWidget; +import org.sonar.plugins.core.widgets.ComplexityWidget; +import org.sonar.plugins.core.widgets.CoverageWidget; +import org.sonar.plugins.core.widgets.CustomMeasuresWidget; +import org.sonar.plugins.core.widgets.DescriptionWidget; +import org.sonar.plugins.core.widgets.DocumentationCommentsWidget; +import org.sonar.plugins.core.widgets.DuplicationsWidget; +import org.sonar.plugins.core.widgets.EventsWidget; +import org.sonar.plugins.core.widgets.HotspotMetricWidget; +import org.sonar.plugins.core.widgets.HotspotMostViolatedResourcesWidget; +import org.sonar.plugins.core.widgets.HotspotMostViolatedRulesWidget; +import org.sonar.plugins.core.widgets.ItCoverageWidget; +import org.sonar.plugins.core.widgets.SizeWidget; +import org.sonar.plugins.core.widgets.TechnicalDebtPyramidWidget; +import org.sonar.plugins.core.widgets.TimeMachineWidget; +import org.sonar.plugins.core.widgets.TimelineWidget; +import org.sonar.plugins.core.widgets.TreemapWidget; +import org.sonar.plugins.core.widgets.WelcomeWidget; +import org.sonar.plugins.core.widgets.issues.ActionPlansWidget; +import org.sonar.plugins.core.widgets.issues.FalsePositiveIssuesWidget; +import org.sonar.plugins.core.widgets.issues.IssueFilterWidget; +import org.sonar.plugins.core.widgets.issues.IssuesWidget; +import org.sonar.plugins.core.widgets.issues.MyUnresolvedIssuesWidget; +import org.sonar.plugins.core.widgets.issues.UnresolvedIssuesPerAssigneeWidget; +import org.sonar.plugins.core.widgets.issues.UnresolvedIssuesStatusesWidget; +import org.sonar.plugins.core.widgets.measures.MeasureFilterAsBubbleChartWidget; +import org.sonar.plugins.core.widgets.measures.MeasureFilterAsHistogramWidget; +import org.sonar.plugins.core.widgets.measures.MeasureFilterAsPieChartWidget; +import org.sonar.plugins.core.widgets.measures.MeasureFilterListWidget; +import org.sonar.plugins.core.widgets.measures.MeasureFilterTreemapWidget; import java.util.Arrays; import java.util.List; @@ -194,7 +270,8 @@ import java.util.List; @Property( key = CoreProperties.CORE_AUTHENTICATOR_LOCAL_USERS, name = "Local/technical users", - description = "Comma separated list of user logins that will always be authenticated using SonarQube database. When using the LDAP plugin, for these accounts, the user attributes (name, email, ...) are not re-synchronized", + description = "Comma separated list of user logins that will always be authenticated using SonarQube database. " + + "When using the LDAP plugin, for these accounts, the user attributes (name, email, ...) are not re-synchronized", project = false, global = false, defaultValue = "admin", @@ -336,7 +413,7 @@ public final class CorePlugin extends SonarPlugin { NewAlerts.newMetadata()); extensions.addAll(ExclusionProperties.definitions()); - extensions.addAll(IgnoreIssuesPlugin.getExtensions()); + extensions.addAll(IssueExclusionsConfiguration.getPropertyDefinitions()); extensions.addAll(CoverageMeasurementFilter.getPropertyDefinitions()); extensions.addAll(PastSnapshotFinder.getPropertyDefinitions()); extensions.addAll(TechnicalDebtDecorator.definitions()); diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/EnforceIssuesFilter.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/EnforceIssuesFilter.java deleted file mode 100644 index cd443178177..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/EnforceIssuesFilter.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore; - -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.plugins.core.issue.ignore.pattern.InclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; - -public class EnforceIssuesFilter implements IssueFilter { - - private InclusionPatternInitializer patternInitializer; - - private static final Logger LOG = LoggerFactory.getLogger(EnforceIssuesFilter.class); - - public EnforceIssuesFilter(InclusionPatternInitializer patternInitializer) { - this.patternInitializer = patternInitializer; - } - - @Override - public boolean accept(Issue issue, IssueFilterChain chain) { - boolean atLeastOneRuleMatched = false; - boolean atLeastOnePatternFullyMatched = false; - IssuePattern matchingPattern = null; - - for (IssuePattern pattern : patternInitializer.getMulticriteriaPatterns()) { - if (pattern.getRulePattern().match(issue.ruleKey().toString())) { - atLeastOneRuleMatched = true; - String pathForComponent = patternInitializer.getPathForComponent(issue.componentKey()); - if (pathForComponent != null && pattern.getResourcePattern().match(pathForComponent)) { - atLeastOnePatternFullyMatched = true; - matchingPattern = pattern; - } - } - } - - if (atLeastOneRuleMatched) { - if (atLeastOnePatternFullyMatched) { - LOG.debug("Issue {} enforced by pattern {}", issue, matchingPattern); - } - return atLeastOnePatternFullyMatched; - } else { - return chain.accept(issue); - } - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesConfiguration.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesConfiguration.java deleted file mode 100644 index 2f85575c379..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesConfiguration.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore; - -import com.google.common.collect.ImmutableList; -import org.sonar.api.CoreProperties; -import org.sonar.api.PropertyType; -import org.sonar.api.config.PropertyDefinition; -import org.sonar.api.config.PropertyFieldDefinition; -import org.sonar.api.resources.Qualifiers; - -import java.util.List; - -public final class IgnoreIssuesConfiguration { - - public static final String SUB_CATEGORY_IGNORE_ISSUES = "issues"; - - public static final String EXCLUSION_KEY_PREFIX = "sonar.issue.ignore"; - public static final String INCLUSION_KEY_PREFIX = "sonar.issue.enforce"; - - public static final String MULTICRITERIA_SUFFIX = ".multicriteria"; - public static final String PATTERNS_MULTICRITERIA_EXCLUSION_KEY = EXCLUSION_KEY_PREFIX + MULTICRITERIA_SUFFIX; - public static final String PATTERNS_MULTICRITERIA_INCLUSION_KEY = INCLUSION_KEY_PREFIX + MULTICRITERIA_SUFFIX; - public static final String RESOURCE_KEY = "resourceKey"; - private static final String PROPERTY_FILE_PATH_PATTERN = "File Path Pattern"; - public static final String RULE_KEY = "ruleKey"; - private static final String PROPERTY_RULE_KEY_PATTERN = "Rule Key Pattern"; - - public static final String BLOCK_SUFFIX = ".block"; - public static final String PATTERNS_BLOCK_KEY = EXCLUSION_KEY_PREFIX + BLOCK_SUFFIX; - public static final String BEGIN_BLOCK_REGEXP = "beginBlockRegexp"; - public static final String END_BLOCK_REGEXP = "endBlockRegexp"; - - public static final String ALLFILE_SUFFIX = ".allfile"; - public static final String PATTERNS_ALLFILE_KEY = EXCLUSION_KEY_PREFIX + ALLFILE_SUFFIX; - public static final String FILE_REGEXP = "fileRegexp"; - - static final int LARGE_SIZE = 40; - static final int SMALL_SIZE = 10; - - private IgnoreIssuesConfiguration() { - // static configuration declaration only - } - - public static List getPropertyDefinitions() { - return ImmutableList.of( - PropertyDefinition.builder(PATTERNS_MULTICRITERIA_EXCLUSION_KEY) - .category(CoreProperties.CATEGORY_EXCLUSIONS) - .subCategory(SUB_CATEGORY_IGNORE_ISSUES) - .name("Ignore Issues on Multiple Criteria") - .description("Patterns to ignore issues on certain components and for certain coding rules.") - .onQualifiers(Qualifiers.PROJECT) - .index(3) - .fields( - PropertyFieldDefinition.build(RULE_KEY) - .name(PROPERTY_RULE_KEY_PATTERN) - .description("Pattern to match rules which should be ignored.") - .type(PropertyType.STRING) - .indicativeSize(LARGE_SIZE) - .build(), - PropertyFieldDefinition.build(RESOURCE_KEY) - .name(PROPERTY_FILE_PATH_PATTERN) - .description("Pattern to match files which should be ignored.") - .type(PropertyType.STRING) - .indicativeSize(LARGE_SIZE) - .build()) - .build(), - PropertyDefinition.builder(PATTERNS_BLOCK_KEY) - .category(CoreProperties.CATEGORY_EXCLUSIONS) - .subCategory(SUB_CATEGORY_IGNORE_ISSUES) - .name("Ignore Issues in Blocks") - .description("Patterns to ignore all issues on specific blocks of code, while continuing to scan and mark issues on the remainder of the file.") - .onQualifiers(Qualifiers.PROJECT) - .index(2) - .fields( - PropertyFieldDefinition.build(BEGIN_BLOCK_REGEXP) - .name("Regular Expression for Start of Block") - .description("If this regular expression is found in a file, then following lines are ignored until end of block.") - .type(PropertyType.STRING) - .indicativeSize(LARGE_SIZE) - .build(), - PropertyFieldDefinition.build(END_BLOCK_REGEXP) - .name("Regular Expression for End of Block") - .description("If specified, this regular expression is used to determine the end of code blocks to ignore. If not, then block ends at the end of file.") - .type(PropertyType.STRING) - .indicativeSize(LARGE_SIZE) - .build()) - .build(), - PropertyDefinition.builder(PATTERNS_ALLFILE_KEY) - .category(CoreProperties.CATEGORY_EXCLUSIONS) - .subCategory(SUB_CATEGORY_IGNORE_ISSUES) - .name("Ignore Issues on Files") - .description("Patterns to ignore all issues on files that contain a block of code matching a given regular expression.") - .onQualifiers(Qualifiers.PROJECT) - .index(1) - .fields( - PropertyFieldDefinition.build(FILE_REGEXP) - .name("Regular Expression") - .description("If this regular expression is found in a file, then the whole file is ignored.") - .type(PropertyType.STRING) - .indicativeSize(LARGE_SIZE) - .build()) - .build(), - PropertyDefinition.builder(PATTERNS_MULTICRITERIA_INCLUSION_KEY) - .category(CoreProperties.CATEGORY_EXCLUSIONS) - .subCategory(SUB_CATEGORY_IGNORE_ISSUES) - .name("Restrict Scope of Coding Rules") - .description("Patterns to restrict the application of a rule to only certain components, ignoring all others.") - .onQualifiers(Qualifiers.PROJECT) - .index(4) - .fields( - PropertyFieldDefinition.build(RULE_KEY) - .name(PROPERTY_RULE_KEY_PATTERN) - .description("Pattern used to match rules which should be restricted.") - .type(PropertyType.STRING) - .indicativeSize(LARGE_SIZE) - .build(), - PropertyFieldDefinition.build(RESOURCE_KEY) - .name(PROPERTY_FILE_PATH_PATTERN) - .description("Pattern used to match files to which the rules should be restricted.") - .type(PropertyType.STRING) - .indicativeSize(LARGE_SIZE) - .build()) - .build()); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilter.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilter.java deleted file mode 100644 index d49369dddae..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilter.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore; - -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.plugins.core.issue.ignore.pattern.ExclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; -import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; - -public class IgnoreIssuesFilter implements IssueFilter { - - private PatternMatcher patternMatcher; - - private static final Logger LOG = LoggerFactory.getLogger(IgnoreIssuesFilter.class); - - public IgnoreIssuesFilter(ExclusionPatternInitializer patternInitializer) { - this.patternMatcher = patternInitializer.getPatternMatcher(); - } - - @Override - public boolean accept(Issue issue, IssueFilterChain chain) { - if (hasMatchFor(issue)) { - return false; - } else { - return chain.accept(issue); - } - } - - private boolean hasMatchFor(Issue issue) { - IssuePattern pattern = patternMatcher.getMatchingPattern(issue); - if (pattern != null) { - logExclusion(issue, pattern); - return true; - } - return false; - } - - private void logExclusion(Issue issue, IssuePattern pattern) { - LOG.debug("Issue {} ignored by exclusion pattern {}", issue, pattern); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPlugin.java deleted file mode 100644 index c39060a912c..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPlugin.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore; - -import com.google.common.collect.ImmutableList; -import org.sonar.plugins.core.issue.ignore.pattern.ExclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.InclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.scanner.IgnoreIssuesRegexpScanner; -import org.sonar.plugins.core.issue.ignore.scanner.IgnoreIssuesSourceScanner; - -import java.util.List; - -public final class IgnoreIssuesPlugin { - - private IgnoreIssuesPlugin() { - // static extension declaration only - } - - public static List getExtensions() { - ImmutableList.Builder extensions = ImmutableList.builder(); - - extensions.addAll(IgnoreIssuesConfiguration.getPropertyDefinitions()); - extensions.add( - InclusionPatternInitializer.class, - ExclusionPatternInitializer.class, - IgnoreIssuesRegexpScanner.class, - IgnoreIssuesSourceScanner.class, - EnforceIssuesFilter.class, - IgnoreIssuesFilter.class); - - return extensions.build(); - } - -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/package-info.java deleted file mode 100644 index bdadd24e158..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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. - */ -@ParametersAreNonnullByDefault -package org.sonar.plugins.core.issue.ignore; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/AbstractPatternInitializer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/AbstractPatternInitializer.java deleted file mode 100644 index f8d23186c0e..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/AbstractPatternInitializer.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.BatchExtension; -import org.sonar.api.config.Settings; -import org.sonar.plugins.core.issue.ignore.IgnoreIssuesConfiguration; - -import java.util.List; - -import static com.google.common.base.Objects.firstNonNull; - -public abstract class AbstractPatternInitializer implements BatchExtension { - - private Settings settings; - - private List multicriteriaPatterns; - - protected AbstractPatternInitializer(Settings settings) { - this.settings = settings; - initPatterns(); - } - - protected Settings getSettings() { - return settings; - } - - public List getMulticriteriaPatterns() { - return multicriteriaPatterns; - } - - public boolean hasConfiguredPatterns() { - return hasMulticriteriaPatterns(); - } - - public boolean hasMulticriteriaPatterns() { - return ! multicriteriaPatterns.isEmpty(); - } - - public abstract void initializePatternsForPath(String relativePath, String componentKey); - - @VisibleForTesting - protected final void initPatterns() { - // Patterns Multicriteria - multicriteriaPatterns = Lists.newArrayList(); - String patternConf = StringUtils.defaultIfBlank(settings.getString(getMulticriteriaConfigurationKey()), ""); - for (String id : StringUtils.split(patternConf, ',')) { - String propPrefix = getMulticriteriaConfigurationKey() + "." + id + "."; - String resourceKeyPattern = settings.getString(propPrefix + IgnoreIssuesConfiguration.RESOURCE_KEY); - String ruleKeyPattern = settings.getString(propPrefix + IgnoreIssuesConfiguration.RULE_KEY); - String lineRange = "*"; - String[] fields = new String[] { resourceKeyPattern, ruleKeyPattern, lineRange }; - PatternDecoder.checkRegularLineConstraints(StringUtils.join(fields, ","), fields); - IssuePattern pattern = new IssuePattern(firstNonNull(resourceKeyPattern, "*"), firstNonNull(ruleKeyPattern, "*")); - PatternDecoder.decodeRangeOfLines(pattern, firstNonNull(lineRange, "*")); - multicriteriaPatterns.add(pattern); - } - } - - protected abstract String getMulticriteriaConfigurationKey(); -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/ExclusionPatternInitializer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/ExclusionPatternInitializer.java deleted file mode 100644 index a20e8c33ba7..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/ExclusionPatternInitializer.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.config.Settings; -import org.sonar.plugins.core.issue.ignore.IgnoreIssuesConfiguration; - -import java.util.List; - -import static com.google.common.base.Strings.nullToEmpty; - -public class ExclusionPatternInitializer extends AbstractPatternInitializer { - - private List blockPatterns; - private List allFilePatterns; - private PatternMatcher patternMatcher; - - public ExclusionPatternInitializer(Settings settings) { - super(settings); - patternMatcher = new PatternMatcher(); - loadFileContentPatterns(); - } - - @Override - protected String getMulticriteriaConfigurationKey() { - return IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY; - } - - public PatternMatcher getPatternMatcher() { - return patternMatcher; - } - - @Override - public void initializePatternsForPath(String relativePath, String componentKey) { - for (IssuePattern pattern: getMulticriteriaPatterns()) { - if (pattern.matchResource(relativePath)) { - getPatternMatcher().addPatternForComponent(componentKey, pattern); - } - } - } - - @Override - public boolean hasConfiguredPatterns() { - return hasFileContentPattern() || hasMulticriteriaPatterns(); - } - - @VisibleForTesting - protected final void loadFileContentPatterns() { - // Patterns Block - blockPatterns = Lists.newArrayList(); - String patternConf = StringUtils.defaultIfBlank(getSettings().getString(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY), ""); - for (String id : StringUtils.split(patternConf, ',')) { - String propPrefix = IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + "." + id + "."; - String beginBlockRegexp = getSettings().getString(propPrefix + IgnoreIssuesConfiguration.BEGIN_BLOCK_REGEXP); - String endBlockRegexp = getSettings().getString(propPrefix + IgnoreIssuesConfiguration.END_BLOCK_REGEXP); - String[] fields = new String[] { beginBlockRegexp, endBlockRegexp }; - PatternDecoder.checkDoubleRegexpLineConstraints(StringUtils.join(fields, ","), fields); - IssuePattern pattern = new IssuePattern().setBeginBlockRegexp(nullToEmpty(beginBlockRegexp)).setEndBlockRegexp(nullToEmpty(endBlockRegexp)); - blockPatterns.add(pattern); - } - - // Patterns All File - allFilePatterns = Lists.newArrayList(); - patternConf = StringUtils.defaultIfBlank(getSettings().getString(IgnoreIssuesConfiguration.PATTERNS_ALLFILE_KEY), ""); - for (String id : StringUtils.split(patternConf, ',')) { - String propPrefix = IgnoreIssuesConfiguration.PATTERNS_ALLFILE_KEY + "." + id + "."; - String allFileRegexp = getSettings().getString(propPrefix + IgnoreIssuesConfiguration.FILE_REGEXP); - PatternDecoder.checkWholeFileRegexp(allFileRegexp); - IssuePattern pattern = new IssuePattern().setAllFileRegexp(nullToEmpty(allFileRegexp)); - allFilePatterns.add(pattern); - } - } - - public List getBlockPatterns() { - return blockPatterns; - } - - public List getAllFilePatterns() { - return allFilePatterns; - } - - public boolean hasFileContentPattern() { - return ! (blockPatterns.isEmpty() && allFilePatterns.isEmpty()); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/InclusionPatternInitializer.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/InclusionPatternInitializer.java deleted file mode 100644 index 57dd0086c03..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/InclusionPatternInitializer.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import com.google.common.collect.Maps; -import org.sonar.api.config.Settings; -import org.sonar.plugins.core.issue.ignore.IgnoreIssuesConfiguration; - -import java.util.Map; - -public class InclusionPatternInitializer extends AbstractPatternInitializer { - - private Map pathForComponent; - - public InclusionPatternInitializer(Settings settings) { - super(settings); - pathForComponent = Maps.newHashMap(); - } - - @Override - protected String getMulticriteriaConfigurationKey() { - return IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY; - } - - @Override - public void initializePatternsForPath(String relativePath, String componentKey) { - pathForComponent.put(componentKey, relativePath); - } - - public String getPathForComponent(String componentKey) { - return pathForComponent.get(componentKey); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePattern.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePattern.java deleted file mode 100644 index 458292a6e80..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePattern.java +++ /dev/null @@ -1,167 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -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; - -import java.util.Set; - -public class IssuePattern { - - private WildcardPattern resourcePattern; - private WildcardPattern rulePattern; - private Set lines = Sets.newLinkedHashSet(); - private Set lineRanges = Sets.newLinkedHashSet(); - private String beginBlockRegexp; - private String endBlockRegexp; - private String allFileRegexp; - private boolean checkLines = true; - - public IssuePattern() { - } - - public IssuePattern(String resourcePattern, String rulePattern) { - this.resourcePattern = WildcardPattern.create(resourcePattern); - this.rulePattern = WildcardPattern.create(rulePattern); - } - - public IssuePattern(String resourcePattern, String rulePattern, Set lineRanges) { - this(resourcePattern, rulePattern); - this.lineRanges = lineRanges; - } - - public WildcardPattern getResourcePattern() { - return resourcePattern; - } - - public WildcardPattern getRulePattern() { - return rulePattern; - } - - public String getBeginBlockRegexp() { - return beginBlockRegexp; - } - - public String getEndBlockRegexp() { - return endBlockRegexp; - } - - public String getAllFileRegexp() { - return allFileRegexp; - } - - IssuePattern addLineRange(int fromLineId, int toLineId) { - lineRanges.add(new LineRange(fromLineId, toLineId)); - return this; - } - - IssuePattern addLine(int lineId) { - lines.add(lineId); - return this; - } - - boolean isCheckLines() { - return checkLines; - } - - IssuePattern setCheckLines(boolean b) { - this.checkLines = b; - return this; - } - - IssuePattern setBeginBlockRegexp(String beginBlockRegexp) { - this.beginBlockRegexp = beginBlockRegexp; - return this; - } - - IssuePattern setEndBlockRegexp(String endBlockRegexp) { - this.endBlockRegexp = endBlockRegexp; - return this; - } - - IssuePattern setAllFileRegexp(String allFileRegexp) { - this.allFileRegexp = allFileRegexp; - return this; - } - - Set getAllLines() { - Set allLines = Sets.newLinkedHashSet(lines); - for (LineRange lineRange : lineRanges) { - allLines.addAll(lineRange.toLines()); - } - return allLines; - } - - public boolean match(Issue issue) { - boolean match = matchResource(issue.componentKey()) - && matchRule(issue.ruleKey()); - if (checkLines) { - Integer line = issue.line(); - if (line == null) { - match = false; - } else { - match = match && matchLine(line); - } - } - return match; - } - - boolean matchLine(int lineId) { - if (lines.contains(lineId)) { - return true; - } - - for (LineRange range : lineRanges) { - if (range.in(lineId)) { - return true; - } - } - - return false; - } - - boolean matchRule(RuleKey rule) { - if (rule == null) { - return false; - } - - String key = new StringBuilder().append(rule.repository()).append(':').append(rule.rule()).toString(); - return rulePattern.match(key); - } - - boolean matchResource(String resource) { - return resource != null && resourcePattern.match(resource); - } - - public IssuePattern forResource(String resource) { - return new IssuePattern(resource, rulePattern.toString(), lineRanges).setCheckLines(isCheckLines()); - } - - @Override - public String toString() { - return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/LineRange.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/LineRange.java deleted file mode 100644 index 743533d05f3..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/LineRange.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Sets; - -import java.util.Set; - -public class LineRange { - private int from; - private int to; - - public LineRange(int from, int to) { - Preconditions.checkArgument(from <= to, "Line range is not valid: %s must be greater than %s", from, to); - - this.from = from; - this.to = to; - } - - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - for (int index = from; index <= to; index++) { - lines.add(index); - } - return lines; - } - - @Override - public String toString() { - return "[" + from + "-" + to + "]"; - } - - @Override - public int hashCode() { - final int prime = 31; - int result = 1; - result = prime * result + from; - result = prime * result + to; - return result; - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - if (fieldsDiffer((LineRange) obj)) { - return false; - } - return true; - } - - private boolean fieldsDiffer(LineRange other) { - if (from != other.from) { - return true; - } - if (to != other.to) { - return true; - } - return false; - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternDecoder.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternDecoder.java deleted file mode 100644 index 7912ed1e4c0..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternDecoder.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.collect.Lists; -import org.apache.commons.lang.StringUtils; -import org.sonar.api.utils.SonarException; - -import java.util.List; - -public class PatternDecoder { - - private static final int THREE_FIELDS_PER_LINE = 3; - private static final String LINE_RANGE_REGEXP = "\\[((\\d+|\\d+-\\d+),?)*\\]"; - private static final String CONFIG_FORMAT_ERROR_PREFIX = "Exclusions > Issues : Invalid format. "; - - public List decode(String patternsList) { - List patterns = Lists.newLinkedList(); - String[] patternsLines = StringUtils.split(patternsList, "\n"); - for (String patternLine : patternsLines) { - IssuePattern pattern = decodeLine(patternLine.trim()); - if (pattern != null) { - patterns.add(pattern); - } - } - return patterns; - } - - /** - * Main method that decodes a line which defines a pattern - */ - public IssuePattern decodeLine(String line) { - if (isBlankOrComment(line)) { - return null; - } - - String[] fields = StringUtils.splitPreserveAllTokens(line, ';'); - if (fields.length > THREE_FIELDS_PER_LINE) { - throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The following line has more than 3 fields separated by comma: " + line); - } - - IssuePattern pattern; - if (fields.length == THREE_FIELDS_PER_LINE) { - checkRegularLineConstraints(line, fields); - pattern = new IssuePattern(StringUtils.trim(fields[0]), StringUtils.trim(fields[1])); - decodeRangeOfLines(pattern, fields[2]); - } else if (fields.length == 2) { - checkDoubleRegexpLineConstraints(line, fields); - pattern = new IssuePattern().setBeginBlockRegexp(fields[0]).setEndBlockRegexp(fields[1]); - } else { - checkWholeFileRegexp(fields[0]); - pattern = new IssuePattern().setAllFileRegexp(fields[0]); - } - - return pattern; - } - - static void checkRegularLineConstraints(String line, String[] fields) { - if (!isResource(fields[0])) { - throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The first field does not define a resource pattern: " + line); - } - if (!isRule(fields[1])) { - throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The second field does not define a rule pattern: " + line); - } - if (!isLinesRange(fields[2])) { - throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The third field does not define a range of lines: " + line); - } - } - - static void checkDoubleRegexpLineConstraints(String line, String[] fields) { - if (!isRegexp(fields[0])) { - throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The first field does not define a regular expression: " + line); - } - // As per configuration help, missing second field means: from start regexp to EOF - } - - static void checkWholeFileRegexp(String regexp) { - if (!isRegexp(regexp)) { - throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The field does not define a regular expression: " + regexp); - } - } - - public static void decodeRangeOfLines(IssuePattern pattern, String field) { - if (StringUtils.equals(field, "*")) { - pattern.setCheckLines(false); - } else { - pattern.setCheckLines(true); - String s = StringUtils.substringBetween(StringUtils.trim(field), "[", "]"); - String[] parts = StringUtils.split(s, ','); - for (String part : parts) { - if (StringUtils.contains(part, '-')) { - String[] range = StringUtils.split(part, '-'); - pattern.addLineRange(Integer.valueOf(range[0]), Integer.valueOf(range[1])); - } else { - pattern.addLine(Integer.valueOf(part)); - } - } - } - } - - @VisibleForTesting - static boolean isLinesRange(String field) { - return StringUtils.equals(field, "*") || java.util.regex.Pattern.matches(LINE_RANGE_REGEXP, field); - } - - @VisibleForTesting - static boolean isBlankOrComment(String line) { - return StringUtils.isBlank(line) ^ StringUtils.startsWith(line, "#"); - } - - @VisibleForTesting - static boolean isResource(String field) { - return StringUtils.isNotBlank(field); - } - - @VisibleForTesting - static boolean isRule(String field) { - return StringUtils.isNotBlank(field); - } - - @VisibleForTesting - static boolean isRegexp(String field) { - return StringUtils.isNotBlank(field); - } -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcher.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcher.java deleted file mode 100644 index a01be7b19a2..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcher.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -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; -import java.util.Set; - -public class PatternMatcher { - - private Multimap patternByComponent = LinkedHashMultimap.create(); - - public IssuePattern getMatchingPattern(Issue issue) { - IssuePattern matchingPattern = null; - Iterator patternIterator = getPatternsForComponent(issue.componentKey()).iterator(); - while(matchingPattern == null && patternIterator.hasNext()) { - IssuePattern nextPattern = patternIterator.next(); - if (nextPattern.match(issue)) { - matchingPattern = nextPattern; - } - } - return matchingPattern; - } - - public Collection getPatternsForComponent(String componentKey) { - return patternByComponent.get(componentKey); - } - - public void addPatternForComponent(String component, IssuePattern pattern) { - patternByComponent.put(component, pattern.forResource(component)); - } - - public void addPatternToExcludeResource(String resource) { - addPatternForComponent(resource, new IssuePattern(resource, "*").setCheckLines(false)); - } - - public void addPatternToExcludeLines(String resource, Set lineRanges) { - addPatternForComponent(resource, new IssuePattern(resource, "*", lineRanges).setCheckLines(true)); - } - -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/package-info.java deleted file mode 100644 index 55174ccde1c..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/pattern/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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. - */ -@ParametersAreNonnullByDefault -package org.sonar.plugins.core.issue.ignore.pattern; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScanner.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScanner.java deleted file mode 100644 index d6fa2d26fa6..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScanner.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.scanner; - -import com.google.common.collect.Lists; -import com.google.common.collect.Sets; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.sonar.api.BatchExtension; -import org.sonar.plugins.core.issue.ignore.pattern.ExclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; -import org.sonar.plugins.core.issue.ignore.pattern.LineRange; - -import java.io.File; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.List; -import java.util.Set; - -public class IgnoreIssuesRegexpScanner implements BatchExtension { - - private static final Logger LOG = LoggerFactory.getLogger(IgnoreIssuesRegexpScanner.class); - - private ExclusionPatternInitializer exclusionPatternInitializer; - private List allFilePatterns; - private List blockMatchers; - - // fields to be reset at every new scan - private DoubleRegexpMatcher currentMatcher; - private int fileLength; - private List lineExclusions; - private LineExclusion currentLineExclusion; - - public IgnoreIssuesRegexpScanner(ExclusionPatternInitializer patternsInitializer) { - this.exclusionPatternInitializer = patternsInitializer; - - lineExclusions = Lists.newArrayList(); - allFilePatterns = Lists.newArrayList(); - blockMatchers = Lists.newArrayList(); - - for (IssuePattern pattern : patternsInitializer.getAllFilePatterns()) { - allFilePatterns.add(java.util.regex.Pattern.compile(pattern.getAllFileRegexp())); - } - for (IssuePattern pattern : patternsInitializer.getBlockPatterns()) { - blockMatchers.add(new DoubleRegexpMatcher( - java.util.regex.Pattern.compile(pattern.getBeginBlockRegexp()), - java.util.regex.Pattern.compile(pattern.getEndBlockRegexp()))); - } - - init(); - } - - private void init() { - currentMatcher = null; - fileLength = 0; - lineExclusions.clear(); - currentLineExclusion = null; - } - - public void scan(String resource, File file, Charset sourcesEncoding) throws IOException { - LOG.debug("Scanning {}", resource); - init(); - - List lines = FileUtils.readLines(file, sourcesEncoding.name()); - int lineIndex = 0; - for (String line : lines) { - lineIndex++; - if (line.trim().length() == 0) { - continue; - } - - // first check the single regexp patterns that can be used to totally exclude a file - for (java.util.regex.Pattern pattern : allFilePatterns) { - if (pattern.matcher(line).find()) { - exclusionPatternInitializer.getPatternMatcher().addPatternToExcludeResource(resource); - // nothing more to do on this file - LOG.debug("- Exclusion pattern '{}': every violation in this file will be ignored.", pattern); - return; - } - } - - // then check the double regexps if we're still here - checkDoubleRegexps(line, lineIndex); - } - - if (currentMatcher != null && !currentMatcher.hasSecondPattern()) { - // this will happen when there is a start block regexp but no end block regexp - endExclusion(lineIndex + 1); - } - - // now create the new line-based pattern for this file if there are exclusions - fileLength = lineIndex; - if (!lineExclusions.isEmpty()) { - Set lineRanges = convertLineExclusionsToLineRanges(); - LOG.debug("- Line exclusions found: {}", lineRanges); - exclusionPatternInitializer.getPatternMatcher().addPatternToExcludeLines(resource, lineRanges); - } - } - - private Set convertLineExclusionsToLineRanges() { - Set lineRanges = Sets.newHashSet(); - for (LineExclusion lineExclusion : lineExclusions) { - lineRanges.add(lineExclusion.toLineRange()); - } - return lineRanges; - } - - private void checkDoubleRegexps(String line, int lineIndex) { - if (currentMatcher == null) { - for (DoubleRegexpMatcher matcher : blockMatchers) { - if (matcher.matchesFirstPattern(line)) { - startExclusion(lineIndex); - currentMatcher = matcher; - break; - } - } - } else { - if (currentMatcher.matchesSecondPattern(line)) { - endExclusion(lineIndex); - currentMatcher = null; - } - } - } - - private void startExclusion(int lineIndex) { - currentLineExclusion = new LineExclusion(lineIndex); - lineExclusions.add(currentLineExclusion); - } - - private void endExclusion(int lineIndex) { - currentLineExclusion.setEnd(lineIndex); - currentLineExclusion = null; - } - - private class LineExclusion { - - private int start; - private int end; - - LineExclusion(int start) { - this.start = start; - this.end = -1; - } - - void setEnd(int end) { - this.end = end; - } - - public LineRange toLineRange() { - return new LineRange(start, end == -1 ? fileLength : end); - } - - } - - private static class DoubleRegexpMatcher { - - private java.util.regex.Pattern firstPattern; - private java.util.regex.Pattern secondPattern; - - DoubleRegexpMatcher(java.util.regex.Pattern firstPattern, java.util.regex.Pattern secondPattern) { - this.firstPattern = firstPattern; - this.secondPattern = secondPattern; - } - - boolean matchesFirstPattern(String line) { - return firstPattern.matcher(line).find(); - } - - boolean matchesSecondPattern(String line) { - return hasSecondPattern() && secondPattern.matcher(line).find(); - } - - boolean hasSecondPattern() { - return StringUtils.isNotEmpty(secondPattern.toString()); - } - } - -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesSourceScanner.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesSourceScanner.java deleted file mode 100644 index f88696d7128..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesSourceScanner.java +++ /dev/null @@ -1,91 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.scanner; - -import org.sonar.api.batch.DependedUpon; -import org.sonar.api.batch.Phase; -import org.sonar.api.batch.Sensor; -import org.sonar.api.batch.SensorContext; -import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.InputFile; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; -import org.sonar.java.api.JavaUtils; -import org.sonar.plugins.core.issue.ignore.pattern.ExclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.InclusionPatternInitializer; - -import java.nio.charset.Charset; - -@Phase(name = Phase.Name.PRE) -// Issue Exclusions must be computed before JavaSquidSensor is executed and creates issues -@DependedUpon(value = JavaUtils.BARRIER_BEFORE_SQUID) -public final class IgnoreIssuesSourceScanner implements Sensor { - - private final IgnoreIssuesRegexpScanner regexpScanner; - private final ExclusionPatternInitializer exclusionPatternInitializer; - private final InclusionPatternInitializer inclusionPatternInitializer; - private final DefaultModuleFileSystem fileSystem; - - public IgnoreIssuesSourceScanner(IgnoreIssuesRegexpScanner regexpScanner, ExclusionPatternInitializer exclusionPatternInitializer, InclusionPatternInitializer inclusionPatternInitializer, - DefaultModuleFileSystem fileSystem) { - this.regexpScanner = regexpScanner; - this.exclusionPatternInitializer = exclusionPatternInitializer; - this.inclusionPatternInitializer = inclusionPatternInitializer; - this.fileSystem = fileSystem; - } - - public boolean shouldExecuteOnProject(Project project) { - return inclusionPatternInitializer.hasConfiguredPatterns() - || exclusionPatternInitializer.hasConfiguredPatterns(); - } - - /** - * {@inheritDoc} - */ - public void analyse(Project project, SensorContext context) { - Charset sourcesEncoding = fileSystem.sourceCharset(); - - for (InputFile inputFile : fileSystem.inputFiles(FileQuery.all())) { - try { - String componentEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); - if (componentEffectiveKey != null) { - String path = inputFile.path(); - inclusionPatternInitializer.initializePatternsForPath(path, componentEffectiveKey); - exclusionPatternInitializer.initializePatternsForPath(path, componentEffectiveKey); - if (exclusionPatternInitializer.hasFileContentPattern()) { - regexpScanner.scan(componentEffectiveKey, inputFile.file(), sourcesEncoding); - } - } - } catch (Exception e) { - throw new SonarException("Unable to read the source file : '" + inputFile.absolutePath() + "' with the charset : '" - + sourcesEncoding.name() + "'.", e); - } - } - } - - @Override - public String toString() { - return "Issues Exclusions - Source Scanner"; - } - -} diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/package-info.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/package-info.java deleted file mode 100644 index 9471f4ddeb2..00000000000 --- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/issue/ignore/scanner/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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. - */ -@ParametersAreNonnullByDefault -package org.sonar.plugins.core.issue.ignore.scanner; - -import javax.annotation.ParametersAreNonnullByDefault; diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/EnforceIssuesFilterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/EnforceIssuesFilterTest.java deleted file mode 100644 index 3cba13dbd78..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/EnforceIssuesFilterTest.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore; - -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.rule.RuleKey; -import org.sonar.api.utils.WildcardPattern; -import org.sonar.plugins.core.issue.ignore.pattern.InclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; - -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class EnforceIssuesFilterTest { - - private InclusionPatternInitializer exclusionPatternInitializer; - private EnforceIssuesFilter ignoreFilter; - private Issue issue; - private IssueFilterChain chain; - - @Before - public void init() { - exclusionPatternInitializer = mock(InclusionPatternInitializer.class); - issue = mock(Issue.class); - chain = mock(IssueFilterChain.class); - when(chain.accept(issue)).thenReturn(true); - - ignoreFilter = new EnforceIssuesFilter(exclusionPatternInitializer); - } - - @Test - public void shouldPassToChainIfNoConfiguredPatterns() { - assertThat(ignoreFilter.accept(issue, chain)).isTrue(); - verify(chain).accept(issue); - } - - @Test - public void shouldPassToChainIfRuleDoesNotMatch() { - String rule = "rule"; - RuleKey ruleKey = mock(RuleKey.class); - when(ruleKey.toString()).thenReturn(rule); - when(issue.ruleKey()).thenReturn(ruleKey); - - IssuePattern matching = mock(IssuePattern.class); - WildcardPattern rulePattern = mock(WildcardPattern.class); - when(matching.getRulePattern()).thenReturn(rulePattern); - when(rulePattern.match(rule)).thenReturn(false); - when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching)); - - assertThat(ignoreFilter.accept(issue, chain)).isTrue(); - verify(chain).accept(issue); - } - - @Test - public void shouldAcceptIssueIfFullyMatched() { - String rule = "rule"; - String path = "org/sonar/api/Issue.java"; - String componentKey = "org.sonar.api.Issue"; - RuleKey ruleKey = mock(RuleKey.class); - when(ruleKey.toString()).thenReturn(rule); - when(issue.ruleKey()).thenReturn(ruleKey); - when(issue.componentKey()).thenReturn(componentKey); - - IssuePattern matching = mock(IssuePattern.class); - WildcardPattern rulePattern = mock(WildcardPattern.class); - when(matching.getRulePattern()).thenReturn(rulePattern); - when(rulePattern.match(rule)).thenReturn(true); - WildcardPattern pathPattern = mock(WildcardPattern.class); - when(matching.getResourcePattern()).thenReturn(pathPattern); - when(pathPattern.match(path)).thenReturn(true); - when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching)); - when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(path); - - assertThat(ignoreFilter.accept(issue, chain)).isTrue(); - verifyZeroInteractions(chain); - } - - @Test - public void shouldRefuseIssueIfRuleMatchesButNotPath() { - String rule = "rule"; - String path = "org/sonar/api/Issue.java"; - String componentKey = "org.sonar.api.Issue"; - RuleKey ruleKey = mock(RuleKey.class); - when(ruleKey.toString()).thenReturn(rule); - when(issue.ruleKey()).thenReturn(ruleKey); - when(issue.componentKey()).thenReturn(componentKey); - - IssuePattern matching = mock(IssuePattern.class); - WildcardPattern rulePattern = mock(WildcardPattern.class); - when(matching.getRulePattern()).thenReturn(rulePattern); - when(rulePattern.match(rule)).thenReturn(true); - WildcardPattern pathPattern = mock(WildcardPattern.class); - when(matching.getResourcePattern()).thenReturn(pathPattern); - when(pathPattern.match(path)).thenReturn(false); - when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching)); - when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(path); - - assertThat(ignoreFilter.accept(issue, chain)).isFalse(); - verifyZeroInteractions(chain); - } - - @Test - public void shouldRefuseIssueIfRuleMatchesAndPathUnknown() { - String rule = "rule"; - String path = "org/sonar/api/Issue.java"; - String componentKey = "org.sonar.api.Issue"; - RuleKey ruleKey = mock(RuleKey.class); - when(ruleKey.toString()).thenReturn(rule); - when(issue.ruleKey()).thenReturn(ruleKey); - when(issue.componentKey()).thenReturn(componentKey); - - IssuePattern matching = mock(IssuePattern.class); - WildcardPattern rulePattern = mock(WildcardPattern.class); - when(matching.getRulePattern()).thenReturn(rulePattern); - when(rulePattern.match(rule)).thenReturn(true); - WildcardPattern pathPattern = mock(WildcardPattern.class); - when(matching.getResourcePattern()).thenReturn(pathPattern); - when(pathPattern.match(path)).thenReturn(false); - when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching)); - when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(null); - - assertThat(ignoreFilter.accept(issue, chain)).isFalse(); - verifyZeroInteractions(chain); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilterTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilterTest.java deleted file mode 100644 index b582c101e03..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesFilterTest.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.issue.Issue; -import org.sonar.api.issue.batch.IssueFilterChain; -import org.sonar.plugins.core.issue.ignore.pattern.ExclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; -import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; - -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class IgnoreIssuesFilterTest { - - private ExclusionPatternInitializer exclusionPatternInitializer; - private PatternMatcher exclusionPatternMatcher; - private IgnoreIssuesFilter ignoreFilter; - private Issue issue; - private IssueFilterChain chain; - - @Before - public void init() { - exclusionPatternMatcher = mock(PatternMatcher.class); - exclusionPatternInitializer = mock(ExclusionPatternInitializer.class); - when(exclusionPatternInitializer.getPatternMatcher()).thenReturn(exclusionPatternMatcher); - issue = mock(Issue.class); - chain = mock(IssueFilterChain.class); - when(chain.accept(issue)).thenReturn(true); - - ignoreFilter = new IgnoreIssuesFilter(exclusionPatternInitializer); - } - - @Test - public void shouldPassToChainIfMatcherHasNoPatternForIssue() { - when(exclusionPatternMatcher.getMatchingPattern(issue)).thenReturn(null); - - assertThat(ignoreFilter.accept(issue, chain)).isTrue(); - } - - @Test - public void shouldAcceptOrRefuseIfMatcherHasPatternForIssue() { - when(exclusionPatternMatcher.getMatchingPattern(issue)).thenReturn(mock(IssuePattern.class)); - - assertThat(ignoreFilter.accept(issue, chain)).isFalse(); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPluginTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPluginTest.java deleted file mode 100644 index 339ebee90f3..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/IgnoreIssuesPluginTest.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore; - -import org.junit.Test; - -import static org.fest.assertions.Assertions.assertThat; - -public class IgnoreIssuesPluginTest { - @Test - public void justForCoverage() { - assertThat(IgnoreIssuesPlugin.getExtensions()).hasSize(4 /* properties */ + 6 /* extensions */); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/ExclusionPatternInitializerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/ExclusionPatternInitializerTest.java deleted file mode 100644 index 0f9b6493e8a..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/ExclusionPatternInitializerTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.config.PropertyDefinitions; -import org.sonar.api.config.Settings; -import org.sonar.api.utils.SonarException; -import org.sonar.plugins.core.issue.ignore.IgnoreIssuesConfiguration; - -import static org.fest.assertions.Assertions.assertThat; - -public class ExclusionPatternInitializerTest { - - private ExclusionPatternInitializer patternsInitializer; - - private Settings settings; - - @Before - public void init() { - settings = new Settings(new PropertyDefinitions(IgnoreIssuesConfiguration.getPropertyDefinitions())); - patternsInitializer = new ExclusionPatternInitializer(settings); - } - - @Test - public void testNoConfiguration() { - patternsInitializer.initPatterns(); - assertThat(patternsInitializer.hasConfiguredPatterns()).isFalse(); - assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0); - } - - @Test - public void shouldHavePatternsBasedOnMulticriteriaPattern() { - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1,2"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IgnoreIssuesConfiguration.RESOURCE_KEY, "org/foo/Bar.java"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IgnoreIssuesConfiguration.RULE_KEY, "*"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".2." + IgnoreIssuesConfiguration.RESOURCE_KEY, "org/foo/Hello.java"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".2." + IgnoreIssuesConfiguration.RULE_KEY, "checkstyle:MagicNumber"); - patternsInitializer.initPatterns(); - - assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue(); - assertThat(patternsInitializer.hasFileContentPattern()).isFalse(); - assertThat(patternsInitializer.hasMulticriteriaPatterns()).isTrue(); - assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(2); - assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(0); - assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(0); - - patternsInitializer.initializePatternsForPath("org/foo/Bar.java", "org.foo.Bar"); - patternsInitializer.initializePatternsForPath("org/foo/Baz.java", "org.foo.Baz"); - patternsInitializer.initializePatternsForPath("org/foo/Hello.java", "org.foo.Hello"); - - assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Bar")).hasSize(1); - assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Baz")).hasSize(0); - assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Hello")).hasSize(1); - - } - - @Test(expected = SonarException.class) - public void shouldLogInvalidResourceKey() { - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IgnoreIssuesConfiguration.RESOURCE_KEY, ""); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IgnoreIssuesConfiguration.RULE_KEY, "*"); - patternsInitializer.initPatterns(); - } - - @Test(expected = SonarException.class) - public void shouldLogInvalidRuleKey() { - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IgnoreIssuesConfiguration.RESOURCE_KEY, "*"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IgnoreIssuesConfiguration.RULE_KEY, ""); - patternsInitializer.initPatterns(); - } - - @Test - public void shouldReturnBlockPattern() { - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY, "1,2,3"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + ".1." + IgnoreIssuesConfiguration.BEGIN_BLOCK_REGEXP, "// SONAR-OFF"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + ".1." + IgnoreIssuesConfiguration.END_BLOCK_REGEXP, "// SONAR-ON"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + ".2." + IgnoreIssuesConfiguration.BEGIN_BLOCK_REGEXP, "// FOO-OFF"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + ".2." + IgnoreIssuesConfiguration.END_BLOCK_REGEXP, "// FOO-ON"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + ".3." + IgnoreIssuesConfiguration.BEGIN_BLOCK_REGEXP, "// IGNORE-TO-EOF"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + ".3." + IgnoreIssuesConfiguration.END_BLOCK_REGEXP, ""); - patternsInitializer.loadFileContentPatterns(); - - assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue(); - assertThat(patternsInitializer.hasFileContentPattern()).isTrue(); - assertThat(patternsInitializer.hasMulticriteriaPatterns()).isFalse(); - assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0); - assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(3); - assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(0); - } - - @Test(expected = SonarException.class) - public void shouldLogInvalidStartBlockPattern() { - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY, "1"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + ".1." + IgnoreIssuesConfiguration.BEGIN_BLOCK_REGEXP, ""); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_BLOCK_KEY + ".1." + IgnoreIssuesConfiguration.END_BLOCK_REGEXP, "// SONAR-ON"); - patternsInitializer.loadFileContentPatterns(); - } - - @Test - public void shouldReturnAllFilePattern() { - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_ALLFILE_KEY, "1,2"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_ALLFILE_KEY + ".1." + IgnoreIssuesConfiguration.FILE_REGEXP, "@SONAR-IGNORE-ALL"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_ALLFILE_KEY + ".2." + IgnoreIssuesConfiguration.FILE_REGEXP, "//FOO-IGNORE-ALL"); - patternsInitializer.loadFileContentPatterns(); - - assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue(); - assertThat(patternsInitializer.hasFileContentPattern()).isTrue(); - assertThat(patternsInitializer.hasMulticriteriaPatterns()).isFalse(); - assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0); - assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(0); - assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(2); - } - - @Test(expected = SonarException.class) - public void shouldLogInvalidAllFilePattern() { - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_ALLFILE_KEY, "1"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_ALLFILE_KEY + ".1." + IgnoreIssuesConfiguration.FILE_REGEXP, ""); - patternsInitializer.loadFileContentPatterns(); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/InclusionPatternInitializerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/InclusionPatternInitializerTest.java deleted file mode 100644 index d277a2b30a3..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/InclusionPatternInitializerTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import org.junit.Before; -import org.junit.Test; -import org.sonar.api.config.PropertyDefinitions; -import org.sonar.api.config.Settings; -import org.sonar.plugins.core.issue.ignore.IgnoreIssuesConfiguration; - -import static org.fest.assertions.Assertions.assertThat; - -public class InclusionPatternInitializerTest { - - private InclusionPatternInitializer patternsInitializer; - - private Settings settings; - - @Before - public void init() { - settings = new Settings(new PropertyDefinitions(IgnoreIssuesConfiguration.getPropertyDefinitions())); - patternsInitializer = new InclusionPatternInitializer(settings); - } - - @Test - public void testNoConfiguration() { - patternsInitializer.initPatterns(); - assertThat(patternsInitializer.hasConfiguredPatterns()).isFalse(); - } - - @Test - public void shouldHavePatternsBasedOnMulticriteriaPattern() { - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY, "1,2"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".1." + IgnoreIssuesConfiguration.RESOURCE_KEY, "org/foo/Bar.java"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".1." + IgnoreIssuesConfiguration.RULE_KEY, "*"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".2." + IgnoreIssuesConfiguration.RESOURCE_KEY, "org/foo/Hello.java"); - settings.setProperty(IgnoreIssuesConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".2." + IgnoreIssuesConfiguration.RULE_KEY, "checkstyle:MagicNumber"); - patternsInitializer.initPatterns(); - - assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue(); - assertThat(patternsInitializer.hasMulticriteriaPatterns()).isTrue(); - assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(2); - - patternsInitializer.initializePatternsForPath("org/foo/Bar.java", "org.foo.Bar"); - patternsInitializer.initializePatternsForPath("org/foo/Baz.java", "org.foo.Baz"); - patternsInitializer.initializePatternsForPath("org/foo/Hello.java", "org.foo.Hello"); - - assertThat(patternsInitializer.getPathForComponent("org.foo.Bar")).isEqualTo("org/foo/Bar.java"); - assertThat(patternsInitializer.getPathForComponent("org.foo.Baz")).isEqualTo("org/foo/Baz.java"); - assertThat(patternsInitializer.getPathForComponent("org.foo.Hello")).isEqualTo("org/foo/Hello.java"); - } - -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePatternTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePatternTest.java deleted file mode 100644 index 9a069bbb2a1..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/IssuePatternTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -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.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class IssuePatternTest { - - @Test - public void shouldMatchLines() { - IssuePattern pattern = new IssuePattern("*", "*"); - pattern.addLine(12).addLine(15).addLineRange(20, 25); - - assertThat(pattern.matchLine(3)).isFalse(); - assertThat(pattern.matchLine(12)).isTrue(); - assertThat(pattern.matchLine(14)).isFalse(); - assertThat(pattern.matchLine(21)).isTrue(); - assertThat(pattern.matchLine(6599)).isFalse(); - } - - @Test - public void shouldMatchJavaFile() { - String javaFile = "org.foo.Bar"; - assertThat(new IssuePattern("org.foo.Bar", "*").matchResource(javaFile)).isTrue(); - assertThat(new IssuePattern("org.foo.*", "*").matchResource(javaFile)).isTrue(); - assertThat(new IssuePattern("*Bar", "*").matchResource(javaFile)).isTrue(); - assertThat(new IssuePattern("*", "*").matchResource(javaFile)).isTrue(); - assertThat(new IssuePattern("org.*.?ar", "*").matchResource(javaFile)).isTrue(); - - assertThat(new IssuePattern("org.other.Hello", "*").matchResource(javaFile)).isFalse(); - assertThat(new IssuePattern("org.foo.Hello", "*").matchResource(javaFile)).isFalse(); - assertThat(new IssuePattern("org.*.??ar", "*").matchResource(javaFile)).isFalse(); - assertThat(new IssuePattern("org.*.??ar", "*").matchResource(null)).isFalse(); - assertThat(new IssuePattern("org.*.??ar", "*").matchResource("plop")).isFalse(); - } - - @Test - public void shouldMatchRule() { - RuleKey rule = Rule.create("checkstyle", "IllegalRegexp", "").ruleKey(); - assertThat(new IssuePattern("*", "*").matchRule(rule)).isTrue(); - assertThat(new IssuePattern("*", "checkstyle:*").matchRule(rule)).isTrue(); - assertThat(new IssuePattern("*", "checkstyle:IllegalRegexp").matchRule(rule)).isTrue(); - assertThat(new IssuePattern("*", "checkstyle:Illegal*").matchRule(rule)).isTrue(); - assertThat(new IssuePattern("*", "*:*Illegal*").matchRule(rule)).isTrue(); - - assertThat(new IssuePattern("*", "pmd:IllegalRegexp").matchRule(rule)).isFalse(); - assertThat(new IssuePattern("*", "pmd:*").matchRule(rule)).isFalse(); - assertThat(new IssuePattern("*", "*:Foo*IllegalRegexp").matchRule(rule)).isFalse(); - } - - @Test - public void shouldMatchViolation() { - Rule rule = Rule.create("checkstyle", "IllegalRegexp", ""); - String javaFile = "org.foo.Bar"; - - IssuePattern pattern = new IssuePattern("*", "*"); - pattern.addLine(12); - - assertThat(pattern.match(create(rule, javaFile, null))).isFalse(); - assertThat(pattern.match(create(rule, javaFile, 12))).isTrue(); - assertThat(pattern.match(create((Rule) null, javaFile, 5))).isFalse(); - assertThat(pattern.match(create(rule, null, null))).isFalse(); - assertThat(pattern.match(create((Rule) null, null, null))).isFalse(); - } - - private Issue create(Rule rule, String component, Integer line) { - Issue mockIssue = mock(Issue.class); - RuleKey ruleKey = null; - if (rule != null) { - ruleKey = rule.ruleKey(); - } - when(mockIssue.ruleKey()).thenReturn(ruleKey); - when(mockIssue.componentKey()).thenReturn(component); - when(mockIssue.line()).thenReturn(line); - return mockIssue; - } - - @Test - public void shouldNotMatchNullRule() { - assertThat(new IssuePattern("*", "*").matchRule(null)).isFalse(); - } - - @Test - public void shouldPrintPatternToString() { - IssuePattern pattern = new IssuePattern("*", "checkstyle:*"); - - assertThat(pattern.toString()).isEqualTo("IssuePattern[resourcePattern=*,rulePattern=checkstyle:*,lines=[],lineRanges=[],beginBlockRegexp=,endBlockRegexp=,allFileRegexp=,checkLines=true]"); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/LineRangeTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/LineRangeTest.java deleted file mode 100644 index 3c4c02aedf4..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/LineRangeTest.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import org.junit.Test; - -import static org.fest.assertions.Assertions.assertThat; - -public class LineRangeTest { - - @Test(expected = IllegalArgumentException.class) - public void lineRangeShouldBeOrdered() { - new LineRange(25, 12); - } - - @Test - public void shouldConvertLineRangeToLines() { - LineRange range = new LineRange(12, 15); - - assertThat(range.toLines()).containsOnly(12, 13, 14, 15); - } - - @Test - public void shouldTestInclusionInRangeOfLines() { - LineRange range = new LineRange(12, 15); - - assertThat(range.in(3)).isFalse(); - assertThat(range.in(12)).isTrue(); - assertThat(range.in(13)).isTrue(); - assertThat(range.in(14)).isTrue(); - assertThat(range.in(15)).isTrue(); - assertThat(range.in(16)).isFalse(); - } - - @Test - public void testToString() throws Exception { - assertThat(new LineRange(12, 15).toString()).isEqualTo("[12-15]"); - } - - @Test - public void testEquals() throws Exception { - LineRange range = new LineRange(12, 15); - assertThat(range).isEqualTo(range); - assertThat(range).isEqualTo(new LineRange(12, 15)); - assertThat(range).isNotEqualTo(new LineRange(12, 2000)); - assertThat(range).isNotEqualTo(new LineRange(1000, 2000)); - assertThat(range).isNotEqualTo(null); - assertThat(range).isNotEqualTo(new StringBuffer()); - } - - @Test - public void testHashCode() throws Exception { - assertThat(new LineRange(12, 15).hashCode()).isEqualTo(new LineRange(12, 15).hashCode()); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternDecoderTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternDecoderTest.java deleted file mode 100644 index 18e9e58436c..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternDecoderTest.java +++ /dev/null @@ -1,188 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.sonar.api.utils.SonarException; - -import java.util.List; - -import static org.fest.assertions.Assertions.assertThat; - -public class PatternDecoderTest { - - private PatternDecoder decoder = new PatternDecoder(); - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void shouldReadString() { - String patternsList = "# a comment followed by a blank line\n\n" + - "# suppress all violations\n" + - "*;*;*\n\n" + - "# exclude a Java file\n" + - "com.foo.Bar;*;*\n\n" + - "# exclude a Java package\n" + - "com.foo.*;*;*\n\n" + - "# exclude a specific rule\n" + - "*;checkstyle:IllegalRegexp;*\n\n" + - "# exclude a specific rule on a specific file\n" + - "com.foo.Bar;checkstyle:IllegalRegexp;*\n"; - List patterns = decoder.decode(patternsList); - - assertThat(patterns).hasSize(5); - } - - @Test - public void shouldCheckFormatOfResource() { - assertThat(PatternDecoder.isResource("")).isFalse(); - assertThat(PatternDecoder.isResource("*")).isTrue(); - assertThat(PatternDecoder.isResource("com.foo.*")).isTrue(); - } - - @Test - public void shouldCheckFormatOfRule() { - assertThat(PatternDecoder.isRule("")).isFalse(); - assertThat(PatternDecoder.isRule("*")).isTrue(); - assertThat(PatternDecoder.isRule("com.foo.*")).isTrue(); - } - - @Test - public void shouldCheckFormatOfLinesRange() { - assertThat(PatternDecoder.isLinesRange("")).isFalse(); - assertThat(PatternDecoder.isLinesRange(" ")).isFalse(); - assertThat(PatternDecoder.isLinesRange("12")).isFalse(); - assertThat(PatternDecoder.isLinesRange("12,212")).isFalse(); - - assertThat(PatternDecoder.isLinesRange("*")).isTrue(); - assertThat(PatternDecoder.isLinesRange("[]")).isTrue(); - assertThat(PatternDecoder.isLinesRange("[13]")).isTrue(); - assertThat(PatternDecoder.isLinesRange("[13,24]")).isTrue(); - assertThat(PatternDecoder.isLinesRange("[13,24,25-500]")).isTrue(); - assertThat(PatternDecoder.isLinesRange("[24-65]")).isTrue(); - assertThat(PatternDecoder.isLinesRange("[13,24-65,84-89,122]")).isTrue(); - } - - @Test - public void shouldReadStarPatterns() { - IssuePattern pattern = decoder.decodeLine("*;*;*"); - - assertThat(pattern.getResourcePattern().toString()).isEqualTo("*"); - assertThat(pattern.getRulePattern().toString()).isEqualTo("*"); - assertThat(pattern.isCheckLines()).isFalse(); - } - - @Test - public void shouldReadLineIds() { - IssuePattern pattern = decoder.decodeLine("*;*;[10,25,98]"); - - assertThat(pattern.isCheckLines()).isTrue(); - assertThat(pattern.getAllLines()).containsOnly(10, 25, 98); - } - - @Test - public void shouldReadRangeOfLineIds() { - IssuePattern pattern = decoder.decodeLine("*;*;[10-12,25,97-100]"); - - assertThat(pattern.isCheckLines()).isTrue(); - assertThat(pattern.getAllLines()).containsOnly(10, 11, 12, 25, 97, 98, 99, 100); - } - - @Test - public void shouldNotExcludeLines() { - // [] is different than * - // - all violations are excluded on * - // * no violations are excluded on [] - IssuePattern pattern = decoder.decodeLine("*;*;[]"); - - assertThat(pattern.isCheckLines()).isTrue(); - assertThat(pattern.getAllLines()).isEmpty(); - } - - @Test - public void shouldReadBlockPattern() { - IssuePattern pattern = decoder.decodeLine("SONAR-OFF;SONAR-ON"); - - assertThat(pattern.getResourcePattern()).isNull(); - assertThat(pattern.getBeginBlockRegexp()).isEqualTo("SONAR-OFF"); - assertThat(pattern.getEndBlockRegexp()).isEqualTo("SONAR-ON"); - } - - @Test - public void shouldReadAllFilePattern() { - IssuePattern pattern = decoder.decodeLine("SONAR-ALL-OFF"); - - assertThat(pattern.getResourcePattern()).isNull(); - assertThat(pattern.getAllFileRegexp()).isEqualTo("SONAR-ALL-OFF"); - } - - @Test - public void shouldFailToReadUncorrectLine1() { - thrown.expect(SonarException.class); - thrown.expectMessage("Exclusions > Issues : Invalid format. The following line has more than 3 fields separated by comma"); - - decoder.decode(";;;;"); - } - - @Test - public void shouldFailToReadUncorrectLine3() { - thrown.expect(SonarException.class); - thrown.expectMessage("Exclusions > Issues : Invalid format. The first field does not define a resource pattern"); - - decoder.decode(";*;*"); - } - - @Test - public void shouldFailToReadUncorrectLine4() { - thrown.expect(SonarException.class); - thrown.expectMessage("Exclusions > Issues : Invalid format. The second field does not define a rule pattern"); - - decoder.decode("*;;*"); - } - - @Test - public void shouldFailToReadUncorrectLine5() { - thrown.expect(SonarException.class); - thrown.expectMessage("Exclusions > Issues : Invalid format. The third field does not define a range of lines"); - - decoder.decode("*;*;blabla"); - } - - @Test - public void shouldFailToReadUncorrectLine6() { - thrown.expect(SonarException.class); - thrown.expectMessage("Exclusions > Issues : Invalid format. The first field does not define a regular expression"); - - decoder.decode(";ON"); - } - - @Test - public void shouldAcceptEmptyEndBlockRegexp() { - IssuePattern pattern = decoder.decodeLine("OFF;"); - - assertThat(pattern.getResourcePattern()).isNull(); - assertThat(pattern.getBeginBlockRegexp()).isEqualTo("OFF"); - assertThat(pattern.getEndBlockRegexp()).isEmpty(); - } -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcherTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcherTest.java deleted file mode 100644 index af7f97e9f0e..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/pattern/PatternMatcherTest.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.pattern; - -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; - -import java.io.IOException; -import java.util.Set; - -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; - -public class PatternMatcherTest { - - public static final Rule CHECKSTYLE_RULE = Rule.create("checkstyle", "MagicNumber", ""); - public static final String JAVA_FILE = "org.foo.Hello"; - - private PatternMatcher patternMatcher; - - @Before - public void setUp() { - patternMatcher = new PatternMatcher(); - } - - @Test - public void shouldReturnExtraPatternForResource() { - String file = "foo"; - patternMatcher.addPatternToExcludeResource(file); - - IssuePattern extraPattern = patternMatcher.getPatternsForComponent(file).iterator().next(); - assertThat(extraPattern.matchResource(file)).isTrue(); - assertThat(extraPattern.isCheckLines()).isFalse(); - } - - @Test - public void shouldReturnExtraPatternForLinesOfResource() { - String file = "foo"; - Set lineRanges = Sets.newHashSet(); - lineRanges.add(new LineRange(25, 28)); - patternMatcher.addPatternToExcludeLines(file, lineRanges); - - IssuePattern extraPattern = patternMatcher.getPatternsForComponent(file).iterator().next(); - assertThat(extraPattern.matchResource(file)).isTrue(); - assertThat(extraPattern.getAllLines()).isEqualTo(Sets.newHashSet(25, 26, 27, 28)); - } - - @Test - public void shouldHaveNoMatcherIfNoneDefined() { - assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, null))).isNull(); - } - - @Test - public void shouldMatchWithStandardPatterns() throws IOException { - patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;checkstyle:MagicNumber;[15-200]")); - - assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isNotNull(); - } - - @Test - public void shouldNotMatchWithStandardPatterns() throws IOException { - patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;checkstyle:MagicNumber;[15-200]")); - - assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull(); - } - - @Test - public void shouldMatchWithExtraPattern() throws IOException { - patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;*;[15-200]")); - - assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isNotNull(); - } - - @Test - public void shouldNotMatchWithExtraPattern() throws IOException { - patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;*;[15-200]")); - - assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull(); - } - - private Issue create(Rule rule, String component, Integer line) { - Issue mockIssue = mock(Issue.class); - RuleKey ruleKey = null; - if (rule != null) { - ruleKey = rule.ruleKey(); - } - when(mockIssue.ruleKey()).thenReturn(ruleKey); - when(mockIssue.componentKey()).thenReturn(component); - when(mockIssue.line()).thenReturn(line); - return mockIssue; - } - - private IssuePattern createPattern(String line) { - return new PatternDecoder().decode(line).get(0); - } - -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest.java deleted file mode 100644 index bfbe6c6aee0..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.scanner; - -import com.google.common.collect.Sets; -import org.junit.Before; -import org.junit.Test; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; -import org.sonar.plugins.core.issue.ignore.pattern.ExclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.IssuePattern; -import org.sonar.plugins.core.issue.ignore.pattern.LineRange; -import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; -import org.sonar.test.TestUtils; - -import java.io.IOException; -import java.util.Arrays; -import java.util.Set; - -import static com.google.common.base.Charsets.UTF_8; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyNoMoreInteractions; -import static org.mockito.Mockito.when; - -public class IgnoreIssuesRegexpScannerTest { - - private IgnoreIssuesRegexpScanner regexpScanner; - - private String javaFile; - @Mock - private ExclusionPatternInitializer patternsInitializer; - @Mock - private PatternMatcher patternMatcher; - @Mock - private IssuePattern allFilePattern; - @Mock - private IssuePattern blockPattern1; - @Mock - private IssuePattern blockPattern2; - - @Before - public void init() { - MockitoAnnotations.initMocks(this); - - when(allFilePattern.getAllFileRegexp()).thenReturn("@SONAR-IGNORE-ALL"); - when(blockPattern1.getBeginBlockRegexp()).thenReturn("// SONAR-OFF"); - when(blockPattern1.getEndBlockRegexp()).thenReturn("// SONAR-ON"); - when(blockPattern2.getBeginBlockRegexp()).thenReturn("// FOO-OFF"); - when(blockPattern2.getEndBlockRegexp()).thenReturn("// FOO-ON"); - when(patternsInitializer.getAllFilePatterns()).thenReturn(Arrays.asList(allFilePattern)); - when(patternsInitializer.getBlockPatterns()).thenReturn(Arrays.asList(blockPattern1, blockPattern2)); - when(patternsInitializer.getPatternMatcher()).thenReturn(patternMatcher); - - regexpScanner = new IgnoreIssuesRegexpScanner(patternsInitializer); - verify(patternsInitializer, times(1)).getAllFilePatterns(); - verify(patternsInitializer, times(1)).getBlockPatterns(); - - javaFile = "org.sonar.test.MyFile"; - } - - @Test - public void shouldDoNothing() throws IOException { - regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-no-regexp.txt"), UTF_8); - - verifyNoMoreInteractions(patternsInitializer); - } - - @Test - public void shouldAddPatternToExcludeFile() throws IOException { - regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-single-regexp.txt"), UTF_8); - - verify(patternsInitializer).getPatternMatcher(); - verify(patternMatcher, times(1)).addPatternToExcludeResource(javaFile); - verifyNoMoreInteractions(patternsInitializer); - } - - @Test - public void shouldAddPatternToExcludeFileEvenIfAlsoDoubleRegexps() throws IOException { - regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-single-regexp-and-double-regexp.txt"), UTF_8); - - verify(patternsInitializer).getPatternMatcher(); - verify(patternMatcher, times(1)).addPatternToExcludeResource(javaFile); - verifyNoMoreInteractions(patternsInitializer); - } - - @Test - public void shouldAddPatternToExcludeLines() throws IOException { - regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp.txt"), UTF_8); - - Set lineRanges = Sets.newHashSet(); - lineRanges.add(new LineRange(21, 25)); - verify(patternsInitializer).getPatternMatcher(); - verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); - verifyNoMoreInteractions(patternsInitializer); - } - - @Test - public void shouldAddPatternToExcludeLinesTillTheEnd() throws IOException { - regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-unfinished.txt"), UTF_8); - - Set lineRanges = Sets.newHashSet(); - lineRanges.add(new LineRange(21, 34)); - verify(patternsInitializer).getPatternMatcher(); - verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); - verifyNoMoreInteractions(patternsInitializer); - } - - @Test - public void shouldAddPatternToExcludeSeveralLineRanges() throws IOException { - regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-twice.txt"), UTF_8); - - Set lineRanges = Sets.newHashSet(); - lineRanges.add(new LineRange(21, 25)); - lineRanges.add(new LineRange(29, 33)); - verify(patternsInitializer).getPatternMatcher(); - verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); - verifyNoMoreInteractions(patternsInitializer); - } - - @Test - public void shouldAddPatternToExcludeLinesWithWrongOrder() throws IOException { - regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-wrong-order.txt"), UTF_8); - - Set lineRanges = Sets.newHashSet(); - lineRanges.add(new LineRange(25, 35)); - verify(patternsInitializer).getPatternMatcher(); - verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); - verifyNoMoreInteractions(patternsInitializer); - } - - @Test - public void shouldAddPatternToExcludeLinesWithMess() throws IOException { - regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-mess.txt"), UTF_8); - - Set lineRanges = Sets.newHashSet(); - lineRanges.add(new LineRange(21, 29)); - verify(patternsInitializer).getPatternMatcher(); - verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); - verifyNoMoreInteractions(patternsInitializer); - } - -} diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesSourceScannerTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesSourceScannerTest.java deleted file mode 100644 index 5fc3a27c648..00000000000 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesSourceScannerTest.java +++ /dev/null @@ -1,179 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 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.plugins.core.issue.ignore.scanner; - -import com.google.common.base.Charsets; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; -import org.mockito.Mock; -import org.mockito.Mockito; -import org.mockito.MockitoAnnotations; -import org.sonar.api.resources.Project; -import org.sonar.api.scan.filesystem.FileQuery; -import org.sonar.api.scan.filesystem.internal.DefaultInputFile; -import org.sonar.api.scan.filesystem.internal.InputFileBuilder; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; -import org.sonar.plugins.core.issue.ignore.pattern.ExclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.InclusionPatternInitializer; -import org.sonar.plugins.core.issue.ignore.pattern.PatternMatcher; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; - -import static com.google.common.base.Charsets.UTF_8; -import static org.fest.assertions.Assertions.assertThat; -import static org.mockito.Mockito.doThrow; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.verifyZeroInteractions; -import static org.mockito.Mockito.when; - -public class IgnoreIssuesSourceScannerTest { - - private IgnoreIssuesSourceScanner scanner; - - @Mock - private IgnoreIssuesRegexpScanner regexpScanner; - @Mock - private InclusionPatternInitializer inclusionPatternInitializer; - @Mock - private ExclusionPatternInitializer exclusionPatternInitializer; - @Mock - private PatternMatcher patternMatcher; - @Mock - private DefaultModuleFileSystem fs; - - private Project project; - - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - private File baseDir; - - @Before - public void init() throws IOException { - baseDir = temp.newFolder(); - MockitoAnnotations.initMocks(this); - - Project realProject = new Project("polop"); - project = Mockito.spy(realProject); - Mockito.doReturn("java").when(project).getLanguageKey(); - when(fs.sourceCharset()).thenReturn(UTF_8); - - scanner = new IgnoreIssuesSourceScanner(regexpScanner, exclusionPatternInitializer, inclusionPatternInitializer, fs); - } - - @Test - public void testToString() throws Exception { - assertThat(scanner.toString()).isEqualTo("Issues Exclusions - Source Scanner"); - } - - @Test - public void shouldExecute() throws IOException { - when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true); - when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true); - assertThat(scanner.shouldExecuteOnProject(null)).isTrue(); - - when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true); - when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false); - assertThat(scanner.shouldExecuteOnProject(null)).isTrue(); - - when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false); - when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true); - assertThat(scanner.shouldExecuteOnProject(null)).isTrue(); - - when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false); - when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false); - assertThat(scanner.shouldExecuteOnProject(null)).isFalse(); - - } - - @Test - public void shouldAnalyseProject() throws IOException { - File javaFile1 = new File(baseDir, "src/main/java/Foo.java"); - File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java"); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - new InputFileBuilder(javaFile1, Charsets.UTF_8, "src/main/java/Foo.java") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/main/java/Foo.java") - .build(), - new InputFileBuilder(javaTestFile1, Charsets.UTF_8, "src/test/java/FooTest.java") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/test/java/FooTest.java") - .build())); - - when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); - - scanner.analyse(project, null); - - verify(inclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java"); - verify(inclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java"); - verify(exclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java"); - verify(exclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java"); - verify(regexpScanner).scan("polop:src/main/java/Foo.java", javaFile1, UTF_8); - verify(regexpScanner).scan("polop:src/test/java/FooTest.java", javaTestFile1, UTF_8); - } - - @Test - public void shouldAnalyseFilesOnlyWhenRegexConfigured() throws IOException { - File javaFile1 = new File(baseDir, "src/main/java/Foo.java"); - File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java"); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - new InputFileBuilder(javaFile1, Charsets.UTF_8, "src/main/java/Foo.java") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/main/java/Foo.java") - .build(), - new InputFileBuilder(javaTestFile1, Charsets.UTF_8, "src/test/java/FooTest.java") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/test/java/FooTest.java") - .build())); - - when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(false); - - scanner.analyse(project, null); - - verify(inclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java"); - verify(inclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java"); - verify(exclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java"); - verify(exclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java"); - verifyZeroInteractions(regexpScanner); - } - - @Test - public void shouldReportFailure() throws IOException { - File phpFile1 = new File(baseDir, "src/Foo.php"); - when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( - new InputFileBuilder(phpFile1, Charsets.UTF_8, "src/Foo.php") - .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/Foo.php") - .build())); - - when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); - doThrow(new IOException("BUG")).when(regexpScanner).scan("polop:src/Foo.php", phpFile1, UTF_8); - - thrown.expect(SonarException.class); - thrown.expectMessage("Unable to read the source file"); - - scanner.analyse(project, null); - } -} diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-mess.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-mess.txt deleted file mode 100644 index 48d30c92f97..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-mess.txt +++ /dev/null @@ -1,37 +0,0 @@ -package org.sonar.plugins.switchoffviolations.pattern; - -import com.google.common.collect.Sets; - -import java.util.Set; - -/** - * - */ -public class LineRange { - int from, to; - - public LineRange(int from, int to) { - if (to < from) { - throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); - } - this.from = from; - this.to = to; - } - - // SONAR-OFF - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - // FOO-OFF - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - // SONAR-ON - for (int index = from; index <= to; index++) { - lines.add(index); - } - // FOO-ON - return lines; - } - -} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-twice.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-twice.txt deleted file mode 100644 index 9ae63dc57f9..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-twice.txt +++ /dev/null @@ -1,37 +0,0 @@ -package org.sonar.plugins.switchoffviolations.pattern; - -import com.google.common.collect.Sets; - -import java.util.Set; - -/** - * - */ -public class LineRange { - int from, to; - - public LineRange(int from, int to) { - if (to < from) { - throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); - } - this.from = from; - this.to = to; - } - - // SONAR-OFF - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - // SONAR-ON - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - // FOO-OFF - for (int index = from; index <= to; index++) { - lines.add(index); - } - // FOO-ON - return lines; - } - -} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-unfinished.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-unfinished.txt deleted file mode 100644 index dd7656180ab..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-unfinished.txt +++ /dev/null @@ -1,34 +0,0 @@ -package org.sonar.plugins.switchoffviolations.pattern; - -import com.google.common.collect.Sets; - -import java.util.Set; - -/** - * - */ -public class LineRange { - int from, to; - - public LineRange(int from, int to) { - if (to < from) { - throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); - } - this.from = from; - this.to = to; - } - - // SONAR-OFF - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - for (int index = from; index <= to; index++) { - lines.add(index); - } - return lines; - } - -} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-wrong-order.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-wrong-order.txt deleted file mode 100644 index 7cac0b98aed..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp-wrong-order.txt +++ /dev/null @@ -1,35 +0,0 @@ -package org.sonar.plugins.switchoffviolations.pattern; - -import com.google.common.collect.Sets; - -import java.util.Set; - -/** - * - */ -public class LineRange { - int from, to; - - public LineRange(int from, int to) { - if (to < from) { - throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); - } - this.from = from; - this.to = to; - } - - // SONAR-ON - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - // SONAR-OFF - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - for (int index = from; index <= to; index++) { - lines.add(index); - } - return lines; - } - -} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp.txt deleted file mode 100644 index 002169fe031..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-double-regexp.txt +++ /dev/null @@ -1,35 +0,0 @@ -package org.sonar.plugins.switchoffviolations.pattern; - -import com.google.common.collect.Sets; - -import java.util.Set; - -/** - * - */ -public class LineRange { - int from, to; - - public LineRange(int from, int to) { - if (to < from) { - throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); - } - this.from = from; - this.to = to; - } - - // SONAR-OFF - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - // SONAR-ON - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - for (int index = from; index <= to; index++) { - lines.add(index); - } - return lines; - } - -} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-no-regexp.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-no-regexp.txt deleted file mode 100644 index f18fa5b90ad..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-no-regexp.txt +++ /dev/null @@ -1,33 +0,0 @@ -package org.sonar.plugins.switchoffviolations.pattern; - -import com.google.common.collect.Sets; - -import java.util.Set; - -/** - * - */ -public class LineRange { - int from, to; - - public LineRange(int from, int to) { - if (to < from) { - throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); - } - this.from = from; - this.to = to; - } - - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - for (int index = from; index <= to; index++) { - lines.add(index); - } - return lines; - } - -} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-single-regexp-and-double-regexp.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-single-regexp-and-double-regexp.txt deleted file mode 100644 index e09ecd7a323..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-single-regexp-and-double-regexp.txt +++ /dev/null @@ -1,36 +0,0 @@ -package org.sonar.plugins.switchoffviolations.pattern; - -import com.google.common.collect.Sets; - - // SONAR-OFF - -import java.util.Set; - -/** - * @SONAR-IGNORE-ALL - */ -public class LineRange { - int from, to; - - public LineRange(int from, int to) { - if (to < from) { - throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); - } - this.from = from; - this.to = to; - } - - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - // SONAR-ON - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - for (int index = from; index <= to; index++) { - lines.add(index); - } - return lines; - } - -} \ No newline at end of file diff --git a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-single-regexp.txt b/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-single-regexp.txt deleted file mode 100644 index ef135ebc50c..00000000000 --- a/plugins/sonar-core-plugin/src/test/resources/org/sonar/plugins/core/issue/ignore/scanner/IgnoreIssuesRegexpScannerTest/file-with-single-regexp.txt +++ /dev/null @@ -1,33 +0,0 @@ -package org.sonar.plugins.switchoffviolations.pattern; - -import com.google.common.collect.Sets; - -import java.util.Set; - -/** - * @SONAR-IGNORE-ALL - */ -public class LineRange { - int from, to; - - public LineRange(int from, int to) { - if (to < from) { - throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); - } - this.from = from; - this.to = to; - } - - public boolean in(int lineId) { - return from <= lineId && lineId <= to; - } - - public Set toLines() { - Set lines = Sets.newLinkedHashSet(); - for (int index = from; index <= to; index++) { - lines.add(index); - } - return lines; - } - -} \ No newline at end of file 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 new file mode 100644 index 00000000000..7245d904823 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/EnforceIssuesFilter.java @@ -0,0 +1,67 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore; + +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; + +public class EnforceIssuesFilter implements IssueFilter { + + private IssueInclusionPatternInitializer patternInitializer; + + private static final Logger LOG = LoggerFactory.getLogger(EnforceIssuesFilter.class); + + public EnforceIssuesFilter(IssueInclusionPatternInitializer patternInitializer) { + this.patternInitializer = patternInitializer; + } + + @Override + public boolean accept(Issue issue, IssueFilterChain chain) { + boolean atLeastOneRuleMatched = false; + boolean atLeastOnePatternFullyMatched = false; + IssuePattern matchingPattern = null; + + for (IssuePattern pattern : patternInitializer.getMulticriteriaPatterns()) { + if (pattern.getRulePattern().match(issue.ruleKey().toString())) { + atLeastOneRuleMatched = true; + String pathForComponent = patternInitializer.getPathForComponent(issue.componentKey()); + if (pathForComponent != null && pattern.getResourcePattern().match(pathForComponent)) { + atLeastOnePatternFullyMatched = true; + matchingPattern = pattern; + } + } + } + + if (atLeastOneRuleMatched) { + if (atLeastOnePatternFullyMatched) { + LOG.debug("Issue {} enforced by pattern {}", issue, matchingPattern); + } + return atLeastOnePatternFullyMatched; + } else { + return chain.accept(issue); + } + } +} 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 new file mode 100644 index 00000000000..d880bf6f8ca --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilter.java @@ -0,0 +1,63 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore; + +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; + +public class IgnoreIssuesFilter implements IssueFilter { + + private PatternMatcher patternMatcher; + + private static final Logger LOG = LoggerFactory.getLogger(IgnoreIssuesFilter.class); + + public IgnoreIssuesFilter(IssueExclusionPatternInitializer patternInitializer) { + this.patternMatcher = patternInitializer.getPatternMatcher(); + } + + @Override + public boolean accept(Issue issue, IssueFilterChain chain) { + if (hasMatchFor(issue)) { + return false; + } else { + return chain.accept(issue); + } + } + + private boolean hasMatchFor(Issue issue) { + IssuePattern pattern = patternMatcher.getMatchingPattern(issue); + if (pattern != null) { + logExclusion(issue, pattern); + return true; + } + return false; + } + + private void logExclusion(Issue 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/IssueExclusionsConfiguration.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/IssueExclusionsConfiguration.java new file mode 100644 index 00000000000..441f08d468c --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/IssueExclusionsConfiguration.java @@ -0,0 +1,144 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore; + +import com.google.common.collect.ImmutableList; +import org.sonar.api.CoreProperties; +import org.sonar.api.PropertyType; +import org.sonar.api.config.PropertyDefinition; +import org.sonar.api.config.PropertyFieldDefinition; +import org.sonar.api.resources.Qualifiers; + +import java.util.List; + +public final class IssueExclusionsConfiguration { + + public static final String SUB_CATEGORY_IGNORE_ISSUES = "issues"; + + public static final String EXCLUSION_KEY_PREFIX = "sonar.issue.ignore"; + public static final String INCLUSION_KEY_PREFIX = "sonar.issue.enforce"; + + public static final String MULTICRITERIA_SUFFIX = ".multicriteria"; + public static final String PATTERNS_MULTICRITERIA_EXCLUSION_KEY = EXCLUSION_KEY_PREFIX + MULTICRITERIA_SUFFIX; + public static final String PATTERNS_MULTICRITERIA_INCLUSION_KEY = INCLUSION_KEY_PREFIX + MULTICRITERIA_SUFFIX; + public static final String RESOURCE_KEY = "resourceKey"; + private static final String PROPERTY_FILE_PATH_PATTERN = "File Path Pattern"; + public static final String RULE_KEY = "ruleKey"; + private static final String PROPERTY_RULE_KEY_PATTERN = "Rule Key Pattern"; + + public static final String BLOCK_SUFFIX = ".block"; + public static final String PATTERNS_BLOCK_KEY = EXCLUSION_KEY_PREFIX + BLOCK_SUFFIX; + public static final String BEGIN_BLOCK_REGEXP = "beginBlockRegexp"; + public static final String END_BLOCK_REGEXP = "endBlockRegexp"; + + public static final String ALLFILE_SUFFIX = ".allfile"; + public static final String PATTERNS_ALLFILE_KEY = EXCLUSION_KEY_PREFIX + ALLFILE_SUFFIX; + public static final String FILE_REGEXP = "fileRegexp"; + + static final int LARGE_SIZE = 40; + static final int SMALL_SIZE = 10; + + private IssueExclusionsConfiguration() { + // static configuration declaration only + } + + public static List getPropertyDefinitions() { + return ImmutableList.of( + PropertyDefinition.builder(PATTERNS_MULTICRITERIA_EXCLUSION_KEY) + .category(CoreProperties.CATEGORY_EXCLUSIONS) + .subCategory(SUB_CATEGORY_IGNORE_ISSUES) + .name("Ignore Issues on Multiple Criteria") + .description("Patterns to ignore issues on certain components and for certain coding rules.") + .onQualifiers(Qualifiers.PROJECT) + .index(3) + .fields( + PropertyFieldDefinition.build(RULE_KEY) + .name(PROPERTY_RULE_KEY_PATTERN) + .description("Pattern to match rules which should be ignored.") + .type(PropertyType.STRING) + .indicativeSize(LARGE_SIZE) + .build(), + PropertyFieldDefinition.build(RESOURCE_KEY) + .name(PROPERTY_FILE_PATH_PATTERN) + .description("Pattern to match files which should be ignored.") + .type(PropertyType.STRING) + .indicativeSize(LARGE_SIZE) + .build()) + .build(), + PropertyDefinition.builder(PATTERNS_BLOCK_KEY) + .category(CoreProperties.CATEGORY_EXCLUSIONS) + .subCategory(SUB_CATEGORY_IGNORE_ISSUES) + .name("Ignore Issues in Blocks") + .description("Patterns to ignore all issues on specific blocks of code, while continuing to scan and mark issues on the remainder of the file.") + .onQualifiers(Qualifiers.PROJECT) + .index(2) + .fields( + PropertyFieldDefinition.build(BEGIN_BLOCK_REGEXP) + .name("Regular Expression for Start of Block") + .description("If this regular expression is found in a file, then following lines are ignored until end of block.") + .type(PropertyType.STRING) + .indicativeSize(LARGE_SIZE) + .build(), + PropertyFieldDefinition.build(END_BLOCK_REGEXP) + .name("Regular Expression for End of Block") + .description("If specified, this regular expression is used to determine the end of code blocks to ignore. If not, then block ends at the end of file.") + .type(PropertyType.STRING) + .indicativeSize(LARGE_SIZE) + .build()) + .build(), + PropertyDefinition.builder(PATTERNS_ALLFILE_KEY) + .category(CoreProperties.CATEGORY_EXCLUSIONS) + .subCategory(SUB_CATEGORY_IGNORE_ISSUES) + .name("Ignore Issues on Files") + .description("Patterns to ignore all issues on files that contain a block of code matching a given regular expression.") + .onQualifiers(Qualifiers.PROJECT) + .index(1) + .fields( + PropertyFieldDefinition.build(FILE_REGEXP) + .name("Regular Expression") + .description("If this regular expression is found in a file, then the whole file is ignored.") + .type(PropertyType.STRING) + .indicativeSize(LARGE_SIZE) + .build()) + .build(), + PropertyDefinition.builder(PATTERNS_MULTICRITERIA_INCLUSION_KEY) + .category(CoreProperties.CATEGORY_EXCLUSIONS) + .subCategory(SUB_CATEGORY_IGNORE_ISSUES) + .name("Restrict Scope of Coding Rules") + .description("Patterns to restrict the application of a rule to only certain components, ignoring all others.") + .onQualifiers(Qualifiers.PROJECT) + .index(4) + .fields( + PropertyFieldDefinition.build(RULE_KEY) + .name(PROPERTY_RULE_KEY_PATTERN) + .description("Pattern used to match rules which should be restricted.") + .type(PropertyType.STRING) + .indicativeSize(LARGE_SIZE) + .build(), + PropertyFieldDefinition.build(RESOURCE_KEY) + .name(PROPERTY_FILE_PATH_PATTERN) + .description("Pattern used to match files to which the rules should be restricted.") + .type(PropertyType.STRING) + .indicativeSize(LARGE_SIZE) + .build()) + .build()); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/package-info.java new file mode 100644 index 00000000000..c25ccd37c3e --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.batch.issue.ignore; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/AbstractPatternInitializer.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/AbstractPatternInitializer.java new file mode 100644 index 00000000000..10d5e5513d7 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/AbstractPatternInitializer.java @@ -0,0 +1,82 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.BatchExtension; +import org.sonar.api.config.Settings; + +import java.util.List; + +import static com.google.common.base.Objects.firstNonNull; + +public abstract class AbstractPatternInitializer implements BatchExtension { + + private Settings settings; + + private List multicriteriaPatterns; + + protected AbstractPatternInitializer(Settings settings) { + this.settings = settings; + initPatterns(); + } + + protected Settings getSettings() { + return settings; + } + + public List getMulticriteriaPatterns() { + return multicriteriaPatterns; + } + + public boolean hasConfiguredPatterns() { + return hasMulticriteriaPatterns(); + } + + public boolean hasMulticriteriaPatterns() { + return ! multicriteriaPatterns.isEmpty(); + } + + public abstract void initializePatternsForPath(String relativePath, String componentKey); + + @VisibleForTesting + protected final void initPatterns() { + // Patterns Multicriteria + multicriteriaPatterns = Lists.newArrayList(); + String patternConf = StringUtils.defaultIfBlank(settings.getString(getMulticriteriaConfigurationKey()), ""); + for (String id : StringUtils.split(patternConf, ',')) { + String propPrefix = getMulticriteriaConfigurationKey() + "." + id + "."; + String resourceKeyPattern = settings.getString(propPrefix + IssueExclusionsConfiguration.RESOURCE_KEY); + String ruleKeyPattern = settings.getString(propPrefix + IssueExclusionsConfiguration.RULE_KEY); + String lineRange = "*"; + String[] fields = new String[] { resourceKeyPattern, ruleKeyPattern, lineRange }; + PatternDecoder.checkRegularLineConstraints(StringUtils.join(fields, ","), fields); + IssuePattern pattern = new IssuePattern(firstNonNull(resourceKeyPattern, "*"), firstNonNull(ruleKeyPattern, "*")); + PatternDecoder.decodeRangeOfLines(pattern, firstNonNull(lineRange, "*")); + multicriteriaPatterns.add(pattern); + } + } + + protected abstract String getMulticriteriaConfigurationKey(); +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializer.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializer.java new file mode 100644 index 00000000000..9cddda00fd8 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializer.java @@ -0,0 +1,107 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.config.Settings; + +import java.util.List; + +import static com.google.common.base.Strings.nullToEmpty; + +public class IssueExclusionPatternInitializer extends AbstractPatternInitializer { + + private List blockPatterns; + private List allFilePatterns; + private PatternMatcher patternMatcher; + + public IssueExclusionPatternInitializer(Settings settings) { + super(settings); + patternMatcher = new PatternMatcher(); + loadFileContentPatterns(); + } + + @Override + protected String getMulticriteriaConfigurationKey() { + return IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY; + } + + public PatternMatcher getPatternMatcher() { + return patternMatcher; + } + + @Override + public void initializePatternsForPath(String relativePath, String componentKey) { + for (IssuePattern pattern: getMulticriteriaPatterns()) { + if (pattern.matchResource(relativePath)) { + getPatternMatcher().addPatternForComponent(componentKey, pattern); + } + } + } + + @Override + public boolean hasConfiguredPatterns() { + return hasFileContentPattern() || hasMulticriteriaPatterns(); + } + + @VisibleForTesting + protected final void loadFileContentPatterns() { + // Patterns Block + blockPatterns = Lists.newArrayList(); + String patternConf = StringUtils.defaultIfBlank(getSettings().getString(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY), ""); + for (String id : StringUtils.split(patternConf, ',')) { + String propPrefix = IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + "." + id + "."; + String beginBlockRegexp = getSettings().getString(propPrefix + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP); + String endBlockRegexp = getSettings().getString(propPrefix + IssueExclusionsConfiguration.END_BLOCK_REGEXP); + String[] fields = new String[] { beginBlockRegexp, endBlockRegexp }; + PatternDecoder.checkDoubleRegexpLineConstraints(StringUtils.join(fields, ","), fields); + IssuePattern pattern = new IssuePattern().setBeginBlockRegexp(nullToEmpty(beginBlockRegexp)).setEndBlockRegexp(nullToEmpty(endBlockRegexp)); + blockPatterns.add(pattern); + } + + // Patterns All File + allFilePatterns = Lists.newArrayList(); + patternConf = StringUtils.defaultIfBlank(getSettings().getString(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY), ""); + for (String id : StringUtils.split(patternConf, ',')) { + String propPrefix = IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY + "." + id + "."; + String allFileRegexp = getSettings().getString(propPrefix + IssueExclusionsConfiguration.FILE_REGEXP); + PatternDecoder.checkWholeFileRegexp(allFileRegexp); + IssuePattern pattern = new IssuePattern().setAllFileRegexp(nullToEmpty(allFileRegexp)); + allFilePatterns.add(pattern); + } + } + + public List getBlockPatterns() { + return blockPatterns; + } + + public List getAllFilePatterns() { + return allFilePatterns; + } + + public boolean hasFileContentPattern() { + return ! (blockPatterns.isEmpty() && allFilePatterns.isEmpty()); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializer.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializer.java new file mode 100644 index 00000000000..08f7ccaeba7 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializer.java @@ -0,0 +1,52 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration; + +import com.google.common.collect.Maps; +import org.sonar.api.config.Settings; + +import java.util.Map; + +public class IssueInclusionPatternInitializer extends AbstractPatternInitializer { + + private Map pathForComponent; + + public IssueInclusionPatternInitializer(Settings settings) { + super(settings); + pathForComponent = Maps.newHashMap(); + } + + @Override + protected String getMulticriteriaConfigurationKey() { + return IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY; + } + + @Override + public void initializePatternsForPath(String relativePath, String componentKey) { + pathForComponent.put(componentKey, relativePath); + } + + public String getPathForComponent(String componentKey) { + return pathForComponent.get(componentKey); + } +} 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 new file mode 100644 index 00000000000..294afb629de --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/IssuePattern.java @@ -0,0 +1,167 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +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; + +import java.util.Set; + +public class IssuePattern { + + private WildcardPattern resourcePattern; + private WildcardPattern rulePattern; + private Set lines = Sets.newLinkedHashSet(); + private Set lineRanges = Sets.newLinkedHashSet(); + private String beginBlockRegexp; + private String endBlockRegexp; + private String allFileRegexp; + private boolean checkLines = true; + + public IssuePattern() { + } + + public IssuePattern(String resourcePattern, String rulePattern) { + this.resourcePattern = WildcardPattern.create(resourcePattern); + this.rulePattern = WildcardPattern.create(rulePattern); + } + + public IssuePattern(String resourcePattern, String rulePattern, Set lineRanges) { + this(resourcePattern, rulePattern); + this.lineRanges = lineRanges; + } + + public WildcardPattern getResourcePattern() { + return resourcePattern; + } + + public WildcardPattern getRulePattern() { + return rulePattern; + } + + public String getBeginBlockRegexp() { + return beginBlockRegexp; + } + + public String getEndBlockRegexp() { + return endBlockRegexp; + } + + public String getAllFileRegexp() { + return allFileRegexp; + } + + IssuePattern addLineRange(int fromLineId, int toLineId) { + lineRanges.add(new LineRange(fromLineId, toLineId)); + return this; + } + + IssuePattern addLine(int lineId) { + lines.add(lineId); + return this; + } + + boolean isCheckLines() { + return checkLines; + } + + IssuePattern setCheckLines(boolean b) { + this.checkLines = b; + return this; + } + + IssuePattern setBeginBlockRegexp(String beginBlockRegexp) { + this.beginBlockRegexp = beginBlockRegexp; + return this; + } + + IssuePattern setEndBlockRegexp(String endBlockRegexp) { + this.endBlockRegexp = endBlockRegexp; + return this; + } + + IssuePattern setAllFileRegexp(String allFileRegexp) { + this.allFileRegexp = allFileRegexp; + return this; + } + + Set getAllLines() { + Set allLines = Sets.newLinkedHashSet(lines); + for (LineRange lineRange : lineRanges) { + allLines.addAll(lineRange.toLines()); + } + return allLines; + } + + public boolean match(Issue issue) { + boolean match = matchResource(issue.componentKey()) + && matchRule(issue.ruleKey()); + if (checkLines) { + Integer line = issue.line(); + if (line == null) { + match = false; + } else { + match = match && matchLine(line); + } + } + return match; + } + + boolean matchLine(int lineId) { + if (lines.contains(lineId)) { + return true; + } + + for (LineRange range : lineRanges) { + if (range.in(lineId)) { + return true; + } + } + + return false; + } + + boolean matchRule(RuleKey rule) { + if (rule == null) { + return false; + } + + String key = new StringBuilder().append(rule.repository()).append(':').append(rule.rule()).toString(); + return rulePattern.match(key); + } + + boolean matchResource(String resource) { + return resource != null && resourcePattern.match(resource); + } + + public IssuePattern forResource(String resource) { + return new IssuePattern(resource, rulePattern.toString(), lineRanges).setCheckLines(isCheckLines()); + } + + @Override + public String toString() { + return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE); + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/LineRange.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/LineRange.java new file mode 100644 index 00000000000..89433b8934f --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/LineRange.java @@ -0,0 +1,91 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import com.google.common.base.Preconditions; +import com.google.common.collect.Sets; + +import java.util.Set; + +public class LineRange { + private int from; + private int to; + + public LineRange(int from, int to) { + Preconditions.checkArgument(from <= to, "Line range is not valid: %s must be greater than %s", from, to); + + this.from = from; + this.to = to; + } + + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + for (int index = from; index <= to; index++) { + lines.add(index); + } + return lines; + } + + @Override + public String toString() { + return "[" + from + "-" + to + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + from; + result = prime * result + to; + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null) { + return false; + } + if (getClass() != obj.getClass()) { + return false; + } + if (fieldsDiffer((LineRange) obj)) { + return false; + } + return true; + } + + private boolean fieldsDiffer(LineRange other) { + if (from != other.from) { + return true; + } + if (to != other.to) { + return true; + } + return false; + } +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/PatternDecoder.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/PatternDecoder.java new file mode 100644 index 00000000000..59f02ed891d --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/PatternDecoder.java @@ -0,0 +1,144 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Lists; +import org.apache.commons.lang.StringUtils; +import org.sonar.api.utils.SonarException; + +import java.util.List; + +public class PatternDecoder { + + private static final int THREE_FIELDS_PER_LINE = 3; + private static final String LINE_RANGE_REGEXP = "\\[((\\d+|\\d+-\\d+),?)*\\]"; + private static final String CONFIG_FORMAT_ERROR_PREFIX = "Exclusions > Issues : Invalid format. "; + + public List decode(String patternsList) { + List patterns = Lists.newLinkedList(); + String[] patternsLines = StringUtils.split(patternsList, "\n"); + for (String patternLine : patternsLines) { + IssuePattern pattern = decodeLine(patternLine.trim()); + if (pattern != null) { + patterns.add(pattern); + } + } + return patterns; + } + + /** + * Main method that decodes a line which defines a pattern + */ + public IssuePattern decodeLine(String line) { + if (isBlankOrComment(line)) { + return null; + } + + String[] fields = StringUtils.splitPreserveAllTokens(line, ';'); + if (fields.length > THREE_FIELDS_PER_LINE) { + throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The following line has more than 3 fields separated by comma: " + line); + } + + IssuePattern pattern; + if (fields.length == THREE_FIELDS_PER_LINE) { + checkRegularLineConstraints(line, fields); + pattern = new IssuePattern(StringUtils.trim(fields[0]), StringUtils.trim(fields[1])); + decodeRangeOfLines(pattern, fields[2]); + } else if (fields.length == 2) { + checkDoubleRegexpLineConstraints(line, fields); + pattern = new IssuePattern().setBeginBlockRegexp(fields[0]).setEndBlockRegexp(fields[1]); + } else { + checkWholeFileRegexp(fields[0]); + pattern = new IssuePattern().setAllFileRegexp(fields[0]); + } + + return pattern; + } + + static void checkRegularLineConstraints(String line, String[] fields) { + if (!isResource(fields[0])) { + throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The first field does not define a resource pattern: " + line); + } + if (!isRule(fields[1])) { + throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The second field does not define a rule pattern: " + line); + } + if (!isLinesRange(fields[2])) { + throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The third field does not define a range of lines: " + line); + } + } + + static void checkDoubleRegexpLineConstraints(String line, String[] fields) { + if (!isRegexp(fields[0])) { + throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The first field does not define a regular expression: " + line); + } + // As per configuration help, missing second field means: from start regexp to EOF + } + + static void checkWholeFileRegexp(String regexp) { + if (!isRegexp(regexp)) { + throw new SonarException(CONFIG_FORMAT_ERROR_PREFIX + "The field does not define a regular expression: " + regexp); + } + } + + public static void decodeRangeOfLines(IssuePattern pattern, String field) { + if (StringUtils.equals(field, "*")) { + pattern.setCheckLines(false); + } else { + pattern.setCheckLines(true); + String s = StringUtils.substringBetween(StringUtils.trim(field), "[", "]"); + String[] parts = StringUtils.split(s, ','); + for (String part : parts) { + if (StringUtils.contains(part, '-')) { + String[] range = StringUtils.split(part, '-'); + pattern.addLineRange(Integer.valueOf(range[0]), Integer.valueOf(range[1])); + } else { + pattern.addLine(Integer.valueOf(part)); + } + } + } + } + + @VisibleForTesting + static boolean isLinesRange(String field) { + return StringUtils.equals(field, "*") || java.util.regex.Pattern.matches(LINE_RANGE_REGEXP, field); + } + + @VisibleForTesting + static boolean isBlankOrComment(String line) { + return StringUtils.isBlank(line) ^ StringUtils.startsWith(line, "#"); + } + + @VisibleForTesting + static boolean isResource(String field) { + return StringUtils.isNotBlank(field); + } + + @VisibleForTesting + static boolean isRule(String field) { + return StringUtils.isNotBlank(field); + } + + @VisibleForTesting + static boolean isRegexp(String field) { + return StringUtils.isNotBlank(field); + } +} 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 new file mode 100644 index 00000000000..5de14be060a --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/PatternMatcher.java @@ -0,0 +1,62 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +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; +import java.util.Set; + +public class PatternMatcher { + + private Multimap patternByComponent = LinkedHashMultimap.create(); + + public IssuePattern getMatchingPattern(Issue issue) { + IssuePattern matchingPattern = null; + Iterator patternIterator = getPatternsForComponent(issue.componentKey()).iterator(); + while(matchingPattern == null && patternIterator.hasNext()) { + IssuePattern nextPattern = patternIterator.next(); + if (nextPattern.match(issue)) { + matchingPattern = nextPattern; + } + } + return matchingPattern; + } + + public Collection getPatternsForComponent(String componentKey) { + return patternByComponent.get(componentKey); + } + + public void addPatternForComponent(String component, IssuePattern pattern) { + patternByComponent.put(component, pattern.forResource(component)); + } + + public void addPatternToExcludeResource(String resource) { + addPatternForComponent(resource, new IssuePattern(resource, "*").setCheckLines(false)); + } + + public void addPatternToExcludeLines(String resource, Set lineRanges) { + addPatternForComponent(resource, new IssuePattern(resource, "*", lineRanges).setCheckLines(true)); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/package-info.java new file mode 100644 index 00000000000..d8d49069d04 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/pattern/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.batch.issue.ignore.pattern; + +import javax.annotation.ParametersAreNonnullByDefault; 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 new file mode 100644 index 00000000000..fbe61421f5f --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoader.java @@ -0,0 +1,84 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.scanner; + +import org.sonar.api.resources.Project; +import org.sonar.api.scan.filesystem.FileQuery; +import org.sonar.api.scan.filesystem.InputFile; +import org.sonar.api.scan.filesystem.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.scan.filesystem.DefaultModuleFileSystem; + +import java.nio.charset.Charset; + +public final class IssueExclusionsLoader { + + private final IssueExclusionsRegexpScanner regexpScanner; + private final IssueExclusionPatternInitializer exclusionPatternInitializer; + private final IssueInclusionPatternInitializer inclusionPatternInitializer; + private final DefaultModuleFileSystem fileSystem; + + public IssueExclusionsLoader(IssueExclusionsRegexpScanner regexpScanner, IssueExclusionPatternInitializer exclusionPatternInitializer, + IssueInclusionPatternInitializer inclusionPatternInitializer, + DefaultModuleFileSystem fileSystem) { + this.regexpScanner = regexpScanner; + this.exclusionPatternInitializer = exclusionPatternInitializer; + this.inclusionPatternInitializer = inclusionPatternInitializer; + this.fileSystem = fileSystem; + } + + public boolean shouldExecuteOnProject(Project project) { + return inclusionPatternInitializer.hasConfiguredPatterns() + || exclusionPatternInitializer.hasConfiguredPatterns(); + } + + /** + * {@inheritDoc} + */ + public void execute() { + Charset sourcesEncoding = fileSystem.sourceCharset(); + + for (InputFile inputFile : fileSystem.inputFiles(FileQuery.all())) { + try { + String componentEffectiveKey = inputFile.attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY); + if (componentEffectiveKey != null) { + String path = inputFile.path(); + inclusionPatternInitializer.initializePatternsForPath(path, componentEffectiveKey); + exclusionPatternInitializer.initializePatternsForPath(path, componentEffectiveKey); + if (exclusionPatternInitializer.hasFileContentPattern()) { + regexpScanner.scan(componentEffectiveKey, inputFile.file(), sourcesEncoding); + } + } + } catch (Exception e) { + throw new SonarException("Unable to read the source file : '" + inputFile.absolutePath() + "' with the charset : '" + + sourcesEncoding.name() + "'.", e); + } + } + } + + @Override + public String toString() { + return "Issues Exclusions - Source Scanner"; + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScanner.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScanner.java new file mode 100644 index 00000000000..3ddbbaf57f7 --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScanner.java @@ -0,0 +1,199 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.scanner; + +import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; +import org.sonar.batch.issue.ignore.pattern.IssuePattern; +import org.sonar.batch.issue.ignore.pattern.LineRange; + +import com.google.common.collect.Lists; +import com.google.common.collect.Sets; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang.StringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.sonar.api.BatchExtension; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.util.List; +import java.util.Set; + +public class IssueExclusionsRegexpScanner implements BatchExtension { + + private static final Logger LOG = LoggerFactory.getLogger(IssueExclusionsRegexpScanner.class); + + private IssueExclusionPatternInitializer exclusionPatternInitializer; + private List allFilePatterns; + private List blockMatchers; + + // fields to be reset at every new scan + private DoubleRegexpMatcher currentMatcher; + private int fileLength; + private List lineExclusions; + private LineExclusion currentLineExclusion; + + public IssueExclusionsRegexpScanner(IssueExclusionPatternInitializer patternsInitializer) { + this.exclusionPatternInitializer = patternsInitializer; + + lineExclusions = Lists.newArrayList(); + allFilePatterns = Lists.newArrayList(); + blockMatchers = Lists.newArrayList(); + + for (IssuePattern pattern : patternsInitializer.getAllFilePatterns()) { + allFilePatterns.add(java.util.regex.Pattern.compile(pattern.getAllFileRegexp())); + } + for (IssuePattern pattern : patternsInitializer.getBlockPatterns()) { + blockMatchers.add(new DoubleRegexpMatcher( + java.util.regex.Pattern.compile(pattern.getBeginBlockRegexp()), + java.util.regex.Pattern.compile(pattern.getEndBlockRegexp()))); + } + + init(); + } + + private void init() { + currentMatcher = null; + fileLength = 0; + lineExclusions.clear(); + currentLineExclusion = null; + } + + public void scan(String resource, File file, Charset sourcesEncoding) throws IOException { + LOG.debug("Scanning {}", resource); + init(); + + List lines = FileUtils.readLines(file, sourcesEncoding.name()); + int lineIndex = 0; + for (String line : lines) { + lineIndex++; + if (line.trim().length() == 0) { + continue; + } + + // first check the single regexp patterns that can be used to totally exclude a file + for (java.util.regex.Pattern pattern : allFilePatterns) { + if (pattern.matcher(line).find()) { + exclusionPatternInitializer.getPatternMatcher().addPatternToExcludeResource(resource); + // nothing more to do on this file + LOG.debug("- Exclusion pattern '{}': every violation in this file will be ignored.", pattern); + return; + } + } + + // then check the double regexps if we're still here + checkDoubleRegexps(line, lineIndex); + } + + if (currentMatcher != null && !currentMatcher.hasSecondPattern()) { + // this will happen when there is a start block regexp but no end block regexp + endExclusion(lineIndex + 1); + } + + // now create the new line-based pattern for this file if there are exclusions + fileLength = lineIndex; + if (!lineExclusions.isEmpty()) { + Set lineRanges = convertLineExclusionsToLineRanges(); + LOG.debug("- Line exclusions found: {}", lineRanges); + exclusionPatternInitializer.getPatternMatcher().addPatternToExcludeLines(resource, lineRanges); + } + } + + private Set convertLineExclusionsToLineRanges() { + Set lineRanges = Sets.newHashSet(); + for (LineExclusion lineExclusion : lineExclusions) { + lineRanges.add(lineExclusion.toLineRange()); + } + return lineRanges; + } + + private void checkDoubleRegexps(String line, int lineIndex) { + if (currentMatcher == null) { + for (DoubleRegexpMatcher matcher : blockMatchers) { + if (matcher.matchesFirstPattern(line)) { + startExclusion(lineIndex); + currentMatcher = matcher; + break; + } + } + } else { + if (currentMatcher.matchesSecondPattern(line)) { + endExclusion(lineIndex); + currentMatcher = null; + } + } + } + + private void startExclusion(int lineIndex) { + currentLineExclusion = new LineExclusion(lineIndex); + lineExclusions.add(currentLineExclusion); + } + + private void endExclusion(int lineIndex) { + currentLineExclusion.setEnd(lineIndex); + currentLineExclusion = null; + } + + private class LineExclusion { + + private int start; + private int end; + + LineExclusion(int start) { + this.start = start; + this.end = -1; + } + + void setEnd(int end) { + this.end = end; + } + + public LineRange toLineRange() { + return new LineRange(start, end == -1 ? fileLength : end); + } + + } + + private static class DoubleRegexpMatcher { + + private java.util.regex.Pattern firstPattern; + private java.util.regex.Pattern secondPattern; + + DoubleRegexpMatcher(java.util.regex.Pattern firstPattern, java.util.regex.Pattern secondPattern) { + this.firstPattern = firstPattern; + this.secondPattern = secondPattern; + } + + boolean matchesFirstPattern(String line) { + return firstPattern.matcher(line).find(); + } + + boolean matchesSecondPattern(String line) { + return hasSecondPattern() && secondPattern.matcher(line).find(); + } + + boolean hasSecondPattern() { + return StringUtils.isNotEmpty(secondPattern.toString()); + } + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/package-info.java b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/package-info.java new file mode 100644 index 00000000000..89e3708cdbb --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/issue/ignore/scanner/package-info.java @@ -0,0 +1,23 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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. + */ +@ParametersAreNonnullByDefault +package org.sonar.batch.issue.ignore.scanner; + +import javax.annotation.ParametersAreNonnullByDefault; diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java index 8cc3ee7cee9..2043d7ee452 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/phases/PhaseExecutor.java @@ -29,6 +29,7 @@ import org.sonar.batch.events.EventBus; import org.sonar.batch.index.DefaultIndex; import org.sonar.batch.index.PersistenceManager; import org.sonar.batch.index.ScanPersister; +import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader; import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; import org.sonar.batch.scan.filesystem.FileSystemLogger; import org.sonar.batch.scan.maven.MavenPhaseExecutor; @@ -65,13 +66,15 @@ public final class PhaseExecutor { private final JsonReport jsonReport; private final DefaultModuleFileSystem fs; private final ProfileLogger profileLogger; + private final IssueExclusionsLoader issueExclusionsLoader; public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor, MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index, EventBus eventBus, UpdateStatusJob updateStatusJob, ProjectInitializer pi, - ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, DefaultModuleFileSystem fs, ProfileLogger profileLogger) { + ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, DefaultModuleFileSystem fs, ProfileLogger profileLogger, + IssueExclusionsLoader issueExclusionsLoader) { this.phases = phases; this.decoratorsExecutor = decoratorsExecutor; this.mavenPhaseExecutor = mavenPhaseExecutor; @@ -90,15 +93,17 @@ public final class PhaseExecutor { this.jsonReport = jsonReport; this.fs = fs; this.profileLogger = profileLogger; + this.issueExclusionsLoader = issueExclusionsLoader; } public PhaseExecutor(Phases phases, DecoratorsExecutor decoratorsExecutor, MavenPhaseExecutor mavenPhaseExecutor, MavenPluginsConfigurator mavenPluginsConfigurator, InitializersExecutor initializersExecutor, PostJobsExecutor postJobsExecutor, SensorsExecutor sensorsExecutor, PersistenceManager persistenceManager, SensorContext sensorContext, DefaultIndex index, - EventBus eventBus, ProjectInitializer pi, ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, DefaultModuleFileSystem fs, ProfileLogger profileLogger) { + EventBus eventBus, ProjectInitializer pi, ScanPersister[] persisters, FileSystemLogger fsLogger, JsonReport jsonReport, + DefaultModuleFileSystem fs, ProfileLogger profileLogger, IssueExclusionsLoader issueExclusionsLoader) { this(phases, decoratorsExecutor, mavenPhaseExecutor, mavenPluginsConfigurator, initializersExecutor, postJobsExecutor, - sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, persisters, fsLogger, jsonReport, fs, profileLogger); + sensorsExecutor, persistenceManager, sensorContext, index, eventBus, null, pi, persisters, fsLogger, jsonReport, fs, profileLogger, issueExclusionsLoader); } /** @@ -122,6 +127,9 @@ public final class PhaseExecutor { // Log detected languages and their profiles after FS is indexed and languages detected profileLogger.execute(); + // Initialize issue exclusions + issueExclusionsLoader.execute(); + sensorsExecutor.execute(sensorContext); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java index fbb5c6b9465..17c4182d137 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java @@ -19,6 +19,13 @@ */ package org.sonar.batch.scan; +import org.sonar.batch.issue.ignore.EnforceIssuesFilter; +import org.sonar.batch.issue.ignore.IgnoreIssuesFilter; +import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; +import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; +import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader; +import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner; + import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.sonar.api.BatchExtension; @@ -148,6 +155,14 @@ public class ModuleScanContainer extends ComponentContainer { IssuableFactory.class, ModuleIssues.class, + // issue exclusions + IssueInclusionPatternInitializer.class, + IssueExclusionPatternInitializer.class, + IssueExclusionsRegexpScanner.class, + IssueExclusionsLoader.class, + EnforceIssuesFilter.class, + IgnoreIssuesFilter.class, + ScanPerspectives.class); } 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 new file mode 100644 index 00000000000..9c1731097e5 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/EnforceIssuesFilterTest.java @@ -0,0 +1,151 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore; + +import org.sonar.batch.issue.ignore.EnforceIssuesFilter; +import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; +import org.sonar.batch.issue.ignore.pattern.IssuePattern; + +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.rule.RuleKey; +import org.sonar.api.utils.WildcardPattern; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class EnforceIssuesFilterTest { + + private IssueInclusionPatternInitializer exclusionPatternInitializer; + private EnforceIssuesFilter ignoreFilter; + private Issue issue; + private IssueFilterChain chain; + + @Before + public void init() { + exclusionPatternInitializer = mock(IssueInclusionPatternInitializer.class); + issue = mock(Issue.class); + chain = mock(IssueFilterChain.class); + when(chain.accept(issue)).thenReturn(true); + + ignoreFilter = new EnforceIssuesFilter(exclusionPatternInitializer); + } + + @Test + public void shouldPassToChainIfNoConfiguredPatterns() { + assertThat(ignoreFilter.accept(issue, chain)).isTrue(); + verify(chain).accept(issue); + } + + @Test + public void shouldPassToChainIfRuleDoesNotMatch() { + String rule = "rule"; + RuleKey ruleKey = mock(RuleKey.class); + when(ruleKey.toString()).thenReturn(rule); + when(issue.ruleKey()).thenReturn(ruleKey); + + IssuePattern matching = mock(IssuePattern.class); + WildcardPattern rulePattern = mock(WildcardPattern.class); + when(matching.getRulePattern()).thenReturn(rulePattern); + when(rulePattern.match(rule)).thenReturn(false); + when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching)); + + assertThat(ignoreFilter.accept(issue, chain)).isTrue(); + verify(chain).accept(issue); + } + + @Test + public void shouldAcceptIssueIfFullyMatched() { + String rule = "rule"; + String path = "org/sonar/api/Issue.java"; + String componentKey = "org.sonar.api.Issue"; + RuleKey ruleKey = mock(RuleKey.class); + when(ruleKey.toString()).thenReturn(rule); + when(issue.ruleKey()).thenReturn(ruleKey); + when(issue.componentKey()).thenReturn(componentKey); + + IssuePattern matching = mock(IssuePattern.class); + WildcardPattern rulePattern = mock(WildcardPattern.class); + when(matching.getRulePattern()).thenReturn(rulePattern); + when(rulePattern.match(rule)).thenReturn(true); + WildcardPattern pathPattern = mock(WildcardPattern.class); + when(matching.getResourcePattern()).thenReturn(pathPattern); + when(pathPattern.match(path)).thenReturn(true); + when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching)); + when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(path); + + assertThat(ignoreFilter.accept(issue, chain)).isTrue(); + verifyZeroInteractions(chain); + } + + @Test + public void shouldRefuseIssueIfRuleMatchesButNotPath() { + String rule = "rule"; + String path = "org/sonar/api/Issue.java"; + String componentKey = "org.sonar.api.Issue"; + RuleKey ruleKey = mock(RuleKey.class); + when(ruleKey.toString()).thenReturn(rule); + when(issue.ruleKey()).thenReturn(ruleKey); + when(issue.componentKey()).thenReturn(componentKey); + + IssuePattern matching = mock(IssuePattern.class); + WildcardPattern rulePattern = mock(WildcardPattern.class); + when(matching.getRulePattern()).thenReturn(rulePattern); + when(rulePattern.match(rule)).thenReturn(true); + WildcardPattern pathPattern = mock(WildcardPattern.class); + when(matching.getResourcePattern()).thenReturn(pathPattern); + when(pathPattern.match(path)).thenReturn(false); + when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching)); + when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(path); + + assertThat(ignoreFilter.accept(issue, chain)).isFalse(); + verifyZeroInteractions(chain); + } + + @Test + public void shouldRefuseIssueIfRuleMatchesAndPathUnknown() { + String rule = "rule"; + String path = "org/sonar/api/Issue.java"; + String componentKey = "org.sonar.api.Issue"; + RuleKey ruleKey = mock(RuleKey.class); + when(ruleKey.toString()).thenReturn(rule); + when(issue.ruleKey()).thenReturn(ruleKey); + when(issue.componentKey()).thenReturn(componentKey); + + IssuePattern matching = mock(IssuePattern.class); + WildcardPattern rulePattern = mock(WildcardPattern.class); + when(matching.getRulePattern()).thenReturn(rulePattern); + when(rulePattern.match(rule)).thenReturn(true); + WildcardPattern pathPattern = mock(WildcardPattern.class); + when(matching.getResourcePattern()).thenReturn(pathPattern); + when(pathPattern.match(path)).thenReturn(false); + when(exclusionPatternInitializer.getMulticriteriaPatterns()).thenReturn(ImmutableList.of(matching)); + when(exclusionPatternInitializer.getPathForComponent(componentKey)).thenReturn(null); + + assertThat(ignoreFilter.accept(issue, chain)).isFalse(); + verifyZeroInteractions(chain); + } +} 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 new file mode 100644 index 00000000000..2dae552a56a --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IgnoreIssuesFilterTest.java @@ -0,0 +1,69 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore; + +import org.sonar.batch.issue.ignore.IgnoreIssuesFilter; +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.junit.Before; +import org.junit.Test; +import org.sonar.api.issue.Issue; +import org.sonar.api.issue.batch.IssueFilterChain; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class IgnoreIssuesFilterTest { + + private IssueExclusionPatternInitializer exclusionPatternInitializer; + private PatternMatcher exclusionPatternMatcher; + private IgnoreIssuesFilter ignoreFilter; + private Issue issue; + private IssueFilterChain chain; + + @Before + public void init() { + exclusionPatternMatcher = mock(PatternMatcher.class); + exclusionPatternInitializer = mock(IssueExclusionPatternInitializer.class); + when(exclusionPatternInitializer.getPatternMatcher()).thenReturn(exclusionPatternMatcher); + issue = mock(Issue.class); + chain = mock(IssueFilterChain.class); + when(chain.accept(issue)).thenReturn(true); + + ignoreFilter = new IgnoreIssuesFilter(exclusionPatternInitializer); + } + + @Test + public void shouldPassToChainIfMatcherHasNoPatternForIssue() { + when(exclusionPatternMatcher.getMatchingPattern(issue)).thenReturn(null); + + assertThat(ignoreFilter.accept(issue, chain)).isTrue(); + } + + @Test + public void shouldAcceptOrRefuseIfMatcherHasPatternForIssue() { + when(exclusionPatternMatcher.getMatchingPattern(issue)).thenReturn(mock(IssuePattern.class)); + + assertThat(ignoreFilter.accept(issue, chain)).isFalse(); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IssueExclusionsConfigurationTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IssueExclusionsConfigurationTest.java new file mode 100644 index 00000000000..ef93bd8a4c9 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/IssueExclusionsConfigurationTest.java @@ -0,0 +1,33 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore; + +import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration; + +import org.junit.Test; +import static org.fest.assertions.Assertions.assertThat; + +public class IssueExclusionsConfigurationTest { + @Test + public void justForCoverage() { + assertThat(IssueExclusionsConfiguration.getPropertyDefinitions()).hasSize(4); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java new file mode 100644 index 00000000000..fb769ec2569 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueExclusionPatternInitializerTest.java @@ -0,0 +1,142 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration; +import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.api.config.Settings; +import org.sonar.api.utils.SonarException; +import static org.fest.assertions.Assertions.assertThat; + +public class IssueExclusionPatternInitializerTest { + + private IssueExclusionPatternInitializer patternsInitializer; + + private Settings settings; + + @Before + public void init() { + settings = new Settings(new PropertyDefinitions(IssueExclusionsConfiguration.getPropertyDefinitions())); + patternsInitializer = new IssueExclusionPatternInitializer(settings); + } + + @Test + public void testNoConfiguration() { + patternsInitializer.initPatterns(); + assertThat(patternsInitializer.hasConfiguredPatterns()).isFalse(); + assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0); + } + + @Test + public void shouldHavePatternsBasedOnMulticriteriaPattern() { + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1,2"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RESOURCE_KEY, "org/foo/Bar.java"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RULE_KEY, "*"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".2." + IssueExclusionsConfiguration.RESOURCE_KEY, "org/foo/Hello.java"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".2." + IssueExclusionsConfiguration.RULE_KEY, "checkstyle:MagicNumber"); + patternsInitializer.initPatterns(); + + assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue(); + assertThat(patternsInitializer.hasFileContentPattern()).isFalse(); + assertThat(patternsInitializer.hasMulticriteriaPatterns()).isTrue(); + assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(2); + assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(0); + assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(0); + + patternsInitializer.initializePatternsForPath("org/foo/Bar.java", "org.foo.Bar"); + patternsInitializer.initializePatternsForPath("org/foo/Baz.java", "org.foo.Baz"); + patternsInitializer.initializePatternsForPath("org/foo/Hello.java", "org.foo.Hello"); + + assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Bar")).hasSize(1); + assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Baz")).hasSize(0); + assertThat(patternsInitializer.getPatternMatcher().getPatternsForComponent("org.foo.Hello")).hasSize(1); + + } + + @Test(expected = SonarException.class) + public void shouldLogInvalidResourceKey() { + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RESOURCE_KEY, ""); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RULE_KEY, "*"); + patternsInitializer.initPatterns(); + } + + @Test(expected = SonarException.class) + public void shouldLogInvalidRuleKey() { + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY, "1"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RESOURCE_KEY, "*"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_EXCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RULE_KEY, ""); + patternsInitializer.initPatterns(); + } + + @Test + public void shouldReturnBlockPattern() { + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY, "1,2,3"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".1." + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP, "// SONAR-OFF"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".1." + IssueExclusionsConfiguration.END_BLOCK_REGEXP, "// SONAR-ON"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".2." + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP, "// FOO-OFF"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".2." + IssueExclusionsConfiguration.END_BLOCK_REGEXP, "// FOO-ON"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".3." + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP, "// IGNORE-TO-EOF"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".3." + IssueExclusionsConfiguration.END_BLOCK_REGEXP, ""); + patternsInitializer.loadFileContentPatterns(); + + assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue(); + assertThat(patternsInitializer.hasFileContentPattern()).isTrue(); + assertThat(patternsInitializer.hasMulticriteriaPatterns()).isFalse(); + assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0); + assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(3); + assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(0); + } + + @Test(expected = SonarException.class) + public void shouldLogInvalidStartBlockPattern() { + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY, "1"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".1." + IssueExclusionsConfiguration.BEGIN_BLOCK_REGEXP, ""); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_BLOCK_KEY + ".1." + IssueExclusionsConfiguration.END_BLOCK_REGEXP, "// SONAR-ON"); + patternsInitializer.loadFileContentPatterns(); + } + + @Test + public void shouldReturnAllFilePattern() { + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY, "1,2"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY + ".1." + IssueExclusionsConfiguration.FILE_REGEXP, "@SONAR-IGNORE-ALL"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY + ".2." + IssueExclusionsConfiguration.FILE_REGEXP, "//FOO-IGNORE-ALL"); + patternsInitializer.loadFileContentPatterns(); + + assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue(); + assertThat(patternsInitializer.hasFileContentPattern()).isTrue(); + assertThat(patternsInitializer.hasMulticriteriaPatterns()).isFalse(); + assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(0); + assertThat(patternsInitializer.getBlockPatterns().size()).isEqualTo(0); + assertThat(patternsInitializer.getAllFilePatterns().size()).isEqualTo(2); + } + + @Test(expected = SonarException.class) + public void shouldLogInvalidAllFilePattern() { + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY, "1"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_ALLFILE_KEY + ".1." + IssueExclusionsConfiguration.FILE_REGEXP, ""); + patternsInitializer.loadFileContentPatterns(); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java new file mode 100644 index 00000000000..59542512bfc --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssueInclusionPatternInitializerTest.java @@ -0,0 +1,72 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.IssueExclusionsConfiguration; +import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; + +import org.junit.Before; +import org.junit.Test; +import org.sonar.api.config.PropertyDefinitions; +import org.sonar.api.config.Settings; +import static org.fest.assertions.Assertions.assertThat; + +public class IssueInclusionPatternInitializerTest { + + private IssueInclusionPatternInitializer patternsInitializer; + + private Settings settings; + + @Before + public void init() { + settings = new Settings(new PropertyDefinitions(IssueExclusionsConfiguration.getPropertyDefinitions())); + patternsInitializer = new IssueInclusionPatternInitializer(settings); + } + + @Test + public void testNoConfiguration() { + patternsInitializer.initPatterns(); + assertThat(patternsInitializer.hasConfiguredPatterns()).isFalse(); + } + + @Test + public void shouldHavePatternsBasedOnMulticriteriaPattern() { + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY, "1,2"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RESOURCE_KEY, "org/foo/Bar.java"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".1." + IssueExclusionsConfiguration.RULE_KEY, "*"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".2." + IssueExclusionsConfiguration.RESOURCE_KEY, "org/foo/Hello.java"); + settings.setProperty(IssueExclusionsConfiguration.PATTERNS_MULTICRITERIA_INCLUSION_KEY + ".2." + IssueExclusionsConfiguration.RULE_KEY, "checkstyle:MagicNumber"); + patternsInitializer.initPatterns(); + + assertThat(patternsInitializer.hasConfiguredPatterns()).isTrue(); + assertThat(patternsInitializer.hasMulticriteriaPatterns()).isTrue(); + assertThat(patternsInitializer.getMulticriteriaPatterns().size()).isEqualTo(2); + + patternsInitializer.initializePatternsForPath("org/foo/Bar.java", "org.foo.Bar"); + patternsInitializer.initializePatternsForPath("org/foo/Baz.java", "org.foo.Baz"); + patternsInitializer.initializePatternsForPath("org/foo/Hello.java", "org.foo.Hello"); + + assertThat(patternsInitializer.getPathForComponent("org.foo.Bar")).isEqualTo("org/foo/Bar.java"); + assertThat(patternsInitializer.getPathForComponent("org.foo.Baz")).isEqualTo("org/foo/Baz.java"); + assertThat(patternsInitializer.getPathForComponent("org.foo.Hello")).isEqualTo("org/foo/Hello.java"); + } + +} 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 new file mode 100644 index 00000000000..3c9d43dfe13 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/IssuePatternTest.java @@ -0,0 +1,115 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.pattern.IssuePattern; + +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.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class IssuePatternTest { + + @Test + public void shouldMatchLines() { + IssuePattern pattern = new IssuePattern("*", "*"); + pattern.addLine(12).addLine(15).addLineRange(20, 25); + + assertThat(pattern.matchLine(3)).isFalse(); + assertThat(pattern.matchLine(12)).isTrue(); + assertThat(pattern.matchLine(14)).isFalse(); + assertThat(pattern.matchLine(21)).isTrue(); + assertThat(pattern.matchLine(6599)).isFalse(); + } + + @Test + public void shouldMatchJavaFile() { + String javaFile = "org.foo.Bar"; + assertThat(new IssuePattern("org.foo.Bar", "*").matchResource(javaFile)).isTrue(); + assertThat(new IssuePattern("org.foo.*", "*").matchResource(javaFile)).isTrue(); + assertThat(new IssuePattern("*Bar", "*").matchResource(javaFile)).isTrue(); + assertThat(new IssuePattern("*", "*").matchResource(javaFile)).isTrue(); + assertThat(new IssuePattern("org.*.?ar", "*").matchResource(javaFile)).isTrue(); + + assertThat(new IssuePattern("org.other.Hello", "*").matchResource(javaFile)).isFalse(); + assertThat(new IssuePattern("org.foo.Hello", "*").matchResource(javaFile)).isFalse(); + assertThat(new IssuePattern("org.*.??ar", "*").matchResource(javaFile)).isFalse(); + assertThat(new IssuePattern("org.*.??ar", "*").matchResource(null)).isFalse(); + assertThat(new IssuePattern("org.*.??ar", "*").matchResource("plop")).isFalse(); + } + + @Test + public void shouldMatchRule() { + RuleKey rule = Rule.create("checkstyle", "IllegalRegexp", "").ruleKey(); + assertThat(new IssuePattern("*", "*").matchRule(rule)).isTrue(); + assertThat(new IssuePattern("*", "checkstyle:*").matchRule(rule)).isTrue(); + assertThat(new IssuePattern("*", "checkstyle:IllegalRegexp").matchRule(rule)).isTrue(); + assertThat(new IssuePattern("*", "checkstyle:Illegal*").matchRule(rule)).isTrue(); + assertThat(new IssuePattern("*", "*:*Illegal*").matchRule(rule)).isTrue(); + + assertThat(new IssuePattern("*", "pmd:IllegalRegexp").matchRule(rule)).isFalse(); + assertThat(new IssuePattern("*", "pmd:*").matchRule(rule)).isFalse(); + assertThat(new IssuePattern("*", "*:Foo*IllegalRegexp").matchRule(rule)).isFalse(); + } + + @Test + public void shouldMatchViolation() { + Rule rule = Rule.create("checkstyle", "IllegalRegexp", ""); + String javaFile = "org.foo.Bar"; + + IssuePattern pattern = new IssuePattern("*", "*"); + pattern.addLine(12); + + assertThat(pattern.match(create(rule, javaFile, null))).isFalse(); + assertThat(pattern.match(create(rule, javaFile, 12))).isTrue(); + assertThat(pattern.match(create((Rule) null, javaFile, 5))).isFalse(); + assertThat(pattern.match(create(rule, null, null))).isFalse(); + assertThat(pattern.match(create((Rule) null, null, null))).isFalse(); + } + + private Issue create(Rule rule, String component, Integer line) { + Issue mockIssue = mock(Issue.class); + RuleKey ruleKey = null; + if (rule != null) { + ruleKey = rule.ruleKey(); + } + when(mockIssue.ruleKey()).thenReturn(ruleKey); + when(mockIssue.componentKey()).thenReturn(component); + when(mockIssue.line()).thenReturn(line); + return mockIssue; + } + + @Test + public void shouldNotMatchNullRule() { + assertThat(new IssuePattern("*", "*").matchRule(null)).isFalse(); + } + + @Test + public void shouldPrintPatternToString() { + IssuePattern pattern = new IssuePattern("*", "checkstyle:*"); + + assertThat(pattern.toString()).isEqualTo("IssuePattern[resourcePattern=*,rulePattern=checkstyle:*,lines=[],lineRanges=[],beginBlockRegexp=,endBlockRegexp=,allFileRegexp=,checkLines=true]"); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/LineRangeTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/LineRangeTest.java new file mode 100644 index 00000000000..21df72ba862 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/LineRangeTest.java @@ -0,0 +1,74 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.pattern.LineRange; + +import org.junit.Test; +import static org.fest.assertions.Assertions.assertThat; + +public class LineRangeTest { + + @Test(expected = IllegalArgumentException.class) + public void lineRangeShouldBeOrdered() { + new LineRange(25, 12); + } + + @Test + public void shouldConvertLineRangeToLines() { + LineRange range = new LineRange(12, 15); + + assertThat(range.toLines()).containsOnly(12, 13, 14, 15); + } + + @Test + public void shouldTestInclusionInRangeOfLines() { + LineRange range = new LineRange(12, 15); + + assertThat(range.in(3)).isFalse(); + assertThat(range.in(12)).isTrue(); + assertThat(range.in(13)).isTrue(); + assertThat(range.in(14)).isTrue(); + assertThat(range.in(15)).isTrue(); + assertThat(range.in(16)).isFalse(); + } + + @Test + public void testToString() throws Exception { + assertThat(new LineRange(12, 15).toString()).isEqualTo("[12-15]"); + } + + @Test + public void testEquals() throws Exception { + LineRange range = new LineRange(12, 15); + assertThat(range).isEqualTo(range); + assertThat(range).isEqualTo(new LineRange(12, 15)); + assertThat(range).isNotEqualTo(new LineRange(12, 2000)); + assertThat(range).isNotEqualTo(new LineRange(1000, 2000)); + assertThat(range).isNotEqualTo(null); + assertThat(range).isNotEqualTo(new StringBuffer()); + } + + @Test + public void testHashCode() throws Exception { + assertThat(new LineRange(12, 15).hashCode()).isEqualTo(new LineRange(12, 15).hashCode()); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternDecoderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternDecoderTest.java new file mode 100644 index 00000000000..b993e82e8ff --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternDecoderTest.java @@ -0,0 +1,191 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.pattern.IssuePattern; +import org.sonar.batch.issue.ignore.pattern.PatternDecoder; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.utils.SonarException; + +import java.util.List; + +import static org.fest.assertions.Assertions.assertThat; + +public class PatternDecoderTest { + + private PatternDecoder decoder = new PatternDecoder(); + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void shouldReadString() { + String patternsList = "# a comment followed by a blank line\n\n" + + "# suppress all violations\n" + + "*;*;*\n\n" + + "# exclude a Java file\n" + + "com.foo.Bar;*;*\n\n" + + "# exclude a Java package\n" + + "com.foo.*;*;*\n\n" + + "# exclude a specific rule\n" + + "*;checkstyle:IllegalRegexp;*\n\n" + + "# exclude a specific rule on a specific file\n" + + "com.foo.Bar;checkstyle:IllegalRegexp;*\n"; + List patterns = decoder.decode(patternsList); + + assertThat(patterns).hasSize(5); + } + + @Test + public void shouldCheckFormatOfResource() { + assertThat(PatternDecoder.isResource("")).isFalse(); + assertThat(PatternDecoder.isResource("*")).isTrue(); + assertThat(PatternDecoder.isResource("com.foo.*")).isTrue(); + } + + @Test + public void shouldCheckFormatOfRule() { + assertThat(PatternDecoder.isRule("")).isFalse(); + assertThat(PatternDecoder.isRule("*")).isTrue(); + assertThat(PatternDecoder.isRule("com.foo.*")).isTrue(); + } + + @Test + public void shouldCheckFormatOfLinesRange() { + assertThat(PatternDecoder.isLinesRange("")).isFalse(); + assertThat(PatternDecoder.isLinesRange(" ")).isFalse(); + assertThat(PatternDecoder.isLinesRange("12")).isFalse(); + assertThat(PatternDecoder.isLinesRange("12,212")).isFalse(); + + assertThat(PatternDecoder.isLinesRange("*")).isTrue(); + assertThat(PatternDecoder.isLinesRange("[]")).isTrue(); + assertThat(PatternDecoder.isLinesRange("[13]")).isTrue(); + assertThat(PatternDecoder.isLinesRange("[13,24]")).isTrue(); + assertThat(PatternDecoder.isLinesRange("[13,24,25-500]")).isTrue(); + assertThat(PatternDecoder.isLinesRange("[24-65]")).isTrue(); + assertThat(PatternDecoder.isLinesRange("[13,24-65,84-89,122]")).isTrue(); + } + + @Test + public void shouldReadStarPatterns() { + IssuePattern pattern = decoder.decodeLine("*;*;*"); + + assertThat(pattern.getResourcePattern().toString()).isEqualTo("*"); + assertThat(pattern.getRulePattern().toString()).isEqualTo("*"); + assertThat(pattern.isCheckLines()).isFalse(); + } + + @Test + public void shouldReadLineIds() { + IssuePattern pattern = decoder.decodeLine("*;*;[10,25,98]"); + + assertThat(pattern.isCheckLines()).isTrue(); + assertThat(pattern.getAllLines()).containsOnly(10, 25, 98); + } + + @Test + public void shouldReadRangeOfLineIds() { + IssuePattern pattern = decoder.decodeLine("*;*;[10-12,25,97-100]"); + + assertThat(pattern.isCheckLines()).isTrue(); + assertThat(pattern.getAllLines()).containsOnly(10, 11, 12, 25, 97, 98, 99, 100); + } + + @Test + public void shouldNotExcludeLines() { + // [] is different than * + // - all violations are excluded on * + // * no violations are excluded on [] + IssuePattern pattern = decoder.decodeLine("*;*;[]"); + + assertThat(pattern.isCheckLines()).isTrue(); + assertThat(pattern.getAllLines()).isEmpty(); + } + + @Test + public void shouldReadBlockPattern() { + IssuePattern pattern = decoder.decodeLine("SONAR-OFF;SONAR-ON"); + + assertThat(pattern.getResourcePattern()).isNull(); + assertThat(pattern.getBeginBlockRegexp()).isEqualTo("SONAR-OFF"); + assertThat(pattern.getEndBlockRegexp()).isEqualTo("SONAR-ON"); + } + + @Test + public void shouldReadAllFilePattern() { + IssuePattern pattern = decoder.decodeLine("SONAR-ALL-OFF"); + + assertThat(pattern.getResourcePattern()).isNull(); + assertThat(pattern.getAllFileRegexp()).isEqualTo("SONAR-ALL-OFF"); + } + + @Test + public void shouldFailToReadUncorrectLine1() { + thrown.expect(SonarException.class); + thrown.expectMessage("Exclusions > Issues : Invalid format. The following line has more than 3 fields separated by comma"); + + decoder.decode(";;;;"); + } + + @Test + public void shouldFailToReadUncorrectLine3() { + thrown.expect(SonarException.class); + thrown.expectMessage("Exclusions > Issues : Invalid format. The first field does not define a resource pattern"); + + decoder.decode(";*;*"); + } + + @Test + public void shouldFailToReadUncorrectLine4() { + thrown.expect(SonarException.class); + thrown.expectMessage("Exclusions > Issues : Invalid format. The second field does not define a rule pattern"); + + decoder.decode("*;;*"); + } + + @Test + public void shouldFailToReadUncorrectLine5() { + thrown.expect(SonarException.class); + thrown.expectMessage("Exclusions > Issues : Invalid format. The third field does not define a range of lines"); + + decoder.decode("*;*;blabla"); + } + + @Test + public void shouldFailToReadUncorrectLine6() { + thrown.expect(SonarException.class); + thrown.expectMessage("Exclusions > Issues : Invalid format. The first field does not define a regular expression"); + + decoder.decode(";ON"); + } + + @Test + public void shouldAcceptEmptyEndBlockRegexp() { + IssuePattern pattern = decoder.decodeLine("OFF;"); + + assertThat(pattern.getResourcePattern()).isNull(); + assertThat(pattern.getBeginBlockRegexp()).isEqualTo("OFF"); + assertThat(pattern.getEndBlockRegexp()).isEmpty(); + } +} 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 new file mode 100644 index 00000000000..a948aac47f7 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/pattern/PatternMatcherTest.java @@ -0,0 +1,124 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.pattern; + +import org.sonar.batch.issue.ignore.pattern.IssuePattern; +import org.sonar.batch.issue.ignore.pattern.LineRange; +import org.sonar.batch.issue.ignore.pattern.PatternDecoder; +import org.sonar.batch.issue.ignore.pattern.PatternMatcher; + +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; + +import java.io.IOException; +import java.util.Set; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class PatternMatcherTest { + + public static final Rule CHECKSTYLE_RULE = Rule.create("checkstyle", "MagicNumber", ""); + public static final String JAVA_FILE = "org.foo.Hello"; + + private PatternMatcher patternMatcher; + + @Before + public void setUp() { + patternMatcher = new PatternMatcher(); + } + + @Test + public void shouldReturnExtraPatternForResource() { + String file = "foo"; + patternMatcher.addPatternToExcludeResource(file); + + IssuePattern extraPattern = patternMatcher.getPatternsForComponent(file).iterator().next(); + assertThat(extraPattern.matchResource(file)).isTrue(); + assertThat(extraPattern.isCheckLines()).isFalse(); + } + + @Test + public void shouldReturnExtraPatternForLinesOfResource() { + String file = "foo"; + Set lineRanges = Sets.newHashSet(); + lineRanges.add(new LineRange(25, 28)); + patternMatcher.addPatternToExcludeLines(file, lineRanges); + + IssuePattern extraPattern = patternMatcher.getPatternsForComponent(file).iterator().next(); + assertThat(extraPattern.matchResource(file)).isTrue(); + assertThat(extraPattern.getAllLines()).isEqualTo(Sets.newHashSet(25, 26, 27, 28)); + } + + @Test + public void shouldHaveNoMatcherIfNoneDefined() { + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, null))).isNull(); + } + + @Test + public void shouldMatchWithStandardPatterns() throws IOException { + patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;checkstyle:MagicNumber;[15-200]")); + + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isNotNull(); + } + + @Test + public void shouldNotMatchWithStandardPatterns() throws IOException { + patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;checkstyle:MagicNumber;[15-200]")); + + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull(); + } + + @Test + public void shouldMatchWithExtraPattern() throws IOException { + patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;*;[15-200]")); + + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 150))).isNotNull(); + } + + @Test + public void shouldNotMatchWithExtraPattern() throws IOException { + patternMatcher.addPatternForComponent(JAVA_FILE, createPattern("org.foo.Hello;*;[15-200]")); + + assertThat(patternMatcher.getMatchingPattern(create(CHECKSTYLE_RULE, JAVA_FILE, 5))).isNull(); + } + + private Issue create(Rule rule, String component, Integer line) { + Issue mockIssue = mock(Issue.class); + RuleKey ruleKey = null; + if (rule != null) { + ruleKey = rule.ruleKey(); + } + when(mockIssue.ruleKey()).thenReturn(ruleKey); + when(mockIssue.componentKey()).thenReturn(component); + when(mockIssue.line()).thenReturn(line); + return mockIssue; + } + + private IssuePattern createPattern(String line) { + return new PatternDecoder().decode(line).get(0); + } + +} 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 new file mode 100644 index 00000000000..8f8eba536f7 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsLoaderTest.java @@ -0,0 +1,175 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.scanner; + +import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; +import org.sonar.batch.issue.ignore.pattern.IssueInclusionPatternInitializer; +import org.sonar.batch.issue.ignore.pattern.PatternMatcher; +import org.sonar.batch.issue.ignore.scanner.IssueExclusionsLoader; +import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner; + +import com.google.common.base.Charsets; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.sonar.api.scan.filesystem.FileQuery; +import org.sonar.api.scan.filesystem.internal.DefaultInputFile; +import org.sonar.api.scan.filesystem.internal.InputFileBuilder; +import org.sonar.api.utils.SonarException; +import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; + +import static com.google.common.base.Charsets.UTF_8; +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.doThrow; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; + +public class IssueExclusionsLoaderTest { + + private IssueExclusionsLoader scanner; + + @Mock + private IssueExclusionsRegexpScanner regexpScanner; + @Mock + private IssueInclusionPatternInitializer inclusionPatternInitializer; + @Mock + private IssueExclusionPatternInitializer exclusionPatternInitializer; + @Mock + private PatternMatcher patternMatcher; + @Mock + private DefaultModuleFileSystem fs; + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + private File baseDir; + + @Before + public void init() throws IOException { + baseDir = temp.newFolder(); + MockitoAnnotations.initMocks(this); + + when(fs.sourceCharset()).thenReturn(UTF_8); + + scanner = new IssueExclusionsLoader(regexpScanner, exclusionPatternInitializer, inclusionPatternInitializer, fs); + } + + @Test + public void testToString() throws Exception { + assertThat(scanner.toString()).isEqualTo("Issues Exclusions - Source Scanner"); + } + + @Test + public void shouldExecute() throws IOException { + when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true); + when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true); + assertThat(scanner.shouldExecuteOnProject(null)).isTrue(); + + when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true); + when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false); + assertThat(scanner.shouldExecuteOnProject(null)).isTrue(); + + when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false); + when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(true); + assertThat(scanner.shouldExecuteOnProject(null)).isTrue(); + + when(exclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false); + when(inclusionPatternInitializer.hasConfiguredPatterns()).thenReturn(false); + assertThat(scanner.shouldExecuteOnProject(null)).isFalse(); + + } + + @Test + public void shouldAnalyseProject() throws IOException { + File javaFile1 = new File(baseDir, "src/main/java/Foo.java"); + File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java"); + when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( + new InputFileBuilder(javaFile1, Charsets.UTF_8, "src/main/java/Foo.java") + .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/main/java/Foo.java") + .build(), + new InputFileBuilder(javaTestFile1, Charsets.UTF_8, "src/test/java/FooTest.java") + .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/test/java/FooTest.java") + .build())); + + when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); + + scanner.execute(); + + verify(inclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java"); + verify(inclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java"); + verify(exclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java"); + verify(exclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java"); + verify(regexpScanner).scan("polop:src/main/java/Foo.java", javaFile1, UTF_8); + verify(regexpScanner).scan("polop:src/test/java/FooTest.java", javaTestFile1, UTF_8); + } + + @Test + public void shouldAnalyseFilesOnlyWhenRegexConfigured() throws IOException { + File javaFile1 = new File(baseDir, "src/main/java/Foo.java"); + File javaTestFile1 = new File(baseDir, "src/test/java/FooTest.java"); + when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( + new InputFileBuilder(javaFile1, Charsets.UTF_8, "src/main/java/Foo.java") + .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/main/java/Foo.java") + .build(), + new InputFileBuilder(javaTestFile1, Charsets.UTF_8, "src/test/java/FooTest.java") + .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/test/java/FooTest.java") + .build())); + + when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(false); + + scanner.execute(); + + verify(inclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java"); + verify(inclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java"); + verify(exclusionPatternInitializer).initializePatternsForPath("src/main/java/Foo.java", "polop:src/main/java/Foo.java"); + verify(exclusionPatternInitializer).initializePatternsForPath("src/test/java/FooTest.java", "polop:src/test/java/FooTest.java"); + verifyZeroInteractions(regexpScanner); + } + + @Test + public void shouldReportFailure() throws IOException { + File phpFile1 = new File(baseDir, "src/Foo.php"); + when(fs.inputFiles(FileQuery.all())).thenReturn((Iterable) Arrays.asList( + new InputFileBuilder(phpFile1, Charsets.UTF_8, "src/Foo.php") + .attribute(DefaultInputFile.ATTRIBUTE_COMPONENT_KEY, "polop:src/Foo.php") + .build())); + + when(exclusionPatternInitializer.hasFileContentPattern()).thenReturn(true); + doThrow(new IOException("BUG")).when(regexpScanner).scan("polop:src/Foo.php", phpFile1, UTF_8); + + thrown.expect(SonarException.class); + thrown.expectMessage("Unable to read the source file"); + + scanner.execute(); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java new file mode 100644 index 00000000000..d50c3778e32 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest.java @@ -0,0 +1,163 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 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.ignore.scanner; + +import org.sonar.batch.issue.ignore.pattern.IssueExclusionPatternInitializer; +import org.sonar.batch.issue.ignore.pattern.IssuePattern; +import org.sonar.batch.issue.ignore.pattern.LineRange; +import org.sonar.batch.issue.ignore.pattern.PatternMatcher; +import org.sonar.batch.issue.ignore.scanner.IssueExclusionsRegexpScanner; + +import com.google.common.collect.Sets; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.sonar.test.TestUtils; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Set; + +import static com.google.common.base.Charsets.UTF_8; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyNoMoreInteractions; +import static org.mockito.Mockito.when; + +public class IssueExclusionsRegexpScannerTest { + + private IssueExclusionsRegexpScanner regexpScanner; + + private String javaFile; + @Mock + private IssueExclusionPatternInitializer patternsInitializer; + @Mock + private PatternMatcher patternMatcher; + @Mock + private IssuePattern allFilePattern; + @Mock + private IssuePattern blockPattern1; + @Mock + private IssuePattern blockPattern2; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + + when(allFilePattern.getAllFileRegexp()).thenReturn("@SONAR-IGNORE-ALL"); + when(blockPattern1.getBeginBlockRegexp()).thenReturn("// SONAR-OFF"); + when(blockPattern1.getEndBlockRegexp()).thenReturn("// SONAR-ON"); + when(blockPattern2.getBeginBlockRegexp()).thenReturn("// FOO-OFF"); + when(blockPattern2.getEndBlockRegexp()).thenReturn("// FOO-ON"); + when(patternsInitializer.getAllFilePatterns()).thenReturn(Arrays.asList(allFilePattern)); + when(patternsInitializer.getBlockPatterns()).thenReturn(Arrays.asList(blockPattern1, blockPattern2)); + when(patternsInitializer.getPatternMatcher()).thenReturn(patternMatcher); + + regexpScanner = new IssueExclusionsRegexpScanner(patternsInitializer); + verify(patternsInitializer, times(1)).getAllFilePatterns(); + verify(patternsInitializer, times(1)).getBlockPatterns(); + + javaFile = "org.sonar.test.MyFile"; + } + + @Test + public void shouldDoNothing() throws IOException { + regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-no-regexp.txt"), UTF_8); + + verifyNoMoreInteractions(patternsInitializer); + } + + @Test + public void shouldAddPatternToExcludeFile() throws IOException { + regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-single-regexp.txt"), UTF_8); + + verify(patternsInitializer).getPatternMatcher(); + verify(patternMatcher, times(1)).addPatternToExcludeResource(javaFile); + verifyNoMoreInteractions(patternsInitializer); + } + + @Test + public void shouldAddPatternToExcludeFileEvenIfAlsoDoubleRegexps() throws IOException { + regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-single-regexp-and-double-regexp.txt"), UTF_8); + + verify(patternsInitializer).getPatternMatcher(); + verify(patternMatcher, times(1)).addPatternToExcludeResource(javaFile); + verifyNoMoreInteractions(patternsInitializer); + } + + @Test + public void shouldAddPatternToExcludeLines() throws IOException { + regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp.txt"), UTF_8); + + Set lineRanges = Sets.newHashSet(); + lineRanges.add(new LineRange(21, 25)); + verify(patternsInitializer).getPatternMatcher(); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verifyNoMoreInteractions(patternsInitializer); + } + + @Test + public void shouldAddPatternToExcludeLinesTillTheEnd() throws IOException { + regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-unfinished.txt"), UTF_8); + + Set lineRanges = Sets.newHashSet(); + lineRanges.add(new LineRange(21, 34)); + verify(patternsInitializer).getPatternMatcher(); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verifyNoMoreInteractions(patternsInitializer); + } + + @Test + public void shouldAddPatternToExcludeSeveralLineRanges() throws IOException { + regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-twice.txt"), UTF_8); + + Set lineRanges = Sets.newHashSet(); + lineRanges.add(new LineRange(21, 25)); + lineRanges.add(new LineRange(29, 33)); + verify(patternsInitializer).getPatternMatcher(); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verifyNoMoreInteractions(patternsInitializer); + } + + @Test + public void shouldAddPatternToExcludeLinesWithWrongOrder() throws IOException { + regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-wrong-order.txt"), UTF_8); + + Set lineRanges = Sets.newHashSet(); + lineRanges.add(new LineRange(25, 35)); + verify(patternsInitializer).getPatternMatcher(); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verifyNoMoreInteractions(patternsInitializer); + } + + @Test + public void shouldAddPatternToExcludeLinesWithMess() throws IOException { + regexpScanner.scan(javaFile, TestUtils.getResource(getClass(), "file-with-double-regexp-mess.txt"), UTF_8); + + Set lineRanges = Sets.newHashSet(); + lineRanges.add(new LineRange(21, 29)); + verify(patternsInitializer).getPatternMatcher(); + verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges); + verifyNoMoreInteractions(patternsInitializer); + } + +} diff --git a/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-mess.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-mess.txt new file mode 100644 index 00000000000..48d30c92f97 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-mess.txt @@ -0,0 +1,37 @@ +package org.sonar.plugins.switchoffviolations.pattern; + +import com.google.common.collect.Sets; + +import java.util.Set; + +/** + * + */ +public class LineRange { + int from, to; + + public LineRange(int from, int to) { + if (to < from) { + throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); + } + this.from = from; + this.to = to; + } + + // SONAR-OFF + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + // FOO-OFF + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + // SONAR-ON + for (int index = from; index <= to; index++) { + lines.add(index); + } + // FOO-ON + return lines; + } + +} \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-twice.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-twice.txt new file mode 100644 index 00000000000..9ae63dc57f9 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-twice.txt @@ -0,0 +1,37 @@ +package org.sonar.plugins.switchoffviolations.pattern; + +import com.google.common.collect.Sets; + +import java.util.Set; + +/** + * + */ +public class LineRange { + int from, to; + + public LineRange(int from, int to) { + if (to < from) { + throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); + } + this.from = from; + this.to = to; + } + + // SONAR-OFF + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + // SONAR-ON + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + // FOO-OFF + for (int index = from; index <= to; index++) { + lines.add(index); + } + // FOO-ON + return lines; + } + +} \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-unfinished.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-unfinished.txt new file mode 100644 index 00000000000..dd7656180ab --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-unfinished.txt @@ -0,0 +1,34 @@ +package org.sonar.plugins.switchoffviolations.pattern; + +import com.google.common.collect.Sets; + +import java.util.Set; + +/** + * + */ +public class LineRange { + int from, to; + + public LineRange(int from, int to) { + if (to < from) { + throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); + } + this.from = from; + this.to = to; + } + + // SONAR-OFF + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + for (int index = from; index <= to; index++) { + lines.add(index); + } + return lines; + } + +} \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-wrong-order.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-wrong-order.txt new file mode 100644 index 00000000000..7cac0b98aed --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp-wrong-order.txt @@ -0,0 +1,35 @@ +package org.sonar.plugins.switchoffviolations.pattern; + +import com.google.common.collect.Sets; + +import java.util.Set; + +/** + * + */ +public class LineRange { + int from, to; + + public LineRange(int from, int to) { + if (to < from) { + throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); + } + this.from = from; + this.to = to; + } + + // SONAR-ON + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + // SONAR-OFF + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + for (int index = from; index <= to; index++) { + lines.add(index); + } + return lines; + } + +} \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp.txt new file mode 100644 index 00000000000..002169fe031 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-double-regexp.txt @@ -0,0 +1,35 @@ +package org.sonar.plugins.switchoffviolations.pattern; + +import com.google.common.collect.Sets; + +import java.util.Set; + +/** + * + */ +public class LineRange { + int from, to; + + public LineRange(int from, int to) { + if (to < from) { + throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); + } + this.from = from; + this.to = to; + } + + // SONAR-OFF + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + // SONAR-ON + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + for (int index = from; index <= to; index++) { + lines.add(index); + } + return lines; + } + +} \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-no-regexp.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-no-regexp.txt new file mode 100644 index 00000000000..f18fa5b90ad --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-no-regexp.txt @@ -0,0 +1,33 @@ +package org.sonar.plugins.switchoffviolations.pattern; + +import com.google.common.collect.Sets; + +import java.util.Set; + +/** + * + */ +public class LineRange { + int from, to; + + public LineRange(int from, int to) { + if (to < from) { + throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); + } + this.from = from; + this.to = to; + } + + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + for (int index = from; index <= to; index++) { + lines.add(index); + } + return lines; + } + +} \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-single-regexp-and-double-regexp.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-single-regexp-and-double-regexp.txt new file mode 100644 index 00000000000..e09ecd7a323 --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-single-regexp-and-double-regexp.txt @@ -0,0 +1,36 @@ +package org.sonar.plugins.switchoffviolations.pattern; + +import com.google.common.collect.Sets; + + // SONAR-OFF + +import java.util.Set; + +/** + * @SONAR-IGNORE-ALL + */ +public class LineRange { + int from, to; + + public LineRange(int from, int to) { + if (to < from) { + throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); + } + this.from = from; + this.to = to; + } + + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + // SONAR-ON + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + for (int index = from; index <= to; index++) { + lines.add(index); + } + return lines; + } + +} \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-single-regexp.txt b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-single-regexp.txt new file mode 100644 index 00000000000..ef135ebc50c --- /dev/null +++ b/sonar-batch/src/test/resources/org/sonar/batch/issue/ignore/scanner/IssueExclusionsRegexpScannerTest/file-with-single-regexp.txt @@ -0,0 +1,33 @@ +package org.sonar.plugins.switchoffviolations.pattern; + +import com.google.common.collect.Sets; + +import java.util.Set; + +/** + * @SONAR-IGNORE-ALL + */ +public class LineRange { + int from, to; + + public LineRange(int from, int to) { + if (to < from) { + throw new IllegalArgumentException("Line range is not valid: " + from + " must be greater than " + to); + } + this.from = from; + this.to = to; + } + + public boolean in(int lineId) { + return from <= lineId && lineId <= to; + } + + public Set toLines() { + Set lines = Sets.newLinkedHashSet(); + for (int index = from; index <= to; index++) { + lines.add(index); + } + return lines; + } + +} \ No newline at end of file