View Javadoc
1   ///////////////////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code and other text files for adherence to a set of rules.
3   // Copyright (C) 2001-2025 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.
52   * </li>
53   * <li>
54   * {@code checks} - a <a href="https://checkstyle.org/property_types.html#Pattern">
55   * Pattern</a> matched against the name of the check associated with an audit event.
56   * Optional as long as {@code id} or {@code message} is specified.
57   * </li>
58   * <li>
59   * {@code message} - a <a href="https://checkstyle.org/property_types.html#Pattern">
60   * Pattern</a> matched against the message of the check associated with an audit event.
61   * Optional as long as {@code checks} or {@code id} is specified.
62   * </li>
63   * <li>
64   * {@code id} - a <a href="https://checkstyle.org/property_types.html#String">String</a>
65   * matched against the <a href="https://checkstyle.org/config.html#Id">check id</a>
66   * associated with an audit event.
67   * Optional as long as {@code checks} or {@code message} is specified.
68   * </li>
69   * <li>
70   * {@code lines} - a comma-separated list of values, where each value is an
71   * <a href="https://checkstyle.org/property_types.html#int">int</a>
72   * or a range of integers denoted by integer-integer.
73   * It is optional.
74   * </li>
75   * <li>
76   * {@code columns} - a comma-separated list of values, where each value is an
77   * <a href="https://checkstyle.org/property_types.html#int">int</a>
78   * or a range of integers denoted by integer-integer.
79   * It is optional.
80   * </li>
81   * </ul>
82   *
83   * <p>
84   * Each audit event is checked against each {@code suppress} element.
85   * It is suppressed if all specified attributes match against the audit event.
86   * </p>
87   *
88   * <p>
89   * ATTENTION: filtering by message is dependent on runtime locale.
90   * If project is running in different languages it is better to avoid filtering by message.
91   * </p>
92   *
93   * <p>
94   * You can download template of empty suppression filter
95   * <a href="https://checkstyle.org/files/suppressions_none.xml">here</a>.
96   * </p>
97   *
98   * <p>
99   * Location of the file defined in {@code file} property is checked in the following order:
100  * </p>
101  * <ol>
102  * <li>
103  * as a filesystem location
104  * </li>
105  * <li>
106  * if no file found, and the location starts with either {@code http://} or {@code https://},
107  * then it is interpreted as a URL
108  * </li>
109  * <li>
110  * if no file found, then passed to the {@code ClassLoader.getResource()} method.
111  * </li>
112  * </ol>
113  *
114  * <p>
115  * SuppressionFilter can suppress Checks that have Treewalker or Checker as parent module.
116  * </p>
117  * <ul>
118  * <li>
119  * Property {@code file} - Specify the location of the <em>suppressions XML document</em> file.
120  * Type is {@code java.lang.String}.
121  * Default value is {@code null}.
122  * </li>
123  * <li>
124  * Property {@code optional} - Control what to do when the file is not existing.
125  * If {@code optional} is set to {@code false} the file must exist, or else it
126  * ends with error. On the other hand if optional is {@code true} and file is
127  * not found, the filter accept all audit events.
128  * Type is {@code boolean}.
129  * Default value is {@code false}.
130  * </li>
131  * </ul>
132  *
133  * <p>
134  * Parent is {@code com.puppycrawl.tools.checkstyle.Checker}
135  * </p>
136  *
137  * @since 3.2
138  */
139 public class SuppressionFilter
140         extends AbstractAutomaticBean
141         implements Filter, ExternalResourceHolder {
142 
143     /** Specify the location of the <em>suppressions XML document</em> file. */
144     private String file;
145     /**
146      * Control what to do when the file is not existing. If {@code optional} is
147      * set to {@code false} the file must exist, or else it ends with error.
148      * On the other hand if optional is {@code true} and file is not found,
149      * the filter accept all audit events.
150      */
151     private boolean optional;
152     /** Set of individual suppresses. */
153     private FilterSet filters = new FilterSet();
154 
155     /**
156      * Setter to specify the location of the <em>suppressions XML document</em> file.
157      *
158      * @param fileName name of the suppressions file.
159      * @since 3.2
160      */
161     public void setFile(String fileName) {
162         file = fileName;
163     }
164 
165     /**
166      * Setter to control what to do when the file is not existing.
167      * If {@code optional} is set to {@code false} the file must exist, or else
168      * it ends with error. On the other hand if optional is {@code true}
169      * and file is not found, the filter accept all audit events.
170      *
171      * @param optional tells if config file existence is optional.
172      * @since 6.15
173      */
174     public void setOptional(boolean optional) {
175         this.optional = optional;
176     }
177 
178     @Override
179     public boolean accept(AuditEvent event) {
180         return filters.accept(event);
181     }
182 
183     @Override
184     protected void finishLocalSetup() throws CheckstyleException {
185         if (file != null) {
186             if (optional) {
187                 if (FilterUtil.isFileExists(file)) {
188                     filters = SuppressionsLoader.loadSuppressions(file);
189                 }
190             }
191             else {
192                 filters = SuppressionsLoader.loadSuppressions(file);
193             }
194         }
195     }
196 
197     @Override
198     public Set<String> getExternalResourceLocations() {
199         return UnmodifiableCollectionUtil.singleton(file);
200     }
201 
202 }