diff --git a/.github/workflows/build-test.yml b/.github/workflows/build-test.yml index 137a44300..4863701a5 100644 --- a/.github/workflows/build-test.yml +++ b/.github/workflows/build-test.yml @@ -2,7 +2,7 @@ name: Build Test on: push: - branches: [ master, build-test ] + branches: [ master, stable, build-test ] pull_request: branches: [ master ] diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java index 4e38809b7..a678a40fa 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java @@ -292,6 +292,17 @@ public abstract class InsnArg extends Typed { return false; } + public boolean isSameVar(SSAVar ssaVar) { + if (ssaVar == null) { + return false; + } + if (isRegister()) { + SSAVar thisSsaVar = ((RegisterArg) this).getSVar(); + return Objects.equals(thisSsaVar, ssaVar); + } + return false; + } + public boolean isSameCodeVar(RegisterArg arg) { if (arg == null) { return false; diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/FixTypesVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/FixTypesVisitor.java index 5041be98e..551b42468 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/FixTypesVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/FixTypesVisitor.java @@ -23,6 +23,7 @@ import jadx.core.dex.instructions.ArithNode; import jadx.core.dex.instructions.ArithOp; import jadx.core.dex.instructions.IndexInsnNode; import jadx.core.dex.instructions.InsnType; +import jadx.core.dex.instructions.InvokeNode; import jadx.core.dex.instructions.PhiInsn; import jadx.core.dex.instructions.args.ArgType; import jadx.core.dex.instructions.args.InsnArg; @@ -32,6 +33,7 @@ import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.instructions.args.SSAVar; import jadx.core.dex.instructions.mods.TernaryInsn; import jadx.core.dex.nodes.BlockNode; +import jadx.core.dex.nodes.IMethodDetails; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.nodes.MethodNode; import jadx.core.dex.nodes.RootNode; @@ -70,6 +72,7 @@ public final class FixTypesVisitor extends AbstractVisitor { this.typeUpdate = root.getTypeUpdate(); this.typeInference.init(root); this.resolvers = Arrays.asList( + this::applyFieldType, this::tryRestoreTypeVarCasts, this::tryInsertCasts, this::tryDeduceTypes, @@ -292,6 +295,117 @@ public final class FixTypesVisitor extends AbstractVisitor { return false; } + /** + * Use type for var assigned from field (IGET or SGET). + * Insert additional casts at var use places. + */ + private Boolean applyFieldType(MethodNode mth) { + try { + boolean changed = false; + // will add new SSA vars, can't use for-each loop + List sVars = mth.getSVars(); + for (int i = 0, varsCount = sVars.size(); i < varsCount; i++) { + SSAVar ssaVar = sVars.get(i); + if (tryFieldTypeWithNewCasts(mth, ssaVar, true)) { + changed = true; + } + } + if (!changed) { + return false; + } + // rerun full type inference + InitCodeVariables.rerun(mth); + typeInference.initTypeBounds(mth); + typeInference.runTypePropagation(mth); + + // check if changed var types are fixed + boolean success = true; + for (SSAVar ssaVar : mth.getSVars()) { + if (tryFieldTypeWithNewCasts(mth, ssaVar, false)) { + success = false; + } + } + if (!success) { + typeInference.initTypeBounds(mth); + typeInference.runTypePropagation(mth); + mth.addWarnComment("Type inference incomplete: some casts might be missing"); + } + return success; + } catch (Exception e) { + mth.addWarnComment("Type inference fix 'apply assigned field type' failed", e); + return false; + } + } + + private boolean tryFieldTypeWithNewCasts(MethodNode mth, SSAVar ssaVar, boolean insertCasts) { + ArgType type = ssaVar.getTypeInfo().getType(); + if (type.isTypeKnown() || ssaVar.isTypeImmutable()) { + return false; + } + InsnNode assignInsn = ssaVar.getAssignInsn(); + if (assignInsn == null) { + return false; + } + InsnType insnType = assignInsn.getType(); + if (insnType != InsnType.IGET && insnType != InsnType.SGET) { + return false; + } + ArgType fieldType = assignInsn.getResult().getInitType(); + // field type should be used + if (insertCasts) { + // try to find a use place and insert cast + boolean inserted = false; + for (RegisterArg useArg : ssaVar.getUseList()) { + if (insertExplicitUseCast(mth, ssaVar, useArg, fieldType)) { + inserted = true; + } + } + return inserted; + } + // force field type, will make type inference incomplete, + // but it is better that completely unknown type + ssaVar.setType(fieldType); + return true; + } + + private boolean insertExplicitUseCast(MethodNode mth, SSAVar ssaVar, RegisterArg useArg, ArgType fieldType) { + InsnNode parentInsn = useArg.getParentInsn(); + if (!InsnUtils.isInsnType(parentInsn, InsnType.INVOKE)) { + return false; + } + InvokeNode invoke = (InvokeNode) parentInsn; + InsnArg instanceArg = invoke.getInstanceArg(); + if (instanceArg == null || !instanceArg.isSameVar(ssaVar)) { + return false; + } + IMethodDetails details = mth.root().getMethodUtils().getMethodDetails(invoke); + if (details == null) { + return false; + } + int newCasts = 0; + int k = -1; + for (InsnArg invArg : invoke.getArgList()) { + if (invArg == instanceArg) { + continue; + } + k++; + if (!invArg.isRegister()) { + continue; + } + ArgType detailsArg = details.getArgTypes().get(k); + ArgType invArgType = invArg.getType(); + ArgType resolvedType = mth.root().getTypeUtils().replaceClassGenerics(fieldType, invArgType, detailsArg); + if (resolvedType != null && !resolvedType.equals(invArgType)) { + IndexInsnNode castInsn = insertUseCast(mth, (RegisterArg) invArg, resolvedType); + if (castInsn != null) { + castInsn.add(AFlag.EXPLICIT_CAST); + newCasts++; + } + } + } + return newCasts > 0; + } + /** * Fix check casts to type var extend type: *
@@ -372,7 +486,9 @@ public final class FixTypesVisitor extends AbstractVisitor { && !boundType.equals(var.getTypeInfo().getType()) && boundType.containsTypeVariable() && !mth.root().getTypeUtils().containsUnknownTypeVar(mth, boundType)) { - if (insertAssignCast(mth, var, boundType)) { + IndexInsnNode castInsn = insertAssignCast(mth, var, boundType); + if (castInsn != null) { + castInsn.add(AFlag.SOFT_CAST); return 1; } return insertUseCasts(mth, var); @@ -388,58 +504,65 @@ public final class FixTypesVisitor extends AbstractVisitor { } int useCasts = 0; for (RegisterArg useReg : new ArrayList<>(useList)) { - if (insertSoftUseCast(mth, useReg)) { + IndexInsnNode castInsn = insertUseCast(mth, useReg, useReg.getInitType()); + if (castInsn != null) { + castInsn.add(AFlag.SOFT_CAST); useCasts++; } } return useCasts; } - private boolean insertAssignCast(MethodNode mth, SSAVar var, ArgType castType) { + private @Nullable IndexInsnNode insertAssignCast(MethodNode mth, SSAVar var, ArgType castType) { RegisterArg assignArg = var.getAssign(); InsnNode assignInsn = assignArg.getParentInsn(); if (assignInsn == null || assignInsn.getType() == InsnType.PHI) { - return false; + return null; } BlockNode assignBlock = BlockUtils.getBlockByInsn(mth, assignInsn); if (assignBlock == null) { - return false; + return null; } assignInsn.setResult(assignArg.duplicateWithNewSSAVar(mth)); - IndexInsnNode castInsn = makeSoftCastInsn(assignArg.duplicate(), assignInsn.getResult().duplicate(), castType); - return BlockUtils.insertAfterInsn(assignBlock, assignInsn, castInsn); + IndexInsnNode castInsn = makeCastInsn(assignArg.duplicate(), assignInsn.getResult().duplicate(), castType); + if (!BlockUtils.insertAfterInsn(assignBlock, assignInsn, castInsn)) { + return null; + } + return castInsn; } - private boolean insertSoftUseCast(MethodNode mth, RegisterArg useArg) { + private @Nullable IndexInsnNode insertUseCast(MethodNode mth, RegisterArg useArg, ArgType castType) { InsnNode useInsn = useArg.getParentInsn(); if (useInsn == null || useInsn.getType() == InsnType.PHI) { - return false; + return null; } if (useInsn.getType() == InsnType.IF && useInsn.getArg(1).isZeroConst()) { // cast isn't needed if compare with null - return false; + return null; } BlockNode useBlock = BlockUtils.getBlockByInsn(mth, useInsn); if (useBlock == null) { - return false; + return null; } - IndexInsnNode castInsn = makeSoftCastInsn( + IndexInsnNode castInsn = makeCastInsn( useArg.duplicateWithNewSSAVar(mth), useArg.duplicate(), - useArg.getInitType()); + castType); useInsn.replaceArg(useArg, castInsn.getResult().duplicate()); - boolean success = BlockUtils.insertBeforeInsn(useBlock, useInsn, castInsn); - if (Consts.DEBUG_TYPE_INFERENCE && success) { - LOG.info("Insert soft cast for {} before {} in {}", useArg, useInsn, useBlock); + boolean inserted = BlockUtils.insertBeforeInsn(useBlock, useInsn, castInsn); + if (!inserted) { + return null; } - return success; + if (Consts.DEBUG_TYPE_INFERENCE) { + LOG.info("Insert cast for {} before {} in {}", useArg, useInsn, useBlock); + } + return castInsn; } - private IndexInsnNode makeSoftCastInsn(RegisterArg result, RegisterArg arg, ArgType castType) { + private IndexInsnNode makeCastInsn(RegisterArg result, RegisterArg arg, ArgType castType) { IndexInsnNode castInsn = new IndexInsnNode(InsnType.CHECK_CAST, castType, 1); castInsn.setResult(result); castInsn.addArg(arg); - castInsn.add(AFlag.SOFT_CAST); castInsn.add(AFlag.SYNTHETIC); return castInsn; } diff --git a/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver26.java b/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver26.java new file mode 100644 index 000000000..0766f3d85 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/types/TestTypeResolver26.java @@ -0,0 +1,31 @@ +package jadx.tests.integration.types; + +import java.util.ArrayList; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.IntegrationTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestTypeResolver26 extends IntegrationTest { + + @SuppressWarnings({ "rawtypes", "unchecked", "checkstyle:IllegalType" }) + public static class TestCls { + final ArrayList target = new ArrayList<>(); + final ArrayList source = new ArrayList(); + + public void test() { + ((ArrayList) target).add(source.get(0)); // cast removed in bytecode + } + } + + @Test + public void test() { + noDebugInfo(); + assertThat(getClassNode(TestCls.class)) + .code() + .doesNotContain("type inference failed") + .containsOne("this.target.add((String) this.source.get(0));"); + } +} diff --git a/jadx-gui/src/main/java/jadx/gui/jobs/SilentTask.java b/jadx-gui/src/main/java/jadx/gui/jobs/SilentTask.java index 14d15b3d1..9a4110513 100644 --- a/jadx-gui/src/main/java/jadx/gui/jobs/SilentTask.java +++ b/jadx-gui/src/main/java/jadx/gui/jobs/SilentTask.java @@ -9,8 +9,8 @@ import jadx.core.utils.tasks.TaskExecutor; public class SilentTask extends CancelableBackgroundTask { private final Runnable task; - public SilentTask(Runnable task) { - this.task = task; + public SilentTask(Runnable backgroundTask) { + this.task = backgroundTask; } @Override diff --git a/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java b/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java index 911906a9b..5c61c59ef 100644 --- a/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java +++ b/jadx-gui/src/main/java/jadx/gui/settings/JadxProject.java @@ -61,10 +61,15 @@ public class JadxProject { private transient boolean initial = true; private transient boolean saved; - private ProjectData data = new ProjectData(); + private final ProjectData data; public JadxProject(MainWindow mainWindow) { + this(mainWindow, new ProjectData()); + } + + private JadxProject(MainWindow mainWindow, ProjectData projectData) { this.mainWindow = mainWindow; + this.data = Objects.requireNonNull(projectData); } public void fillJadxArgs(JadxArgs jadxArgs) { @@ -312,16 +317,11 @@ public class JadxProject { } public static JadxProject load(MainWindow mainWindow, Path path) { - try { - JadxProject project = new JadxProject(mainWindow); - project.data = loadProjectData(path); - project.saved = true; - project.setProjectPath(path); - return project; - } catch (Exception e) { - LOG.error("Error loading project", e); - return null; - } + ProjectData projectData = loadProjectData(path); + JadxProject project = new JadxProject(mainWindow, projectData); + project.saved = true; + project.setProjectPath(path); + return project; } public static ProjectData loadProjectData(Path path) { diff --git a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java index a6cc8ca62..cae2cf50e 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/MainWindow.java @@ -551,17 +551,8 @@ public class MainWindow extends JFrame { private void openProject(Path path, Runnable onFinish) { LOG.debug("Loading project: {}", path); - JadxProject jadxProject = JadxProject.load(this, path); - if (jadxProject == null) { - JOptionPane.showMessageDialog( - this, - NLS.str("msg.project_error"), - NLS.str("msg.project_error_title"), - JOptionPane.INFORMATION_MESSAGE); - jadxProject = new JadxProject(this); - } + project = JadxProject.load(this, path); settings.addRecentProject(path); - project = jadxProject; loadFiles(onFinish); } diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/ClassCodeContentPanel.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/ClassCodeContentPanel.java index 2dc9e5608..a717bd59c 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/ClassCodeContentPanel.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/ClassCodeContentPanel.java @@ -21,6 +21,7 @@ import jadx.gui.ui.codearea.mode.JCodeMode; import jadx.gui.ui.panel.IViewStateSupport; import jadx.gui.ui.tab.TabbedPane; import jadx.gui.utils.NLS; +import jadx.gui.utils.UiUtils; import static com.formdev.flatlaf.FlatClientProperties.TABBED_PANE_TRAILING_COMPONENT; @@ -41,6 +42,7 @@ public final class ClassCodeContentPanel extends AbstractCodeContentPanel implem private final transient JTabbedPane areaTabbedPane; private boolean splitView = false; + private final JCheckBox splitCheckboxNormal; public ClassCodeContentPanel(TabbedPane panel, JClass jCls) { super(panel, jCls); @@ -48,26 +50,31 @@ public final class ClassCodeContentPanel extends AbstractCodeContentPanel implem javaCodePanel = new CodePanel(new CodeArea(this, jCls)); smaliCodePanel = new CodePanel(new SmaliArea(this, jCls)); areaTabbedPane = buildTabbedPane(jCls, false); - addCustomControls(areaTabbedPane); + splitCheckboxNormal = addCustomControls(areaTabbedPane, false); - initView(); javaCodePanel.load(); + initView(false); } - private void initView() { + private void initView(boolean splitViewEnabled) { + splitView = splitViewEnabled; removeAll(); setLayout(new BorderLayout()); setBorder(new EmptyBorder(0, 0, 0, 0)); - if (splitView) { - JTabbedPane splitPaneView = buildTabbedPane(((JClass) node), true); + if (splitViewEnabled) { + JTabbedPane splitPaneView = buildTabbedPane((JClass) node, true); JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, areaTabbedPane, splitPaneView); add(splitPane); - splitPane.setDividerLocation(0.5); - splitPaneView.setSelectedIndex(1); + UiUtils.uiRun(() -> { + splitPane.setDividerLocation(0.5); + splitPaneView.setSelectedIndex(1); + }); } else { + splitCheckboxNormal.setSelected(false); add(areaTabbedPane); } - invalidate(); + revalidate(); + repaint(); } private JTabbedPane buildTabbedPane(JClass jCls, boolean split) { @@ -92,11 +99,13 @@ public final class ClassCodeContentPanel extends AbstractCodeContentPanel implem return areaTabbedPane; } - private void addCustomControls(JTabbedPane tabbedPane) { - JCheckBox splitCheckBox = new JCheckBox("Split view", splitView); + private JCheckBox addCustomControls(JTabbedPane tabbedPane, boolean splitCheckboxInitialState) { + JCheckBox splitCheckBox = new JCheckBox("Split view", splitCheckboxInitialState); splitCheckBox.addItemListener(e -> { - splitView = splitCheckBox.isSelected(); - this.initView(); + boolean newSplitView = splitCheckBox.isSelected(); + if (splitView != newSplitView) { + this.initView(newSplitView); + } }); JToolBar trailing = new JToolBar(); @@ -106,6 +115,7 @@ public final class ClassCodeContentPanel extends AbstractCodeContentPanel implem trailing.addSeparator(new Dimension(50, 1)); trailing.add(splitCheckBox); tabbedPane.putClientProperty(TABBED_PANE_TRAILING_COMPONENT, trailing); + return splitCheckBox; } private void execInBackground(Runnable runnable) { diff --git a/jadx-gui/src/main/java/jadx/gui/ui/codearea/JadxTokenMaker.java b/jadx-gui/src/main/java/jadx/gui/ui/codearea/JadxTokenMaker.java index b890544ad..475bc908b 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/codearea/JadxTokenMaker.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/codearea/JadxTokenMaker.java @@ -47,7 +47,7 @@ public final class JadxTokenMaker extends JavaTokenMaker { private void processTokens(Token tokens) { Token prev = null; Token current = tokens; - while (current != null) { + while (current != null && current.getType() != TokenTypes.NULL) { if (prev != null) { switch (current.getType()) { case TokenTypes.RESERVED_WORD: diff --git a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java index 6dff674b2..b9988f92f 100644 --- a/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java +++ b/jadx-gui/src/main/java/jadx/gui/ui/tab/TabbedPane.java @@ -221,6 +221,7 @@ public class TabbedPane extends JTabbedPane implements ITabStatesListener { } private @Nullable ContentPanel showCode(JumpPosition jumpPos) { + UiUtils.uiThreadGuard(); JNode jumpNode = jumpPos.getNode(); ContentPanel contentPanel = getTabByNode(jumpNode); if (contentPanel == null) { @@ -442,7 +443,9 @@ public class TabbedPane extends JTabbedPane implements ITabStatesListener { @Override public void onTabCodeJump(TabBlueprint blueprint, @Nullable JumpPosition prevPos, JumpPosition position) { // queue task to wait completion of loading tasks - mainWindow.getBackgroundExecutor().execute(new SilentTask(() -> showCode(position))); + mainWindow.getBackgroundExecutor().execute(new SilentTask(() -> { + UiUtils.uiRun(() -> showCode(position)); + })); } @Override diff --git a/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java b/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java index 8fd9f195b..56bd6d7e2 100644 --- a/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java +++ b/jadx-gui/src/main/java/jadx/gui/utils/UiUtils.java @@ -379,9 +379,12 @@ public class UiUtils { } public static void errorMessage(Component parent, String message) { + errorMessage(parent, NLS.str("message.errorTitle"), message); + } + + public static void errorMessage(Component parent, String title, String message) { LOG.error(message); - JOptionPane.showMessageDialog(parent, message, - NLS.str("message.errorTitle"), JOptionPane.ERROR_MESSAGE); + JOptionPane.showMessageDialog(parent, message, title, JOptionPane.ERROR_MESSAGE); } public static void copyToClipboard(String text) { 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 a07b42929..6474909e3 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_de_DE.properties @@ -346,8 +346,6 @@ msg.language_changed=Die neue Sprache wird beim nächsten Start der Anwendung an msg.warning_title=Warnung msg.common_mouse_shortcut=Dies ist eine häufig verwendete Taste. Möchtest du sie wirklich an eine Aktion binden? msg.duplicate_shortcut=Der Tastenkürzel %s ist bereits in der Aktion „%s“ aus der Kategorie „%s“ festgelegt, fortfahren? -msg.project_error_title=Fehler -msg.project_error=Projekt konnte nicht geladen werden msg.cmd_select_class_error=Klasse\n%s auswählen nicht möglich\nSie existiert nicht. msg.cant_add_comment=Kann hier keinen Kommentar hinzufügen #msg.non_displayable_chars=Some characters were found in code are not displayable by currently used font "%s". Show chars? 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 cd4ac9391..aea15722f 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_en_US.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_en_US.properties @@ -346,8 +346,6 @@ msg.language_changed=New language will be displayed the next time application st msg.warning_title=Warning msg.common_mouse_shortcut=This is a commonly used key, are you sure you would like to bind it to an action? msg.duplicate_shortcut=The shortcut %s is already set in action "%s" from category "%s", continue ? -msg.project_error_title=Error -msg.project_error=Project could not be loaded msg.cmd_select_class_error=Failed to select the class\n%s\nThe class does not exist. msg.cant_add_comment=Can't add comment here msg.non_displayable_chars=Some characters were found in code are not displayable by currently used font "%s". Show chars? 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 cddd03108..6150aface 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_es_ES.properties @@ -346,8 +346,6 @@ msg.language_changed=El nuevo idioma se mostrará la próxima vez que la aplicac #msg.warning_title=Warning #msg.common_mouse_shortcut=This is a commonly used key, are you sure you would like to bind it to an action? #msg.duplicate_shortcut=The shortcut %s is already set in action "%s" from category "%s", continue ? -#msg.project_error_title=Error -#msg.project_error=Project could not be loaded #msg.cmd_select_class_error=Failed to select the class\n%s\nThe class does not exist. #msg.cant_add_comment=Can't add comment here #msg.non_displayable_chars=Some characters were found in code are not displayable by currently used font "%s". Show chars? 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 23e7e1a18..b3adbefe0 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_id_ID.properties @@ -346,8 +346,6 @@ msg.language_changed=Bahasa baru akan ditampilkan saat aplikasi dimulai kembali. msg.warning_title=Peringatan msg.common_mouse_shortcut=Ini adalah tombol yang sering digunakan, apakah Anda yakin ingin mengaitkannya dengan tindakan? msg.duplicate_shortcut=Pintas %s sudah diatur pada tindakan "%s" dari kategori "%s", lanjutkan? -msg.project_error_title=Kesalahan -msg.project_error=Proyek tidak dapat dimuat msg.cmd_select_class_error=Gagal memilih kelas\n%s\nKelas tidak ada. msg.cant_add_comment=Tidak dapat menambahkan komentar di sini #msg.non_displayable_chars=Some characters were found in code are not displayable by currently used font "%s". Show chars? 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 01090790f..b4a542138 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ko_KR.properties @@ -346,8 +346,6 @@ msg.language_changed=다음에 응용 프로그램이 시작되면 새 언어가 #msg.warning_title=Warning #msg.common_mouse_shortcut=This is a commonly used key, are you sure you would like to bind it to an action? #msg.duplicate_shortcut=The shortcut %s is already set in action "%s" from category "%s", continue ? -msg.project_error_title=오류 -msg.project_error=프로젝트를 로드 할 수 없습니다. msg.cmd_select_class_error=클래스를 선택하지 못했습니다.\n%s\n클래스가 없습니다. msg.cant_add_comment=여기에 주석을 추가할수 없음 #msg.non_displayable_chars=Some characters were found in code are not displayable by currently used font "%s". Show chars? 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 c236657fb..83cbcb556 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_pt_BR.properties @@ -346,8 +346,6 @@ msg.language_changed=Novo idioma será mostrado na próxima inicialização. #msg.warning_title=Warning #msg.common_mouse_shortcut=This is a commonly used key, are you sure you would like to bind it to an action? #msg.duplicate_shortcut=The shortcut %s is already set in action "%s" from category "%s", continue ? -msg.project_error_title=Erro -msg.project_error=Projeto não pôde ser carregado msg.cmd_select_class_error=Falha ao selecionar classe\n%s\nA classe não existe. msg.cant_add_comment=Não é possível adicionar comentários aqui #msg.non_displayable_chars=Some characters were found in code are not displayable by currently used font "%s". Show chars? 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 3e2bf3403..5020031fa 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_ru_RU.properties @@ -346,8 +346,6 @@ msg.language_changed=Новый язык применится при следу msg.warning_title=Внимание msg.common_mouse_shortcut=Это часто распространенная комбинация, вы действительно хотите назначить ее? msg.duplicate_shortcut=Действие %s уже выполняет "%s" в категории "%s", продолжить? -msg.project_error_title=Ошибка -msg.project_error=Проект не может быть загружен msg.cmd_select_class_error=Ошибка выбора класса\n%s\nЭтот класс не существует. msg.cant_add_comment=Невозможно добавить комментарий сюда #msg.non_displayable_chars=Some characters were found in code are not displayable by currently used font "%s". Show chars? 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 a8e8c2f41..45f7d4f7a 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_CN.properties @@ -346,8 +346,6 @@ msg.language_changed=新的语言将在下次应用程序启动时显示。 msg.warning_title=警告 msg.common_mouse_shortcut=这是常用按键,您确定要绑定操作吗? msg.duplicate_shortcut=快捷键 %s 已设为操作 “%s”,位于群组 “%s”。确定要继续吗? -msg.project_error_title=错误 -msg.project_error=项目无法加载 msg.cmd_select_class_error=无法选择类\n%s\n该类不存在。 msg.cant_add_comment=无法在此添加注释 msg.non_displayable_chars=部分字符在当前使用的字体“%s”中无法显示,是否显示这些字符? 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 86bbd9e0f..d25dfb791 100644 --- a/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties +++ b/jadx-gui/src/main/resources/i18n/Messages_zh_TW.properties @@ -346,8 +346,6 @@ msg.language_changed=新語言將於下次應用程式啟動時套用。 msg.warning_title=警告 msg.common_mouse_shortcut=這是常用按鍵,您確定要綁定操作嗎? msg.duplicate_shortcut=快捷鍵 %s 已設為操作 "%s",位於群組 "%s"。確定要繼續嗎? -msg.project_error_title=錯誤 -msg.project_error=無法載入專案 msg.cmd_select_class_error=無法選擇類別\n%s\n類別不存在。 msg.cant_add_comment=無法在此新增註解 #msg.non_displayable_chars=Some characters were found in code are not displayable by currently used font "%s". Show chars?