Skip to content

Commit

Permalink
Issue checkstyle#11604: allow 3rd party checks to print their own cus…
Browse files Browse the repository at this point in the history
…tom asts
  • Loading branch information
rnveach committed Dec 8, 2022
1 parent bef49ae commit 15c40ac
Show file tree
Hide file tree
Showing 14 changed files with 208 additions and 60 deletions.
5 changes: 2 additions & 3 deletions config/pmd.xml
Original file line number Diff line number Diff line change
Expand Up @@ -354,10 +354,9 @@
<rule ref="category/java/design.xml/CognitiveComplexity">
<properties>
<property name="reportLevel" value="22"/>
<!-- Till https://github.com/checkstyle/checkstyle/issues/10064 -->
<property name="violationSuppressXPath"
value="//ClassOrInterfaceDeclaration[@SimpleName='XdocsPagesTest']
//MethodDeclaration[@Name='getModulePropertyExpectedValue']"/>
value="//ClassOrInterfaceDeclaration[@SimpleName='Main']
//MethodDeclaration[@Name='runCli']"/>
</properties>
</rule>

Expand Down
2 changes: 1 addition & 1 deletion config/suppressions.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@
|AbstractCheckTest)\.java"/>
<suppress checks="ClassDataAbstractionCoupling"
files="XpathFileGeneratorAuditListenerTest\.java"/>
<suppress checks="ClassFanOutComplexity" files="[\\/]Main\.java"/>
<suppress checks="ClassFanOutComplexity|CyclomaticComplexity" files="[\\/]Main\.java"/>
<suppress checks="ClassFanOutComplexity" files="CheckerTest\.java"/>
<suppress checks="ClassFanOutComplexity" files="Checker\.java"/>
<suppress checks="ClassFanOutComplexity" files="XdocsPagesTest\.java"/>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
// Copyright (C) 2001-2022 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
///////////////////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle;

import java.io.File;
import java.io.IOException;

import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.TreeStringPrinter;

