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