Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in / Register
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
3b84aec5
Commit
3b84aec5
authored
Apr 14, 2013
by
Skylot
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add generic types to methods declarations
parent
cc318b13
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
250 additions
and
80 deletions
+250
-80
AnnotationGen.java
src/main/java/jadx/codegen/AnnotationGen.java
+8
-4
ClassGen.java
src/main/java/jadx/codegen/ClassGen.java
+23
-1
InsnGen.java
src/main/java/jadx/codegen/InsnGen.java
+3
-23
MethodGen.java
src/main/java/jadx/codegen/MethodGen.java
+3
-4
LocalVarInfo.java
src/main/java/jadx/dex/info/LocalVarInfo.java
+1
-1
InsnDecoder.java
src/main/java/jadx/dex/instructions/InsnDecoder.java
+1
-1
ArgType.java
src/main/java/jadx/dex/instructions/args/ArgType.java
+83
-27
MethodNode.java
src/main/java/jadx/dex/nodes/MethodNode.java
+60
-14
ConstInlinerVisitor.java
src/main/java/jadx/dex/visitors/ConstInlinerVisitor.java
+1
-1
DotGraphVisitor.java
src/main/java/jadx/dex/visitors/DotGraphVisitor.java
+1
-1
PostRegionVisitor.java
...ain/java/jadx/dex/visitors/regions/PostRegionVisitor.java
+1
-1
Utils.java
src/main/java/jadx/utils/Utils.java
+17
-2
TestCF3.java
src/samples/java/jadx/samples/TestCF3.java
+13
-0
TestGenerics.java
src/samples/java/jadx/samples/TestGenerics.java
+35
-0
No files found.
src/main/java/jadx/codegen/AnnotationGen.java
View file @
3b84aec5
...
...
@@ -62,11 +62,15 @@ public class AnnotationGen {
String
aCls
=
a
.
getAnnotationClass
();
if
(
aCls
.
startsWith
(
"dalvik.annotation."
))
{
// skip
if
(
aCls
.
equals
(
"dalvik.annotation.Signature"
))
code
.
startLine
(
"// signature: "
+
Utils
.
mergeSignature
((
List
<
String
>)
a
.
getValues
().
get
(
"value"
)));
else
if
(
Consts
.
DEBUG
)
if
(
aCls
.
equals
(
"dalvik.annotation.Signature"
))
{
if
(!(
node
instanceof
MethodNode
))
{
String
sign
=
Utils
.
mergeSignature
((
List
<
String
>)
a
.
getValues
().
get
(
"value"
));
List
<
ArgType
>
types
=
ArgType
.
parseSignatureList
(
sign
);
code
.
startLine
(
"// signature: "
+
Utils
.
listToString
(
types
));
}
}
else
if
(
Consts
.
DEBUG
)
{
code
.
startLine
(
"// "
+
a
);
}
}
else
{
code
.
startLine
();
code
.
add
(
formatAnnotation
(
a
));
...
...
src/main/java/jadx/codegen/ClassGen.java
View file @
3b84aec5
...
...
@@ -248,7 +248,29 @@ public class ClassGen {
}
public
String
useClass
(
ArgType
clsType
)
{
return
useClass
(
ClassInfo
.
fromType
(
cls
.
dex
(),
clsType
));
String
baseClass
=
useClass
(
ClassInfo
.
fromType
(
cls
.
dex
(),
clsType
));
ArgType
[]
generics
=
clsType
.
getGenericTypes
();
if
(
generics
!=
null
)
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
baseClass
);
sb
.
append
(
"<"
);
int
len
=
generics
.
length
;
for
(
int
i
=
0
;
i
<
len
;
i
++)
{
if
(
i
!=
0
)
{
sb
.
append
(
", "
);
}
ArgType
gt
=
generics
[
i
];
if
(
gt
.
isTypeKnown
())
sb
.
append
(
useClass
(
gt
));
else
sb
.
append
(
'?'
);
}
sb
.
append
(
">"
);
return
sb
.
toString
();
}
else
{
return
baseClass
;
}
}
public
String
useClass
(
ClassInfo
classInfo
)
{
...
...
src/main/java/jadx/codegen/InsnGen.java
View file @
3b84aec5
...
...
@@ -94,19 +94,7 @@ public class InsnGen {
}
public
String
declareVar
(
RegisterArg
arg
)
throws
CodegenException
{
String
type
=
useType
(
arg
.
getType
());
ArgType
[]
generics
=
arg
.
getType
().
getGenericTypes
();
if
(
generics
!=
null
)
{
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
type
);
sb
.
append
(
"/*<"
);
for
(
ArgType
gt
:
generics
)
{
sb
.
append
(
useType
(
gt
));
}
sb
.
append
(
">*/"
);
type
=
sb
.
toString
();
}
return
type
+
" "
+
arg
(
arg
);
return
useType
(
arg
.
getType
())
+
" "
+
arg
(
arg
);
}
private
String
lit
(
LiteralArg
arg
)
{
...
...
@@ -144,13 +132,6 @@ public class InsnGen {
}
private
String
useType
(
ArgType
type
)
{
if
(
type
.
isObject
())
return
mgen
.
getClassGen
().
useClass
(
type
);
else
return
translate
(
type
);
}
private
String
translate
(
ArgType
type
)
{
return
TypeGen
.
translate
(
mgen
.
getClassGen
(),
type
);
}
...
...
@@ -160,7 +141,6 @@ public class InsnGen {
private
void
makeInsn
(
InsnNode
insn
,
CodeWriter
code
,
boolean
bodyOnly
)
throws
CodegenException
{
try
{
// code.startLine("/* " + insn + "*/");
EnumSet
<
InsnGenState
>
state
=
EnumSet
.
noneOf
(
InsnGenState
.
class
);
if
(
bodyOnly
)
{
state
.
add
(
InsnGenState
.
BODY_ONLY
);
...
...
@@ -213,7 +193,7 @@ public class InsnGen {
case
CHECK_CAST:
case
CAST:
code
.
add
(
"(("
);
code
.
add
(
translat
e
(((
ArgType
)
((
IndexInsnNode
)
insn
).
getIndex
())));
code
.
add
(
useTyp
e
(((
ArgType
)
((
IndexInsnNode
)
insn
).
getIndex
())));
code
.
add
(
") ("
);
code
.
add
(
arg
(
insn
.
getArg
(
0
)));
code
.
add
(
"))"
);
...
...
@@ -445,7 +425,7 @@ public class InsnGen {
}
int
len
=
str
.
length
();
str
.
delete
(
len
-
2
,
len
);
code
.
add
(
"new "
).
add
(
translat
e
(
elType
)).
add
(
"[] { "
).
add
(
str
.
toString
()).
add
(
" }"
);
code
.
add
(
"new "
).
add
(
useTyp
e
(
elType
)).
add
(
"[] { "
).
add
(
str
.
toString
()).
add
(
" }"
);
}
private
void
makeConstructor
(
ConstructorInsn
insn
,
CodeWriter
code
,
EnumSet
<
InsnGenState
>
state
)
...
...
src/main/java/jadx/codegen/MethodGen.java
View file @
3b84aec5
...
...
@@ -81,13 +81,12 @@ public class MethodGen {
if
(
mth
.
getAccessFlags
().
isConstructor
())
{
code
.
add
(
classGen
.
getClassNode
().
getShortName
());
// constructor
}
else
{
code
.
add
(
TypeGen
.
translate
(
classGen
,
mth
.
get
MethodInfo
().
get
ReturnType
()));
code
.
add
(
" "
);
code
.
add
(
TypeGen
.
translate
(
classGen
,
mth
.
getReturnType
()));
code
.
add
(
' '
);
code
.
add
(
mth
.
getName
());
}
code
.
add
(
"("
);
code
.
add
(
'('
);
mth
.
resetArgsTypes
();
List
<
RegisterArg
>
args
=
mth
.
getArguments
(
false
);
if
(
mth
.
getMethodInfo
().
isConstructor
()
&&
mth
.
getParentClass
().
getAttributes
().
contains
(
AttributeType
.
ENUM_CLASS
))
{
...
...
src/main/java/jadx/dex/info/LocalVarInfo.java
View file @
3b84aec5
...
...
@@ -28,7 +28,7 @@ public class LocalVarInfo extends RegisterArg {
private
void
init
(
String
name
,
ArgType
type
,
String
sign
)
{
if
(
sign
!=
null
)
{
type
=
ArgType
.
generic
(
type
.
getObject
(),
sign
);
type
=
ArgType
.
generic
(
sign
);
}
TypedVar
tv
=
new
TypedVar
(
type
);
tv
.
setName
(
name
);
...
...
src/main/java/jadx/dex/instructions/InsnDecoder.java
View file @
3b84aec5
...
...
@@ -401,7 +401,7 @@ public class InsnDecoder {
case
Opcodes
.
RETURN_OBJECT
:
return
insn
(
InsnType
.
RETURN
,
null
,
InsnArg
.
reg
(
insn
,
0
,
method
.
get
MethodInfo
().
get
ReturnType
()));
InsnArg
.
reg
(
insn
,
0
,
method
.
getReturnType
()));
case
Opcodes
.
INSTANCE_OF
:
{
InsnNode
node
=
new
IndexInsnNode
(
method
,
InsnType
.
INSTANCE_OF
,
dex
.
getType
(
insn
.
getIndex
()),
1
);
...
...
src/main/java/jadx/dex/instructions/args/ArgType.java
View file @
3b84aec5
...
...
@@ -24,6 +24,7 @@ public abstract class ArgType {
public
static
final
ArgType
THROWABLE
=
object
(
Consts
.
CLASS_THROWABLE
);
public
static
final
ArgType
UNKNOWN
=
unknown
(
PrimitiveType
.
values
());
public
static
final
ArgType
UNKNOWN_OBJECT
=
unknown
(
PrimitiveType
.
OBJECT
,
PrimitiveType
.
ARRAY
);
public
static
final
ArgType
NARROW
=
unknown
(
PrimitiveType
.
INT
,
PrimitiveType
.
FLOAT
,
...
...
@@ -32,8 +33,6 @@ public abstract class ArgType {
public
static
final
ArgType
WIDE
=
unknown
(
PrimitiveType
.
LONG
,
PrimitiveType
.
DOUBLE
);
public
static
final
ArgType
UNKNOWN_OBJECT
=
unknown
(
PrimitiveType
.
OBJECT
,
PrimitiveType
.
ARRAY
);
protected
int
hash
;
private
static
ArgType
primitive
(
PrimitiveType
stype
)
{
...
...
@@ -41,11 +40,15 @@ public abstract class ArgType {
}
public
static
ArgType
object
(
String
obj
)
{
return
new
ObjectArg
(
Utils
.
cleanObjectName
(
obj
)
);
return
new
ObjectArg
(
obj
);
}
public
static
ArgType
generic
(
String
obj
,
String
signature
)
{
return
new
GenericObjectArg
(
obj
,
signature
);
public
static
ArgType
generic
(
String
sign
)
{
return
parseSignature
(
sign
);
}
public
static
ArgType
generic
(
String
obj
,
ArgType
[]
generics
)
{
return
new
GenericObjectArg
(
obj
,
generics
);
}
public
static
ArgType
array
(
ArgType
vtype
)
{
...
...
@@ -91,7 +94,7 @@ public abstract class ArgType {
private
final
String
object
;
public
ObjectArg
(
String
obj
)
{
this
.
object
=
obj
;
this
.
object
=
Utils
.
cleanObjectName
(
obj
)
;
this
.
hash
=
obj
.
hashCode
();
}
...
...
@@ -119,9 +122,9 @@ public abstract class ArgType {
private
static
final
class
GenericObjectArg
extends
ObjectArg
{
private
final
ArgType
[]
generics
;
public
GenericObjectArg
(
String
obj
,
String
signature
)
{
public
GenericObjectArg
(
String
obj
,
ArgType
[]
generics
)
{
super
(
obj
);
this
.
generics
=
parseSignature
(
signature
)
;
this
.
generics
=
generics
;
this
.
hash
=
obj
.
hashCode
()
+
31
*
Arrays
.
hashCode
(
generics
);
}
...
...
@@ -132,7 +135,7 @@ public abstract class ArgType {
@Override
public
String
toString
()
{
return
super
.
toString
()
+
"<"
+
Arrays
.
t
oString
(
generics
)
+
">"
;
return
super
.
toString
()
+
"<"
+
Utils
.
arrayT
oString
(
generics
)
+
">"
;
}
}
...
...
@@ -177,7 +180,7 @@ public abstract class ArgType {
@Override
public
String
toString
()
{
return
arrayElement
.
toString
();
return
arrayElement
.
toString
()
+
"[]"
;
}
}
...
...
@@ -220,7 +223,7 @@ public abstract class ArgType {
@Override
public
String
toString
()
{
if
(
possibleTypes
.
length
==
PrimitiveType
.
values
().
length
)
return
"
*
"
;
return
"
?
"
;
else
return
"?"
+
Arrays
.
toString
(
possibleTypes
);
}
...
...
@@ -363,30 +366,83 @@ public abstract class ArgType {
}
}
public
static
ArgType
[]
parseSignature
(
String
signature
)
{
int
b
=
signature
.
indexOf
(
'<'
)
+
1
;
int
e
=
signature
.
lastIndexOf
(
'>'
);
String
gens
=
signature
.
substring
(
b
,
e
);
String
[]
split
=
gens
.
split
(
";"
);
ArgType
[]
result
=
new
ArgType
[
split
.
length
];
for
(
int
i
=
0
;
i
<
split
.
length
;
i
++)
{
String
g
=
split
[
i
];
switch
(
g
.
charAt
(
0
))
{
public
static
ArgType
parseSignature
(
String
sign
)
{
int
b
=
sign
.
indexOf
(
'<'
);
if
(
b
==
-
1
)
return
parse
(
sign
);
String
obj
=
sign
.
substring
(
0
,
b
);
String
genericsStr
=
sign
.
substring
(
b
+
1
,
sign
.
length
()
-
2
);
List
<
ArgType
>
generics
=
parseSignatureList
(
genericsStr
);
ArgType
res
=
generic
(
obj
+
";"
,
generics
.
toArray
(
new
ArgType
[
generics
.
size
()]));
return
res
;
}
public
static
List
<
ArgType
>
parseSignatureList
(
String
str
)
{
List
<
ArgType
>
signs
=
new
ArrayList
<
ArgType
>(
3
);
if
(
str
.
equals
(
"*"
))
{
signs
.
add
(
UNKNOWN
);
return
signs
;
}
int
obj
=
0
;
int
objStart
=
0
;
int
gen
=
0
;
int
arr
=
0
;
int
pos
=
0
;
ArgType
type
=
null
;
while
(
pos
<
str
.
length
())
{
char
c
=
str
.
charAt
(
pos
);
switch
(
c
)
{
case
'L'
:
result
[
i
]
=
object
(
g
+
";"
);
if
(
obj
==
0
&&
gen
==
0
)
{
obj
++;
objStart
=
pos
;
}
break
;
case
'*'
:
case
'?'
:
result
[
i
]
=
UNKNOWN
;
case
';'
:
if
(
obj
==
1
&&
gen
==
0
)
{
obj
--;
String
o
=
str
.
substring
(
objStart
,
pos
+
1
);
type
=
parseSignature
(
o
);
}
break
;
case
'<'
:
gen
++;
break
;
case
'>'
:
gen
--;
break
;
case
'['
:
arr
++;
break
;
default
:
result
[
i
]
=
UNKNOWN_OBJECT
;
if
(
obj
==
0
&&
gen
==
0
)
{
type
=
parse
(
c
);
}
break
;
}
if
(
type
!=
null
)
{
if
(
arr
==
0
)
{
signs
.
add
(
type
);
}
else
{
for
(
int
i
=
0
;
i
<
arr
;
i
++)
{
type
=
array
(
type
);
}
signs
.
add
(
type
);
arr
=
0
;
}
return
result
;
type
=
null
;
}
pos
++;
}
return
signs
;
}
private
static
ArgType
parse
(
char
f
)
{
...
...
@@ -410,7 +466,7 @@ public abstract class ArgType {
case
'V'
:
return
VOID
;
}
throw
new
RuntimeException
(
"Unknown type: "
+
f
)
;
return
null
;
}
public
int
getRegCount
()
{
...
...
src/main/java/jadx/dex/nodes/MethodNode.java
View file @
3b84aec5
...
...
@@ -2,7 +2,10 @@ package jadx.dex.nodes;
import
jadx.dex.attributes.AttrNode
;
import
jadx.dex.attributes.AttributeFlag
;
import
jadx.dex.attributes.AttributeType
;
import
jadx.dex.attributes.JumpAttribute
;
import
jadx.dex.attributes.annotations.Annotation
;
import
jadx.dex.attributes.annotations.AnnotationsList
;
import
jadx.dex.info.AccessInfo
;
import
jadx.dex.info.AccessInfo.AFType
;
import
jadx.dex.info.ClassInfo
;
...
...
@@ -28,12 +31,16 @@ import java.util.HashSet;
import
java.util.List
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
com.android.dx.io.ClassData.Method
;
import
com.android.dx.io.Code
;
import
com.android.dx.io.Code.CatchHandler
;
import
com.android.dx.io.Code.Try
;
public
class
MethodNode
extends
AttrNode
implements
ILoadable
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
MethodNode
.
class
);
private
final
MethodInfo
mthInfo
;
private
final
ClassNode
parentClass
;
...
...
@@ -44,6 +51,7 @@ public class MethodNode extends AttrNode implements ILoadable {
private
List
<
InsnNode
>
instructions
;
private
boolean
noCode
;
private
ArgType
retType
;
private
RegisterArg
thisArg
;
private
List
<
RegisterArg
>
argsList
;
...
...
@@ -65,7 +73,8 @@ public class MethodNode extends AttrNode implements ILoadable {
if
(
methodData
.
getCodeOffset
()
==
0
)
{
noCode
=
true
;
regsCount
=
0
;
initArguments
();
retType
=
mthInfo
.
getReturnType
();
initArguments
(
mthInfo
.
getArgumentsTypes
());
}
else
{
noCode
=
false
;
}
...
...
@@ -81,6 +90,11 @@ public class MethodNode extends AttrNode implements ILoadable {
Code
mthCode
=
dex
.
readCode
(
methodData
);
regsCount
=
mthCode
.
getRegistersSize
();
if
(!
parseSignature
())
{
retType
=
mthInfo
.
getReturnType
();
initArguments
(
mthInfo
.
getArgumentsTypes
());
}
InsnDecoder
decoder
=
new
InsnDecoder
(
this
,
mthCode
);
InsnNode
[]
insnByOffset
=
decoder
.
run
();
instructions
=
new
ArrayList
<
InsnNode
>();
...
...
@@ -90,7 +104,6 @@ public class MethodNode extends AttrNode implements ILoadable {
}
((
ArrayList
<
InsnNode
>)
instructions
).
trimToSize
();
initArguments
();
initTryCatches
(
mthCode
,
insnByOffset
);
initJumps
(
insnByOffset
);
...
...
@@ -116,8 +129,43 @@ public class MethodNode extends AttrNode implements ILoadable {
noCode
=
true
;
}
private
void
initArguments
()
{
List
<
ArgType
>
args
=
mthInfo
.
getArgumentsTypes
();
@SuppressWarnings
(
"unchecked"
)
private
boolean
parseSignature
()
{
AnnotationsList
aList
=
(
AnnotationsList
)
getAttributes
().
get
(
AttributeType
.
ANNOTATION_LIST
);
if
(
aList
==
null
||
aList
.
size
()
==
0
)
return
false
;
Annotation
a
=
aList
.
get
(
"dalvik.annotation.Signature"
);
if
(
a
==
null
)
return
false
;
String
sign
=
Utils
.
mergeSignature
((
List
<
String
>)
a
.
getValues
().
get
(
"value"
));
int
lastBracket
=
sign
.
indexOf
(
')'
);
String
argsTypesStr
=
sign
.
substring
(
1
,
lastBracket
);
String
returnType
=
sign
.
substring
(
lastBracket
+
1
);
retType
=
ArgType
.
parseSignature
(
returnType
);
if
(
mthInfo
.
getArgumentsTypes
().
isEmpty
())
{
argsList
=
Collections
.
emptyList
();
return
true
;
}
List
<
ArgType
>
argsTypes
=
ArgType
.
parseSignatureList
(
argsTypesStr
);
if
(
argsTypes
.
size
()
!=
mthInfo
.
getArgumentsTypes
().
size
())
{
if
(!
getParentClass
().
getAccessFlags
().
isEnum
()
&&
!
mthInfo
.
isConstructor
())
{
// error parsing signature
LOG
.
error
(
"Wrong parse result: "
+
sign
+
" -> "
+
argsTypes
+
" must be: "
+
mthInfo
.
getArgumentsTypes
()
// + " in method " + this
);
}
return
false
;
}
initArguments
(
argsTypes
);
return
true
;
}
private
void
initArguments
(
List
<
ArgType
>
args
)
{
int
pos
;
if
(!
noCode
)
{
pos
=
regsCount
;
...
...
@@ -134,6 +182,11 @@ public class MethodNode extends AttrNode implements ILoadable {
thisArg
.
getTypedVar
().
setName
(
"this"
);
}
if
(
args
.
isEmpty
())
{
argsList
=
Collections
.
emptyList
();
return
;
}
argsList
=
new
ArrayList
<
RegisterArg
>(
args
.
size
());
for
(
ArgType
arg
:
args
)
{
argsList
.
add
(
InsnArg
.
reg
(
pos
,
arg
));
...
...
@@ -156,15 +209,8 @@ public class MethodNode extends AttrNode implements ILoadable {
return
thisArg
;
}
// TODO: args types can change during type resolving => reset and copy back names
@Deprecated
public
void
resetArgsTypes
()
{
List
<
InsnArg
>
modArgs
=
new
ArrayList
<
InsnArg
>(
argsList
);
initArguments
();
for
(
int
i
=
0
;
i
<
argsList
.
size
();
i
++)
{
argsList
.
get
(
i
).
getTypedVar
().
setName
(
modArgs
.
get
(
i
).
getTypedVar
().
getName
());
}
public
ArgType
getReturnType
()
{
return
retType
;
}
// move to external class
...
...
@@ -394,7 +440,7 @@ public class MethodNode extends AttrNode implements ILoadable {
@Override
public
String
toString
()
{
return
mthInfo
.
getReturnType
()
return
retType
+
" "
+
parentClass
.
getFullName
()
+
"."
+
mthInfo
.
getName
()
+
"("
+
Utils
.
listToString
(
mthInfo
.
getArgumentsTypes
())
+
")"
;
}
...
...
src/main/java/jadx/dex/visitors/ConstInlinerVisitor.java
View file @
3b84aec5
...
...
@@ -137,7 +137,7 @@ public class ConstInlinerVisitor extends AbstractVisitor {
case
RETURN:
if
(
insn
.
getArgsCount
()
!=
0
)
{
insn
.
getArg
(
0
).
merge
(
mth
.
get
MethodInfo
().
get
ReturnType
());
insn
.
getArg
(
0
).
merge
(
mth
.
getReturnType
());
}
break
;
...
...
src/main/java/jadx/dex/visitors/DotGraphVisitor.java
View file @
3b84aec5
...
...
@@ -64,7 +64,7 @@ public class DotGraphVisitor extends AbstractVisitor {
dot
.
startLine
(
"MethodNode[shape=record,label=\"{"
+
escape
(
mth
.
getAccessFlags
().
makeString
())
+
escape
(
mth
.
get
MethodInfo
().
get
ReturnType
()
+
" "
+
escape
(
mth
.
getReturnType
()
+
" "
+
mth
.
getParentClass
().
getFullName
()
+
"."
+
mth
.
getName
()
+
"("
+
Utils
.
listToString
(
mth
.
getArguments
(
true
))
+
") "
)
+
(
attrs
.
length
()
==
0
?
""
:
" | "
+
attrs
)
...
...
src/main/java/jadx/dex/visitors/regions/PostRegionVisitor.java
View file @
3b84aec5
...
...
@@ -29,7 +29,7 @@ public class PostRegionVisitor extends AbstractVisitor {
* Remove useless return at end
*/
private
void
removeReturn
(
MethodNode
mth
)
{
if
(!
mth
.
get
MethodInfo
().
get
ReturnType
().
equals
(
ArgType
.
VOID
))
if
(!
mth
.
getReturnType
().
equals
(
ArgType
.
VOID
))
return
;
if
(!(
mth
.
getRegion
()
instanceof
Region
))
...
...
src/main/java/jadx/utils/Utils.java
View file @
3b84aec5
...
...
@@ -28,8 +28,13 @@ public class Utils {
}
public
static
String
escape
(
String
str
)
{
return
str
.
replace
(
'.'
,
'_'
).
replace
(
'/'
,
'_'
).
replace
(
';'
,
'_'
)
.
replace
(
'$'
,
'_'
).
replace
(
"[]"
,
"_A"
);
return
str
.
replace
(
'.'
,
'_'
)
.
replace
(
'/'
,
'_'
)
.
replace
(
';'
,
'_'
)
.
replace
(
'$'
,
'_'
)
.
replace
(
'<'
,
'_'
)
.
replace
(
'>'
,
'_'
)
.
replace
(
"[]"
,
"_A"
);
}
public
static
String
listToString
(
Iterable
<?>
list
)
{
...
...
@@ -46,6 +51,16 @@ public class Utils {
return
str
.
toString
();
}
public
static
String
arrayToString
(
Object
[]
array
)
{
StringBuilder
sb
=
new
StringBuilder
();
for
(
int
i
=
0
;
i
<
array
.
length
;
i
++)
{
if
(
i
!=
0
)
sb
.
append
(
", "
);
sb
.
append
(
array
[
i
]);
}
return
sb
.
toString
();
}
public
static
String
getStackTrace
(
Throwable
throwable
)
{
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
,
true
);
...
...
src/samples/java/jadx/samples/TestCF3.java
View file @
3b84aec5
...
...
@@ -68,6 +68,19 @@ public class TestCF3 extends AbstractTest {
return
l1
.
size
()
==
0
;
}
public
boolean
testNestedLoops2
(
List
<
String
>
list
)
{
int
i
=
0
;
int
j
=
0
;
while
(
i
<
list
.
size
())
{
String
s
=
list
.
get
(
i
);
while
(
j
<
s
.
length
())
{
j
++;
}
i
++;
}
return
j
>
10
;
}
public
static
boolean
testLabeledBreakContinue
()
{
String
searchMe
=
"Look for a substring in me"
;
String
substring
=
"sub"
;
...
...
src/samples/java/jadx/samples/TestGenerics.java
0 → 100644
View file @
3b84aec5
package
jadx
.
samples
;
import
java.util.ArrayList
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
public
class
TestGenerics
extends
AbstractTest
{
private
List
<
String
>
test1
(
Map
<
String
,
String
>
map
)
{
List
<
String
>
list
=
new
ArrayList
<
String
>();
String
str
=
map
.
get
(
"key"
);
list
.
add
(
str
);
return
list
;
}
public
void
test2
(
Map
<
String
,
String
>
map
,
List
<
Object
>
list
)
{
String
str
=
map
.
get
(
"key"
);
list
.
add
(
str
);
}
public
void
test3
(
List
<
Object
>
list
,
int
a
,
float
[]
b
,
String
[]
c
,
String
[][][]
d
)
{
}
@Override
public
boolean
testRun
()
throws
Exception
{
assertTrue
(
test1
(
new
HashMap
<
String
,
String
>())
!=
null
);
return
true
;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
new
TestGenerics
().
testRun
();
}
}
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