1   ////////////////////////////////////////////////////////////////////////////////
2   // checkstyle: Checks Java source code for adherence to a set of rules.
3   // Copyright (C) 2001-2019 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 static com.puppycrawl.tools.checkstyle.checks.whitespace.FileTabCharacterCheck.MSG_CONTAINS_TAB;
23  import static com.puppycrawl.tools.checkstyle.checks.whitespace.FileTabCharacterCheck.MSG_FILE_CONTAINS_TAB;
24  import static org.junit.Assert.assertEquals;
25  import static org.junit.Assert.assertTrue;
26  import static org.junit.Assert.fail;
27  
28  import java.io.FileNotFoundException;
29  import java.io.IOException;
30  import java.util.Arrays;
31  import java.util.Collection;
32  import java.util.stream.Collectors;
33  
34  import org.junit.Assert;
35  import org.junit.Test;
36  
37  import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
38  import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
39  import com.puppycrawl.tools.checkstyle.api.AuditEvent;
40  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
41  import com.puppycrawl.tools.checkstyle.api.Configuration;
42  import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
43  import com.puppycrawl.tools.checkstyle.api.SeverityLevel;
44  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
45  import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineCheck;
46  import com.puppycrawl.tools.checkstyle.checks.whitespace.FileTabCharacterCheck;
47  import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
48  import nl.jqno.equalsverifier.EqualsVerifier;
49  import nl.jqno.equalsverifier.EqualsVerifierReport;
50  
51  public class SuppressWithPlainTextCommentFilterTest extends AbstractModuleTestSupport {
52  
53      private static final String MSG_REGEXP_EXCEEDED = "regexp.exceeded";
54  
55      @Override
56      protected String getPackageLocation() {
57          return "com/puppycrawl/tools/checkstyle/filters/suppresswithplaintextcommentfilter";
58      }
59  
60      @Test
61      public void testFilterWithDefaultConfig() throws Exception {
62          final DefaultConfiguration filterCfg =
63              createModuleConfig(SuppressWithPlainTextCommentFilter.class);
64  
65          final DefaultConfiguration checkCfg = createModuleConfig(FileTabCharacterCheck.class);
66          checkCfg.addAttribute("eachLine", "true");
67  
68          final String[] suppressed = {
69              "5:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_FILE_CONTAINS_TAB),
70              "10:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
71          };
72  
73          final String[] violationMessages = {
74              "5:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_FILE_CONTAINS_TAB),
75              "8:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
76              "10:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
77          };
78  
79          verifySuppressed(
80              "InputSuppressWithPlainTextCommentFilterWithDefaultCfg.java",
81              removeSuppressed(violationMessages, suppressed),
82              filterCfg, checkCfg
83          );
84      }
85  
86      @Test
87      public void testChangeOffAndOnFormat() throws Exception {
88          final DefaultConfiguration filterCfg =
89              createModuleConfig(SuppressWithPlainTextCommentFilter.class);
90          filterCfg.addAttribute("onCommentFormat", "cs-on");
91          filterCfg.addAttribute("offCommentFormat", "cs-off");
92  
93          final DefaultConfiguration checkCfg = createModuleConfig(FileTabCharacterCheck.class);
94          checkCfg.addAttribute("eachLine", "true");
95  
96          final String[] suppressed = {
97              "5:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_FILE_CONTAINS_TAB),
98              "10:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
99              "11:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
100             "13:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
101         };
102 
103         final String[] violationMessage = {
104             "5:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_FILE_CONTAINS_TAB),
105             "8:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
106             "10:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
107             "11:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
108         };
109 
110         verifySuppressed(
111             "InputSuppressWithPlainTextCommentFilterWithCustomOnAndOffComments.java",
112             removeSuppressed(violationMessage, suppressed),
113             filterCfg, checkCfg
114         );
115     }
116 
117     @Test
118     public void testSuppressionCommentsInXmlFile() throws Exception {
119         final DefaultConfiguration filterCfg =
120             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
121         filterCfg.addAttribute("offCommentFormat", "CS-OFF");
122         filterCfg.addAttribute("onCommentFormat", "CS-ON");
123 
124         final DefaultConfiguration checkCfg = createModuleConfig(FileTabCharacterCheck.class);
125         checkCfg.addAttribute("eachLine", "true");
126 
127         final String[] suppressed = {
128             "7:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
129         };
130 
131         final String[] violationMessages = {
132             "7:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
133             "10:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
134         };
135 
136         verifySuppressed(
137             "InputSuppressWithPlainTextCommentFilter.xml",
138             removeSuppressed(violationMessages, suppressed),
139             filterCfg, checkCfg
140         );
141     }
142 
143     @Test
144     public void testSuppressionCommentsInPropertiesFile() throws Exception {
145         final DefaultConfiguration filterCfg =
146             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
147         filterCfg.addAttribute("offCommentFormat", "# CHECKSTYLE:OFF");
148         filterCfg.addAttribute("onCommentFormat", "# CHECKSTYLE:ON");
149 
150         final DefaultConfiguration checkCfg = createModuleConfig(RegexpSinglelineCheck.class);
151         checkCfg.addAttribute("format", "^key[0-9]=$");
152 
153         final String[] suppressed = {
154             "2: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
155                 "^key[0-9]=$"),
156         };
157 
158         final String[] violationMessages = {
159             "2: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
160                 "^key[0-9]=$"),
161             "4: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
162                 "^key[0-9]=$"),
163         };
164 
165         verifySuppressed(
166             "InputSuppressWithPlainTextCommentFilter.properties",
167             removeSuppressed(violationMessages, suppressed),
168             filterCfg, checkCfg
169         );
170     }
171 
172     @Test
173     public void testSuppressionCommentsInSqlFile() throws Exception {
174         final DefaultConfiguration filterCfg =
175             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
176         filterCfg.addAttribute("offCommentFormat", "-- CHECKSTYLE OFF");
177         filterCfg.addAttribute("onCommentFormat", "-- CHECKSTYLE ON");
178 
179         final DefaultConfiguration checkCfg = createModuleConfig(FileTabCharacterCheck.class);
180         checkCfg.addAttribute("eachLine", "true");
181 
182         final String[] suppressed = {
183             "2:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
184         };
185 
186         final String[] violationMessages = {
187             "2:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
188             "5:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
189         };
190 
191         verifySuppressed(
192             "InputSuppressWithPlainTextCommentFilter.sql",
193             removeSuppressed(violationMessages, suppressed),
194             filterCfg, checkCfg
195         );
196     }
197 
198     @Test
199     public void testSuppressionCommentsInJavaScriptFile() throws Exception {
200         final DefaultConfiguration filterCfg =
201             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
202         filterCfg.addAttribute("offCommentFormat", "// CS-OFF");
203         filterCfg.addAttribute("onCommentFormat", "// CS-ON");
204 
205         final DefaultConfiguration checkCfg = createModuleConfig(RegexpSinglelineCheck.class);
206         checkCfg.addAttribute("format", ".*===.*");
207 
208         final String[] suppressed = {
209             "2: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED, ".*===.*"),
210         };
211 
212         final String[] violationMessages = {
213             "2: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED, ".*===.*"),
214             "5: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED, ".*===.*"),
215         };
216 
217         verifySuppressed(
218             "InputSuppressWithPlainTextCommentFilter.js",
219             removeSuppressed(violationMessages, suppressed),
220             filterCfg, checkCfg
221         );
222     }
223 
224     @Test
225     public void testInvalidCheckFormat() throws Exception {
226         final DefaultConfiguration filterCfg =
227             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
228         filterCfg.addAttribute("checkFormat", "e[l");
229         filterCfg.addAttribute("onCommentFormat", "// cs-on");
230         filterCfg.addAttribute("offCommentFormat", "// cs-off");
231 
232         final DefaultConfiguration checkCfg = createModuleConfig(FileTabCharacterCheck.class);
233         checkCfg.addAttribute("eachLine", "true");
234 
235         final String[] suppressed = CommonUtil.EMPTY_STRING_ARRAY;
236 
237         final String[] violationMessages = {
238             "5:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_FILE_CONTAINS_TAB),
239             "8:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
240             "10:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
241         };
242 
243         try {
244             verifySuppressed(
245                 "InputSuppressWithPlainTextCommentFilterWithCustomOnAndOffComments.java",
246                 removeSuppressed(violationMessages, suppressed),
247                 filterCfg, checkCfg
248             );
249             fail("CheckstyleException is expected");
250         }
251         catch (CheckstyleException ex) {
252             final IllegalArgumentException cause = (IllegalArgumentException) ex.getCause();
253             assertEquals("Invalid exception message",
254                 "unable to parse expanded comment e[l", cause.getMessage());
255         }
256     }
257 
258     @Test
259     public void testInvalidMessageFormat() throws Exception {
260         final DefaultConfiguration filterCfg =
261             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
262         filterCfg.addAttribute("messageFormat", "e[l");
263         filterCfg.addAttribute("onCommentFormat", "// cs-on");
264         filterCfg.addAttribute("offCommentFormat", "// cs-off");
265 
266         final DefaultConfiguration checkCfg = createModuleConfig(FileTabCharacterCheck.class);
267         checkCfg.addAttribute("eachLine", "true");
268 
269         final String[] suppressed = CommonUtil.EMPTY_STRING_ARRAY;
270 
271         final String[] violationMessages = {
272             "5:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_FILE_CONTAINS_TAB),
273             "8:7: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
274             "10:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
275         };
276 
277         try {
278             verifySuppressed(
279                 "InputSuppressWithPlainTextCommentFilterWithCustomOnAndOffComments.java",
280                 removeSuppressed(violationMessages, suppressed),
281                 filterCfg, checkCfg
282             );
283             fail("CheckstyleException is expected");
284         }
285         catch (CheckstyleException ex) {
286             final IllegalArgumentException cause = (IllegalArgumentException) ex.getCause();
287             assertEquals("Invalid exception message",
288                 "unable to parse expanded comment e[l", cause.getMessage());
289         }
290     }
291 
292     @Test
293     public void testAcceptNullLocalizedMessage() {
294         final SuppressWithPlainTextCommentFilter filter = new SuppressWithPlainTextCommentFilter();
295         final AuditEvent auditEvent = new AuditEvent(this);
296         assertTrue("Filter should accept audit event", filter.accept(auditEvent));
297         Assert.assertNull("File name should not be null", auditEvent.getFileName());
298     }
299 
300     @Test
301     public void testEqualsAndHashCodeOfTagClass() {
302         final EqualsVerifierReport ev = EqualsVerifier
303                 .forClass(SuppressWithPlainTextCommentFilter.Suppression.class).usingGetClass()
304                 .report();
305         assertEquals("Error: " + ev.getMessage(), EqualsVerifierReport.SUCCESS, ev);
306     }
307 
308     @Test
309     public void testSuppressByModuleId() throws Exception {
310         final DefaultConfiguration filterCfg =
311             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
312         filterCfg.addAttribute("offCommentFormat", "CSOFF (\\w+) \\(\\w+\\)");
313         filterCfg.addAttribute("onCommentFormat", "CSON (\\w+)");
314         filterCfg.addAttribute("checkFormat", "$1");
315 
316         final DefaultConfiguration regexpCheckCfg = createModuleConfig(RegexpSinglelineCheck.class);
317         regexpCheckCfg.addAttribute("id", "ignore");
318         regexpCheckCfg.addAttribute("format", ".*[a-zA-Z][0-9].*");
319 
320         final DefaultConfiguration fileTabCheckCfg =
321             createModuleConfig(FileTabCharacterCheck.class);
322         fileTabCheckCfg.addAttribute("eachLine", "true");
323         fileTabCheckCfg.addAttribute("id", "foo");
324 
325         final String[] suppressedViolationMessages = {
326             "6: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
327                 ".*[a-zA-Z][0-9].*"),
328             "9: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
329                 ".*[a-zA-Z][0-9].*"),
330             "11: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
331                 ".*[a-zA-Z][0-9].*"),
332         };
333 
334         final String[] expectedViolationMessages = {
335             "6: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
336                 ".*[a-zA-Z][0-9].*"),
337             "9:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
338             "9: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
339                 ".*[a-zA-Z][0-9].*"),
340             "11: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
341                 ".*[a-zA-Z][0-9].*"),
342             "14: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
343                 ".*[a-zA-Z][0-9].*"),
344         };
345 
346         verifySuppressed(
347             "InputSuppressWithPlainTextCommentFilterSuppressById.java",
348             removeSuppressed(expectedViolationMessages, suppressedViolationMessages),
349             filterCfg, regexpCheckCfg, fileTabCheckCfg
350         );
351     }
352 
353     @Test
354     public void testSuppressByModuleIdWithNullModuleId() throws Exception {
355         final DefaultConfiguration filterCfg =
356             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
357         filterCfg.addAttribute("offCommentFormat", "CSOFF (\\w+) \\(\\w+\\)");
358         filterCfg.addAttribute("onCommentFormat", "CSON (\\w+)");
359         filterCfg.addAttribute("checkFormat", "$1");
360 
361         final DefaultConfiguration regexpCheckCfg = createModuleConfig(RegexpSinglelineCheck.class);
362         regexpCheckCfg.addAttribute("id", "ignore");
363         regexpCheckCfg.addAttribute("format", ".*[a-zA-Z][0-9].*");
364 
365         final DefaultConfiguration fileTabCheckCfg =
366             createModuleConfig(FileTabCharacterCheck.class);
367         fileTabCheckCfg.addAttribute("eachLine", "true");
368         fileTabCheckCfg.addAttribute("id", null);
369 
370         final String[] suppressedViolationMessages = {
371             "6: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
372                 ".*[a-zA-Z][0-9].*"),
373             "9: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
374                 ".*[a-zA-Z][0-9].*"),
375             "11: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
376                 ".*[a-zA-Z][0-9].*"),
377             };
378 
379         final String[] expectedViolationMessages = {
380             "6: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
381                 ".*[a-zA-Z][0-9].*"),
382             "9:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
383             "9: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
384                 ".*[a-zA-Z][0-9].*"),
385             "11: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
386                 ".*[a-zA-Z][0-9].*"),
387             "14: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
388                 ".*[a-zA-Z][0-9].*"),
389         };
390 
391         verifySuppressed(
392             "InputSuppressWithPlainTextCommentFilterSuppressById.java",
393             removeSuppressed(expectedViolationMessages, suppressedViolationMessages),
394             filterCfg, regexpCheckCfg, fileTabCheckCfg
395         );
396     }
397 
398     @Test
399     public void testAcceptThrowsIllegalStateExceptionAsFileNotFound() {
400         final LocalizedMessage message = new LocalizedMessage(1, 1, 1, TokenTypes.CLASS_DEF,
401             "messages.properties", "key", null, SeverityLevel.ERROR, null, getClass(), null);
402         final String fileName = "nonexisting_file";
403         final AuditEvent auditEvent = new AuditEvent(this, fileName, message);
404 
405         final SuppressWithPlainTextCommentFilter filter = new SuppressWithPlainTextCommentFilter();
406 
407         try {
408             filter.accept(auditEvent);
409             fail(IllegalStateException.class.getSimpleName() + " is expected");
410         }
411         catch (IllegalStateException ex) {
412             assertEquals("Invalid exception message",
413                 "Cannot read source file: " + fileName, ex.getMessage());
414 
415             final Throwable cause = ex.getCause();
416             assertTrue("Exception cause has invalid type",
417                 cause instanceof FileNotFoundException);
418             assertEquals("Invalid exception message",
419                 fileName + " (No such file or directory)", cause.getMessage());
420         }
421     }
422 
423     @Test
424     public void testFilterWithCustomMessageFormat() throws Exception {
425         final DefaultConfiguration filterCfg =
426             createModuleConfig(SuppressWithPlainTextCommentFilter.class);
427         final String messageFormat =
428             ".*" + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB) + ".*";
429         // -@cs[CheckstyleTestMakeup] need to test dynamic property
430         filterCfg.addAttribute("messageFormat", messageFormat);
431 
432         final DefaultConfiguration fileTabCheckCfg =
433             createModuleConfig(FileTabCharacterCheck.class);
434         fileTabCheckCfg.addAttribute("eachLine", "true");
435 
436         final DefaultConfiguration regexpCheckCfg = createModuleConfig(RegexpSinglelineCheck.class);
437         regexpCheckCfg.addAttribute("id", "ignore");
438         regexpCheckCfg.addAttribute("format", ".*[a-zA-Z][0-9].*");
439 
440         final String[] suppressed = {
441             "8:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
442         };
443 
444         final String[] violationMessages = {
445             "6: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
446                 ".*[a-zA-Z][0-9].*"),
447             "8:1: " + getCheckMessage(FileTabCharacterCheck.class, MSG_CONTAINS_TAB),
448             "8: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
449                 ".*[a-zA-Z][0-9].*"),
450             "10: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
451                 ".*[a-zA-Z][0-9].*"),
452             "13: " + getCheckMessage(RegexpSinglelineCheck.class, MSG_REGEXP_EXCEEDED,
453                 ".*[a-zA-Z][0-9].*"),
454         };
455 
456         verifySuppressed(
457             "InputSuppressWithPlainTextCommentFilterCustomMessageFormat.java",
458             removeSuppressed(violationMessages, suppressed),
459             filterCfg, fileTabCheckCfg, regexpCheckCfg
460         );
461     }
462 
463     @Test
464     public void testFilterWithDirectory() throws IOException {
465         final SuppressWithPlainTextCommentFilter filter = new SuppressWithPlainTextCommentFilter();
466         final AuditEvent event = new AuditEvent(this, getPath(""), new LocalizedMessage(1, 1,
467                 "bundle", "key", null, SeverityLevel.ERROR, "moduleId", getClass(),
468                 "customMessage"));
469 
470         assertTrue("filter should accept directory", filter.accept(event));
471     }
472 
473     private void verifySuppressed(String fileNameWithExtension, String[] violationMessages,
474                                   Configuration... childConfigs) throws Exception {
475         final DefaultConfiguration checkerConfig = createRootConfig(null);
476 
477         Arrays.stream(childConfigs).forEach(checkerConfig::addChild);
478 
479         final String fileExtension = CommonUtil.getFileExtension(fileNameWithExtension);
480         checkerConfig.addAttribute("fileExtensions", fileExtension);
481 
482         verify(checkerConfig, getPath(fileNameWithExtension), violationMessages);
483     }
484 
485     private static String[] removeSuppressed(String[] from, String... remove) {
486         final Collection<String> coll = Arrays.stream(from).collect(Collectors.toList());
487         coll.removeAll(Arrays.asList(remove));
488         return coll.toArray(CommonUtil.EMPTY_STRING_ARRAY);
489     }
490 
491 }