From d24d2b9ad9b5c895020b56f700a72906346482e5 Mon Sep 17 00:00:00 2001 From: jeff Date: Sun, 10 Aug 2014 01:03:40 -0400 Subject: 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 --- src/cuchaz/enigma/Deobfuscator.java | 114 ++-- src/cuchaz/enigma/analysis/Analyzer.java | 263 --------- src/cuchaz/enigma/analysis/ClassNameIndex.java | 19 - .../enigma/analysis/JavaSourceFromString.java | 31 -- src/cuchaz/enigma/analysis/Lexer.java | 79 --- src/cuchaz/enigma/analysis/SourceIndex.java | 99 ++-- src/cuchaz/enigma/analysis/SourceIndexVisitor.java | 618 +++++++++++++++++++++ src/cuchaz/enigma/analysis/SourcedAst.java | 140 ----- src/cuchaz/enigma/analysis/Token.java | 49 ++ .../enigma/gui/ClassInheritanceTreeNode.java | 2 +- src/cuchaz/enigma/gui/Gui.java | 29 +- src/cuchaz/enigma/gui/GuiController.java | 56 +- src/cuchaz/enigma/mapping/Ancestries.java | 2 +- src/cuchaz/enigma/mapping/ClassMapping.java | 24 +- src/cuchaz/enigma/mapping/EntryPair.java | 5 +- src/cuchaz/enigma/mapping/Mappings.java | 2 +- 16 files changed, 865 insertions(+), 667 deletions(-) delete mode 100644 src/cuchaz/enigma/analysis/Analyzer.java delete mode 100644 src/cuchaz/enigma/analysis/ClassNameIndex.java delete mode 100644 src/cuchaz/enigma/analysis/JavaSourceFromString.java delete mode 100644 src/cuchaz/enigma/analysis/Lexer.java create mode 100644 src/cuchaz/enigma/analysis/SourceIndexVisitor.java delete mode 100644 src/cuchaz/enigma/analysis/SourcedAst.java create mode 100644 src/cuchaz/enigma/analysis/Token.java (limited to 'src') diff --git a/src/cuchaz/enigma/Deobfuscator.java b/src/cuchaz/enigma/Deobfuscator.java index e6e647e9..8eda889f 100644 --- a/src/cuchaz/enigma/Deobfuscator.java +++ b/src/cuchaz/enigma/Deobfuscator.java @@ -10,12 +10,10 @@ ******************************************************************************/ package cuchaz.enigma; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.StringReader; import java.io.StringWriter; import java.util.Enumeration; import java.util.List; @@ -23,11 +21,26 @@ import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import com.beust.jcommander.internal.Lists; -import com.strobel.decompiler.Decompiler; +import com.google.common.collect.Lists; +import com.strobel.assembler.metadata.MemberReference; +import com.strobel.assembler.metadata.MetadataSystem; +import com.strobel.assembler.metadata.TypeDefinition; +import com.strobel.componentmodel.Key; +import com.strobel.decompiler.DecompilerContext; import com.strobel.decompiler.DecompilerSettings; import com.strobel.decompiler.PlainTextOutput; +import com.strobel.decompiler.languages.java.JavaOutputVisitor; +import com.strobel.decompiler.languages.java.ast.AstBuilder; +import com.strobel.decompiler.languages.java.ast.AstNode; +import com.strobel.decompiler.languages.java.ast.CompilationUnit; +import com.strobel.decompiler.languages.java.ast.Identifier; +import com.strobel.decompiler.languages.java.ast.InsertParenthesesVisitor; +import com.strobel.decompiler.languages.java.ast.InvocationExpression; +import com.strobel.decompiler.languages.java.ast.Keys; +import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression; +import cuchaz.enigma.analysis.SourceIndex; +import cuchaz.enigma.analysis.SourceIndexVisitor; import cuchaz.enigma.mapping.Ancestries; import cuchaz.enigma.mapping.ArgumentEntry; import cuchaz.enigma.mapping.ClassEntry; @@ -91,7 +104,6 @@ public class Deobfuscator // config the decompiler m_settings = DecompilerSettings.javaDefaults(); - m_settings.setForceExplicitImports( true ); m_settings.setShowSyntheticMembers( true ); // init mappings @@ -157,7 +169,7 @@ public class Deobfuscator } } - public String getSource( final ClassFile classFile ) + public SourceIndex getSource( final ClassFile classFile ) { // is this class deobfuscated? // we need to tell the decompiler the deobfuscated name so it doesn't get freaked out @@ -170,45 +182,79 @@ public class Deobfuscator } // decompile it! + TypeDefinition resolvedType = new MetadataSystem( m_settings.getTypeLoader() ).lookupType( deobfName ).resolve(); + DecompilerContext context = new DecompilerContext(); + context.setCurrentType( resolvedType ); + context.setSettings( m_settings ); + AstBuilder builder = new AstBuilder( context ); + builder.addType( resolvedType ); + builder.runTransformations( null ); + CompilationUnit root = builder.getCompilationUnit(); + + // render the AST into source StringWriter buf = new StringWriter(); - Decompiler.decompile( deobfName, new PlainTextOutput( buf ), m_settings ); - return fixSource( buf.toString() ); + root.acceptVisitor( new InsertParenthesesVisitor(), null ); + root.acceptVisitor( new JavaOutputVisitor( new PlainTextOutput( buf ), m_settings ), null ); + + // build the source index + SourceIndex index = new SourceIndex( buf.toString() ); + root.acceptVisitor( new SourceIndexVisitor(), index ); + + return index; } - private String fixSource( String source ) + private void dump( AstNode node, int depth ) { - // fix the imports from the default package in the source - try + StringBuilder buf = new StringBuilder(); + for( int i=0; i %s)", memberRef.getDeclaringType(), memberRef.getName(), memberRef.getSignature() ) ); + } + + for( Key key : Keys.ALL_KEYS ) + { + if( key == Keys.MEMBER_REFERENCE ) { - String[] parts = line.trim().split( " " ); - if( parts.length == 2 && parts[0].equals( "import" ) ) - { - // is this an (illegal) import from the default package? - String className = parts[1]; - if( className.indexOf( '.' ) < 0 ) - { - // this is an illegal import, replace it - line = "import __DEFAULT__." + parts[1]; - } - } - - buf.append( line ); - buf.append( "\n" ); + continue; + } + Object val = node.getUserData( key ); + if( val != null ) + { + buf.append( String.format( " (%s=%s)", key, val ) ); } - return buf.toString(); } - catch( IOException ex ) + + + if( node instanceof Identifier ) + { + Identifier n = (Identifier)node; + buf.append( ": " + n.getName() ); + } + else if( node instanceof MemberReferenceExpression ) + { + MemberReferenceExpression n = (MemberReferenceExpression)node; + buf.append( ": " + n.getTarget() + "." + n.getMemberName() ); + } + else if( node instanceof InvocationExpression ) { - // dealing with IOExceptions on StringReaders is silly... - throw new Error( ex ); + + } + + System.out.println( buf ); + + for( AstNode child : node.getChildren() ) + { + dump( child, depth + 1 ); } } - + // NOTE: these methods are a bit messy... oh well public void rename( Entry obfEntry, String newName ) diff --git a/src/cuchaz/enigma/analysis/Analyzer.java b/src/cuchaz/enigma/analysis/Analyzer.java deleted file mode 100644 index 2b7e0b0b..00000000 --- a/src/cuchaz/enigma/analysis/Analyzer.java +++ /dev/null @@ -1,263 +0,0 @@ -/******************************************************************************* - * 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.IOException; -import java.util.Arrays; - -import javax.tools.JavaCompiler; -import javax.tools.StandardJavaFileManager; -import javax.tools.ToolProvider; - -import jsyntaxpane.Token; -import jsyntaxpane.TokenType; - -import com.sun.source.tree.ArrayTypeTree; -import com.sun.source.tree.ClassTree; -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.IdentifierTree; -import com.sun.source.tree.MethodTree; -import com.sun.source.tree.PrimitiveTypeTree; -import com.sun.source.tree.Tree; -import com.sun.source.tree.Tree.Kind; -import com.sun.source.tree.VariableTree; -import com.sun.source.util.JavacTask; -import com.sun.source.util.TreeScanner; -import com.sun.source.util.Trees; - -import cuchaz.enigma.mapping.ArgumentEntry; -import cuchaz.enigma.mapping.ClassEntry; -import cuchaz.enigma.mapping.Entry; -import cuchaz.enigma.mapping.FieldEntry; -import cuchaz.enigma.mapping.MethodEntry; - -class TreeVisitor extends TreeScanner -{ - private SourceIndex m_index; - - public TreeVisitor( SourceIndex index ) - { - m_index = index; - } - - @Override - public CompilationUnitTree visitClass( ClassTree classTree, SourcedAst ast ) - { - ClassEntry classEntry = indexClass( classTree, ast ); - - // look at the class members - for( Tree memberTree : classTree.getMembers() ) - { - if( memberTree.getKind() == Kind.VARIABLE ) - { - indexField( (VariableTree)memberTree, ast, classEntry ); - } - else if( memberTree.getKind() == Kind.METHOD ) - { - MethodTree methodTree = (MethodTree)memberTree; - MethodEntry methodEntry = indexMethod( methodTree, ast, classEntry ); - - // look at method arguments - int argNum = 0; - for( VariableTree variableTree : methodTree.getParameters() ) - { - indexArgument( variableTree, ast, methodEntry, argNum++ ); - } - } - } - - return super.visitClass( classTree, ast ); - } - - private ClassEntry indexClass( ClassTree classTree, SourcedAst ast ) - { - // index the class name - ClassEntry classEntry = indexClassIdentifier( classTree, ast ); - assert( classEntry != null ); - - // index the extends clause - indexClassIdentifier( classTree.getExtendsClause(), ast ); - - // index the implements clauses - for( Tree implementsTree : classTree.getImplementsClause() ) - { - indexClassIdentifier( implementsTree, ast ); - } - - return classEntry; - } - - private FieldEntry indexField( VariableTree variableTree, SourcedAst ast, ClassEntry classEntry ) - { - // index the field name - FieldEntry entry = new FieldEntry( classEntry, variableTree.getName().toString() ); - Token nameToken = new Lexer( ast.getSource( variableTree ) ).getFirstIdentifierMatching( variableTree.getName() ); - addToken( entry, nameToken, variableTree, ast ); - - // index the field type - indexClassIdentifier( variableTree.getType(), ast ); - - return entry; - } - - private MethodEntry indexMethod( MethodTree methodTree, SourcedAst ast, ClassEntry classEntry ) - { - // build the entry - StringBuilder signature = new StringBuilder(); - signature.append( "(" ); - for( VariableTree variableTree : methodTree.getParameters() ) - { - signature.append( toJvmType( variableTree.getType(), ast ) ); - } - signature.append( ")" ); - if( methodTree.getReturnType() != null ) - { - signature.append( toJvmType( methodTree.getReturnType(), ast ) ); - } - else - { - signature.append( "V" ); - } - MethodEntry entry = new MethodEntry( classEntry, methodTree.getName().toString(), signature.toString() ); - - // lex the source at this tree node - Lexer lexer = new Lexer( ast.getSource( methodTree ) ); - for( Token token : lexer ) - { - // scan until we find an identifier that matches the method name - if( token.type == TokenType.IDENTIFIER && lexer.getText( token ).equals( entry.getName() ) ) - { - addToken( entry, token, methodTree, ast ); - break; - } - } - - return entry; - } - - private void indexArgument( VariableTree variableTree, SourcedAst ast, MethodEntry methodEntry, int index ) - { - // index argument name - ArgumentEntry entry = new ArgumentEntry( methodEntry, index, variableTree.getName().toString() ); - Token token = new Lexer( ast.getSource( variableTree ) ).getLastIdentifier(); - addToken( entry, token, variableTree, ast ); - - // index argument type - indexClassIdentifier( variableTree.getType(), ast ); - } - - private ClassEntry indexClassIdentifier( Tree tree, SourcedAst ast ) - { - if( tree == null ) - { - return null; - } - - Lexer lexer = new Lexer( ast.getSource( tree ) ); - Token token = lexer.getFirstIdentifier(); - if( token == null ) - { - return null; - } - - ClassEntry classEntry = new ClassEntry( ast.getFullClassName( lexer.getText( token ) ) ); - addToken( classEntry, token, tree, ast ); - return classEntry; - } - - private void addToken( Entry entry, Token token, Tree tree, SourcedAst ast ) - { - if( token == null ) - { - throw new IllegalArgumentException( "token cannot be null!" ); - } - - // offset the token by the tree - Token offsetToken = new Token( token.type, token.start + ast.getStart( tree ), token.length ); - - m_index.add( entry, offsetToken ); - } - - private String toJvmType( Tree tree, SourcedAst ast ) - { - switch( tree.getKind() ) - { - case PRIMITIVE_TYPE: - { - PrimitiveTypeTree primitiveTypeTree = (PrimitiveTypeTree)tree; - switch( primitiveTypeTree.getPrimitiveTypeKind() ) - { - case BOOLEAN: return "Z"; - case BYTE: return "B"; - case CHAR: return "C"; - case DOUBLE: return "D"; - case FLOAT: return "F"; - case INT: return "I"; - case LONG: return "J"; - case SHORT: return "S"; - case VOID: return "V"; - - default: - throw new Error( "Unsupported primitive type: " + primitiveTypeTree.getPrimitiveTypeKind() ); - } - } - - case IDENTIFIER: - { - IdentifierTree identifierTree = (IdentifierTree)tree; - String className = identifierTree.getName().toString(); - className = ast.getFullClassName( className ); - return "L" + className.replace( ".", "/" ) + ";"; - } - - case ARRAY_TYPE: - { - ArrayTypeTree arrayTree = (ArrayTypeTree)tree; - return "[" + toJvmType( arrayTree.getType(), ast ); - } - - - default: - throw new Error( "Unsupported type kind: " + tree.getKind() ); - } - } -} - -public class Analyzer -{ - public static SourceIndex analyze( String className, String source ) - { - SourceIndex index = new SourceIndex(); - SourcedAst ast = getAst( className, source ); - ast.visit( new TreeVisitor( index ) ); - return index; - } - - private static SourcedAst getAst( String className, String source ) - { - JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); - StandardJavaFileManager fileManager = compiler.getStandardFileManager( null, null, null ); - JavaSourceFromString unit = new JavaSourceFromString( className, source ); - JavacTask task = (JavacTask)compiler.getTask( null, fileManager, null, null, null, Arrays.asList( unit ) ); - - try - { - return new SourcedAst( - task.parse().iterator().next(), - Trees.instance( task ) - ); - } - catch( IOException ex ) - { - throw new Error( ex ); - } - } -} diff --git a/src/cuchaz/enigma/analysis/ClassNameIndex.java b/src/cuchaz/enigma/analysis/ClassNameIndex.java deleted file mode 100644 index ea3e2cae..00000000 --- a/src/cuchaz/enigma/analysis/ClassNameIndex.java +++ /dev/null @@ -1,19 +0,0 @@ -/******************************************************************************* - * 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 com.sun.source.tree.CompilationUnitTree; -import com.sun.source.util.TreeScanner; - -public class ClassNameIndex extends TreeScanner -{ - -} diff --git a/src/cuchaz/enigma/analysis/JavaSourceFromString.java b/src/cuchaz/enigma/analysis/JavaSourceFromString.java deleted file mode 100644 index cf5c4c27..00000000 --- a/src/cuchaz/enigma/analysis/JavaSourceFromString.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * 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.net.URI; - -import javax.tools.SimpleJavaFileObject; - -public class JavaSourceFromString extends SimpleJavaFileObject -{ - private final String m_source; - - JavaSourceFromString( String name, String source ) - { - super( URI.create( "string:///" + name.replace( '.', '/' ) + Kind.SOURCE.extension ), Kind.SOURCE ); - m_source = source; - } - - public CharSequence getCharContent( boolean ignoreEncodingErrors ) - { - return m_source; - } -} diff --git a/src/cuchaz/enigma/analysis/Lexer.java b/src/cuchaz/enigma/analysis/Lexer.java deleted file mode 100644 index 602e3a9b..00000000 --- a/src/cuchaz/enigma/analysis/Lexer.java +++ /dev/null @@ -1,79 +0,0 @@ -/******************************************************************************* - * 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.util.Iterator; - -import jsyntaxpane.SyntaxDocument; -import jsyntaxpane.Token; -import jsyntaxpane.TokenType; -import jsyntaxpane.lexers.JavaLexer; - -public class Lexer implements Iterable -{ - private SyntaxDocument m_doc; - private Iterator m_iter; - - public Lexer( CharSequence source ) - { - m_doc = new SyntaxDocument( new JavaLexer() ); - m_doc.append( source.toString() ); - m_iter = m_doc.getTokens( 0, m_doc.getLength() ); - } - - @Override - public Iterator iterator( ) - { - return m_iter; - } - - public String getText( Token token ) - { - return token.getString( m_doc ); - } - - public Token getFirstIdentifier( ) - { - for( Token token : this ) - { - if( token.type == TokenType.IDENTIFIER ) - { - return token; - } - } - return null; - } - - public Token getFirstIdentifierMatching( CharSequence val ) - { - for( Token token : this ) - { - if( token.type == TokenType.IDENTIFIER && getText( token ).equals( val.toString() ) ) - { - return token; - } - } - return null; - } - - public Token getLastIdentifier( ) - { - Token lastToken = null; - for( Token token : this ) - { - if( token.type == TokenType.IDENTIFIER ) - { - lastToken = token; - } - } - return lastToken; - } -} diff --git a/src/cuchaz/enigma/analysis/SourceIndex.java b/src/cuchaz/enigma/analysis/SourceIndex.java index de163087..398a50d1 100644 --- a/src/cuchaz/enigma/analysis/SourceIndex.java +++ b/src/cuchaz/enigma/analysis/SourceIndex.java @@ -10,70 +10,101 @@ ******************************************************************************/ package cuchaz.enigma.analysis; -import java.util.Collection; -import java.util.Iterator; +import java.util.List; import java.util.Map; +import java.util.TreeMap; -import jsyntaxpane.Token; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.strobel.decompiler.languages.Region; +import com.strobel.decompiler.languages.java.ast.AstNode; import cuchaz.enigma.mapping.Entry; -public class SourceIndex implements Iterable> +public class SourceIndex { - private Multimap m_entryToTokens; + private String m_source; + private TreeMap m_tokens; + private List m_lineOffsets; - public SourceIndex( ) + public SourceIndex( String source ) { - m_entryToTokens = HashMultimap.create(); + m_source = source; + m_tokens = Maps.newTreeMap(); + m_lineOffsets = Lists.newArrayList(); + + // count the lines + m_lineOffsets.add( 0 ); + for( int i=0; i> iterator( ) + public Token getToken( AstNode node ) { - return m_entryToTokens.entries().iterator(); + // get a token for this node's region + Region region = node.getRegion(); + if( region.getBeginLine() == 0 || region.getEndLine() == 0 ) + { + throw new IllegalArgumentException( "Invalid region: " + region ); + } + return new Token( + toPos( region.getBeginLine(), region.getBeginColumn() ), + toPos( region.getEndLine(), region.getEndColumn() ) + ); } - public Collection tokens( ) + public void add( AstNode node, Entry entry ) { - return m_entryToTokens.values(); + m_tokens.put( getToken( node ), entry ); } - public Entry getEntry( Token token ) + public void add( Token token, Entry entry ) + { + m_tokens.put( token, entry ); + } + + public Token getToken( int pos ) { - // linear search is fast enough for now - for( Map.Entry entry : this ) + Map.Entry mapEntry = m_tokens.floorEntry( new Token( pos, pos ) ); + if( mapEntry == null ) { - if( entry.getValue().equals( token ) ) - { - return entry.getKey(); - } + return null; + } + Token token = mapEntry.getKey(); + if( token.contains( pos ) ) + { + return token; } return null; } - public Map.Entry getEntry( int pos ) + public Entry getEntry( Token token ) { - // linear search is fast enough for now - for( Map.Entry entry : this ) + if( token == null ) { - Token token = entry.getValue(); - if( pos >= token.start && pos <= token.end() ) - { - return entry; - } + return null; } - return null; + return m_tokens.get( token ); + } + + public Iterable tokens( ) + { + return m_tokens.keySet(); } - public Collection getTokens( Entry entry ) + private int toPos( int line, int col ) { - return m_entryToTokens.get( entry ); + // line and col are 1-based + return m_lineOffsets.get( line - 1 ) + col - 1; } } diff --git a/src/cuchaz/enigma/analysis/SourceIndexVisitor.java b/src/cuchaz/enigma/analysis/SourceIndexVisitor.java new file mode 100644 index 00000000..2a26c85f --- /dev/null +++ b/src/cuchaz/enigma/analysis/SourceIndexVisitor.java @@ -0,0 +1,618 @@ +/******************************************************************************* + * 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 com.strobel.assembler.metadata.FieldDefinition; +import com.strobel.assembler.metadata.MemberReference; +import com.strobel.assembler.metadata.MethodDefinition; +import com.strobel.assembler.metadata.ParameterDefinition; +import com.strobel.assembler.metadata.TypeDefinition; +import com.strobel.assembler.metadata.TypeReference; +import com.strobel.componentmodel.Key; +import com.strobel.decompiler.languages.TextLocation; +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.Expression; +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; + +import cuchaz.enigma.mapping.ArgumentEntry; +import cuchaz.enigma.mapping.ClassEntry; +import cuchaz.enigma.mapping.FieldEntry; +import cuchaz.enigma.mapping.MethodEntry; + +public class SourceIndexVisitor implements IAstVisitor +{ + @Override + public Void visitComment( Comment node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitPatternPlaceholder( AstNode node, Pattern pattern, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitInvocationExpression( InvocationExpression node, SourceIndex index ) + { + MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE ); + ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); + MethodEntry methodEntry = new MethodEntry( classEntry, ref.getName(), ref.getSignature() ); + if( node.getTarget() instanceof MemberReferenceExpression ) + { + index.add( ((MemberReferenceExpression)node.getTarget()).getMemberNameToken(), methodEntry ); + } + + return recurse( node, index ); + } + + @Override + public Void visitTypeReference( TypeReferenceExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitJavaTokenNode( JavaTokenNode node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitMemberReferenceExpression( MemberReferenceExpression node, SourceIndex index ) + { + MemberReference ref = node.getUserData( Keys.MEMBER_REFERENCE ); + if( ref != null ) + { + ClassEntry classEntry = new ClassEntry( ref.getDeclaringType().getInternalName() ); + FieldEntry fieldEntry = new FieldEntry( classEntry, ref.getName() ); + index.add( node.getMemberNameToken(), fieldEntry ); + } + + return recurse( node, index ); + } + + @Override + public Void visitIdentifier( Identifier node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitNullReferenceExpression( NullReferenceExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitThisReferenceExpression( ThisReferenceExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitSuperReferenceExpression( SuperReferenceExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitClassOfExpression( ClassOfExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitBlockStatement( BlockStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitExpressionStatement( ExpressionStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitBreakStatement( BreakStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitContinueStatement( ContinueStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitDoWhileStatement( DoWhileStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitEmptyStatement( EmptyStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitIfElseStatement( IfElseStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitLabelStatement( LabelStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitLabeledStatement( LabeledStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitReturnStatement( ReturnStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitSwitchStatement( SwitchStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitSwitchSection( SwitchSection node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitCaseLabel( CaseLabel node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitThrowStatement( ThrowStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitCatchClause( CatchClause node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitAnnotation( Annotation node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitNewLine( NewLineNode node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitVariableDeclaration( VariableDeclarationStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitVariableInitializer( VariableInitializer node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitText( TextNode node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitImportDeclaration( ImportDeclaration node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitSimpleType( SimpleType node, SourceIndex index ) + { + TypeReference ref = node.getUserData( Keys.TYPE_REFERENCE ); + if( node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY ) + { + index.add( node.getIdentifierToken(), new ClassEntry( ref.getInternalName() ) ); + } + + return recurse( node, index ); + } + + @Override + public Void visitMethodDeclaration( MethodDeclaration node, SourceIndex index ) + { + MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION ); + ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); + MethodEntry methodEntry = new MethodEntry( classEntry, def.getName(), def.getSignature() ); + index.add( node.getNameToken(), methodEntry ); + + return recurse( node, index ); + } + + @Override + public Void visitInitializerBlock( InstanceInitializer node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitConstructorDeclaration( ConstructorDeclaration node, SourceIndex index ) + { + MethodDefinition def = node.getUserData( Keys.METHOD_DEFINITION ); + index.add( node.getNameToken(), new ClassEntry( def.getDeclaringType().getInternalName() ) ); + + return recurse( node, index ); + } + + @Override + public Void visitTypeParameterDeclaration( TypeParameterDeclaration node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitParameterDeclaration( ParameterDeclaration node, SourceIndex index ) + { + ParameterDefinition def = node.getUserData( Keys.PARAMETER_DEFINITION ); + ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); + MethodDefinition methodDef = (MethodDefinition)def.getMethod(); + MethodEntry methodEntry = new MethodEntry( classEntry, methodDef.getName(), methodDef.getSignature() ); + ArgumentEntry argumentEntry = new ArgumentEntry( methodEntry, def.getPosition(), def.getName() ); + index.add( node.getNameToken(), argumentEntry ); + + return recurse( node, index ); + } + + @Override + public Void visitFieldDeclaration( FieldDeclaration node, SourceIndex index ) + { + FieldDefinition def = node.getUserData( Keys.FIELD_DEFINITION ); + ClassEntry classEntry = new ClassEntry( def.getDeclaringType().getInternalName() ); + FieldEntry fieldEntry = new FieldEntry( classEntry, def.getName() ); + assert( node.getVariables().size() == 1 ); + VariableInitializer variable = node.getVariables().firstOrNullObject(); + index.add( variable.getNameToken(), fieldEntry ); + + return recurse( node, index ); + } + + @Override + public Void visitTypeDeclaration( TypeDeclaration node, SourceIndex index ) + { + TypeDefinition def = node.getUserData( Keys.TYPE_DEFINITION ); + index.add( node.getNameToken(), new ClassEntry( def.getInternalName() ) ); + + return recurse( node, index ); + } + + @Override + public Void visitCompilationUnit( CompilationUnit node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitPackageDeclaration( PackageDeclaration node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitArraySpecifier( ArraySpecifier node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitComposedType( ComposedType node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitWhileStatement( WhileStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitPrimitiveExpression( PrimitiveExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitCastExpression( CastExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitBinaryOperatorExpression( BinaryOperatorExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitInstanceOfExpression( InstanceOfExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitIndexerExpression( IndexerExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitIdentifierExpression( IdentifierExpression node, SourceIndex index ) + { + // TODO + return recurse( node, index ); + } + + @Override + public Void visitUnaryOperatorExpression( UnaryOperatorExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitConditionalExpression( ConditionalExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitArrayInitializerExpression( ArrayInitializerExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitObjectCreationExpression( ObjectCreationExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitArrayCreationExpression( ArrayCreationExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitAssignmentExpression( AssignmentExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitForStatement( ForStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitForEachStatement( ForEachStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitTryCatchStatement( TryCatchStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitGotoStatement( GotoStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitParenthesizedExpression( ParenthesizedExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitSynchronizedStatement( SynchronizedStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitAnonymousObjectCreationExpression( AnonymousObjectCreationExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitWildcardType( WildcardType node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitMethodGroupExpression( MethodGroupExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitEnumValueDeclaration( EnumValueDeclaration node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitAssertStatement( AssertStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitLambdaExpression( LambdaExpression node, SourceIndex index ) + { + return recurse( node, index ); + } + + @Override + public Void visitLocalTypeDeclarationStatement( LocalTypeDeclarationStatement node, SourceIndex index ) + { + return recurse( node, index ); + } + + private Void recurse( AstNode node, SourceIndex index ) + { + // TEMP: show the tree + System.out.println( getIndent( node ) + node.getClass().getSimpleName() + dumpUserData( node ) + " " + node.getRegion() ); + + for( final AstNode child : node.getChildren() ) + { + child.acceptVisitor( this, index ); + } + return null; + } + + 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; + } +} diff --git a/src/cuchaz/enigma/analysis/SourcedAst.java b/src/cuchaz/enigma/analysis/SourcedAst.java deleted file mode 100644 index a88cc754..00000000 --- a/src/cuchaz/enigma/analysis/SourcedAst.java +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************* - * 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.IOException; -import java.util.HashMap; - -import javassist.bytecode.Descriptor; - -import com.google.common.collect.Maps; -import com.sun.source.tree.CompilationUnitTree; -import com.sun.source.tree.ImportTree; -import com.sun.source.tree.Tree; -import com.sun.source.util.SourcePositions; -import com.sun.source.util.Trees; - -public class SourcedAst -{ - private CompilationUnitTree m_tree; - private Trees m_trees; - private SourcePositions m_positions; - private HashMap m_classNameIndex; - private String m_packageName; - - public SourcedAst( CompilationUnitTree tree, Trees trees ) - { - m_tree = tree; - m_trees = trees; - m_positions = m_trees.getSourcePositions(); - m_classNameIndex = Maps.newHashMap(); - - // index all the class names from package imports - for( ImportTree importTree : m_tree.getImports() ) - { - // ignore static imports for now - if( importTree.isStatic() ) - { - continue; - } - - // get the full and simple class names - String fullName = Descriptor.toJvmName( importTree.getQualifiedIdentifier().toString() ); - String simpleName = fullName; - - if( fullName.startsWith( "__DEFAULT__/" ) ) - { - // remove the default package flag - fullName = fullName.substring( 12 ); - } - - String[] parts = fullName.split( "/" ); - if( parts.length > 0 ) - { - simpleName = parts[parts.length - 1]; - } - - m_classNameIndex.put( simpleName, fullName ); - } - - // get the package name - m_packageName = null; - if( m_tree.getPackageName() != null ) - { - m_packageName = Descriptor.toJvmName( m_tree.getPackageName().toString() ); - } - } - - public int getStart( Tree node ) - { - int pos = (int)m_positions.getStartPosition( m_tree, node ); - assert( pos >= 0 ); - return pos; - } - - public int getEnd( Tree node ) - { - int pos = (int)m_positions.getEndPosition( m_tree, node ); - assert( pos >= 0 ); - return pos; - } - - public int getLine( Tree node ) - { - return getLine( getStart( node ) ); - } - - public int getLine( int pos ) - { - return (int)m_tree.getLineMap().getLineNumber( pos ); - } - - public CharSequence getSource( ) - { - try - { - return m_tree.getSourceFile().getCharContent( true ); - } - catch( IOException ex ) - { - throw new Error( ex ); - } - } - - public CharSequence getSource( Tree node ) - { - return getSource().subSequence( getStart( node ), getEnd( node ) ); - } - - public void visit( TreeVisitor visitor ) - { - m_tree.accept( visitor, this ); - } - - public String getFullClassName( String simpleClassName ) - { - String fullClassName = m_classNameIndex.get( simpleClassName ); - if( fullClassName == null ) - { - if( m_packageName != null ) - { - // no mapping was found, assume it's in the package - fullClassName = m_packageName + "/" + simpleClassName; - } - else - { - // this must be in the default package - fullClassName = simpleClassName; - } - } - return fullClassName; - } -} diff --git a/src/cuchaz/enigma/analysis/Token.java b/src/cuchaz/enigma/analysis/Token.java new file mode 100644 index 00000000..74023e32 --- /dev/null +++ b/src/cuchaz/enigma/analysis/Token.java @@ -0,0 +1,49 @@ +/******************************************************************************* + * 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; + +public class Token implements Comparable +{ + public int start; + public int end; + + public Token( int start, int end ) + { + this.start = start; + this.end = end; + } + + public boolean contains( int pos ) + { + return pos >= start && pos <= end; + } + + @Override + public int compareTo( Token other ) + { + return start - other.start; + } + + @Override + public boolean equals( Object other ) + { + if( other instanceof Token ) + { + return equals( (Token)other ); + } + return false; + } + + public boolean equals( Token other ) + { + return start == other.start && end == other.end; + } +} diff --git a/src/cuchaz/enigma/gui/ClassInheritanceTreeNode.java b/src/cuchaz/enigma/gui/ClassInheritanceTreeNode.java index d8e67554..61e582df 100644 --- a/src/cuchaz/enigma/gui/ClassInheritanceTreeNode.java +++ b/src/cuchaz/enigma/gui/ClassInheritanceTreeNode.java @@ -14,7 +14,7 @@ import java.util.List; import javax.swing.tree.DefaultMutableTreeNode; -import com.beust.jcommander.internal.Lists; +import com.google.common.collect.Lists; import cuchaz.enigma.mapping.Ancestries; import cuchaz.enigma.mapping.Translator; diff --git a/src/cuchaz/enigma/gui/Gui.java b/src/cuchaz/enigma/gui/Gui.java index 61e66e04..187852a2 100644 --- a/src/cuchaz/enigma/gui/Gui.java +++ b/src/cuchaz/enigma/gui/Gui.java @@ -62,12 +62,12 @@ import javax.swing.tree.TreePath; import jsyntaxpane.DefaultSyntaxKit; import jsyntaxpane.SyntaxDocument; -import jsyntaxpane.Token; -import com.beust.jcommander.internal.Lists; +import com.google.common.collect.Lists; import cuchaz.enigma.ClassFile; import cuchaz.enigma.Constants; +import cuchaz.enigma.analysis.Token; import cuchaz.enigma.mapping.ArgumentEntry; import cuchaz.enigma.mapping.ClassEntry; import cuchaz.enigma.mapping.Entry; @@ -643,7 +643,7 @@ public class Gui { try { - m_editor.getHighlighter().addHighlight( token.start, token.end(), painter ); + m_editor.getHighlighter().addHighlight( token.start, token.end, painter ); } catch( BadLocationException ex ) { @@ -740,22 +740,20 @@ public class Gui private void onCaretMove( int pos ) { - m_selectedEntryPair = m_controller.getEntryPair( pos ); - - boolean isEntry = m_selectedEntryPair != null; - boolean isClassEntry = isEntry && m_selectedEntryPair.obf instanceof ClassEntry; - boolean isMethodEntry = isEntry && m_selectedEntryPair.obf instanceof MethodEntry; - - if( isEntry ) - { - showEntryPair( m_selectedEntryPair ); - } - else + Token token = m_controller.getToken( pos ); + m_renameMenu.setEnabled( token != null ); + if( token == null ) { clearEntryPair(); + return; } - m_renameMenu.setEnabled( isEntry ); + m_selectedEntryPair = m_controller.getEntryPair( token ); + boolean isClassEntry = m_selectedEntryPair.obf instanceof ClassEntry; + boolean isMethodEntry = m_selectedEntryPair.obf instanceof MethodEntry; + + showEntryPair( m_selectedEntryPair ); + m_inheritanceMenu.setEnabled( isClassEntry || isMethodEntry ); m_openEntryMenu.setEnabled( isClassEntry ); } @@ -803,6 +801,7 @@ public class Gui int lineNum = doc.getLineNumberAt( m_editor.getCaretPosition() ); try { + // TODO: give token to the controller so we can put the caret back there m_controller.rename( m_selectedEntryPair.obf, newName, lineNum ); } catch( IllegalNameException ex ) diff --git a/src/cuchaz/enigma/gui/GuiController.java b/src/cuchaz/enigma/gui/GuiController.java index 2219e05b..e0aad860 100644 --- a/src/cuchaz/enigma/gui/GuiController.java +++ b/src/cuchaz/enigma/gui/GuiController.java @@ -17,15 +17,13 @@ import java.io.IOException; import java.util.List; import java.util.Map; -import jsyntaxpane.Token; - -import com.beust.jcommander.internal.Lists; -import com.beust.jcommander.internal.Maps; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; import cuchaz.enigma.ClassFile; import cuchaz.enigma.Deobfuscator; -import cuchaz.enigma.analysis.Analyzer; import cuchaz.enigma.analysis.SourceIndex; +import cuchaz.enigma.analysis.Token; import cuchaz.enigma.mapping.ClassEntry; import cuchaz.enigma.mapping.Entry; import cuchaz.enigma.mapping.EntryPair; @@ -105,41 +103,35 @@ public class GuiController deobfuscate( m_currentFile ); } - public EntryPair getEntryPair( int pos ) + public Token getToken( int pos ) { if( m_index == null ) { return null; } - Map.Entry deobfEntryAndToken = m_index.getEntry( pos ); - if( deobfEntryAndToken == null ) + return m_index.getToken( pos ); + } + + public EntryPair getEntryPair( Token token ) + { + if( m_index == null ) { return null; } - Entry deobfEntry = deobfEntryAndToken.getKey(); - Token token = deobfEntryAndToken.getValue(); - return new EntryPair( m_deobfuscator.obfuscateEntry( deobfEntry ), deobfEntry, token ); + + Entry deobfEntry = m_index.getEntry( token ); + return new EntryPair( m_deobfuscator.obfuscateEntry( deobfEntry ), deobfEntry ); } - public boolean entryHasMapping( int pos ) + public boolean entryHasMapping( Entry deobfEntry ) { - EntryPair pair = getEntryPair( pos ); - if( pair == null || pair.obf == null ) - { - return false; - } - return m_deobfuscator.hasMapping( pair.obf ); + return m_deobfuscator.hasMapping( m_deobfuscator.obfuscateEntry( deobfEntry ) ); } - public boolean entryIsObfuscatedIdenfitier( int pos ) + public boolean entryIsObfuscatedIdenfitier( Entry deobfEntry ) { - EntryPair pair = getEntryPair( pos ); - if( pair == null || pair.obf == null ) - { - return false; - } - return m_deobfuscator.entryIsObfuscatedIdenfitier( pair.obf ); + return m_deobfuscator.entryIsObfuscatedIdenfitier( m_deobfuscator.obfuscateEntry( deobfEntry ) ); } public ClassInheritanceTreeNode getClassInheritance( ClassEntry classEntry ) @@ -210,23 +202,21 @@ public class GuiController @Override public void run( ) { - // deobfuscate,decompile the bytecode - String source = m_deobfuscator.getSource( classFile ); - m_gui.setSource( source, lineNum ); - - // index the source file - m_index = Analyzer.analyze( classFile.getName(), source ); + // decopmile,deobfuscate the bytecode + m_index = m_deobfuscator.getSource( classFile ); + m_gui.setSource( m_index.getSource(), lineNum ); // set the highlighted tokens List obfuscatedTokens = Lists.newArrayList(); List deobfuscatedTokens = Lists.newArrayList(); for( Token token : m_index.tokens() ) { - if( entryHasMapping( token.start ) ) + Entry entry = m_index.getEntry( token ); + if( entryHasMapping( entry ) ) { deobfuscatedTokens.add( token ); } - else if( entryIsObfuscatedIdenfitier( token.start ) ) + else if( entryIsObfuscatedIdenfitier( entry ) ) { obfuscatedTokens.add( token ); } diff --git a/src/cuchaz/enigma/mapping/Ancestries.java b/src/cuchaz/enigma/mapping/Ancestries.java index f77a00eb..894cf802 100644 --- a/src/cuchaz/enigma/mapping/Ancestries.java +++ b/src/cuchaz/enigma/mapping/Ancestries.java @@ -26,7 +26,7 @@ import javassist.CtClass; import javassist.NotFoundException; import javassist.bytecode.Descriptor; -import com.beust.jcommander.internal.Lists; +import com.google.common.collect.Lists; import com.google.common.collect.Maps; import cuchaz.enigma.Constants; diff --git a/src/cuchaz/enigma/mapping/ClassMapping.java b/src/cuchaz/enigma/mapping/ClassMapping.java index a1cc775f..c6826f31 100644 --- a/src/cuchaz/enigma/mapping/ClassMapping.java +++ b/src/cuchaz/enigma/mapping/ClassMapping.java @@ -13,7 +13,7 @@ package cuchaz.enigma.mapping; import java.io.Serializable; import java.util.Map; -import com.beust.jcommander.internal.Maps; +import com.google.common.collect.Maps; public class ClassMapping implements Serializable, Comparable { @@ -135,16 +135,16 @@ public class ClassMapping implements Serializable, Comparable public void setMethodNameAndSignature( String obfName, String obfSignature, String deobfName, String deobfSignature ) { - MethodMapping methodIndex = m_methodsByObf.get( getMethodKey( obfName, obfSignature ) ); - if( methodIndex == null ) + MethodMapping methodMapping = m_methodsByObf.get( getMethodKey( obfName, obfSignature ) ); + if( methodMapping == null ) { - methodIndex = createMethodIndex( obfName, obfSignature ); + methodMapping = createMethodIndex( obfName, obfSignature ); } - m_methodsByDeobf.remove( getMethodKey( methodIndex.getDeobfName(), methodIndex.getDeobfSignature() ) ); - methodIndex.setDeobfName( deobfName ); - methodIndex.setDeobfSignature( deobfSignature ); - m_methodsByDeobf.put( getMethodKey( deobfName, deobfSignature ), methodIndex ); + m_methodsByDeobf.remove( getMethodKey( methodMapping.getDeobfName(), methodMapping.getDeobfSignature() ) ); + methodMapping.setDeobfName( deobfName ); + methodMapping.setDeobfSignature( deobfSignature ); + m_methodsByDeobf.put( getMethodKey( deobfName, deobfSignature ), methodMapping ); } public void updateDeobfMethodSignatures( Translator translator ) @@ -167,11 +167,11 @@ public class ClassMapping implements Serializable, Comparable private MethodMapping createMethodIndex( String obfName, String obfSignature ) { - MethodMapping methodIndex = new MethodMapping( obfName, obfName, obfSignature, obfSignature ); + MethodMapping methodMapping = new MethodMapping( obfName, obfName, obfSignature, obfSignature ); String key = getMethodKey( obfName, obfSignature ); - m_methodsByObf.put( key, methodIndex ); - m_methodsByDeobf.put( key, methodIndex ); - return methodIndex; + m_methodsByObf.put( key, methodMapping ); + m_methodsByDeobf.put( key, methodMapping ); + return methodMapping; } @Override diff --git a/src/cuchaz/enigma/mapping/EntryPair.java b/src/cuchaz/enigma/mapping/EntryPair.java index 1bf9be09..f94d77ea 100644 --- a/src/cuchaz/enigma/mapping/EntryPair.java +++ b/src/cuchaz/enigma/mapping/EntryPair.java @@ -10,19 +10,16 @@ ******************************************************************************/ package cuchaz.enigma.mapping; -import jsyntaxpane.Token; public class EntryPair { public T obf; public T deobf; - public Token token; - public EntryPair( T obf, T deobf, Token token ) + public EntryPair( T obf, T deobf ) { this.obf = obf; this.deobf = deobf; - this.token = token; } } diff --git a/src/cuchaz/enigma/mapping/Mappings.java b/src/cuchaz/enigma/mapping/Mappings.java index 2a39057a..4dff6935 100644 --- a/src/cuchaz/enigma/mapping/Mappings.java +++ b/src/cuchaz/enigma/mapping/Mappings.java @@ -17,7 +17,7 @@ import java.io.Serializable; import java.util.Map; import java.util.zip.GZIPInputStream; -import com.beust.jcommander.internal.Maps; +import com.google.common.collect.Maps; import cuchaz.enigma.Util; -- cgit v1.2.3