Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
tsaltedfishking
jadx
提交
e07bc7f6
J
jadx
项目概览
tsaltedfishking
/
jadx
与 Fork 源项目一致
从无法访问的项目Fork
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
J
jadx
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
前往新版Gitcode,体验更适合开发者的 AI 搜索 >>
未验证
提交
e07bc7f6
编写于
8月 10, 2022
作者:
S
Skylot
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
refactor: use package nodes in api and ui
上级
5894fadc
变更
29
隐藏空白更改
内联
并排
Showing
29 changed file
with
818 addition
and
514 deletion
+818
-514
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
+23
-20
jadx-core/src/main/java/jadx/api/JavaNode.java
jadx-core/src/main/java/jadx/api/JavaNode.java
+1
-2
jadx-core/src/main/java/jadx/api/JavaPackage.java
jadx-core/src/main/java/jadx/api/JavaPackage.java
+70
-12
jadx-core/src/main/java/jadx/api/JavaVariable.java
jadx-core/src/main/java/jadx/api/JavaVariable.java
+4
-0
jadx-core/src/main/java/jadx/api/data/impl/JadxCodeRename.java
...core/src/main/java/jadx/api/data/impl/JadxCodeRename.java
+8
-0
jadx-core/src/main/java/jadx/core/deobf/NameMapper.java
jadx-core/src/main/java/jadx/core/deobf/NameMapper.java
+1
-1
jadx-core/src/main/java/jadx/core/dex/nodes/PackageNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/PackageNode.java
+4
-0
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
+3
-0
jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
+1
-1
jadx-core/src/main/java/jadx/core/utils/Utils.java
jadx-core/src/main/java/jadx/core/utils/Utils.java
+35
-1
jadx-gui/src/main/java/jadx/gui/JadxWrapper.java
jadx-gui/src/main/java/jadx/gui/JadxWrapper.java
+5
-0
jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java
jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java
+40
-8
jadx-gui/src/main/java/jadx/gui/treemodel/JField.java
jadx-gui/src/main/java/jadx/gui/treemodel/JField.java
+38
-1
jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java
jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java
+66
-9
jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java
jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java
+0
-4
jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java
jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java
+52
-63
jadx-gui/src/main/java/jadx/gui/treemodel/JRenameNode.java
jadx-gui/src/main/java/jadx/gui/treemodel/JRenameNode.java
+35
-0
jadx-gui/src/main/java/jadx/gui/treemodel/JSources.java
jadx-gui/src/main/java/jadx/gui/treemodel/JSources.java
+9
-89
jadx-gui/src/main/java/jadx/gui/treemodel/JVariable.java
jadx-gui/src/main/java/jadx/gui/treemodel/JVariable.java
+39
-1
jadx-gui/src/main/java/jadx/gui/ui/codearea/RenameAction.java
...-gui/src/main/java/jadx/gui/ui/codearea/RenameAction.java
+9
-2
jadx-gui/src/main/java/jadx/gui/ui/dialog/RenameDialog.java
jadx-gui/src/main/java/jadx/gui/ui/dialog/RenameDialog.java
+27
-110
jadx-gui/src/main/java/jadx/gui/ui/popupmenu/JPackagePopupMenu.java
...rc/main/java/jadx/gui/ui/popupmenu/JPackagePopupMenu.java
+12
-68
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
+11
-0
jadx-gui/src/main/java/jadx/gui/utils/JNodeCache.java
jadx-gui/src/main/java/jadx/gui/utils/JNodeCache.java
+1
-1
jadx-gui/src/main/java/jadx/gui/utils/pkgs/JRenamePackage.java
...gui/src/main/java/jadx/gui/utils/pkgs/JRenamePackage.java
+103
-0
jadx-gui/src/main/java/jadx/gui/utils/pkgs/PackageHelper.java
...-gui/src/main/java/jadx/gui/utils/pkgs/PackageHelper.java
+187
-0
jadx-gui/src/test/java/jadx/api/Factory.java
jadx-gui/src/test/java/jadx/api/Factory.java
+0
-16
jadx-gui/src/test/java/jadx/gui/treemodel/JSourcesTest.java
jadx-gui/src/test/java/jadx/gui/treemodel/JSourcesTest.java
+0
-105
jadx-gui/src/test/java/jadx/gui/utils/pkgs/TestJRenamePackage.java
...src/test/java/jadx/gui/utils/pkgs/TestJRenamePackage.java
+34
-0
未找到文件。
jadx-core/src/main/java/jadx/api/JadxDecompiler.java
浏览文件 @
e07bc7f6
...
...
@@ -6,7 +6,6 @@ import java.nio.file.Path;
import
java.util.ArrayList
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.List
;
import
java.util.Map
;
...
...
@@ -46,6 +45,7 @@ import jadx.core.dex.attributes.AFlag;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.core.dex.nodes.FieldNode
;
import
jadx.core.dex.nodes.MethodNode
;
import
jadx.core.dex.nodes.PackageNode
;
import
jadx.core.dex.nodes.RootNode
;
import
jadx.core.dex.visitors.SaveCode
;
import
jadx.core.export.ExportGradleProject
;
...
...
@@ -102,6 +102,7 @@ public final class JadxDecompiler implements IJadxDecompiler, Closeable {
private
final
Map
<
ClassNode
,
JavaClass
>
classesMap
=
new
ConcurrentHashMap
<>();
private
final
Map
<
MethodNode
,
JavaMethod
>
methodsMap
=
new
ConcurrentHashMap
<>();
private
final
Map
<
FieldNode
,
JavaField
>
fieldsMap
=
new
ConcurrentHashMap
<>();
private
final
Map
<
PackageNode
,
JavaPackage
>
pkgsMap
=
new
ConcurrentHashMap
<>();
private
final
IDecompileScheduler
decompileScheduler
=
new
DecompilerScheduler
();
...
...
@@ -441,25 +442,7 @@ public final class JadxDecompiler implements IJadxDecompiler, Closeable {
}
public
List
<
JavaPackage
>
getPackages
()
{
List
<
JavaClass
>
classList
=
getClasses
();
if
(
classList
.
isEmpty
())
{
return
Collections
.
emptyList
();
}
Map
<
String
,
List
<
JavaClass
>>
map
=
new
HashMap
<>();
for
(
JavaClass
javaClass
:
classList
)
{
String
pkg
=
javaClass
.
getPackage
();
List
<
JavaClass
>
clsList
=
map
.
computeIfAbsent
(
pkg
,
k
->
new
ArrayList
<>());
clsList
.
add
(
javaClass
);
}
List
<
JavaPackage
>
packages
=
new
ArrayList
<>(
map
.
size
());
for
(
Map
.
Entry
<
String
,
List
<
JavaClass
>>
entry
:
map
.
entrySet
())
{
packages
.
add
(
new
JavaPackage
(
entry
.
getKey
(),
entry
.
getValue
()));
}
Collections
.
sort
(
packages
);
for
(
JavaPackage
pkg
:
packages
)
{
pkg
.
getClasses
().
sort
(
Comparator
.
comparing
(
JavaClass:
:
getName
,
String
.
CASE_INSENSITIVE_ORDER
));
}
return
Collections
.
unmodifiableList
(
packages
);
return
Utils
.
collectionMap
(
root
.
getPackages
(),
this
::
convertPackageNode
);
}
public
int
getErrorsCount
()
{
...
...
@@ -539,6 +522,26 @@ public final class JadxDecompiler implements IJadxDecompiler, Closeable {
});
}
@ApiStatus
.
Internal
JavaPackage
convertPackageNode
(
PackageNode
pkg
)
{
JavaPackage
foundPkg
=
pkgsMap
.
get
(
pkg
);
if
(
foundPkg
!=
null
)
{
return
foundPkg
;
}
List
<
JavaClass
>
clsList
=
Utils
.
collectionMap
(
pkg
.
getClasses
(),
this
::
convertClassNode
);
int
subPkgsCount
=
pkg
.
getSubPackages
().
size
();
List
<
JavaPackage
>
subPkgs
=
subPkgsCount
==
0
?
Collections
.
emptyList
()
:
new
ArrayList
<>(
subPkgsCount
);
JavaPackage
javaPkg
=
new
JavaPackage
(
pkg
,
clsList
,
subPkgs
);
pkgsMap
.
put
(
pkg
,
javaPkg
);
if
(
subPkgsCount
!=
0
)
{
// add subpackages after parent to avoid endless recursion
for
(
PackageNode
subPackage
:
pkg
.
getSubPackages
())
{
subPkgs
.
add
(
convertPackageNode
(
subPackage
));
}
}
return
javaPkg
;
}
@Nullable
public
JavaClass
searchJavaClassByOrigFullName
(
String
fullName
)
{
return
getRoot
().
getClasses
().
stream
()
...
...
jadx-core/src/main/java/jadx/api/JavaNode.java
浏览文件 @
e07bc7f6
...
...
@@ -18,8 +18,7 @@ public interface JavaNode {
List
<
JavaNode
>
getUseIn
();
default
void
removeAlias
()
{
}
void
removeAlias
();
boolean
isOwnCodeAnnotation
(
ICodeAnnotation
ann
);
}
jadx-core/src/main/java/jadx/api/JavaPackage.java
浏览文件 @
e07bc7f6
package
jadx.api
;
import
java.util.
Collections
;
import
java.util.
ArrayList
;
import
java.util.List
;
import
java.util.Objects
;
import
org.jetbrains.annotations.ApiStatus.Internal
;
import
org.jetbrains.annotations.NotNull
;
import
jadx.api.metadata.ICodeAnnotation
;
import
jadx.core.dex.info.PackageInfo
;
import
jadx.core.dex.nodes.PackageNode
;
public
final
class
JavaPackage
implements
JavaNode
,
Comparable
<
JavaPackage
>
{
private
final
String
nam
e
;
private
final
PackageNode
pkgNod
e
;
private
final
List
<
JavaClass
>
classes
;
private
final
List
<
JavaPackage
>
subPkgs
;
JavaPackage
(
String
name
,
List
<
JavaClass
>
classe
s
)
{
this
.
name
=
nam
e
;
JavaPackage
(
PackageNode
pkgNode
,
List
<
JavaClass
>
classes
,
List
<
JavaPackage
>
subPkg
s
)
{
this
.
pkgNode
=
pkgNod
e
;
this
.
classes
=
classes
;
this
.
subPkgs
=
subPkgs
;
}
@Override
public
String
getName
()
{
return
name
;
return
pkgNode
.
getAliasPkgInfo
().
getName
()
;
}
@Override
public
String
getFullName
()
{
// TODO: store full package name
return
name
;
return
pkgNode
.
getAliasPkgInfo
().
getFullName
();
}
public
String
getRawName
()
{
return
pkgNode
.
getPkgInfo
().
getName
();
}
public
String
getRawFullName
()
{
return
pkgNode
.
getPkgInfo
().
getFullName
();
}
public
List
<
JavaPackage
>
getSubPackages
()
{
return
subPkgs
;
}
public
List
<
JavaClass
>
getClasses
()
{
return
classes
;
}
public
boolean
isRoot
()
{
return
pkgNode
.
isRoot
();
}
public
boolean
isLeaf
()
{
return
pkgNode
.
isLeaf
();
}
public
boolean
isDefault
()
{
return
getFullName
().
isEmpty
();
}
public
void
rename
(
String
alias
)
{
pkgNode
.
rename
(
alias
);
}
@Override
public
void
removeAlias
()
{
pkgNode
.
removeAlias
();
}
public
boolean
isParentRenamed
()
{
PackageInfo
parent
=
pkgNode
.
getPkgInfo
().
getParentPkg
();
PackageInfo
aliasParent
=
pkgNode
.
getAliasPkgInfo
().
getParentPkg
();
return
!
Objects
.
equals
(
parent
,
aliasParent
);
}
@Internal
public
PackageNode
getPkgNode
()
{
return
pkgNode
;
}
@Override
public
JavaClass
getDeclaringClass
()
{
return
null
;
...
...
@@ -48,7 +97,16 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
@Override
public
List
<
JavaNode
>
getUseIn
()
{
return
Collections
.
emptyList
();
List
<
JavaNode
>
list
=
new
ArrayList
<>();
addUseIn
(
list
);
return
list
;
}
public
void
addUseIn
(
List
<
JavaNode
>
list
)
{
list
.
addAll
(
classes
);
for
(
JavaPackage
subPkg
:
subPkgs
)
{
subPkg
.
addUseIn
(
list
);
}
}
@Override
...
...
@@ -58,7 +116,7 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
@Override
public
int
compareTo
(
@NotNull
JavaPackage
o
)
{
return
name
.
compareTo
(
o
.
nam
e
);
return
pkgNode
.
compareTo
(
o
.
pkgNod
e
);
}
@Override
...
...
@@ -70,16 +128,16 @@ public final class JavaPackage implements JavaNode, Comparable<JavaPackage> {
return
false
;
}
JavaPackage
that
=
(
JavaPackage
)
o
;
return
name
.
equals
(
that
.
nam
e
);
return
pkgNode
.
equals
(
that
.
pkgNod
e
);
}
@Override
public
int
hashCode
()
{
return
nam
e
.
hashCode
();
return
pkgNod
e
.
hashCode
();
}
@Override
public
String
toString
()
{
return
name
;
return
pkgNode
.
toString
()
;
}
}
jadx-core/src/main/java/jadx/api/JavaVariable.java
浏览文件 @
e07bc7f6
...
...
@@ -71,6 +71,10 @@ public class JavaVariable implements JavaNode {
return
Collections
.
singletonList
(
mth
);
}
@Override
public
void
removeAlias
()
{
}
@Override
public
boolean
isOwnCodeAnnotation
(
ICodeAnnotation
ann
)
{
if
(
ann
.
getAnnType
()
==
ICodeAnnotation
.
AnnType
.
VAR_REF
)
{
...
...
jadx-core/src/main/java/jadx/api/data/impl/JadxCodeRename.java
浏览文件 @
e07bc7f6
...
...
@@ -85,4 +85,12 @@ public class JadxCodeRename implements ICodeRename {
public
int
hashCode
()
{
return
31
*
getNodeRef
().
hashCode
()
+
Objects
.
hashCode
(
getCodeRef
());
}
@Override
public
String
toString
()
{
return
"JadxCodeRename{"
+
nodeRef
+
", codeRef="
+
codeRef
+
", newName='"
+
newName
+
'\''
+
'}'
;
}
}
jadx-core/src/main/java/jadx/core/deobf/NameMapper.java
浏览文件 @
e07bc7f6
...
...
@@ -11,7 +11,7 @@ import static jadx.core.utils.StringUtils.notEmpty;
public
class
NameMapper
{
p
rivate
static
final
Pattern
VALID_JAVA_IDENTIFIER
=
Pattern
.
compile
(
p
ublic
static
final
Pattern
VALID_JAVA_IDENTIFIER
=
Pattern
.
compile
(
"\\p{javaJavaIdentifierStart}\\p{javaJavaIdentifierPart}*"
);
private
static
final
Pattern
VALID_JAVA_FULL_IDENTIFIER
=
Pattern
.
compile
(
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/PackageNode.java
浏览文件 @
e07bc7f6
...
...
@@ -144,6 +144,10 @@ public class PackageNode implements IPackageUpdate, IDexNode, Comparable<Package
return
!
Objects
.
equals
(
pkgInfo
.
getParentPkg
(),
aliasPkgInfo
.
getParentPkg
());
}
public
void
removeAlias
()
{
aliasPkgInfo
=
pkgInfo
;
}
public
PackageNode
getParentPkg
()
{
return
parentPkg
;
}
...
...
jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
浏览文件 @
e07bc7f6
...
...
@@ -295,6 +295,9 @@ public class RootNode implements IRootNode {
}
}
classes
.
forEach
(
ClassNode:
:
updateParentClass
);
for
(
PackageNode
pkg
:
packages
)
{
pkg
.
getClasses
().
removeIf
(
ClassNode:
:
isInner
);
}
}
public
void
mergePasses
(
Map
<
JadxPassType
,
List
<
JadxPass
>>
customPasses
)
{
...
...
jadx-core/src/main/java/jadx/core/utils/DebugUtils.java
浏览文件 @
e07bc7f6
...
...
@@ -225,7 +225,7 @@ public class DebugUtils {
}
public
static
void
printStackTrace
(
String
label
)
{
LOG
.
debug
(
"StackTrace: {}\n{}"
,
label
,
Utils
.
getStackTrace
(
new
Exception
()));
LOG
.
debug
(
"StackTrace: {}\n{}"
,
label
,
Utils
.
get
Full
StackTrace
(
new
Exception
()));
}
public
static
void
printMethodOverrideTop
(
RootNode
root
)
{
...
...
jadx-core/src/main/java/jadx/core/utils/Utils.java
浏览文件 @
e07bc7f6
...
...
@@ -3,10 +3,12 @@ package jadx.core.utils;
import
java.io.OutputStream
;
import
java.io.PrintWriter
;
import
java.io.StringWriter
;
import
java.util.ArrayDeque
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Collection
;
import
java.util.Collections
;
import
java.util.Deque
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.Iterator
;
...
...
@@ -14,6 +16,7 @@ import java.util.List;
import
java.util.Map
;
import
java.util.Objects
;
import
java.util.Set
;
import
java.util.function.Consumer
;
import
java.util.function.Function
;
import
org.jetbrains.annotations.Nullable
;
...
...
@@ -116,13 +119,23 @@ public class Utils {
return
sb
.
toString
();
}
public
static
String
getFullStackTrace
(
Throwable
throwable
)
{
return
getStackTrace
(
throwable
,
false
);
}
public
static
String
getStackTrace
(
Throwable
throwable
)
{
return
getStackTrace
(
throwable
,
true
);
}
private
static
String
getStackTrace
(
Throwable
throwable
,
boolean
filter
)
{
if
(
throwable
==
null
)
{
return
""
;
}
StringWriter
sw
=
new
StringWriter
();
PrintWriter
pw
=
new
PrintWriter
(
sw
,
true
);
filterRecursive
(
throwable
);
if
(
filter
)
{
filterRecursive
(
throwable
);
}
throwable
.
printStackTrace
(
pw
);
return
sw
.
getBuffer
().
toString
();
}
...
...
@@ -345,6 +358,27 @@ public class Utils {
return
map
;
}
/**
* Simple DFS visit for tree (cycles not allowed)
*/
public
static
<
T
>
void
treeDfsVisit
(
T
root
,
Function
<
T
,
List
<
T
>>
childrenProvider
,
Consumer
<
T
>
visitor
)
{
multiRootTreeDfsVisit
(
Collections
.
singletonList
(
root
),
childrenProvider
,
visitor
);
}
public
static
<
T
>
void
multiRootTreeDfsVisit
(
List
<
T
>
roots
,
Function
<
T
,
List
<
T
>>
childrenProvider
,
Consumer
<
T
>
visitor
)
{
Deque
<
T
>
queue
=
new
ArrayDeque
<>(
roots
);
while
(
true
)
{
T
current
=
queue
.
pollLast
();
if
(
current
==
null
)
{
return
;
}
visitor
.
accept
(
current
);
for
(
T
child
:
childrenProvider
.
apply
(
current
))
{
queue
.
addLast
(
child
);
}
}
}
@Nullable
public
static
<
T
>
T
getOne
(
@Nullable
List
<
T
>
list
)
{
if
(
list
==
null
||
list
.
size
()
!=
1
)
{
...
...
jadx-gui/src/main/java/jadx/gui/JadxWrapper.java
浏览文件 @
e07bc7f6
...
...
@@ -32,6 +32,7 @@ import jadx.gui.plugins.context.PluginsContext;
import
jadx.gui.settings.JadxProject
;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.CacheObject
;
import
jadx.gui.utils.codecache.CodeStringCache
;
import
jadx.gui.utils.codecache.disk.BufferCodeCache
;
import
jadx.gui.utils.codecache.disk.DiskCodeCache
;
...
...
@@ -264,6 +265,10 @@ public class JadxWrapper {
return
mainWindow
.
getSettings
();
}
public
CacheObject
getCache
()
{
return
mainWindow
.
getCacheObject
();
}
/**
* @param fullName
* Full name of an outer class. Inner classes are not supported.
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JClass.java
浏览文件 @
e07bc7f6
package
jadx.gui.treemodel
;
import
java.util.List
;
import
java.util.Set
;
import
javax.swing.Icon
;
import
javax.swing.ImageIcon
;
import
javax.swing.JPopupMenu
;
...
...
@@ -12,6 +15,10 @@ import jadx.api.JavaClass;
import
jadx.api.JavaField
;
import
jadx.api.JavaMethod
;
import
jadx.api.JavaNode
;
import
jadx.api.data.ICodeRename
;
import
jadx.api.data.impl.JadxCodeRename
;
import
jadx.api.data.impl.JadxNodeRef
;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.gui.ui.MainWindow
;
...
...
@@ -24,7 +31,7 @@ import jadx.gui.utils.Icons;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.UiUtils
;
public
class
JClass
extends
JLoadableNode
{
public
class
JClass
extends
JLoadableNode
implements
JRenameNode
{
private
static
final
long
serialVersionUID
=
-
1239986875244097177L
;
private
static
final
ImageIcon
ICON_CLASS_ABSTRACT
=
UiUtils
.
openSvgIcon
(
"nodes/abstractClass"
);
...
...
@@ -39,16 +46,10 @@ public class JClass extends JLoadableNode {
private
final
transient
JClass
jParent
;
private
transient
boolean
loaded
;
public
JClass
(
JavaClass
cls
)
{
this
.
cls
=
cls
;
this
.
jParent
=
null
;
this
.
loaded
=
false
;
}
public
JClass
(
JavaClass
cls
,
JClass
parent
)
{
this
.
cls
=
cls
;
this
.
jParent
=
parent
;
this
.
loaded
=
true
;
this
.
loaded
=
parent
!=
null
;
}
public
JavaClass
getCls
()
{
...
...
@@ -185,6 +186,37 @@ public class JClass extends JLoadableNode {
return
cls
.
getFullName
();
}
@Override
public
String
getTitle
()
{
return
makeLongStringHtml
();
}
@Override
public
boolean
isValidName
(
String
newName
)
{
return
NameMapper
.
isValidIdentifier
(
newName
);
}
@Override
public
ICodeRename
buildCodeRename
(
String
newName
,
Set
<
ICodeRename
>
renames
)
{
return
new
JadxCodeRename
(
JadxNodeRef
.
forCls
(
cls
),
newName
);
}
@Override
public
void
removeAlias
()
{
cls
.
removeAlias
();
}
@Override
public
void
addUpdateNodes
(
List
<
JavaNode
>
toUpdate
)
{
toUpdate
.
add
(
cls
);
toUpdate
.
addAll
(
cls
.
getUseIn
());
}
@Override
public
void
reload
(
MainWindow
mainWindow
)
{
mainWindow
.
reloadTree
();
}
@Override
public
int
hashCode
()
{
return
cls
.
hashCode
();
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JField.java
浏览文件 @
e07bc7f6
package
jadx.gui.treemodel
;
import
java.util.Comparator
;
import
java.util.List
;
import
java.util.Set
;
import
javax.swing.Icon
;
import
javax.swing.ImageIcon
;
...
...
@@ -11,6 +13,10 @@ import org.jetbrains.annotations.NotNull;
import
jadx.api.JavaField
;
import
jadx.api.JavaNode
;
import
jadx.api.data.ICodeRename
;
import
jadx.api.data.impl.JadxCodeRename
;
import
jadx.api.data.impl.JadxNodeRef
;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.gui.ui.MainWindow
;
...
...
@@ -18,7 +24,7 @@ import jadx.gui.ui.dialog.RenameDialog;
import
jadx.gui.utils.Icons
;
import
jadx.gui.utils.UiUtils
;
public
class
JField
extends
JNode
{
public
class
JField
extends
JNode
implements
JRenameNode
{
private
static
final
long
serialVersionUID
=
1712572192106793359L
;
private
static
final
ImageIcon
ICON_FLD_PRI
=
UiUtils
.
openSvgIcon
(
"nodes/privateField"
);
...
...
@@ -61,6 +67,37 @@ public class JField extends JNode {
return
RenameDialog
.
buildRenamePopup
(
mainWindow
,
this
);
}
@Override
public
String
getTitle
()
{
return
makeLongStringHtml
();
}
@Override
public
ICodeRename
buildCodeRename
(
String
newName
,
Set
<
ICodeRename
>
renames
)
{
return
new
JadxCodeRename
(
JadxNodeRef
.
forFld
(
field
),
newName
);
}
@Override
public
boolean
isValidName
(
String
newName
)
{
return
NameMapper
.
isValidIdentifier
(
newName
);
}
@Override
public
void
removeAlias
()
{
field
.
removeAlias
();
}
@Override
public
void
addUpdateNodes
(
List
<
JavaNode
>
toUpdate
)
{
toUpdate
.
add
(
field
);
toUpdate
.
addAll
(
field
.
getUseIn
());
}
@Override
public
void
reload
(
MainWindow
mainWindow
)
{
mainWindow
.
reloadTree
();
}
@Override
public
Icon
getIcon
()
{
AccessInfo
af
=
field
.
getAccessFlags
();
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JMethod.java
浏览文件 @
e07bc7f6
...
...
@@ -2,6 +2,8 @@ package jadx.gui.treemodel;
import
java.util.Comparator
;
import
java.util.Iterator
;
import
java.util.List
;
import
java.util.Set
;
import
javax.swing.Icon
;
import
javax.swing.ImageIcon
;
...
...
@@ -12,6 +14,10 @@ import org.jetbrains.annotations.NotNull;
import
jadx.api.JavaMethod
;
import
jadx.api.JavaNode
;
import
jadx.api.data.ICodeRename
;
import
jadx.api.data.impl.JadxCodeRename
;
import
jadx.api.data.impl.JadxNodeRef
;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.dex.attributes.AFlag
;
import
jadx.core.dex.info.AccessInfo
;
import
jadx.core.dex.instructions.args.ArgType
;
...
...
@@ -21,7 +27,7 @@ import jadx.gui.utils.Icons;
import
jadx.gui.utils.OverlayIcon
;
import
jadx.gui.utils.UiUtils
;
public
class
JMethod
extends
JNode
{
public
class
JMethod
extends
JNode
implements
JRenameNode
{
private
static
final
long
serialVersionUID
=
3834526867464663751L
;
private
static
final
ImageIcon
ICON_METHOD_ABSTRACT
=
UiUtils
.
openSvgIcon
(
"nodes/abstractMethod"
);
private
static
final
ImageIcon
ICON_METHOD_PRIVATE
=
UiUtils
.
openSvgIcon
(
"nodes/privateMethod"
);
...
...
@@ -100,14 +106,6 @@ public class JMethod extends JNode {
return
SyntaxConstants
.
SYNTAX_STYLE_JAVA
;
}
@Override
public
boolean
canRename
()
{
if
(
mth
.
isClassInit
())
{
return
false
;
}
return
!
mth
.
getMethodNode
().
contains
(
AFlag
.
DONT_RENAME
);
}
@Override
public
JPopupMenu
onTreePopupMenu
(
MainWindow
mainWindow
)
{
return
RenameDialog
.
buildRenamePopup
(
mainWindow
,
this
);
...
...
@@ -139,6 +137,65 @@ public class JMethod extends JNode {
return
mth
.
getName
();
}
@Override
public
String
getTitle
()
{
return
makeLongStringHtml
();
}
@Override
public
boolean
canRename
()
{
if
(
mth
.
isClassInit
())
{
return
false
;
}
return
!
mth
.
getMethodNode
().
contains
(
AFlag
.
DONT_RENAME
);
}
@Override
public
JRenameNode
replace
()
{
if
(
mth
.
isConstructor
())
{
// rename class instead constructor
return
jParent
;
}
return
this
;
}
@Override
public
ICodeRename
buildCodeRename
(
String
newName
,
Set
<
ICodeRename
>
renames
)
{
List
<
JavaMethod
>
relatedMethods
=
mth
.
getOverrideRelatedMethods
();
if
(!
relatedMethods
.
isEmpty
())
{
for
(
JavaMethod
relatedMethod
:
relatedMethods
)
{
renames
.
remove
(
new
JadxCodeRename
(
JadxNodeRef
.
forMth
(
relatedMethod
),
""
));
}
}
return
new
JadxCodeRename
(
JadxNodeRef
.
forMth
(
mth
),
newName
);
}
@Override
public
boolean
isValidName
(
String
newName
)
{
return
NameMapper
.
isValidIdentifier
(
newName
);
}
@Override
public
void
removeAlias
()
{
mth
.
removeAlias
();
}
@Override
public
void
addUpdateNodes
(
List
<
JavaNode
>
toUpdate
)
{
toUpdate
.
add
(
mth
);
toUpdate
.
addAll
(
mth
.
getUseIn
());
List
<
JavaMethod
>
overrideRelatedMethods
=
mth
.
getOverrideRelatedMethods
();
toUpdate
.
addAll
(
overrideRelatedMethods
);
for
(
JavaMethod
ovrdMth
:
overrideRelatedMethods
)
{
toUpdate
.
addAll
(
ovrdMth
.
getUseIn
());
}
}
@Override
public
void
reload
(
MainWindow
mainWindow
)
{
mainWindow
.
reloadTree
();
}
@Override
public
String
makeString
()
{
return
UiUtils
.
typeFormat
(
makeBaseString
(),
getReturnType
());
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JNode.java
浏览文件 @
e07bc7f6
...
...
@@ -63,10 +63,6 @@ public abstract class JNode extends DefaultMutableTreeNode implements Comparable
return
javaNode
.
getName
();
}
public
boolean
canRename
()
{
return
false
;
}
public
@Nullable
JPopupMenu
onTreePopupMenu
(
MainWindow
mainWindow
)
{
return
null
;
}
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JPackage.java
浏览文件 @
e07bc7f6
package
jadx.gui.treemodel
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.List
;
import
javax.swing.Icon
;
import
javax.swing.JPopupMenu
;
import
jadx.api.JavaNode
;
import
jadx.api.JavaPackage
;
import
jadx.core.utils.Utils
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.popupmenu.JPackagePopupMenu
;
import
jadx.gui.utils.Icons
;
import
static
jadx
.
gui
.
utils
.
UiUtils
.
escapeHtml
;
import
static
jadx
.
gui
.
utils
.
UiUtils
.
fadeHtml
;
import
static
jadx
.
gui
.
utils
.
UiUtils
.
wrapHtml
;
public
class
JPackage
extends
JNode
{
private
static
final
long
serialVersionUID
=
-
4120718634156839804L
;
private
String
fullName
;
private
String
name
;
private
boolean
enabled
;
private
List
<
JClass
>
classes
;
private
List
<
JPackage
>
innerPackages
;
public
static
final
String
PACKAGE_DEFAULT_HTML_STR
=
wrapHtml
(
fadeHtml
(
escapeHtml
(
"<empty>"
)));
public
JPackage
(
JavaPackage
pkg
,
JadxWrapper
wrapper
)
{
this
(
pkg
.
getName
(),
pkg
.
getName
(),
isPkgEnabled
(
wrapper
,
pkg
.
getName
()),
Utils
.
collectionMap
(
pkg
.
getClasses
(),
JClass:
:
new
),
new
ArrayList
<>());
update
();
}
private
final
JavaPackage
pkg
;
private
final
boolean
enabled
;
private
final
List
<
JClass
>
classes
;
private
final
List
<
JPackage
>
subPackages
;
public
JPackage
(
String
fullName
,
JadxWrapper
wrapper
)
{
this
(
fullName
,
fullName
,
isPkgEnabled
(
wrapper
,
fullName
),
new
ArrayList
<>(),
new
ArrayList
<>());
}
/**
* Package created by full package alias, don't have a raw package reference.
* `pkg` field point to the closest raw package leaf.
*/
private
final
boolean
synthetic
;
public
JPackage
(
String
fullName
,
String
name
)
{
this
(
fullName
,
name
,
true
,
Collections
.
emptyList
(),
Collections
.
emptyList
());
}
private
String
name
;
private
JPackage
(
String
fullName
,
String
name
,
boolean
enabled
,
List
<
JClass
>
classes
,
List
<
JPackage
>
innerPackages
)
{
this
.
fullName
=
fullName
;
this
.
name
=
name
;
public
JPackage
(
JavaPackage
pkg
,
boolean
enabled
,
List
<
JClass
>
classes
,
List
<
JPackage
>
subPackages
,
boolean
synthetic
)
{
this
.
pkg
=
pkg
;
this
.
enabled
=
enabled
;
this
.
classes
=
classes
;
this
.
innerPackages
=
innerPackages
;
}
private
static
boolean
isPkgEnabled
(
JadxWrapper
wrapper
,
String
fullPkgName
)
{
List
<
String
>
excludedPackages
=
wrapper
.
getExcludedPackages
();
return
excludedPackages
.
isEmpty
()
||
excludedPackages
.
stream
().
filter
(
p
->
!
p
.
isEmpty
())
.
noneMatch
(
p
->
fullPkgName
.
equals
(
p
)
||
fullPkgName
.
startsWith
(
p
+
'.'
));
this
.
subPackages
=
subPackages
;
this
.
synthetic
=
synthetic
;
}
public
final
void
update
()
{
public
void
update
()
{
removeAllChildren
();
if
(
isEnabled
())
{
for
(
JPackage
pkg
:
inner
Packages
)
{
for
(
JPackage
pkg
:
sub
Packages
)
{
pkg
.
update
();
add
(
pkg
);
}
...
...
@@ -73,44 +60,37 @@ public class JPackage extends JNode {
return
new
JPackagePopupMenu
(
mainWindow
,
this
);
}
@Override
public
String
getName
()
{
return
name
;
public
JavaPackage
getPkg
()
{
return
pkg
;
}
@Override
public
boolean
canRename
()
{
return
true
;
public
JavaNode
getJavaNode
()
{
return
pkg
;
}
public
String
getFullName
()
{
return
fullName
;
}
public
void
updateBothNames
(
String
fullName
,
String
name
,
JadxWrapper
wrapper
)
{
this
.
fullName
=
fullName
;
this
.
name
=
name
;
this
.
enabled
=
isPkgEnabled
(
wrapper
,
fullName
);
@Override
public
String
getName
()
{
return
name
;
}
public
void
update
Name
(
String
name
)
{
public
void
set
Name
(
String
name
)
{
this
.
name
=
name
;
}
public
List
<
JPackage
>
getInnerPackages
()
{
return
innerPackages
;
}
public
void
setInnerPackages
(
List
<
JPackage
>
innerPackages
)
{
this
.
innerPackages
=
innerPackages
;
public
List
<
JPackage
>
getSubPackages
()
{
return
subPackages
;
}
public
List
<
JClass
>
getClasses
()
{
return
classes
;
}
public
void
setClasses
(
List
<
JClass
>
classes
)
{
this
.
classes
=
classes
;
public
boolean
isEnabled
()
{
return
enabled
;
}
public
boolean
isSynthetic
()
{
return
synthetic
;
}
@Override
...
...
@@ -131,12 +111,12 @@ public class JPackage extends JNode {
if
(
o
==
null
||
getClass
()
!=
o
.
getClass
())
{
return
false
;
}
return
name
.
equals
(((
JPackage
)
o
).
name
);
return
pkg
.
equals
(((
JPackage
)
o
).
pkg
);
}
@Override
public
int
hashCode
()
{
return
name
.
hashCode
();
return
pkg
.
hashCode
();
}
@Override
...
...
@@ -145,11 +125,20 @@ public class JPackage extends JNode {
}
@Override
public
String
makeLongString
()
{
public
String
makeStringHtml
()
{
if
(
name
.
isEmpty
())
{
return
PACKAGE_DEFAULT_HTML_STR
;
}
return
name
;
}
public
boolean
isEnabled
()
{
return
enabled
;
@Override
public
String
makeLongString
()
{
return
pkg
.
getFullName
();
}
@Override
public
String
toString
()
{
return
name
;
}
}
jadx-gui/src/main/java/jadx/gui/treemodel/JRenameNode.java
0 → 100644
浏览文件 @
e07bc7f6
package
jadx.gui.treemodel
;
import
java.util.List
;
import
java.util.Set
;
import
javax.swing.Icon
;
import
jadx.api.JavaNode
;
import
jadx.api.data.ICodeRename
;
import
jadx.gui.ui.MainWindow
;
public
interface
JRenameNode
{
String
getTitle
();
String
getName
();
Icon
getIcon
();
boolean
canRename
();
default
JRenameNode
replace
()
{
return
this
;
}
ICodeRename
buildCodeRename
(
String
newName
,
Set
<
ICodeRename
>
renames
);
boolean
isValidName
(
String
newName
);
void
removeAlias
();
void
addUpdateNodes
(
List
<
JavaNode
>
toUpdate
);
void
reload
(
MainWindow
mainWindow
);
}
jadx-gui/src/main/java/jadx/gui/treemodel/JSources.java
浏览文件 @
e07bc7f6
package
jadx.gui.treemodel
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.HashMap
;
import
java.util.IdentityHashMap
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
javax.swing.Icon
;
import
javax.swing.ImageIcon
;
import
jadx.api.JavaPackage
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.UiUtils
;
import
jadx.gui.utils.pkgs.PackageHelper
;
public
class
JSources
extends
JNode
{
private
static
final
long
serialVersionUID
=
8962924556824862801L
;
...
...
@@ -32,89 +26,15 @@ public class JSources extends JNode {
public
final
void
update
()
{
removeAllChildren
();
if
(
flatPackages
)
{
for
(
JavaPackage
pkg
:
wrapper
.
getPackages
())
{
add
(
new
JPackage
(
pkg
,
wrapper
));
}
}
else
{
// build packages hierarchy
List
<
JPackage
>
rootPkgs
=
getHierarchyPackages
(
wrapper
.
getPackages
());
for
(
JPackage
jPackage
:
rootPkgs
)
{
jPackage
.
update
();
add
(
jPackage
);
}
PackageHelper
packageHelper
=
wrapper
.
getCache
().
getPackageHelper
();
if
(
packageHelper
==
null
)
{
packageHelper
=
new
PackageHelper
(
wrapper
);
wrapper
.
getCache
().
setPackageHelper
(
packageHelper
);
}
}
/**
* Convert packages list to hierarchical packages representation
*
* @param packages input packages list
* @return root packages
*/
List
<
JPackage
>
getHierarchyPackages
(
List
<
JavaPackage
>
packages
)
{
Map
<
String
,
JPackage
>
pkgMap
=
new
HashMap
<>();
for
(
JavaPackage
pkg
:
packages
)
{
addPackage
(
pkgMap
,
new
JPackage
(
pkg
,
wrapper
));
}
// merge packages without classes
boolean
repeat
;
do
{
repeat
=
false
;
for
(
JPackage
pkg
:
pkgMap
.
values
())
{
List
<
JPackage
>
innerPackages
=
pkg
.
getInnerPackages
();
if
(
innerPackages
.
size
()
==
1
&&
pkg
.
getClasses
().
isEmpty
())
{
JPackage
innerPkg
=
innerPackages
.
get
(
0
);
pkg
.
setInnerPackages
(
innerPkg
.
getInnerPackages
());
pkg
.
setClasses
(
innerPkg
.
getClasses
());
String
innerName
=
'.'
+
innerPkg
.
getName
();
pkg
.
updateBothNames
(
pkg
.
getFullName
()
+
innerName
,
pkg
.
getName
()
+
innerName
,
wrapper
);
innerPkg
.
setInnerPackages
(
Collections
.
emptyList
());
innerPkg
.
setClasses
(
Collections
.
emptyList
());
repeat
=
true
;
break
;
}
}
}
while
(
repeat
);
// remove empty packages
pkgMap
.
values
().
removeIf
(
pkg
->
pkg
.
getInnerPackages
().
isEmpty
()
&&
pkg
.
getClasses
().
isEmpty
());
// use identity set for collect inner packages
Set
<
JPackage
>
innerPackages
=
Collections
.
newSetFromMap
(
new
IdentityHashMap
<>());
for
(
JPackage
pkg
:
pkgMap
.
values
())
{
innerPackages
.
addAll
(
pkg
.
getInnerPackages
());
}
// find root packages
List
<
JPackage
>
rootPkgs
=
new
ArrayList
<>();
for
(
JPackage
pkg
:
pkgMap
.
values
())
{
if
(!
innerPackages
.
contains
(
pkg
))
{
rootPkgs
.
add
(
pkg
);
}
}
Collections
.
sort
(
rootPkgs
);
return
rootPkgs
;
}
private
void
addPackage
(
Map
<
String
,
JPackage
>
pkgs
,
JPackage
pkg
)
{
String
pkgName
=
pkg
.
getFullName
();
JPackage
replaced
=
pkgs
.
put
(
pkgName
,
pkg
);
if
(
replaced
!=
null
)
{
pkg
.
getInnerPackages
().
addAll
(
replaced
.
getInnerPackages
());
pkg
.
getClasses
().
addAll
(
replaced
.
getClasses
());
}
int
dot
=
pkgName
.
lastIndexOf
(
'.'
);
if
(
dot
>
0
)
{
String
prevPart
=
pkgName
.
substring
(
0
,
dot
);
String
shortName
=
pkgName
.
substring
(
dot
+
1
);
pkg
.
updateName
(
shortName
);
JPackage
prevPkg
=
pkgs
.
get
(
prevPart
);
if
(
prevPkg
==
null
)
{
prevPkg
=
new
JPackage
(
prevPart
,
wrapper
);
addPackage
(
pkgs
,
prevPkg
);
}
prevPkg
.
getInnerPackages
().
add
(
pkg
);
List
<
JPackage
>
roots
=
packageHelper
.
getRoots
(
flatPackages
);
for
(
JPackage
rootPkg
:
roots
)
{
rootPkg
.
update
();
add
(
rootPkg
);
}
}
...
...
jadx-gui/src/main/java/jadx/gui/treemodel/JVariable.java
浏览文件 @
e07bc7f6
package
jadx.gui.treemodel
;
import
java.util.List
;
import
java.util.Set
;
import
javax.swing.Icon
;
import
jadx.api.JavaNode
;
import
jadx.api.JavaVariable
;
import
jadx.api.data.ICodeRename
;
import
jadx.api.data.impl.JadxCodeRef
;
import
jadx.api.data.impl.JadxCodeRename
;
import
jadx.api.data.impl.JadxNodeRef
;
import
jadx.core.deobf.NameMapper
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.UiUtils
;
public
class
JVariable
extends
JNode
{
public
class
JVariable
extends
JNode
implements
JRenameNode
{
private
static
final
long
serialVersionUID
=
-
3002100457834453783L
;
private
final
JMethod
jMth
;
...
...
@@ -72,4 +81,33 @@ public class JVariable extends JNode {
public
boolean
canRename
()
{
return
var
.
getName
()
!=
null
;
}
@Override
public
String
getTitle
()
{
return
makeLongStringHtml
();
}
@Override
public
boolean
isValidName
(
String
newName
)
{
return
NameMapper
.
isValidIdentifier
(
newName
);
}
@Override
public
ICodeRename
buildCodeRename
(
String
newName
,
Set
<
ICodeRename
>
renames
)
{
return
new
JadxCodeRename
(
JadxNodeRef
.
forMth
(
var
.
getMth
()),
JadxCodeRef
.
forVar
(
var
),
newName
);
}
@Override
public
void
removeAlias
()
{
var
.
removeAlias
();
}
@Override
public
void
addUpdateNodes
(
List
<
JavaNode
>
toUpdate
)
{
toUpdate
.
add
(
var
.
getMth
());
}
@Override
public
void
reload
(
MainWindow
mainWindow
)
{
}
}
jadx-gui/src/main/java/jadx/gui/ui/codearea/RenameAction.java
浏览文件 @
e07bc7f6
package
jadx.gui.ui.codearea
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.treemodel.JRenameNode
;
import
jadx.gui.ui.dialog.RenameDialog
;
import
jadx.gui.utils.NLS
;
...
...
@@ -17,11 +18,17 @@ public final class RenameAction extends JNodeAction {
@Override
public
boolean
isActionEnabled
(
JNode
node
)
{
return
node
!=
null
&&
node
.
canRename
();
if
(
node
==
null
)
{
return
false
;
}
if
(
node
instanceof
JRenameNode
)
{
return
((
JRenameNode
)
node
).
canRename
();
}
return
false
;
}
@Override
public
void
runAction
(
JNode
node
)
{
RenameDialog
.
rename
(
getCodeArea
().
getMainWindow
(),
getCodeArea
().
getNode
(),
node
);
RenameDialog
.
rename
(
getCodeArea
().
getMainWindow
(),
getCodeArea
().
getNode
(),
(
JRenameNode
)
node
);
}
}
jadx-gui/src/main/java/jadx/gui/ui/dialog/RenameDialog.java
浏览文件 @
e07bc7f6
...
...
@@ -28,29 +28,19 @@ import javax.swing.SwingConstants;
import
javax.swing.WindowConstants
;
import
org.jetbrains.annotations.NotNull
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.JavaClass
;
import
jadx.api.JavaMethod
;
import
jadx.api.JavaNode
;
import
jadx.api.JavaVariable
;
import
jadx.api.data.ICodeRename
;
import
jadx.api.data.impl.JadxCodeData
;
import
jadx.api.data.impl.JadxCodeRef
;
import
jadx.api.data.impl.JadxCodeRename
;
import
jadx.api.data.impl.JadxNodeRef
;
import
jadx.core.deobf.NameMapper
;
import
jadx.core.utils.Utils
;
import
jadx.core.utils.exceptions.JadxRuntimeException
;
import
jadx.gui.jobs.TaskStatus
;
import
jadx.gui.settings.JadxProject
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JField
;
import
jadx.gui.treemodel.JMethod
;
import
jadx.gui.treemodel.JNode
;
import
jadx.gui.treemodel.JPackage
;
import
jadx.gui.treemodel.JVariable
;
import
jadx.gui.treemodel.JRenameNode
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.TabbedPane
;
import
jadx.gui.ui.codearea.ClassCodeContentPanel
;
...
...
@@ -70,36 +60,32 @@ public class RenameDialog extends JDialog {
private
final
transient
MainWindow
mainWindow
;
private
final
transient
CacheObject
cache
;
private
final
transient
JNode
source
;
private
final
transient
JNode
node
;
private
final
transient
@Nullable
JNode
source
;
private
final
transient
J
Rename
Node
node
;
private
transient
JTextField
renameField
;
private
transient
JButton
renameBtn
;
public
static
boolean
rename
(
MainWindow
mainWindow
,
JNode
node
)
{
return
rename
(
mainWindow
,
node
,
node
);
}
public
static
boolean
rename
(
MainWindow
mainWindow
,
JNode
source
,
JNode
node
)
{
public
static
boolean
rename
(
MainWindow
mainWindow
,
JNode
source
,
JRenameNode
node
)
{
RenameDialog
renameDialog
=
new
RenameDialog
(
mainWindow
,
source
,
node
);
UiUtils
.
uiRun
(()
->
renameDialog
.
setVisible
(
true
));
UiUtils
.
uiRun
(
renameDialog:
:
initRenameField
);
// wait for UI events to propagate
return
true
;
}
public
static
JPopupMenu
buildRenamePopup
(
MainWindow
mainWindow
,
JNode
node
)
{
public
static
JPopupMenu
buildRenamePopup
(
MainWindow
mainWindow
,
J
Rename
Node
node
)
{
JMenuItem
jmi
=
new
JMenuItem
(
NLS
.
str
(
"popup.rename"
));
jmi
.
addActionListener
(
action
->
RenameDialog
.
rename
(
mainWindow
,
node
));
jmi
.
addActionListener
(
action
->
RenameDialog
.
rename
(
mainWindow
,
n
ull
,
n
ode
));
JPopupMenu
menu
=
new
JPopupMenu
();
menu
.
add
(
jmi
);
return
menu
;
}
private
RenameDialog
(
MainWindow
mainWindow
,
JNode
source
,
JNode
node
)
{
private
RenameDialog
(
MainWindow
mainWindow
,
JNode
source
,
J
Rename
Node
node
)
{
super
(
mainWindow
);
this
.
mainWindow
=
mainWindow
;
this
.
cache
=
mainWindow
.
getCacheObject
();
this
.
source
=
source
;
this
.
node
=
replaceNode
(
node
);
this
.
node
=
node
.
replace
(
);
initUI
();
}
...
...
@@ -108,27 +94,12 @@ public class RenameDialog extends JDialog {
renameField
.
selectAll
();
}
private
JNode
replaceNode
(
JNode
node
)
{
if
(
node
instanceof
JMethod
)
{
JavaMethod
javaMethod
=
((
JMethod
)
node
).
getJavaMethod
();
if
(
javaMethod
.
isClassInit
())
{
throw
new
JadxRuntimeException
(
"Can't rename class init method: "
+
node
);
}
if
(
javaMethod
.
isConstructor
())
{
// rename class instead constructor
return
node
.
getJParent
();
}
}
return
node
;
}
private
boolean
checkNewName
()
{
String
newName
=
renameField
.
getText
();
private
boolean
checkNewName
(
String
newName
)
{
if
(
newName
.
isEmpty
())
{
// use empty name to reset rename (revert to original)
return
true
;
}
boolean
valid
=
NameMapper
.
isValidIdentifier
(
newName
);
boolean
valid
=
node
.
isValidName
(
newName
);
if
(
renameBtn
.
isEnabled
()
!=
valid
)
{
renameBtn
.
setEnabled
(
valid
);
renameField
.
putClientProperty
(
"JComponent.outline"
,
valid
?
""
:
"error"
);
...
...
@@ -137,11 +108,12 @@ public class RenameDialog extends JDialog {
}
private
void
rename
()
{
if
(!
checkNewName
())
{
String
newName
=
renameField
.
getText
().
trim
();
if
(!
checkNewName
(
newName
))
{
return
;
}
try
{
updateCodeRenames
(
set
->
processRename
(
n
ode
,
renameField
.
getText
()
,
set
));
updateCodeRenames
(
set
->
processRename
(
n
ewName
,
set
));
refreshState
();
}
catch
(
Exception
e
)
{
LOG
.
error
(
"Rename failed"
,
e
);
...
...
@@ -150,46 +122,15 @@ public class RenameDialog extends JDialog {
dispose
();
}
private
void
processRename
(
JNode
node
,
String
newName
,
Set
<
ICodeRename
>
renames
)
{
JadxCodeRename
rename
=
buildRename
(
node
,
newName
,
renames
);
private
void
processRename
(
String
newName
,
Set
<
ICodeRename
>
renames
)
{
ICodeRename
rename
=
node
.
buildCodeRename
(
newName
,
renames
);
renames
.
remove
(
rename
);
JavaNode
javaNode
=
node
.
getJavaNode
();
if
(
javaNode
!=
null
)
{
javaNode
.
removeAlias
();
}
node
.
removeAlias
();
if
(!
newName
.
isEmpty
())
{
renames
.
add
(
rename
);
}
}
@NotNull
private
JadxCodeRename
buildRename
(
JNode
node
,
String
newName
,
Set
<
ICodeRename
>
renames
)
{
if
(
node
instanceof
JMethod
)
{
JavaMethod
javaMethod
=
((
JMethod
)
node
).
getJavaMethod
();
List
<
JavaMethod
>
relatedMethods
=
javaMethod
.
getOverrideRelatedMethods
();
if
(!
relatedMethods
.
isEmpty
())
{
for
(
JavaMethod
relatedMethod
:
relatedMethods
)
{
renames
.
remove
(
new
JadxCodeRename
(
JadxNodeRef
.
forMth
(
relatedMethod
),
""
));
}
}
return
new
JadxCodeRename
(
JadxNodeRef
.
forMth
(
javaMethod
),
newName
);
}
if
(
node
instanceof
JField
)
{
return
new
JadxCodeRename
(
JadxNodeRef
.
forFld
(((
JField
)
node
).
getJavaField
()),
newName
);
}
if
(
node
instanceof
JClass
)
{
return
new
JadxCodeRename
(
JadxNodeRef
.
forCls
(((
JClass
)
node
).
getCls
()),
newName
);
}
if
(
node
instanceof
JPackage
)
{
return
new
JadxCodeRename
(
JadxNodeRef
.
forPkg
(((
JPackage
)
node
).
getFullName
()),
newName
);
}
if
(
node
instanceof
JVariable
)
{
JavaVariable
javaVar
=
((
JVariable
)
node
).
getJavaVarNode
();
return
new
JadxCodeRename
(
JadxNodeRef
.
forMth
(
javaVar
.
getMth
()),
JadxCodeRef
.
forVar
(
javaVar
),
newName
);
}
throw
new
JadxRuntimeException
(
"Failed to build rename node for: "
+
node
);
}
private
void
updateCodeRenames
(
Consumer
<
Set
<
ICodeRename
>>
updater
)
{
JadxProject
project
=
mainWindow
.
getProject
();
JadxCodeData
codeData
=
project
.
getCodeData
();
...
...
@@ -208,24 +149,13 @@ public class RenameDialog extends JDialog {
private
void
refreshState
()
{
mainWindow
.
getWrapper
().
reInitRenameVisitor
();
JNodeCache
nodeCache
=
cache
.
getNodeCache
();
JavaNode
javaNode
=
node
.
getJavaNode
();
List
<
JavaNode
>
toUpdate
=
new
ArrayList
<>();
if
(
source
!=
null
&&
source
!=
node
)
{
toUpdate
.
add
(
source
.
getJavaNode
());
}
if
(
javaNode
!=
null
)
{
toUpdate
.
add
(
javaNode
);
toUpdate
.
addAll
(
javaNode
.
getUseIn
());
if
(
node
instanceof
JMethod
)
{
toUpdate
.
addAll
(((
JMethod
)
node
).
getJavaMethod
().
getOverrideRelatedMethods
());
}
}
else
if
(
node
instanceof
JPackage
)
{
processPackage
(
toUpdate
);
}
else
{
throw
new
JadxRuntimeException
(
"Unexpected node type: "
+
node
);
}
node
.
addUpdateNodes
(
toUpdate
);
JNodeCache
nodeCache
=
cache
.
getNodeCache
();
Set
<
JClass
>
updatedTopClasses
=
toUpdate
.
stream
()
.
map
(
JavaNode:
:
getTopParentClass
)
...
...
@@ -245,28 +175,15 @@ public class RenameDialog extends JDialog {
mainWindow
.
showHeapUsageBar
();
UiUtils
.
errorMessage
(
this
,
NLS
.
str
(
"message.memoryLow"
));
}
if
(
node
instanceof
JPackage
)
{
mainWindow
.
getTreeRoot
().
update
();
}
mainWindow
.
reloadTree
();
// if (node instanceof JPackage) {
// mainWindow.getTreeRoot().update();
// }
// mainWindow.reloadTree();
node
.
reload
(
mainWindow
);
});
}
}
private
void
processPackage
(
List
<
JavaNode
>
toUpdate
)
{
String
rawFullPkg
=
((
JPackage
)
node
).
getFullName
();
String
rawFullPkgDot
=
rawFullPkg
+
"."
;
for
(
JavaClass
cls
:
mainWindow
.
getWrapper
().
getClasses
())
{
String
clsPkg
=
cls
.
getClassNode
().
getClassInfo
().
getPackage
();
// search all classes in package
if
(
clsPkg
.
equals
(
rawFullPkg
)
||
clsPkg
.
startsWith
(
rawFullPkgDot
))
{
toUpdate
.
add
(
cls
);
// also include all usages (for import fix)
toUpdate
.
addAll
(
cls
.
getUseIn
());
}
}
}
private
void
refreshClasses
(
Set
<
JClass
>
updatedTopClasses
)
{
if
(
updatedTopClasses
.
size
()
<
10
)
{
// small batch => reload
...
...
@@ -323,11 +240,11 @@ public class RenameDialog extends JDialog {
private
void
initUI
()
{
JLabel
lbl
=
new
JLabel
(
NLS
.
str
(
"popup.rename"
));
JLabel
nodeLabel
=
new
JLabel
(
this
.
node
.
makeLongStringHtml
(),
this
.
node
.
getIcon
(),
SwingConstants
.
LEFT
);
JLabel
nodeLabel
=
new
JLabel
(
node
.
getTitle
(),
node
.
getIcon
(),
SwingConstants
.
LEFT
);
lbl
.
setLabelFor
(
nodeLabel
);
renameField
=
new
JTextField
(
40
);
renameField
.
getDocument
().
addDocumentListener
(
new
DocumentUpdateListener
(
ev
->
checkNewName
()));
renameField
.
getDocument
().
addDocumentListener
(
new
DocumentUpdateListener
(
ev
->
checkNewName
(
renameField
.
getText
()
)));
renameField
.
addActionListener
(
e
->
rename
());
new
TextStandardActions
(
renameField
);
...
...
jadx-gui/src/main/java/jadx/gui/ui/popupmenu/JPackagePopupMenu.java
浏览文件 @
e07bc7f6
package
jadx.gui.ui.popupmenu
;
import
java.awt.event.ActionEvent
;
import
java.util.Arrays
;
import
java.util.List
;
import
javax.swing.AbstractAction
;
...
...
@@ -10,17 +9,17 @@ import javax.swing.JMenu;
import
javax.swing.JMenuItem
;
import
javax.swing.JPopupMenu
;
import
org.jetbrains.annotations.Nullable
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JPackage
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.ui.dialog.ExcludePkgDialog
;
import
jadx.gui.ui.dialog.RenameDialog
;
import
jadx.gui.utils.NLS
;
import
jadx.gui.utils.pkgs.JRenamePackage
;
import
jadx.gui.utils.pkgs.PackageHelper
;
public
class
JPackagePopupMenu
extends
JPopupMenu
{
private
static
final
long
serialVersionUID
=
-
7781009781149224131L
;
...
...
@@ -34,79 +33,24 @@ public class JPackagePopupMenu extends JPopupMenu {
add
(
makeExcludeItem
(
pkg
));
add
(
makeExcludeItem
());
JMenuItem
menuItem
=
makeRenameMenuItem
(
pkg
);
if
(
menuItem
!=
null
)
{
add
(
menuItem
);
}
add
(
makeRenameMenuItem
(
pkg
));
}
@Nullable
private
JMenuItem
makeRenameMenuItem
(
JPackage
pkg
)
{
List
<
String
>
aliasShortParts
=
splitPackage
(
pkg
.
getName
());
int
count
=
aliasShortParts
.
size
();
if
(
count
==
0
)
{
return
null
;
}
String
rawPackage
=
getRawPackage
(
pkg
);
if
(
rawPackage
==
null
)
{
return
null
;
}
List
<
String
>
aliasParts
=
splitPackage
(
pkg
.
getFullName
());
List
<
String
>
rawParts
=
splitPackage
(
rawPackage
);
// can be longer then alias parts
int
start
=
aliasParts
.
size
()
-
count
;
if
(
count
==
1
)
{
// single case => no submenu
JPackage
renamePkg
=
new
JPackage
(
concat
(
rawParts
,
start
),
aliasParts
.
get
(
start
));
JMenuItem
pkgItem
=
new
JMenuItem
(
NLS
.
str
(
"popup.rename"
));
pkgItem
.
addActionListener
(
e
->
rename
(
renamePkg
));
return
pkgItem
;
}
JMenuItem
renameSubMenu
=
new
JMenu
(
NLS
.
str
(
"popup.rename"
));
for
(
int
i
=
start
;
i
<
aliasParts
.
size
();
i
++)
{
String
aliasShortPkg
=
aliasParts
.
get
(
i
);
JPackage
pkgPart
=
new
JPackage
(
concat
(
rawParts
,
i
),
aliasShortPkg
);
JMenuItem
pkgPartItem
=
new
JMenuItem
(
aliasShortPkg
);
pkgPartItem
.
addActionListener
(
e
->
rename
(
pkgPart
));
PackageHelper
packageHelper
=
mainWindow
.
getCacheObject
().
getPackageHelper
();
List
<
JRenamePackage
>
nodes
=
packageHelper
.
getRenameNodes
(
pkg
);
for
(
JRenamePackage
node
:
nodes
)
{
JMenuItem
pkgPartItem
=
new
JMenuItem
(
node
.
getTitle
(),
node
.
getIcon
()
);
pkgPartItem
.
addActionListener
(
e
->
rename
(
node
));
renameSubMenu
.
add
(
pkgPartItem
);
}
return
renameSubMenu
;
}
private
String
concat
(
List
<
String
>
parts
,
int
n
)
{
if
(
n
==
0
)
{
return
parts
.
get
(
0
);
}
StringBuilder
sb
=
new
StringBuilder
();
sb
.
append
(
parts
.
get
(
0
));
int
count
=
parts
.
size
();
for
(
int
i
=
1
;
i
<
count
&&
i
<=
n
;
i
++)
{
sb
.
append
(
'.'
);
sb
.
append
(
parts
.
get
(
i
));
}
return
sb
.
toString
();
}
private
void
rename
(
JPackage
pkg
)
{
LOG
.
debug
(
"Renaming package: fullName={}, name={}"
,
pkg
.
getFullName
(),
pkg
.
getName
());
RenameDialog
.
rename
(
mainWindow
,
pkg
);
}
private
List
<
String
>
splitPackage
(
String
rawPackage
)
{
return
Arrays
.
asList
(
rawPackage
.
split
(
"\\."
));
}
private
String
getRawPackage
(
JPackage
pkg
)
{
List
<
JClass
>
classes
=
pkg
.
getClasses
();
if
(!
classes
.
isEmpty
())
{
return
classes
.
get
(
0
).
getRootClass
().
getCls
().
getClassNode
().
getClassInfo
().
getPackage
();
}
for
(
JPackage
innerPkg
:
pkg
.
getInnerPackages
())
{
String
rawPackage
=
getRawPackage
(
innerPkg
);
if
(
rawPackage
!=
null
)
{
return
rawPackage
;
}
}
return
null
;
private
void
rename
(
JRenamePackage
pkg
)
{
LOG
.
debug
(
"Renaming package: {}"
,
pkg
);
RenameDialog
.
rename
(
mainWindow
,
null
,
pkg
);
}
private
JMenuItem
makeExcludeItem
(
JPackage
pkg
)
{
...
...
@@ -114,7 +58,7 @@ public class JPackagePopupMenu extends JPopupMenu {
excludeItem
.
setSelected
(!
pkg
.
isEnabled
());
excludeItem
.
addItemListener
(
e
->
{
JadxWrapper
wrapper
=
mainWindow
.
getWrapper
();
String
fullName
=
pkg
.
getFullName
();
String
fullName
=
pkg
.
get
Pkg
().
get
FullName
();
if
(
excludeItem
.
isSelected
())
{
wrapper
.
addExcludedPackage
(
fullName
);
}
else
{
...
...
jadx-gui/src/main/java/jadx/gui/utils/CacheObject.java
浏览文件 @
e07bc7f6
...
...
@@ -11,6 +11,7 @@ import jadx.api.JavaClass;
import
jadx.gui.settings.JadxSettings
;
import
jadx.gui.treemodel.JRoot
;
import
jadx.gui.ui.dialog.SearchDialog
;
import
jadx.gui.utils.pkgs.PackageHelper
;
public
class
CacheObject
{
...
...
@@ -22,6 +23,7 @@ public class CacheObject {
private
JadxSettings
settings
;
private
List
<
List
<
JavaClass
>>
decompileBatches
;
private
PackageHelper
packageHelper
;
public
CacheObject
()
{
reset
();
...
...
@@ -34,6 +36,7 @@ public class CacheObject {
jNodeCache
=
new
JNodeCache
();
lastSearchOptions
=
new
HashMap
<>();
decompileBatches
=
null
;
packageHelper
=
null
;
}
@Nullable
...
...
@@ -76,4 +79,12 @@ public class CacheObject {
public
void
setDecompileBatches
(
List
<
List
<
JavaClass
>>
decompileBatches
)
{
this
.
decompileBatches
=
decompileBatches
;
}
public
PackageHelper
getPackageHelper
()
{
return
packageHelper
;
}
public
void
setPackageHelper
(
PackageHelper
packageHelper
)
{
this
.
packageHelper
=
packageHelper
;
}
}
jadx-gui/src/main/java/jadx/gui/utils/JNodeCache.java
浏览文件 @
e07bc7f6
...
...
@@ -23,7 +23,7 @@ public class JNodeCache {
if
(
javaNode
==
null
)
{
return
null
;
}
// don't use 'computeIfAbsent' method here, it
this
cause 'Recursive update' exception
// don't use 'computeIfAbsent' method here, it
will
cause 'Recursive update' exception
JNode
jNode
=
cache
.
get
(
javaNode
);
if
(
jNode
==
null
||
jNode
.
getJavaNode
()
!=
javaNode
)
{
jNode
=
convert
(
javaNode
);
...
...
jadx-gui/src/main/java/jadx/gui/utils/pkgs/JRenamePackage.java
0 → 100644
浏览文件 @
e07bc7f6
package
jadx.gui.utils.pkgs
;
import
java.util.List
;
import
java.util.Set
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
import
javax.swing.Icon
;
import
org.apache.commons.lang3.StringUtils
;
import
jadx.api.JavaNode
;
import
jadx.api.JavaPackage
;
import
jadx.api.data.ICodeRename
;
import
jadx.api.data.impl.JadxCodeRename
;
import
jadx.api.data.impl.JadxNodeRef
;
import
jadx.core.deobf.NameMapper
;
import
jadx.gui.treemodel.JRenameNode
;
import
jadx.gui.ui.MainWindow
;
import
jadx.gui.utils.Icons
;
import
static
jadx
.
core
.
deobf
.
NameMapper
.
VALID_JAVA_IDENTIFIER
;
public
class
JRenamePackage
implements
JRenameNode
{
private
final
JavaPackage
refPkg
;
private
final
String
rawFullName
;
private
final
String
fullName
;
private
final
String
name
;
public
JRenamePackage
(
JavaPackage
refPkg
,
String
rawFullName
,
String
fullName
,
String
name
)
{
this
.
refPkg
=
refPkg
;
this
.
rawFullName
=
rawFullName
;
this
.
fullName
=
fullName
;
this
.
name
=
name
;
}
@Override
public
String
getTitle
()
{
return
fullName
;
}
@Override
public
String
getName
()
{
return
name
;
}
@Override
public
Icon
getIcon
()
{
return
Icons
.
PACKAGE
;
}
@Override
public
boolean
canRename
()
{
return
true
;
}
@Override
public
ICodeRename
buildCodeRename
(
String
newName
,
Set
<
ICodeRename
>
renames
)
{
return
new
JadxCodeRename
(
JadxNodeRef
.
forPkg
(
rawFullName
),
newName
);
}
@Override
public
boolean
isValidName
(
String
newName
)
{
return
isValidPackageName
(
newName
);
}
private
static
final
Pattern
PACKAGE_RENAME_PATTERN
=
Pattern
.
compile
(
"PKG(\\.PKG)*(\\.)?"
.
replace
(
"PKG"
,
VALID_JAVA_IDENTIFIER
.
pattern
()));
static
boolean
isValidPackageName
(
String
newName
)
{
if
(
newName
==
null
||
newName
.
isEmpty
()
||
NameMapper
.
isReserved
(
newName
))
{
return
false
;
}
Matcher
matcher
=
PACKAGE_RENAME_PATTERN
.
matcher
(
newName
);
if
(!
matcher
.
matches
())
{
return
false
;
}
for
(
String
part
:
StringUtils
.
split
(
newName
,
'.'
))
{
if
(
NameMapper
.
isReserved
(
part
))
{
return
false
;
}
}
return
true
;
}
@Override
public
void
removeAlias
()
{
refPkg
.
removeAlias
();
}
@Override
public
void
addUpdateNodes
(
List
<
JavaNode
>
toUpdate
)
{
refPkg
.
addUseIn
(
toUpdate
);
}
@Override
public
void
reload
(
MainWindow
mainWindow
)
{
mainWindow
.
getCacheObject
().
setPackageHelper
(
null
);
mainWindow
.
getTreeRoot
().
update
();
mainWindow
.
reloadTree
();
}
}
jadx-gui/src/main/java/jadx/gui/utils/pkgs/PackageHelper.java
0 → 100644
浏览文件 @
e07bc7f6
package
jadx.gui.utils.pkgs
;
import
java.util.ArrayList
;
import
java.util.Collections
;
import
java.util.Comparator
;
import
java.util.HashMap
;
import
java.util.HashSet
;
import
java.util.List
;
import
java.util.Map
;
import
java.util.Set
;
import
org.slf4j.Logger
;
import
org.slf4j.LoggerFactory
;
import
jadx.api.JavaPackage
;
import
jadx.core.dex.info.PackageInfo
;
import
jadx.core.utils.ListUtils
;
import
jadx.core.utils.Utils
;
import
jadx.gui.JadxWrapper
;
import
jadx.gui.treemodel.JClass
;
import
jadx.gui.treemodel.JPackage
;
import
jadx.gui.utils.JNodeCache
;
public
class
PackageHelper
{
private
static
final
Logger
LOG
=
LoggerFactory
.
getLogger
(
PackageHelper
.
class
);
private
static
final
Comparator
<
JClass
>
CLASS_COMPARATOR
=
Comparator
.
comparing
(
JClass:
:
getName
,
String
.
CASE_INSENSITIVE_ORDER
);
private
static
final
Comparator
<
JPackage
>
PKG_COMPARATOR
=
Comparator
.
comparing
(
JPackage:
:
getName
,
String
.
CASE_INSENSITIVE_ORDER
);
private
final
JadxWrapper
wrapper
;
private
List
<
String
>
excludedPackages
;
private
JNodeCache
nodeCache
;
private
final
Map
<
PackageInfo
,
JPackage
>
pkgInfoMap
=
new
HashMap
<>();
public
PackageHelper
(
JadxWrapper
wrapper
)
{
this
.
wrapper
=
wrapper
;
}
public
List
<
JPackage
>
getRoots
(
boolean
flatPackages
)
{
excludedPackages
=
wrapper
.
getExcludedPackages
();
nodeCache
=
wrapper
.
getCache
().
getNodeCache
();
pkgInfoMap
.
clear
();
if
(
flatPackages
)
{
return
prepareFlatPackages
();
}
long
start
=
System
.
currentTimeMillis
();
List
<
JPackage
>
roots
=
prepareHierarchyPackages
();
if
(
LOG
.
isDebugEnabled
())
{
LOG
.
debug
(
"Prepare hierarchy packages in {} ms"
,
System
.
currentTimeMillis
()
-
start
);
}
return
roots
;
}
public
List
<
JRenamePackage
>
getRenameNodes
(
JPackage
pkg
)
{
List
<
JRenamePackage
>
list
=
new
ArrayList
<>();
PackageInfo
pkgInfo
=
pkg
.
getPkg
().
getPkgNode
().
getAliasPkgInfo
();
Set
<
String
>
added
=
new
HashSet
<>();
do
{
JPackage
jPkg
=
pkgInfoMap
.
get
(
pkgInfo
);
if
(
jPkg
!=
null
)
{
JavaPackage
javaPkg
=
jPkg
.
getPkg
();
String
fullName
=
javaPkg
.
isDefault
()
?
JPackage
.
PACKAGE_DEFAULT_HTML_STR
:
javaPkg
.
getFullName
();
String
name
=
jPkg
.
isSynthetic
()
||
javaPkg
.
isParentRenamed
()
?
fullName
:
javaPkg
.
getName
();
JRenamePackage
renamePkg
=
new
JRenamePackage
(
javaPkg
,
javaPkg
.
getRawFullName
(),
fullName
,
name
);
if
(
added
.
add
(
fullName
))
{
list
.
add
(
renamePkg
);
}
}
pkgInfo
=
pkgInfo
.
getParentPkg
();
}
while
(
pkgInfo
!=
null
);
return
list
;
}
private
List
<
JPackage
>
prepareFlatPackages
()
{
List
<
JPackage
>
list
=
new
ArrayList
<>();
for
(
JavaPackage
javaPkg
:
wrapper
.
getPackages
())
{
if
(
javaPkg
.
isLeaf
())
{
JPackage
pkg
=
buildJPackage
(
javaPkg
,
false
);
pkg
.
setName
(
javaPkg
.
getFullName
());
list
.
add
(
pkg
);
pkgInfoMap
.
put
(
javaPkg
.
getPkgNode
().
getAliasPkgInfo
(),
pkg
);
}
}
list
.
sort
(
PKG_COMPARATOR
);
return
list
;
}
private
List
<
JPackage
>
prepareHierarchyPackages
()
{
JPackage
root
=
new
JPackage
(
null
,
true
,
Collections
.
emptyList
(),
new
ArrayList
<>(),
true
);
List
<
JavaPackage
>
packages
=
wrapper
.
getPackages
();
List
<
JPackage
>
jPackages
=
new
ArrayList
<>(
packages
.
size
());
// create nodes for exists packages
for
(
JavaPackage
javaPkg
:
packages
)
{
JPackage
jPkg
=
buildJPackage
(
javaPkg
,
false
);
jPackages
.
add
(
jPkg
);
PackageInfo
aliasPkgInfo
=
javaPkg
.
getPkgNode
().
getAliasPkgInfo
();
jPkg
.
setName
(
aliasPkgInfo
.
getName
());
pkgInfoMap
.
put
(
aliasPkgInfo
,
jPkg
);
if
(
aliasPkgInfo
.
isRoot
())
{
root
.
getSubPackages
().
add
(
jPkg
);
}
}
// link subpackages, create missing packages created by renames
for
(
JPackage
jPkg
:
jPackages
)
{
if
(
jPkg
.
getPkg
().
isLeaf
())
{
buildLeafPath
(
jPkg
,
root
,
pkgInfoMap
);
}
}
List
<
JPackage
>
toMerge
=
new
ArrayList
<>();
traverseMiddlePackages
(
root
,
toMerge
);
Utils
.
treeDfsVisit
(
root
,
JPackage:
:
getSubPackages
,
v
->
v
.
getSubPackages
().
sort
(
PKG_COMPARATOR
));
return
root
.
getSubPackages
();
}
private
void
buildLeafPath
(
JPackage
jPkg
,
JPackage
root
,
Map
<
PackageInfo
,
JPackage
>
pkgMap
)
{
JPackage
currentJPkg
=
jPkg
;
PackageInfo
current
=
jPkg
.
getPkg
().
getPkgNode
().
getAliasPkgInfo
();
while
(
true
)
{
current
=
current
.
getParentPkg
();
if
(
current
==
null
)
{
break
;
}
JPackage
parentJPkg
=
pkgMap
.
get
(
current
);
if
(
parentJPkg
==
null
)
{
parentJPkg
=
buildJPackage
(
currentJPkg
.
getPkg
(),
true
);
parentJPkg
.
setName
(
current
.
getName
());
pkgMap
.
put
(
current
,
parentJPkg
);
if
(
current
.
isRoot
())
{
root
.
getSubPackages
().
add
(
parentJPkg
);
}
}
List
<
JPackage
>
subPackages
=
parentJPkg
.
getSubPackages
();
String
pkgName
=
currentJPkg
.
getName
();
if
(
ListUtils
.
noneMatch
(
subPackages
,
p
->
p
.
getName
().
equals
(
pkgName
)))
{
subPackages
.
add
(
currentJPkg
);
}
currentJPkg
=
parentJPkg
;
}
}
private
static
void
traverseMiddlePackages
(
JPackage
pkg
,
List
<
JPackage
>
toMerge
)
{
List
<
JPackage
>
subPackages
=
pkg
.
getSubPackages
();
int
count
=
subPackages
.
size
();
for
(
int
i
=
0
;
i
<
count
;
i
++)
{
JPackage
subPackage
=
subPackages
.
get
(
i
);
JPackage
replacePkg
=
mergeMiddlePackages
(
subPackage
,
toMerge
);
if
(
replacePkg
!=
subPackage
)
{
subPackages
.
set
(
i
,
replacePkg
);
}
traverseMiddlePackages
(
replacePkg
,
toMerge
);
}
}
private
static
JPackage
mergeMiddlePackages
(
JPackage
jPkg
,
List
<
JPackage
>
merged
)
{
List
<
JPackage
>
subPackages
=
jPkg
.
getSubPackages
();
if
(
subPackages
.
size
()
==
1
&&
jPkg
.
getClasses
().
isEmpty
())
{
merged
.
add
(
jPkg
);
JPackage
endPkg
=
mergeMiddlePackages
(
subPackages
.
get
(
0
),
merged
);
merged
.
clear
();
return
endPkg
;
}
if
(!
merged
.
isEmpty
())
{
merged
.
add
(
jPkg
);
jPkg
.
setName
(
Utils
.
listToString
(
merged
,
"."
,
JPackage:
:
getName
));
}
return
jPkg
;
}
private
JPackage
buildJPackage
(
JavaPackage
javaPkg
,
boolean
synthetic
)
{
boolean
pkgEnabled
=
isPkgEnabled
(
javaPkg
.
getRawFullName
(),
excludedPackages
);
List
<
JClass
>
classes
;
if
(
synthetic
)
{
classes
=
Collections
.
emptyList
();
}
else
{
classes
=
Utils
.
collectionMap
(
javaPkg
.
getClasses
(),
nodeCache:
:
makeFrom
);
classes
.
sort
(
CLASS_COMPARATOR
);
}
return
new
JPackage
(
javaPkg
,
pkgEnabled
,
classes
,
new
ArrayList
<>(),
synthetic
);
}
private
static
boolean
isPkgEnabled
(
String
fullPkgName
,
List
<
String
>
excludedPackages
)
{
return
excludedPackages
.
isEmpty
()
||
excludedPackages
.
stream
()
.
noneMatch
(
p
->
fullPkgName
.
equals
(
p
)
||
fullPkgName
.
startsWith
(
p
+
'.'
));
}
}
jadx-gui/src/test/java/jadx/api/Factory.java
已删除
100644 → 0
浏览文件 @
5894fadc
package
jadx.api
;
import
java.util.List
;
import
jadx.core.dex.nodes.ClassNode
;
public
class
Factory
{
public
static
JavaPackage
newPackage
(
String
name
,
List
<
JavaClass
>
classes
)
{
return
new
JavaPackage
(
name
,
classes
);
}
public
static
JavaClass
newClass
(
JadxDecompiler
decompiler
,
ClassNode
classNode
)
{
return
new
JavaClass
(
classNode
,
decompiler
);
}
}
jadx-gui/src/test/java/jadx/gui/treemodel/JSourcesTest.java
已删除
100644 → 0
浏览文件 @
5894fadc
package
jadx.gui.treemodel
;
import
java.util.Collections
;
import
java.util.List
;
import
org.junit.jupiter.api.BeforeEach
;
import
org.junit.jupiter.api.Test
;
import
jadx.api.Factory
;
import
jadx.api.JadxArgs
;
import
jadx.api.JadxDecompiler
;
import
jadx.api.JavaClass
;
import
jadx.api.JavaPackage
;
import
jadx.core.dex.nodes.ClassNode
;
import
jadx.gui.JadxWrapper
;
import
static
java
.
util
.
Arrays
.
asList
;
import
static
org
.
hamcrest
.
MatcherAssert
.
assertThat
;
import
static
org
.
hamcrest
.
Matchers
.
hasSize
;
import
static
org
.
hamcrest
.
Matchers
.
is
;
import
static
org
.
mockito
.
Mockito
.
mock
;
import
static
org
.
mockito
.
Mockito
.
when
;
public
class
JSourcesTest
{
private
JSources
sources
;
private
JadxDecompiler
decompiler
;
@BeforeEach
public
void
init
()
{
JRoot
root
=
mock
(
JRoot
.
class
);
when
(
root
.
isFlatPackages
()).
thenReturn
(
false
);
JadxWrapper
wrapper
=
mock
(
JadxWrapper
.
class
);
sources
=
new
JSources
(
root
,
wrapper
);
decompiler
=
new
JadxDecompiler
(
new
JadxArgs
());
}
@Test
public
void
testHierarchyPackages
()
{
String
pkgName
=
"a.b.c.d.e"
;
List
<
JavaPackage
>
packages
=
Collections
.
singletonList
(
newPkg
(
pkgName
));
List
<
JPackage
>
out
=
sources
.
getHierarchyPackages
(
packages
);
assertThat
(
out
,
hasSize
(
1
));
JPackage
jPkg
=
out
.
get
(
0
);
assertThat
(
jPkg
.
getName
(),
is
(
pkgName
));
assertThat
(
jPkg
.
getClasses
(),
hasSize
(
1
));
}
@Test
public
void
testHierarchyPackages2
()
{
List
<
JavaPackage
>
packages
=
asList
(
newPkg
(
"a.b"
),
newPkg
(
"a.c"
),
newPkg
(
"a.d"
));
List
<
JPackage
>
out
=
sources
.
getHierarchyPackages
(
packages
);
assertThat
(
out
,
hasSize
(
1
));
JPackage
jPkg
=
out
.
get
(
0
);
assertThat
(
jPkg
.
getName
(),
is
(
"a"
));
assertThat
(
jPkg
.
getClasses
(),
hasSize
(
0
));
assertThat
(
jPkg
.
getInnerPackages
(),
hasSize
(
3
));
}
@Test
public
void
testHierarchyPackages3
()
{
List
<
JavaPackage
>
packages
=
asList
(
newPkg
(
"a.b.p1"
),
newPkg
(
"a.b.p2"
),
newPkg
(
"a.b.p3"
));
List
<
JPackage
>
out
=
sources
.
getHierarchyPackages
(
packages
);
assertThat
(
out
,
hasSize
(
1
));
JPackage
jPkg
=
out
.
get
(
0
);
assertThat
(
jPkg
.
getName
(),
is
(
"a.b"
));
assertThat
(
jPkg
.
getClasses
(),
hasSize
(
0
));
assertThat
(
jPkg
.
getInnerPackages
(),
hasSize
(
3
));
}
@Test
public
void
testHierarchyPackages4
()
{
List
<
JavaPackage
>
packages
=
asList
(
newPkg
(
"a.p1"
),
newPkg
(
"a.b.c.p2"
),
newPkg
(
"a.b.c.p3"
),
newPkg
(
"d.e"
),
newPkg
(
"d.f.a"
));
List
<
JPackage
>
out
=
sources
.
getHierarchyPackages
(
packages
);
assertThat
(
out
,
hasSize
(
2
));
assertThat
(
out
.
get
(
0
).
getName
(),
is
(
"a"
));
assertThat
(
out
.
get
(
0
).
getInnerPackages
(),
hasSize
(
2
));
assertThat
(
out
.
get
(
1
).
getName
(),
is
(
"d"
));
assertThat
(
out
.
get
(
1
).
getInnerPackages
(),
hasSize
(
2
));
}
private
JavaPackage
newPkg
(
String
name
)
{
return
Factory
.
newPackage
(
name
,
Collections
.
singletonList
(
newClass
()));
}
private
JavaClass
newClass
()
{
return
Factory
.
newClass
(
decompiler
,
mock
(
ClassNode
.
class
));
}
}
jadx-gui/src/test/java/jadx/gui/utils/pkgs/TestJRenamePackage.java
0 → 100644
浏览文件 @
e07bc7f6
package
jadx.gui.utils.pkgs
;
import
org.junit.jupiter.api.Test
;
import
static
org
.
assertj
.
core
.
api
.
Assertions
.
assertThat
;
class
TestJRenamePackage
{
@Test
void
isValidName
()
{
valid
(
"foo"
);
valid
(
"foo.bar"
);
valid
(
"foo.bar."
);
invalid
(
""
);
invalid
(
"0foo"
);
invalid
(
".foo"
);
invalid
(
"do"
);
invalid
(
"foo.if"
);
invalid
(
"foo.if.bar"
);
}
private
void
valid
(
String
name
)
{
assertThat
(
JRenamePackage
.
isValidPackageName
(
name
))
.
as
(
"expect valid: %s"
,
name
)
.
isEqualTo
(
true
);
}
private
void
invalid
(
String
name
)
{
assertThat
(
JRenamePackage
.
isValidPackageName
(
name
))
.
as
(
"expect invalid: %s"
,
name
)
.
isEqualTo
(
false
);
}
}
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录