/******************************************************************************* * Copyright (c) 2014 Jeff Martin. * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html * * Contributors: * Jeff Martin - initial API and implementation ******************************************************************************/ package cuchaz.enigma.analysis; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.Writer; import com.strobel.componentmodel.Key; import com.strobel.decompiler.languages.java.ast.Annotation; import com.strobel.decompiler.languages.java.ast.AnonymousObjectCreationExpression; import com.strobel.decompiler.languages.java.ast.ArrayCreationExpression; import com.strobel.decompiler.languages.java.ast.ArrayInitializerExpression; import com.strobel.decompiler.languages.java.ast.ArraySpecifier; import com.strobel.decompiler.languages.java.ast.AssertStatement; import com.strobel.decompiler.languages.java.ast.AssignmentExpression; import com.strobel.decompiler.languages.java.ast.AstNode; import com.strobel.decompiler.languages.java.ast.BinaryOperatorExpression; import com.strobel.decompiler.languages.java.ast.BlockStatement; import com.strobel.decompiler.languages.java.ast.BreakStatement; import com.strobel.decompiler.languages.java.ast.CaseLabel; import com.strobel.decompiler.languages.java.ast.CastExpression; import com.strobel.decompiler.languages.java.ast.CatchClause; import com.strobel.decompiler.languages.java.ast.ClassOfExpression; import com.strobel.decompiler.languages.java.ast.Comment; import com.strobel.decompiler.languages.java.ast.CompilationUnit; import com.strobel.decompiler.languages.java.ast.ComposedType; import com.strobel.decompiler.languages.java.ast.ConditionalExpression; import com.strobel.decompiler.languages.java.ast.ConstructorDeclaration; import com.strobel.decompiler.languages.java.ast.ContinueStatement; import com.strobel.decompiler.languages.java.ast.DoWhileStatement; import com.strobel.decompiler.languages.java.ast.EmptyStatement; import com.strobel.decompiler.languages.java.ast.EnumValueDeclaration; import com.strobel.decompiler.languages.java.ast.ExpressionStatement; import com.strobel.decompiler.languages.java.ast.FieldDeclaration; import com.strobel.decompiler.languages.java.ast.ForEachStatement; import com.strobel.decompiler.languages.java.ast.ForStatement; import com.strobel.decompiler.languages.java.ast.GotoStatement; import com.strobel.decompiler.languages.java.ast.IAstVisitor; import com.strobel.decompiler.languages.java.ast.Identifier; import com.strobel.decompiler.languages.java.ast.IdentifierExpression; import com.strobel.decompiler.languages.java.ast.IfElseStatement; import com.strobel.decompiler.languages.java.ast.ImportDeclaration; import com.strobel.decompiler.languages.java.ast.IndexerExpression; import com.strobel.decompiler.languages.java.ast.InstanceInitializer; import com.strobel.decompiler.languages.java.ast.InstanceOfExpression; import com.strobel.decompiler.languages.java.ast.InvocationExpression; import com.strobel.decompiler.languages.java.ast.JavaTokenNode; import com.strobel.decompiler.languages.java.ast.Keys; import com.strobel.decompiler.languages.java.ast.LabelStatement; import com.strobel.decompiler.languages.java.ast.LabeledStatement; import com.strobel.decompiler.languages.java.ast.LambdaExpression; import com.strobel.decompiler.languages.java.ast.LocalTypeDeclarationStatement; import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression; import com.strobel.decompiler.languages.java.ast.MethodDeclaration; import com.strobel.decompiler.languages.java.ast.MethodGroupExpression; import com.strobel.decompiler.languages.java.ast.NewLineNode; import com.strobel.decompiler.languages.java.ast.NullReferenceExpression; import com.strobel.decompiler.languages.java.ast.ObjectCreationExpression; import com.strobel.decompiler.languages.java.ast.PackageDeclaration; import com.strobel.decompiler.languages.java.ast.ParameterDeclaration; import com.strobel.decompiler.languages.java.ast.ParenthesizedExpression; import com.strobel.decompiler.languages.java.ast.PrimitiveExpression; import com.strobel.decompiler.languages.java.ast.ReturnStatement; import com.strobel.decompiler.languages.java.ast.SimpleType; import com.strobel.decompiler.languages.java.ast.SuperReferenceExpression; import com.strobel.decompiler.languages.java.ast.SwitchSection; import com.strobel.decompiler.languages.java.ast.SwitchStatement; import com.strobel.decompiler.languages.java.ast.SynchronizedStatement; import com.strobel.decompiler.languages.java.ast.TextNode; import com.strobel.decompiler.languages.java.ast.ThisReferenceExpression; import com.strobel.decompiler.languages.java.ast.ThrowStatement; import com.strobel.decompiler.languages.java.ast.TryCatchStatement; import com.strobel.decompiler.languages.java.ast.TypeDeclaration; import com.strobel.decompiler.languages.java.ast.TypeParameterDeclaration; import com.strobel.decompiler.languages.java.ast.TypeReferenceExpression; import com.strobel.decompiler.languages.java.ast.UnaryOperatorExpression; import com.strobel.decompiler.languages.java.ast.VariableDeclarationStatement; import com.strobel.decompiler.languages.java.ast.VariableInitializer; import com.strobel.decompiler.languages.java.ast.WhileStatement; import com.strobel.decompiler.languages.java.ast.WildcardType; import com.strobel.decompiler.patterns.Pattern; public class TreeDumpVisitor implements IAstVisitor { private File m_file; private Writer m_out; public TreeDumpVisitor(File file) { m_file = file; m_out = null; } @Override public Void visitCompilationUnit(CompilationUnit node, Void ignored) { try { m_out = new FileWriter(m_file); recurse(node, ignored); m_out.close(); return null; } catch (IOException ex) { throw new Error(ex); } } private Void recurse(AstNode node, Void ignored) { // show the tree try { m_out.write(getIndent(node) + node.getClass().getSimpleName() + " " + getText(node) + " " + dumpUserData(node) + " " + node.getRegion() + "\n"); } catch (IOException ex) { throw new Error(ex); } // recurse for (final AstNode child : node.getChildren()) { child.acceptVisitor(this, ignored); } return null; } private String getText(AstNode node) { if (node instanceof Identifier) { return "\"" + ((Identifier)node).getName() + "\""; } return ""; } private String dumpUserData(AstNode node) { StringBuilder buf = new StringBuilder(); for (Key key : Keys.ALL_KEYS) { Object val = node.getUserData(key); if (val != null) { buf.append(String.format(" [%s=%s]", key, val)); } } return buf.toString(); } private String getIndent(AstNode node) { StringBuilder buf = new StringBuilder(); int depth = getDepth(node); for (int i = 0; i < depth; i++) { buf.append("\t"); } return buf.toString(); } private int getDepth(AstNode node) { int depth = -1; while (node != null) { depth++; node = node.getParent(); } return depth; } // OVERRIDES WE DON'T CARE ABOUT @Override public Void visitInvocationExpression(InvocationExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitMemberReferenceExpression(MemberReferenceExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitSimpleType(SimpleType node, Void ignored) { return recurse(node, ignored); } @Override public Void visitMethodDeclaration(MethodDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitConstructorDeclaration(ConstructorDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitParameterDeclaration(ParameterDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitFieldDeclaration(FieldDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitTypeDeclaration(TypeDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitComment(Comment node, Void ignored) { return recurse(node, ignored); } @Override public Void visitPatternPlaceholder(AstNode node, Pattern pattern, Void ignored) { return recurse(node, ignored); } @Override public Void visitTypeReference(TypeReferenceExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitJavaTokenNode(JavaTokenNode node, Void ignored) { return recurse(node, ignored); } @Override public Void visitIdentifier(Identifier node, Void ignored) { return recurse(node, ignored); } @Override public Void visitNullReferenceExpression(NullReferenceExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitThisReferenceExpression(ThisReferenceExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitSuperReferenceExpression(SuperReferenceExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitClassOfExpression(ClassOfExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitBlockStatement(BlockStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitExpressionStatement(ExpressionStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitBreakStatement(BreakStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitContinueStatement(ContinueStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitDoWhileStatement(DoWhileStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitEmptyStatement(EmptyStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitIfElseStatement(IfElseStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitLabelStatement(LabelStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitLabeledStatement(LabeledStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitReturnStatement(ReturnStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitSwitchStatement(SwitchStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitSwitchSection(SwitchSection node, Void ignored) { return recurse(node, ignored); } @Override public Void visitCaseLabel(CaseLabel node, Void ignored) { return recurse(node, ignored); } @Override public Void visitThrowStatement(ThrowStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitCatchClause(CatchClause node, Void ignored) { return recurse(node, ignored); } @Override public Void visitAnnotation(Annotation node, Void ignored) { return recurse(node, ignored); } @Override public Void visitNewLine(NewLineNode node, Void ignored) { return recurse(node, ignored); } @Override public Void visitVariableDeclaration(VariableDeclarationStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitVariableInitializer(VariableInitializer node, Void ignored) { return recurse(node, ignored); } @Override public Void visitText(TextNode node, Void ignored) { return recurse(node, ignored); } @Override public Void visitImportDeclaration(ImportDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitInitializerBlock(InstanceInitializer node, Void ignored) { return recurse(node, ignored); } @Override public Void visitTypeParameterDeclaration(TypeParameterDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitPackageDeclaration(PackageDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitArraySpecifier(ArraySpecifier node, Void ignored) { return recurse(node, ignored); } @Override public Void visitComposedType(ComposedType node, Void ignored) { return recurse(node, ignored); } @Override public Void visitWhileStatement(WhileStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitPrimitiveExpression(PrimitiveExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitCastExpression(CastExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitBinaryOperatorExpression(BinaryOperatorExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitInstanceOfExpression(InstanceOfExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitIndexerExpression(IndexerExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitIdentifierExpression(IdentifierExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitUnaryOperatorExpression(UnaryOperatorExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitConditionalExpression(ConditionalExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitArrayInitializerExpression(ArrayInitializerExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitObjectCreationExpression(ObjectCreationExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitArrayCreationExpression(ArrayCreationExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitAssignmentExpression(AssignmentExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitForStatement(ForStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitForEachStatement(ForEachStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitTryCatchStatement(TryCatchStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitGotoStatement(GotoStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitParenthesizedExpression(ParenthesizedExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitSynchronizedStatement(SynchronizedStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitAnonymousObjectCreationExpression(AnonymousObjectCreationExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitWildcardType(WildcardType node, Void ignored) { return recurse(node, ignored); } @Override public Void visitMethodGroupExpression(MethodGroupExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitEnumValueDeclaration(EnumValueDeclaration node, Void ignored) { return recurse(node, ignored); } @Override public Void visitAssertStatement(AssertStatement node, Void ignored) { return recurse(node, ignored); } @Override public Void visitLambdaExpression(LambdaExpression node, Void ignored) { return recurse(node, ignored); } @Override public Void visitLocalTypeDeclarationStatement(LocalTypeDeclarationStatement node, Void ignored) { return recurse(node, ignored); } }