Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
J
jadx
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
open-source
jadx
Commits
324f544b
Commit
324f544b
authored
May 30, 2014
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
gui: show source line numbers
parent
0a1981f9
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
242 additions
and
39 deletions
+242
-39
JavaClass.java
jadx-core/src/main/java/jadx/api/JavaClass.java
+5
-0
ClassGen.java
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
+0
-3
CodeWriter.java
jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
+29
-21
InsnGen.java
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
+3
-2
DotGraphVisitor.java
...src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
+3
-3
CodeArea.java
jadx-gui/src/main/java/jadx/gui/ui/CodeArea.java
+6
-2
CodePanel.java
jadx-gui/src/main/java/jadx/gui/ui/CodePanel.java
+5
-6
LineNumbers.java
jadx-gui/src/main/java/jadx/gui/ui/LineNumbers.java
+188
-0
MainWindow.java
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
+2
-2
TestJumpManager.groovy
...gui/src/test/groovy/jadx/gui/tests/TestJumpManager.groovy
+1
-0
No files found.
jadx-core/src/main/java/jadx/api/JavaClass.java
View file @
324f544b
...
...
@@ -130,6 +130,11 @@ public final class JavaClass {
return
null
;
}
public
Integer
getSourceLine
(
int
decompiledLine
)
{
decompile
();
return
cls
.
getCode
().
getLineMapping
().
get
(
decompiledLine
);
}
public
String
getFullName
()
{
return
cls
.
getFullName
();
}
...
...
jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
View file @
324f544b
...
...
@@ -63,12 +63,10 @@ public class ClassGen {
addClassCode
(
clsBody
);
CodeWriter
clsCode
=
new
CodeWriter
();
if
(!
""
.
equals
(
cls
.
getPackage
()))
{
clsCode
.
add
(
"package "
).
add
(
cls
.
getPackage
()).
add
(
';'
);
clsCode
.
newLine
();
}
int
importsCount
=
imports
.
size
();
if
(
importsCount
!=
0
)
{
List
<
String
>
sortImports
=
new
ArrayList
<
String
>(
importsCount
);
...
...
@@ -85,7 +83,6 @@ public class ClassGen {
sortImports
.
clear
();
imports
.
clear
();
}
clsCode
.
add
(
clsBody
);
return
clsCode
;
}
...
...
jadx-core/src/main/java/jadx/core/codegen/CodeWriter.java
View file @
324f544b
...
...
@@ -37,17 +37,13 @@ public class CodeWriter {
private
int
line
=
1
;
private
int
offset
=
0
;
private
Map
<
CodePosition
,
Object
>
annotations
=
Collections
.
emptyMap
();
private
Map
<
Integer
,
Integer
>
lineMap
=
Collections
.
emptyMap
();
public
CodeWriter
()
{
this
.
indent
=
0
;
this
.
indentStr
=
""
;
}
public
CodeWriter
(
int
indent
)
{
this
.
indent
=
indent
;
updateIndent
();
}
public
CodeWriter
startLine
()
{
addLine
();
addLineIndent
();
...
...
@@ -68,11 +64,6 @@ public class CodeWriter {
return
this
;
}
public
CodeWriter
add
(
Object
obj
)
{
add
(
obj
.
toString
());
return
this
;
}
public
CodeWriter
add
(
String
str
)
{
buf
.
append
(
str
);
offset
+=
str
.
length
();
...
...
@@ -91,6 +82,9 @@ public class CodeWriter {
CodePosition
pos
=
entry
.
getKey
();
attachAnnotation
(
entry
.
getValue
(),
new
CodePosition
(
line
+
pos
.
getLine
(),
pos
.
getOffset
()));
}
for
(
Map
.
Entry
<
Integer
,
Integer
>
entry
:
code
.
lineMap
.
entrySet
())
{
attachSourceLine
(
line
+
entry
.
getKey
(),
entry
.
getValue
());
}
line
+=
code
.
line
;
offset
=
code
.
offset
;
buf
.
append
(
code
);
...
...
@@ -102,6 +96,11 @@ public class CodeWriter {
return
this
;
}
public
CodeWriter
addIndent
()
{
add
(
INDENT
);
return
this
;
}
private
void
addLine
()
{
buf
.
append
(
NL
);
line
++;
...
...
@@ -114,11 +113,6 @@ public class CodeWriter {
return
this
;
}
public
CodeWriter
addIndent
()
{
add
(
INDENT
);
return
this
;
}
private
void
updateIndent
()
{
int
curIndent
=
indent
;
if
(
curIndent
<
INDENT_CACHE
.
length
)
{
...
...
@@ -178,17 +172,32 @@ public class CodeWriter {
return
attachAnnotation
(
obj
,
new
CodePosition
(
line
,
offset
+
1
));
}
private
Object
attachAnnotation
(
Object
obj
,
CodePosition
pos
)
{
if
(
annotations
.
isEmpty
())
{
annotations
=
new
HashMap
<
CodePosition
,
Object
>();
private
void
attachSourceLine
(
int
decompiledLine
,
int
sourceLine
)
{
if
(
lineMap
.
isEmpty
())
{
lineMap
=
new
HashMap
<
Integer
,
Integer
>();
}
return
annotations
.
put
(
pos
,
obj
);
lineMap
.
put
(
decompiledLine
,
sourceLine
);
}
public
Map
<
CodePosition
,
Object
>
getAnnotations
()
{
return
annotations
;
}
public
void
attachSourceLine
(
int
sourceLine
)
{
attachSourceLine
(
line
,
sourceLine
);
}
public
Map
<
Integer
,
Integer
>
getLineMapping
()
{
return
lineMap
;
}
private
Object
attachAnnotation
(
Object
obj
,
CodePosition
pos
)
{
if
(
annotations
.
isEmpty
())
{
annotations
=
new
HashMap
<
CodePosition
,
Object
>();
}
return
annotations
.
put
(
pos
,
obj
);
}
public
void
finish
()
{
buf
.
trimToSize
();
Iterator
<
Map
.
Entry
<
CodePosition
,
Object
>>
it
=
annotations
.
entrySet
().
iterator
();
...
...
@@ -206,9 +215,8 @@ public class CodeWriter {
private
static
String
removeFirstEmptyLine
(
String
str
)
{
if
(
str
.
startsWith
(
NL
))
{
return
str
.
substring
(
NL
.
length
());
}
else
{
return
str
;
}
return
str
;
}
public
int
length
()
{
...
...
jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
View file @
324f544b
...
...
@@ -198,7 +198,7 @@ public class InsnGen {
}
else
{
code
.
startLine
();
if
(
insn
.
getSourceLine
()
!=
0
)
{
code
.
attach
Annotation
(
insn
.
getSourceLine
());
code
.
attach
SourceLine
(
insn
.
getSourceLine
());
}
if
(
insn
.
getResult
()
!=
null
&&
insn
.
getType
()
!=
InsnType
.
ARITH_ONEARG
)
{
assignVar
(
code
,
insn
);
...
...
@@ -469,7 +469,8 @@ public class InsnGen {
code
.
add
(
") {"
);
code
.
incIndent
();
for
(
int
i
=
0
;
i
<
sw
.
getCasesCount
();
i
++)
{
code
.
startLine
(
"case "
).
add
(
sw
.
getKeys
()[
i
]).
add
(
": goto "
);
String
key
=
sw
.
getKeys
()[
i
].
toString
();
code
.
startLine
(
"case "
).
add
(
key
).
add
(
": goto "
);
code
.
add
(
MethodGen
.
getLabelName
(
sw
.
getTargets
()[
i
])).
add
(
';'
);
}
code
.
startLine
(
"default: goto "
);
...
...
jadx-core/src/main/java/jadx/core/dex/visitors/DotGraphVisitor.java
View file @
324f544b
...
...
@@ -120,7 +120,7 @@ public class DotGraphVisitor extends AbstractVisitor {
if
(
region
instanceof
IRegion
)
{
IRegion
r
=
(
IRegion
)
region
;
dot
.
startLine
(
"subgraph "
+
makeName
(
region
)
+
" {"
);
dot
.
startLine
(
"label = \""
).
add
(
r
);
dot
.
startLine
(
"label = \""
).
add
(
r
.
toString
()
);
String
attrs
=
attributesString
(
r
);
if
(
attrs
.
length
()
!=
0
)
{
dot
.
add
(
" | "
).
add
(
attrs
);
...
...
@@ -146,7 +146,7 @@ public class DotGraphVisitor extends AbstractVisitor {
dot
.
add
(
"color=red,"
);
}
dot
.
add
(
"label=\"{"
);
dot
.
add
(
block
.
getId
(
)).
add
(
"\\:\\ "
);
dot
.
add
(
String
.
valueOf
(
block
.
getId
()
)).
add
(
"\\:\\ "
);
dot
.
add
(
InsnUtils
.
formatOffset
(
block
.
getStartOffset
()));
if
(
attrs
.
length
()
!=
0
)
{
dot
.
add
(
'|'
).
add
(
attrs
);
...
...
@@ -210,7 +210,7 @@ public class DotGraphVisitor extends AbstractVisitor {
}
return
str
.
toString
();
}
else
{
CodeWriter
code
=
new
CodeWriter
(
0
);
CodeWriter
code
=
new
CodeWriter
();
MethodGen
.
addFallbackInsns
(
code
,
mth
,
block
.
getInstructions
(),
false
);
String
str
=
escape
(
code
.
newLine
().
toString
());
if
(
str
.
startsWith
(
NL
))
{
...
...
jadx-gui/src/main/java/jadx/gui/ui/CodeArea.java
View file @
324f544b
...
...
@@ -30,7 +30,7 @@ class CodeArea extends RSyntaxTextArea {
private
static
final
long
serialVersionUID
=
6312736869579635796L
;
p
rivate
static
final
Color
BACKGROUND
=
new
Color
(
0xf7f7f7
);
p
ublic
static
final
Color
BACKGROUND
=
new
Color
(
0xf7f7f7
);
private
static
final
Color
JUMP_FOREGROUND
=
new
Color
(
0x785523
);
private
static
final
Color
JUMP_BACKGROUND
=
new
Color
(
0xE6E6FF
);
...
...
@@ -96,7 +96,11 @@ class CodeArea extends RSyntaxTextArea {
}
Position
getCurrentPosition
()
{
return
new
Position
(
cls
,
getCaretLineNumber
());
return
new
Position
(
cls
,
getCaretLineNumber
()
+
1
);
}
Integer
getSourceLine
(
int
line
)
{
return
cls
.
getCls
().
getSourceLine
(
line
);
}
void
scrollToLine
(
int
line
)
{
...
...
jadx-gui/src/main/java/jadx/gui/ui/CodePanel.java
View file @
324f544b
...
...
@@ -5,14 +5,13 @@ import jadx.gui.utils.Utils;
import
javax.swing.AbstractAction
;
import
javax.swing.JPanel
;
import
javax.swing.JScrollPane
;
import
javax.swing.KeyStroke
;
import
java.awt.BorderLayout
;
import
java.awt.event.ActionEvent
;
import
java.awt.event.InputEvent
;
import
java.awt.event.KeyEvent
;
import
org.fife.ui.rtextarea.RTextScrollPane
;
class
CodePanel
extends
JPanel
{
private
static
final
long
serialVersionUID
=
5310536092010045565L
;
...
...
@@ -21,7 +20,7 @@ class CodePanel extends JPanel {
private
final
JClass
jClass
;
private
final
SearchBar
searchBar
;
private
final
CodeArea
codeArea
;
private
final
RText
ScrollPane
scrollPane
;
private
final
J
ScrollPane
scrollPane
;
CodePanel
(
TabbedPane
panel
,
JClass
cls
)
{
tabbedPane
=
panel
;
...
...
@@ -29,8 +28,8 @@ class CodePanel extends JPanel {
codeArea
=
new
CodeArea
(
this
);
searchBar
=
new
SearchBar
(
codeArea
);
scrollPane
=
new
RText
ScrollPane
(
codeArea
);
scrollPane
.
set
FoldIndicatorEnabled
(
true
);
scrollPane
=
new
J
ScrollPane
(
codeArea
);
scrollPane
.
set
RowHeaderView
(
new
LineNumbers
(
codeArea
)
);
setLayout
(
new
BorderLayout
());
add
(
searchBar
,
BorderLayout
.
NORTH
);
...
...
@@ -65,7 +64,7 @@ class CodePanel extends JPanel {
return
codeArea
;
}
RText
ScrollPane
getScrollPane
()
{
J
ScrollPane
getScrollPane
()
{
return
scrollPane
;
}
}
jadx-gui/src/main/java/jadx/gui/ui/LineNumbers.java
0 → 100644
View file @
324f544b
package
jadx
.
gui
.
ui
;
import
javax.swing.JPanel
;
import
javax.swing.border.Border
;
import
javax.swing.border.CompoundBorder
;
import
javax.swing.border.EmptyBorder
;
import
javax.swing.border.MatteBorder
;
import
javax.swing.event.CaretEvent
;
import
javax.swing.event.CaretListener
;
import
javax.swing.text.AttributeSet
;
import
javax.swing.text.BadLocationException
;
import
javax.swing.text.Element
;
import
javax.swing.text.StyleConstants
;
import
javax.swing.text.Utilities
;
import
java.awt.Color
;
import
java.awt.Dimension
;
import
java.awt.Font
;
import
java.awt.FontMetrics
;
import
java.awt.Graphics
;
import
java.awt.Insets
;
import
java.awt.Point
;
import
java.awt.Rectangle
;
import
java.awt.event.MouseAdapter
;
import
java.awt.event.MouseEvent
;
import
java.util.HashMap
;
public
class
LineNumbers
extends
JPanel
implements
CaretListener
{
private
final
static
Border
OUTER
=
new
MatteBorder
(
0
,
0
,
0
,
1
,
Color
.
LIGHT_GRAY
);
private
final
static
int
HEIGHT
=
Integer
.
MAX_VALUE
-
1000000
;
public
static
final
Color
FOREGROUND
=
Color
.
GRAY
;
public
static
final
Color
BACKGROUND
=
CodeArea
.
BACKGROUND
;
public
static
final
Color
CURRENT_LINE_FOREGROUND
=
new
Color
(
227
,
0
,
0
);
private
CodeArea
codeArea
;
private
boolean
useSourceLines
=
true
;
private
int
lastDigits
;
private
int
lastLine
;
private
HashMap
<
String
,
FontMetrics
>
fonts
;
public
LineNumbers
(
CodeArea
component
)
{
this
.
codeArea
=
component
;
setFont
(
component
.
getFont
());
setBackground
(
BACKGROUND
);
setForeground
(
FOREGROUND
);
setBorderGap
(
5
);
setPreferredWidth
();
component
.
addCaretListener
(
this
);
addMouseListener
(
new
MouseAdapter
()
{
@Override
public
void
mouseClicked
(
MouseEvent
e
)
{
if
(
e
.
getClickCount
()
==
2
)
{
useSourceLines
=
!
useSourceLines
;
repaint
();
}
}
});
}
public
void
setBorderGap
(
int
borderGap
)
{
Border
inner
=
new
EmptyBorder
(
0
,
borderGap
,
0
,
borderGap
);
setBorder
(
new
CompoundBorder
(
OUTER
,
inner
));
lastDigits
=
0
;
}
private
void
setPreferredWidth
()
{
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
int
lines
=
root
.
getElementCount
();
int
digits
=
Math
.
max
(
String
.
valueOf
(
lines
).
length
(),
3
);
if
(
lastDigits
!=
digits
)
{
lastDigits
=
digits
;
FontMetrics
fontMetrics
=
getFontMetrics
(
getFont
());
int
width
=
fontMetrics
.
charWidth
(
'0'
)
*
digits
;
Insets
insets
=
getInsets
();
int
preferredWidth
=
insets
.
left
+
insets
.
right
+
width
;
Dimension
d
=
getPreferredSize
();
if
(
d
!=
null
)
{
d
.
setSize
(
preferredWidth
,
HEIGHT
);
setPreferredSize
(
d
);
setSize
(
d
);
}
}
}
@Override
public
void
paintComponent
(
Graphics
g
)
{
super
.
paintComponent
(
g
);
FontMetrics
fontMetrics
=
codeArea
.
getFontMetrics
(
codeArea
.
getFont
());
Insets
insets
=
getInsets
();
int
availableWidth
=
getSize
().
width
-
insets
.
left
-
insets
.
right
;
Rectangle
clip
=
g
.
getClipBounds
();
int
rowStartOffset
=
codeArea
.
viewToModel
(
new
Point
(
0
,
clip
.
y
));
int
endOffset
=
codeArea
.
viewToModel
(
new
Point
(
0
,
clip
.
y
+
clip
.
height
));
while
(
rowStartOffset
<=
endOffset
)
{
try
{
if
(
isCurrentLine
(
rowStartOffset
))
{
g
.
setColor
(
CURRENT_LINE_FOREGROUND
);
}
else
{
g
.
setColor
(
FOREGROUND
);
}
String
lineNumber
=
getTextLineNumber
(
rowStartOffset
);
int
stringWidth
=
fontMetrics
.
stringWidth
(
lineNumber
);
int
x
=
availableWidth
-
stringWidth
+
insets
.
left
;
int
y
=
getOffsetY
(
rowStartOffset
,
fontMetrics
);
g
.
drawString
(
lineNumber
,
x
,
y
);
rowStartOffset
=
Utilities
.
getRowEnd
(
codeArea
,
rowStartOffset
)
+
1
;
}
catch
(
Exception
e
)
{
break
;
}
}
}
private
boolean
isCurrentLine
(
int
rowStartOffset
)
{
int
caretPosition
=
codeArea
.
getCaretPosition
();
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
return
root
.
getElementIndex
(
rowStartOffset
)
==
root
.
getElementIndex
(
caretPosition
);
}
protected
String
getTextLineNumber
(
int
rowStartOffset
)
{
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
int
index
=
root
.
getElementIndex
(
rowStartOffset
);
Element
line
=
root
.
getElement
(
index
);
if
(
line
.
getStartOffset
()
==
rowStartOffset
)
{
int
lineNumber
=
index
+
1
;
if
(
useSourceLines
)
{
Integer
sourceLine
=
codeArea
.
getSourceLine
(
lineNumber
);
if
(
sourceLine
!=
null
)
{
return
String
.
valueOf
(
sourceLine
);
}
}
else
{
return
String
.
valueOf
(
lineNumber
);
}
}
return
""
;
}
private
int
getOffsetY
(
int
rowStartOffset
,
FontMetrics
fontMetrics
)
throws
BadLocationException
{
Rectangle
r
=
codeArea
.
modelToView
(
rowStartOffset
);
if
(
r
==
null
)
{
throw
new
BadLocationException
(
"Can't get Y offset"
,
rowStartOffset
);
}
int
lineHeight
=
fontMetrics
.
getHeight
();
int
y
=
r
.
y
+
r
.
height
;
int
descent
=
0
;
if
(
r
.
height
==
lineHeight
)
{
descent
=
fontMetrics
.
getDescent
();
}
else
{
if
(
fonts
==
null
)
{
fonts
=
new
HashMap
<
String
,
FontMetrics
>();
}
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
int
index
=
root
.
getElementIndex
(
rowStartOffset
);
Element
line
=
root
.
getElement
(
index
);
for
(
int
i
=
0
;
i
<
line
.
getElementCount
();
i
++)
{
Element
child
=
line
.
getElement
(
i
);
AttributeSet
as
=
child
.
getAttributes
();
String
fontFamily
=
(
String
)
as
.
getAttribute
(
StyleConstants
.
FontFamily
);
Integer
fontSize
=
(
Integer
)
as
.
getAttribute
(
StyleConstants
.
FontSize
);
String
key
=
fontFamily
+
fontSize
;
FontMetrics
fm
=
fonts
.
get
(
key
);
if
(
fm
==
null
)
{
Font
font
=
new
Font
(
fontFamily
,
Font
.
PLAIN
,
fontSize
);
fm
=
codeArea
.
getFontMetrics
(
font
);
fonts
.
put
(
key
,
fm
);
}
descent
=
Math
.
max
(
descent
,
fm
.
getDescent
());
}
}
return
y
-
descent
;
}
@Override
public
void
caretUpdate
(
CaretEvent
e
)
{
int
caretPosition
=
codeArea
.
getCaretPosition
();
Element
root
=
codeArea
.
getDocument
().
getDefaultRootElement
();
int
currentLine
=
root
.
getElementIndex
(
caretPosition
);
if
(
lastLine
!=
currentLine
)
{
repaint
();
lastLine
=
currentLine
;
}
}
}
jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java
View file @
324f544b
...
...
@@ -54,13 +54,13 @@ public class MainWindow extends JFrame {
private
static
final
double
BORDER_RATIO
=
0.15
;
private
static
final
double
WINDOW_RATIO
=
1
-
BORDER_RATIO
*
2
;
private
static
final
double
SPLIT_PANE_RESIZE_WEIGHT
=
0.15
;
private
static
final
ImageIcon
ICON_OPEN
=
Utils
.
openIcon
(
"folder"
);
private
static
final
ImageIcon
ICON_SAVE_ALL
=
Utils
.
openIcon
(
"disk_multiple"
);
private
static
final
ImageIcon
ICON_CLOSE
=
Utils
.
openIcon
(
"cross"
);
private
static
final
ImageIcon
ICON_FLAT_PKG
=
Utils
.
openIcon
(
"empty_logical_package_obj"
);
private
static
final
ImageIcon
ICON_SEARCH
=
Utils
.
openIcon
(
"magnifier"
);
private
static
final
ImageIcon
ICON_BACK
=
Utils
.
openIcon
(
"icon_back"
);
private
static
final
ImageIcon
ICON_FORWARD
=
Utils
.
openIcon
(
"icon_forward"
);
...
...
@@ -248,7 +248,7 @@ public class MainWindow extends JFrame {
private
void
initUI
()
{
mainPanel
=
new
JPanel
(
new
BorderLayout
());
JSplitPane
splitPane
=
new
JSplitPane
();
splitPane
.
setResizeWeight
(
0.2
);
splitPane
.
setResizeWeight
(
SPLIT_PANE_RESIZE_WEIGHT
);
mainPanel
.
add
(
splitPane
);
DefaultMutableTreeNode
treeRoot
=
new
DefaultMutableTreeNode
(
"Please open file"
);
...
...
jadx-gui/src/test/groovy/jadx/gui/tests/TestJumpManager.groovy
View file @
324f544b
...
...
@@ -36,6 +36,7 @@ class TestJumpManager extends Specification {
then:
noExceptionThrown
()
jm
.
getPrev
()
==
mock1
jm
.
getPrev
()
==
null
jm
.
getNext
()
==
mock2
jm
.
getNext
()
==
null
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment