summaryrefslogtreecommitdiff
path: root/src/cuchaz/enigma/analysis/Analyzer.java
diff options
context:
space:
mode:
authorGravatar jeff2014-08-10 01:03:40 -0400
committerGravatar jeff2014-08-10 01:03:40 -0400
commitd24d2b9ad9b5c895020b56f700a72906346482e5 (patch)
treeda360c07209e6e327325db53dbb4df05e77cb7e9 /src/cuchaz/enigma/analysis/Analyzer.java
parentadded sorting for deobfuscated classes (diff)
downloadenigma-fork-d24d2b9ad9b5c895020b56f700a72906346482e5.tar.gz
enigma-fork-d24d2b9ad9b5c895020b56f700a72906346482e5.tar.xz
enigma-fork-d24d2b9ad9b5c895020b56f700a72906346482e5.zip
completely re-wrote token recognizer to bootstrap from Procyon's AST
changed imports to guava instead of whatever collections library happened to be on my classpath
Diffstat (limited to 'src/cuchaz/enigma/analysis/Analyzer.java')
-rw-r--r--src/cuchaz/enigma/analysis/Analyzer.java263
1 files changed, 0 insertions, 263 deletions
diff --git a/src/cuchaz/enigma/analysis/Analyzer.java b/src/cuchaz/enigma/analysis/Analyzer.java
deleted file mode 100644
index 2b7e0b0..0000000
--- a/src/cuchaz/enigma/analysis/Analyzer.java
+++ /dev/null
@@ -1,263 +0,0 @@
1/*******************************************************************************
2 * Copyright (c) 2014 Jeff Martin.
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the GNU Public License v3.0
5 * which accompanies this distribution, and is available at
6 * http://www.gnu.org/licenses/gpl.html
7 *
8 * Contributors:
9 * Jeff Martin - initial API and implementation
10 ******************************************************************************/
11package cuchaz.enigma.analysis;
12
13import java.io.IOException;
14import java.util.Arrays;
15
16import javax.tools.JavaCompiler;
17import javax.tools.StandardJavaFileManager;
18import javax.tools.ToolProvider;
19
20import jsyntaxpane.Token;
21import jsyntaxpane.TokenType;
22
23import com.sun.source.tree.ArrayTypeTree;
24import com.sun.source.tree.ClassTree;
25import com.sun.source.tree.CompilationUnitTree;
26import com.sun.source.tree.IdentifierTree;
27import com.sun.source.tree.MethodTree;
28import com.sun.source.tree.PrimitiveTypeTree;
29import com.sun.source.tree.Tree;
30import com.sun.source.tree.Tree.Kind;
31import com.sun.source.tree.VariableTree;
32import com.sun.source.util.JavacTask;
33import com.sun.source.util.TreeScanner;
34import com.sun.source.util.Trees;
35
36import cuchaz.enigma.mapping.ArgumentEntry;
37import cuchaz.enigma.mapping.ClassEntry;
38import cuchaz.enigma.mapping.Entry;
39import cuchaz.enigma.mapping.FieldEntry;
40import cuchaz.enigma.mapping.MethodEntry;
41
42class TreeVisitor extends TreeScanner<CompilationUnitTree, SourcedAst>
43{
44 private SourceIndex m_index;
45
46 public TreeVisitor( SourceIndex index )
47 {
48 m_index = index;
49 }
50
51 @Override
52 public CompilationUnitTree visitClass( ClassTree classTree, SourcedAst ast )
53 {
54 ClassEntry classEntry = indexClass( classTree, ast );
55
56 // look at the class members
57 for( Tree memberTree : classTree.getMembers() )
58 {
59 if( memberTree.getKind() == Kind.VARIABLE )
60 {
61 indexField( (VariableTree)memberTree, ast, classEntry );
62 }
63 else if( memberTree.getKind() == Kind.METHOD )
64 {
65 MethodTree methodTree = (MethodTree)memberTree;
66 MethodEntry methodEntry = indexMethod( methodTree, ast, classEntry );
67
68 // look at method arguments
69 int argNum = 0;
70 for( VariableTree variableTree : methodTree.getParameters() )
71 {
72 indexArgument( variableTree, ast, methodEntry, argNum++ );
73 }
74 }
75 }
76
77 return super.visitClass( classTree, ast );
78 }
79
80 private ClassEntry indexClass( ClassTree classTree, SourcedAst ast )
81 {
82 // index the class name
83 ClassEntry classEntry = indexClassIdentifier( classTree, ast );
84 assert( classEntry != null );
85
86 // index the extends clause
87 indexClassIdentifier( classTree.getExtendsClause(), ast );
88
89 // index the implements clauses
90 for( Tree implementsTree : classTree.getImplementsClause() )
91 {
92 indexClassIdentifier( implementsTree, ast );
93 }
94
95 return classEntry;
96 }
97
98 private FieldEntry indexField( VariableTree variableTree, SourcedAst ast, ClassEntry classEntry )
99 {
100 // index the field name
101 FieldEntry entry = new FieldEntry( classEntry, variableTree.getName().toString() );
102 Token nameToken = new Lexer( ast.getSource( variableTree ) ).getFirstIdentifierMatching( variableTree.getName() );
103 addToken( entry, nameToken, variableTree, ast );
104
105 // index the field type
106 indexClassIdentifier( variableTree.getType(), ast );
107
108 return entry;
109 }
110
111 private MethodEntry indexMethod( MethodTree methodTree, SourcedAst ast, ClassEntry classEntry )
112 {
113 // build the entry
114 StringBuilder signature = new StringBuilder();
115 signature.append( "(" );
116 for( VariableTree variableTree : methodTree.getParameters() )
117 {
118 signature.append( toJvmType( variableTree.getType(), ast ) );
119 }
120 signature.append( ")" );
121 if( methodTree.getReturnType() != null )
122 {
123 signature.append( toJvmType( methodTree.getReturnType(), ast ) );
124 }
125 else
126 {
127 signature.append( "V" );
128 }
129 MethodEntry entry = new MethodEntry( classEntry, methodTree.getName().toString(), signature.toString() );
130
131 // lex the source at this tree node
132 Lexer lexer = new Lexer( ast.getSource( methodTree ) );
133 for( Token token : lexer )
134 {
135 // scan until we find an identifier that matches the method name
136 if( token.type == TokenType.IDENTIFIER && lexer.getText( token ).equals( entry.getName() ) )
137 {
138 addToken( entry, token, methodTree, ast );
139 break;
140 }
141 }
142
143 return entry;
144 }
145
146 private void indexArgument( VariableTree variableTree, SourcedAst ast, MethodEntry methodEntry, int index )
147 {
148 // index argument name
149 ArgumentEntry entry = new ArgumentEntry( methodEntry, index, variableTree.getName().toString() );
150 Token token = new Lexer( ast.getSource( variableTree ) ).getLastIdentifier();
151 addToken( entry, token, variableTree, ast );
152
153 // index argument type
154 indexClassIdentifier( variableTree.getType(), ast );
155 }
156
157 private ClassEntry indexClassIdentifier( Tree tree, SourcedAst ast )
158 {
159 if( tree == null )
160 {
161 return null;
162 }
163
164 Lexer lexer = new Lexer( ast.getSource( tree ) );
165 Token token = lexer.getFirstIdentifier();
166 if( token == null )
167 {
168 return null;
169 }
170
171 ClassEntry classEntry = new ClassEntry( ast.getFullClassName( lexer.getText( token ) ) );
172 addToken( classEntry, token, tree, ast );
173 return classEntry;
174 }
175
176 private void addToken( Entry entry, Token token, Tree tree, SourcedAst ast )
177 {
178 if( token == null )
179 {
180 throw new IllegalArgumentException( "token cannot be null!" );
181 }
182
183 // offset the token by the tree
184 Token offsetToken = new Token( token.type, token.start + ast.getStart( tree ), token.length );
185
186 m_index.add( entry, offsetToken );
187 }
188
189 private String toJvmType( Tree tree, SourcedAst ast )
190 {
191 switch( tree.getKind() )
192 {
193 case PRIMITIVE_TYPE:
194 {
195 PrimitiveTypeTree primitiveTypeTree = (PrimitiveTypeTree)tree;
196 switch( primitiveTypeTree.getPrimitiveTypeKind() )
197 {
198 case BOOLEAN: return "Z";
199 case BYTE: return "B";
200 case CHAR: return "C";
201 case DOUBLE: return "D";
202 case FLOAT: return "F";
203 case INT: return "I";
204 case LONG: return "J";
205 case SHORT: return "S";
206 case VOID: return "V";
207
208 default:
209 throw new Error( "Unsupported primitive type: " + primitiveTypeTree.getPrimitiveTypeKind() );
210 }
211 }
212
213 case IDENTIFIER:
214 {
215 IdentifierTree identifierTree = (IdentifierTree)tree;
216 String className = identifierTree.getName().toString();
217 className = ast.getFullClassName( className );
218 return "L" + className.replace( ".", "/" ) + ";";
219 }
220
221 case ARRAY_TYPE:
222 {
223 ArrayTypeTree arrayTree = (ArrayTypeTree)tree;
224 return "[" + toJvmType( arrayTree.getType(), ast );
225 }
226
227
228 default:
229 throw new Error( "Unsupported type kind: " + tree.getKind() );
230 }
231 }
232}
233
234public class Analyzer
235{
236 public static SourceIndex analyze( String className, String source )
237 {
238 SourceIndex index = new SourceIndex();
239 SourcedAst ast = getAst( className, source );
240 ast.visit( new TreeVisitor( index ) );
241 return index;
242 }
243
244 private static SourcedAst getAst( String className, String source )
245 {
246 JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
247 StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null );
248 JavaSourceFromString unit = new JavaSourceFromString( className, source );
249 JavacTask task = (JavacTask)compiler.getTask( null, fileManager, null, null, null, Arrays.asList( unit ) );
250
251 try
252 {
253 return new SourcedAst(
254 task.parse().iterator().next(),
255 Trees.instance( task )
256 );
257 }
258 catch( IOException ex )
259 {
260 throw new Error( ex );
261 }
262 }
263}