001//////////////////////////////////////////////////////////////////////////////// 002// checkstyle: Checks Java source code for adherence to a set of rules. 003// Copyright (C) 2001-2020 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("^([0-9]+):([0-9]+)$"); 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 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.getAbsoluteFile(), 076 System.getProperty("file.encoding", StandardCharsets.UTF_8.name())); 077 final DetailAST detailAST = 078 JavaParser.parseFileText(fileText, JavaParser.Options.WITH_COMMENTS); 079 final int lineNumber = Integer.parseInt(matcher.group(1)); 080 final int columnNumber = Integer.parseInt(matcher.group(2)); 081 return generate(fileText, detailAST, lineNumber, columnNumber, tabWidth); 082 } 083 084 /** 085 * Creates {@code XpathQueryGenerator} instance and generates suppressions. 086 * 087 * @param fileText {@code FileText} object. 088 * @param detailAST {@code DetailAST} object. 089 * @param lineNumber line number. 090 * @param columnNumber column number. 091 * @param tabWidth length of the tab character. 092 * @return generated suppressions. 093 */ 094 private static String generate(FileText fileText, DetailAST detailAST, int lineNumber, 095 int columnNumber, int tabWidth) { 096 final XpathQueryGenerator queryGenerator = 097 new XpathQueryGenerator(detailAST, lineNumber, columnNumber, fileText, 098 tabWidth); 099 final List<String> suppressions = queryGenerator.generate(); 100 return suppressions.stream().collect(Collectors.joining(LINE_SEPARATOR, 101 "", LINE_SEPARATOR)); 102 } 103}