@ -1,83 +1,99 @@
/ *
* Copyright 2000 - 2014 JetBrains s . r . o .
*
* Licensed under the Apache License , Version 2 . 0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* You may obtain a copy of the License at
*
* http : //www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing , software
* distributed under the License is distributed on an "AS IS" BASIS ,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND , either express or implied .
* See the License for the specific language governing permissions and
* limitations under the License .
* /
package org.jetbrains.java.decompiler.main.collectors ;
package org.jetbrains.java.decompiler.main.collectors ;
import java.util.* ;
import java.util.Map.Entry ;
import org.jetbrains.java.decompiler.main.DecompilerContext ;
import org.jetbrains.java.decompiler.main.DecompilerContext ;
import org.jetbrains.java.decompiler.main.TextBuffer ;
import org.jetbrains.java.decompiler.main.TextBuffer ;
import java.util.* ;
import java.util.Map.Entry ;
public class BytecodeSourceMapper {
public class BytecodeSourceMapper {
private int offset_total ;
private int offset_total ;
private final HashMap < Integer , Integer > myOriginalLinesMapping = new HashMap < Integer , Integer > ( ) ;
// class, method, bytecode offset, source line
// class, method, bytecode offset, source line
private final Hash Map< String , Hash Map< String , Hash Map< Integer , Integer > > > mapping = new LinkedHashMap < String , Hash Map< String , Hash Map< Integer , Integer > > > ( ) ; // need to preserve order
private final Map < String , Map < String , Map < Integer , Integer > > > mapping = new LinkedHashMap < String , Map < String , Map < Integer , Integer > > > ( ) ;
public void addMapping ( String classname , String methodname , int bytecode_offset , int source_line ) {
// original line to decompiled line
private final Map < Integer , Integer > linesMapping = new LinkedHashMap < Integer , Integer > ( ) ;
HashMap < String , HashMap < Integer , Integer > > class_mapping = mapping . get ( classname ) ;
public void addMapping ( String className , String methodName , int bytecodeOffset , int sourceLine ) {
if ( class_mapping = = null ) {
Map < String , Map < Integer , Integer > > class_mapping = mapping . get ( className ) ;
mapping . put ( classname , class_mapping = new LinkedHashMap < String , HashMap < Integer , Integer > > ( ) ) ; // need to preserve order
if ( class_mapping = = null ) {
mapping . put ( className , class_mapping = new LinkedHashMap < String , Map < Integer , Integer > > ( ) ) ; // need to preserve order
}
}
Hash Map< Integer , Integer > method_mapping = class_mapping . get ( methodn ame ) ;
Map < Integer , Integer > method_mapping = class_mapping . get ( methodN ame ) ;
if ( method_mapping = = null ) {
if ( method_mapping = = null ) {
class_mapping . put ( methodn ame , method_mapping = new HashMap < Integer , Integer > ( ) ) ;
class_mapping . put ( methodN ame , method_mapping = new HashMap < Integer , Integer > ( ) ) ;
}
}
// don't overwrite
// don't overwrite
if ( ! method_mapping . containsKey ( bytecode_o ffset ) ) {
if ( ! method_mapping . containsKey ( bytecodeO ffset ) ) {
method_mapping . put ( bytecode_offset , source_l ine ) ;
method_mapping . put ( bytecodeOffset , sourceL ine ) ;
}
}
}
}
public void addTracer ( String classname , String methodn ame , BytecodeMappingTracer tracer ) {
public void addTracer ( String className , String methodN ame , BytecodeMappingTracer tracer ) {
for ( Entry < Integer , Integer > entry : tracer . getMapping ( ) . entrySet ( ) ) {
for ( Entry < Integer , Integer > entry : tracer . getMapping ( ) . entrySet ( ) ) {
addMapping ( classname , methodn ame , entry . getKey ( ) , entry . getValue ( ) ) ;
addMapping ( className , methodN ame , entry . getKey ( ) , entry . getValue ( ) ) ;
}
}
myOrigina lL inesMapping. putAll ( tracer . getOriginalLinesMapping ( ) ) ;
linesMapping . putAll ( tracer . getOriginalLinesMapping ( ) ) ;
}
}
public void dumpMapping ( TextBuffer buffer , boolean offsetsToHex ) {
public void dumpMapping ( TextBuffer buffer , boolean offsetsToHex ) {
String lineSeparator = DecompilerContext . getNewLineSeparator ( ) ;
String lineSeparator = DecompilerContext . getNewLineSeparator ( ) ;
for ( Entry < String , Hash Map< String , Hash Map< Integer , Integer > > > class_entry : mapping . entrySet ( ) ) {
for ( Entry < String , Map < String , Map < Integer , Integer > > > class_entry : mapping . entrySet ( ) ) {
Hash Map< String , Hash Map< Integer , Integer > > class_mapping = class_entry . getValue ( ) ;
Map < String , Map < Integer , Integer > > class_mapping = class_entry . getValue ( ) ;
buffer . append ( "class " + class_entry . getKey ( ) + "{" + lineSeparator ) ;
buffer . append ( "class '" + class_entry . getKey ( ) + "' {" + lineSeparator ) ;
boolean is_first_method = true ;
boolean is_first_method = true ;
for ( Entry < String , Map < Integer , Integer > > method_entry : class_mapping . entrySet ( ) ) {
Map < Integer , Integer > method_mapping = method_entry . getValue ( ) ;
for ( Entry < String , HashMap < Integer , Integer > > method_entry : class_mapping . entrySet ( ) ) {
if ( ! is_first_method ) {
HashMap < Integer , Integer > method_mapping = method_entry . getValue ( ) ;
if ( ! is_first_method ) {
buffer . appendLineSeparator ( ) ;
buffer . appendLineSeparator ( ) ;
}
}
buffer . appendIndent ( 1 ) . append ( "method " + method_entry . getKey ( ) + "{" + lineSeparator ) ;
buffer . appendIndent ( 1 ) . append ( "method '" + method_entry . getKey ( ) + "' {" + lineSeparator ) ;
List < Integer > lstBytecodeOffsets = new ArrayList < Integer > ( method_mapping . keySet ( ) ) ;
List < Integer > lstBytecodeOffsets = new ArrayList < Integer > ( method_mapping . keySet ( ) ) ;
Collections . sort ( lstBytecodeOffsets ) ;
Collections . sort ( lstBytecodeOffsets ) ;
for ( Integer offset : lstBytecodeOffsets ) {
for ( Integer offset : lstBytecodeOffsets ) {
Integer line = method_mapping . get ( offset ) ;
Integer line = method_mapping . get ( offset ) ;
String strOffset = offsetsToHex ? Integer . toHexString ( offset ) : line . toString ( ) ;
String strOffset = offsetsToHex ? Integer . toHexString ( offset ) : line . toString ( ) ;
buffer . appendIndent ( 2 ) . append ( strOffset ) . appendIndent ( 2 ) . append ( ( line + offset_total ) + lineSeparator ) ;
buffer . appendIndent ( 2 ) . append ( strOffset ) . appendIndent ( 2 ) . append ( ( line + offset_total ) + lineSeparator ) ;
}
}
buffer . appendIndent ( 1 ) . append ( "}" ) . appendLineSeparator ( ) ;
buffer . appendIndent ( 1 ) . append ( "}" ) . appendLineSeparator ( ) ;
is_first_method = false ;
is_first_method = false ;
}
}
buffer . append ( "}" ) . appendLineSeparator ( ) ;
buffer . append ( "}" ) . appendLineSeparator ( ) . appendLineSeparator ( ) ;
}
}
// lines mapping
// lines mapping
buffer . append ( "Lines mapping:" ) . appendLineSeparator ( ) ;
buffer . append ( "Lines mapping:" ) . appendLineSeparator ( ) ;
int [ ] mapping = getOriginalLinesMapping ( ) ;
int [ ] mapping = getOriginalLinesMapping ( ) ;
for ( int i = 0 ; i < mapping . length ; i + = 2 ) {
for ( int i = 0 ; i < mapping . length ; i + = 2 ) {
buffer . append ( mapping [ i ] ) . append ( " <-> " ) . append ( mapping [ i + 1 ] ) . appendLineSeparator ( ) ;
buffer . append ( mapping [ i ] ) . append ( " <-> " ) . append ( mapping [ i + 1 ] ) . appendLineSeparator ( ) ;
}
}
}
}
@ -94,15 +110,15 @@ public class BytecodeSourceMapper {
}
}
/ * *
/ * *
* original to our line mapping
* Original to decompiled line mapping .
* /
* /
public int [ ] getOriginalLinesMapping ( ) {
public int [ ] getOriginalLinesMapping ( ) {
int [ ] res = new int [ myOrigina lL inesMapping. size ( ) * 2 ] ;
int [ ] res = new int [ linesMapping . size ( ) * 2 ] ;
int i = 0 ;
int i = 0 ;
for ( Entry < Integer , Integer > entry : myOrigina lL inesMapping. entrySet ( ) ) {
for ( Entry < Integer , Integer > entry : linesMapping . entrySet ( ) ) {
res [ i ] = entry . getKey ( ) ;
res [ i ] = entry . getKey ( ) ;
res [ i + 1 ] = entry . getValue ( ) + offset_total + 1 ; // make it 1 based
res [ i + 1 ] = entry . getValue ( ) + offset_total + 1 ; // make it 1 based
i + = 2 ;
i + = 2 ;
}
}
return res ;
return res ;
}
}