*/
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;
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;
@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",
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());
+++ /dev/null
-/*
- * 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);
- }
- }
-}
+++ /dev/null
-/*
- * 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<PropertyDefinition> 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());
- }
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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<Object> extensions = ImmutableList.builder();
-
- extensions.addAll(IgnoreIssuesConfiguration.getPropertyDefinitions());
- extensions.add(
- InclusionPatternInitializer.class,
- ExclusionPatternInitializer.class,
- IgnoreIssuesRegexpScanner.class,
- IgnoreIssuesSourceScanner.class,
- EnforceIssuesFilter.class,
- IgnoreIssuesFilter.class);
-
- return extensions.build();
- }
-
-}
+++ /dev/null
-/*
- * 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;
+++ /dev/null
-/*
- * 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<IssuePattern> multicriteriaPatterns;
-
- protected AbstractPatternInitializer(Settings settings) {
- this.settings = settings;
- initPatterns();
- }
-
- protected Settings getSettings() {
- return settings;
- }
-
- public List<IssuePattern> 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();
-}
+++ /dev/null
-/*
- * 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<IssuePattern> blockPatterns;
- private List<IssuePattern> 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<IssuePattern> getBlockPatterns() {
- return blockPatterns;
- }
-
- public List<IssuePattern> getAllFilePatterns() {
- return allFilePatterns;
- }
-
- public boolean hasFileContentPattern() {
- return ! (blockPatterns.isEmpty() && allFilePatterns.isEmpty());
- }
-}
+++ /dev/null
-/*
- * 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<String, String> 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);
- }
-}
+++ /dev/null
-/*
- * 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<Integer> lines = Sets.newLinkedHashSet();
- private Set<LineRange> 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<LineRange> 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<Integer> getAllLines() {
- Set<Integer> 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);
- }
-}
+++ /dev/null
-/*
- * 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<Integer> toLines() {
- Set<Integer> 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;
- }
-}
+++ /dev/null
-/*
- * 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<IssuePattern> decode(String patternsList) {
- List<IssuePattern> 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);
- }
-}
+++ /dev/null
-/*
- * 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<String, IssuePattern> patternByComponent = LinkedHashMultimap.create();
-
- public IssuePattern getMatchingPattern(Issue issue) {
- IssuePattern matchingPattern = null;
- Iterator<IssuePattern> patternIterator = getPatternsForComponent(issue.componentKey()).iterator();
- while(matchingPattern == null && patternIterator.hasNext()) {
- IssuePattern nextPattern = patternIterator.next();
- if (nextPattern.match(issue)) {
- matchingPattern = nextPattern;
- }
- }
- return matchingPattern;
- }
-
- public Collection<IssuePattern> 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<LineRange> lineRanges) {
- addPatternForComponent(resource, new IssuePattern(resource, "*", lineRanges).setCheckLines(true));
- }
-
-}
+++ /dev/null
-/*
- * 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;
+++ /dev/null
-/*
- * 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<java.util.regex.Pattern> allFilePatterns;
- private List<DoubleRegexpMatcher> blockMatchers;
-
- // fields to be reset at every new scan
- private DoubleRegexpMatcher currentMatcher;
- private int fileLength;
- private List<LineExclusion> 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<String> 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<LineRange> lineRanges = convertLineExclusionsToLineRanges();
- LOG.debug("- Line exclusions found: {}", lineRanges);
- exclusionPatternInitializer.getPatternMatcher().addPatternToExcludeLines(resource, lineRanges);
- }
- }
-
- private Set<LineRange> convertLineExclusionsToLineRanges() {
- Set<LineRange> 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());
- }
- }
-
-}
+++ /dev/null
-/*
- * 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";
- }
-
-}
+++ /dev/null
-/*
- * 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;
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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 */);
- }
-}
+++ /dev/null
-/*
- * 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();
- }
-}
+++ /dev/null
-/*
- * 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");
- }
-
-}
+++ /dev/null
-/*
- * 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=<null>,endBlockRegexp=<null>,allFileRegexp=<null>,checkLines=true]");
- }
-}
+++ /dev/null
-/*
- * 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());
- }
-}
+++ /dev/null
-/*
- * 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<IssuePattern> 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();
- }
-}
+++ /dev/null
-/*
- * 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<LineRange> 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);
- }
-
-}
+++ /dev/null
-/*
- * 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<LineRange> 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<LineRange> 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<LineRange> 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<LineRange> 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<LineRange> lineRanges = Sets.newHashSet();
- lineRanges.add(new LineRange(21, 29));
- verify(patternsInitializer).getPatternMatcher();
- verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges);
- verifyNoMoreInteractions(patternsInitializer);
- }
-
-}
+++ /dev/null
-/*
- * 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);
- }
-}
+++ /dev/null
-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<Integer> toLines() {
- Set<Integer> 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
+++ /dev/null
-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<Integer> toLines() {
- Set<Integer> 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
+++ /dev/null
-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<Integer> toLines() {
- Set<Integer> lines = Sets.newLinkedHashSet();
- for (int index = from; index <= to; index++) {
- lines.add(index);
- }
- return lines;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-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<Integer> toLines() {
- Set<Integer> lines = Sets.newLinkedHashSet();
- for (int index = from; index <= to; index++) {
- lines.add(index);
- }
- return lines;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-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<Integer> toLines() {
- Set<Integer> lines = Sets.newLinkedHashSet();
- for (int index = from; index <= to; index++) {
- lines.add(index);
- }
- return lines;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-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<Integer> toLines() {
- Set<Integer> lines = Sets.newLinkedHashSet();
- for (int index = from; index <= to; index++) {
- lines.add(index);
- }
- return lines;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-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<Integer> toLines() {
- Set<Integer> lines = Sets.newLinkedHashSet();
- for (int index = from; index <= to; index++) {
- lines.add(index);
- }
- return lines;
- }
-
-}
\ No newline at end of file
+++ /dev/null
-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<Integer> toLines() {
- Set<Integer> lines = Sets.newLinkedHashSet();
- for (int index = from; index <= to; index++) {
- lines.add(index);
- }
- return lines;
- }
-
-}
\ No newline at end of file
--- /dev/null
+/*
+ * 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);
+ }
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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<PropertyDefinition> 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());
+ }
+}
--- /dev/null
+/*
+ * 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;
--- /dev/null
+/*
+ * 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<IssuePattern> multicriteriaPatterns;
+
+ protected AbstractPatternInitializer(Settings settings) {
+ this.settings = settings;
+ initPatterns();
+ }
+
+ protected Settings getSettings() {
+ return settings;
+ }
+
+ public List<IssuePattern> 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();
+}
--- /dev/null
+/*
+ * 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<IssuePattern> blockPatterns;
+ private List<IssuePattern> 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<IssuePattern> getBlockPatterns() {
+ return blockPatterns;
+ }
+
+ public List<IssuePattern> getAllFilePatterns() {
+ return allFilePatterns;
+ }
+
+ public boolean hasFileContentPattern() {
+ return ! (blockPatterns.isEmpty() && allFilePatterns.isEmpty());
+ }
+}
--- /dev/null
+/*
+ * 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<String, String> 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);
+ }
+}
--- /dev/null
+/*
+ * 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<Integer> lines = Sets.newLinkedHashSet();
+ private Set<LineRange> 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<LineRange> 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<Integer> getAllLines() {
+ Set<Integer> 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);
+ }
+}
--- /dev/null
+/*
+ * 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<Integer> toLines() {
+ Set<Integer> 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;
+ }
+}
--- /dev/null
+/*
+ * 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<IssuePattern> decode(String patternsList) {
+ List<IssuePattern> 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);
+ }
+}
--- /dev/null
+/*
+ * 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<String, IssuePattern> patternByComponent = LinkedHashMultimap.create();
+
+ public IssuePattern getMatchingPattern(Issue issue) {
+ IssuePattern matchingPattern = null;
+ Iterator<IssuePattern> patternIterator = getPatternsForComponent(issue.componentKey()).iterator();
+ while(matchingPattern == null && patternIterator.hasNext()) {
+ IssuePattern nextPattern = patternIterator.next();
+ if (nextPattern.match(issue)) {
+ matchingPattern = nextPattern;
+ }
+ }
+ return matchingPattern;
+ }
+
+ public Collection<IssuePattern> 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<LineRange> lineRanges) {
+ addPatternForComponent(resource, new IssuePattern(resource, "*", lineRanges).setCheckLines(true));
+ }
+
+}
--- /dev/null
+/*
+ * 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;
--- /dev/null
+/*
+ * 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";
+ }
+
+}
--- /dev/null
+/*
+ * 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<java.util.regex.Pattern> allFilePatterns;
+ private List<DoubleRegexpMatcher> blockMatchers;
+
+ // fields to be reset at every new scan
+ private DoubleRegexpMatcher currentMatcher;
+ private int fileLength;
+ private List<LineExclusion> 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<String> 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<LineRange> lineRanges = convertLineExclusionsToLineRanges();
+ LOG.debug("- Line exclusions found: {}", lineRanges);
+ exclusionPatternInitializer.getPatternMatcher().addPatternToExcludeLines(resource, lineRanges);
+ }
+ }
+
+ private Set<LineRange> convertLineExclusionsToLineRanges() {
+ Set<LineRange> 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());
+ }
+ }
+
+}
--- /dev/null
+/*
+ * 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;
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;
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;
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);
}
/**
// Log detected languages and their profiles after FS is indexed and languages detected
profileLogger.execute();
+ // Initialize issue exclusions
+ issueExclusionsLoader.execute();
+
sensorsExecutor.execute(sensorContext);
}
*/
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;
IssuableFactory.class,
ModuleIssues.class,
+ // issue exclusions
+ IssueInclusionPatternInitializer.class,
+ IssueExclusionPatternInitializer.class,
+ IssueExclusionsRegexpScanner.class,
+ IssueExclusionsLoader.class,
+ EnforceIssuesFilter.class,
+ IgnoreIssuesFilter.class,
+
ScanPerspectives.class);
}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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);
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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");
+ }
+
+}
--- /dev/null
+/*
+ * 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=<null>,endBlockRegexp=<null>,allFileRegexp=<null>,checkLines=true]");
+ }
+}
--- /dev/null
+/*
+ * 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());
+ }
+}
--- /dev/null
+/*
+ * 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<IssuePattern> 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();
+ }
+}
--- /dev/null
+/*
+ * 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<LineRange> 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);
+ }
+
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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<LineRange> 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<LineRange> 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<LineRange> 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<LineRange> 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<LineRange> lineRanges = Sets.newHashSet();
+ lineRanges.add(new LineRange(21, 29));
+ verify(patternsInitializer).getPatternMatcher();
+ verify(patternMatcher, times(1)).addPatternToExcludeLines(javaFile, lineRanges);
+ verifyNoMoreInteractions(patternsInitializer);
+ }
+
+}
--- /dev/null
+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<Integer> toLines() {
+ Set<Integer> 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
--- /dev/null
+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<Integer> toLines() {
+ Set<Integer> 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
--- /dev/null
+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<Integer> toLines() {
+ Set<Integer> lines = Sets.newLinkedHashSet();
+ for (int index = from; index <= to; index++) {
+ lines.add(index);
+ }
+ return lines;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+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<Integer> toLines() {
+ Set<Integer> lines = Sets.newLinkedHashSet();
+ for (int index = from; index <= to; index++) {
+ lines.add(index);
+ }
+ return lines;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+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<Integer> toLines() {
+ Set<Integer> lines = Sets.newLinkedHashSet();
+ for (int index = from; index <= to; index++) {
+ lines.add(index);
+ }
+ return lines;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+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<Integer> toLines() {
+ Set<Integer> lines = Sets.newLinkedHashSet();
+ for (int index = from; index <= to; index++) {
+ lines.add(index);
+ }
+ return lines;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+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<Integer> toLines() {
+ Set<Integer> lines = Sets.newLinkedHashSet();
+ for (int index = from; index <= to; index++) {
+ lines.add(index);
+ }
+ return lines;
+ }
+
+}
\ No newline at end of file
--- /dev/null
+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<Integer> toLines() {
+ Set<Integer> lines = Sets.newLinkedHashSet();
+ for (int index = from; index <= to; index++) {
+ lines.add(index);
+ }
+ return lines;
+ }
+
+}
\ No newline at end of file