001/////////////////////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code and other text files for adherence to a set of rules. 003// Copyright (C) 2001-2024 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; 021 022import java.io.File; 023import java.io.IOException; 024import java.nio.charset.StandardCharsets; 025import java.util.List; 026import java.util.Locale; 027import java.util.regex.Matcher; 028import java.util.regex.Pattern; 029import java.util.stream.Collectors; 030 031import com.puppycrawl.tools.checkstyle.api.CheckstyleException; 032import com.puppycrawl.tools.checkstyle.api.DetailAST; 033import com.puppycrawl.tools.checkstyle.api.FileText; 034import com.puppycrawl.tools.checkstyle.xpath.XpathQueryGenerator; 035 036/** 037 * Class for constructing xpath queries to suppress nodes 038 * with specified line and column number. 039 */ 040public final class SuppressionsStringPrinter { 041 042 /** Line and column number config value pattern. */ 043 private static final Pattern VALID_SUPPRESSION_LINE_COLUMN_NUMBER_REGEX = 044 Pattern.compile("^(\\d+):(\\d+)$"); 045 046 /** OS specific line separator. */ 047 private static final String LINE_SEPARATOR = System.getProperty("line.separator"); 048 049 /** Prevent instances. */ 050 private SuppressionsStringPrinter() { 051 // no code 052 } 053 054 /** 055 * Prints generated suppressions. 056 * 057 * @param file the file to process. 058 * @param suppressionLineColumnNumber line and column number of the suppression 059 * @param tabWidth length of the tab character 060 * @return generated suppressions. 061 * @throws IOException if the file could not be read. 062 * @throws IllegalStateException if suppressionLineColumnNumber is not of a valid format. 063 * @throws CheckstyleException if the file is not a Java source. 064 */ 065 public static String printSuppressions(File file, String suppressionLineColumnNumber, 066 int tabWidth) throws IOException, CheckstyleException { 067 final Matcher matcher = 068 VALID_SUPPRESSION_LINE_COLUMN_NUMBER_REGEX.matcher(suppressionLineColumnNumber); 069 if (!matcher.matches()) { 070 final String exceptionMsg = String.format(Locale.ROOT, 071 "%s does not match valid format 'line:column'.", 072 suppressionLineColumnNumber); 073 throw new IllegalStateException(exceptionMsg); 074 } 075 076 final FileText fileText = new FileText(file.getAbsoluteFile(), 077 System.getProperty("file.encoding", StandardCharsets.UTF_8.name())); 078 final DetailAST detailAST = 079 JavaParser.parseFileText(fileText, JavaParser.Options.WITH_COMMENTS); 080 final int lineNumber = Integer.parseInt(matcher.group(1)); 081 final int columnNumber = Integer.parseInt(matcher.group(2)); 082 return generate(fileText, detailAST, lineNumber, columnNumber, tabWidth); 083 } 084 085 /** 086 * Creates {@code XpathQueryGenerator} instance and generates suppressions. 087 * 088 * @param fileText {@code FileText} object. 089 * @param detailAST {@code DetailAST} object. 090 * @param lineNumber line number. 091 * @param columnNumber column number. 092 * @param tabWidth length of the tab character. 093 * @return generated suppressions. 094 */ 095 private static String generate(FileText fileText, DetailAST detailAST, int lineNumber, 096 int columnNumber, int tabWidth) { 097 final XpathQueryGenerator queryGenerator = 098 new XpathQueryGenerator(detailAST, lineNumber, columnNumber, fileText, 099 tabWidth); 100 final List<String> suppressions = queryGenerator.generate(); 101 return suppressions.stream().collect(Collectors.joining(LINE_SEPARATOR, 102 "", LINE_SEPARATOR)); 103 } 104}