diff --git a/README.md b/README.md index f9af04c5f09..bd2106189ba 100644 --- a/README.md +++ b/README.md @@ -144,6 +144,7 @@ options: 'always' - always use source name if it's available 'if-better' - use source name if it seems better than the current one 'never' - never use source name, even if it's available + --source-name-repeat-limit - allow using source name if it appears less than a limit number, default: 10 --use-kotlin-methods-for-var-names - use kotlin intrinsic methods to rename variables, values: disable, apply, apply-and-hide, default: apply --rename-flags - fix options (comma-separated list of): 'case' - fix case sensitivity issues (according to --fs-case-sensitive option), diff --git a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java index 20526b41e51..b08e1f71b6a 100644 --- a/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java +++ b/jadx-cli/src/main/java/jadx/cli/JadxCLIArgs.java @@ -200,6 +200,12 @@ public class JadxCLIArgs { ) protected UseSourceNameAsClassNameAlias useSourceNameAsClassNameAlias = null; + @Parameter( + names = { "--source-name-repeat-limit" }, + description = "allow using source name if it appears less than a limit number" + ) + protected int sourceNameRepeatLimit = 10; + @Parameter( names = { "--use-kotlin-methods-for-var-names" }, description = "use kotlin intrinsic methods to rename variables, values: disable, apply, apply-and-hide", @@ -352,6 +358,7 @@ public JadxArgs toJadxArgs() { args.setDeobfuscationMaxLength(deobfuscationMaxLength); args.setDeobfuscationWhitelist(Arrays.asList(deobfuscationWhitelistStr.split(" "))); args.setUseSourceNameAsClassNameAlias(getUseSourceNameAsClassNameAlias()); + args.setSourceNameRepeatLimit(sourceNameRepeatLimit); args.setUseKotlinMethodsForVarNames(useKotlinMethodsForVarNames); args.setResourceNameSource(resourceNameSource); args.setEscapeUnicode(escapeUnicode); @@ -508,6 +515,10 @@ public UseSourceNameAsClassNameAlias getUseSourceNameAsClassNameAlias() { } } + public int getSourceNameRepeatLimit() { + return sourceNameRepeatLimit; + } + /** * @deprecated Use {@link #getUseSourceNameAsClassNameAlias()} instead. */ diff --git a/jadx-core/src/main/java/jadx/api/JadxArgs.java b/jadx-core/src/main/java/jadx/api/JadxArgs.java index 62b749ca679..b3677516d62 100644 --- a/jadx-core/src/main/java/jadx/api/JadxArgs.java +++ b/jadx-core/src/main/java/jadx/api/JadxArgs.java @@ -106,6 +106,7 @@ public class JadxArgs implements Closeable { private boolean deobfuscationOn = false; private UseSourceNameAsClassNameAlias useSourceNameAsClassNameAlias = UseSourceNameAsClassNameAlias.getDefault(); + private int sourceNameRepeatLimit = 10; private File generatedRenamesMappingFile = null; private GeneratedRenamesMappingFileMode generatedRenamesMappingFileMode = GeneratedRenamesMappingFileMode.getDefault(); @@ -460,6 +461,14 @@ public void setUseSourceNameAsClassNameAlias(UseSourceNameAsClassNameAlias useSo this.useSourceNameAsClassNameAlias = useSourceNameAsClassNameAlias; } + public int getSourceNameRepeatLimit() { + return sourceNameRepeatLimit; + } + + public void setSourceNameRepeatLimit(int sourceNameRepeatLimit) { + this.sourceNameRepeatLimit = sourceNameRepeatLimit; + } + /** * @deprecated Use {@link #getUseSourceNameAsClassNameAlias()} instead. */ @@ -800,7 +809,7 @@ public String makeCodeArgsHash(@Nullable JadxDecompiler decompiler) { String argStr = "args:" + decompilationMode + useImports + showInconsistentCode + inlineAnonymousClasses + inlineMethods + moveInnerClasses + allowInlineKotlinLambda + deobfuscationOn + deobfuscationMinLength + deobfuscationMaxLength + deobfuscationWhitelist - + useSourceNameAsClassNameAlias + + useSourceNameAsClassNameAlias + sourceNameRepeatLimit + resourceNameSource + useKotlinMethodsForVarNames + insertDebugLines + extractFinally @@ -841,6 +850,7 @@ public String toString() { + ", generatedRenamesMappingFileMode=" + generatedRenamesMappingFileMode + ", resourceNameSource=" + resourceNameSource + ", useSourceNameAsClassNameAlias=" + useSourceNameAsClassNameAlias + + ", sourceNameRepeatLimit=" + sourceNameRepeatLimit + ", useKotlinMethodsForVarNames=" + useKotlinMethodsForVarNames + ", insertDebugLines=" + insertDebugLines + ", extractFinally=" + extractFinally diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/rename/SourceFileRename.java b/jadx-core/src/main/java/jadx/core/dex/visitors/rename/SourceFileRename.java index a6f745fc006..eaff971e88b 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/rename/SourceFileRename.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/rename/SourceFileRename.java @@ -34,11 +34,15 @@ public void init(RootNode root) throws JadxException { if (useSourceName == UseSourceNameAsClassNameAlias.NEVER) { return; } + int repeatLimit = root.getArgs().getSourceNameRepeatLimit(); + if (repeatLimit <= 1) { + return; + } List classes = root.getClasses(); - Map canUseAlias = new HashMap<>(); + Map aliasUseCount = new HashMap<>(); for (ClassNode cls : classes) { - canUseAlias.put(cls.getClassInfo().getShortName(), Boolean.FALSE); + aliasUseCount.put(cls.getClassInfo().getShortName(), 1); } List renames = new ArrayList<>(); for (ClassNode cls : classes) { @@ -47,19 +51,17 @@ public void init(RootNode root) throws JadxException { } String alias = getAliasFromSourceFile(cls); if (alias != null) { - Boolean prev = canUseAlias.get(alias); - if (prev == null) { - canUseAlias.put(alias, Boolean.TRUE); - renames.add(new ClsRename(cls, alias)); - } else if (prev == Boolean.TRUE) { - canUseAlias.put(alias, Boolean.FALSE); + int count = aliasUseCount.merge(alias, 1, Integer::sum); + if (count < repeatLimit) { + renames.add(new ClsRename(cls, alias, count)); } } } for (ClsRename clsRename : renames) { String alias = clsRename.getAlias(); - if (canUseAlias.get(alias) == Boolean.TRUE) { - applyRename(clsRename.getCls(), alias, useSourceName); + Integer count = aliasUseCount.get(alias); + if (count < repeatLimit) { + applyRename(clsRename.getCls(), clsRename.buildAlias(), useSourceName); } } } @@ -112,10 +114,12 @@ private static String getBetterName(String currentName, String sourceName, UseSo private static final class ClsRename { private final ClassNode cls; private final String alias; + private final int suffix; - private ClsRename(ClassNode cls, String alias) { + private ClsRename(ClassNode cls, String alias, int suffix) { this.cls = cls; this.alias = alias; + this.suffix = suffix; } public ClassNode getCls() { @@ -126,9 +130,17 @@ public String getAlias() { return alias; } + public int getSuffix() { + return suffix; + } + + public String buildAlias() { + return suffix < 2 ? alias : alias + suffix; + } + @Override public String toString() { - return "ClsRename{" + cls + " -> '" + alias + "'}"; + return "ClsRename{" + cls + " -> '" + alias + suffix + "'}"; } } } diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java index 1c3fffc90ca..e52ceb98501 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxSettings.java @@ -406,6 +406,10 @@ public void setUseSourceNameAsClassNameAlias(UseSourceNameAsClassNameAlias useSo this.useSourceNameAsClassNameAlias = useSourceNameAsClassNameAlias; } + public void setSourceNameRepeatLimit(int sourceNameRepeatLimit) { + this.sourceNameRepeatLimit = sourceNameRepeatLimit; + } + /** * @deprecated Use {@link #setUseSourceNameAsClassNameAlias(UseSourceNameAsClassNameAlias)} instead. */ diff --git a/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java b/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java index 439aa60da1d..0e7bbcfc2c0 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/ui/JadxSettingsWindow.java @@ -302,11 +302,18 @@ private SettingsGroup makeRenameGroup() { needReload(); }); + JSpinner repeatLimit = new JSpinner(new SpinnerNumberModel(settings.getSourceNameRepeatLimit(), 1, Integer.MAX_VALUE, 1)); + repeatLimit.addChangeListener(e -> { + settings.setSourceNameRepeatLimit((Integer) repeatLimit.getValue()); + needReload(); + }); + SettingsGroup group = new SettingsGroup(NLS.str("preferences.rename")); group.addRow(NLS.str("preferences.rename_case"), renameCaseSensitive); group.addRow(NLS.str("preferences.rename_valid"), renameValid); group.addRow(NLS.str("preferences.rename_printable"), renamePrintable); group.addRow(NLS.str("preferences.rename_use_source_name_as_class_name_alias"), useSourceNameAsClassNameAlias); + group.addRow(NLS.str("preferences.rename_source_name_repeat_limit"), repeatLimit); return group; } diff --git a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties index 9238c008006..31c377a504b 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties @@ -261,6 +261,7 @@ preferences.rename_case=System unterscheidet zwischen Groß/Kleinschreibung preferences.rename_valid=Ist eine gültige Kennung preferences.rename_printable=Ist druckbar preferences.rename_use_source_name_as_class_name_alias=Quelldateiname als Klassennamen-Alias verwenden +#preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number preferences.search_group_title=Ressourcen durchsuchen #preferences.search_results_per_page=Results per page (0 - no limit) preferences.res_file_ext=Dateierweiterungen (z.B. .xml|.html), * bedeutet alle diff --git a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties index 561096507c1..90cbbd8d2ca 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -261,6 +261,7 @@ preferences.rename_case=To fix case sensitivity issues preferences.rename_valid=To make them valid preferences.rename_printable=To make printable preferences.rename_use_source_name_as_class_name_alias=Use source file name as class name alias +preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number preferences.search_group_title=Search preferences.search_results_per_page=Results per page (0 - no limit) preferences.res_file_ext=Resource files extensions ('xml|html', * for all) diff --git a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties index 6724e1fde51..53e2661483c 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties @@ -261,6 +261,7 @@ preferences.reset_title=Reestablecer preferencias #preferences.rename_valid=To make them valid #preferences.rename_printable=To make printable preferences.rename_use_source_name_as_class_name_alias=Usar el nombre del source como alias para la clase +#preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number #preferences.search_group_title=Search #preferences.search_results_per_page=Results per page (0 - no limit) #preferences.res_file_ext=Resource files extensions ('xml|html', * for all) diff --git a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties index 423921636eb..bc6c3bfa5ce 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties @@ -261,6 +261,7 @@ preferences.rename_case=Untuk memperbaiki masalah sensitivitas huruf besar-kecil preferences.rename_valid=Untuk membuatnya valid preferences.rename_printable=Untuk membuatnya dapat dicetak preferences.rename_use_source_name_as_class_name_alias=Gunakan nama berkas sumber sebagai alias nama kelas +#preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number preferences.search_group_title=Pencarian preferences.search_results_per_page=Hasil per halaman (0 - tanpa batas) preferences.res_file_ext=Ekstensi berkas sumber daya ('xml|html', * untuk semua) diff --git a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties index 538984d5167..5ebba6089fd 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties @@ -261,6 +261,7 @@ preferences.rename_case=시스템 대소문자 구분 preferences.rename_valid=유효한 식별자로 바꾸기 preferences.rename_printable=출력 가능하게 바꾸기 preferences.rename_use_source_name_as_class_name_alias=소스 파일 이름을 클래스 이름 별칭으로 사용 +#preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number preferences.search_group_title=리소스 검색 #preferences.search_results_per_page=Results per page (0 - no limit) preferences.res_file_ext=파일 확장자 (예: .xml|.html) (* 은 전체를 의미) diff --git a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties index a205688befd..edc7e3f31b1 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties @@ -261,6 +261,7 @@ preferences.rename_case=Corrigir problemas de capitalização (case sensitivity) preferences.rename_valid=Deixá-las válidas preferences.rename_printable=Deixá-las imprimíveis (printable) preferences.rename_use_source_name_as_class_name_alias=Utilizar nome do arquivo como apelido da classe +#preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number preferences.search_group_title=Buscar recursos #preferences.search_results_per_page=Results per page (0 - no limit) preferences.res_file_ext=Extensões de arquivos (ex: .xml|.html), * significa todas diff --git a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties index e94bfe92d74..9ca7a45ff91 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties @@ -261,6 +261,7 @@ preferences.rename_case=И исправить проблемы именован preferences.rename_valid=И сделать их верными preferences.rename_printable=И сделать их доступными для печати preferences.rename_use_source_name_as_class_name_alias=Иcпользовать атрибут SOURCE +#preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number preferences.search_group_title=Поиск preferences.search_results_per_page=Результатов на страницу (0 - без лимита) preferences.res_file_ext=Расширения файлов ресурсов ('xml|html', * для всех) diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties index b826561ccc1..0e5f4bb7350 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties @@ -261,6 +261,7 @@ preferences.rename_case=标识符要能够区分大小写 preferences.rename_valid=标识符应该符合标准规范 preferences.rename_printable=标识符必须要能正常显示 preferences.rename_use_source_name_as_class_name_alias=使用资源名作为类的别名 +#preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number preferences.search_group_title=搜索资源 preferences.search_results_per_page=每页结果数(0 - 无限制) preferences.res_file_ext=文件扩展名(比如 .xml|.html),* 表示所有 diff --git a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties index c5c932fd0d5..41500ef2aaa 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties @@ -261,6 +261,7 @@ preferences.rename_case=以修復區分大小寫問題 preferences.rename_valid=以使其有效 preferences.rename_printable=以使其可列印 preferences.rename_use_source_name_as_class_name_alias=將原始檔案名稱作為類別別名 +#preferences.rename_source_name_repeat_limit=Allow using source name if it appears less than a limit number preferences.search_group_title=搜尋資源 preferences.search_results_per_page=每頁的搜尋結果數 (0 - 無限制) preferences.res_file_ext=副檔名 (e.g. .xml|.html), * 表示全部