/**
* Class for printing AST combined with DetailNode to String.
*/
public class AstAndDetailNodeTreeStringPrinter implements TreeStringPrinter {

@Override
public String printFileAst(File file) throws IOException, CheckstyleException {
return AstTreeStringPrinter.printJavaAndJavadocTree(file);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@
import com.puppycrawl.tools.checkstyle.api.DetailNode;
import com.puppycrawl.tools.checkstyle.api.FileText;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.api.TreeStringPrinter;
import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
import com.puppycrawl.tools.checkstyle.utils.TokenUtil;

/**
* Class for printing AST to String.
*/
public final class AstTreeStringPrinter {
public final class AstTreeStringPrinter implements TreeStringPrinter {

/** Newline pattern. */
private static final Pattern NEWLINE = Pattern.compile("\n");
Expand All @@ -46,9 +47,9 @@ public final class AstTreeStringPrinter {
/** OS specific line separator. */
private static final String LINE_SEPARATOR = System.lineSeparator();

/** Prevent instances. */
private AstTreeStringPrinter() {
// no code
@Override
public String printFileAst(File file) throws IOException, CheckstyleException {
return printFileAst(file, JavaParser.Options.WITHOUT_COMMENTS);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
// Copyright (C) 2001-2022 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
///////////////////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle;

import java.io.File;
import java.io.IOException;

import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.TreeStringPrinter;

/**
* Class for printing AST with Comments to String.
*/
public class AstWithCommentsTreeStringPrinter implements TreeStringPrinter {

@Override
public String printFileAst(File file) throws IOException, CheckstyleException {
return AstTreeStringPrinter.printFileAst(file, JavaParser.Options.WITH_COMMENTS);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,21 @@
import com.puppycrawl.tools.checkstyle.api.DetailNode;
import com.puppycrawl.tools.checkstyle.api.FileText;
import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes;
import com.puppycrawl.tools.checkstyle.api.TreeStringPrinter;
import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
import com.puppycrawl.tools.checkstyle.utils.ParserUtil;

/**
* Parses file as javadoc DetailNode tree and prints to system output stream.
*/
public final class DetailNodeTreeStringPrinter {
public final class DetailNodeTreeStringPrinter implements TreeStringPrinter {

/** OS specific line separator. */
private static final String LINE_SEPARATOR = System.getProperty("line.separator");

/** Prevent instances. */
private DetailNodeTreeStringPrinter() {
// no code
@Override
public String printFileAst(File file) throws IOException {
return printFileAstEx(file);
}

/**
Expand All @@ -52,7 +53,7 @@ private DetailNodeTreeStringPrinter() {
* @return parse tree as a string
* @throws IOException if the file could not be read.
*/
public static String printFileAst(File file) throws IOException {
public static String printFileAstEx(File file) throws IOException {
return printTree(parseFile(file), "", "");
}

Expand Down
66 changes: 47 additions & 19 deletions src/main/java/com/puppycrawl/tools/checkstyle/Main.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
Expand All @@ -48,6 +49,7 @@
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.RootModule;
import com.puppycrawl.tools.checkstyle.api.TreeStringPrinter;
import com.puppycrawl.tools.checkstyle.utils.ChainedPropertyUtil;
import com.puppycrawl.tools.checkstyle.utils.CommonUtil;
import com.puppycrawl.tools.checkstyle.utils.XpathUtil;
Expand Down Expand Up @@ -286,31 +288,29 @@ private static int runCli(CliOptions options, List<File> filesToProcess)

// create config helper object
if (options.printAst) {
// print AST
final File file = filesToProcess.get(0);
final String stringAst = AstTreeStringPrinter.printFileAst(file,
JavaParser.Options.WITHOUT_COMMENTS);
System.out.print(stringAst);
}
else if (Objects.nonNull(options.xpath)) {
final String branch = XpathUtil.printXpathBranch(options.xpath, filesToProcess.get(0));
System.out.print(branch);
callTreeStringPrinter(filesToProcess.get(0), AstTreeStringPrinter.class);
}
else if (options.printAstWithComments) {
final File file = filesToProcess.get(0);
final String stringAst = AstTreeStringPrinter.printFileAst(file,
JavaParser.Options.WITH_COMMENTS);
System.out.print(stringAst);
callTreeStringPrinter(filesToProcess.get(0), AstWithCommentsTreeStringPrinter.class);
}
else if (options.printJavadocTree) {
final File file = filesToProcess.get(0);
final String stringAst = DetailNodeTreeStringPrinter.printFileAst(file);
System.out.print(stringAst);
callTreeStringPrinter(filesToProcess.get(0), DetailNodeTreeStringPrinter.class);
}
else if (options.printTreeWithJavadoc) {
final File file = filesToProcess.get(0);
final String stringAst = AstTreeStringPrinter.printJavaAndJavadocTree(file);
System.out.print(stringAst);
callTreeStringPrinter(filesToProcess.get(0), AstAndDetailNodeTreeStringPrinter.class);
}
else if (Objects.nonNull(options.customTreePrinterClass)) {
try {
callTreeStringPrinter(filesToProcess.get(0),
Class.forName(options.customTreePrinterClass));
}
catch (ClassNotFoundException | IOException | CheckstyleException ex) {
throw new CheckstyleException("", ex);
}
}
else if (Objects.nonNull(options.xpath)) {
final String branch = XpathUtil.printXpathBranch(options.xpath, filesToProcess.get(0));
System.out.print(branch);
}
else if (hasSuppressionLineColumnNumber) {
final File file = filesToProcess.get(0);
Expand Down Expand Up @@ -341,6 +341,29 @@ else if (hasSuppressionLineColumnNumber) {
return result;
}

/**
* Calls the {@link TreeStringPrinter} class's method with the provided file.
*
* @param file The file to parse.
* @param clss The custom implementation of {@link TreeStringPrinter} to use for printing.
* @throws IOException Failed to open a file
* @throws CheckstyleException error while parsing the file
*/
private static void callTreeStringPrinter(File file, Class<?> clss)
throws IOException, CheckstyleException {
final String output;
try {
output = ((TreeStringPrinter) clss.getDeclaredConstructor().newInstance())
.printFileAst(file);
}
catch (NoSuchMethodException | InvocationTargetException | InstantiationException
| IllegalAccessException ex) {
throw new CheckstyleException("", ex);
}

System.out.print(output);
}

/**
* Executes required Checkstyle actions based on passed parameters.
*
Expand Down Expand Up @@ -754,6 +777,11 @@ private static class CliOptions {
+ "be specified.")
private boolean printTreeWithJavadoc;

/** Option that controls whether to print the custom AST of the file. */
@Option(names = {"-pc", "--printWithCustomTree"},
description = "Prints Tree based on the provided custom class.")
private String customTreePrinterClass;

/** Option that controls whether to print debug info. */
@Option(names = {"-d", "--debug"},
description = "Prints all debug logging of CheckStyle utility.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
///////////////////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code and other text files for adherence to a set of rules.
// Copyright (C) 2001-2022 the original author or authors.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
///////////////////////////////////////////////////////////////////////////////////////////////

package com.puppycrawl.tools.checkstyle.api;

import java.io.File;
import java.io.IOException;

/**
* Interface for printing ASTs to String.
*/
public interface TreeStringPrinter {

/**
* Prints AST of the provided file.
*
* @param file the file to parse.
* @return Full tree
* @throws IOException Failed to open a file
* @throws CheckstyleException error while parsing the file
*/
String printFileAst(File file) throws IOException, CheckstyleException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ protected static void verifyJavadocTree(String expectedTextPrintFilename,
String actualJavadocFilename) throws Exception {
final String expectedContents = readFile(expectedTextPrintFilename);

final String actualContents = toLfLineEnding(DetailNodeTreeStringPrinter.printFileAst(
final String actualContents = toLfLineEnding(DetailNodeTreeStringPrinter.printFileAstEx(
new File(actualJavadocFilename)));

assertWithMessage("Generated tree from the javadoc file should match the pre-defined tree")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
package com.puppycrawl.tools.checkstyle;

import static com.google.common.truth.Truth.assertWithMessage;
import static com.puppycrawl.tools.checkstyle.internal.utils.TestUtil.isUtilsClassHasPrivateConstructor;

import java.io.File;
import java.nio.charset.StandardCharsets;
Expand All @@ -41,13 +40,6 @@ protected String getPackageLocation() {
return "com/puppycrawl/tools/checkstyle/asttreestringprinter";
}

@Test
public void testIsProperUtilsClass() throws ReflectiveOperationException {
assertWithMessage("Constructor is not private")
.that(isUtilsClassHasPrivateConstructor(AstTreeStringPrinter.class))
.isTrue();
}

@Test
public void testParseFileThrowable() throws Exception {
final File input = new File(getNonCompilablePath("InputAstTreeStringPrinter.java"));
Expand Down

0 comments on commit 15c40ac

Please sign in to comment.