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 * 118 * @since 3.2 119 */ 120 public class SuppressionFilter 121 extends AbstractAutomaticBean 122 implements Filter, ExternalResourceHolder { 123 124 /** Specify the location of the <em>suppressions XML document</em> file. */ 125 private String file; 126 /** 127 * Control what to do when the file is not existing. If {@code optional} is 128 * set to {@code false} the file must exist, or else it ends with error. 129 * On the other hand if optional is {@code true} and file is not found, 130 * the filter accept all audit events. 131 */ 132 private boolean optional; 133 /** Set of individual suppresses. */ 134 private FilterSet filters = new FilterSet(); 135 136 /** 137 * Setter to specify the location of the <em>suppressions XML document</em> file. 138 * 139 * @param fileName name of the suppressions file. 140 * @since 3.2 141 */ 142 public void setFile(String fileName) { 143 file = fileName; 144 } 145 146 /** 147 * Setter to control what to do when the file is not existing. 148 * If {@code optional} is set to {@code false} the file must exist, or else 149 * it ends with error. On the other hand if optional is {@code true} 150 * and file is not found, the filter accept all audit events. 151 * 152 * @param optional tells if config file existence is optional. 153 * @since 6.15 154 */ 155 public void setOptional(boolean optional) { 156 this.optional = optional; 157 } 158 159 @Override 160 public boolean accept(AuditEvent event) { 161 return filters.accept(event); 162 } 163 164 @Override 165 protected void finishLocalSetup() throws CheckstyleException { 166 if (file != null) { 167 if (optional) { 168 if (FilterUtil.isFileExists(file)) { 169 filters = SuppressionsLoader.loadSuppressions(file); 170 } 171 } 172 else { 173 filters = SuppressionsLoader.loadSuppressions(file); 174 } 175 } 176 } 177 178 @Override 179 public Set<String> getExternalResourceLocations() { 180 return UnmodifiableCollectionUtil.singleton(file); 181 } 182 183 }