View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2026 the original author or authors.
4   //
5   // This library is free software; you can redistribute it and/or
6   // modify it under the terms of the GNU Lesser General Public
7   // License as published by the Free Software Foundation; either
8   // version 2.1 of the License, or (at your option) any later version.
9   //
10  // This library is distributed in the hope that it will be useful,
11  // but WITHOUT ANY WARRANTY; without even the implied warranty of
12  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  // Lesser General Public License for more details.
14  //
15  // You should have received a copy of the GNU Lesser General Public
16  // License along with this library; if not, write to the Free Software
17  // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  ///////////////////////////////////////////////////////////////////////////////////////////////
19  
20  package com.puppycrawl.tools.checkstyle.filters;
21  
22  import java.util.Set;
23  
24  import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean;
25  import com.puppycrawl.tools.checkstyle.api.AuditEvent;
26  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
27  import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
28  import com.puppycrawl.tools.checkstyle.api.Filter;
29  import com.puppycrawl.tools.checkstyle.api.FilterSet;
30  import com.puppycrawl.tools.checkstyle.utils.FilterUtil;
31  import com.puppycrawl.tools.checkstyle.utils.UnmodifiableCollectionUtil;
32  
33  /**
34   * <div>
35   * Filter {@code SuppressionFilter} rejects audit events for Check violations according to a
36   * <a href="https://checkstyle.org/dtds/suppressions_1_2.dtd">suppressions XML document</a>
37   * in a file. If there is no configured suppressions file or the optional is set to true and
38   * suppressions file was not found the Filter accepts all audit events.
39   * </div>
40   *
41   * <p>
42   * Notes:
43   * A <a href="https://checkstyle.org/dtds/suppressions_1_2.dtd">suppressions XML document</a>
44   * contains a set of {@code suppress} elements, where each {@code suppress}
45   * element can have the following attributes:
46   * </p>
47   * <ul>
48   * <li>
49   * {@code files} - a <a href="https://checkstyle.org/property-types.html#Pattern">
50   * Pattern</a> matched against the file name associated with an audit event.
51   * It is optional. If unmatched, all Unix path separators (/)
52   * are converted to Windows separators (\) and retried.
53   * </li>
54   * <li>
55   * {@code checks} - a <a href="https://checkstyle.org/property-types.html#Pattern">
56   * Pattern</a> matched against the name of the check associated with an audit event.
57   * Optional as long as {@code id} or {@code message} is specified.
58   * </li>
59   * <li>
60   * {@code message} - a <a href="https://checkstyle.org/property-types.html#Pattern">
61   * Pattern</a> matched against the message of the check associated with an audit event.
62   * Optional as long as {@code checks} or {@code id} is specified.
63   * </li>
64   * <li>
65   * {@code id} - a <a href="https://checkstyle.org/property-types.html#String">String</a>
66   * matched against the <a href="https://checkstyle.org/config.html#Id">check id</a>
67   * associated with an audit event.
68   * Optional as long as {@code checks} or {@code message} is specified.
69   * </li>
70   * <li>
71   * {@code lines} - a comma-separated list of values, where each value is an
72   * <a href="https://checkstyle.org/property-types.html#int">int</a>
73   * or a range of integers denoted by integer-integer.
74   * It is optional.
75   * </li>
76   * <li>
77   * {@code columns} - a comma-separated list of values, where each value is an
78   * <a href="https://checkstyle.org/property-types.html#int">int</a>
79   * or a range of integers denoted by integer-integer.
80   * It is optional.
81   * </li>
82   * </ul>
83   *
84   * <p>
85   * Each audit event is checked against each {@code suppress} element.
86   * It is suppressed if all specified attributes match against the audit event.
87   * </p>
88   *
89   * <p>
90   * ATTENTION: filtering by message is dependent on runtime locale.
91   * If project is running in different languages it is better to avoid filtering by message.
92   * </p>
93   *
94   * <p>
95   * You can download template of empty suppression filter
96   * <a href="https://checkstyle.org/files/suppressions_none.xml">here</a>.
97   * </p>
98   *
99   * <p>
100  * Location of the file defined in {@code file} property is checked in the following order:
101  * </p>
102  * <ol>
103  * <li>
104  * as a filesystem location
105  * </li>
106  * <li>
107  * if no file found, and the location starts with either {@code http://} or {@code https://},
108  * then it is interpreted as a URL
109  * </li>
110  * <li>
111  * if no file found, then passed to the {@code ClassLoader.getResource()} method.
112  * </li>
113  * </ol>
114  *
115  * <p>
116  * SuppressionFilter can suppress Checks that have Treewalker or Checker as parent module.
117  * </p>
118  *
119  * @since 3.2
120  */
121 public class SuppressionFilter
122         extends AbstractAutomaticBean
123         implements Filter, ExternalResourceHolder {
124 
125     /** Specify the location of the <em>suppressions XML document</em> file. */
126     private String file;
127     /**
128      * Control what to do when the file is not existing. If {@code optional} is
129      * set to {@code false} the file must exist, or else it ends with error.
130      * On the other hand if optional is {@code true} and file is not found,
131      * the filter accept all audit events.
132      */
133     private boolean optional;
134     /** Set of individual suppresses. */
135     private FilterSet filters = new FilterSet();
136 
137     /**
138      * Creates a new {@code SuppressionFilter} instance.
139      */
140     public SuppressionFilter() {
141         // no code by default
142     }
143 
144     /**
145      * Setter to specify the location of the <em>suppressions XML document</em> file.
146      *
147      * @param fileName name of the suppressions file.
148      * @since 3.2
149      */
150     public void setFile(String fileName) {
151         file = fileName;
152     }
153 
154     /**
155      * Setter to control what to do when the file is not existing.
156      * If {@code optional} is set to {@code false} the file must exist, or else
157      * it ends with error. On the other hand if optional is {@code true}
158      * and file is not found, the filter accept all audit events.
159      *
160      * @param optional tells if config file existence is optional.
161      * @since 6.15
162      */
163     public void setOptional(boolean optional) {
164         this.optional = optional;
165     }
166 
167     @Override
168     public boolean accept(AuditEvent event) {
169         return filters.accept(event);
170     }
171 
172     @Override
173     protected void finishLocalSetup() throws CheckstyleException {
174         if (file != null) {
175             if (optional) {
176                 if (FilterUtil.isFileExists(file)) {
177                     filters = SuppressionsLoader.loadSuppressions(file);
178                 }
179             }
180             else {
181                 filters = SuppressionsLoader.loadSuppressions(file);
182             }
183         }
184     }
185 
186     @Override
187     public Set<String> getExternalResourceLocations() {
188         return UnmodifiableCollectionUtil.singleton(file);
189     }
190 
191 }