001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2026 the original author or authors. 004// 005// This library is free software; you can redistribute it and/or 006// modify it under the terms of the GNU Lesser General Public 007// License as published by the Free Software Foundation; either 008// version 2.1 of the License, or (at your option) any later version. 009// 010// This library is distributed in the hope that it will be useful, 011// but WITHOUT ANY WARRANTY; without even the implied warranty of 012// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013// Lesser General Public License for more details. 014// 015// You should have received a copy of the GNU Lesser General Public 016// License along with this library; if not, write to the Free Software 017// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 018/////////////////////////////////////////////////////////////////////////////////////////////// 019 020package com.puppycrawl.tools.checkstyle.filters; 021 022import java.util.Set; 023 024import com.puppycrawl.tools.checkstyle.AbstractAutomaticBean; 025import com.puppycrawl.tools.checkstyle.api.AuditEvent; 026import com.puppycrawl.tools.checkstyle.api.CheckstyleException; 027import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder; 028import com.puppycrawl.tools.checkstyle.api.Filter; 029import com.puppycrawl.tools.checkstyle.api.FilterSet; 030import com.puppycrawl.tools.checkstyle.utils.FilterUtil; 031import com.puppycrawl.tools.checkstyle.utils.UnmodifiableCollectionUtil; 032 033/** 034 * <div> 035 * Filter {@code SuppressionFilter} rejects audit events for Check violations according to a 036 * <a href="https://checkstyle.org/dtds/suppressions_1_2.dtd">suppressions XML document</a> 037 * in a file. If there is no configured suppressions file or the optional is set to true and 038 * suppressions file was not found the Filter accepts all audit events. 039 * </div> 040 * 041 * <p> 042 * Notes: 043 * A <a href="https://checkstyle.org/dtds/suppressions_1_2.dtd">suppressions XML document</a> 044 * contains a set of {@code suppress} elements, where each {@code suppress} 045 * element can have the following attributes: 046 * </p> 047 * <ul> 048 * <li> 049 * {@code files} - a <a href="https://checkstyle.org/property_types.html#Pattern"> 050 * Pattern</a> matched against the file name associated with an audit event. 051 * It is optional. If unmatched, all Unix path separators (/) 052 * are converted to Windows separators (\) and retried. 053 * </li> 054 * <li> 055 * {@code checks} - a <a href="https://checkstyle.org/property_types.html#Pattern"> 056 * Pattern</a> matched against the name of the check associated with an audit event. 057 * Optional as long as {@code id} or {@code message} is specified. 058 * </li> 059 * <li> 060 * {@code message} - a <a href="https://checkstyle.org/property_types.html#Pattern"> 061 * Pattern</a> matched against the message of the check associated with an audit event. 062 * Optional as long as {@code checks} or {@code id} is specified. 063 * </li> 064 * <li> 065 * {@code id} - a <a href="https://checkstyle.org/property_types.html#String">String</a> 066 * matched against the <a href="https://checkstyle.org/config.html#Id">check id</a> 067 * associated with an audit event. 068 * Optional as long as {@code checks} or {@code message} is specified. 069 * </li> 070 * <li> 071 * {@code lines} - a comma-separated list of values, where each value is an 072 * <a href="https://checkstyle.org/property_types.html#int">int</a> 073 * or a range of integers denoted by integer-integer. 074 * It is optional. 075 * </li> 076 * <li> 077 * {@code columns} - a comma-separated list of values, where each value is an 078 * <a href="https://checkstyle.org/property_types.html#int">int</a> 079 * or a range of integers denoted by integer-integer. 080 * It is optional. 081 * </li> 082 * </ul> 083 * 084 * <p> 085 * Each audit event is checked against each {@code suppress} element. 086 * It is suppressed if all specified attributes match against the audit event. 087 * </p> 088 * 089 * <p> 090 * ATTENTION: filtering by message is dependent on runtime locale. 091 * If project is running in different languages it is better to avoid filtering by message. 092 * </p> 093 * 094 * <p> 095 * You can download template of empty suppression filter 096 * <a href="https://checkstyle.org/files/suppressions_none.xml">here</a>. 097 * </p> 098 * 099 * <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 */ 121public 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}