1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  
17  
18  
19  
20  package com.puppycrawl.tools.checkstyle;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.util.regex.Pattern;
25  
26  import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
27  import com.puppycrawl.tools.checkstyle.api.DetailAST;
28  import com.puppycrawl.tools.checkstyle.api.DetailNode;
29  import com.puppycrawl.tools.checkstyle.api.FileText;
30  import com.puppycrawl.tools.checkstyle.api.TokenTypes;
31  import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
32  import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
33  
34  
35  
36  
37  public final class AstTreeStringPrinter {
38  
39      
40      private static final Pattern NEWLINE = Pattern.compile("\n");
41      
42      private static final Pattern RETURN = Pattern.compile("\r");
43      
44      private static final Pattern TAB = Pattern.compile("\t");
45  
46      
47      private static final String LINE_SEPARATOR = System.lineSeparator();
48  
49      
50      private AstTreeStringPrinter() {
51          
52      }
53  
54      
55  
56  
57  
58  
59  
60  
61  
62  
63      public static String printFileAst(File file, JavaParser.Options options)
64              throws IOException, CheckstyleException {
65          return printTree(JavaParser.parseFile(file, options));
66      }
67  
68      
69  
70  
71  
72  
73  
74  
75  
76      public static String printJavaAndJavadocTree(File file)
77              throws IOException, CheckstyleException {
78          final DetailAST tree = JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS);
79          return printJavaAndJavadocTree(tree);
80      }
81  
82      
83  
84  
85  
86  
87  
88      private static String printJavaAndJavadocTree(DetailAST ast) {
89          final StringBuilder messageBuilder = new StringBuilder(1024);
90          DetailAST node = ast;
91          while (node != null) {
92              messageBuilder.append(getIndentation(node))
93                  .append(getNodeInfo(node))
94                  .append(LINE_SEPARATOR);
95              if (node.getType() == TokenTypes.COMMENT_CONTENT
96                      && JavadocUtil.isJavadocComment(node.getParent())) {
97                  final String javadocTree = parseAndPrintJavadocTree(node);
98                  messageBuilder.append(javadocTree);
99              }
100             else {
101                 messageBuilder.append(printJavaAndJavadocTree(node.getFirstChild()));
102             }
103             node = node.getNextSibling();
104         }
105         return messageBuilder.toString();
106     }
107 
108     
109 
110 
111 
112 
113 
114     private static String parseAndPrintJavadocTree(DetailAST node) {
115         final DetailAST javadocBlock = node.getParent();
116         final DetailNode tree = DetailNodeTreeStringPrinter.parseJavadocAsDetailNode(javadocBlock);
117 
118         String baseIndentation = getIndentation(node);
119         baseIndentation = baseIndentation.substring(0, baseIndentation.length() - 2);
120         final String rootPrefix = baseIndentation + "   `--";
121         final String prefix = baseIndentation + "       ";
122         return DetailNodeTreeStringPrinter.printTree(tree, rootPrefix, prefix);
123     }
124 
125     
126 
127 
128 
129 
130 
131 
132 
133     public static String printAst(FileText text, JavaParser.Options options)
134             throws CheckstyleException {
135         final DetailAST ast = JavaParser.parseFileText(text, options);
136         return printTree(ast);
137     }
138 
139     
140 
141 
142 
143 
144 
145     public static String printBranch(DetailAST node) {
146         final String result;
147         if (node == null) {
148             result = "";
149         }
150         else {
151             result = printBranch(node.getParent())
152                 + getIndentation(node)
153                 + getNodeInfo(node)
154                 + LINE_SEPARATOR;
155         }
156         return result;
157     }
158 
159     
160 
161 
162 
163 
164 
165     private static String printTree(DetailAST ast) {
166         final StringBuilder messageBuilder = new StringBuilder(1024);
167         DetailAST node = ast;
168         while (node != null) {
169             messageBuilder.append(getIndentation(node))
170                     .append(getNodeInfo(node))
171                     .append(LINE_SEPARATOR)
172                     .append(printTree(node.getFirstChild()));
173             node = node.getNextSibling();
174         }
175         return messageBuilder.toString();
176     }
177 
178     
179 
180 
181 
182 
183 
184 
185     private static String getNodeInfo(DetailAST node) {
186         return TokenUtil.getTokenName(node.getType())
187                 + " -> " + escapeAllControlChars(node.getText())
188                 + " [" + node.getLineNo() + ':' + node.getColumnNo() + ']';
189     }
190 
191     
192 
193 
194 
195 
196 
197     private static String getIndentation(DetailAST ast) {
198         final boolean isLastChild = ast.getNextSibling() == null;
199         DetailAST node = ast;
200         final StringBuilder indentation = new StringBuilder(1024);
201         while (node.getParent() != null) {
202             node = node.getParent();
203             if (node.getParent() == null) {
204                 if (isLastChild) {
205                     
206                     
207                     indentation.append("`--");
208                 }
209                 else {
210                     indentation.append("|--");
211                 }
212             }
213             else {
214                 if (node.getNextSibling() == null) {
215                     indentation.insert(0, "    ");
216                 }
217                 else {
218                     indentation.insert(0, "|   ");
219                 }
220             }
221         }
222         return indentation.toString();
223     }
224 
225     
226 
227 
228 
229 
230 
231     private static String escapeAllControlChars(String text) {
232         final String textWithoutNewlines = NEWLINE.matcher(text).replaceAll("\\\\n");
233         final String textWithoutReturns = RETURN.matcher(textWithoutNewlines).replaceAll("\\\\r");
234         return TAB.matcher(textWithoutReturns).replaceAll("\\\\t");
235     }
236 
237 }