3 * Copyright (C) 2009-2024 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.scanner.issue.ignore.scanner;
22 import java.util.ArrayList;
23 import java.util.List;
24 import javax.annotation.CheckForNull;
25 import org.apache.commons.lang.StringUtils;
26 import org.sonar.api.notifications.AnalysisWarnings;
27 import org.slf4j.Logger;
28 import org.slf4j.LoggerFactory;
29 import org.sonar.api.batch.fs.internal.DefaultInputFile;
30 import org.sonar.api.batch.fs.internal.charhandler.CharHandler;
31 import org.sonar.scanner.issue.ignore.IgnoreIssuesFilter;
32 import org.sonar.scanner.issue.ignore.pattern.BlockIssuePattern;
33 import org.sonar.scanner.issue.ignore.pattern.IssueExclusionPatternInitializer;
34 import org.sonar.scanner.issue.ignore.pattern.IssuePattern;
36 public final class IssueExclusionsLoader {
37 private static final Logger LOG = LoggerFactory.getLogger(IssueExclusionsLoader.class);
39 private final List<java.util.regex.Pattern> allFilePatterns;
40 private final List<DoubleRegexpMatcher> blockMatchers;
41 private final IgnoreIssuesFilter ignoreIssuesFilter;
42 private final AnalysisWarnings analysisWarnings;
43 private final IssueExclusionPatternInitializer patternsInitializer;
44 private final boolean enableCharHandler;
45 private boolean warnDeprecatedIssuePatternAlreadyLogged;
47 public IssueExclusionsLoader(IssueExclusionPatternInitializer patternsInitializer, IgnoreIssuesFilter ignoreIssuesFilter, AnalysisWarnings analysisWarnings) {
48 this.patternsInitializer = patternsInitializer;
49 this.ignoreIssuesFilter = ignoreIssuesFilter;
50 this.analysisWarnings = analysisWarnings;
51 this.allFilePatterns = new ArrayList<>();
52 this.blockMatchers = new ArrayList<>();
54 for (String pattern : patternsInitializer.getAllFilePatterns()) {
55 allFilePatterns.add(java.util.regex.Pattern.compile(pattern));
57 for (BlockIssuePattern pattern : patternsInitializer.getBlockPatterns()) {
58 blockMatchers.add(new DoubleRegexpMatcher(
59 java.util.regex.Pattern.compile(pattern.getBeginBlockRegexp()),
60 java.util.regex.Pattern.compile(pattern.getEndBlockRegexp())));
62 enableCharHandler = !allFilePatterns.isEmpty() || !blockMatchers.isEmpty();
65 public void addMulticriteriaPatterns(DefaultInputFile inputFile) {
66 for (IssuePattern pattern : patternsInitializer.getMulticriteriaPatterns()) {
67 if (pattern.matchFile(inputFile.getProjectRelativePath())) {
68 ignoreIssuesFilter.addRuleExclusionPatternForComponent(inputFile, pattern.getRulePattern());
69 } else if (pattern.matchFile(inputFile.getModuleRelativePath())) {
70 warnOnceDeprecatedIssuePattern(
71 "Specifying module-relative paths at project level in property '" + IssueExclusionPatternInitializer.CONFIG_KEY + "' is deprecated. " +
72 "To continue matching files like '" + inputFile.getProjectRelativePath() + "', update this property so that patterns refer to project-relative paths.");
73 ignoreIssuesFilter.addRuleExclusionPatternForComponent(inputFile, pattern.getRulePattern());
78 private void warnOnceDeprecatedIssuePattern(String msg) {
79 if (!warnDeprecatedIssuePatternAlreadyLogged) {
81 analysisWarnings.addUnique(msg);
82 warnDeprecatedIssuePatternAlreadyLogged = true;
87 public CharHandler createCharHandlerFor(DefaultInputFile inputFile) {
88 if (enableCharHandler) {
89 return new IssueExclusionsRegexpScanner(inputFile, allFilePatterns, blockMatchers);
94 public static class DoubleRegexpMatcher {
96 private java.util.regex.Pattern firstPattern;
97 private java.util.regex.Pattern secondPattern;
99 DoubleRegexpMatcher(java.util.regex.Pattern firstPattern, java.util.regex.Pattern secondPattern) {
100 this.firstPattern = firstPattern;
101 this.secondPattern = secondPattern;
104 boolean matchesFirstPattern(String line) {
105 return firstPattern.matcher(line).find();
108 boolean matchesSecondPattern(String line) {
109 return hasSecondPattern() && secondPattern.matcher(line).find();
112 boolean hasSecondPattern() {
113 return StringUtils.isNotEmpty(secondPattern.toString());
118 public String toString() {
119 return "Issues Exclusions - Source Scanner";