From 0f47403d0220757fed189b76e2071e25b1025cb8 Mon Sep 17 00:00:00 2001 From: Runemoro Date: Wed, 3 Jun 2020 13:39:42 -0400 Subject: Split GUI code to separate module (#242) * Split into modules * Post merge compile fixes Co-authored-by: modmuss50 --- src/main/java/cuchaz/enigma/ClassProvider.java | 10 - src/main/java/cuchaz/enigma/CommandMain.java | 105 -- src/main/java/cuchaz/enigma/Constants.java | 20 - src/main/java/cuchaz/enigma/Enigma.java | 121 --- src/main/java/cuchaz/enigma/EnigmaProfile.java | 131 --- src/main/java/cuchaz/enigma/EnigmaProject.java | 276 ----- src/main/java/cuchaz/enigma/EnigmaServices.java | 20 - src/main/java/cuchaz/enigma/ExceptionIgnorer.java | 35 - src/main/java/cuchaz/enigma/Main.java | 116 --- src/main/java/cuchaz/enigma/ProgressListener.java | 19 - .../java/cuchaz/enigma/ProposingTranslator.java | 53 - src/main/java/cuchaz/enigma/analysis/Access.java | 43 - .../java/cuchaz/enigma/analysis/BuiltinPlugin.java | 157 --- .../java/cuchaz/enigma/analysis/ClassCache.java | 127 --- .../analysis/ClassImplementationsTreeNode.java | 72 -- .../enigma/analysis/ClassInheritanceTreeNode.java | 72 -- .../enigma/analysis/ClassReferenceTreeNode.java | 94 -- .../cuchaz/enigma/analysis/EntryReference.java | 140 --- .../enigma/analysis/FieldReferenceTreeNode.java | 83 -- .../enigma/analysis/IndexSimpleVerifier.java | 154 --- .../cuchaz/enigma/analysis/IndexTreeBuilder.java | 74 -- .../cuchaz/enigma/analysis/InterpreterPair.java | 131 --- .../analysis/MethodImplementationsTreeNode.java | 85 -- .../enigma/analysis/MethodInheritanceTreeNode.java | 95 -- .../enigma/analysis/MethodNodeWithAction.java | 19 - .../enigma/analysis/MethodReferenceTreeNode.java | 113 --- .../enigma/analysis/ReferenceTargetType.java | 74 -- .../cuchaz/enigma/analysis/ReferenceTreeNode.java | 20 - src/main/java/cuchaz/enigma/analysis/Token.java | 72 -- .../enigma/analysis/index/BridgeMethodIndex.java | 156 --- .../cuchaz/enigma/analysis/index/EntryIndex.java | 102 -- .../enigma/analysis/index/IndexClassVisitor.java | 40 - .../analysis/index/IndexReferenceVisitor.java | 180 ---- .../enigma/analysis/index/InheritanceIndex.java | 127 --- .../cuchaz/enigma/analysis/index/JarIndex.java | 171 ---- .../cuchaz/enigma/analysis/index/JarIndexer.java | 28 - .../analysis/index/PackageVisibilityIndex.java | 147 --- .../enigma/analysis/index/ReferenceIndex.java | 148 --- src/main/java/cuchaz/enigma/api/EnigmaPlugin.java | 5 - .../cuchaz/enigma/api/EnigmaPluginContext.java | 9 - .../cuchaz/enigma/api/service/EnigmaService.java | 4 - .../enigma/api/service/EnigmaServiceContext.java | 11 - .../enigma/api/service/EnigmaServiceFactory.java | 5 - .../enigma/api/service/EnigmaServiceType.java | 29 - .../enigma/api/service/JarIndexerService.java | 10 - .../enigma/api/service/NameProposalService.java | 12 - .../enigma/api/service/ObfuscationTestService.java | 9 - .../bytecode/translators/AsmObjectTranslator.java | 46 - .../translators/LocalVariableFixVisitor.java | 126 --- .../bytecode/translators/SourceFixVisitor.java | 39 - .../translators/TranslationAnnotationVisitor.java | 51 - .../translators/TranslationClassVisitor.java | 102 -- .../translators/TranslationFieldVisitor.java | 33 - .../translators/TranslationMethodVisitor.java | 145 --- .../translators/TranslationSignatureVisitor.java | 129 --- .../enigma/command/CheckMappingsCommand.java | 77 -- src/main/java/cuchaz/enigma/command/Command.java | 154 --- .../enigma/command/ComposeMappingsCommand.java | 41 - .../enigma/command/ConvertMappingsCommand.java | 39 - .../cuchaz/enigma/command/DecompileCommand.java | 54 - .../cuchaz/enigma/command/DeobfuscateCommand.java | 37 - .../enigma/command/InvertMappingsCommand.java | 40 - .../command/MapSpecializedMethodsCommand.java | 69 -- .../cuchaz/enigma/command/MappingCommandsUtil.java | 148 --- src/main/java/cuchaz/enigma/config/Config.java | 261 ----- src/main/java/cuchaz/enigma/config/Themes.java | 48 - src/main/java/cuchaz/enigma/gui/BrowserCaret.java | 28 - src/main/java/cuchaz/enigma/gui/ClassSelector.java | 532 ---------- src/main/java/cuchaz/enigma/gui/CodeReader.java | 73 -- .../java/cuchaz/enigma/gui/ConnectionState.java | 7 - .../cuchaz/enigma/gui/DecompiledClassSource.java | 159 --- .../cuchaz/enigma/gui/EnigmaQuickFindDialog.java | 90 -- .../java/cuchaz/enigma/gui/EnigmaSyntaxKit.java | 44 - src/main/java/cuchaz/enigma/gui/Gui.java | 1058 -------------------- src/main/java/cuchaz/enigma/gui/GuiController.java | 729 -------------- .../cuchaz/enigma/gui/MessageListCellRenderer.java | 24 - .../cuchaz/enigma/gui/MethodTreeCellRenderer.java | 42 - .../java/cuchaz/enigma/gui/QuickFindAction.java | 45 - src/main/java/cuchaz/enigma/gui/RefreshMode.java | 7 - .../java/cuchaz/enigma/gui/SourceRemapper.java | 64 -- .../cuchaz/enigma/gui/TokenListCellRenderer.java | 35 - .../java/cuchaz/enigma/gui/dialog/AboutDialog.java | 69 -- .../cuchaz/enigma/gui/dialog/ChangeDialog.java | 50 - .../enigma/gui/dialog/ConnectToServerDialog.java | 82 -- .../java/cuchaz/enigma/gui/dialog/CrashDialog.java | 105 -- .../enigma/gui/dialog/CreateServerDialog.java | 65 -- .../cuchaz/enigma/gui/dialog/JavadocDialog.java | 159 --- .../cuchaz/enigma/gui/dialog/ProgressDialog.java | 109 -- .../cuchaz/enigma/gui/dialog/SearchDialog.java | 261 ----- .../java/cuchaz/enigma/gui/dialog/StatsDialog.java | 82 -- .../enigma/gui/elements/CollapsibleTabbedPane.java | 40 - .../java/cuchaz/enigma/gui/elements/MenuBar.java | 386 ------- .../cuchaz/enigma/gui/elements/PopupMenuBar.java | 125 --- .../enigma/gui/filechooser/FileChooserAny.java | 10 - .../enigma/gui/filechooser/FileChooserFile.java | 8 - .../enigma/gui/filechooser/FileChooserFolder.java | 11 - .../enigma/gui/highlight/BoxHighlightPainter.java | 69 -- .../gui/highlight/SelectionHighlightPainter.java | 31 - .../enigma/gui/highlight/TokenHighlightType.java | 7 - .../enigma/gui/node/ClassSelectorClassNode.java | 72 -- .../enigma/gui/node/ClassSelectorPackageNode.java | 58 -- .../java/cuchaz/enigma/gui/panels/PanelDeobf.java | 26 - .../java/cuchaz/enigma/gui/panels/PanelEditor.java | 171 ---- .../cuchaz/enigma/gui/panels/PanelIdentifier.java | 32 - .../java/cuchaz/enigma/gui/panels/PanelObf.java | 37 - .../cuchaz/enigma/gui/stats/StatsGenerator.java | 197 ---- .../java/cuchaz/enigma/gui/stats/StatsMember.java | 8 - .../enigma/gui/util/AbstractListCellRenderer.java | 77 -- src/main/java/cuchaz/enigma/gui/util/History.java | 49 - .../enigma/gui/util/ScaleChangeListener.java | 8 - .../java/cuchaz/enigma/gui/util/ScaleUtil.java | 110 -- .../enigma/network/DedicatedEnigmaServer.java | 164 --- .../java/cuchaz/enigma/network/EnigmaClient.java | 85 -- .../java/cuchaz/enigma/network/EnigmaServer.java | 292 ------ .../enigma/network/IntegratedEnigmaServer.java | 16 - .../cuchaz/enigma/network/ServerPacketHandler.java | 22 - .../enigma/network/packet/ChangeDocsC2SPacket.java | 59 -- .../enigma/network/packet/ChangeDocsS2CPacket.java | 44 - .../network/packet/ConfirmChangeC2SPacket.java | 33 - .../enigma/network/packet/KickS2CPacket.java | 33 - .../enigma/network/packet/LoginC2SPacket.java | 75 -- .../network/packet/MarkDeobfuscatedC2SPacket.java | 48 - .../network/packet/MarkDeobfuscatedS2CPacket.java | 40 - .../enigma/network/packet/MessageC2SPacket.java | 39 - .../enigma/network/packet/MessageS2CPacket.java | 36 - .../java/cuchaz/enigma/network/packet/Packet.java | 15 - .../cuchaz/enigma/network/packet/PacketHelper.java | 135 --- .../enigma/network/packet/PacketRegistry.java | 64 -- .../network/packet/RemoveMappingC2SPacket.java | 55 - .../network/packet/RemoveMappingS2CPacket.java | 40 - .../enigma/network/packet/RenameC2SPacket.java | 64 -- .../enigma/network/packet/RenameS2CPacket.java | 48 - .../network/packet/SyncMappingsS2CPacket.java | 88 -- .../enigma/network/packet/UserListS2CPacket.java | 44 - src/main/java/cuchaz/enigma/source/Decompiler.java | 5 - .../cuchaz/enigma/source/DecompilerService.java | 11 - .../java/cuchaz/enigma/source/Decompilers.java | 9 - src/main/java/cuchaz/enigma/source/Source.java | 11 - .../java/cuchaz/enigma/source/SourceIndex.java | 174 ---- .../java/cuchaz/enigma/source/SourceSettings.java | 11 - .../cuchaz/enigma/source/cfr/CfrDecompiler.java | 108 -- .../java/cuchaz/enigma/source/cfr/CfrSource.java | 38 - .../cuchaz/enigma/source/cfr/EnigmaDumper.java | 433 -------- .../cuchaz/enigma/source/procyon/EntryParser.java | 49 - .../enigma/source/procyon/ProcyonDecompiler.java | 81 -- .../enigma/source/procyon/ProcyonSource.java | 49 - .../procyon/index/SourceIndexClassVisitor.java | 95 -- .../procyon/index/SourceIndexMethodVisitor.java | 218 ---- .../source/procyon/index/SourceIndexVisitor.java | 40 - .../enigma/source/procyon/index/TokenFactory.java | 46 - .../transformers/AddJavadocsAstTransform.java | 134 --- .../transformers/DropImportAstTransform.java | 33 - .../transformers/DropVarModifiersAstTransform.java | 37 - .../procyon/transformers/InvalidIdentifierFix.java | 29 - .../source/procyon/transformers/Java8Generics.java | 107 -- .../ObfuscatedEnumSwitchRewriterTransform.java | 414 -------- .../procyon/transformers/RemoveObjectCasts.java | 39 - .../source/procyon/transformers/VarargsFixer.java | 197 ---- .../typeloader/CachingClasspathTypeLoader.java | 33 - .../procyon/typeloader/CachingTypeLoader.java | 38 - .../typeloader/CompiledSourceTypeLoader.java | 140 --- .../procyon/typeloader/NoRetryMetadataSystem.java | 38 - .../procyon/typeloader/SynchronizedTypeLoader.java | 20 - .../enigma/throwables/IllegalNameException.java | 39 - .../cuchaz/enigma/throwables/MappingConflict.java | 7 - .../enigma/throwables/MappingParseException.java | 39 - .../enigma/translation/LocalNameGenerator.java | 44 - .../enigma/translation/MappingTranslator.java | 24 - .../enigma/translation/SignatureUpdater.java | 92 -- .../cuchaz/enigma/translation/Translatable.java | 9 - .../enigma/translation/TranslationDirection.java | 36 - .../java/cuchaz/enigma/translation/Translator.java | 61 -- .../cuchaz/enigma/translation/VoidTranslator.java | 10 - .../enigma/translation/mapping/AccessModifier.java | 25 - .../enigma/translation/mapping/EntryMap.java | 24 - .../enigma/translation/mapping/EntryMapping.java | 75 -- .../enigma/translation/mapping/EntryRemapper.java | 105 -- .../enigma/translation/mapping/EntryResolver.java | 41 - .../translation/mapping/IndexEntryResolver.java | 227 ----- .../enigma/translation/mapping/MappingDelta.java | 54 - .../translation/mapping/MappingFileNameFormat.java | 10 - .../enigma/translation/mapping/MappingPair.java | 32 - .../translation/mapping/MappingSaveParameters.java | 16 - .../translation/mapping/MappingValidator.java | 76 -- .../translation/mapping/MappingsChecker.java | 99 -- .../enigma/translation/mapping/NameValidator.java | 53 - .../translation/mapping/ResolutionStrategy.java | 6 - .../translation/mapping/VoidEntryResolver.java | 27 - .../translation/mapping/serde/EnigmaFormat.java | 9 - .../mapping/serde/EnigmaMappingsReader.java | 319 ------ .../mapping/serde/EnigmaMappingsWriter.java | 316 ------ .../translation/mapping/serde/MappingFormat.java | 59 -- .../translation/mapping/serde/MappingHelper.java | 51 - .../translation/mapping/serde/MappingsReader.java | 14 - .../translation/mapping/serde/MappingsWriter.java | 17 - .../mapping/serde/ProguardMappingsReader.java | 134 --- .../translation/mapping/serde/RawEntryMapping.java | 30 - .../mapping/serde/SrgMappingsWriter.java | 118 --- .../mapping/serde/TinyMappingsReader.java | 115 --- .../mapping/serde/TinyMappingsWriter.java | 148 --- .../translation/mapping/serde/TinyV2Reader.java | 295 ------ .../translation/mapping/serde/TinyV2Writer.java | 169 ---- .../mapping/tree/DeltaTrackingTree.java | 110 -- .../enigma/translation/mapping/tree/EntryTree.java | 26 - .../translation/mapping/tree/EntryTreeNode.java | 40 - .../translation/mapping/tree/HashEntryTree.java | 188 ---- .../translation/mapping/tree/HashTreeNode.java | 75 -- .../translation/representation/AccessFlags.java | 116 --- .../enigma/translation/representation/Lambda.java | 105 -- .../representation/MethodDescriptor.java | 132 --- .../translation/representation/Signature.java | 98 -- .../translation/representation/TypeDescriptor.java | 268 ----- .../representation/entry/ClassDefEntry.java | 93 -- .../representation/entry/ClassEntry.java | 214 ---- .../translation/representation/entry/DefEntry.java | 7 - .../translation/representation/entry/Entry.java | 107 -- .../representation/entry/FieldDefEntry.java | 71 -- .../representation/entry/FieldEntry.java | 96 -- .../entry/LocalVariableDefEntry.java | 51 - .../representation/entry/LocalVariableEntry.java | 93 -- .../representation/entry/MethodDefEntry.java | 71 -- .../representation/entry/MethodEntry.java | 105 -- .../representation/entry/ParentedEntry.java | 82 -- src/main/java/cuchaz/enigma/utils/I18n.java | 102 -- .../java/cuchaz/enigma/utils/LFPrintWriter.java | 16 - src/main/java/cuchaz/enigma/utils/Message.java | 392 -------- src/main/java/cuchaz/enigma/utils/Pair.java | 26 - .../java/cuchaz/enigma/utils/ReadableToken.java | 30 - src/main/java/cuchaz/enigma/utils/Utils.java | 179 ---- .../cuchaz/enigma/utils/search/SearchEntry.java | 17 - .../cuchaz/enigma/utils/search/SearchUtil.java | 268 ----- .../services/cuchaz.enigma.api.EnigmaPlugin | 1 - src/main/resources/about.html | 6 - src/main/resources/lang/en_us.json | 164 --- src/main/resources/lang/fr_fr.json | 164 --- src/main/resources/lang/zh_cn.json | 118 --- src/main/resources/profile.json | 20 - src/main/resources/stats.html | 34 - 238 files changed, 21700 deletions(-) delete mode 100644 src/main/java/cuchaz/enigma/ClassProvider.java delete mode 100644 src/main/java/cuchaz/enigma/CommandMain.java delete mode 100644 src/main/java/cuchaz/enigma/Constants.java delete mode 100644 src/main/java/cuchaz/enigma/Enigma.java delete mode 100644 src/main/java/cuchaz/enigma/EnigmaProfile.java delete mode 100644 src/main/java/cuchaz/enigma/EnigmaProject.java delete mode 100644 src/main/java/cuchaz/enigma/EnigmaServices.java delete mode 100644 src/main/java/cuchaz/enigma/ExceptionIgnorer.java delete mode 100644 src/main/java/cuchaz/enigma/Main.java delete mode 100644 src/main/java/cuchaz/enigma/ProgressListener.java delete mode 100644 src/main/java/cuchaz/enigma/ProposingTranslator.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/Access.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/ClassCache.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/ClassImplementationsTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/ClassInheritanceTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/EntryReference.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/FieldReferenceTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/IndexTreeBuilder.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/InterpreterPair.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/MethodNodeWithAction.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/MethodReferenceTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/ReferenceTargetType.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/ReferenceTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/Token.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/IndexClassVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/IndexReferenceVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/JarIndex.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/PackageVisibilityIndex.java delete mode 100644 src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java delete mode 100644 src/main/java/cuchaz/enigma/api/EnigmaPlugin.java delete mode 100644 src/main/java/cuchaz/enigma/api/EnigmaPluginContext.java delete mode 100644 src/main/java/cuchaz/enigma/api/service/EnigmaService.java delete mode 100644 src/main/java/cuchaz/enigma/api/service/EnigmaServiceContext.java delete mode 100644 src/main/java/cuchaz/enigma/api/service/EnigmaServiceFactory.java delete mode 100644 src/main/java/cuchaz/enigma/api/service/EnigmaServiceType.java delete mode 100644 src/main/java/cuchaz/enigma/api/service/JarIndexerService.java delete mode 100644 src/main/java/cuchaz/enigma/api/service/NameProposalService.java delete mode 100644 src/main/java/cuchaz/enigma/api/service/ObfuscationTestService.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/AsmObjectTranslator.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationFieldVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/bytecode/translators/TranslationSignatureVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java delete mode 100644 src/main/java/cuchaz/enigma/command/Command.java delete mode 100644 src/main/java/cuchaz/enigma/command/ComposeMappingsCommand.java delete mode 100644 src/main/java/cuchaz/enigma/command/ConvertMappingsCommand.java delete mode 100644 src/main/java/cuchaz/enigma/command/DecompileCommand.java delete mode 100644 src/main/java/cuchaz/enigma/command/DeobfuscateCommand.java delete mode 100644 src/main/java/cuchaz/enigma/command/InvertMappingsCommand.java delete mode 100644 src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java delete mode 100644 src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java delete mode 100644 src/main/java/cuchaz/enigma/config/Config.java delete mode 100644 src/main/java/cuchaz/enigma/config/Themes.java delete mode 100644 src/main/java/cuchaz/enigma/gui/BrowserCaret.java delete mode 100644 src/main/java/cuchaz/enigma/gui/ClassSelector.java delete mode 100644 src/main/java/cuchaz/enigma/gui/CodeReader.java delete mode 100644 src/main/java/cuchaz/enigma/gui/ConnectionState.java delete mode 100644 src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java delete mode 100644 src/main/java/cuchaz/enigma/gui/EnigmaQuickFindDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java delete mode 100644 src/main/java/cuchaz/enigma/gui/Gui.java delete mode 100644 src/main/java/cuchaz/enigma/gui/GuiController.java delete mode 100644 src/main/java/cuchaz/enigma/gui/MessageListCellRenderer.java delete mode 100644 src/main/java/cuchaz/enigma/gui/MethodTreeCellRenderer.java delete mode 100644 src/main/java/cuchaz/enigma/gui/QuickFindAction.java delete mode 100644 src/main/java/cuchaz/enigma/gui/RefreshMode.java delete mode 100644 src/main/java/cuchaz/enigma/gui/SourceRemapper.java delete mode 100644 src/main/java/cuchaz/enigma/gui/TokenListCellRenderer.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/ChangeDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/dialog/StatsDialog.java delete mode 100644 src/main/java/cuchaz/enigma/gui/elements/CollapsibleTabbedPane.java delete mode 100644 src/main/java/cuchaz/enigma/gui/elements/MenuBar.java delete mode 100644 src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java delete mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java delete mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java delete mode 100644 src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java delete mode 100644 src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java delete mode 100644 src/main/java/cuchaz/enigma/gui/highlight/SelectionHighlightPainter.java delete mode 100644 src/main/java/cuchaz/enigma/gui/highlight/TokenHighlightType.java delete mode 100644 src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java delete mode 100644 src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java delete mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java delete mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java delete mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java delete mode 100644 src/main/java/cuchaz/enigma/gui/panels/PanelObf.java delete mode 100644 src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java delete mode 100644 src/main/java/cuchaz/enigma/gui/stats/StatsMember.java delete mode 100644 src/main/java/cuchaz/enigma/gui/util/AbstractListCellRenderer.java delete mode 100644 src/main/java/cuchaz/enigma/gui/util/History.java delete mode 100644 src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java delete mode 100644 src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java delete mode 100644 src/main/java/cuchaz/enigma/network/DedicatedEnigmaServer.java delete mode 100644 src/main/java/cuchaz/enigma/network/EnigmaClient.java delete mode 100644 src/main/java/cuchaz/enigma/network/EnigmaServer.java delete mode 100644 src/main/java/cuchaz/enigma/network/IntegratedEnigmaServer.java delete mode 100644 src/main/java/cuchaz/enigma/network/ServerPacketHandler.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/ChangeDocsC2SPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/ChangeDocsS2CPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/ConfirmChangeC2SPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/KickS2CPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/LoginC2SPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedC2SPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedS2CPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/MessageC2SPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/MessageS2CPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/Packet.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/PacketHelper.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/RemoveMappingC2SPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/RemoveMappingS2CPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/RenameC2SPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/RenameS2CPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java delete mode 100644 src/main/java/cuchaz/enigma/network/packet/UserListS2CPacket.java delete mode 100644 src/main/java/cuchaz/enigma/source/Decompiler.java delete mode 100644 src/main/java/cuchaz/enigma/source/DecompilerService.java delete mode 100644 src/main/java/cuchaz/enigma/source/Decompilers.java delete mode 100644 src/main/java/cuchaz/enigma/source/Source.java delete mode 100644 src/main/java/cuchaz/enigma/source/SourceIndex.java delete mode 100644 src/main/java/cuchaz/enigma/source/SourceSettings.java delete mode 100644 src/main/java/cuchaz/enigma/source/cfr/CfrDecompiler.java delete mode 100644 src/main/java/cuchaz/enigma/source/cfr/CfrSource.java delete mode 100644 src/main/java/cuchaz/enigma/source/cfr/EnigmaDumper.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/EntryParser.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/ProcyonDecompiler.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/ProcyonSource.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexClassVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexMethodVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexVisitor.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/index/TokenFactory.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/AddJavadocsAstTransform.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/DropImportAstTransform.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/DropVarModifiersAstTransform.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/InvalidIdentifierFix.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/Java8Generics.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/ObfuscatedEnumSwitchRewriterTransform.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/RemoveObjectCasts.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/transformers/VarargsFixer.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingClasspathTypeLoader.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingTypeLoader.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/CompiledSourceTypeLoader.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/NoRetryMetadataSystem.java delete mode 100644 src/main/java/cuchaz/enigma/source/procyon/typeloader/SynchronizedTypeLoader.java delete mode 100644 src/main/java/cuchaz/enigma/throwables/IllegalNameException.java delete mode 100644 src/main/java/cuchaz/enigma/throwables/MappingConflict.java delete mode 100644 src/main/java/cuchaz/enigma/throwables/MappingParseException.java delete mode 100644 src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java delete mode 100644 src/main/java/cuchaz/enigma/translation/MappingTranslator.java delete mode 100644 src/main/java/cuchaz/enigma/translation/SignatureUpdater.java delete mode 100644 src/main/java/cuchaz/enigma/translation/Translatable.java delete mode 100644 src/main/java/cuchaz/enigma/translation/TranslationDirection.java delete mode 100644 src/main/java/cuchaz/enigma/translation/Translator.java delete mode 100644 src/main/java/cuchaz/enigma/translation/VoidTranslator.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/AccessModifier.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/EntryMap.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/EntryResolver.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/IndexEntryResolver.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/MappingFileNameFormat.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/MappingPair.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/MappingSaveParameters.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/MappingsChecker.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/NameValidator.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/ResolutionStrategy.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/VoidEntryResolver.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/ProguardMappingsReader.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsWriter.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java delete mode 100644 src/main/java/cuchaz/enigma/translation/mapping/tree/HashTreeNode.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/Lambda.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/MethodDescriptor.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/Signature.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/DefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java delete mode 100644 src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java delete mode 100644 src/main/java/cuchaz/enigma/utils/I18n.java delete mode 100644 src/main/java/cuchaz/enigma/utils/LFPrintWriter.java delete mode 100644 src/main/java/cuchaz/enigma/utils/Message.java delete mode 100644 src/main/java/cuchaz/enigma/utils/Pair.java delete mode 100644 src/main/java/cuchaz/enigma/utils/ReadableToken.java delete mode 100644 src/main/java/cuchaz/enigma/utils/Utils.java delete mode 100644 src/main/java/cuchaz/enigma/utils/search/SearchEntry.java delete mode 100644 src/main/java/cuchaz/enigma/utils/search/SearchUtil.java delete mode 100644 src/main/resources/META-INF/services/cuchaz.enigma.api.EnigmaPlugin delete mode 100644 src/main/resources/about.html delete mode 100644 src/main/resources/lang/en_us.json delete mode 100644 src/main/resources/lang/fr_fr.json delete mode 100644 src/main/resources/lang/zh_cn.json delete mode 100644 src/main/resources/profile.json delete mode 100644 src/main/resources/stats.html (limited to 'src/main') diff --git a/src/main/java/cuchaz/enigma/ClassProvider.java b/src/main/java/cuchaz/enigma/ClassProvider.java deleted file mode 100644 index 2b913792..00000000 --- a/src/main/java/cuchaz/enigma/ClassProvider.java +++ /dev/null @@ -1,10 +0,0 @@ -package cuchaz.enigma; - -import org.objectweb.asm.tree.ClassNode; - -import javax.annotation.Nullable; - -public interface ClassProvider { - @Nullable - ClassNode getClassNode(String name); -} diff --git a/src/main/java/cuchaz/enigma/CommandMain.java b/src/main/java/cuchaz/enigma/CommandMain.java deleted file mode 100644 index 93b013d5..00000000 --- a/src/main/java/cuchaz/enigma/CommandMain.java +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma; - -import cuchaz.enigma.command.*; - -import java.util.LinkedHashMap; -import java.util.Locale; -import java.util.Map; - -public class CommandMain { - - private static final Map COMMANDS = new LinkedHashMap<>(); - - public static void main(String... args) throws Exception { - try { - // process the command - if (args.length < 1) - throw new IllegalArgumentException("Requires a command"); - String command = args[0].toLowerCase(Locale.ROOT); - - Command cmd = COMMANDS.get(command); - if (cmd == null) - throw new IllegalArgumentException("Command not recognized: " + command); - - if (!cmd.isValidArgument(args.length - 1)) { - throw new CommandHelpException(cmd); - } - - String[] cmdArgs = new String[args.length - 1]; - System.arraycopy(args, 1, cmdArgs, 0, args.length - 1); - - try { - cmd.run(cmdArgs); - } catch (Exception ex) { - throw new CommandHelpException(cmd, ex); - } - } catch (CommandHelpException ex) { - System.err.println(ex.getMessage()); - System.out.println(String.format("%s - %s", Constants.NAME, Constants.VERSION)); - System.out.println("Command " + ex.command.name + " has encountered an error! Usage:"); - printHelp(ex.command); - System.exit(1); - } catch (IllegalArgumentException ex) { - System.err.println(ex.getMessage()); - printHelp(); - System.exit(1); - } - } - - private static void printHelp() { - System.out.println(String.format("%s - %s", Constants.NAME, Constants.VERSION)); - System.out.println("Usage:"); - System.out.println("\tjava -cp enigma.jar cuchaz.enigma.CommandMain "); - System.out.println("\twhere is one of:"); - - for (Command command : COMMANDS.values()) { - printHelp(command); - } - } - - private static void printHelp(Command command) { - System.out.println("\t\t" + command.name + " " + command.getUsage()); - } - - private static void register(Command command) { - Command old = COMMANDS.put(command.name, command); - if (old != null) { - System.err.println("Command " + old + " with name " + command.name + " has been substituted by " + command); - } - } - - static { - register(new DeobfuscateCommand()); - register(new DecompileCommand()); - register(new ConvertMappingsCommand()); - register(new ComposeMappingsCommand()); - register(new InvertMappingsCommand()); - register(new CheckMappingsCommand()); - register(new MapSpecializedMethodsCommand()); - } - - private static final class CommandHelpException extends IllegalArgumentException { - - final Command command; - - CommandHelpException(Command command) { - this.command = command; - } - - CommandHelpException(Command command, Throwable cause) { - super(cause); - this.command = command; - } - } -} diff --git a/src/main/java/cuchaz/enigma/Constants.java b/src/main/java/cuchaz/enigma/Constants.java deleted file mode 100644 index 577315ff..00000000 --- a/src/main/java/cuchaz/enigma/Constants.java +++ /dev/null @@ -1,20 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma; - -public class Constants { - public static final String NAME = "Enigma"; - public static final String VERSION = "@VERSION@/Fabric"; - public static final String URL = "https://fabricmc.net"; - public static final int MiB = 1024 * 1024; // 1 mebibyte - public static final int KiB = 1024; // 1 kebibyte -} diff --git a/src/main/java/cuchaz/enigma/Enigma.java b/src/main/java/cuchaz/enigma/Enigma.java deleted file mode 100644 index f5f06491..00000000 --- a/src/main/java/cuchaz/enigma/Enigma.java +++ /dev/null @@ -1,121 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableListMultimap; -import cuchaz.enigma.analysis.ClassCache; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.api.EnigmaPlugin; -import cuchaz.enigma.api.EnigmaPluginContext; -import cuchaz.enigma.api.service.EnigmaService; -import cuchaz.enigma.api.service.EnigmaServiceFactory; -import cuchaz.enigma.api.service.EnigmaServiceType; -import cuchaz.enigma.api.service.JarIndexerService; -import cuchaz.enigma.utils.Utils; - -import java.io.IOException; -import java.nio.file.Path; -import java.util.List; -import java.util.ServiceLoader; - -public class Enigma { - private final EnigmaProfile profile; - private final EnigmaServices services; - - private Enigma(EnigmaProfile profile, EnigmaServices services) { - this.profile = profile; - this.services = services; - } - - public static Enigma create() { - return new Builder().build(); - } - - public static Builder builder() { - return new Builder(); - } - - public EnigmaProject openJar(Path path, ProgressListener progress) throws IOException { - ClassCache classCache = ClassCache.of(path); - JarIndex jarIndex = classCache.index(progress); - - services.get(JarIndexerService.TYPE).forEach(indexer -> indexer.acceptJar(classCache, jarIndex)); - - return new EnigmaProject(this, classCache, jarIndex, Utils.zipSha1(path)); - } - - public EnigmaProfile getProfile() { - return profile; - } - - public EnigmaServices getServices() { - return services; - } - - public static class Builder { - private EnigmaProfile profile = EnigmaProfile.EMPTY; - private Iterable plugins = ServiceLoader.load(EnigmaPlugin.class); - - private Builder() { - } - - public Builder setProfile(EnigmaProfile profile) { - Preconditions.checkNotNull(profile, "profile cannot be null"); - this.profile = profile; - return this; - } - - public Builder setPlugins(Iterable plugins) { - Preconditions.checkNotNull(plugins, "plugins cannot be null"); - this.plugins = plugins; - return this; - } - - public Enigma build() { - PluginContext pluginContext = new PluginContext(profile); - for (EnigmaPlugin plugin : plugins) { - plugin.init(pluginContext); - } - - EnigmaServices services = pluginContext.buildServices(); - return new Enigma(profile, services); - } - } - - private static class PluginContext implements EnigmaPluginContext { - private final EnigmaProfile profile; - - private final ImmutableListMultimap.Builder, EnigmaService> services = ImmutableListMultimap.builder(); - - PluginContext(EnigmaProfile profile) { - this.profile = profile; - } - - @Override - public void registerService(String id, EnigmaServiceType serviceType, EnigmaServiceFactory factory) { - List serviceProfiles = profile.getServiceProfiles(serviceType); - - for (EnigmaProfile.Service serviceProfile : serviceProfiles) { - if (serviceProfile.matches(id)) { - T service = factory.create(serviceProfile::getArgument); - services.put(serviceType, service); - break; - } - } - } - - EnigmaServices buildServices() { - return new EnigmaServices(services.build()); - } - } -} diff --git a/src/main/java/cuchaz/enigma/EnigmaProfile.java b/src/main/java/cuchaz/enigma/EnigmaProfile.java deleted file mode 100644 index 09b90f5f..00000000 --- a/src/main/java/cuchaz/enigma/EnigmaProfile.java +++ /dev/null @@ -1,131 +0,0 @@ -package cuchaz.enigma; - -import com.google.common.collect.ImmutableMap; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import com.google.gson.JsonDeserializationContext; -import com.google.gson.JsonDeserializer; -import com.google.gson.JsonElement; -import com.google.gson.JsonObject; -import com.google.gson.JsonParseException; -import com.google.gson.annotations.SerializedName; -import com.google.gson.reflect.TypeToken; -import cuchaz.enigma.api.service.EnigmaServiceType; -import cuchaz.enigma.translation.mapping.MappingFileNameFormat; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; - -import javax.annotation.Nullable; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.lang.reflect.Type; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -public final class EnigmaProfile { - public static final EnigmaProfile EMPTY = new EnigmaProfile(new ServiceContainer(ImmutableMap.of())); - - private static final MappingSaveParameters DEFAULT_MAPPING_SAVE_PARAMETERS = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); - private static final Gson GSON = new GsonBuilder() - .registerTypeAdapter(ServiceContainer.class, (JsonDeserializer) EnigmaProfile::loadServiceContainer) - .create(); - private static final Type SERVICE_LIST_TYPE = new TypeToken>() { - }.getType(); - - @SerializedName("services") - private final ServiceContainer serviceProfiles; - - @SerializedName("mapping_save_parameters") - private final MappingSaveParameters mappingSaveParameters = null; - - private EnigmaProfile(ServiceContainer serviceProfiles) { - this.serviceProfiles = serviceProfiles; - } - - public static EnigmaProfile read(@Nullable Path file) throws IOException { - if (file != null) { - try (BufferedReader reader = Files.newBufferedReader(file)) { - return EnigmaProfile.parse(reader); - } - } else { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream("/profile.json"), StandardCharsets.UTF_8))) { - return EnigmaProfile.parse(reader); - } catch (IOException ex) { - System.err.println("Failed to load default profile, will use empty profile: " + ex.getMessage()); - return EnigmaProfile.EMPTY; - } - } - } - - public static EnigmaProfile parse(Reader reader) { - return GSON.fromJson(reader, EnigmaProfile.class); - } - - private static ServiceContainer loadServiceContainer(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - if (!json.isJsonObject()) { - throw new JsonParseException("services must be an Object!"); - } - - JsonObject object = json.getAsJsonObject(); - - ImmutableMap.Builder> builder = ImmutableMap.builder(); - - for (Map.Entry entry : object.entrySet()) { - JsonElement value = entry.getValue(); - if (value.isJsonObject()) { - builder.put(entry.getKey(), Collections.singletonList(GSON.fromJson(value, Service.class))); - } else if (value.isJsonArray()) { - builder.put(entry.getKey(), GSON.fromJson(value, SERVICE_LIST_TYPE)); - } else { - throw new JsonParseException(String.format("Don't know how to convert %s to a list of service!", value)); - } - } - - return new ServiceContainer(builder.build()); - } - - public List getServiceProfiles(EnigmaServiceType serviceType) { - return serviceProfiles.get(serviceType.key); - } - - public MappingSaveParameters getMappingSaveParameters() { - //noinspection ConstantConditions - return mappingSaveParameters == null ? EnigmaProfile.DEFAULT_MAPPING_SAVE_PARAMETERS : mappingSaveParameters; - } - - public static class Service { - private final String id; - private final Map args; - - Service(String id, Map args) { - this.id = id; - this.args = args; - } - - public boolean matches(String id) { - return this.id.equals(id); - } - - public Optional getArgument(String key) { - return args != null ? Optional.ofNullable(args.get(key)) : Optional.empty(); - } - } - - static final class ServiceContainer { - private final Map> services; - - ServiceContainer(Map> services) { - this.services = services; - } - - List get(String key) { - return services.getOrDefault(key, Collections.emptyList()); - } - } -} diff --git a/src/main/java/cuchaz/enigma/EnigmaProject.java b/src/main/java/cuchaz/enigma/EnigmaProject.java deleted file mode 100644 index b345fb39..00000000 --- a/src/main/java/cuchaz/enigma/EnigmaProject.java +++ /dev/null @@ -1,276 +0,0 @@ -package cuchaz.enigma; - -import com.google.common.base.Functions; -import com.google.common.base.Preconditions; -import cuchaz.enigma.analysis.ClassCache; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.bytecode.translators.SourceFixVisitor; -import cuchaz.enigma.bytecode.translators.TranslationClassVisitor; -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.source.*; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.*; -import cuchaz.enigma.translation.mapping.tree.DeltaTrackingTree; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.I18n; - -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.ClassNode; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Collection; -import java.util.Map; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.jar.JarEntry; -import java.util.jar.JarOutputStream; -import java.util.stream.Collectors; - -public class EnigmaProject { - private final Enigma enigma; - - private final ClassCache classCache; - private final JarIndex jarIndex; - private final byte[] jarChecksum; - - private EntryRemapper mapper; - - public EnigmaProject(Enigma enigma, ClassCache classCache, JarIndex jarIndex, byte[] jarChecksum) { - Preconditions.checkArgument(jarChecksum.length == EnigmaServer.CHECKSUM_SIZE); - this.enigma = enigma; - this.classCache = classCache; - this.jarIndex = jarIndex; - this.jarChecksum = jarChecksum; - - this.mapper = EntryRemapper.empty(jarIndex); - } - - public void setMappings(EntryTree mappings) { - if (mappings != null) { - mapper = EntryRemapper.mapped(jarIndex, mappings); - } else { - mapper = EntryRemapper.empty(jarIndex); - } - } - - public Enigma getEnigma() { - return enigma; - } - - public ClassCache getClassCache() { - return classCache; - } - - public JarIndex getJarIndex() { - return jarIndex; - } - - public byte[] getJarChecksum() { - return jarChecksum; - } - - public EntryRemapper getMapper() { - return mapper; - } - - public void dropMappings(ProgressListener progress) { - DeltaTrackingTree mappings = mapper.getObfToDeobf(); - - Collection> dropped = dropMappings(mappings, progress); - for (Entry entry : dropped) { - mappings.trackChange(entry); - } - } - - private Collection> dropMappings(EntryTree mappings, ProgressListener progress) { - // drop mappings that don't match the jar - MappingsChecker checker = new MappingsChecker(jarIndex, mappings); - MappingsChecker.Dropped dropped = checker.dropBrokenMappings(progress); - - Map, String> droppedMappings = dropped.getDroppedMappings(); - for (Map.Entry, String> mapping : droppedMappings.entrySet()) { - System.out.println("WARNING: Couldn't find " + mapping.getKey() + " (" + mapping.getValue() + ") in jar. Mapping was dropped."); - } - - return droppedMappings.keySet(); - } - - public boolean isRenamable(Entry obfEntry) { - if (obfEntry instanceof MethodEntry) { - // HACKHACK: Object methods are not obfuscated identifiers - MethodEntry obfMethodEntry = (MethodEntry) obfEntry; - String name = obfMethodEntry.getName(); - String sig = obfMethodEntry.getDesc().toString(); - if (name.equals("clone") && sig.equals("()Ljava/lang/Object;")) { - return false; - } else if (name.equals("equals") && sig.equals("(Ljava/lang/Object;)Z")) { - return false; - } else if (name.equals("finalize") && sig.equals("()V")) { - return false; - } else if (name.equals("getClass") && sig.equals("()Ljava/lang/Class;")) { - return false; - } else if (name.equals("hashCode") && sig.equals("()I")) { - return false; - } else if (name.equals("notify") && sig.equals("()V")) { - return false; - } else if (name.equals("notifyAll") && sig.equals("()V")) { - return false; - } else if (name.equals("toString") && sig.equals("()Ljava/lang/String;")) { - return false; - } else if (name.equals("wait") && sig.equals("()V")) { - return false; - } else if (name.equals("wait") && sig.equals("(J)V")) { - return false; - } else if (name.equals("wait") && sig.equals("(JI)V")) { - return false; - } - } else if (obfEntry instanceof LocalVariableEntry && !((LocalVariableEntry) obfEntry).isArgument()) { - return false; - } - - return this.jarIndex.getEntryIndex().hasEntry(obfEntry); - } - - public boolean isRenamable(EntryReference, Entry> obfReference) { - return obfReference.isNamed() && isRenamable(obfReference.getNameableEntry()); - } - - public JarExport exportRemappedJar(ProgressListener progress) { - Collection classEntries = jarIndex.getEntryIndex().getClasses(); - - NameProposalService[] nameProposalServices = getEnigma().getServices().get(NameProposalService.TYPE).toArray(new NameProposalService[0]); - Translator deobfuscator = nameProposalServices.length == 0 ? mapper.getDeobfuscator() : new ProposingTranslator(mapper, nameProposalServices); - - AtomicInteger count = new AtomicInteger(); - progress.init(classEntries.size(), I18n.translate("progress.classes.deobfuscating")); - - Map compiled = classEntries.parallelStream() - .map(entry -> { - ClassEntry translatedEntry = deobfuscator.translate(entry); - progress.step(count.getAndIncrement(), translatedEntry.toString()); - - ClassNode node = classCache.getClassNode(entry.getFullName()); - if (node != null) { - ClassNode translatedNode = new ClassNode(); - node.accept(new TranslationClassVisitor(deobfuscator, Utils.ASM_VERSION, new SourceFixVisitor(Utils.ASM_VERSION, translatedNode, jarIndex))); - return translatedNode; - } - - return null; - }) - .filter(Objects::nonNull) - .collect(Collectors.toMap(n -> n.name, Functions.identity())); - - return new JarExport(jarIndex, compiled); - } - - public static final class JarExport { - private final JarIndex jarIndex; - private final Map compiled; - - JarExport(JarIndex jarIndex, Map compiled) { - this.jarIndex = jarIndex; - this.compiled = compiled; - } - - public void write(Path path, ProgressListener progress) throws IOException { - progress.init(this.compiled.size(), I18n.translate("progress.jar.writing")); - - try (JarOutputStream out = new JarOutputStream(Files.newOutputStream(path))) { - AtomicInteger count = new AtomicInteger(); - - for (ClassNode node : this.compiled.values()) { - progress.step(count.getAndIncrement(), node.name); - - String entryName = node.name.replace('.', '/') + ".class"; - - ClassWriter writer = new ClassWriter(0); - node.accept(writer); - - out.putNextEntry(new JarEntry(entryName)); - out.write(writer.toByteArray()); - out.closeEntry(); - } - } - } - - public SourceExport decompile(ProgressListener progress, DecompilerService decompilerService) { - Collection classes = this.compiled.values().stream() - .filter(classNode -> classNode.name.indexOf('$') == -1) - .collect(Collectors.toList()); - - progress.init(classes.size(), I18n.translate("progress.classes.decompiling")); - - //create a common instance outside the loop as mappings shouldn't be changing while this is happening - Decompiler decompiler = decompilerService.create(compiled::get, new SourceSettings(false, false)); - - AtomicInteger count = new AtomicInteger(); - - Collection decompiled = classes.parallelStream() - .map(translatedNode -> { - progress.step(count.getAndIncrement(), translatedNode.name); - - String source = decompileClass(translatedNode, decompiler); - return new ClassSource(translatedNode.name, source); - }) - .collect(Collectors.toList()); - - return new SourceExport(decompiled); - } - - private String decompileClass(ClassNode translatedNode, Decompiler decompiler) { - return decompiler.getSource(translatedNode.name).asString(); - } - } - - public static final class SourceExport { - private final Collection decompiled; - - SourceExport(Collection decompiled) { - this.decompiled = decompiled; - } - - public void write(Path path, ProgressListener progress) throws IOException { - progress.init(decompiled.size(), I18n.translate("progress.sources.writing")); - - int count = 0; - for (ClassSource source : decompiled) { - progress.step(count++, source.name); - - Path sourcePath = source.resolvePath(path); - source.writeTo(sourcePath); - } - } - } - - private static class ClassSource { - private final String name; - private final String source; - - ClassSource(String name, String source) { - this.name = name; - this.source = source; - } - - void writeTo(Path path) throws IOException { - Files.createDirectories(path.getParent()); - try (BufferedWriter writer = Files.newBufferedWriter(path)) { - writer.write(source); - } - } - - Path resolvePath(Path root) { - return root.resolve(name.replace('.', '/') + ".java"); - } - } -} diff --git a/src/main/java/cuchaz/enigma/EnigmaServices.java b/src/main/java/cuchaz/enigma/EnigmaServices.java deleted file mode 100644 index df3b7bba..00000000 --- a/src/main/java/cuchaz/enigma/EnigmaServices.java +++ /dev/null @@ -1,20 +0,0 @@ -package cuchaz.enigma; - -import com.google.common.collect.ImmutableListMultimap; -import cuchaz.enigma.api.service.EnigmaService; -import cuchaz.enigma.api.service.EnigmaServiceType; - -import java.util.List; - -public final class EnigmaServices { - private final ImmutableListMultimap, EnigmaService> services; - - EnigmaServices(ImmutableListMultimap, EnigmaService> services) { - this.services = services; - } - - @SuppressWarnings("unchecked") - public List get(EnigmaServiceType type) { - return (List) services.get(type); - } -} diff --git a/src/main/java/cuchaz/enigma/ExceptionIgnorer.java b/src/main/java/cuchaz/enigma/ExceptionIgnorer.java deleted file mode 100644 index 84331cc1..00000000 --- a/src/main/java/cuchaz/enigma/ExceptionIgnorer.java +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma; - -public class ExceptionIgnorer { - - public static boolean shouldIgnore(Throwable t) { - - // is this that pesky concurrent access bug in the highlight painter system? - // (ancient ui code is ancient) - if (t instanceof ArrayIndexOutOfBoundsException) { - StackTraceElement[] stackTrace = t.getStackTrace(); - if (stackTrace.length > 1) { - - // does this stack frame match javax.swing.text.DefaultHighlighter.paint*() ? - StackTraceElement frame = stackTrace[1]; - if (frame.getClassName().equals("javax.swing.text.DefaultHighlighter") && frame.getMethodName().startsWith("paint")) { - return true; - } - } - } - - return false; - } - -} diff --git a/src/main/java/cuchaz/enigma/Main.java b/src/main/java/cuchaz/enigma/Main.java deleted file mode 100644 index 7c87669f..00000000 --- a/src/main/java/cuchaz/enigma/Main.java +++ /dev/null @@ -1,116 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; - -import joptsimple.*; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import com.google.common.io.MoreFiles; - -public class Main { - - public static void main(String[] args) throws IOException { - OptionParser parser = new OptionParser(); - - OptionSpec jar = parser.accepts("jar", "Jar file to open at startup") - .withRequiredArg() - .withValuesConvertedBy(PathConverter.INSTANCE); - - OptionSpec mappings = parser.accepts("mappings", "Mappings file to open at startup") - .withRequiredArg() - .withValuesConvertedBy(PathConverter.INSTANCE); - - OptionSpec profile = parser.accepts("profile", "Profile json to apply at startup") - .withRequiredArg() - .withValuesConvertedBy(PathConverter.INSTANCE); - - parser.accepts("help", "Displays help information"); - - try { - OptionSet options = parser.parse(args); - - if (options.has("help")) { - parser.printHelpOn(System.out); - return; - } - - EnigmaProfile parsedProfile = EnigmaProfile.read(options.valueOf(profile)); - - Gui gui = new Gui(parsedProfile); - GuiController controller = gui.getController(); - - if (options.has(jar)) { - Path jarPath = options.valueOf(jar); - controller.openJar(jarPath) - .whenComplete((v, t) -> { - if (options.has(mappings)) { - Path mappingsPath = options.valueOf(mappings); - if (Files.isDirectory(mappingsPath)) { - controller.openMappings(MappingFormat.ENIGMA_DIRECTORY, mappingsPath); - } else if ("zip".equalsIgnoreCase(MoreFiles.getFileExtension(mappingsPath))) { - controller.openMappings(MappingFormat.ENIGMA_ZIP, mappingsPath); - } else { - controller.openMappings(MappingFormat.ENIGMA_FILE, mappingsPath); - } - } - }); - } - } catch (OptionException e) { - System.out.println("Invalid arguments: " + e.getMessage()); - System.out.println(); - parser.printHelpOn(System.out); - } - } - - public static class PathConverter implements ValueConverter { - public static final ValueConverter INSTANCE = new PathConverter(); - - PathConverter() { - } - - @Override - public Path convert(String path) { - // expand ~ to the home dir - if (path.startsWith("~")) { - // get the home dir - Path dirHome = Paths.get(System.getProperty("user.home")); - - // is the path just ~/ or is it ~user/ ? - if (path.startsWith("~/")) { - return dirHome.resolve(path.substring(2)); - } else { - return dirHome.getParent().resolve(path.substring(1)); - } - } - - return Paths.get(path); - } - - @Override - public Class valueType() { - return Path.class; - } - - @Override - public String valuePattern() { - return "path"; - } - } -} diff --git a/src/main/java/cuchaz/enigma/ProgressListener.java b/src/main/java/cuchaz/enigma/ProgressListener.java deleted file mode 100644 index 6da3b81a..00000000 --- a/src/main/java/cuchaz/enigma/ProgressListener.java +++ /dev/null @@ -1,19 +0,0 @@ -package cuchaz.enigma; - -public interface ProgressListener { - static ProgressListener none() { - return new ProgressListener() { - @Override - public void init(int totalWork, String title) { - } - - @Override - public void step(int numDone, String message) { - } - }; - } - - void init(int totalWork, String title); - - void step(int numDone, String message); -} diff --git a/src/main/java/cuchaz/enigma/ProposingTranslator.java b/src/main/java/cuchaz/enigma/ProposingTranslator.java deleted file mode 100644 index 018fbfda..00000000 --- a/src/main/java/cuchaz/enigma/ProposingTranslator.java +++ /dev/null @@ -1,53 +0,0 @@ -package cuchaz.enigma; - -import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.util.Arrays; -import java.util.Optional; - -public class ProposingTranslator implements Translator { - private final EntryRemapper mapper; - private final NameProposalService[] nameProposalServices; - - public ProposingTranslator(EntryRemapper mapper, NameProposalService[] nameProposalServices) { - this.mapper = mapper; - this.nameProposalServices = nameProposalServices; - } - - @Override - @SuppressWarnings("unchecked") - public T translate(T translatable) { - if (translatable == null) { - return null; - } - - T deobfuscated = mapper.deobfuscate(translatable); - - if (translatable instanceof Entry && ((Entry) deobfuscated).getName().equals(((Entry) translatable).getName())) { - return mapper.getObfResolver() - .resolveEntry((Entry) translatable, ResolutionStrategy.RESOLVE_ROOT) - .stream() - .map(this::proposeName) - .filter(Optional::isPresent) - .map(Optional::get) - .findFirst() - .map(newName -> (T) ((Entry) deobfuscated).withName(newName)) - .orElse(deobfuscated); - } - - return deobfuscated; - } - - private Optional proposeName(Entry entry) { - return Arrays.stream(nameProposalServices) - .map(service -> service.proposeName(entry, mapper)) - .filter(Optional::isPresent) - .map(Optional::get) - .findFirst(); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/Access.java b/src/main/java/cuchaz/enigma/analysis/Access.java deleted file mode 100644 index 82ca6692..00000000 --- a/src/main/java/cuchaz/enigma/analysis/Access.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import cuchaz.enigma.translation.representation.AccessFlags; - -import java.lang.reflect.Modifier; - -public enum Access { - - PUBLIC, PROTECTED, PACKAGE, PRIVATE; - - public static Access get(AccessFlags flags) { - return get(flags.getFlags()); - } - - public static Access get(int modifiers) { - boolean isPublic = Modifier.isPublic(modifiers); - boolean isProtected = Modifier.isProtected(modifiers); - boolean isPrivate = Modifier.isPrivate(modifiers); - - if (isPublic && !isProtected && !isPrivate) { - return PUBLIC; - } else if (!isPublic && isProtected && !isPrivate) { - return PROTECTED; - } else if (!isPublic && !isProtected && isPrivate) { - return PRIVATE; - } else if (!isPublic && !isProtected && !isPrivate) { - return PACKAGE; - } - // assume public by default - return PUBLIC; - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java b/src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java deleted file mode 100644 index dc3f5535..00000000 --- a/src/main/java/cuchaz/enigma/analysis/BuiltinPlugin.java +++ /dev/null @@ -1,157 +0,0 @@ -package cuchaz.enigma.analysis; - -import cuchaz.enigma.api.EnigmaPlugin; -import cuchaz.enigma.api.EnigmaPluginContext; -import cuchaz.enigma.api.service.JarIndexerService; -import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.source.DecompilerService; -import cuchaz.enigma.source.Decompilers; -import cuchaz.enigma.source.procyon.ProcyonDecompiler; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.utils.Pair; -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.InsnList; -import org.objectweb.asm.tree.LdcInsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; -import org.objectweb.asm.tree.analysis.Analyzer; -import org.objectweb.asm.tree.analysis.Frame; -import org.objectweb.asm.tree.analysis.SourceInterpreter; -import org.objectweb.asm.tree.analysis.SourceValue; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Optional; -import java.util.Set; - -public final class BuiltinPlugin implements EnigmaPlugin { - - public BuiltinPlugin() { - } - - @Override - public void init(EnigmaPluginContext ctx) { - registerEnumNamingService(ctx); - registerDecompilerServices(ctx); - } - - private void registerEnumNamingService(EnigmaPluginContext ctx) { - final Map, String> names = new HashMap<>(); - final EnumFieldNameFindingVisitor visitor = new EnumFieldNameFindingVisitor(names); - - ctx.registerService("enigma:enum_initializer_indexer", JarIndexerService.TYPE, ctx1 -> (classCache, jarIndex) -> classCache.visit(() -> visitor, ClassReader.SKIP_FRAMES)); - ctx.registerService("enigma:enum_name_proposer", NameProposalService.TYPE, ctx1 -> (obfEntry, remapper) -> Optional.ofNullable(names.get(obfEntry))); - } - - private void registerDecompilerServices(EnigmaPluginContext ctx) { - ctx.registerService("enigma:procyon", DecompilerService.TYPE, ctx1 -> Decompilers.PROCYON); - ctx.registerService("enigma:cfr", DecompilerService.TYPE, ctx1 -> Decompilers.CFR); - } - - private static final class EnumFieldNameFindingVisitor extends ClassVisitor { - - private ClassEntry clazz; - private String className; - private final Map, String> mappings; - private final Set> enumFields = new HashSet<>(); - private final List classInits = new ArrayList<>(); - - EnumFieldNameFindingVisitor(Map, String> mappings) { - super(Utils.ASM_VERSION); - this.mappings = mappings; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - super.visit(version, access, name, signature, superName, interfaces); - this.className = name; - this.clazz = new ClassEntry(name); - this.enumFields.clear(); - this.classInits.clear(); - } - - @Override - public FieldVisitor visitField(int access, String name, String descriptor, String signature, Object value) { - if ((access & Opcodes.ACC_ENUM) != 0) { - if (!enumFields.add(new Pair<>(name, descriptor))) { - throw new IllegalArgumentException("Found two enum fields with the same name \"" + name + "\" and desc \"" + descriptor + "\"!"); - } - } - return super.visitField(access, name, descriptor, signature, value); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - if ("".equals(name)) { - MethodNode node = new MethodNode(api, access, name, descriptor, signature, exceptions); - classInits.add(node); - return node; - } - return super.visitMethod(access, name, descriptor, signature, exceptions); - } - - @Override - public void visitEnd() { - super.visitEnd(); - try { - collectResults(); - } catch (Exception ex) { - throw new RuntimeException(ex); - } - } - - private void collectResults() throws Exception { - String owner = className; - Analyzer analyzer = new Analyzer<>(new SourceInterpreter()); - - for (MethodNode mn : classInits) { - Frame[] frames = analyzer.analyze(className, mn); - - InsnList instrs = mn.instructions; - for (int i = 1; i < instrs.size(); i++) { - AbstractInsnNode instr1 = instrs.get(i - 1); - AbstractInsnNode instr2 = instrs.get(i); - String s = null; - - if (instr2.getOpcode() == Opcodes.PUTSTATIC - && ((FieldInsnNode) instr2).owner.equals(owner) - && enumFields.contains(new Pair<>(((FieldInsnNode) instr2).name, ((FieldInsnNode) instr2).desc)) - && instr1.getOpcode() == Opcodes.INVOKESPECIAL - && "".equals(((MethodInsnNode) instr1).name)) { - - for (int j = 0; j < frames[i - 1].getStackSize(); j++) { - SourceValue sv = frames[i - 1].getStack(j); - for (AbstractInsnNode ci : sv.insns) { - if (ci instanceof LdcInsnNode && ((LdcInsnNode) ci).cst instanceof String) { - //if (s == null || !s.equals(((LdcInsnNode) ci).cst)) { - if (s == null) { - s = (String) (((LdcInsnNode) ci).cst); - // stringsFound++; - } - } - } - } - } - - if (s != null) { - mappings.put(new FieldEntry(clazz, ((FieldInsnNode) instr2).name, new TypeDescriptor(((FieldInsnNode) instr2).desc)), s); - } - // report otherwise? - } - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/ClassCache.java b/src/main/java/cuchaz/enigma/analysis/ClassCache.java deleted file mode 100644 index f694bf35..00000000 --- a/src/main/java/cuchaz/enigma/analysis/ClassCache.java +++ /dev/null @@ -1,127 +0,0 @@ -package cuchaz.enigma.analysis; - -import com.google.common.cache.Cache; -import com.google.common.cache.CacheBuilder; -import com.google.common.collect.ImmutableSet; -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.bytecode.translators.LocalVariableFixVisitor; -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.ClassNode; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.TimeUnit; -import java.util.function.Supplier; - -public final class ClassCache implements AutoCloseable, ClassProvider { - private final FileSystem fileSystem; - private final ImmutableSet classNames; - - private final Cache nodeCache = CacheBuilder.newBuilder() - .maximumSize(128) - .expireAfterAccess(1, TimeUnit.MINUTES) - .build(); - - private ClassCache(FileSystem fileSystem, ImmutableSet classNames) { - this.fileSystem = fileSystem; - this.classNames = classNames; - } - - public static ClassCache of(Path jarPath) throws IOException { - FileSystem fileSystem = FileSystems.newFileSystem(jarPath, (ClassLoader) null); - ImmutableSet classNames = collectClassNames(fileSystem); - - return new ClassCache(fileSystem, classNames); - } - - private static ImmutableSet collectClassNames(FileSystem fileSystem) throws IOException { - ImmutableSet.Builder classNames = ImmutableSet.builder(); - for (Path root : fileSystem.getRootDirectories()) { - Files.walk(root).map(Path::toString) - .forEach(path -> { - if (path.endsWith(".class")) { - String name = path.substring(1, path.length() - ".class".length()); - classNames.add(name); - } - }); - } - - return classNames.build(); - } - - @Nullable - @Override - public ClassNode getClassNode(String name) { - if (!classNames.contains(name)) { - return null; - } - - try { - return nodeCache.get(name, () -> parseNode(name)); - } catch (ExecutionException e) { - throw new RuntimeException(e); - } - } - - private ClassNode parseNode(String name) throws IOException { - ClassReader reader = getReader(name); - - ClassNode node = new ClassNode(); - - LocalVariableFixVisitor visitor = new LocalVariableFixVisitor(Utils.ASM_VERSION, node); - reader.accept(visitor, 0); - - return node; - } - - private ClassReader getReader(String name) throws IOException { - Path path = fileSystem.getPath(name + ".class"); - byte[] bytes = Files.readAllBytes(path); - return new ClassReader(bytes); - } - - public int getClassCount() { - return classNames.size(); - } - - public void visit(Supplier visitorSupplier, int readFlags) { - for (String className : classNames) { - ClassVisitor visitor = visitorSupplier.get(); - - ClassNode cached = nodeCache.getIfPresent(className); - if (cached != null) { - cached.accept(visitor); - continue; - } - - try { - ClassReader reader = getReader(className); - reader.accept(visitor, readFlags); - } catch (IOException e) { - System.out.println("Failed to visit class " + className); - e.printStackTrace(); - } - } - } - - @Override - public void close() throws IOException { - this.fileSystem.close(); - } - - public JarIndex index(ProgressListener progress) { - JarIndex index = JarIndex.empty(); - index.indexJar(this, progress); - return index; - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/ClassImplementationsTreeNode.java b/src/main/java/cuchaz/enigma/analysis/ClassImplementationsTreeNode.java deleted file mode 100644 index 0fc44ca6..00000000 --- a/src/main/java/cuchaz/enigma/analysis/ClassImplementationsTreeNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import com.google.common.collect.Lists; -import cuchaz.enigma.analysis.index.InheritanceIndex; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import javax.swing.tree.DefaultMutableTreeNode; -import java.util.Collection; -import java.util.List; - -public class ClassImplementationsTreeNode extends DefaultMutableTreeNode { - private final Translator translator; - private final ClassEntry entry; - - public ClassImplementationsTreeNode(Translator translator, ClassEntry entry) { - this.translator = translator; - this.entry = entry; - } - - public static ClassImplementationsTreeNode findNode(ClassImplementationsTreeNode node, MethodEntry entry) { - // is this the node? - if (node.entry.equals(entry.getParent())) { - return node; - } - - // recurse - for (int i = 0; i < node.getChildCount(); i++) { - ClassImplementationsTreeNode foundNode = findNode((ClassImplementationsTreeNode) node.getChildAt(i), entry); - if (foundNode != null) { - return foundNode; - } - } - return null; - } - - public ClassEntry getClassEntry() { - return this.entry; - } - - @Override - public String toString() { - return translator.translate(entry).toString(); - } - - public void load(JarIndex index) { - // get all method implementations - List nodes = Lists.newArrayList(); - InheritanceIndex inheritanceIndex = index.getInheritanceIndex(); - - Collection inheritors = inheritanceIndex.getChildren(entry); - for (ClassEntry inheritor : inheritors) { - nodes.add(new ClassImplementationsTreeNode(translator, inheritor)); - } - - // add them to this node - nodes.forEach(this::add); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/ClassInheritanceTreeNode.java b/src/main/java/cuchaz/enigma/analysis/ClassInheritanceTreeNode.java deleted file mode 100644 index 7904c5f0..00000000 --- a/src/main/java/cuchaz/enigma/analysis/ClassInheritanceTreeNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import com.google.common.collect.Lists; -import cuchaz.enigma.analysis.index.InheritanceIndex; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -import javax.swing.tree.DefaultMutableTreeNode; -import java.util.List; - -public class ClassInheritanceTreeNode extends DefaultMutableTreeNode { - private final Translator translator; - private final ClassEntry obfClassEntry; - - public ClassInheritanceTreeNode(Translator translator, String obfClassName) { - this.translator = translator; - this.obfClassEntry = new ClassEntry(obfClassName); - } - - public static ClassInheritanceTreeNode findNode(ClassInheritanceTreeNode node, ClassEntry entry) { - // is this the node? - if (node.getObfClassName().equals(entry.getFullName())) { - return node; - } - - // recurse - for (int i = 0; i < node.getChildCount(); i++) { - ClassInheritanceTreeNode foundNode = findNode((ClassInheritanceTreeNode) node.getChildAt(i), entry); - if (foundNode != null) { - return foundNode; - } - } - return null; - } - - public String getObfClassName() { - return this.obfClassEntry.getFullName(); - } - - @Override - public String toString() { - return translator.translate(obfClassEntry).getFullName(); - } - - public void load(InheritanceIndex ancestries, boolean recurse) { - // get all the child nodes - List nodes = Lists.newArrayList(); - for (ClassEntry inheritor : ancestries.getChildren(this.obfClassEntry)) { - nodes.add(new ClassInheritanceTreeNode(translator, inheritor.getFullName())); - } - - // add them to this node - nodes.forEach(this::add); - - if (recurse) { - for (ClassInheritanceTreeNode node : nodes) { - node.load(ancestries, true); - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java b/src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java deleted file mode 100644 index 90d8a6cf..00000000 --- a/src/main/java/cuchaz/enigma/analysis/ClassReferenceTreeNode.java +++ /dev/null @@ -1,94 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import com.google.common.collect.Sets; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.analysis.index.ReferenceIndex; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; - -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreeNode; -import java.util.Set; - -public class ClassReferenceTreeNode extends DefaultMutableTreeNode - implements ReferenceTreeNode { - - private Translator deobfuscatingTranslator; - private ClassEntry entry; - private EntryReference reference; - - public ClassReferenceTreeNode(Translator deobfuscatingTranslator, ClassEntry entry) { - this.deobfuscatingTranslator = deobfuscatingTranslator; - this.entry = entry; - this.reference = null; - } - - public ClassReferenceTreeNode(Translator deobfuscatingTranslator, EntryReference reference) { - this.deobfuscatingTranslator = deobfuscatingTranslator; - this.entry = reference.entry; - this.reference = reference; - } - - @Override - public ClassEntry getEntry() { - return this.entry; - } - - @Override - public EntryReference getReference() { - return this.reference; - } - - @Override - public String toString() { - if (this.reference != null) { - return String.format("%s", this.deobfuscatingTranslator.translate(this.reference.context)); - } - return this.deobfuscatingTranslator.translate(this.entry).getFullName(); - } - - public void load(JarIndex index, boolean recurse) { - ReferenceIndex referenceIndex = index.getReferenceIndex(); - - // get all the child nodes - for (EntryReference reference : referenceIndex.getReferencesToClass(this.entry)) { - add(new ClassReferenceTreeNode(this.deobfuscatingTranslator, reference)); - } - - if (recurse && this.children != null) { - for (Object child : this.children) { - if (child instanceof ClassReferenceTreeNode) { - ClassReferenceTreeNode node = (ClassReferenceTreeNode) child; - - // don't recurse into ancestor - Set> ancestors = Sets.newHashSet(); - TreeNode n = node; - while (n.getParent() != null) { - n = n.getParent(); - if (n instanceof ClassReferenceTreeNode) { - ancestors.add(((ClassReferenceTreeNode) n).getEntry()); - } - } - if (ancestors.contains(node.getEntry())) { - continue; - } - - node.load(index, true); - } - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/EntryReference.java b/src/main/java/cuchaz/enigma/analysis/EntryReference.java deleted file mode 100644 index 2e738c01..00000000 --- a/src/main/java/cuchaz/enigma/analysis/EntryReference.java +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.Utils; - -import java.util.Arrays; -import java.util.List; - -public class EntryReference, C extends Entry> implements Translatable { - - private static final List CONSTRUCTOR_NON_NAMES = Arrays.asList("this", "super", "static"); - public E entry; - public C context; - public ReferenceTargetType targetType; - - private boolean sourceName; - - public EntryReference(E entry, String sourceName) { - this(entry, sourceName, null); - } - - public EntryReference(E entry, String sourceName, C context) { - this(entry, sourceName, context, ReferenceTargetType.none()); - } - - public EntryReference(E entry, String sourceName, C context, ReferenceTargetType targetType) { - if (entry == null) { - throw new IllegalArgumentException("Entry cannot be null!"); - } - - this.entry = entry; - this.context = context; - this.targetType = targetType; - - this.sourceName = sourceName != null && !sourceName.isEmpty(); - if (entry instanceof MethodEntry && ((MethodEntry) entry).isConstructor() && CONSTRUCTOR_NON_NAMES.contains(sourceName)) { - this.sourceName = false; - } - } - - public EntryReference(E entry, C context, EntryReference other) { - this.entry = entry; - this.context = context; - this.sourceName = other.sourceName; - this.targetType = other.targetType; - } - - public ClassEntry getLocationClassEntry() { - if (context != null) { - return context.getContainingClass(); - } - return entry.getContainingClass(); - } - - public boolean isNamed() { - return this.sourceName; - } - - public Entry getNameableEntry() { - if (entry instanceof MethodEntry && ((MethodEntry) entry).isConstructor()) { - // renaming a constructor really means renaming the class - return entry.getContainingClass(); - } - return entry; - } - - public String getNameableName() { - return getNameableEntry().getName(); - } - - @Override - public int hashCode() { - if (context != null) { - return Utils.combineHashesOrdered(entry.hashCode(), context.hashCode()); - } - return entry.hashCode(); - } - - @Override - public boolean equals(Object other) { - return other instanceof EntryReference && equals((EntryReference) other); - } - - public boolean equals(EntryReference other) { - // check entry first - boolean isEntrySame = entry.equals(other.entry); - if (!isEntrySame) { - return false; - } - - // check caller - if (context == null && other.context == null) { - return true; - } else if (context != null && other.context != null) { - return context.equals(other.context); - } - return false; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append(entry); - - if (context != null) { - buf.append(" called from "); - buf.append(context); - } - - if (targetType != null && targetType.getKind() != ReferenceTargetType.Kind.NONE) { - buf.append(" on target of type "); - buf.append(targetType); - } - - return buf.toString(); - } - - @Override - public Translatable translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - return new EntryReference<>(translator.translate(entry), translator.translate(context), this); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/FieldReferenceTreeNode.java b/src/main/java/cuchaz/enigma/analysis/FieldReferenceTreeNode.java deleted file mode 100644 index 4beab7f8..00000000 --- a/src/main/java/cuchaz/enigma/analysis/FieldReferenceTreeNode.java +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.analysis.index.ReferenceIndex; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import javax.swing.tree.DefaultMutableTreeNode; - -public class FieldReferenceTreeNode extends DefaultMutableTreeNode implements ReferenceTreeNode { - - private final Translator translator; - private FieldEntry entry; - private EntryReference reference; - - public FieldReferenceTreeNode(Translator translator, FieldEntry entry) { - this.translator = translator; - this.entry = entry; - this.reference = null; - } - - private FieldReferenceTreeNode(Translator translator, EntryReference reference) { - this.translator = translator; - this.entry = reference.entry; - this.reference = reference; - } - - @Override - public FieldEntry getEntry() { - return this.entry; - } - - @Override - public EntryReference getReference() { - return this.reference; - } - - @Override - public String toString() { - if (this.reference != null) { - return String.format("%s", translator.translate(this.reference.context)); - } - return translator.translate(entry).toString(); - } - - public void load(JarIndex index, boolean recurse) { - ReferenceIndex referenceIndex = index.getReferenceIndex(); - - // get all the child nodes - if (this.reference == null) { - for (EntryReference reference : referenceIndex.getReferencesToField(this.entry)) { - add(new FieldReferenceTreeNode(translator, reference)); - } - } else { - for (EntryReference reference : referenceIndex.getReferencesToMethod(this.reference.context)) { - add(new MethodReferenceTreeNode(translator, reference)); - } - } - - if (recurse && children != null) { - for (Object node : children) { - if (node instanceof MethodReferenceTreeNode) { - ((MethodReferenceTreeNode) node).load(index, true, false); - } else if (node instanceof FieldReferenceTreeNode) { - ((FieldReferenceTreeNode) node).load(index, true); - } - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java b/src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java deleted file mode 100644 index 80a71546..00000000 --- a/src/main/java/cuchaz/enigma/analysis/IndexSimpleVerifier.java +++ /dev/null @@ -1,154 +0,0 @@ -package cuchaz.enigma.analysis; - -import cuchaz.enigma.analysis.index.EntryIndex; -import cuchaz.enigma.analysis.index.InheritanceIndex; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.analysis.BasicValue; -import org.objectweb.asm.tree.analysis.SimpleVerifier; - -import java.util.Set; - -public class IndexSimpleVerifier extends SimpleVerifier { - private static final Type OBJECT_TYPE = Type.getType("Ljava/lang/Object;"); - private final EntryIndex entryIndex; - private final InheritanceIndex inheritanceIndex; - - public IndexSimpleVerifier(EntryIndex entryIndex, InheritanceIndex inheritanceIndex) { - super(Utils.ASM_VERSION, null, null, null, false); - this.entryIndex = entryIndex; - this.inheritanceIndex = inheritanceIndex; - } - - @Override - protected boolean isSubTypeOf(BasicValue value, BasicValue expected) { - Type expectedType = expected.getType(); - Type type = value.getType(); - switch (expectedType.getSort()) { - case Type.INT: - case Type.FLOAT: - case Type.LONG: - case Type.DOUBLE: - return type.equals(expectedType); - case Type.ARRAY: - case Type.OBJECT: - if (type.equals(NULL_TYPE)) { - return true; - } else if (type.getSort() == Type.OBJECT || type.getSort() == Type.ARRAY) { - if (isAssignableFrom(expectedType, type)) { - return true; - } else if (isInterface(expectedType)) { - return isAssignableFrom(OBJECT_TYPE, type); - } else { - return false; - } - } else { - return false; - } - default: - throw new AssertionError(); - } - } - - @Override - protected boolean isInterface(Type type) { - AccessFlags classAccess = entryIndex.getClassAccess(new ClassEntry(type.getInternalName())); - if (classAccess != null) { - return classAccess.isInterface(); - } - - Class clazz = getClass(type); - if (clazz != null) { - return clazz.isInterface(); - } - - return false; - } - - @Override - protected Type getSuperClass(Type type) { - ClassDefEntry definition = entryIndex.getDefinition(new ClassEntry(type.getInternalName())); - if (definition != null) { - return Type.getType('L' + definition.getSuperClass().getFullName() + ';'); - } - - Class clazz = getClass(type); - if (clazz != null) { - return Type.getType(clazz.getSuperclass()); - } - - return OBJECT_TYPE; - } - - @Override - protected boolean isAssignableFrom(Type type1, Type type2) { - if (type1.equals(type2)) { - return true; - } - - if (type2.equals(NULL_TYPE)) { - return true; - } - - if (type1.getSort() == Type.ARRAY) { - return type2.getSort() == Type.ARRAY && isAssignableFrom(Type.getType(type1.getDescriptor().substring(1)), Type.getType(type2.getDescriptor().substring(1))); - } - - if (type2.getSort() == Type.ARRAY) { - return type1.equals(OBJECT_TYPE); - } - - if (type1.getSort() == Type.OBJECT && type2.getSort() == Type.OBJECT) { - if (type1.equals(OBJECT_TYPE)) { - return true; - } - - ClassEntry class1 = new ClassEntry(type1.getInternalName()); - ClassEntry class2 = new ClassEntry(type2.getInternalName()); - - if (entryIndex.hasClass(class1) && entryIndex.hasClass(class2)) { - return inheritanceIndex.getAncestors(class2).contains(class1); - } - - Class class1Class = getClass(Type.getType('L' + class1.getFullName() + ';')); - Class class2Class = getClass(Type.getType('L' + class2.getFullName() + ';')); - - if (class1Class == null) { - return true; // missing classes to find out - } - - if (class2Class != null) { - return class1Class.isAssignableFrom(class2Class); - } - - if (entryIndex.hasClass(class2)) { - Set ancestors = inheritanceIndex.getAncestors(class2); - - for (ClassEntry ancestorEntry : ancestors) { - Class ancestor = getClass(Type.getType('L' + ancestorEntry.getFullName() + ';')); - if (ancestor == null || class1Class.isAssignableFrom(ancestor)) { - return true; // assignable, or missing classes to find out - } - } - - return false; - } - - return true; // missing classes to find out - } - - return false; - } - - @Override - protected final Class getClass(Type type) { - try { - return Class.forName(type.getSort() == Type.ARRAY ? type.getDescriptor().replace('/', '.') : type.getClassName(), false, null); - } catch (ClassNotFoundException e) { - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/IndexTreeBuilder.java b/src/main/java/cuchaz/enigma/analysis/IndexTreeBuilder.java deleted file mode 100644 index 0c2dfd77..00000000 --- a/src/main/java/cuchaz/enigma/analysis/IndexTreeBuilder.java +++ /dev/null @@ -1,74 +0,0 @@ -package cuchaz.enigma.analysis; - -import com.google.common.collect.Lists; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.util.Collection; -import java.util.List; - -public class IndexTreeBuilder { - private final JarIndex index; - - public IndexTreeBuilder(JarIndex index) { - this.index = index; - } - - public ClassInheritanceTreeNode buildClassInheritance(Translator translator, ClassEntry obfClassEntry) { - // get the root node - List ancestry = Lists.newArrayList(); - ancestry.add(obfClassEntry.getFullName()); - for (ClassEntry classEntry : index.getInheritanceIndex().getAncestors(obfClassEntry)) { - ancestry.add(classEntry.getFullName()); - } - - ClassInheritanceTreeNode rootNode = new ClassInheritanceTreeNode(translator, ancestry.get(ancestry.size() - 1)); - - // expand all children recursively - rootNode.load(index.getInheritanceIndex(), true); - - return rootNode; - } - - public ClassImplementationsTreeNode buildClassImplementations(Translator translator, ClassEntry obfClassEntry) { - if (index.getInheritanceIndex().isParent(obfClassEntry)) { - ClassImplementationsTreeNode node = new ClassImplementationsTreeNode(translator, obfClassEntry); - node.load(index); - return node; - } - return null; - } - - public MethodInheritanceTreeNode buildMethodInheritance(Translator translator, MethodEntry obfMethodEntry) { - MethodEntry resolvedEntry = index.getEntryResolver().resolveFirstEntry(obfMethodEntry, ResolutionStrategy.RESOLVE_ROOT); - - // make a root node at the base - MethodInheritanceTreeNode rootNode = new MethodInheritanceTreeNode( - translator, resolvedEntry, - index.getEntryIndex().hasMethod(resolvedEntry) - ); - - // expand the full tree - rootNode.load(index); - - return rootNode; - } - - public List buildMethodImplementations(Translator translator, MethodEntry obfMethodEntry) { - EntryResolver resolver = index.getEntryResolver(); - Collection resolvedEntries = resolver.resolveEntry(obfMethodEntry, ResolutionStrategy.RESOLVE_ROOT); - - List nodes = Lists.newArrayList(); - for (MethodEntry resolvedEntry : resolvedEntries) { - MethodImplementationsTreeNode node = new MethodImplementationsTreeNode(translator, resolvedEntry); - node.load(index); - nodes.add(node); - } - - return nodes; - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/InterpreterPair.java b/src/main/java/cuchaz/enigma/analysis/InterpreterPair.java deleted file mode 100644 index 8a1c2388..00000000 --- a/src/main/java/cuchaz/enigma/analysis/InterpreterPair.java +++ /dev/null @@ -1,131 +0,0 @@ -package cuchaz.enigma.analysis; - -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.Type; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.analysis.AnalyzerException; -import org.objectweb.asm.tree.analysis.Interpreter; -import org.objectweb.asm.tree.analysis.Value; - -import java.util.List; -import java.util.Objects; -import java.util.stream.Collectors; - -public class InterpreterPair extends Interpreter> { - private final Interpreter left; - private final Interpreter right; - - public InterpreterPair(Interpreter left, Interpreter right) { - super(Utils.ASM_VERSION); - this.left = left; - this.right = right; - } - - @Override - public PairValue newValue(Type type) { - return pair( - left.newValue(type), - right.newValue(type) - ); - } - - @Override - public PairValue newOperation(AbstractInsnNode insn) throws AnalyzerException { - return pair( - left.newOperation(insn), - right.newOperation(insn) - ); - } - - @Override - public PairValue copyOperation(AbstractInsnNode insn, PairValue value) throws AnalyzerException { - return pair( - left.copyOperation(insn, value.left), - right.copyOperation(insn, value.right) - ); - } - - @Override - public PairValue unaryOperation(AbstractInsnNode insn, PairValue value) throws AnalyzerException { - return pair( - left.unaryOperation(insn, value.left), - right.unaryOperation(insn, value.right) - ); - } - - @Override - public PairValue binaryOperation(AbstractInsnNode insn, PairValue value1, PairValue value2) throws AnalyzerException { - return pair( - left.binaryOperation(insn, value1.left, value2.left), - right.binaryOperation(insn, value1.right, value2.right) - ); - } - - @Override - public PairValue ternaryOperation(AbstractInsnNode insn, PairValue value1, PairValue value2, PairValue value3) throws AnalyzerException { - return pair( - left.ternaryOperation(insn, value1.left, value2.left, value3.left), - right.ternaryOperation(insn, value1.right, value2.right, value3.right) - ); - } - - @Override - public PairValue naryOperation(AbstractInsnNode insn, List> values) throws AnalyzerException { - return pair( - left.naryOperation(insn, values.stream().map(v -> v.left).collect(Collectors.toList())), - right.naryOperation(insn, values.stream().map(v -> v.right).collect(Collectors.toList())) - ); - } - - @Override - public void returnOperation(AbstractInsnNode insn, PairValue value, PairValue expected) throws AnalyzerException { - left.returnOperation(insn, value.left, expected.left); - right.returnOperation(insn, value.right, expected.right); - } - - @Override - public PairValue merge(PairValue value1, PairValue value2) { - return pair( - left.merge(value1.left, value2.left), - right.merge(value1.right, value2.right) - ); - } - - private PairValue pair(V left, W right) { - if (left == null && right == null) { - return null; - } - - return new PairValue<>(left, right); - } - - public static final class PairValue implements Value { - public final V left; - public final W right; - - public PairValue(V left, W right) { - if (left == null && right == null) { - throw new IllegalArgumentException("should use null rather than pair of nulls"); - } - - this.left = left; - this.right = right; - } - - @Override - public boolean equals(Object o) { - return o instanceof InterpreterPair.PairValue && Objects.equals(left, ((PairValue) o).left) && Objects.equals(right, ((PairValue) o).right); - } - - @Override - public int hashCode() { - return left.hashCode() * 31 + right.hashCode(); - } - - @Override - public int getSize() { - return (left == null ? right : left).getSize(); - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java b/src/main/java/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java deleted file mode 100644 index b09f7ac6..00000000 --- a/src/main/java/cuchaz/enigma/analysis/MethodImplementationsTreeNode.java +++ /dev/null @@ -1,85 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import com.google.common.collect.Lists; -import cuchaz.enigma.analysis.index.EntryIndex; -import cuchaz.enigma.analysis.index.InheritanceIndex; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import javax.swing.tree.DefaultMutableTreeNode; -import java.util.Collection; -import java.util.List; - -public class MethodImplementationsTreeNode extends DefaultMutableTreeNode { - - private final Translator translator; - private MethodEntry entry; - - public MethodImplementationsTreeNode(Translator translator, MethodEntry entry) { - this.translator = translator; - if (entry == null) { - throw new IllegalArgumentException("Entry cannot be null!"); - } - - this.entry = entry; - } - - public static MethodImplementationsTreeNode findNode(MethodImplementationsTreeNode node, MethodEntry entry) { - // is this the node? - if (node.getMethodEntry().equals(entry)) { - return node; - } - - // recurse - for (int i = 0; i < node.getChildCount(); i++) { - MethodImplementationsTreeNode foundNode = findNode((MethodImplementationsTreeNode) node.getChildAt(i), entry); - if (foundNode != null) { - return foundNode; - } - } - return null; - } - - public MethodEntry getMethodEntry() { - return this.entry; - } - - @Override - public String toString() { - MethodEntry translatedEntry = translator.translate(entry); - String className = translatedEntry.getParent().getFullName(); - String methodName = translatedEntry.getName(); - return className + "." + methodName + "()"; - } - - public void load(JarIndex index) { - // get all method implementations - List nodes = Lists.newArrayList(); - EntryIndex entryIndex = index.getEntryIndex(); - InheritanceIndex inheritanceIndex = index.getInheritanceIndex(); - - Collection descendants = inheritanceIndex.getDescendants(entry.getParent()); - for (ClassEntry inheritor : descendants) { - MethodEntry methodEntry = entry.withParent(inheritor); - if (entryIndex.hasMethod(methodEntry)) { - nodes.add(new MethodImplementationsTreeNode(translator, methodEntry)); - } - } - - // add them to this node - nodes.forEach(this::add); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java b/src/main/java/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java deleted file mode 100644 index e77b5cce..00000000 --- a/src/main/java/cuchaz/enigma/analysis/MethodInheritanceTreeNode.java +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import cuchaz.enigma.analysis.index.EntryIndex; -import cuchaz.enigma.analysis.index.InheritanceIndex; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import javax.swing.tree.DefaultMutableTreeNode; - -public class MethodInheritanceTreeNode extends DefaultMutableTreeNode { - - private final Translator translator; - private MethodEntry entry; - private boolean implemented; - - public MethodInheritanceTreeNode(Translator translator, MethodEntry entry, boolean implemented) { - this.translator = translator; - this.entry = entry; - this.implemented = implemented; - } - - public static MethodInheritanceTreeNode findNode(MethodInheritanceTreeNode node, MethodEntry entry) { - // is this the node? - if (node.getMethodEntry().equals(entry)) { - return node; - } - - // recurse - for (int i = 0; i < node.getChildCount(); i++) { - MethodInheritanceTreeNode foundNode = findNode((MethodInheritanceTreeNode) node.getChildAt(i), entry); - if (foundNode != null) { - return foundNode; - } - } - return null; - } - - public MethodEntry getMethodEntry() { - return this.entry; - } - - public boolean isImplemented() { - return this.implemented; - } - - @Override - public String toString() { - MethodEntry translatedEntry = translator.translate(entry); - String className = translatedEntry.getContainingClass().getFullName(); - - if (!this.implemented) { - return className; - } else { - String methodName = translatedEntry.getName(); - return className + "." + methodName + "()"; - } - } - - /** - * Returns true if there is sub-node worthy to display. - */ - public boolean load(JarIndex index) { - // get all the child nodes - EntryIndex entryIndex = index.getEntryIndex(); - InheritanceIndex inheritanceIndex = index.getInheritanceIndex(); - - boolean ret = false; - for (ClassEntry inheritorEntry : inheritanceIndex.getChildren(this.entry.getParent())) { - MethodEntry methodEntry = new MethodEntry(inheritorEntry, this.entry.getName(), this.entry.getDesc()); - - MethodInheritanceTreeNode node = new MethodInheritanceTreeNode(translator, methodEntry, entryIndex.hasMethod(methodEntry)); - boolean childOverride = node.load(index); - - if (childOverride || node.implemented) { - this.add(node); - ret = true; - } - } - - return ret; - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/MethodNodeWithAction.java b/src/main/java/cuchaz/enigma/analysis/MethodNodeWithAction.java deleted file mode 100644 index 81171038..00000000 --- a/src/main/java/cuchaz/enigma/analysis/MethodNodeWithAction.java +++ /dev/null @@ -1,19 +0,0 @@ -package cuchaz.enigma.analysis; - -import org.objectweb.asm.tree.MethodNode; - -import java.util.function.Consumer; - -public class MethodNodeWithAction extends MethodNode { - private final Consumer action; - - public MethodNodeWithAction(int api, int access, String name, String descriptor, String signature, String[] exceptions, Consumer action) { - super(api, access, name, descriptor, signature, exceptions); - this.action = action; - } - - @Override - public void visitEnd() { - action.accept(this); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/MethodReferenceTreeNode.java b/src/main/java/cuchaz/enigma/analysis/MethodReferenceTreeNode.java deleted file mode 100644 index 8995eb5c..00000000 --- a/src/main/java/cuchaz/enigma/analysis/MethodReferenceTreeNode.java +++ /dev/null @@ -1,113 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import com.google.common.collect.Sets; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.analysis.index.ReferenceIndex; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import javax.swing.tree.DefaultMutableTreeNode; -import javax.swing.tree.TreeNode; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Set; - -public class MethodReferenceTreeNode extends DefaultMutableTreeNode implements ReferenceTreeNode { - - private final Translator translator; - private MethodEntry entry; - private EntryReference reference; - - public MethodReferenceTreeNode(Translator translator, MethodEntry entry) { - this.translator = translator; - this.entry = entry; - this.reference = null; - } - - public MethodReferenceTreeNode(Translator translator, EntryReference reference) { - this.translator = translator; - this.entry = reference.entry; - this.reference = reference; - } - - @Override - public MethodEntry getEntry() { - return this.entry; - } - - @Override - public EntryReference getReference() { - return this.reference; - } - - @Override - public String toString() { - if (this.reference != null) { - return String.format("%s", translator.translate(this.reference.context)); - } - return translator.translate(this.entry).getName(); - } - - public void load(JarIndex index, boolean recurse, boolean recurseMethod) { - // get all the child nodes - Collection> references = getReferences(index, recurseMethod); - - for (EntryReference reference : references) { - add(new MethodReferenceTreeNode(translator, reference)); - } - - if (recurse && this.children != null) { - for (Object child : this.children) { - if (child instanceof MethodReferenceTreeNode) { - MethodReferenceTreeNode node = (MethodReferenceTreeNode) child; - - // don't recurse into ancestor - Set> ancestors = Sets.newHashSet(); - TreeNode n = node; - while (n.getParent() != null) { - n = n.getParent(); - if (n instanceof MethodReferenceTreeNode) { - ancestors.add(((MethodReferenceTreeNode) n).getEntry()); - } - } - if (ancestors.contains(node.getEntry())) { - continue; - } - - node.load(index, true, false); - } - } - } - } - - private Collection> getReferences(JarIndex index, boolean recurseMethod) { - ReferenceIndex referenceIndex = index.getReferenceIndex(); - - if (recurseMethod) { - Collection> references = new ArrayList<>(); - - EntryResolver entryResolver = index.getEntryResolver(); - for (MethodEntry methodEntry : entryResolver.resolveEquivalentMethods(entry)) { - references.addAll(referenceIndex.getReferencesToMethod(methodEntry)); - } - - return references; - } else { - return referenceIndex.getReferencesToMethod(entry); - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/ReferenceTargetType.java b/src/main/java/cuchaz/enigma/analysis/ReferenceTargetType.java deleted file mode 100644 index 5b19d189..00000000 --- a/src/main/java/cuchaz/enigma/analysis/ReferenceTargetType.java +++ /dev/null @@ -1,74 +0,0 @@ -package cuchaz.enigma.analysis; - -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -public abstract class ReferenceTargetType { - private static final None NONE = new None(); - private static final Uninitialized UNINITIALIZED = new Uninitialized(); - - public abstract Kind getKind(); - - public static None none() { - return NONE; - } - - public static Uninitialized uninitialized() { - return UNINITIALIZED; - } - - public static ClassType classType(ClassEntry name) { - return new ClassType(name); - } - - public enum Kind { - NONE, - UNINITIALIZED, - CLASS_TYPE - } - - public static class None extends ReferenceTargetType { - @Override - public Kind getKind() { - return Kind.NONE; - } - - @Override - public String toString() { - return "(none)"; - } - } - - public static class Uninitialized extends ReferenceTargetType { - @Override - public Kind getKind() { - return Kind.UNINITIALIZED; - } - - @Override - public String toString() { - return "(uninitialized)"; - } - } - - public static class ClassType extends ReferenceTargetType { - private final ClassEntry entry; - - private ClassType(ClassEntry entry) { - this.entry = entry; - } - - public ClassEntry getEntry() { - return entry; - } - - @Override - public Kind getKind() { - return Kind.CLASS_TYPE; - } - - @Override - public String toString() { - return entry.toString(); - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/ReferenceTreeNode.java b/src/main/java/cuchaz/enigma/analysis/ReferenceTreeNode.java deleted file mode 100644 index c0a3a754..00000000 --- a/src/main/java/cuchaz/enigma/analysis/ReferenceTreeNode.java +++ /dev/null @@ -1,20 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -import cuchaz.enigma.translation.representation.entry.Entry; - -public interface ReferenceTreeNode, C extends Entry> { - E getEntry(); - - EntryReference getReference(); -} diff --git a/src/main/java/cuchaz/enigma/analysis/Token.java b/src/main/java/cuchaz/enigma/analysis/Token.java deleted file mode 100644 index f0155e56..00000000 --- a/src/main/java/cuchaz/enigma/analysis/Token.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis; - -public class Token implements Comparable { - - public int start; - public int end; - public String text; - - public Token(int start, int end, String text) { - this.start = start; - this.end = end; - this.text = text; - } - - public int getRenameOffset(String to) { - int length = this.end - this.start; - return to.length() - length; - } - - public void rename(StringBuffer source, String to) { - int oldEnd = this.end; - this.text = to; - this.end = this.start + to.length(); - - source.replace(start, oldEnd, to); - } - - public Token move(int offset) { - Token token = new Token(this.start + offset, this.end + offset, null); - token.text = text; - return token; - } - - public boolean contains(int pos) { - return pos >= start && pos <= end; - } - - @Override - public int compareTo(Token other) { - return start - other.start; - } - - @Override - public boolean equals(Object other) { - return other instanceof Token && equals((Token) other); - } - - @Override - public int hashCode() { - return start * 37 + end; - } - - public boolean equals(Token other) { - return start == other.start && end == other.end && text.equals(other.text); - } - - @Override - public String toString() { - return String.format("[%d,%d]", start, end); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java b/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java deleted file mode 100644 index a4b1aac9..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/BridgeMethodIndex.java +++ /dev/null @@ -1,156 +0,0 @@ -package cuchaz.enigma.analysis.index; - -import com.google.common.collect.Maps; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import javax.annotation.Nullable; -import java.util.*; - -public class BridgeMethodIndex implements JarIndexer { - private final EntryIndex entryIndex; - private final InheritanceIndex inheritanceIndex; - private final ReferenceIndex referenceIndex; - - private final Map bridgeToSpecialized = Maps.newHashMap(); - private final Map specializedToBridge = Maps.newHashMap(); - - public BridgeMethodIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex) { - this.entryIndex = entryIndex; - this.inheritanceIndex = inheritanceIndex; - this.referenceIndex = referenceIndex; - } - - public void findBridgeMethods() { - // look for access and bridged methods - for (MethodEntry methodEntry : entryIndex.getMethods()) { - MethodDefEntry methodDefEntry = (MethodDefEntry) methodEntry; - - AccessFlags access = methodDefEntry.getAccess(); - if (access == null || !access.isSynthetic()) { - continue; - } - - indexSyntheticMethod(methodDefEntry, access); - } - } - - @Override - public void processIndex(JarIndex index) { - Map copiedAccessToBridge = new HashMap<>(specializedToBridge); - - for (Map.Entry entry : copiedAccessToBridge.entrySet()) { - MethodEntry specializedEntry = entry.getKey(); - MethodEntry bridgeEntry = entry.getValue(); - if (bridgeEntry.getName().equals(specializedEntry.getName())) { - continue; - } - - MethodEntry renamedSpecializedEntry = specializedEntry.withName(bridgeEntry.getName()); - specializedToBridge.put(renamedSpecializedEntry, specializedToBridge.get(specializedEntry)); - } - } - - private void indexSyntheticMethod(MethodDefEntry syntheticMethod, AccessFlags access) { - MethodEntry specializedMethod = findSpecializedMethod(syntheticMethod); - if (specializedMethod == null) { - return; - } - - if (access.isBridge() || isPotentialBridge(syntheticMethod, specializedMethod)) { - bridgeToSpecialized.put(syntheticMethod, specializedMethod); - specializedToBridge.put(specializedMethod, syntheticMethod); - } - } - - private MethodEntry findSpecializedMethod(MethodEntry method) { - // we want to find all compiler-added methods that directly call another with no processing - - // get all the methods that we call - final Collection referencedMethods = referenceIndex.getMethodsReferencedBy(method); - - // is there just one? - if (referencedMethods.size() != 1) { - return null; - } - - return referencedMethods.stream().findFirst().orElse(null); - } - - private boolean isPotentialBridge(MethodDefEntry bridgeMethod, MethodEntry specializedMethod) { - // Bridge methods only exist for inheritance purposes, if we're private, final, or static, we cannot be inherited - AccessFlags bridgeAccess = bridgeMethod.getAccess(); - if (bridgeAccess.isPrivate() || bridgeAccess.isFinal() || bridgeAccess.isStatic()) { - return false; - } - - MethodDescriptor bridgeDesc = bridgeMethod.getDesc(); - MethodDescriptor specializedDesc = specializedMethod.getDesc(); - List bridgeArguments = bridgeDesc.getArgumentDescs(); - List specializedArguments = specializedDesc.getArgumentDescs(); - - // A bridge method will always have the same number of arguments - if (bridgeArguments.size() != specializedArguments.size()) { - return false; - } - - // Check that all argument types are bridge-compatible - for (int i = 0; i < bridgeArguments.size(); i++) { - if (!areTypesBridgeCompatible(bridgeArguments.get(i), specializedArguments.get(i))) { - return false; - } - } - - // Check that the return type is bridge-compatible - return areTypesBridgeCompatible(bridgeDesc.getReturnDesc(), specializedDesc.getReturnDesc()); - } - - private boolean areTypesBridgeCompatible(TypeDescriptor bridgeDesc, TypeDescriptor specializedDesc) { - if (bridgeDesc.equals(specializedDesc)) { - return true; - } - - // Either the descs will be equal, or they are both types and different through a generic - if (bridgeDesc.isType() && specializedDesc.isType()) { - ClassEntry bridgeType = bridgeDesc.getTypeEntry(); - ClassEntry accessedType = specializedDesc.getTypeEntry(); - - // If the given types are completely unrelated to each other, this can't be bridge compatible - InheritanceIndex.Relation relation = inheritanceIndex.computeClassRelation(accessedType, bridgeType); - return relation != InheritanceIndex.Relation.UNRELATED; - } - - return false; - } - - public boolean isBridgeMethod(MethodEntry entry) { - return bridgeToSpecialized.containsKey(entry); - } - - public boolean isSpecializedMethod(MethodEntry entry) { - return specializedToBridge.containsKey(entry); - } - - @Nullable - public MethodEntry getBridgeFromSpecialized(MethodEntry specialized) { - return specializedToBridge.get(specialized); - } - - public MethodEntry getSpecializedFromBridge(MethodEntry bridge) { - return bridgeToSpecialized.get(bridge); - } - - /** Includes "renamed specialized -> bridge" entries. */ - public Map getSpecializedToBridge() { - return Collections.unmodifiableMap(specializedToBridge); - } - - /** Only "bridge -> original name" entries. **/ - public Map getBridgeToSpecialized() { - return Collections.unmodifiableMap(bridgeToSpecialized); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java b/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java deleted file mode 100644 index 9a2726e5..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/EntryIndex.java +++ /dev/null @@ -1,102 +0,0 @@ -package cuchaz.enigma.analysis.index; - -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.entry.*; - -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - -public class EntryIndex implements JarIndexer { - private Map classes = new HashMap<>(); - private Map fields = new HashMap<>(); - private Map methods = new HashMap<>(); - private Map definitions = new HashMap<>(); - - @Override - public void indexClass(ClassDefEntry classEntry) { - definitions.put(classEntry, classEntry); - classes.put(classEntry, classEntry.getAccess()); - } - - @Override - public void indexMethod(MethodDefEntry methodEntry) { - methods.put(methodEntry, methodEntry.getAccess()); - } - - @Override - public void indexField(FieldDefEntry fieldEntry) { - fields.put(fieldEntry, fieldEntry.getAccess()); - } - - public boolean hasClass(ClassEntry entry) { - return classes.containsKey(entry); - } - - public boolean hasMethod(MethodEntry entry) { - return methods.containsKey(entry); - } - - public boolean hasField(FieldEntry entry) { - return fields.containsKey(entry); - } - - public boolean hasEntry(Entry entry) { - if (entry instanceof ClassEntry) { - return hasClass((ClassEntry) entry); - } else if (entry instanceof MethodEntry) { - return hasMethod((MethodEntry) entry); - } else if (entry instanceof FieldEntry) { - return hasField((FieldEntry) entry); - } else if (entry instanceof LocalVariableEntry) { - return hasMethod(((LocalVariableEntry) entry).getParent()); - } - - return false; - } - - @Nullable - public AccessFlags getMethodAccess(MethodEntry entry) { - return methods.get(entry); - } - - @Nullable - public AccessFlags getFieldAccess(FieldEntry entry) { - return fields.get(entry); - } - - @Nullable - public AccessFlags getClassAccess(ClassEntry entry) { - return classes.get(entry); - } - - @Nullable - public AccessFlags getEntryAccess(Entry entry) { - if (entry instanceof MethodEntry) { - return getMethodAccess((MethodEntry) entry); - } else if (entry instanceof FieldEntry) { - return getFieldAccess((FieldEntry) entry); - } else if (entry instanceof LocalVariableEntry) { - return getMethodAccess(((LocalVariableEntry) entry).getParent()); - } - - return null; - } - - public ClassDefEntry getDefinition(ClassEntry entry) { - return definitions.get(entry); - } - - public Collection getClasses() { - return classes.keySet(); - } - - public Collection getMethods() { - return methods.keySet(); - } - - public Collection getFields() { - return fields.keySet(); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/IndexClassVisitor.java b/src/main/java/cuchaz/enigma/analysis/index/IndexClassVisitor.java deleted file mode 100644 index f9cb23ce..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/IndexClassVisitor.java +++ /dev/null @@ -1,40 +0,0 @@ -package cuchaz.enigma.analysis.index; - -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; -import cuchaz.enigma.translation.representation.entry.FieldDefEntry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.MethodVisitor; - -public class IndexClassVisitor extends ClassVisitor { - private final JarIndexer indexer; - private ClassDefEntry classEntry; - - public IndexClassVisitor(JarIndex indexer, int api) { - super(api); - this.indexer = indexer; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - classEntry = ClassDefEntry.parse(access, name, signature, superName, interfaces); - indexer.indexClass(classEntry); - - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { - indexer.indexField(FieldDefEntry.parse(classEntry, access, name, desc, signature)); - - return super.visitField(access, name, desc, signature, value); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - indexer.indexMethod(MethodDefEntry.parse(classEntry, access, name, desc, signature)); - - return super.visitMethod(access, name, desc, signature, exceptions); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/IndexReferenceVisitor.java b/src/main/java/cuchaz/enigma/analysis/index/IndexReferenceVisitor.java deleted file mode 100644 index f3d419ee..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/IndexReferenceVisitor.java +++ /dev/null @@ -1,180 +0,0 @@ -package cuchaz.enigma.analysis.index; - -import cuchaz.enigma.analysis.IndexSimpleVerifier; -import cuchaz.enigma.analysis.InterpreterPair; -import cuchaz.enigma.analysis.MethodNodeWithAction; -import cuchaz.enigma.analysis.ReferenceTargetType; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.Lambda; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.Signature; -import cuchaz.enigma.translation.representation.entry.*; -import org.objectweb.asm.*; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.FieldInsnNode; -import org.objectweb.asm.tree.InvokeDynamicInsnNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.analysis.*; - -import java.util.List; -import java.util.stream.Collectors; - -public class IndexReferenceVisitor extends ClassVisitor { - private final JarIndexer indexer; - private final EntryIndex entryIndex; - private final InheritanceIndex inheritanceIndex; - private ClassEntry classEntry; - private String className; - - public IndexReferenceVisitor(JarIndexer indexer, EntryIndex entryIndex, InheritanceIndex inheritanceIndex, int api) { - super(api); - this.indexer = indexer; - this.entryIndex = entryIndex; - this.inheritanceIndex = inheritanceIndex; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - classEntry = new ClassEntry(name); - className = name; - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodDefEntry entry = new MethodDefEntry(classEntry, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access)); - return new MethodNodeWithAction(api, access, name, desc, signature, exceptions, methodNode -> { - try { - new Analyzer<>(new MethodInterpreter(entry, indexer, entryIndex, inheritanceIndex)).analyze(className, methodNode); - } catch (AnalyzerException e) { - throw new RuntimeException(e); - } - }); - } - - private static class MethodInterpreter extends InterpreterPair { - private final MethodDefEntry callerEntry; - private JarIndexer indexer; - - public MethodInterpreter(MethodDefEntry callerEntry, JarIndexer indexer, EntryIndex entryIndex, InheritanceIndex inheritanceIndex) { - super(new IndexSimpleVerifier(entryIndex, inheritanceIndex), new SourceInterpreter()); - this.callerEntry = callerEntry; - this.indexer = indexer; - } - - @Override - public PairValue newOperation(AbstractInsnNode insn) throws AnalyzerException { - if (insn.getOpcode() == Opcodes.GETSTATIC) { - FieldInsnNode field = (FieldInsnNode) insn; - indexer.indexFieldReference(callerEntry, FieldEntry.parse(field.owner, field.name, field.desc), ReferenceTargetType.none()); - } - - return super.newOperation(insn); - } - - @Override - public PairValue unaryOperation(AbstractInsnNode insn, PairValue value) throws AnalyzerException { - if (insn.getOpcode() == Opcodes.PUTSTATIC) { - FieldInsnNode field = (FieldInsnNode) insn; - indexer.indexFieldReference(callerEntry, FieldEntry.parse(field.owner, field.name, field.desc), ReferenceTargetType.none()); - } - - if (insn.getOpcode() == Opcodes.GETFIELD) { - FieldInsnNode field = (FieldInsnNode) insn; - indexer.indexFieldReference(callerEntry, FieldEntry.parse(field.owner, field.name, field.desc), getReferenceTargetType(value, insn)); - } - - return super.unaryOperation(insn, value); - } - - - @Override - public PairValue binaryOperation(AbstractInsnNode insn, PairValue value1, PairValue value2) throws AnalyzerException { - if (insn.getOpcode() == Opcodes.PUTFIELD) { - FieldInsnNode field = (FieldInsnNode) insn; - FieldEntry fieldEntry = FieldEntry.parse(field.owner, field.name, field.desc); - indexer.indexFieldReference(callerEntry, fieldEntry, ReferenceTargetType.none()); - } - - return super.binaryOperation(insn, value1, value2); - } - - @Override - public PairValue naryOperation(AbstractInsnNode insn, List> values) throws AnalyzerException { - if (insn.getOpcode() == Opcodes.INVOKEINTERFACE || insn.getOpcode() == Opcodes.INVOKESPECIAL || insn.getOpcode() == Opcodes.INVOKEVIRTUAL) { - MethodInsnNode methodInsn = (MethodInsnNode) insn; - indexer.indexMethodReference(callerEntry, MethodEntry.parse(methodInsn.owner, methodInsn.name, methodInsn.desc), getReferenceTargetType(values.get(0), insn)); - } - - if (insn.getOpcode() == Opcodes.INVOKESTATIC) { - MethodInsnNode methodInsn = (MethodInsnNode) insn; - indexer.indexMethodReference(callerEntry, MethodEntry.parse(methodInsn.owner, methodInsn.name, methodInsn.desc), ReferenceTargetType.none()); - } - - if (insn.getOpcode() == Opcodes.INVOKEDYNAMIC) { - InvokeDynamicInsnNode invokeDynamicInsn = (InvokeDynamicInsnNode) insn; - List args = values.stream().map(v -> v.right.insns.stream().findFirst().orElseThrow(AssertionError::new)).collect(Collectors.toList()); - - if ("java/lang/invoke/LambdaMetafactory".equals(invokeDynamicInsn.bsm.getOwner()) && "metafactory".equals(invokeDynamicInsn.bsm.getName())) { - Type samMethodType = (Type) invokeDynamicInsn.bsmArgs[0]; - Handle implMethod = (Handle) invokeDynamicInsn.bsmArgs[1]; - Type instantiatedMethodType = (Type) invokeDynamicInsn.bsmArgs[2]; - - ReferenceTargetType targetType; - if (implMethod.getTag() != Opcodes.H_GETSTATIC && implMethod.getTag() != Opcodes.H_PUTFIELD && implMethod.getTag() != Opcodes.H_INVOKESTATIC) { - if (instantiatedMethodType.getArgumentTypes().length < Type.getArgumentTypes(implMethod.getDesc()).length) { - targetType = getReferenceTargetType(values.get(0), insn); - } else { - targetType = ReferenceTargetType.none(); // no "this" argument - } - } else { - targetType = ReferenceTargetType.none(); - } - - indexer.indexLambda(callerEntry, new Lambda( - invokeDynamicInsn.name, - new MethodDescriptor(invokeDynamicInsn.desc), - new MethodDescriptor(samMethodType.getDescriptor()), - getHandleEntry(implMethod), - new MethodDescriptor(instantiatedMethodType.getDescriptor()) - ), targetType); - } - } - - return super.naryOperation(insn, values); - } - - private ReferenceTargetType getReferenceTargetType(PairValue target, AbstractInsnNode insn) throws AnalyzerException { - if (target.left == BasicValue.UNINITIALIZED_VALUE) { - return ReferenceTargetType.uninitialized(); - } - - if (target.left.getType().getSort() == Type.OBJECT) { - return ReferenceTargetType.classType(new ClassEntry(target.left.getType().getInternalName())); - } - - if (target.left.getType().getSort() == Type.ARRAY) { - return ReferenceTargetType.classType(new ClassEntry("java/lang/Object")); - } - - throw new AnalyzerException(insn, "called method on or accessed field of non-object type"); - } - - private static ParentedEntry getHandleEntry(Handle handle) { - switch (handle.getTag()) { - case Opcodes.H_GETFIELD: - case Opcodes.H_GETSTATIC: - case Opcodes.H_PUTFIELD: - case Opcodes.H_PUTSTATIC: - return FieldEntry.parse(handle.getOwner(), handle.getName(), handle.getDesc()); - case Opcodes.H_INVOKEINTERFACE: - case Opcodes.H_INVOKESPECIAL: - case Opcodes.H_INVOKESTATIC: - case Opcodes.H_INVOKEVIRTUAL: - case Opcodes.H_NEWINVOKESPECIAL: - return MethodEntry.parse(handle.getOwner(), handle.getName(), handle.getDesc()); - } - - throw new RuntimeException("Invalid handle tag " + handle.getTag()); - } - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java b/src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java deleted file mode 100644 index 1ab2abdf..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/InheritanceIndex.java +++ /dev/null @@ -1,127 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis.index; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import com.google.common.collect.Sets; -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -import java.util.Collection; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Set; - -public class InheritanceIndex implements JarIndexer { - private final EntryIndex entryIndex; - - private Multimap classParents = HashMultimap.create(); - private Multimap classChildren = HashMultimap.create(); - - public InheritanceIndex(EntryIndex entryIndex) { - this.entryIndex = entryIndex; - } - - @Override - public void indexClass(ClassDefEntry classEntry) { - if (classEntry.isJre()) { - return; - } - - ClassEntry superClass = classEntry.getSuperClass(); - if (superClass != null && !superClass.getName().equals("java/lang/Object")) { - indexParent(classEntry, superClass); - } - - for (ClassEntry interfaceEntry : classEntry.getInterfaces()) { - indexParent(classEntry, interfaceEntry); - } - } - - private void indexParent(ClassEntry childEntry, ClassEntry parentEntry) { - classParents.put(childEntry, parentEntry); - classChildren.put(parentEntry, childEntry); - } - - public Collection getParents(ClassEntry classEntry) { - return classParents.get(classEntry); - } - - public Collection getChildren(ClassEntry classEntry) { - return classChildren.get(classEntry); - } - - public Collection getDescendants(ClassEntry classEntry) { - Collection descendants = new HashSet<>(); - - LinkedList descendantQueue = new LinkedList<>(); - descendantQueue.push(classEntry); - - while (!descendantQueue.isEmpty()) { - ClassEntry descendant = descendantQueue.pop(); - Collection children = getChildren(descendant); - - children.forEach(descendantQueue::push); - descendants.addAll(children); - } - - return descendants; - } - - public Set getAncestors(ClassEntry classEntry) { - Set ancestors = Sets.newHashSet(); - - LinkedList ancestorQueue = new LinkedList<>(); - ancestorQueue.push(classEntry); - - while (!ancestorQueue.isEmpty()) { - ClassEntry ancestor = ancestorQueue.pop(); - Collection parents = getParents(ancestor); - - parents.forEach(ancestorQueue::push); - ancestors.addAll(parents); - } - - return ancestors; - } - - public Relation computeClassRelation(ClassEntry classEntry, ClassEntry potentialAncestor) { - if (potentialAncestor.getName().equals("java/lang/Object")) return Relation.RELATED; - if (!entryIndex.hasClass(classEntry)) return Relation.UNKNOWN; - - for (ClassEntry ancestor : getAncestors(classEntry)) { - if (potentialAncestor.equals(ancestor)) { - return Relation.RELATED; - } else if (!entryIndex.hasClass(ancestor)) { - return Relation.UNKNOWN; - } - } - - return Relation.UNRELATED; - } - - public boolean isParent(ClassEntry classEntry) { - return classChildren.containsKey(classEntry); - } - - public boolean hasParents(ClassEntry classEntry) { - Collection parents = classParents.get(classEntry); - return parents != null && !parents.isEmpty(); - } - - public enum Relation { - RELATED, - UNRELATED, - UNKNOWN - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java b/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java deleted file mode 100644 index e401c2f7..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/JarIndex.java +++ /dev/null @@ -1,171 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.analysis.index; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.analysis.ClassCache; -import cuchaz.enigma.analysis.ReferenceTargetType; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.IndexEntryResolver; -import cuchaz.enigma.translation.representation.Lambda; -import cuchaz.enigma.translation.representation.entry.*; -import cuchaz.enigma.utils.I18n; - -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.ClassReader; -import org.objectweb.asm.Opcodes; - -import java.util.Arrays; -import java.util.Collection; - -public class JarIndex implements JarIndexer { - private final EntryIndex entryIndex; - private final InheritanceIndex inheritanceIndex; - private final ReferenceIndex referenceIndex; - private final BridgeMethodIndex bridgeMethodIndex; - private final PackageVisibilityIndex packageVisibilityIndex; - private final EntryResolver entryResolver; - - private final Collection indexers; - - private final Multimap methodImplementations = HashMultimap.create(); - - public JarIndex(EntryIndex entryIndex, InheritanceIndex inheritanceIndex, ReferenceIndex referenceIndex, BridgeMethodIndex bridgeMethodIndex, PackageVisibilityIndex packageVisibilityIndex) { - this.entryIndex = entryIndex; - this.inheritanceIndex = inheritanceIndex; - this.referenceIndex = referenceIndex; - this.bridgeMethodIndex = bridgeMethodIndex; - this.packageVisibilityIndex = packageVisibilityIndex; - this.indexers = Arrays.asList(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex, packageVisibilityIndex); - this.entryResolver = new IndexEntryResolver(this); - } - - public static JarIndex empty() { - EntryIndex entryIndex = new EntryIndex(); - InheritanceIndex inheritanceIndex = new InheritanceIndex(entryIndex); - ReferenceIndex referenceIndex = new ReferenceIndex(); - BridgeMethodIndex bridgeMethodIndex = new BridgeMethodIndex(entryIndex, inheritanceIndex, referenceIndex); - PackageVisibilityIndex packageVisibilityIndex = new PackageVisibilityIndex(); - return new JarIndex(entryIndex, inheritanceIndex, referenceIndex, bridgeMethodIndex, packageVisibilityIndex); - } - - public void indexJar(ClassCache classCache, ProgressListener progress) { - progress.init(4, I18n.translate("progress.jar.indexing")); - - progress.step(1, I18n.translate("progress.jar.indexing.entries")); - classCache.visit(() -> new IndexClassVisitor(this, Utils.ASM_VERSION), ClassReader.SKIP_CODE); - - progress.step(2, I18n.translate("progress.jar.indexing.references")); - classCache.visit(() -> new IndexReferenceVisitor(this, entryIndex, inheritanceIndex, Utils.ASM_VERSION), 0); - - progress.step(3, I18n.translate("progress.jar.indexing.methods")); - bridgeMethodIndex.findBridgeMethods(); - - progress.step(4, I18n.translate("progress.jar.indexing.process")); - processIndex(this); - } - - @Override - public void processIndex(JarIndex index) { - indexers.forEach(indexer -> indexer.processIndex(index)); - } - - @Override - public void indexClass(ClassDefEntry classEntry) { - if (classEntry.isJre()) { - return; - } - - for (ClassEntry interfaceEntry : classEntry.getInterfaces()) { - if (classEntry.equals(interfaceEntry)) { - throw new IllegalArgumentException("Class cannot be its own interface! " + classEntry); - } - } - - indexers.forEach(indexer -> indexer.indexClass(classEntry)); - } - - @Override - public void indexField(FieldDefEntry fieldEntry) { - if (fieldEntry.getParent().isJre()) { - return; - } - - indexers.forEach(indexer -> indexer.indexField(fieldEntry)); - } - - @Override - public void indexMethod(MethodDefEntry methodEntry) { - if (methodEntry.getParent().isJre()) { - return; - } - - indexers.forEach(indexer -> indexer.indexMethod(methodEntry)); - - if (!methodEntry.isConstructor()) { - methodImplementations.put(methodEntry.getParent().getFullName(), methodEntry); - } - } - - @Override - public void indexMethodReference(MethodDefEntry callerEntry, MethodEntry referencedEntry, ReferenceTargetType targetType) { - if (callerEntry.getParent().isJre()) { - return; - } - - indexers.forEach(indexer -> indexer.indexMethodReference(callerEntry, referencedEntry, targetType)); - } - - @Override - public void indexFieldReference(MethodDefEntry callerEntry, FieldEntry referencedEntry, ReferenceTargetType targetType) { - if (callerEntry.getParent().isJre()) { - return; - } - - indexers.forEach(indexer -> indexer.indexFieldReference(callerEntry, referencedEntry, targetType)); - } - - @Override - public void indexLambda(MethodDefEntry callerEntry, Lambda lambda, ReferenceTargetType targetType) { - if (callerEntry.getParent().isJre()) { - return; - } - - indexers.forEach(indexer -> indexer.indexLambda(callerEntry, lambda, targetType)); - } - - public EntryIndex getEntryIndex() { - return entryIndex; - } - - public InheritanceIndex getInheritanceIndex() { - return this.inheritanceIndex; - } - - public ReferenceIndex getReferenceIndex() { - return referenceIndex; - } - - public BridgeMethodIndex getBridgeMethodIndex() { - return bridgeMethodIndex; - } - - public PackageVisibilityIndex getPackageVisibilityIndex() { - return packageVisibilityIndex; - } - - public EntryResolver getEntryResolver() { - return entryResolver; - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java b/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java deleted file mode 100644 index f17e7c98..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/JarIndexer.java +++ /dev/null @@ -1,28 +0,0 @@ -package cuchaz.enigma.analysis.index; - -import cuchaz.enigma.analysis.ReferenceTargetType; -import cuchaz.enigma.translation.representation.Lambda; -import cuchaz.enigma.translation.representation.entry.*; - -public interface JarIndexer { - default void indexClass(ClassDefEntry classEntry) { - } - - default void indexField(FieldDefEntry fieldEntry) { - } - - default void indexMethod(MethodDefEntry methodEntry) { - } - - default void indexMethodReference(MethodDefEntry callerEntry, MethodEntry referencedEntry, ReferenceTargetType targetType) { - } - - default void indexFieldReference(MethodDefEntry callerEntry, FieldEntry referencedEntry, ReferenceTargetType targetType) { - } - - default void indexLambda(MethodDefEntry callerEntry, Lambda lambda, ReferenceTargetType targetType) { - } - - default void processIndex(JarIndex index) { - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/PackageVisibilityIndex.java b/src/main/java/cuchaz/enigma/analysis/index/PackageVisibilityIndex.java deleted file mode 100644 index 63eb7300..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/PackageVisibilityIndex.java +++ /dev/null @@ -1,147 +0,0 @@ -package cuchaz.enigma.analysis.index; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Sets; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.analysis.ReferenceTargetType; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.entry.*; - -import java.util.*; - -public class PackageVisibilityIndex implements JarIndexer { - private static boolean requiresSamePackage(AccessFlags entryAcc, EntryReference ref, InheritanceIndex inheritanceIndex) { - if (entryAcc.isPublic()) { - return false; - } - - if (entryAcc.isProtected()) { - ClassEntry contextClass = ref.context.getContainingClass(); - ClassEntry referencedClass = ref.entry.getContainingClass(); - - if (!inheritanceIndex.getAncestors(contextClass).contains(referencedClass)) { - return true; // access to protected member not in superclass - } - - if (ref.targetType.getKind() == ReferenceTargetType.Kind.NONE) { - return false; // access to superclass or static superclass member - } - - // access to instance member only valid if target's class assignable to context class - return !(ref.targetType.getKind() == ReferenceTargetType.Kind.UNINITIALIZED || - ((ReferenceTargetType.ClassType) ref.targetType).getEntry().equals(contextClass) || - inheritanceIndex.getAncestors(((ReferenceTargetType.ClassType) ref.targetType).getEntry()).contains(contextClass)); - } - - return true; - } - - private final HashMultimap connections = HashMultimap.create(); - private final List> partitions = Lists.newArrayList(); - private final Map> classPartitions = Maps.newHashMap(); - - private void addConnection(ClassEntry classA, ClassEntry classB) { - if (classA != classB) { - connections.put(classA, classB); - connections.put(classB, classA); - } - } - - private void buildPartition(Set unassignedClasses, Set partition, ClassEntry member) { - for (ClassEntry connected : connections.get(member)) { - if (unassignedClasses.remove(connected)) { - partition.add(connected); - buildPartition(unassignedClasses, partition, connected); - } - } - } - - private void addConnections(EntryIndex entryIndex, ReferenceIndex referenceIndex, InheritanceIndex inheritanceIndex) { - for (FieldEntry entry : entryIndex.getFields()) { - AccessFlags entryAcc = entryIndex.getFieldAccess(entry); - if (!entryAcc.isPublic() && !entryAcc.isPrivate()) { - for (EntryReference ref : referenceIndex.getReferencesToField(entry)) { - if (requiresSamePackage(entryAcc, ref, inheritanceIndex)) { - addConnection(ref.entry.getContainingClass(), ref.context.getContainingClass()); - } - } - } - } - - for (MethodEntry entry : entryIndex.getMethods()) { - AccessFlags entryAcc = entryIndex.getMethodAccess(entry); - if (!entryAcc.isPublic() && !entryAcc.isPrivate()) { - for (EntryReference ref : referenceIndex.getReferencesToMethod(entry)) { - if (requiresSamePackage(entryAcc, ref, inheritanceIndex)) { - addConnection(ref.entry.getContainingClass(), ref.context.getContainingClass()); - } - } - } - } - - for (ClassEntry entry : entryIndex.getClasses()) { - AccessFlags entryAcc = entryIndex.getClassAccess(entry); - if (!entryAcc.isPublic() && !entryAcc.isPrivate()) { - for (EntryReference ref : referenceIndex.getFieldTypeReferencesToClass(entry)) { - if (requiresSamePackage(entryAcc, ref, inheritanceIndex)) { - addConnection(ref.entry.getContainingClass(), ref.context.getContainingClass()); - } - } - - for (EntryReference ref : referenceIndex.getMethodTypeReferencesToClass(entry)) { - if (requiresSamePackage(entryAcc, ref, inheritanceIndex)) { - addConnection(ref.entry.getContainingClass(), ref.context.getContainingClass()); - } - } - } - - for (ClassEntry parent : inheritanceIndex.getParents(entry)) { - AccessFlags parentAcc = entryIndex.getClassAccess(parent); - if (parentAcc != null && !parentAcc.isPublic() && !parentAcc.isPrivate()) { - addConnection(entry, parent); - } - } - - ClassEntry outerClass = entry.getOuterClass(); - if (outerClass != null) { - addConnection(entry, outerClass); - } - } - } - - private void addPartitions(EntryIndex entryIndex) { - Set unassignedClasses = Sets.newHashSet(entryIndex.getClasses()); - while (!unassignedClasses.isEmpty()) { - Iterator iterator = unassignedClasses.iterator(); - ClassEntry initialEntry = iterator.next(); - iterator.remove(); - - HashSet partition = Sets.newHashSet(); - partition.add(initialEntry); - buildPartition(unassignedClasses, partition, initialEntry); - partitions.add(partition); - for (ClassEntry entry : partition) { - classPartitions.put(entry, partition); - } - } - } - - public Collection> getPartitions() { - return partitions; - } - - public Set getPartition(ClassEntry classEntry) { - return classPartitions.get(classEntry); - } - - @Override - public void processIndex(JarIndex index) { - EntryIndex entryIndex = index.getEntryIndex(); - ReferenceIndex referenceIndex = index.getReferenceIndex(); - InheritanceIndex inheritanceIndex = index.getInheritanceIndex(); - addConnections(entryIndex, referenceIndex, inheritanceIndex); - addPartitions(entryIndex); - } -} diff --git a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java b/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java deleted file mode 100644 index b6797c21..00000000 --- a/src/main/java/cuchaz/enigma/analysis/index/ReferenceIndex.java +++ /dev/null @@ -1,148 +0,0 @@ -package cuchaz.enigma.analysis.index; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.analysis.ReferenceTargetType; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.Lambda; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; - -import java.util.Collection; -import java.util.Map; - -public class ReferenceIndex implements JarIndexer { - private Multimap methodReferences = HashMultimap.create(); - - private Multimap> referencesToMethods = HashMultimap.create(); - private Multimap> referencesToClasses = HashMultimap.create(); - private Multimap> referencesToFields = HashMultimap.create(); - private Multimap> fieldTypeReferences = HashMultimap.create(); - private Multimap> methodTypeReferences = HashMultimap.create(); - - @Override - public void indexMethod(MethodDefEntry methodEntry) { - indexMethodDescriptor(methodEntry, methodEntry.getDesc()); - } - - private void indexMethodDescriptor(MethodDefEntry entry, MethodDescriptor descriptor) { - for (TypeDescriptor typeDescriptor : descriptor.getArgumentDescs()) { - indexMethodTypeDescriptor(entry, typeDescriptor); - } - indexMethodTypeDescriptor(entry, descriptor.getReturnDesc()); - } - - private void indexMethodTypeDescriptor(MethodDefEntry method, TypeDescriptor typeDescriptor) { - if (typeDescriptor.isType()) { - ClassEntry referencedClass = typeDescriptor.getTypeEntry(); - methodTypeReferences.put(referencedClass, new EntryReference<>(referencedClass, referencedClass.getName(), method)); - } else if (typeDescriptor.isArray()) { - indexMethodTypeDescriptor(method, typeDescriptor.getArrayType()); - } - } - - @Override - public void indexField(FieldDefEntry fieldEntry) { - indexFieldTypeDescriptor(fieldEntry, fieldEntry.getDesc()); - } - - private void indexFieldTypeDescriptor(FieldDefEntry field, TypeDescriptor typeDescriptor) { - if (typeDescriptor.isType()) { - ClassEntry referencedClass = typeDescriptor.getTypeEntry(); - fieldTypeReferences.put(referencedClass, new EntryReference<>(referencedClass, referencedClass.getName(), field)); - } else if (typeDescriptor.isArray()) { - indexFieldTypeDescriptor(field, typeDescriptor.getArrayType()); - } - } - - @Override - public void indexMethodReference(MethodDefEntry callerEntry, MethodEntry referencedEntry, ReferenceTargetType targetType) { - referencesToMethods.put(referencedEntry, new EntryReference<>(referencedEntry, referencedEntry.getName(), callerEntry, targetType)); - methodReferences.put(callerEntry, referencedEntry); - - if (referencedEntry.isConstructor()) { - ClassEntry referencedClass = referencedEntry.getParent(); - referencesToClasses.put(referencedClass, new EntryReference<>(referencedClass, referencedEntry.getName(), callerEntry, targetType)); - } - } - - @Override - public void indexFieldReference(MethodDefEntry callerEntry, FieldEntry referencedEntry, ReferenceTargetType targetType) { - referencesToFields.put(referencedEntry, new EntryReference<>(referencedEntry, referencedEntry.getName(), callerEntry, targetType)); - } - - @Override - public void indexLambda(MethodDefEntry callerEntry, Lambda lambda, ReferenceTargetType targetType) { - if (lambda.getImplMethod() instanceof MethodEntry) { - indexMethodReference(callerEntry, (MethodEntry) lambda.getImplMethod(), targetType); - } else { - indexFieldReference(callerEntry, (FieldEntry) lambda.getImplMethod(), targetType); - } - - indexMethodDescriptor(callerEntry, lambda.getInvokedType()); - indexMethodDescriptor(callerEntry, lambda.getSamMethodType()); - indexMethodDescriptor(callerEntry, lambda.getInstantiatedMethodType()); - } - - @Override - public void processIndex(JarIndex index) { - methodReferences = remapReferences(index, methodReferences); - referencesToMethods = remapReferencesTo(index, referencesToMethods); - referencesToClasses = remapReferencesTo(index, referencesToClasses); - referencesToFields = remapReferencesTo(index, referencesToFields); - fieldTypeReferences = remapReferencesTo(index, fieldTypeReferences); - methodTypeReferences = remapReferencesTo(index, methodTypeReferences); - } - - private , V extends Entry> Multimap remapReferences(JarIndex index, Multimap multimap) { - final int keySetSize = multimap.keySet().size(); - Multimap resolved = HashMultimap.create(multimap.keySet().size(), keySetSize == 0 ? 0 : multimap.size() / keySetSize); - for (Map.Entry entry : multimap.entries()) { - resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue())); - } - return resolved; - } - - private , C extends Entry> Multimap> remapReferencesTo(JarIndex index, Multimap> multimap) { - final int keySetSize = multimap.keySet().size(); - Multimap> resolved = HashMultimap.create(keySetSize, keySetSize == 0 ? 0 : multimap.size() / keySetSize); - for (Map.Entry> entry : multimap.entries()) { - resolved.put(remap(index, entry.getKey()), remap(index, entry.getValue())); - } - return resolved; - } - - private > E remap(JarIndex index, E entry) { - return index.getEntryResolver().resolveFirstEntry(entry, ResolutionStrategy.RESOLVE_CLOSEST); - } - - private , C extends Entry> EntryReference remap(JarIndex index, EntryReference reference) { - return index.getEntryResolver().resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST); - } - - public Collection getMethodsReferencedBy(MethodEntry entry) { - return methodReferences.get(entry); - } - - public Collection> getReferencesToField(FieldEntry entry) { - return referencesToFields.get(entry); - } - - public Collection> getReferencesToClass(ClassEntry entry) { - return referencesToClasses.get(entry); - } - - public Collection> getReferencesToMethod(MethodEntry entry) { - return referencesToMethods.get(entry); - } - - public Collection> getFieldTypeReferencesToClass(ClassEntry entry) { - return fieldTypeReferences.get(entry); - } - - public Collection> getMethodTypeReferencesToClass(ClassEntry entry) { - return methodTypeReferences.get(entry); - } -} diff --git a/src/main/java/cuchaz/enigma/api/EnigmaPlugin.java b/src/main/java/cuchaz/enigma/api/EnigmaPlugin.java deleted file mode 100644 index bdd60150..00000000 --- a/src/main/java/cuchaz/enigma/api/EnigmaPlugin.java +++ /dev/null @@ -1,5 +0,0 @@ -package cuchaz.enigma.api; - -public interface EnigmaPlugin { - void init(EnigmaPluginContext ctx); -} diff --git a/src/main/java/cuchaz/enigma/api/EnigmaPluginContext.java b/src/main/java/cuchaz/enigma/api/EnigmaPluginContext.java deleted file mode 100644 index a59051ad..00000000 --- a/src/main/java/cuchaz/enigma/api/EnigmaPluginContext.java +++ /dev/null @@ -1,9 +0,0 @@ -package cuchaz.enigma.api; - -import cuchaz.enigma.api.service.EnigmaService; -import cuchaz.enigma.api.service.EnigmaServiceFactory; -import cuchaz.enigma.api.service.EnigmaServiceType; - -public interface EnigmaPluginContext { - void registerService(String id, EnigmaServiceType serviceType, EnigmaServiceFactory factory); -} diff --git a/src/main/java/cuchaz/enigma/api/service/EnigmaService.java b/src/main/java/cuchaz/enigma/api/service/EnigmaService.java deleted file mode 100644 index 526dda77..00000000 --- a/src/main/java/cuchaz/enigma/api/service/EnigmaService.java +++ /dev/null @@ -1,4 +0,0 @@ -package cuchaz.enigma.api.service; - -public interface EnigmaService { -} diff --git a/src/main/java/cuchaz/enigma/api/service/EnigmaServiceContext.java b/src/main/java/cuchaz/enigma/api/service/EnigmaServiceContext.java deleted file mode 100644 index 9e433fb0..00000000 --- a/src/main/java/cuchaz/enigma/api/service/EnigmaServiceContext.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.api.service; - -import java.util.Optional; - -public interface EnigmaServiceContext { - static EnigmaServiceContext empty() { - return key -> Optional.empty(); - } - - Optional getArgument(String key); -} diff --git a/src/main/java/cuchaz/enigma/api/service/EnigmaServiceFactory.java b/src/main/java/cuchaz/enigma/api/service/EnigmaServiceFactory.java deleted file mode 100644 index 7c10ac26..00000000 --- a/src/main/java/cuchaz/enigma/api/service/EnigmaServiceFactory.java +++ /dev/null @@ -1,5 +0,0 @@ -package cuchaz.enigma.api.service; - -public interface EnigmaServiceFactory { - T create(EnigmaServiceContext ctx); -} diff --git a/src/main/java/cuchaz/enigma/api/service/EnigmaServiceType.java b/src/main/java/cuchaz/enigma/api/service/EnigmaServiceType.java deleted file mode 100644 index 358828f0..00000000 --- a/src/main/java/cuchaz/enigma/api/service/EnigmaServiceType.java +++ /dev/null @@ -1,29 +0,0 @@ -package cuchaz.enigma.api.service; - -public final class EnigmaServiceType { - public final String key; - - private EnigmaServiceType(String key) { - this.key = key; - } - - public static EnigmaServiceType create(String key) { - return new EnigmaServiceType<>(key); - } - - @Override - public int hashCode() { - return key.hashCode(); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - - if (obj instanceof EnigmaServiceType) { - return ((EnigmaServiceType) obj).key.equals(key); - } - - return false; - } -} diff --git a/src/main/java/cuchaz/enigma/api/service/JarIndexerService.java b/src/main/java/cuchaz/enigma/api/service/JarIndexerService.java deleted file mode 100644 index 0cda1998..00000000 --- a/src/main/java/cuchaz/enigma/api/service/JarIndexerService.java +++ /dev/null @@ -1,10 +0,0 @@ -package cuchaz.enigma.api.service; - -import cuchaz.enigma.analysis.ClassCache; -import cuchaz.enigma.analysis.index.JarIndex; - -public interface JarIndexerService extends EnigmaService { - EnigmaServiceType TYPE = EnigmaServiceType.create("jar_indexer"); - - void acceptJar(ClassCache classCache, JarIndex jarIndex); -} diff --git a/src/main/java/cuchaz/enigma/api/service/NameProposalService.java b/src/main/java/cuchaz/enigma/api/service/NameProposalService.java deleted file mode 100644 index 4c357db1..00000000 --- a/src/main/java/cuchaz/enigma/api/service/NameProposalService.java +++ /dev/null @@ -1,12 +0,0 @@ -package cuchaz.enigma.api.service; - -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.util.Optional; - -public interface NameProposalService extends EnigmaService { - EnigmaServiceType TYPE = EnigmaServiceType.create("name_proposal"); - - Optional proposeName(Entry obfEntry, EntryRemapper remapper); -} diff --git a/src/main/java/cuchaz/enigma/api/service/ObfuscationTestService.java b/src/main/java/cuchaz/enigma/api/service/ObfuscationTestService.java deleted file mode 100644 index af0cf30b..00000000 --- a/src/main/java/cuchaz/enigma/api/service/ObfuscationTestService.java +++ /dev/null @@ -1,9 +0,0 @@ -package cuchaz.enigma.api.service; - -import cuchaz.enigma.translation.representation.entry.Entry; - -public interface ObfuscationTestService extends EnigmaService { - EnigmaServiceType TYPE = EnigmaServiceType.create("obfuscation_test"); - - boolean testDeobfuscated(Entry entry); -} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/AsmObjectTranslator.java b/src/main/java/cuchaz/enigma/bytecode/translators/AsmObjectTranslator.java deleted file mode 100644 index 1a2b47fb..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/translators/AsmObjectTranslator.java +++ /dev/null @@ -1,46 +0,0 @@ -package cuchaz.enigma.bytecode.translators; - -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import org.objectweb.asm.Handle; -import org.objectweb.asm.Type; - -public class AsmObjectTranslator { - public static Type translateType(Translator translator, Type type) { - String descString = type.getDescriptor(); - switch (type.getSort()) { - case Type.OBJECT: { - ClassEntry classEntry = new ClassEntry(type.getInternalName()); - return Type.getObjectType(translator.translate(classEntry).getFullName()); - } - case Type.ARRAY: { - TypeDescriptor descriptor = new TypeDescriptor(descString); - return Type.getType(translator.translate(descriptor).toString()); - } - case Type.METHOD: { - MethodDescriptor descriptor = new MethodDescriptor(descString); - return Type.getMethodType(translator.translate(descriptor).toString()); - } - } - return type; - } - - public static Handle translateHandle(Translator translator, Handle handle) { - MethodEntry entry = new MethodEntry(new ClassEntry(handle.getOwner()), handle.getName(), new MethodDescriptor(handle.getDesc())); - MethodEntry translatedMethod = translator.translate(entry); - ClassEntry ownerClass = translatedMethod.getParent(); - return new Handle(handle.getTag(), ownerClass.getFullName(), translatedMethod.getName(), translatedMethod.getDesc().toString(), handle.isInterface()); - } - - public static Object translateValue(Translator translator, Object value) { - if (value instanceof Type) { - return translateType(translator, (Type) value); - } else if (value instanceof Handle) { - return translateHandle(translator, (Handle) value); - } - return value; - } -} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java deleted file mode 100644 index cfd8fbee..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/translators/LocalVariableFixVisitor.java +++ /dev/null @@ -1,126 +0,0 @@ -package cuchaz.enigma.bytecode.translators; - -import com.google.common.base.CharMatcher; -import cuchaz.enigma.translation.LocalNameGenerator; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.Label; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class LocalVariableFixVisitor extends ClassVisitor { - private ClassDefEntry ownerEntry; - - public LocalVariableFixVisitor(int api, ClassVisitor visitor) { - super(api, visitor); - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - ownerEntry = ClassDefEntry.parse(access, name, signature, superName, interfaces); - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodDefEntry methodEntry = MethodDefEntry.parse(ownerEntry, access, name, descriptor, signature); - return new Method(api, methodEntry, super.visitMethod(access, name, descriptor, signature, exceptions)); - } - - private class Method extends MethodVisitor { - private final MethodDefEntry methodEntry; - private final Map parameterNames = new HashMap<>(); - private final Map parameterIndices = new HashMap<>(); - private boolean hasParameterTable; - private int parameterIndex = 0; - - Method(int api, MethodDefEntry methodEntry, MethodVisitor visitor) { - super(api, visitor); - this.methodEntry = methodEntry; - - int lvIndex = methodEntry.getAccess().isStatic() ? 0 : 1; - List parameters = methodEntry.getDesc().getArgumentDescs(); - for (int parameterIndex = 0; parameterIndex < parameters.size(); parameterIndex++) { - TypeDescriptor param = parameters.get(parameterIndex); - parameterIndices.put(lvIndex, parameterIndex); - lvIndex += param.getSize(); - } - } - - @Override - public void visitParameter(String name, int access) { - hasParameterTable = true; - super.visitParameter(fixParameterName(parameterIndex, name), fixParameterAccess(parameterIndex, access)); - parameterIndex++; - } - - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { - if (index == 0 && !methodEntry.getAccess().isStatic()) { - name = "this"; - } else if (parameterIndices.containsKey(index)) { - name = fixParameterName(parameterIndices.get(index), name); - } else if (isInvalidName(name)) { - name = LocalNameGenerator.generateLocalVariableName(index, new TypeDescriptor(desc)); - } - - super.visitLocalVariable(name, desc, signature, start, end, index); - } - - private boolean isInvalidName(String name) { - return name == null || name.isEmpty() || !CharMatcher.ascii().matchesAllOf(name); - } - - @Override - public void visitEnd() { - if (!hasParameterTable) { - List arguments = methodEntry.getDesc().getArgumentDescs(); - for (int argumentIndex = 0; argumentIndex < arguments.size(); argumentIndex++) { - super.visitParameter(fixParameterName(argumentIndex, null), fixParameterAccess(argumentIndex, 0)); - } - } - - super.visitEnd(); - } - - private String fixParameterName(int index, String name) { - if (parameterNames.get(index) != null) { - return parameterNames.get(index); // to make sure that LVT names are consistent with parameter table names - } - - if (isInvalidName(name)) { - List arguments = methodEntry.getDesc().getArgumentDescs(); - name = LocalNameGenerator.generateArgumentName(index, arguments.get(index), arguments); - } - - if (index == 0 && ownerEntry.getAccess().isEnum() && methodEntry.getName().equals("")) { - name = "name"; - } - - if (index == 1 && ownerEntry.getAccess().isEnum() && methodEntry.getName().equals("")) { - name = "ordinal"; - } - - parameterNames.put(index, name); - return name; - } - - private int fixParameterAccess(int index, int access) { - if (index == 0 && ownerEntry.getAccess().isEnum() && methodEntry.getName().equals("")) { - access |= Opcodes.ACC_SYNTHETIC; - } - - if (index == 1 && ownerEntry.getAccess().isEnum() && methodEntry.getName().equals("")) { - access |= Opcodes.ACC_SYNTHETIC; - } - - return access; - } - } -} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java deleted file mode 100644 index 2b750eac..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/translators/SourceFixVisitor.java +++ /dev/null @@ -1,39 +0,0 @@ -package cuchaz.enigma.bytecode.translators; - -import cuchaz.enigma.analysis.index.BridgeMethodIndex; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.MethodVisitor; -import org.objectweb.asm.Opcodes; - -public class SourceFixVisitor extends ClassVisitor { - private final JarIndex index; - private ClassDefEntry ownerEntry; - - public SourceFixVisitor(int api, ClassVisitor visitor, JarIndex index) { - super(api, visitor); - this.index = index; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - ownerEntry = ClassDefEntry.parse(access, name, signature, superName, interfaces); - super.visit(version, access, name, signature, superName, interfaces); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String descriptor, String signature, String[] exceptions) { - MethodDefEntry methodEntry = MethodDefEntry.parse(ownerEntry, access, name, descriptor, signature); - - BridgeMethodIndex bridgeIndex = index.getBridgeMethodIndex(); - if (bridgeIndex.isBridgeMethod(methodEntry)) { - access |= Opcodes.ACC_BRIDGE; - } else if (bridgeIndex.isSpecializedMethod(methodEntry)) { - name = bridgeIndex.getBridgeFromSpecialized(methodEntry).getName(); - } - - return super.visitMethod(access, name, descriptor, signature, exceptions); - } -} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java deleted file mode 100644 index cb843ad4..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationAnnotationVisitor.java +++ /dev/null @@ -1,51 +0,0 @@ -package cuchaz.enigma.bytecode.translators; - -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import org.objectweb.asm.AnnotationVisitor; - -public class TranslationAnnotationVisitor extends AnnotationVisitor { - private final Translator translator; - private final ClassEntry annotationEntry; - - public TranslationAnnotationVisitor(Translator translator, ClassEntry annotationEntry, int api, AnnotationVisitor av) { - super(api, av); - this.translator = translator; - this.annotationEntry = annotationEntry; - } - - @Override - public void visit(String name, Object value) { - super.visit(name, AsmObjectTranslator.translateValue(translator, value)); - } - - @Override - public AnnotationVisitor visitArray(String name) { - return new TranslationAnnotationVisitor(translator, annotationEntry, api, super.visitArray(name)); - } - - @Override - public AnnotationVisitor visitAnnotation(String name, String desc) { - TypeDescriptor type = new TypeDescriptor(desc); - if (name != null) { - FieldEntry annotationField = translator.translate(new FieldEntry(annotationEntry, name, type)); - return super.visitAnnotation(annotationField.getName(), annotationField.getDesc().toString()); - } else { - return super.visitAnnotation(null, translator.translate(type).toString()); - } - } - - @Override - public void visitEnum(String name, String desc, String value) { - TypeDescriptor type = new TypeDescriptor(desc); - FieldEntry enumField = translator.translate(new FieldEntry(type.getTypeEntry(), value, type)); - if (name != null) { - FieldEntry annotationField = translator.translate(new FieldEntry(annotationEntry, name, type)); - super.visitEnum(annotationField.getName(), annotationField.getDesc().toString(), enumField.getName()); - } else { - super.visitEnum(null, translator.translate(type).toString(), enumField.getName()); - } - } -} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java deleted file mode 100644 index e4c41d32..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationClassVisitor.java +++ /dev/null @@ -1,102 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.bytecode.translators; - -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; -import org.objectweb.asm.*; - -import java.util.Arrays; - -public class TranslationClassVisitor extends ClassVisitor { - private final Translator translator; - - private ClassDefEntry obfClassEntry; - - public TranslationClassVisitor(Translator translator, int api, ClassVisitor cv) { - super(api, cv); - this.translator = translator; - } - - @Override - public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) { - obfClassEntry = ClassDefEntry.parse(access, name, signature, superName, interfaces); - - ClassDefEntry translatedEntry = translator.translate(obfClassEntry); - String translatedSuper = translatedEntry.getSuperClass() != null ? translatedEntry.getSuperClass().getFullName() : null; - String[] translatedInterfaces = Arrays.stream(translatedEntry.getInterfaces()).map(ClassEntry::getFullName).toArray(String[]::new); - - super.visit(version, translatedEntry.getAccess().getFlags(), translatedEntry.getFullName(), translatedEntry.getSignature().toString(), translatedSuper, translatedInterfaces); - } - - @Override - public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { - FieldDefEntry entry = FieldDefEntry.parse(obfClassEntry, access, name, desc, signature); - FieldDefEntry translatedEntry = translator.translate(entry); - FieldVisitor fv = super.visitField(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), translatedEntry.getSignature().toString(), value); - return new TranslationFieldVisitor(translator, translatedEntry, api, fv); - } - - @Override - public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) { - MethodDefEntry entry = MethodDefEntry.parse(obfClassEntry, access, name, desc, signature); - MethodDefEntry translatedEntry = translator.translate(entry); - String[] translatedExceptions = new String[exceptions.length]; - for (int i = 0; i < exceptions.length; i++) { - translatedExceptions[i] = translator.translate(new ClassEntry(exceptions[i])).getFullName(); - } - MethodVisitor mv = super.visitMethod(translatedEntry.getAccess().getFlags(), translatedEntry.getName(), translatedEntry.getDesc().toString(), translatedEntry.getSignature().toString(), translatedExceptions); - return new TranslationMethodVisitor(translator, obfClassEntry, entry, api, mv); - } - - @Override - public void visitInnerClass(String name, String outerName, String innerName, int access) { - ClassDefEntry classEntry = ClassDefEntry.parse(access, name, obfClassEntry.getSignature().toString(), null, new String[0]); - ClassDefEntry translatedEntry = translator.translate(classEntry); - ClassEntry translatedOuterClass = translatedEntry.getOuterClass(); - if (translatedOuterClass == null) { - throw new IllegalStateException("Translated inner class did not have outer class"); - } - - // Anonymous classes do not specify an outer or inner name. As we do not translate from the given parameter, ignore if the input is null - String translatedName = translatedEntry.getFullName(); - String translatedOuterName = outerName != null ? translatedOuterClass.getFullName() : null; - String translatedInnerName = innerName != null ? translatedEntry.getName() : null; - super.visitInnerClass(translatedName, translatedOuterName, translatedInnerName, translatedEntry.getAccess().getFlags()); - } - - @Override - public void visitOuterClass(String owner, String name, String desc) { - if (desc != null) { - MethodEntry translatedEntry = translator.translate(new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc))); - super.visitOuterClass(translatedEntry.getParent().getFullName(), translatedEntry.getName(), translatedEntry.getDesc().toString()); - } else { - super.visitOuterClass(owner, name, desc); - } - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - TypeDescriptor translatedDesc = translator.translate(new TypeDescriptor(desc)); - AnnotationVisitor av = super.visitAnnotation(translatedDesc.toString(), visible); - return new TranslationAnnotationVisitor(translator, translatedDesc.getTypeEntry(), api, av); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - TypeDescriptor translatedDesc = translator.translate(new TypeDescriptor(desc)); - AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, translatedDesc.toString(), visible); - return new TranslationAnnotationVisitor(translator, translatedDesc.getTypeEntry(), api, av); - } -} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationFieldVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationFieldVisitor.java deleted file mode 100644 index 28fc199c..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationFieldVisitor.java +++ /dev/null @@ -1,33 +0,0 @@ -package cuchaz.enigma.bytecode.translators; - -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.FieldDefEntry; -import org.objectweb.asm.AnnotationVisitor; -import org.objectweb.asm.FieldVisitor; -import org.objectweb.asm.TypePath; - -public class TranslationFieldVisitor extends FieldVisitor { - private final FieldDefEntry fieldEntry; - private final Translator translator; - - public TranslationFieldVisitor(Translator translator, FieldDefEntry fieldEntry, int api, FieldVisitor fv) { - super(api, fv); - this.translator = translator; - this.fieldEntry = fieldEntry; - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - TypeDescriptor typeDesc = translator.translate(new TypeDescriptor(desc)); - AnnotationVisitor av = super.visitAnnotation(typeDesc.toString(), visible); - return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - TypeDescriptor typeDesc = translator.translate(new TypeDescriptor(desc)); - AnnotationVisitor av = super.visitAnnotation(typeDesc.toString(), visible); - return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av); - } -} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java deleted file mode 100644 index a82df1b0..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationMethodVisitor.java +++ /dev/null @@ -1,145 +0,0 @@ -package cuchaz.enigma.bytecode.translators; - -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.Signature; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; -import org.objectweb.asm.*; - -public class TranslationMethodVisitor extends MethodVisitor { - private final MethodDefEntry methodEntry; - private final Translator translator; - - private int parameterIndex = 0; - private int parameterLvIndex; - - public TranslationMethodVisitor(Translator translator, ClassDefEntry ownerEntry, MethodDefEntry methodEntry, int api, MethodVisitor mv) { - super(api, mv); - this.translator = translator; - this.methodEntry = methodEntry; - - parameterLvIndex = methodEntry.getAccess().isStatic() ? 0 : 1; - } - - @Override - public void visitParameter(String name, int access) { - name = translateVariableName(parameterLvIndex, name); - parameterLvIndex += methodEntry.getDesc().getArgumentDescs().get(parameterIndex++).getSize(); - - super.visitParameter(name, access); - } - - @Override - public void visitFieldInsn(int opcode, String owner, String name, String desc) { - FieldEntry entry = new FieldEntry(new ClassEntry(owner), name, new TypeDescriptor(desc)); - FieldEntry translatedEntry = translator.translate(entry); - super.visitFieldInsn(opcode, translatedEntry.getParent().getFullName(), translatedEntry.getName(), translatedEntry.getDesc().toString()); - } - - @Override - public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) { - MethodEntry entry = new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc)); - MethodEntry translatedEntry = translator.translate(entry); - super.visitMethodInsn(opcode, translatedEntry.getParent().getFullName(), translatedEntry.getName(), translatedEntry.getDesc().toString(), itf); - } - - @Override - public void visitFrame(int type, int localCount, Object[] locals, int stackCount, Object[] stack) { - Object[] translatedLocals = this.getTranslatedFrame(locals, localCount); - Object[] translatedStack = this.getTranslatedFrame(stack, stackCount); - super.visitFrame(type, localCount, translatedLocals, stackCount, translatedStack); - } - - private Object[] getTranslatedFrame(Object[] array, int count) { - if (array == null) { - return null; - } - for (int i = 0; i < count; i++) { - Object object = array[i]; - if (object instanceof String) { - String type = (String) object; - array[i] = translator.translate(new ClassEntry(type)).getFullName(); - } - } - return array; - } - - @Override - public AnnotationVisitor visitAnnotation(String desc, boolean visible) { - TypeDescriptor typeDesc = translator.translate(new TypeDescriptor(desc)); - AnnotationVisitor av = super.visitAnnotation(typeDesc.toString(), visible); - return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av); - } - - @Override - public AnnotationVisitor visitParameterAnnotation(int parameter, String desc, boolean visible) { - TypeDescriptor typeDesc = translator.translate(new TypeDescriptor(desc)); - AnnotationVisitor av = super.visitParameterAnnotation(parameter, typeDesc.toString(), visible); - return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av); - } - - @Override - public AnnotationVisitor visitTypeAnnotation(int typeRef, TypePath typePath, String desc, boolean visible) { - TypeDescriptor typeDesc = translator.translate(new TypeDescriptor(desc)); - AnnotationVisitor av = super.visitTypeAnnotation(typeRef, typePath, typeDesc.toString(), visible); - return new TranslationAnnotationVisitor(translator, typeDesc.getTypeEntry(), api, av); - } - - @Override - public void visitTypeInsn(int opcode, String type) { - ClassEntry translatedEntry = translator.translate(new ClassEntry(type)); - super.visitTypeInsn(opcode, translatedEntry.getFullName()); - } - - @Override - public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) { - MethodDescriptor translatedMethodDesc = translator.translate(new MethodDescriptor(desc)); - Object[] translatedBsmArgs = new Object[bsmArgs.length]; - for (int i = 0; i < bsmArgs.length; i++) { - translatedBsmArgs[i] = AsmObjectTranslator.translateValue(translator, bsmArgs[i]); - } - super.visitInvokeDynamicInsn(name, translatedMethodDesc.toString(), AsmObjectTranslator.translateHandle(translator, bsm), translatedBsmArgs); - } - - @Override - public void visitLdcInsn(Object cst) { - super.visitLdcInsn(AsmObjectTranslator.translateValue(translator, cst)); - } - - @Override - public void visitMultiANewArrayInsn(String desc, int dims) { - super.visitMultiANewArrayInsn(translator.translate(new TypeDescriptor(desc)).toString(), dims); - } - - @Override - public void visitTryCatchBlock(Label start, Label end, Label handler, String type) { - if (type != null) { - ClassEntry translatedEntry = translator.translate(new ClassEntry(type)); - super.visitTryCatchBlock(start, end, handler, translatedEntry.getFullName()); - } else { - super.visitTryCatchBlock(start, end, handler, type); - } - } - - @Override - public void visitLocalVariable(String name, String desc, String signature, Label start, Label end, int index) { - signature = translator.translate(Signature.createTypedSignature(signature)).toString(); - name = translateVariableName(index, name); - desc = translator.translate(new TypeDescriptor(desc)).toString(); - - super.visitLocalVariable(name, desc, signature, start, end, index); - } - - private String translateVariableName(int index, String name) { - LocalVariableEntry entry = new LocalVariableEntry(methodEntry, index, "", true,null); - LocalVariableEntry translatedEntry = translator.translate(entry); - String translatedName = translatedEntry.getName(); - - if (!translatedName.isEmpty()) { - return translatedName; - } - - return name; - } -} diff --git a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationSignatureVisitor.java b/src/main/java/cuchaz/enigma/bytecode/translators/TranslationSignatureVisitor.java deleted file mode 100644 index eebd6509..00000000 --- a/src/main/java/cuchaz/enigma/bytecode/translators/TranslationSignatureVisitor.java +++ /dev/null @@ -1,129 +0,0 @@ -package cuchaz.enigma.bytecode.translators; - -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.signature.SignatureVisitor; - -import java.util.Stack; -import java.util.function.Function; - -public class TranslationSignatureVisitor extends SignatureVisitor { - private final Function remapper; - - private final SignatureVisitor sv; - private final Stack classStack = new Stack<>(); - - public TranslationSignatureVisitor(Function remapper, SignatureVisitor sv) { - super(Utils.ASM_VERSION); - this.remapper = remapper; - this.sv = sv; - } - - @Override - public void visitClassType(String name) { - classStack.push(name); - String translatedEntry = this.remapper.apply(name); - this.sv.visitClassType(translatedEntry); - } - - @Override - public void visitInnerClassType(String name) { - String lastClass = classStack.pop(); - if (!name.startsWith(lastClass+"$")){//todo see if there's a way to base this on whether there were type params or not - name = lastClass+"$"+name; - } - String translatedEntry = this.remapper.apply(name); - if (translatedEntry.contains("/")){ - translatedEntry = translatedEntry.substring(translatedEntry.lastIndexOf("/")+1); - } - if (translatedEntry.contains("$")){ - translatedEntry = translatedEntry.substring(translatedEntry.lastIndexOf("$")+1); - } - this.sv.visitInnerClassType(translatedEntry); - } - - @Override - public void visitFormalTypeParameter(String name) { - this.sv.visitFormalTypeParameter(name); - } - - @Override - public void visitTypeVariable(String name) { - this.sv.visitTypeVariable(name); - } - - @Override - public SignatureVisitor visitArrayType() { - this.sv.visitArrayType(); - return this; - } - - @Override - public void visitBaseType(char descriptor) { - this.sv.visitBaseType(descriptor); - } - - @Override - public SignatureVisitor visitClassBound() { - this.sv.visitClassBound(); - return this; - } - - @Override - public SignatureVisitor visitExceptionType() { - this.sv.visitExceptionType(); - return this; - } - - @Override - public SignatureVisitor visitInterface() { - this.sv.visitInterface(); - return this; - } - - @Override - public SignatureVisitor visitInterfaceBound() { - this.sv.visitInterfaceBound(); - return this; - } - - @Override - public SignatureVisitor visitParameterType() { - this.sv.visitParameterType(); - return this; - } - - @Override - public SignatureVisitor visitReturnType() { - this.sv.visitReturnType(); - return this; - } - - @Override - public SignatureVisitor visitSuperclass() { - this.sv.visitSuperclass(); - return this; - } - - @Override - public void visitTypeArgument() { - this.sv.visitTypeArgument(); - } - - @Override - public SignatureVisitor visitTypeArgument(char wildcard) { - this.sv.visitTypeArgument(wildcard); - return this; - } - - @Override - public void visitEnd() { - this.sv.visitEnd(); - if (!classStack.empty()) - classStack.pop(); - } - - @Override - public String toString() { - return this.sv.toString(); - } -} diff --git a/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java b/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java deleted file mode 100644 index 9d238e3a..00000000 --- a/src/main/java/cuchaz/enigma/command/CheckMappingsCommand.java +++ /dev/null @@ -1,77 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.Enigma; -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -import java.nio.file.Path; -import java.util.Set; -import java.util.stream.Collectors; - -public class CheckMappingsCommand extends Command { - - public CheckMappingsCommand() { - super("checkmappings"); - } - - @Override - public String getUsage() { - return " "; - } - - @Override - public boolean isValidArgument(int length) { - return length == 2; - } - - @Override - public void run(String... args) throws Exception { - Path fileJarIn = getReadableFile(getArg(args, 0, "in jar", true)).toPath(); - Path fileMappings = getReadablePath(getArg(args, 1, "mappings file", true)); - - Enigma enigma = Enigma.create(); - - System.out.println("Reading JAR..."); - - EnigmaProject project = enigma.openJar(fileJarIn, ProgressListener.none()); - - System.out.println("Reading mappings..."); - - MappingFormat format = chooseEnigmaFormat(fileMappings); - MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); - - EntryTree mappings = format.read(fileMappings, ProgressListener.none(), saveParameters); - project.setMappings(mappings); - - JarIndex idx = project.getJarIndex(); - - boolean error = false; - - for (Set partition : idx.getPackageVisibilityIndex().getPartitions()) { - long packages = partition.stream() - .map(project.getMapper()::deobfuscate) - .map(ClassEntry::getPackageName) - .distinct() - .count(); - if (packages > 1) { - error = true; - System.err.println("ERROR: Must be in one package:\n" + partition.stream() - .map(project.getMapper()::deobfuscate) - .map(ClassEntry::toString) - .sorted() - .collect(Collectors.joining("\n")) - ); - } - } - - if (error) { - throw new IllegalStateException("Errors in package visibility detected, see SysErr above"); - } - } -} diff --git a/src/main/java/cuchaz/enigma/command/Command.java b/src/main/java/cuchaz/enigma/command/Command.java deleted file mode 100644 index 09dd3216..00000000 --- a/src/main/java/cuchaz/enigma/command/Command.java +++ /dev/null @@ -1,154 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.Enigma; -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; -import cuchaz.enigma.translation.mapping.tree.EntryTree; - -import java.io.File; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; - -import com.google.common.io.MoreFiles; - -public abstract class Command { - public final String name; - - protected Command(String name) { - this.name = name; - } - - public abstract String getUsage(); - - public abstract boolean isValidArgument(int length); - - public abstract void run(String... args) throws Exception; - - protected static EnigmaProject openProject(Path fileJarIn, Path fileMappings) throws Exception { - ProgressListener progress = new ConsoleProgressListener(); - - Enigma enigma = Enigma.create(); - - System.out.println("Reading jar..."); - EnigmaProject project = enigma.openJar(fileJarIn, progress); - - if (fileMappings != null) { - System.out.println("Reading mappings..."); - - MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); - EntryTree mappings = chooseEnigmaFormat(fileMappings).read(fileMappings, progress, saveParameters); - - project.setMappings(mappings); - } - - return project; - } - - protected static MappingFormat chooseEnigmaFormat(Path path) { - if (Files.isDirectory(path)) { - return MappingFormat.ENIGMA_DIRECTORY; - } else if ("zip".equalsIgnoreCase(MoreFiles.getFileExtension(path))) { - return MappingFormat.ENIGMA_ZIP; - } else { - return MappingFormat.ENIGMA_FILE; - } - } - - protected static File getWritableFile(String path) { - if (path == null) { - return null; - } - File file = new File(path).getAbsoluteFile(); - File dir = file.getParentFile(); - if (dir == null) { - throw new IllegalArgumentException("Cannot write file: " + path); - } - // quick fix to avoid stupid stuff in Gradle code - if (!dir.isDirectory()) { - dir.mkdirs(); - } - return file; - } - - protected static File getWritableFolder(String path) { - if (path == null) { - return null; - } - File dir = new File(path).getAbsoluteFile(); - if (!dir.exists()) { - throw new IllegalArgumentException("Cannot write to folder: " + dir); - } - return dir; - } - - protected static File getReadableFile(String path) { - if (path == null) { - return null; - } - File file = new File(path).getAbsoluteFile(); - if (!file.exists()) { - throw new IllegalArgumentException("Cannot find file: " + file.getAbsolutePath()); - } - return file; - } - - protected static Path getReadablePath(String path) { - if (path == null) { - return null; - } - Path file = Paths.get(path).toAbsolutePath(); - if (!Files.exists(file)) { - throw new IllegalArgumentException("Cannot find file: " + file.toString()); - } - return file; - } - - protected static String getArg(String[] args, int i, String name, boolean required) { - if (i >= args.length) { - if (required) { - throw new IllegalArgumentException(name + " is required"); - } else { - return null; - } - } - return args[i]; - } - - public static class ConsoleProgressListener implements ProgressListener { - - private static final int ReportTime = 5000; // 5s - - private int totalWork; - private long startTime; - private long lastReportTime; - - @Override - public void init(int totalWork, String title) { - this.totalWork = totalWork; - this.startTime = System.currentTimeMillis(); - this.lastReportTime = this.startTime; - System.out.println(title); - } - - @Override - public void step(int numDone, String message) { - long now = System.currentTimeMillis(); - boolean isLastUpdate = numDone == this.totalWork; - boolean shouldReport = isLastUpdate || now - this.lastReportTime > ReportTime; - - if (shouldReport) { - int percent = numDone * 100 / this.totalWork; - System.out.println(String.format("\tProgress: %3d%%", percent)); - this.lastReportTime = now; - } - if (isLastUpdate) { - double elapsedSeconds = (now - this.startTime) / 1000.0; - System.out.println(String.format("Finished in %.1f seconds", elapsedSeconds)); - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/command/ComposeMappingsCommand.java b/src/main/java/cuchaz/enigma/command/ComposeMappingsCommand.java deleted file mode 100644 index f57f1fa6..00000000 --- a/src/main/java/cuchaz/enigma/command/ComposeMappingsCommand.java +++ /dev/null @@ -1,41 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingFileNameFormat; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.utils.Utils; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class ComposeMappingsCommand extends Command { - public ComposeMappingsCommand() { - super("compose-mappings"); - } - - @Override - public String getUsage() { - return " "; - } - - @Override - public boolean isValidArgument(int length) { - return length == 7; - } - - @Override - public void run(String... args) throws IOException, MappingParseException { - MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); - - EntryTree left = MappingCommandsUtil.read(args[0], Paths.get(args[1]), saveParameters); - EntryTree right = MappingCommandsUtil.read(args[2], Paths.get(args[3]), saveParameters); - EntryTree result = MappingCommandsUtil.compose(left, right, args[6].equals("left") || args[6].equals("both"), args[6].equals("right") || args[6].equals("both")); - - Path output = Paths.get(args[5]); - Utils.delete(output); - MappingCommandsUtil.write(result, args[4], output, saveParameters); - } -} diff --git a/src/main/java/cuchaz/enigma/command/ConvertMappingsCommand.java b/src/main/java/cuchaz/enigma/command/ConvertMappingsCommand.java deleted file mode 100644 index 689df02d..00000000 --- a/src/main/java/cuchaz/enigma/command/ConvertMappingsCommand.java +++ /dev/null @@ -1,39 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingFileNameFormat; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.utils.Utils; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class ConvertMappingsCommand extends Command { - public ConvertMappingsCommand() { - super("convert-mappings"); - } - - @Override - public String getUsage() { - return " "; - } - - @Override - public boolean isValidArgument(int length) { - return length == 4; - } - - @Override - public void run(String... args) throws IOException, MappingParseException { - MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); - - EntryTree mappings = MappingCommandsUtil.read(args[0], Paths.get(args[1]), saveParameters); - - Path output = Paths.get(args[3]); - Utils.delete(output); - MappingCommandsUtil.write(mappings, args[2], output, saveParameters); - } -} diff --git a/src/main/java/cuchaz/enigma/command/DecompileCommand.java b/src/main/java/cuchaz/enigma/command/DecompileCommand.java deleted file mode 100644 index 3d15dac6..00000000 --- a/src/main/java/cuchaz/enigma/command/DecompileCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.source.DecompilerService; -import cuchaz.enigma.source.Decompilers; - -import java.lang.reflect.Field; -import java.nio.file.Path; -import java.util.Locale; - -public class DecompileCommand extends Command { - - public DecompileCommand() { - super("decompile"); - } - - @Override - public String getUsage() { - return " []"; - } - - @Override - public boolean isValidArgument(int length) { - return length == 2 || length == 3; - } - - @Override - public void run(String... args) throws Exception { - String decompilerName = getArg(args, 1, "decompiler", true); - Path fileJarIn = getReadableFile(getArg(args, 1, "in jar", true)).toPath(); - Path fileJarOut = getWritableFolder(getArg(args, 2, "out folder", true)).toPath(); - Path fileMappings = getReadablePath(getArg(args, 3, "mappings file", false)); - - DecompilerService decompilerService; - - try { - Field decompilerField = Decompilers.class.getField(decompilerName.toUpperCase(Locale.ROOT)); - decompilerService = (DecompilerService) decompilerField.get(null); - } catch (NoSuchFieldException e) { - System.err.println("Decompiler not found."); - return; - } - - EnigmaProject project = openProject(fileJarIn, fileMappings); - - ProgressListener progress = new ConsoleProgressListener(); - - EnigmaProject.JarExport jar = project.exportRemappedJar(progress); - EnigmaProject.SourceExport source = jar.decompile(progress, decompilerService); - - source.write(fileJarOut, progress); - } -} diff --git a/src/main/java/cuchaz/enigma/command/DeobfuscateCommand.java b/src/main/java/cuchaz/enigma/command/DeobfuscateCommand.java deleted file mode 100644 index b0d2a7d0..00000000 --- a/src/main/java/cuchaz/enigma/command/DeobfuscateCommand.java +++ /dev/null @@ -1,37 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.ProgressListener; - -import java.nio.file.Path; - -public class DeobfuscateCommand extends Command { - - public DeobfuscateCommand() { - super("deobfuscate"); - } - - @Override - public String getUsage() { - return " []"; - } - - @Override - public boolean isValidArgument(int length) { - return length == 2 || length == 3; - } - - @Override - public void run(String... args) throws Exception { - Path fileJarIn = getReadablePath(getArg(args, 0, "in jar", true)); - Path fileJarOut = getWritableFile(getArg(args, 1, "out jar", true)).toPath(); - Path fileMappings = getReadablePath(getArg(args, 2, "mappings file", false)); - - EnigmaProject project = openProject(fileJarIn, fileMappings); - - ProgressListener progress = new ConsoleProgressListener(); - - EnigmaProject.JarExport jar = project.exportRemappedJar(progress); - jar.write(fileJarOut, progress); - } -} diff --git a/src/main/java/cuchaz/enigma/command/InvertMappingsCommand.java b/src/main/java/cuchaz/enigma/command/InvertMappingsCommand.java deleted file mode 100644 index cd11e2e6..00000000 --- a/src/main/java/cuchaz/enigma/command/InvertMappingsCommand.java +++ /dev/null @@ -1,40 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingFileNameFormat; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.utils.Utils; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; - -public class InvertMappingsCommand extends Command { - public InvertMappingsCommand() { - super("invert-mappings"); - } - - @Override - public String getUsage() { - return " "; - } - - @Override - public boolean isValidArgument(int length) { - return length == 4; - } - - @Override - public void run(String... args) throws IOException, MappingParseException { - MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); - - EntryTree source = MappingCommandsUtil.read(args[0], Paths.get(args[1]), saveParameters); - EntryTree result = MappingCommandsUtil.invert(source); - - Path output = Paths.get(args[3]); - Utils.delete(output); - MappingCommandsUtil.write(result, args[2], output, saveParameters); - } -} diff --git a/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java b/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java deleted file mode 100644 index eb8d5dcc..00000000 --- a/src/main/java/cuchaz/enigma/command/MapSpecializedMethodsCommand.java +++ /dev/null @@ -1,69 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.analysis.ClassCache; -import cuchaz.enigma.analysis.index.BridgeMethodIndex; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.MappingTranslator; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.*; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.Utils; - -import java.io.IOException; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Map; - -public class MapSpecializedMethodsCommand extends Command { - public MapSpecializedMethodsCommand() { - super("map-specialized-methods"); - } - - @Override - public String getUsage() { - return " "; - } - - @Override - public boolean isValidArgument(int length) { - return length == 5; - } - - @Override - public void run(String... args) throws IOException, MappingParseException { - run(Paths.get(args[0]), args[1], Paths.get(args[2]), args[3], Paths.get(args[4])); - } - - public static void run(Path jar, String sourceFormat, Path sourcePath, String resultFormat, Path output) throws IOException, MappingParseException { - MappingSaveParameters saveParameters = new MappingSaveParameters(MappingFileNameFormat.BY_DEOBF); - EntryTree source = MappingCommandsUtil.read(sourceFormat, sourcePath, saveParameters); - EntryTree result = new HashEntryTree<>(); - ClassCache classCache = ClassCache.of(jar); - JarIndex jarIndex = classCache.index(ProgressListener.none()); - BridgeMethodIndex bridgeMethodIndex = jarIndex.getBridgeMethodIndex(); - Translator translator = new MappingTranslator(source, jarIndex.getEntryResolver()); - - // Copy all non-specialized methods - for (EntryTreeNode node : source) { - if (!(node.getEntry() instanceof MethodEntry) || !bridgeMethodIndex.isSpecializedMethod((MethodEntry) node.getEntry())) { - result.insert(node.getEntry(), node.getValue()); - } - } - - // Add correct mappings for specialized methods - for (Map.Entry entry : bridgeMethodIndex.getBridgeToSpecialized().entrySet()) { - MethodEntry bridge = entry.getKey(); - MethodEntry specialized = entry.getValue(); - String name = translator.translate(bridge).getName(); - result.insert(specialized, new EntryMapping(name)); - } - - Utils.delete(output); - MappingCommandsUtil.write(result, resultFormat, output, saveParameters); - } -} diff --git a/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java b/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java deleted file mode 100644 index fc7afbc0..00000000 --- a/src/main/java/cuchaz/enigma/command/MappingCommandsUtil.java +++ /dev/null @@ -1,148 +0,0 @@ -package cuchaz.enigma.command; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.MappingTranslator; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.VoidEntryResolver; -import cuchaz.enigma.translation.mapping.serde.*; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.HashSet; -import java.util.Set; - -public final class MappingCommandsUtil { - private MappingCommandsUtil() {} - - public static EntryTree invert(EntryTree mappings) { - Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE); - EntryTree result = new HashEntryTree<>(); - - for (EntryTreeNode node : mappings) { - Entry leftEntry = node.getEntry(); - EntryMapping leftMapping = node.getValue(); - - if (!(leftEntry instanceof ClassEntry || leftEntry instanceof MethodEntry || leftEntry instanceof FieldEntry)) { - result.insert(translator.translate(leftEntry), leftMapping); - continue; - } - - Entry rightEntry = translator.translate(leftEntry); - - result.insert(rightEntry, leftMapping == null ? null : new EntryMapping(leftEntry.getName())); // TODO: leftMapping.withName once javadoc PR is merged - } - - return result; - } - - public static EntryTree compose(EntryTree left, EntryTree right, boolean keepLeftOnly, boolean keepRightOnly) { - Translator leftTranslator = new MappingTranslator(left, VoidEntryResolver.INSTANCE); - EntryTree result = new HashEntryTree<>(); - Set> addedMappings = new HashSet<>(); - - for (EntryTreeNode node : left) { - Entry leftEntry = node.getEntry(); - EntryMapping leftMapping = node.getValue(); - - Entry rightEntry = leftTranslator.translate(leftEntry); - - EntryMapping rightMapping = right.get(rightEntry); - if (rightMapping != null) { - result.insert(leftEntry, rightMapping); - addedMappings.add(rightEntry); - } else if (keepLeftOnly) { - result.insert(leftEntry, leftMapping); - } - } - - if (keepRightOnly) { - Translator leftInverseTranslator = new MappingTranslator(invert(left), VoidEntryResolver.INSTANCE); - for (EntryTreeNode node : right) { - Entry rightEntry = node.getEntry(); - EntryMapping rightMapping = node.getValue(); - - if (!addedMappings.contains(rightEntry)) { - result.insert(leftInverseTranslator.translate(rightEntry), rightMapping); - } - } - } - return result; - } - - public static EntryTree read(String type, Path path, MappingSaveParameters saveParameters) throws MappingParseException, IOException { - if (type.equals("enigma")) { - return (Files.isDirectory(path) ? EnigmaMappingsReader.DIRECTORY : EnigmaMappingsReader.ZIP).read(path, ProgressListener.none(), saveParameters); - } - - if (type.equals("tiny")) { - return TinyMappingsReader.INSTANCE.read(path, ProgressListener.none(), saveParameters); - } - - MappingFormat format = null; - try { - format = MappingFormat.valueOf(type.toUpperCase()); - } catch (IllegalArgumentException ignored) { - if (type.equals("tinyv2")) { - format = MappingFormat.TINY_V2; - } - } - - if (format != null) { - return format.getReader().read(path, ProgressListener.none(), saveParameters); - } - - throw new IllegalArgumentException("no reader for " + type); - } - - public static void write(EntryTree mappings, String type, Path path, MappingSaveParameters saveParameters) { - if (type.equals("enigma")) { - EnigmaMappingsWriter.DIRECTORY.write(mappings, path, ProgressListener.none(), saveParameters); - return; - } - - if (type.startsWith("tinyv2:") || type.startsWith("tiny_v2:")) { - String[] split = type.split(":"); - - if (split.length != 3) { - throw new IllegalArgumentException("specify column names as 'tinyv2:from_namespace:to_namespace'"); - } - - new TinyV2Writer(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters); - return; - } - - if (type.startsWith("tiny:")) { - String[] split = type.split(":"); - - if (split.length != 3) { - throw new IllegalArgumentException("specify column names as 'tiny:from_column:to_column'"); - } - - new TinyMappingsWriter(split[1], split[2]).write(mappings, path, ProgressListener.none(), saveParameters); - return; - } - - MappingFormat format = null; - try { - format = MappingFormat.valueOf(type.toUpperCase()); - } catch (IllegalArgumentException ignored) {} - - if (format != null) { - format.getWriter().write(mappings, path, ProgressListener.none(), saveParameters); - return; - } - - throw new IllegalArgumentException("no writer for " + type); - } -} diff --git a/src/main/java/cuchaz/enigma/config/Config.java b/src/main/java/cuchaz/enigma/config/Config.java deleted file mode 100644 index e116fce9..00000000 --- a/src/main/java/cuchaz/enigma/config/Config.java +++ /dev/null @@ -1,261 +0,0 @@ -package cuchaz.enigma.config; - -import com.bulenkov.darcula.DarculaLaf; -import com.google.common.io.Files; -import com.google.gson.*; -import cuchaz.enigma.source.DecompilerService; -import cuchaz.enigma.source.Decompilers; - -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import javax.swing.plaf.metal.MetalLookAndFeel; -import java.awt.*; -import java.awt.image.BufferedImage; -import java.io.File; -import java.io.IOException; -import java.lang.reflect.Type; -import java.nio.charset.Charset; - -public class Config { - public static class AlphaColorEntry { - public Integer rgb; - public float alpha = 1.0f; - - public AlphaColorEntry(Integer rgb, float alpha) { - this.rgb = rgb; - this.alpha = alpha; - } - - public Color get() { - if (rgb == null) { - return new Color(0, 0, 0, 0); - } - - Color baseColor = new Color(rgb); - return new Color(baseColor.getRed(), baseColor.getGreen(), baseColor.getBlue(), (int)(255 * alpha)); - } - } - - public enum LookAndFeel { - DEFAULT("Default"), - DARCULA("Darcula"), - SYSTEM("System"), - NONE("None (JVM default)"); - - // the "JVM default" look and feel, get it at the beginning and store it so we can set it later - private static javax.swing.LookAndFeel NONE_LAF = UIManager.getLookAndFeel(); - private final String name; - - LookAndFeel(String name) { - this.name = name; - } - - public String getName() { - return name; - } - - public void setGlobalLAF() { - try { - switch (this) { - case NONE: - UIManager.setLookAndFeel(NONE_LAF); - break; - case DEFAULT: - UIManager.setLookAndFeel(new MetalLookAndFeel()); - break; - case DARCULA: - UIManager.setLookAndFeel(new DarculaLaf()); - break; - case SYSTEM: - UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); - } - } catch (Exception e){ - throw new Error("Failed to set global look and feel", e); - } - } - - public static boolean isDarkLaf() { - // a bit of a hack because swing doesn't give any API for that, and we need colors that aren't defined in look and feel - JPanel panel = new JPanel(); - panel.setSize(new Dimension(10, 10)); - panel.doLayout(); - - BufferedImage image = new BufferedImage(panel.getSize().width, panel.getSize().height, BufferedImage.TYPE_INT_RGB); - panel.printAll(image.getGraphics()); - - Color c = new Color(image.getRGB(0, 0)); - - // convert the color we got to grayscale - int b = (int) (0.3 * c.getRed() + 0.59 * c.getGreen() + 0.11 * c.getBlue()); - return b < 85; - } - - public void apply(Config config) { - boolean isDark = this == LookAndFeel.DARCULA || isDarkLaf(); - if (!isDark) {//Defaults found here: https://github.com/Sciss/SyntaxPane/blob/122da367ff7a5d31627a70c62a48a9f0f4f85a0a/src/main/resources/de/sciss/syntaxpane/defaultsyntaxkit/config.properties#L139 - config.lineNumbersForeground = 0x333300; - config.lineNumbersBackground = 0xEEEEFF; - config.lineNumbersSelected = 0xCCCCEE; - config.obfuscatedColor = new AlphaColorEntry(0xFFDCDC, 1.0f); - config.obfuscatedColorOutline = new AlphaColorEntry(0xA05050, 1.0f); - config.proposedColor = new AlphaColorEntry(0x000000, 0.075f); - config.proposedColorOutline = new AlphaColorEntry(0x000000, 0.15f); - config.deobfuscatedColor = new AlphaColorEntry(0xDCFFDC, 1.0f); - config.deobfuscatedColorOutline = new AlphaColorEntry(0x50A050, 1.0f); - config.editorBackground = 0xFFFFFF; - config.highlightColor = 0x3333EE; - config.caretColor = 0x000000; - config.selectionHighlightColor = 0x000000; - config.stringColor = 0xCC6600; - config.numberColor = 0x999933; - config.operatorColor = 0x000000; - config.delimiterColor = 0x000000; - config.typeColor = 0x000000; - config.identifierColor = 0x000000; - config.defaultTextColor = 0x000000; - } else {//Based off colors found here: https://github.com/dracula/dracula-theme/ - config.lineNumbersForeground = 0xA4A4A3; - config.lineNumbersBackground = 0x313335; - config.lineNumbersSelected = 0x606366; - config.obfuscatedColor = new AlphaColorEntry(0xFF5555, 0.3f); - config.obfuscatedColorOutline = new AlphaColorEntry(0xFF5555, 0.5f); - config.deobfuscatedColor = new AlphaColorEntry(0x50FA7B, 0.3f); - config.deobfuscatedColorOutline = new AlphaColorEntry(0x50FA7B, 0.5f); - config.proposedColor = new AlphaColorEntry(0x606366, 0.3f); - config.proposedColorOutline = new AlphaColorEntry(0x606366, 0.5f); - config.editorBackground = 0x282A36; - config.highlightColor = 0xFF79C6; - config.caretColor = 0xF8F8F2; - config.selectionHighlightColor = 0xF8F8F2; - config.stringColor = 0xF1FA8C; - config.numberColor = 0xBD93F9; - config.operatorColor = 0xF8F8F2; - config.delimiterColor = 0xF8F8F2; - config.typeColor = 0xF8F8F2; - config.identifierColor = 0xF8F8F2; - config.defaultTextColor = 0xF8F8F2; - } - } - } - - public enum Decompiler { - PROCYON("Procyon", Decompilers.PROCYON), - CFR("CFR", Decompilers.CFR); - - public final DecompilerService service; - public final String name; - - Decompiler(String name, DecompilerService service) { - this.name = name; - this.service = service; - } - } - - private static final File DIR_HOME = new File(System.getProperty("user.home")); - private static final File ENIGMA_DIR = new File(DIR_HOME, ".enigma"); - private static final File CONFIG_FILE = new File(ENIGMA_DIR, "config.json"); - private static final Config INSTANCE = new Config(); - - private final transient Gson gson; // transient to exclude it from being exposed - - public AlphaColorEntry obfuscatedColor; - public AlphaColorEntry obfuscatedColorOutline; - public AlphaColorEntry proposedColor; - public AlphaColorEntry proposedColorOutline; - public AlphaColorEntry deobfuscatedColor; - public AlphaColorEntry deobfuscatedColorOutline; - - public Integer editorBackground; - public Integer highlightColor; - public Integer caretColor; - public Integer selectionHighlightColor; - - public Integer stringColor; - public Integer numberColor; - public Integer operatorColor; - public Integer delimiterColor; - public Integer typeColor; - public Integer identifierColor; - public Integer defaultTextColor; - - public Integer lineNumbersBackground; - public Integer lineNumbersSelected; - public Integer lineNumbersForeground; - - public String language = I18n.DEFAULT_LANGUAGE; - - public LookAndFeel lookAndFeel = LookAndFeel.DEFAULT; - - public float scaleFactor = 1.0f; - - public Decompiler decompiler = Decompiler.PROCYON; - - private Config() { - gson = new GsonBuilder() - .registerTypeAdapter(Integer.class, new IntSerializer()) - .registerTypeAdapter(Integer.class, new IntDeserializer()) - .registerTypeAdapter(Config.class, (InstanceCreator) type -> this) - .setPrettyPrinting() - .create(); - try { - this.loadConfig(); - } catch (IOException ignored) { - try { - this.reset(); - } catch (IOException ignored1) { - } - } - } - - public void loadConfig() throws IOException { - if (!ENIGMA_DIR.exists()) ENIGMA_DIR.mkdirs(); - File configFile = new File(ENIGMA_DIR, "config.json"); - boolean loaded = false; - - if (configFile.exists()) { - try { - gson.fromJson(Files.asCharSource(configFile, Charset.defaultCharset()).read(), Config.class); - loaded = true; - } catch (Exception e) { - e.printStackTrace(); - } - } - - if (!loaded) { - this.reset(); - Files.touch(configFile); - } - saveConfig(); - } - - public void saveConfig() throws IOException { - Files.asCharSink(CONFIG_FILE, Charset.defaultCharset()).write(gson.toJson(this)); - } - - public void reset() throws IOException { - this.lookAndFeel = LookAndFeel.DEFAULT; - this.lookAndFeel.apply(this); - this.decompiler = Decompiler.PROCYON; - this.language = I18n.DEFAULT_LANGUAGE; - this.saveConfig(); - } - - private static class IntSerializer implements JsonSerializer { - @Override - public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) { - return new JsonPrimitive("#" + Integer.toHexString(src).toUpperCase()); - } - } - - private static class IntDeserializer implements JsonDeserializer { - @Override - public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) { - return (int) Long.parseLong(json.getAsString().replace("#", ""), 16); - } - } - - public static Config getInstance() { - return INSTANCE; - } -} diff --git a/src/main/java/cuchaz/enigma/config/Themes.java b/src/main/java/cuchaz/enigma/config/Themes.java deleted file mode 100644 index 547a4202..00000000 --- a/src/main/java/cuchaz/enigma/config/Themes.java +++ /dev/null @@ -1,48 +0,0 @@ -package cuchaz.enigma.config; - -import java.awt.Font; -import java.io.IOException; -import java.lang.reflect.Field; - -import javax.swing.SwingUtilities; - -import com.github.swingdpi.UiDefaultsScaler; -import com.google.common.collect.ImmutableMap; -import cuchaz.enigma.gui.EnigmaSyntaxKit; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.gui.highlight.BoxHighlightPainter; -import cuchaz.enigma.gui.highlight.TokenHighlightType; -import cuchaz.enigma.gui.util.ScaleUtil; -import de.sciss.syntaxpane.DefaultSyntaxKit; - -public class Themes { - - public static void setLookAndFeel(Gui gui, Config.LookAndFeel lookAndFeel) { - Config.getInstance().lookAndFeel = lookAndFeel; - updateTheme(gui); - } - - public static void updateTheme(Gui gui) { - Config config = Config.getInstance(); - config.lookAndFeel.setGlobalLAF(); - config.lookAndFeel.apply(config); - try { - config.saveConfig(); - } catch (IOException e) { - e.printStackTrace(); - } - EnigmaSyntaxKit.invalidate(); - DefaultSyntaxKit.initKit(); - DefaultSyntaxKit.registerContentType("text/enigma-sources", EnigmaSyntaxKit.class.getName()); - gui.boxHighlightPainters = ImmutableMap.of( - TokenHighlightType.OBFUSCATED, BoxHighlightPainter.create(config.obfuscatedColor, config.obfuscatedColorOutline), - TokenHighlightType.PROPOSED, BoxHighlightPainter.create(config.proposedColor, config.proposedColorOutline), - TokenHighlightType.DEOBFUSCATED, BoxHighlightPainter.create(config.deobfuscatedColor, config.deobfuscatedColorOutline) - ); - gui.setEditorTheme(config.lookAndFeel); - SwingUtilities.updateComponentTreeUI(gui.getFrame()); - ScaleUtil.applyScaling(); - } - - -} diff --git a/src/main/java/cuchaz/enigma/gui/BrowserCaret.java b/src/main/java/cuchaz/enigma/gui/BrowserCaret.java deleted file mode 100644 index af105dbd..00000000 --- a/src/main/java/cuchaz/enigma/gui/BrowserCaret.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui; - -import javax.swing.text.DefaultCaret; - -public class BrowserCaret extends DefaultCaret { - - @Override - public boolean isSelectionVisible() { - return true; - } - - @Override - public boolean isVisible() { - return true; - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/ClassSelector.java b/src/main/java/cuchaz/enigma/gui/ClassSelector.java deleted file mode 100644 index a23e24c2..00000000 --- a/src/main/java/cuchaz/enigma/gui/ClassSelector.java +++ /dev/null @@ -1,532 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui; - -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; -import java.util.*; - -import javax.annotation.Nullable; -import javax.swing.JOptionPane; -import javax.swing.JTree; -import javax.swing.event.CellEditorListener; -import javax.swing.event.ChangeEvent; -import javax.swing.tree.*; - -import com.google.common.collect.ArrayListMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import cuchaz.enigma.gui.node.ClassSelectorClassNode; -import cuchaz.enigma.gui.node.ClassSelectorPackageNode; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -public class ClassSelector extends JTree { - - public static final Comparator DEOBF_CLASS_COMPARATOR = Comparator.comparing(ClassEntry::getFullName); - - private final GuiController controller; - - private DefaultMutableTreeNode rootNodes; - private ClassSelectionListener selectionListener; - private RenameSelectionListener renameSelectionListener; - private Comparator comparator; - - private final Map displayedObfToDeobf = new HashMap<>(); - - public ClassSelector(Gui gui, Comparator comparator, boolean isRenamable) { - this.comparator = comparator; - this.controller = gui.getController(); - - // configure the tree control - setEditable(true); - setRootVisible(false); - setShowsRootHandles(false); - setModel(null); - - // hook events - addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (selectionListener != null && event.getClickCount() == 2) { - // get the selected node - TreePath path = getSelectionPath(); - if (path != null && path.getLastPathComponent() instanceof ClassSelectorClassNode) { - ClassSelectorClassNode node = (ClassSelectorClassNode) path.getLastPathComponent(); - selectionListener.onSelectClass(node.getObfEntry()); - } - } - } - }); - - final JTree tree = this; - - final DefaultTreeCellEditor editor = new DefaultTreeCellEditor(tree, - (DefaultTreeCellRenderer) tree.getCellRenderer()) { - @Override - public boolean isCellEditable(EventObject event) { - return isRenamable && !(event instanceof MouseEvent) && super.isCellEditable(event); - } - }; - this.setCellEditor(editor); - editor.addCellEditorListener(new CellEditorListener() { - @Override - public void editingStopped(ChangeEvent e) { - String data = editor.getCellEditorValue().toString(); - TreePath path = getSelectionPath(); - - Object realPath = path.getLastPathComponent(); - if (realPath != null && realPath instanceof DefaultMutableTreeNode && data != null) { - DefaultMutableTreeNode node = (DefaultMutableTreeNode) realPath; - TreeNode parentNode = node.getParent(); - if (parentNode == null) - return; - boolean allowEdit = true; - for (int i = 0; i < parentNode.getChildCount(); i++) { - TreeNode childNode = parentNode.getChildAt(i); - if (childNode != null && childNode.toString().equals(data) && childNode != node) { - allowEdit = false; - break; - } - } - if (allowEdit && renameSelectionListener != null) { - Object prevData = node.getUserObject(); - Object objectData = node.getUserObject() instanceof ClassEntry ? new ClassEntry(((ClassEntry) prevData).getPackageName() + "/" + data) : data; - try { - renameSelectionListener.onSelectionRename(node.getUserObject(), objectData, node); - node.setUserObject(objectData); // Make sure that it's modified - } catch (IllegalNameException ex) { - JOptionPane.showOptionDialog(gui.getFrame(), ex.getMessage(), "Enigma - Error", JOptionPane.OK_OPTION, - JOptionPane.ERROR_MESSAGE, null, new String[]{"Ok"}, "OK"); - editor.cancelCellEditing(); - } - } else - editor.cancelCellEditing(); - } - - } - - @Override - public void editingCanceled(ChangeEvent e) { - // NOP - } - }); - // init defaults - this.selectionListener = null; - this.renameSelectionListener = null; - } - - public boolean isDuplicate(Object[] nodes, String data) { - int count = 0; - - for (Object node : nodes) { - if (node.toString().equals(data)) { - count++; - if (count == 2) - return true; - } - } - return false; - } - - public void setSelectionListener(ClassSelectionListener val) { - this.selectionListener = val; - } - - public void setRenameSelectionListener(RenameSelectionListener renameSelectionListener) { - this.renameSelectionListener = renameSelectionListener; - } - - public void setClasses(Collection classEntries) { - displayedObfToDeobf.clear(); - - List state = getExpansionState(this); - if (classEntries == null) { - setModel(null); - return; - } - - Translator translator = controller.project.getMapper().getDeobfuscator(); - - // build the package names - Map packages = Maps.newHashMap(); - for (ClassEntry obfClass : classEntries) { - ClassEntry deobfClass = translator.translate(obfClass); - packages.put(deobfClass.getPackageName(), null); - } - - // sort the packages - List sortedPackageNames = Lists.newArrayList(packages.keySet()); - sortedPackageNames.sort((a, b) -> - { - // I can never keep this rule straight when writing these damn things... - // a < b => -1, a == b => 0, a > b => +1 - - if (b == null || a == null) { - return 0; - } - - String[] aparts = a.split("/"); - String[] bparts = b.split("/"); - for (int i = 0; true; i++) { - if (i >= aparts.length) { - return -1; - } else if (i >= bparts.length) { - return 1; - } - - int result = aparts[i].compareTo(bparts[i]); - if (result != 0) { - return result; - } - } - }); - - // create the rootNodes node and the package nodes - rootNodes = new DefaultMutableTreeNode(); - for (String packageName : sortedPackageNames) { - ClassSelectorPackageNode node = new ClassSelectorPackageNode(packageName); - packages.put(packageName, node); - rootNodes.add(node); - } - - // put the classes into packages - Multimap packagedClassEntries = ArrayListMultimap.create(); - for (ClassEntry obfClass : classEntries) { - ClassEntry deobfClass = translator.translate(obfClass); - packagedClassEntries.put(deobfClass.getPackageName(), obfClass); - } - - // build the class nodes - for (String packageName : packagedClassEntries.keySet()) { - // sort the class entries - List classEntriesInPackage = Lists.newArrayList(packagedClassEntries.get(packageName)); - classEntriesInPackage.sort((o1, o2) -> comparator.compare(translator.translate(o1), translator.translate(o2))); - - // create the nodes in order - for (ClassEntry obfClass : classEntriesInPackage) { - ClassEntry deobfClass = translator.translate(obfClass); - ClassSelectorPackageNode node = packages.get(packageName); - ClassSelectorClassNode classNode = new ClassSelectorClassNode(obfClass, deobfClass); - displayedObfToDeobf.put(obfClass, deobfClass); - node.add(classNode); - } - } - - // finally, update the tree control - setModel(new DefaultTreeModel(rootNodes)); - - restoreExpansionState(this, state); - } - - public ClassEntry getSelectedClass() { - if (!isSelectionEmpty()) { - Object selectedNode = getSelectionPath().getLastPathComponent(); - if (selectedNode instanceof ClassSelectorClassNode) { - ClassSelectorClassNode classNode = (ClassSelectorClassNode) selectedNode; - return classNode.getClassEntry(); - } - } - return null; - } - - public String getSelectedPackage() { - if (!isSelectionEmpty()) { - Object selectedNode = getSelectionPath().getLastPathComponent(); - if (selectedNode instanceof ClassSelectorPackageNode) { - ClassSelectorPackageNode packageNode = (ClassSelectorPackageNode) selectedNode; - return packageNode.getPackageName(); - } else if (selectedNode instanceof ClassSelectorClassNode) { - ClassSelectorClassNode classNode = (ClassSelectorClassNode) selectedNode; - return classNode.getClassEntry().getPackageName(); - } - } - return null; - } - - public boolean isDescendant(TreePath path1, TreePath path2) { - int count1 = path1.getPathCount(); - int count2 = path2.getPathCount(); - if (count1 <= count2) { - return false; - } - while (count1 != count2) { - path1 = path1.getParentPath(); - count1--; - } - return path1.equals(path2); - } - - public enum State { - EXPANDED, - SELECTED - } - - public static class StateEntry { - public final State state; - public final TreePath path; - - public StateEntry(State state, TreePath path) { - this.state = state; - this.path = path; - } - } - - public List getExpansionState(JTree tree) { - List state = new ArrayList<>(); - int rowCount = tree.getRowCount(); - for (int i = 0; i < rowCount; i++) { - TreePath path = tree.getPathForRow(i); - if (tree.isPathSelected(path)) { - state.add(new StateEntry(State.SELECTED, path)); - } - if (tree.isExpanded(path)) { - state.add(new StateEntry(State.EXPANDED, path)); - } - } - return state; - } - - public void restoreExpansionState(JTree tree, List expansionState) { - tree.clearSelection(); - - for (StateEntry entry : expansionState) { - switch (entry.state) { - case SELECTED: - tree.addSelectionPath(entry.path); - break; - case EXPANDED: - tree.expandPath(entry.path); - break; - } - } - } - - public List packageNodes() { - List nodes = Lists.newArrayList(); - DefaultMutableTreeNode root = (DefaultMutableTreeNode) getModel().getRoot(); - Enumeration children = root.children(); - while (children.hasMoreElements()) { - ClassSelectorPackageNode packageNode = (ClassSelectorPackageNode) children.nextElement(); - nodes.add(packageNode); - } - return nodes; - } - - public List classNodes(ClassSelectorPackageNode packageNode) { - List nodes = Lists.newArrayList(); - Enumeration children = packageNode.children(); - while (children.hasMoreElements()) { - ClassSelectorClassNode classNode = (ClassSelectorClassNode) children.nextElement(); - nodes.add(classNode); - } - return nodes; - } - - public void expandPackage(String packageName) { - if (packageName == null) { - return; - } - for (ClassSelectorPackageNode packageNode : packageNodes()) { - if (packageNode.getPackageName().equals(packageName)) { - expandPath(new TreePath(new Object[]{getModel().getRoot(), packageNode})); - return; - } - } - } - - public void expandAll() { - for (ClassSelectorPackageNode packageNode : packageNodes()) { - expandPath(new TreePath(new Object[]{getModel().getRoot(), packageNode})); - } - } - - public ClassEntry getFirstClass() { - ClassSelectorPackageNode packageNode = packageNodes().get(0); - if (packageNode != null) { - ClassSelectorClassNode classNode = classNodes(packageNode).get(0); - if (classNode != null) { - return classNode.getClassEntry(); - } - } - return null; - } - - public ClassSelectorPackageNode getPackageNode(ClassEntry entry) { - String packageName = entry.getPackageName(); - if (packageName == null) { - packageName = "(none)"; - } - for (ClassSelectorPackageNode packageNode : packageNodes()) { - if (packageNode.getPackageName().equals(packageName)) { - return packageNode; - } - } - return null; - } - - @Nullable - public ClassEntry getDisplayedDeobf(ClassEntry obfEntry) { - return displayedObfToDeobf.get(obfEntry); - } - - public ClassSelectorPackageNode getPackageNode(ClassSelector selector, ClassEntry entry) { - ClassSelectorPackageNode packageNode = getPackageNode(entry); - - if (selector != null && packageNode == null && selector.getPackageNode(entry) != null) - return selector.getPackageNode(entry); - return packageNode; - } - - public ClassEntry getNextClass(ClassEntry entry) { - boolean foundIt = false; - for (ClassSelectorPackageNode packageNode : packageNodes()) { - if (!foundIt) { - // skip to the package with our target in it - if (packageNode.getPackageName().equals(entry.getPackageName())) { - for (ClassSelectorClassNode classNode : classNodes(packageNode)) { - if (!foundIt) { - if (classNode.getClassEntry().equals(entry)) { - foundIt = true; - } - } else { - // return the next class - return classNode.getClassEntry(); - } - } - } - } else { - // return the next class - ClassSelectorClassNode classNode = classNodes(packageNode).get(0); - if (classNode != null) { - return classNode.getClassEntry(); - } - } - } - return null; - } - - public void setSelectionClass(ClassEntry classEntry) { - expandPackage(classEntry.getPackageName()); - for (ClassSelectorPackageNode packageNode : packageNodes()) { - for (ClassSelectorClassNode classNode : classNodes(packageNode)) { - if (classNode.getClassEntry().equals(classEntry)) { - TreePath path = new TreePath(new Object[]{getModel().getRoot(), packageNode, classNode}); - setSelectionPath(path); - scrollPathToVisible(path); - } - } - } - } - - public void removeNode(ClassSelectorPackageNode packageNode, ClassEntry entry) { - DefaultTreeModel model = (DefaultTreeModel) getModel(); - - if (packageNode == null) - return; - - for (int i = 0; i < packageNode.getChildCount(); i++) { - DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) packageNode.getChildAt(i); - if (childNode.getUserObject() instanceof ClassEntry && childNode.getUserObject().equals(entry)) { - model.removeNodeFromParent(childNode); - if (childNode instanceof ClassSelectorClassNode) { - displayedObfToDeobf.remove(((ClassSelectorClassNode) childNode).getObfEntry()); - } - break; - } - } - } - - public void removeNodeIfEmpty(ClassSelectorPackageNode packageNode) { - if (packageNode != null && packageNode.getChildCount() == 0) - ((DefaultTreeModel) getModel()).removeNodeFromParent(packageNode); - } - - public void moveClassIn(ClassEntry classEntry) { - removeEntry(classEntry); - insertNode(classEntry); - } - - public void moveClassOut(ClassEntry classEntry) { - removeEntry(classEntry); - } - - private void removeEntry(ClassEntry classEntry) { - ClassEntry previousDeobf = displayedObfToDeobf.get(classEntry); - if (previousDeobf != null) { - ClassSelectorPackageNode packageNode = getPackageNode(previousDeobf); - removeNode(packageNode, previousDeobf); - removeNodeIfEmpty(packageNode); - } - } - - public ClassSelectorPackageNode getOrCreatePackage(ClassEntry entry) { - DefaultTreeModel model = (DefaultTreeModel) getModel(); - ClassSelectorPackageNode newPackageNode = getPackageNode(entry); - if (newPackageNode == null) { - newPackageNode = new ClassSelectorPackageNode(entry.getPackageName()); - model.insertNodeInto(newPackageNode, (MutableTreeNode) model.getRoot(), getPlacementIndex(newPackageNode)); - } - return newPackageNode; - } - - public void insertNode(ClassEntry obfEntry) { - ClassEntry deobfEntry = controller.project.getMapper().deobfuscate(obfEntry); - ClassSelectorPackageNode packageNode = getOrCreatePackage(deobfEntry); - - DefaultTreeModel model = (DefaultTreeModel) getModel(); - ClassSelectorClassNode classNode = new ClassSelectorClassNode(obfEntry, deobfEntry); - model.insertNodeInto(classNode, packageNode, getPlacementIndex(packageNode, classNode)); - - displayedObfToDeobf.put(obfEntry, deobfEntry); - } - - public void reload() { - DefaultTreeModel model = (DefaultTreeModel) getModel(); - model.reload(rootNodes); - } - - private int getPlacementIndex(ClassSelectorPackageNode newPackageNode, ClassSelectorClassNode classNode) { - List classNodes = classNodes(newPackageNode); - classNodes.add(classNode); - classNodes.sort((a, b) -> comparator.compare(a.getClassEntry(), b.getClassEntry())); - for (int i = 0; i < classNodes.size(); i++) - if (classNodes.get(i) == classNode) - return i; - - return 0; - } - - private int getPlacementIndex(ClassSelectorPackageNode newPackageNode) { - List packageNodes = packageNodes(); - if (!packageNodes.contains(newPackageNode)) { - packageNodes.add(newPackageNode); - packageNodes.sort(Comparator.comparing(ClassSelectorPackageNode::toString)); - } - - for (int i = 0; i < packageNodes.size(); i++) - if (packageNodes.get(i) == newPackageNode) - return i; - - return 0; - } - - public interface ClassSelectionListener { - void onSelectClass(ClassEntry classEntry); - } - - public interface RenameSelectionListener { - void onSelectionRename(Object prevData, Object data, DefaultMutableTreeNode node); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/CodeReader.java b/src/main/java/cuchaz/enigma/gui/CodeReader.java deleted file mode 100644 index e119640a..00000000 --- a/src/main/java/cuchaz/enigma/gui/CodeReader.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui; - -import cuchaz.enigma.analysis.Token; - -import javax.swing.*; -import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.Highlighter.HighlightPainter; -import java.awt.*; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; - -public class CodeReader extends JEditorPane { - private static final long serialVersionUID = 3673180950485748810L; - - // HACKHACK: someday we can update the main GUI to use this code reader - public static void navigateToToken(final JEditorPane editor, final Token token, final HighlightPainter highlightPainter) { - - // set the caret position to the token - Document document = editor.getDocument(); - int clampedPosition = Math.min(Math.max(token.start, 0), document.getLength()); - - editor.setCaretPosition(clampedPosition); - editor.grabFocus(); - - try { - // make sure the token is visible in the scroll window - Rectangle start = editor.modelToView(token.start); - Rectangle end = editor.modelToView(token.end); - final Rectangle show = start.union(end); - show.grow(start.width * 10, start.height * 6); - SwingUtilities.invokeLater(() -> editor.scrollRectToVisible(show)); - } catch (BadLocationException ex) { - throw new Error(ex); - } - - // highlight the token momentarily - final Timer timer = new Timer(200, new ActionListener() { - private int counter = 0; - private Object highlight = null; - - @Override - public void actionPerformed(ActionEvent event) { - if (counter % 2 == 0) { - try { - highlight = editor.getHighlighter().addHighlight(token.start, token.end, highlightPainter); - } catch (BadLocationException ex) { - // don't care - } - } else if (highlight != null) { - editor.getHighlighter().removeHighlight(highlight); - } - - if (counter++ > 6) { - Timer timer = (Timer) event.getSource(); - timer.stop(); - } - } - }); - timer.start(); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/ConnectionState.java b/src/main/java/cuchaz/enigma/gui/ConnectionState.java deleted file mode 100644 index db6590de..00000000 --- a/src/main/java/cuchaz/enigma/gui/ConnectionState.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.gui; - -public enum ConnectionState { - NOT_CONNECTED, - HOSTING, - CONNECTED, -} diff --git a/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java b/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java deleted file mode 100644 index 08df3e75..00000000 --- a/src/main/java/cuchaz/enigma/gui/DecompiledClassSource.java +++ /dev/null @@ -1,159 +0,0 @@ -package cuchaz.enigma.gui; - -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.EnigmaServices; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.analysis.Token; -import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.gui.highlight.TokenHighlightType; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.translation.LocalNameGenerator; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.LocalVariableDefEntry; - -import javax.annotation.Nullable; -import java.util.*; - -public class DecompiledClassSource { - private final ClassEntry classEntry; - - private final SourceIndex obfuscatedIndex; - private SourceIndex remappedIndex; - - private final Map> highlightedTokens = new EnumMap<>(TokenHighlightType.class); - - public DecompiledClassSource(ClassEntry classEntry, SourceIndex index) { - this.classEntry = classEntry; - this.obfuscatedIndex = index; - this.remappedIndex = index; - } - - public static DecompiledClassSource text(ClassEntry classEntry, String text) { - return new DecompiledClassSource(classEntry, new SourceIndex(text)); - } - - public void remapSource(EnigmaProject project, Translator translator) { - highlightedTokens.clear(); - - SourceRemapper remapper = new SourceRemapper(obfuscatedIndex.getSource(), obfuscatedIndex.referenceTokens()); - - SourceRemapper.Result remapResult = remapper.remap((token, movedToken) -> remapToken(project, token, movedToken, translator)); - remappedIndex = obfuscatedIndex.remapTo(remapResult); - } - - private String remapToken(EnigmaProject project, Token token, Token movedToken, Translator translator) { - EntryReference, Entry> reference = obfuscatedIndex.getReference(token); - - Entry entry = reference.getNameableEntry(); - Entry translatedEntry = translator.translate(entry); - - if (project.isRenamable(reference)) { - if (isDeobfuscated(entry, translatedEntry)) { - highlightToken(movedToken, TokenHighlightType.DEOBFUSCATED); - return translatedEntry.getSourceRemapName(); - } else { - Optional proposedName = proposeName(project, entry); - if (proposedName.isPresent()) { - highlightToken(movedToken, TokenHighlightType.PROPOSED); - return proposedName.get(); - } - - highlightToken(movedToken, TokenHighlightType.OBFUSCATED); - } - } - - String defaultName = generateDefaultName(translatedEntry); - if (defaultName != null) { - return defaultName; - } - - return null; - } - - private Optional proposeName(EnigmaProject project, Entry entry) { - EnigmaServices services = project.getEnigma().getServices(); - - return services.get(NameProposalService.TYPE).stream().flatMap(nameProposalService -> { - EntryRemapper mapper = project.getMapper(); - Collection> resolved = mapper.getObfResolver().resolveEntry(entry, ResolutionStrategy.RESOLVE_ROOT); - - return resolved.stream() - .map(e -> nameProposalService.proposeName(e, mapper)) - .filter(Optional::isPresent) - .map(Optional::get); - }).findFirst(); - } - - @Nullable - private String generateDefaultName(Entry entry) { - if (entry instanceof LocalVariableDefEntry) { - LocalVariableDefEntry localVariable = (LocalVariableDefEntry) entry; - - int index = localVariable.getIndex(); - if (localVariable.isArgument()) { - List arguments = localVariable.getParent().getDesc().getArgumentDescs(); - return LocalNameGenerator.generateArgumentName(index, localVariable.getDesc(), arguments); - } else { - return LocalNameGenerator.generateLocalVariableName(index, localVariable.getDesc()); - } - } - - return null; - } - - private boolean isDeobfuscated(Entry entry, Entry translatedEntry) { - return !entry.getName().equals(translatedEntry.getName()); - } - - public ClassEntry getEntry() { - return classEntry; - } - - public SourceIndex getIndex() { - return remappedIndex; - } - - public Map> getHighlightedTokens() { - return highlightedTokens; - } - - private void highlightToken(Token token, TokenHighlightType highlightType) { - highlightedTokens.computeIfAbsent(highlightType, t -> new ArrayList<>()).add(token); - } - - public int getObfuscatedOffset(int deobfOffset) { - return getOffset(remappedIndex, obfuscatedIndex, deobfOffset); - } - - public int getDeobfuscatedOffset(int obfOffset) { - return getOffset(obfuscatedIndex, remappedIndex, obfOffset); - } - - private static int getOffset(SourceIndex fromIndex, SourceIndex toIndex, int fromOffset) { - int relativeOffset = 0; - - Iterator fromTokenItr = fromIndex.referenceTokens().iterator(); - Iterator toTokenItr = toIndex.referenceTokens().iterator(); - while (fromTokenItr.hasNext() && toTokenItr.hasNext()) { - Token fromToken = fromTokenItr.next(); - Token toToken = toTokenItr.next(); - if (fromToken.end > fromOffset) { - break; - } - - relativeOffset = toToken.end - fromToken.end; - } - - return fromOffset + relativeOffset; - } - - @Override - public String toString() { - return remappedIndex.getSource(); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/EnigmaQuickFindDialog.java b/src/main/java/cuchaz/enigma/gui/EnigmaQuickFindDialog.java deleted file mode 100644 index c912be3a..00000000 --- a/src/main/java/cuchaz/enigma/gui/EnigmaQuickFindDialog.java +++ /dev/null @@ -1,90 +0,0 @@ -package cuchaz.enigma.gui; - -import de.sciss.syntaxpane.actions.DocumentSearchData; -import de.sciss.syntaxpane.actions.gui.QuickFindDialog; - -import javax.swing.*; -import javax.swing.text.JTextComponent; -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.stream.IntStream; -import java.util.stream.Stream; - -public class EnigmaQuickFindDialog extends QuickFindDialog { - public EnigmaQuickFindDialog(JTextComponent target) { - super(target, DocumentSearchData.getFromEditor(target)); - - JToolBar toolBar = getToolBar(); - JTextField textField = getTextField(toolBar); - - textField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - super.keyPressed(e); - if (e.getKeyCode() == KeyEvent.VK_ENTER) { - JToolBar toolBar = getToolBar(); - boolean next = !e.isShiftDown(); - JButton button = next ? getNextButton(toolBar) : getPrevButton(toolBar); - button.doClick(); - } - } - }); - } - - @Override - public void showFor(JTextComponent target) { - String selectedText = target.getSelectedText(); - - try { - super.showFor(target); - } catch (Exception e) { - e.printStackTrace(); - return; - } - - Container view = target.getParent(); - Point loc = new Point(0, view.getHeight() - getSize().height); - setLocationRelativeTo(view); - SwingUtilities.convertPointToScreen(loc, view); - setLocation(loc); - - JToolBar toolBar = getToolBar(); - JTextField textField = getTextField(toolBar); - - if (selectedText != null) { - textField.setText(selectedText); - } - - textField.selectAll(); - } - - private JToolBar getToolBar() { - return components(getContentPane(), JToolBar.class).findFirst().orElse(null); - } - - private JTextField getTextField(JToolBar toolBar) { - return components(toolBar, JTextField.class).findFirst().orElse(null); - } - - private JButton getNextButton(JToolBar toolBar) { - Stream buttons = components(toolBar, JButton.class); - return buttons.skip(1).findFirst().orElse(null); - } - - private JButton getPrevButton(JToolBar toolBar) { - Stream buttons = components(toolBar, JButton.class); - return buttons.findFirst().orElse(null); - } - - private static Stream components(Container container) { - return IntStream.range(0, container.getComponentCount()) - .mapToObj(container::getComponent); - } - - private static Stream components(Container container, Class type) { - return components(container) - .filter(type::isInstance) - .map(type::cast); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java b/src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java deleted file mode 100644 index 42eaa605..00000000 --- a/src/main/java/cuchaz/enigma/gui/EnigmaSyntaxKit.java +++ /dev/null @@ -1,44 +0,0 @@ -package cuchaz.enigma.gui; - -import cuchaz.enigma.config.Config; -import de.sciss.syntaxpane.components.LineNumbersRuler; -import de.sciss.syntaxpane.syntaxkits.JavaSyntaxKit; -import de.sciss.syntaxpane.util.Configuration; - -public class EnigmaSyntaxKit extends JavaSyntaxKit { - private static Configuration configuration = null; - - @Override - public Configuration getConfig() { - if(configuration == null){ - initConfig(super.getConfig(JavaSyntaxKit.class)); - } - return configuration; - } - - public void initConfig(Configuration baseConfig){ - configuration = baseConfig; - //See de.sciss.syntaxpane.TokenType - configuration.put("Style.KEYWORD", Config.getInstance().highlightColor + ", 0"); - configuration.put("Style.KEYWORD2", Config.getInstance().highlightColor + ", 3"); - configuration.put("Style.STRING", Config.getInstance().stringColor + ", 0"); - configuration.put("Style.STRING2", Config.getInstance().stringColor + ", 1"); - configuration.put("Style.NUMBER", Config.getInstance().numberColor + ", 1"); - configuration.put("Style.OPERATOR", Config.getInstance().operatorColor + ", 0"); - configuration.put("Style.DELIMITER", Config.getInstance().delimiterColor + ", 1"); - configuration.put("Style.TYPE", Config.getInstance().typeColor + ", 2"); - configuration.put("Style.TYPE2", Config.getInstance().typeColor + ", 1"); - configuration.put("Style.IDENTIFIER", Config.getInstance().identifierColor + ", 0"); - configuration.put("Style.DEFAULT", Config.getInstance().defaultTextColor + ", 0"); - configuration.put(LineNumbersRuler.PROPERTY_BACKGROUND, Config.getInstance().lineNumbersBackground + ""); - configuration.put(LineNumbersRuler.PROPERTY_FOREGROUND, Config.getInstance().lineNumbersForeground + ""); - configuration.put(LineNumbersRuler.PROPERTY_CURRENT_BACK, Config.getInstance().lineNumbersSelected + ""); - configuration.put("RightMarginColumn", "999"); //No need to have a right margin, if someone wants it add a config - - configuration.put("Action.quick-find", "cuchaz.enigma.gui.QuickFindAction, menu F"); - } - - public static void invalidate(){ - configuration = null; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/Gui.java b/src/main/java/cuchaz/enigma/gui/Gui.java deleted file mode 100644 index ed32469e..00000000 --- a/src/main/java/cuchaz/enigma/gui/Gui.java +++ /dev/null @@ -1,1058 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui; - -import java.awt.*; -import java.awt.event.*; -import java.nio.file.Path; -import java.util.List; -import java.util.*; -import java.util.function.Function; - -import javax.swing.*; -import javax.swing.text.BadLocationException; -import javax.swing.text.Highlighter; -import javax.swing.tree.*; - -import com.google.common.base.Strings; -import com.google.common.collect.Lists; -import cuchaz.enigma.Constants; -import cuchaz.enigma.EnigmaProfile; -import cuchaz.enigma.ExceptionIgnorer; -import cuchaz.enigma.analysis.*; -import cuchaz.enigma.config.Config; -import cuchaz.enigma.config.Themes; -import cuchaz.enigma.gui.dialog.CrashDialog; -import cuchaz.enigma.gui.dialog.JavadocDialog; -import cuchaz.enigma.gui.dialog.SearchDialog; -import cuchaz.enigma.gui.elements.CollapsibleTabbedPane; -import cuchaz.enigma.gui.elements.MenuBar; -import cuchaz.enigma.gui.elements.PopupMenuBar; -import cuchaz.enigma.gui.filechooser.FileChooserAny; -import cuchaz.enigma.gui.filechooser.FileChooserFolder; -import cuchaz.enigma.gui.highlight.BoxHighlightPainter; -import cuchaz.enigma.gui.highlight.SelectionHighlightPainter; -import cuchaz.enigma.gui.highlight.TokenHighlightType; -import cuchaz.enigma.gui.panels.PanelDeobf; -import cuchaz.enigma.gui.panels.PanelEditor; -import cuchaz.enigma.gui.panels.PanelIdentifier; -import cuchaz.enigma.gui.panels.PanelObf; -import cuchaz.enigma.gui.util.History; -import cuchaz.enigma.network.packet.*; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.mapping.*; -import cuchaz.enigma.translation.representation.entry.*; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.Message; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; -import de.sciss.syntaxpane.DefaultSyntaxKit; - -public class Gui { - - public final PopupMenuBar popupMenu; - private final PanelObf obfPanel; - private final PanelDeobf deobfPanel; - - private final MenuBar menuBar; - // state - public History, Entry>> referenceHistory; - public EntryReference, Entry> renamingReference; - public EntryReference, Entry> cursorReference; - private boolean shouldNavigateOnClick; - private ConnectionState connectionState; - private boolean isJarOpen; - - public FileDialog jarFileChooser; - public FileDialog tinyMappingsFileChooser; - public SearchDialog searchDialog; - public JFileChooser enigmaMappingsFileChooser; - public JFileChooser exportSourceFileChooser; - public FileDialog exportJarFileChooser; - private GuiController controller; - private JFrame frame; - public Config.LookAndFeel editorFeel; - public PanelEditor editor; - public JScrollPane sourceScroller; - private JPanel classesPanel; - private JSplitPane splitClasses; - private PanelIdentifier infoPanel; - public Map boxHighlightPainters; - private SelectionHighlightPainter selectionHighlightPainter; - private JTree inheritanceTree; - private JTree implementationsTree; - private JTree callsTree; - private JList tokens; - private JTabbedPane tabs; - - private JSplitPane splitRight; - private JSplitPane logSplit; - private CollapsibleTabbedPane logTabs; - private JList users; - private DefaultListModel userModel; - private JScrollPane messageScrollPane; - private JList messages; - private DefaultListModel messageModel; - private JTextField chatBox; - - private JPanel statusBar; - private JLabel connectionStatusLabel; - private JLabel statusLabel; - - public JTextField renameTextField; - public JTextArea javadocTextArea; - - public void setEditorTheme(Config.LookAndFeel feel) { - if (editor != null && (editorFeel == null || editorFeel != feel)) { - editor.updateUI(); - editor.setBackground(new Color(Config.getInstance().editorBackground)); - if (editorFeel != null) { - getController().refreshCurrentClass(); - } - - editorFeel = feel; - } - } - - public Gui(EnigmaProfile profile) { - Config.getInstance().lookAndFeel.setGlobalLAF(); - - // init frame - this.frame = new JFrame(Constants.NAME); - final Container pane = this.frame.getContentPane(); - pane.setLayout(new BorderLayout()); - - if (Boolean.parseBoolean(System.getProperty("enigma.catchExceptions", "true"))) { - // install a global exception handler to the event thread - CrashDialog.init(this.frame); - Thread.setDefaultUncaughtExceptionHandler((thread, t) -> { - t.printStackTrace(System.err); - if (!ExceptionIgnorer.shouldIgnore(t)) { - CrashDialog.show(t); - } - }); - } - - this.controller = new GuiController(this, profile); - - Themes.updateTheme(this); - - // init file choosers - this.jarFileChooser = new FileDialog(getFrame(), I18n.translate("menu.file.jar.open"), FileDialog.LOAD); - - this.tinyMappingsFileChooser = new FileDialog(getFrame(), "Open tiny Mappings", FileDialog.LOAD); - this.enigmaMappingsFileChooser = new FileChooserAny(); - this.exportSourceFileChooser = new FileChooserFolder(); - this.exportJarFileChooser = new FileDialog(getFrame(), I18n.translate("menu.file.export.jar"), FileDialog.SAVE); - - this.obfPanel = new PanelObf(this); - this.deobfPanel = new PanelDeobf(this); - - // set up classes panel (don't add the splitter yet) - splitClasses = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, this.obfPanel, this.deobfPanel); - splitClasses.setResizeWeight(0.3); - this.classesPanel = new JPanel(); - this.classesPanel.setLayout(new BorderLayout()); - this.classesPanel.setPreferredSize(ScaleUtil.getDimension(250, 0)); - - // init info panel - infoPanel = new PanelIdentifier(this); - infoPanel.clearReference(); - - // init editor - selectionHighlightPainter = new SelectionHighlightPainter(); - this.editor = new PanelEditor(this); - this.sourceScroller = new JScrollPane(this.editor); - this.editor.setContentType("text/enigma-sources"); - this.editor.setBackground(new Color(Config.getInstance().editorBackground)); - DefaultSyntaxKit kit = (DefaultSyntaxKit) this.editor.getEditorKit(); - kit.toggleComponent(this.editor, "de.sciss.syntaxpane.components.TokenMarker"); - - // init editor popup menu - this.popupMenu = new PopupMenuBar(this); - this.editor.setComponentPopupMenu(this.popupMenu); - - // init inheritance panel - inheritanceTree = new JTree(); - inheritanceTree.setModel(null); - inheritanceTree.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { - // get the selected node - TreePath path = inheritanceTree.getSelectionPath(); - if (path == null) { - return; - } - - Object node = path.getLastPathComponent(); - if (node instanceof ClassInheritanceTreeNode) { - ClassInheritanceTreeNode classNode = (ClassInheritanceTreeNode) node; - controller.navigateTo(new ClassEntry(classNode.getObfClassName())); - } else if (node instanceof MethodInheritanceTreeNode) { - MethodInheritanceTreeNode methodNode = (MethodInheritanceTreeNode) node; - if (methodNode.isImplemented()) { - controller.navigateTo(methodNode.getMethodEntry()); - } - } - } - } - }); - TreeCellRenderer cellRenderer = inheritanceTree.getCellRenderer(); - inheritanceTree.setCellRenderer(new MethodTreeCellRenderer(cellRenderer)); - - JPanel inheritancePanel = new JPanel(); - inheritancePanel.setLayout(new BorderLayout()); - inheritancePanel.add(new JScrollPane(inheritanceTree)); - - // init implementations panel - implementationsTree = new JTree(); - implementationsTree.setModel(null); - implementationsTree.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { - // get the selected node - TreePath path = implementationsTree.getSelectionPath(); - if (path == null) { - return; - } - - Object node = path.getLastPathComponent(); - if (node instanceof ClassImplementationsTreeNode) { - ClassImplementationsTreeNode classNode = (ClassImplementationsTreeNode) node; - controller.navigateTo(classNode.getClassEntry()); - } else if (node instanceof MethodImplementationsTreeNode) { - MethodImplementationsTreeNode methodNode = (MethodImplementationsTreeNode) node; - controller.navigateTo(methodNode.getMethodEntry()); - } - } - } - }); - JPanel implementationsPanel = new JPanel(); - implementationsPanel.setLayout(new BorderLayout()); - implementationsPanel.add(new JScrollPane(implementationsTree)); - - // init call panel - callsTree = new JTree(); - callsTree.setModel(null); - callsTree.addMouseListener(new MouseAdapter() { - @SuppressWarnings("unchecked") - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() >= 2) { - // get the selected node - TreePath path = callsTree.getSelectionPath(); - if (path == null) { - return; - } - - Object node = path.getLastPathComponent(); - if (node instanceof ReferenceTreeNode) { - ReferenceTreeNode, Entry> referenceNode = ((ReferenceTreeNode, Entry>) node); - if (referenceNode.getReference() != null) { - controller.navigateTo(referenceNode.getReference()); - } else { - controller.navigateTo(referenceNode.getEntry()); - } - } - } - } - }); - tokens = new JList<>(); - tokens.setCellRenderer(new TokenListCellRenderer(this.controller)); - tokens.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - tokens.setLayoutOrientation(JList.VERTICAL); - tokens.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent event) { - if (event.getClickCount() == 2) { - Token selected = tokens.getSelectedValue(); - if (selected != null) { - showToken(selected); - } - } - } - }); - tokens.setPreferredSize(ScaleUtil.getDimension(0, 200)); - tokens.setMinimumSize(ScaleUtil.getDimension(0, 200)); - JSplitPane callPanel = new JSplitPane( - JSplitPane.VERTICAL_SPLIT, - true, - new JScrollPane(callsTree), - new JScrollPane(tokens) - ); - callPanel.setResizeWeight(1); // let the top side take all the slack - callPanel.resetToPreferredSizes(); - - // layout controls - JPanel centerPanel = new JPanel(); - centerPanel.setLayout(new BorderLayout()); - centerPanel.add(infoPanel, BorderLayout.NORTH); - centerPanel.add(sourceScroller, BorderLayout.CENTER); - tabs = new JTabbedPane(); - tabs.setPreferredSize(ScaleUtil.getDimension(250, 0)); - tabs.addTab(I18n.translate("info_panel.tree.inheritance"), inheritancePanel); - tabs.addTab(I18n.translate("info_panel.tree.implementations"), implementationsPanel); - tabs.addTab(I18n.translate("info_panel.tree.calls"), callPanel); - logTabs = new CollapsibleTabbedPane(JTabbedPane.BOTTOM); - userModel = new DefaultListModel<>(); - users = new JList<>(userModel); - messageModel = new DefaultListModel<>(); - messages = new JList<>(messageModel); - messages.setCellRenderer(new MessageListCellRenderer()); - JPanel messagePanel = new JPanel(new BorderLayout()); - messageScrollPane = new JScrollPane(this.messages); - messagePanel.add(messageScrollPane, BorderLayout.CENTER); - JPanel chatPanel = new JPanel(new BorderLayout()); - chatBox = new JTextField(); - AbstractAction sendListener = new AbstractAction("Send") { - @Override - public void actionPerformed(ActionEvent e) { - sendMessage(); - } - }; - chatBox.addActionListener(sendListener); - JButton chatSendButton = new JButton(sendListener); - chatPanel.add(chatBox, BorderLayout.CENTER); - chatPanel.add(chatSendButton, BorderLayout.EAST); - messagePanel.add(chatPanel, BorderLayout.SOUTH); - logTabs.addTab(I18n.translate("log_panel.users"), new JScrollPane(this.users)); - logTabs.addTab(I18n.translate("log_panel.messages"), messagePanel); - logSplit = new JSplitPane(JSplitPane.VERTICAL_SPLIT, true, tabs, logTabs); - logSplit.setResizeWeight(0.5); - logSplit.resetToPreferredSizes(); - splitRight = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, centerPanel, this.logSplit); - splitRight.setResizeWeight(1); // let the left side take all the slack - splitRight.resetToPreferredSizes(); - JSplitPane splitCenter = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, true, this.classesPanel, splitRight); - splitCenter.setResizeWeight(0); // let the right side take all the slack - pane.add(splitCenter, BorderLayout.CENTER); - - // init menus - this.menuBar = new MenuBar(this); - this.frame.setJMenuBar(this.menuBar); - - // init status bar - statusBar = new JPanel(new BorderLayout()); - statusBar.setBorder(BorderFactory.createLoweredBevelBorder()); - connectionStatusLabel = new JLabel(); - statusLabel = new JLabel(); - statusBar.add(statusLabel, BorderLayout.CENTER); - statusBar.add(connectionStatusLabel, BorderLayout.EAST); - pane.add(statusBar, BorderLayout.SOUTH); - - // init state - setConnectionState(ConnectionState.NOT_CONNECTED); - onCloseJar(); - - this.frame.addWindowListener(new WindowAdapter() { - @Override - public void windowClosing(WindowEvent event) { - close(); - } - }); - - // show the frame - pane.doLayout(); - this.frame.setSize(ScaleUtil.getDimension(1024, 576)); - this.frame.setMinimumSize(ScaleUtil.getDimension(640, 480)); - this.frame.setVisible(true); - this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - this.frame.setLocationRelativeTo(null); - } - - public JFrame getFrame() { - return this.frame; - } - - public GuiController getController() { - return this.controller; - } - - public void onStartOpenJar() { - this.classesPanel.removeAll(); - redraw(); - } - - public void onFinishOpenJar(String jarName) { - // update gui - this.frame.setTitle(Constants.NAME + " - " + jarName); - this.classesPanel.removeAll(); - this.classesPanel.add(splitClasses); - setEditorText(null); - - // update menu - isJarOpen = true; - - updateUiState(); - redraw(); - } - - public void onCloseJar() { - - // update gui - this.frame.setTitle(Constants.NAME); - setObfClasses(null); - setDeobfClasses(null); - setEditorText(null); - this.classesPanel.removeAll(); - - // update menu - isJarOpen = false; - setMappingsFile(null); - - updateUiState(); - redraw(); - } - - public void setObfClasses(Collection obfClasses) { - this.obfPanel.obfClasses.setClasses(obfClasses); - } - - public void setDeobfClasses(Collection deobfClasses) { - this.deobfPanel.deobfClasses.setClasses(deobfClasses); - } - - public void setMappingsFile(Path path) { - this.enigmaMappingsFileChooser.setSelectedFile(path != null ? path.toFile() : null); - updateUiState(); - } - - public void setEditorText(String source) { - this.editor.getHighlighter().removeAllHighlights(); - this.editor.setText(source); - } - - public void setSource(DecompiledClassSource source) { - editor.setText(source.toString()); - setHighlightedTokens(source.getHighlightedTokens()); - } - - public void showToken(final Token token) { - if (token == null) { - throw new IllegalArgumentException("Token cannot be null!"); - } - CodeReader.navigateToToken(this.editor, token, selectionHighlightPainter); - redraw(); - } - - public void showTokens(Collection tokens) { - Vector sortedTokens = new Vector<>(tokens); - Collections.sort(sortedTokens); - if (sortedTokens.size() > 1) { - // sort the tokens and update the tokens panel - this.tokens.setListData(sortedTokens); - this.tokens.setSelectedIndex(0); - } else { - this.tokens.setListData(new Vector<>()); - } - - // show the first token - showToken(sortedTokens.get(0)); - } - - public void setHighlightedTokens(Map> tokens) { - // remove any old highlighters - this.editor.getHighlighter().removeAllHighlights(); - - if (boxHighlightPainters != null) { - for (TokenHighlightType type : tokens.keySet()) { - BoxHighlightPainter painter = boxHighlightPainters.get(type); - if (painter != null) { - setHighlightedTokens(tokens.get(type), painter); - } - } - } - - redraw(); - } - - private void setHighlightedTokens(Iterable tokens, Highlighter.HighlightPainter painter) { - for (Token token : tokens) { - try { - this.editor.getHighlighter().addHighlight(token.start, token.end, painter); - } catch (BadLocationException ex) { - throw new IllegalArgumentException(ex); - } - } - } - - private void showCursorReference(EntryReference, Entry> reference) { - if (reference == null) { - infoPanel.clearReference(); - return; - } - - this.cursorReference = reference; - - EntryReference, Entry> translatedReference = controller.project.getMapper().deobfuscate(reference); - - infoPanel.removeAll(); - if (translatedReference.entry instanceof ClassEntry) { - showClassEntry((ClassEntry) translatedReference.entry); - } else if (translatedReference.entry instanceof FieldEntry) { - showFieldEntry((FieldEntry) translatedReference.entry); - } else if (translatedReference.entry instanceof MethodEntry) { - showMethodEntry((MethodEntry) translatedReference.entry); - } else if (translatedReference.entry instanceof LocalVariableEntry) { - showLocalVariableEntry((LocalVariableEntry) translatedReference.entry); - } else { - throw new Error("Unknown entry desc: " + translatedReference.entry.getClass().getName()); - } - - redraw(); - } - - private void showLocalVariableEntry(LocalVariableEntry entry) { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.variable"), entry.getName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.class"), entry.getContainingClass().getFullName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.method"), entry.getParent().getName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.index"), Integer.toString(entry.getIndex())); - } - - private void showClassEntry(ClassEntry entry) { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.class"), entry.getFullName()); - addModifierComboBox(infoPanel, I18n.translate("info_panel.identifier.modifier"), entry); - } - - private void showFieldEntry(FieldEntry entry) { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.field"), entry.getName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.class"), entry.getParent().getFullName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.type_descriptor"), entry.getDesc().toString()); - addModifierComboBox(infoPanel, I18n.translate("info_panel.identifier.modifier"), entry); - } - - private void showMethodEntry(MethodEntry entry) { - if (entry.isConstructor()) { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.constructor"), entry.getParent().getFullName()); - } else { - addNameValue(infoPanel, I18n.translate("info_panel.identifier.method"), entry.getName()); - addNameValue(infoPanel, I18n.translate("info_panel.identifier.class"), entry.getParent().getFullName()); - } - addNameValue(infoPanel, I18n.translate("info_panel.identifier.method_descriptor"), entry.getDesc().toString()); - addModifierComboBox(infoPanel, I18n.translate("info_panel.identifier.modifier"), entry); - } - - private void addNameValue(JPanel container, String name, String value) { - JPanel panel = new JPanel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0)); - - JLabel label = new JLabel(name + ":", JLabel.RIGHT); - label.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height))); - panel.add(label); - - panel.add(Utils.unboldLabel(new JLabel(value, JLabel.LEFT))); - - container.add(panel); - } - - private JComboBox addModifierComboBox(JPanel container, String name, Entry entry) { - if (!getController().project.isRenamable(entry)) - return null; - JPanel panel = new JPanel(); - panel.setLayout(new FlowLayout(FlowLayout.LEFT, 6, 0)); - JLabel label = new JLabel(name + ":", JLabel.RIGHT); - label.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height))); - panel.add(label); - JComboBox combo = new JComboBox<>(AccessModifier.values()); - ((JLabel) combo.getRenderer()).setHorizontalAlignment(JLabel.LEFT); - combo.setPreferredSize(ScaleUtil.getDimension(100, ScaleUtil.invert(label.getPreferredSize().height))); - - EntryMapping mapping = controller.project.getMapper().getDeobfMapping(entry); - if (mapping != null) { - combo.setSelectedIndex(mapping.getAccessModifier().ordinal()); - } else { - combo.setSelectedIndex(AccessModifier.UNCHANGED.ordinal()); - } - - combo.addItemListener(controller::modifierChange); - - panel.add(combo); - - container.add(panel); - - return combo; - } - - public void onCaretMove(int pos, boolean fromClick) { - if (controller.project == null) - return; - EntryRemapper mapper = controller.project.getMapper(); - Token token = this.controller.getToken(pos); - boolean isToken = token != null; - - cursorReference = this.controller.getReference(token); - Entry referenceEntry = cursorReference != null ? cursorReference.entry : null; - - if (referenceEntry != null && shouldNavigateOnClick && fromClick) { - shouldNavigateOnClick = false; - Entry navigationEntry = referenceEntry; - if (cursorReference.context == null) { - EntryResolver resolver = mapper.getObfResolver(); - navigationEntry = resolver.resolveFirstEntry(referenceEntry, ResolutionStrategy.RESOLVE_ROOT); - } - controller.navigateTo(navigationEntry); - return; - } - - boolean isClassEntry = isToken && referenceEntry instanceof ClassEntry; - boolean isFieldEntry = isToken && referenceEntry instanceof FieldEntry; - boolean isMethodEntry = isToken && referenceEntry instanceof MethodEntry && !((MethodEntry) referenceEntry).isConstructor(); - boolean isConstructorEntry = isToken && referenceEntry instanceof MethodEntry && ((MethodEntry) referenceEntry).isConstructor(); - boolean isRenamable = isToken && this.controller.project.isRenamable(cursorReference); - - if (!isRenaming()) { - if (isToken) { - showCursorReference(cursorReference); - } else { - infoPanel.clearReference(); - } - } - - this.popupMenu.renameMenu.setEnabled(isRenamable); - this.popupMenu.editJavadocMenu.setEnabled(isRenamable); - this.popupMenu.showInheritanceMenu.setEnabled(isClassEntry || isMethodEntry || isConstructorEntry); - this.popupMenu.showImplementationsMenu.setEnabled(isClassEntry || isMethodEntry); - this.popupMenu.showCallsMenu.setEnabled(isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry); - this.popupMenu.showCallsSpecificMenu.setEnabled(isMethodEntry); - this.popupMenu.openEntryMenu.setEnabled(isRenamable && (isClassEntry || isFieldEntry || isMethodEntry || isConstructorEntry)); - this.popupMenu.openPreviousMenu.setEnabled(this.controller.hasPreviousReference()); - this.popupMenu.openNextMenu.setEnabled(this.controller.hasNextReference()); - this.popupMenu.toggleMappingMenu.setEnabled(isRenamable); - - if (isToken && !Objects.equals(referenceEntry, mapper.deobfuscate(referenceEntry))) { - this.popupMenu.toggleMappingMenu.setText(I18n.translate("popup_menu.reset_obfuscated")); - } else { - this.popupMenu.toggleMappingMenu.setText(I18n.translate("popup_menu.mark_deobfuscated")); - } - } - - public void startDocChange() { - EntryReference, Entry> curReference = cursorReference; - if (isRenaming()) { - finishRename(false); - } - renamingReference = curReference; - - // init the text box - javadocTextArea = new JTextArea(10, 40); - - EntryReference, Entry> translatedReference = controller.project.getMapper().deobfuscate(cursorReference); - javadocTextArea.setText(Strings.nullToEmpty(translatedReference.entry.getJavadocs())); - - JavadocDialog.init(frame, javadocTextArea, this::finishDocChange); - javadocTextArea.grabFocus(); - - redraw(); - } - - private void finishDocChange(JFrame ui, boolean saveName) { - String newName = javadocTextArea.getText(); - if (saveName) { - try { - this.controller.changeDocs(renamingReference, newName); - this.controller.sendPacket(new ChangeDocsC2SPacket(renamingReference.getNameableEntry(), newName)); - } catch (IllegalNameException ex) { - javadocTextArea.setBorder(BorderFactory.createLineBorder(Color.red, 1)); - javadocTextArea.setToolTipText(ex.getReason()); - Utils.showToolTipNow(javadocTextArea); - return; - } - - ui.setVisible(false); - showCursorReference(cursorReference); - return; - } - - // abort the jd change - javadocTextArea = null; - ui.setVisible(false); - showCursorReference(cursorReference); - - this.editor.grabFocus(); - - redraw(); - } - - public void startRename() { - - // init the text box - renameTextField = new JTextField(); - - EntryReference, Entry> translatedReference = controller.project.getMapper().deobfuscate(cursorReference); - renameTextField.setText(translatedReference.getNameableName()); - - renameTextField.setPreferredSize(ScaleUtil.getDimension(360, ScaleUtil.invert(renameTextField.getPreferredSize().height))); - renameTextField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - switch (event.getKeyCode()) { - case KeyEvent.VK_ENTER: - finishRename(true); - break; - - case KeyEvent.VK_ESCAPE: - finishRename(false); - break; - default: - break; - } - } - }); - - // find the label with the name and replace it with the text box - JPanel panel = (JPanel) infoPanel.getComponent(0); - panel.remove(panel.getComponentCount() - 1); - panel.add(renameTextField); - renameTextField.grabFocus(); - - int offset = renameTextField.getText().lastIndexOf('/') + 1; - // If it's a class and isn't in the default package, assume that it's deobfuscated. - if (translatedReference.getNameableEntry() instanceof ClassEntry && renameTextField.getText().contains("/") && offset != 0) - renameTextField.select(offset, renameTextField.getText().length()); - else - renameTextField.selectAll(); - - renamingReference = cursorReference; - - redraw(); - } - - private void finishRename(boolean saveName) { - String newName = renameTextField.getText(); - - if (saveName && newName != null && !newName.isEmpty()) { - try { - this.controller.rename(renamingReference, newName, true); - this.controller.sendPacket(new RenameC2SPacket(renamingReference.getNameableEntry(), newName, true)); - renameTextField = null; - } catch (IllegalNameException ex) { - renameTextField.setBorder(BorderFactory.createLineBorder(Color.red, 1)); - renameTextField.setToolTipText(ex.getReason()); - Utils.showToolTipNow(renameTextField); - } - return; - } - - renameTextField = null; - - // abort the rename - showCursorReference(cursorReference); - - this.editor.grabFocus(); - - redraw(); - } - - private boolean isRenaming() { - return renameTextField != null; - } - - public void showInheritance() { - - if (cursorReference == null) { - return; - } - - inheritanceTree.setModel(null); - - if (cursorReference.entry instanceof ClassEntry) { - // get the class inheritance - ClassInheritanceTreeNode classNode = this.controller.getClassInheritance((ClassEntry) cursorReference.entry); - - // show the tree at the root - TreePath path = getPathToRoot(classNode); - inheritanceTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); - inheritanceTree.expandPath(path); - inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path)); - } else if (cursorReference.entry instanceof MethodEntry) { - // get the method inheritance - MethodInheritanceTreeNode classNode = this.controller.getMethodInheritance((MethodEntry) cursorReference.entry); - - // show the tree at the root - TreePath path = getPathToRoot(classNode); - inheritanceTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); - inheritanceTree.expandPath(path); - inheritanceTree.setSelectionRow(inheritanceTree.getRowForPath(path)); - } - - tabs.setSelectedIndex(0); - - redraw(); - } - - public void showImplementations() { - - if (cursorReference == null) { - return; - } - - implementationsTree.setModel(null); - - DefaultMutableTreeNode node = null; - - // get the class implementations - if (cursorReference.entry instanceof ClassEntry) - node = this.controller.getClassImplementations((ClassEntry) cursorReference.entry); - else // get the method implementations - if (cursorReference.entry instanceof MethodEntry) - node = this.controller.getMethodImplementations((MethodEntry) cursorReference.entry); - - if (node != null) { - // show the tree at the root - TreePath path = getPathToRoot(node); - implementationsTree.setModel(new DefaultTreeModel((TreeNode) path.getPathComponent(0))); - implementationsTree.expandPath(path); - implementationsTree.setSelectionRow(implementationsTree.getRowForPath(path)); - } - - tabs.setSelectedIndex(1); - - redraw(); - } - - public void showCalls(boolean recurse) { - if (cursorReference == null) { - return; - } - - if (cursorReference.entry instanceof ClassEntry) { - ClassReferenceTreeNode node = this.controller.getClassReferences((ClassEntry) cursorReference.entry); - callsTree.setModel(new DefaultTreeModel(node)); - } else if (cursorReference.entry instanceof FieldEntry) { - FieldReferenceTreeNode node = this.controller.getFieldReferences((FieldEntry) cursorReference.entry); - callsTree.setModel(new DefaultTreeModel(node)); - } else if (cursorReference.entry instanceof MethodEntry) { - MethodReferenceTreeNode node = this.controller.getMethodReferences((MethodEntry) cursorReference.entry, recurse); - callsTree.setModel(new DefaultTreeModel(node)); - } - - tabs.setSelectedIndex(2); - - redraw(); - } - - public void toggleMapping() { - Entry obfEntry = cursorReference.entry; - Entry deobfEntry = controller.project.getMapper().deobfuscate(obfEntry); - - if (!Objects.equals(obfEntry, deobfEntry)) { - this.controller.removeMapping(cursorReference); - this.controller.sendPacket(new RemoveMappingC2SPacket(cursorReference.getNameableEntry())); - } else { - this.controller.markAsDeobfuscated(cursorReference); - this.controller.sendPacket(new MarkDeobfuscatedC2SPacket(cursorReference.getNameableEntry())); - } - } - - private TreePath getPathToRoot(TreeNode node) { - List nodes = Lists.newArrayList(); - TreeNode n = node; - do { - nodes.add(n); - n = n.getParent(); - } while (n != null); - Collections.reverse(nodes); - return new TreePath(nodes.toArray()); - } - - public void showDiscardDiag(Function callback, String... options) { - int response = JOptionPane.showOptionDialog(this.frame, I18n.translate("prompt.close.summary"), I18n.translate("prompt.close.title"), JOptionPane.YES_NO_CANCEL_OPTION, - JOptionPane.QUESTION_MESSAGE, null, options, options[2]); - callback.apply(response); - } - - public void saveMapping() { - if (this.enigmaMappingsFileChooser.getSelectedFile() != null || this.enigmaMappingsFileChooser.showSaveDialog(this.frame) == JFileChooser.APPROVE_OPTION) - this.controller.saveMappings(this.enigmaMappingsFileChooser.getSelectedFile().toPath()); - } - - public void close() { - if (!this.controller.isDirty()) { - // everything is saved, we can exit safely - exit(); - } else { - // ask to save before closing - showDiscardDiag((response) -> { - if (response == JOptionPane.YES_OPTION) { - this.saveMapping(); - exit(); - } else if (response == JOptionPane.NO_OPTION) { - exit(); - } - - return null; - }, I18n.translate("prompt.close.save"), I18n.translate("prompt.close.discard"), I18n.translate("prompt.close.cancel")); - } - } - - private void exit() { - if (searchDialog != null) { - searchDialog.dispose(); - } - this.frame.dispose(); - System.exit(0); - } - - public void redraw() { - this.frame.validate(); - this.frame.repaint(); - } - - public void onPanelRename(Object prevData, Object data, DefaultMutableTreeNode node) throws IllegalNameException { - // package rename - if (data instanceof String) { - for (int i = 0; i < node.getChildCount(); i++) { - DefaultMutableTreeNode childNode = (DefaultMutableTreeNode) node.getChildAt(i); - ClassEntry prevDataChild = (ClassEntry) childNode.getUserObject(); - ClassEntry dataChild = new ClassEntry(data + "/" + prevDataChild.getSimpleName()); - this.controller.rename(new EntryReference<>(prevDataChild, prevDataChild.getFullName()), dataChild.getFullName(), false); - this.controller.sendPacket(new RenameC2SPacket(prevDataChild, dataChild.getFullName(), false)); - childNode.setUserObject(dataChild); - } - node.setUserObject(data); - // Ob package will never be modified, just reload deob view - this.deobfPanel.deobfClasses.reload(); - } - // class rename - else if (data instanceof ClassEntry) { - this.controller.rename(new EntryReference<>((ClassEntry) prevData, ((ClassEntry) prevData).getFullName()), ((ClassEntry) data).getFullName(), false); - this.controller.sendPacket(new RenameC2SPacket((ClassEntry) prevData, ((ClassEntry) data).getFullName(), false)); - } - } - - public void moveClassTree(EntryReference, Entry> obfReference, String newName) { - String oldEntry = obfReference.entry.getContainingClass().getPackageName(); - String newEntry = new ClassEntry(newName).getPackageName(); - moveClassTree(obfReference, oldEntry == null, newEntry == null); - } - - // TODO: getExpansionState will *not* actually update itself based on name changes! - public void moveClassTree(EntryReference, Entry> obfReference, boolean isOldOb, boolean isNewOb) { - ClassEntry classEntry = obfReference.entry.getContainingClass(); - - List stateDeobf = this.deobfPanel.deobfClasses.getExpansionState(this.deobfPanel.deobfClasses); - List stateObf = this.obfPanel.obfClasses.getExpansionState(this.obfPanel.obfClasses); - - // Ob -> deob - if (!isNewOb) { - this.deobfPanel.deobfClasses.moveClassIn(classEntry); - this.obfPanel.obfClasses.moveClassOut(classEntry); - this.deobfPanel.deobfClasses.reload(); - this.obfPanel.obfClasses.reload(); - } - // Deob -> ob - else if (!isOldOb) { - this.obfPanel.obfClasses.moveClassIn(classEntry); - this.deobfPanel.deobfClasses.moveClassOut(classEntry); - this.deobfPanel.deobfClasses.reload(); - this.obfPanel.obfClasses.reload(); - } - // Local move - else if (isOldOb) { - this.obfPanel.obfClasses.moveClassIn(classEntry); - this.obfPanel.obfClasses.reload(); - } else { - this.deobfPanel.deobfClasses.moveClassIn(classEntry); - this.deobfPanel.deobfClasses.reload(); - } - - this.deobfPanel.deobfClasses.restoreExpansionState(this.deobfPanel.deobfClasses, stateDeobf); - this.obfPanel.obfClasses.restoreExpansionState(this.obfPanel.obfClasses, stateObf); - } - - public PanelObf getObfPanel() { - return obfPanel; - } - - public PanelDeobf getDeobfPanel() { - return deobfPanel; - } - - public void setShouldNavigateOnClick(boolean shouldNavigateOnClick) { - this.shouldNavigateOnClick = shouldNavigateOnClick; - } - - public SearchDialog getSearchDialog() { - if (searchDialog == null) { - searchDialog = new SearchDialog(this); - } - return searchDialog; - } - - - public MenuBar getMenuBar() { - return menuBar; - } - - public void addMessage(Message message) { - JScrollBar verticalScrollBar = messageScrollPane.getVerticalScrollBar(); - boolean isAtBottom = verticalScrollBar.getValue() >= verticalScrollBar.getMaximum() - verticalScrollBar.getModel().getExtent(); - messageModel.addElement(message); - if (isAtBottom) { - SwingUtilities.invokeLater(() -> verticalScrollBar.setValue(verticalScrollBar.getMaximum() - verticalScrollBar.getModel().getExtent())); - } - statusLabel.setText(message.translate()); - } - - public void setUserList(List users) { - userModel.clear(); - users.forEach(userModel::addElement); - connectionStatusLabel.setText(String.format(I18n.translate("status.connected_user_count"), users.size())); - } - - private void sendMessage() { - String text = chatBox.getText().trim(); - if (!text.isEmpty()) { - getController().sendPacket(new MessageC2SPacket(text)); - } - chatBox.setText(""); - } - - /** - * Updates the state of the UI elements (button text, enabled state, ...) to reflect the current program state. - * This is a central place to update the UI state to prevent multiple code paths from changing the same state, - * causing inconsistencies. - */ - public void updateUiState() { - menuBar.connectToServerMenu.setEnabled(isJarOpen && connectionState != ConnectionState.HOSTING); - menuBar.connectToServerMenu.setText(I18n.translate(connectionState != ConnectionState.CONNECTED ? "menu.collab.connect" : "menu.collab.disconnect")); - menuBar.startServerMenu.setEnabled(isJarOpen && connectionState != ConnectionState.CONNECTED); - menuBar.startServerMenu.setText(I18n.translate(connectionState != ConnectionState.HOSTING ? "menu.collab.server.start" : "menu.collab.server.stop")); - - menuBar.closeJarMenu.setEnabled(isJarOpen); - menuBar.openMappingsMenus.forEach(item -> item.setEnabled(isJarOpen)); - menuBar.saveMappingsMenu.setEnabled(isJarOpen && enigmaMappingsFileChooser.getSelectedFile() != null && connectionState != ConnectionState.CONNECTED); - menuBar.saveMappingsMenus.forEach(item -> item.setEnabled(isJarOpen)); - menuBar.closeMappingsMenu.setEnabled(isJarOpen); - menuBar.exportSourceMenu.setEnabled(isJarOpen); - menuBar.exportJarMenu.setEnabled(isJarOpen); - - connectionStatusLabel.setText(I18n.translate(connectionState == ConnectionState.NOT_CONNECTED ? "status.disconnected" : "status.connected")); - - if (connectionState == ConnectionState.NOT_CONNECTED) { - logSplit.setLeftComponent(null); - splitRight.setRightComponent(tabs); - } else { - splitRight.setRightComponent(logSplit); - logSplit.setLeftComponent(tabs); - } - } - - public void setConnectionState(ConnectionState state) { - connectionState = state; - statusLabel.setText(I18n.translate("status.ready")); - updateUiState(); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/GuiController.java b/src/main/java/cuchaz/enigma/gui/GuiController.java deleted file mode 100644 index cccc9e8a..00000000 --- a/src/main/java/cuchaz/enigma/gui/GuiController.java +++ /dev/null @@ -1,729 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui; - -import com.google.common.collect.Lists; -import com.google.common.util.concurrent.ThreadFactoryBuilder; -import cuchaz.enigma.Enigma; -import cuchaz.enigma.EnigmaProfile; -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.analysis.*; -import cuchaz.enigma.api.service.ObfuscationTestService; -import cuchaz.enigma.bytecode.translators.SourceFixVisitor; -import cuchaz.enigma.config.Config; -import cuchaz.enigma.gui.dialog.ProgressDialog; -import cuchaz.enigma.gui.stats.StatsGenerator; -import cuchaz.enigma.gui.stats.StatsMember; -import cuchaz.enigma.gui.util.History; -import cuchaz.enigma.network.EnigmaClient; -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.network.IntegratedEnigmaServer; -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.network.packet.LoginC2SPacket; -import cuchaz.enigma.network.packet.Packet; -import cuchaz.enigma.source.*; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.*; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.Message; -import cuchaz.enigma.utils.ReadableToken; -import cuchaz.enigma.utils.Utils; -import org.objectweb.asm.tree.ClassNode; - -import javax.annotation.Nullable; -import javax.swing.JOptionPane; -import javax.swing.SwingUtilities; -import java.awt.*; -import java.awt.event.ItemEvent; -import java.io.*; -import java.nio.file.Path; -import java.util.Collection; -import java.util.List; -import java.util.Set; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class GuiController { - private static final ExecutorService DECOMPILER_SERVICE = Executors.newSingleThreadExecutor( - new ThreadFactoryBuilder() - .setDaemon(true) - .setNameFormat("decompiler-thread") - .build() - ); - - private final Gui gui; - public final Enigma enigma; - - public EnigmaProject project; - private DecompilerService decompilerService; - private Decompiler decompiler; - private IndexTreeBuilder indexTreeBuilder; - - private Path loadedMappingPath; - private MappingFormat loadedMappingFormat; - - private DecompiledClassSource currentSource; - private Source uncommentedSource; - - private EnigmaClient client; - private EnigmaServer server; - - public GuiController(Gui gui, EnigmaProfile profile) { - this.gui = gui; - this.enigma = Enigma.builder() - .setProfile(profile) - .build(); - - decompilerService = Config.getInstance().decompiler.service; - } - - public boolean isDirty() { - return project != null && project.getMapper().isDirty(); - } - - public CompletableFuture openJar(final Path jarPath) { - this.gui.onStartOpenJar(); - - return ProgressDialog.runOffThread(gui.getFrame(), progress -> { - project = enigma.openJar(jarPath, progress); - indexTreeBuilder = new IndexTreeBuilder(project.getJarIndex()); - decompiler = createDecompiler(); - gui.onFinishOpenJar(jarPath.getFileName().toString()); - refreshClasses(); - }); - } - - private Decompiler createDecompiler() { - return decompilerService.create(name -> { - ClassNode node = project.getClassCache().getClassNode(name); - - if (node == null) { - return null; - } - - ClassNode fixedNode = new ClassNode(); - node.accept(new SourceFixVisitor(Utils.ASM_VERSION, fixedNode, project.getJarIndex())); - return fixedNode; - }, new SourceSettings(true, true)); - } - - public void closeJar() { - this.project = null; - this.gui.onCloseJar(); - } - - public CompletableFuture openMappings(MappingFormat format, Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - gui.setMappingsFile(path); - - return ProgressDialog.runOffThread(gui.getFrame(), progress -> { - try { - MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); - - EntryTree mappings = format.read(path, progress, saveParameters); - project.setMappings(mappings); - - loadedMappingFormat = format; - loadedMappingPath = path; - - refreshClasses(); - refreshCurrentClass(); - } catch (MappingParseException e) { - JOptionPane.showMessageDialog(gui.getFrame(), e.getMessage()); - } - }); - } - - public void openMappings(EntryTree mappings) { - if (project == null) return; - - project.setMappings(mappings); - refreshClasses(); - refreshCurrentClass(); - } - - public CompletableFuture saveMappings(Path path) { - return saveMappings(path, loadedMappingFormat); - } - - public CompletableFuture saveMappings(Path path, MappingFormat format) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EntryRemapper mapper = project.getMapper(); - MappingSaveParameters saveParameters = enigma.getProfile().getMappingSaveParameters(); - - MappingDelta delta = mapper.takeMappingDelta(); - boolean saveAll = !path.equals(loadedMappingPath); - - loadedMappingFormat = format; - loadedMappingPath = path; - - if (saveAll) { - format.write(mapper.getObfToDeobf(), path, progress, saveParameters); - } else { - format.write(mapper.getObfToDeobf(), delta, path, progress, saveParameters); - } - }); - } - - public void closeMappings() { - if (project == null) return; - - project.setMappings(null); - - this.gui.setMappingsFile(null); - refreshClasses(); - refreshCurrentClass(); - } - - public CompletableFuture dropMappings() { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> project.dropMappings(progress)); - } - - public CompletableFuture exportSource(final Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EnigmaProject.JarExport jar = project.exportRemappedJar(progress); - EnigmaProject.SourceExport source = jar.decompile(progress, decompilerService); - - source.write(path, progress); - }); - } - - public CompletableFuture exportJar(final Path path) { - if (project == null) return CompletableFuture.completedFuture(null); - - return ProgressDialog.runOffThread(this.gui.getFrame(), progress -> { - EnigmaProject.JarExport jar = project.exportRemappedJar(progress); - jar.write(path, progress); - }); - } - - public Token getToken(int pos) { - if (this.currentSource == null) { - return null; - } - return this.currentSource.getIndex().getReferenceToken(pos); - } - - @Nullable - public EntryReference, Entry> getReference(Token token) { - if (this.currentSource == null) { - return null; - } - return this.currentSource.getIndex().getReference(token); - } - - public ReadableToken getReadableToken(Token token) { - if (this.currentSource == null) { - return null; - } - - SourceIndex index = this.currentSource.getIndex(); - return new ReadableToken( - index.getLineNumber(token.start), - index.getColumnNumber(token.start), - index.getColumnNumber(token.end) - ); - } - - /** - * Navigates to the declaration with respect to navigation history - * - * @param entry the entry whose declaration will be navigated to - */ - public void openDeclaration(Entry entry) { - if (entry == null) { - throw new IllegalArgumentException("Entry cannot be null!"); - } - openReference(new EntryReference<>(entry, entry.getName())); - } - - /** - * Navigates to the reference with respect to navigation history - * - * @param reference the reference - */ - public void openReference(EntryReference, Entry> reference) { - if (reference == null) { - throw new IllegalArgumentException("Reference cannot be null!"); - } - if (this.gui.referenceHistory == null) { - this.gui.referenceHistory = new History<>(reference); - } else { - if (!reference.equals(this.gui.referenceHistory.getCurrent())) { - this.gui.referenceHistory.push(reference); - } - } - setReference(reference); - } - - /** - * Navigates to the reference without modifying history. If the class is not currently loaded, it will be loaded. - * - * @param reference the reference - */ - private void setReference(EntryReference, Entry> reference) { - // get the reference target class - ClassEntry classEntry = reference.getLocationClassEntry(); - if (!project.isRenamable(classEntry)) { - throw new IllegalArgumentException("Obfuscated class " + classEntry + " was not found in the jar!"); - } - - if (this.currentSource == null || !this.currentSource.getEntry().equals(classEntry)) { - // deobfuscate the class, then navigate to the reference - loadClass(classEntry, () -> showReference(reference)); - } else { - showReference(reference); - } - } - - /** - * Navigates to the reference without modifying history. Assumes the class is loaded. - * - * @param reference - */ - private void showReference(EntryReference, Entry> reference) { - Collection tokens = getTokensForReference(reference); - if (tokens.isEmpty()) { - // DEBUG - System.err.println(String.format("WARNING: no tokens found for %s in %s", reference, this.currentSource.getEntry())); - } else { - this.gui.showTokens(tokens); - } - } - - public Collection getTokensForReference(EntryReference, Entry> reference) { - EntryRemapper mapper = this.project.getMapper(); - - SourceIndex index = this.currentSource.getIndex(); - return mapper.getObfResolver().resolveReference(reference, ResolutionStrategy.RESOLVE_CLOSEST) - .stream() - .flatMap(r -> index.getReferenceTokens(r).stream()) - .collect(Collectors.toList()); - } - - public void openPreviousReference() { - if (hasPreviousReference()) { - setReference(gui.referenceHistory.goBack()); - } - } - - public boolean hasPreviousReference() { - return gui.referenceHistory != null && gui.referenceHistory.canGoBack(); - } - - public void openNextReference() { - if (hasNextReference()) { - setReference(gui.referenceHistory.goForward()); - } - } - - public boolean hasNextReference() { - return gui.referenceHistory != null && gui.referenceHistory.canGoForward(); - } - - public void navigateTo(Entry entry) { - if (!project.isRenamable(entry)) { - // entry is not in the jar. Ignore it - return; - } - openDeclaration(entry); - } - - public void navigateTo(EntryReference, Entry> reference) { - if (!project.isRenamable(reference.getLocationClassEntry())) { - return; - } - openReference(reference); - } - - private void refreshClasses() { - List obfClasses = Lists.newArrayList(); - List deobfClasses = Lists.newArrayList(); - this.addSeparatedClasses(obfClasses, deobfClasses); - this.gui.setObfClasses(obfClasses); - this.gui.setDeobfClasses(deobfClasses); - } - - public void addSeparatedClasses(List obfClasses, List deobfClasses) { - EntryRemapper mapper = project.getMapper(); - - Collection classes = project.getJarIndex().getEntryIndex().getClasses(); - Stream visibleClasses = classes.stream() - .filter(entry -> !entry.isInnerClass()); - - visibleClasses.forEach(entry -> { - ClassEntry deobfEntry = mapper.deobfuscate(entry); - - List obfService = enigma.getServices().get(ObfuscationTestService.TYPE); - boolean obfuscated = deobfEntry.equals(entry); - - if (obfuscated && !obfService.isEmpty()) { - if (obfService.stream().anyMatch(service -> service.testDeobfuscated(entry))) { - obfuscated = false; - } - } - - if (obfuscated) { - obfClasses.add(entry); - } else { - deobfClasses.add(entry); - } - }); - } - - public void refreshCurrentClass() { - refreshCurrentClass(null); - } - - private void refreshCurrentClass(EntryReference, Entry> reference) { - refreshCurrentClass(reference, RefreshMode.MINIMAL); - } - - private void refreshCurrentClass(EntryReference, Entry> reference, RefreshMode mode) { - if (currentSource != null) { - if (reference == null) { - int obfSelectionStart = currentSource.getObfuscatedOffset(gui.editor.getSelectionStart()); - int obfSelectionEnd = currentSource.getObfuscatedOffset(gui.editor.getSelectionEnd()); - - Rectangle viewportBounds = gui.sourceScroller.getViewport().getViewRect(); - // Here we pick an "anchor position", which we want to stay in the same vertical location on the screen after the new text has been set - int anchorModelPos = gui.editor.getSelectionStart(); - Rectangle anchorViewPos = Utils.safeModelToView(gui.editor, anchorModelPos); - if (anchorViewPos.y < viewportBounds.y || anchorViewPos.y >= viewportBounds.y + viewportBounds.height) { - anchorModelPos = gui.editor.viewToModel(new Point(0, viewportBounds.y)); - anchorViewPos = Utils.safeModelToView(gui.editor, anchorModelPos); - } - int obfAnchorPos = currentSource.getObfuscatedOffset(anchorModelPos); - Rectangle anchorViewPos_f = anchorViewPos; - int scrollX = gui.sourceScroller.getHorizontalScrollBar().getValue(); - - loadClass(currentSource.getEntry(), () -> SwingUtilities.invokeLater(() -> { - int newAnchorModelPos = currentSource.getDeobfuscatedOffset(obfAnchorPos); - Rectangle newAnchorViewPos = Utils.safeModelToView(gui.editor, newAnchorModelPos); - int newScrollY = newAnchorViewPos.y - (anchorViewPos_f.y - viewportBounds.y); - - gui.editor.select(currentSource.getDeobfuscatedOffset(obfSelectionStart), currentSource.getDeobfuscatedOffset(obfSelectionEnd)); - // Changing the selection scrolls to the caret position inside a SwingUtilities.invokeLater call, so - // we need to wrap our change to the scroll position inside another invokeLater so it happens after - // the caret's own scrolling. - SwingUtilities.invokeLater(() -> { - gui.sourceScroller.getHorizontalScrollBar().setValue(Math.min(scrollX, gui.sourceScroller.getHorizontalScrollBar().getMaximum())); - gui.sourceScroller.getVerticalScrollBar().setValue(Math.min(newScrollY, gui.sourceScroller.getVerticalScrollBar().getMaximum())); - }); - }), mode); - } else { - loadClass(currentSource.getEntry(), () -> showReference(reference), mode); - } - } - } - - private void loadClass(ClassEntry classEntry, Runnable callback) { - loadClass(classEntry, callback, RefreshMode.MINIMAL); - } - - private void loadClass(ClassEntry classEntry, Runnable callback, RefreshMode mode) { - ClassEntry targetClass = classEntry.getOutermostClass(); - - boolean requiresDecompile = mode == RefreshMode.FULL || currentSource == null || !currentSource.getEntry().equals(targetClass); - if (requiresDecompile) { - currentSource = null; // Or the GUI may try to find a nonexistent token - gui.setEditorText(I18n.translate("info_panel.editor.class.decompiling")); - } - - DECOMPILER_SERVICE.submit(() -> { - try { - if (requiresDecompile || mode == RefreshMode.JAVADOCS) { - currentSource = decompileSource(targetClass, mode == RefreshMode.JAVADOCS); - } - - remapSource(project.getMapper().getDeobfuscator()); - callback.run(); - } catch (Throwable t) { - System.err.println("An exception was thrown while decompiling class " + classEntry.getFullName()); - t.printStackTrace(System.err); - } - }); - } - - private DecompiledClassSource decompileSource(ClassEntry targetClass, boolean onlyRefreshJavadocs) { - try { - if (!onlyRefreshJavadocs || currentSource == null || !currentSource.getEntry().equals(targetClass)) { - uncommentedSource = decompiler.getSource(targetClass.getFullName()); - } - - Source source = uncommentedSource.addJavadocs(project.getMapper()); - - if (source == null) { - gui.setEditorText(I18n.translate("info_panel.editor.class.not_found") + " " + targetClass); - return DecompiledClassSource.text(targetClass, "Unable to find class"); - } - - SourceIndex index = source.index(); - index.resolveReferences(project.getMapper().getObfResolver()); - - return new DecompiledClassSource(targetClass, index); - } catch (Throwable t) { - StringWriter traceWriter = new StringWriter(); - t.printStackTrace(new PrintWriter(traceWriter)); - - return DecompiledClassSource.text(targetClass, traceWriter.toString()); - } - } - - private void remapSource(Translator translator) { - if (currentSource == null) { - return; - } - - currentSource.remapSource(project, translator); - - gui.setEditorTheme(Config.getInstance().lookAndFeel); - gui.setSource(currentSource); - } - - public void modifierChange(ItemEvent event) { - if (event.getStateChange() == ItemEvent.SELECTED) { - EntryRemapper mapper = project.getMapper(); - Entry entry = gui.cursorReference.entry; - AccessModifier modifier = (AccessModifier) event.getItem(); - - EntryMapping mapping = mapper.getDeobfMapping(entry); - if (mapping != null) { - mapper.mapFromObf(entry, new EntryMapping(mapping.getTargetName(), modifier)); - } else { - mapper.mapFromObf(entry, new EntryMapping(entry.getName(), modifier)); - } - - refreshCurrentClass(); - } - } - - public ClassInheritanceTreeNode getClassInheritance(ClassEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - ClassInheritanceTreeNode rootNode = indexTreeBuilder.buildClassInheritance(translator, entry); - return ClassInheritanceTreeNode.findNode(rootNode, entry); - } - - public ClassImplementationsTreeNode getClassImplementations(ClassEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - return this.indexTreeBuilder.buildClassImplementations(translator, entry); - } - - public MethodInheritanceTreeNode getMethodInheritance(MethodEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - MethodInheritanceTreeNode rootNode = indexTreeBuilder.buildMethodInheritance(translator, entry); - return MethodInheritanceTreeNode.findNode(rootNode, entry); - } - - public MethodImplementationsTreeNode getMethodImplementations(MethodEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - List rootNodes = indexTreeBuilder.buildMethodImplementations(translator, entry); - if (rootNodes.isEmpty()) { - return null; - } - if (rootNodes.size() > 1) { - System.err.println("WARNING: Method " + entry + " implements multiple interfaces. Only showing first one."); - } - return MethodImplementationsTreeNode.findNode(rootNodes.get(0), entry); - } - - public ClassReferenceTreeNode getClassReferences(ClassEntry entry) { - Translator deobfuscator = project.getMapper().getDeobfuscator(); - ClassReferenceTreeNode rootNode = new ClassReferenceTreeNode(deobfuscator, entry); - rootNode.load(project.getJarIndex(), true); - return rootNode; - } - - public FieldReferenceTreeNode getFieldReferences(FieldEntry entry) { - Translator translator = project.getMapper().getDeobfuscator(); - FieldReferenceTreeNode rootNode = new FieldReferenceTreeNode(translator, entry); - rootNode.load(project.getJarIndex(), true); - return rootNode; - } - - public MethodReferenceTreeNode getMethodReferences(MethodEntry entry, boolean recursive) { - Translator translator = project.getMapper().getDeobfuscator(); - MethodReferenceTreeNode rootNode = new MethodReferenceTreeNode(translator, entry); - rootNode.load(project.getJarIndex(), true, recursive); - return rootNode; - } - - public void rename(EntryReference, Entry> reference, String newName, boolean refreshClassTree) { - rename(reference, newName, refreshClassTree, true); - } - - public void rename(EntryReference, Entry> reference, String newName, boolean refreshClassTree, boolean jumpToReference) { - Entry entry = reference.getNameableEntry(); - project.getMapper().mapFromObf(entry, new EntryMapping(newName)); - - if (refreshClassTree && reference.entry instanceof ClassEntry && !((ClassEntry) reference.entry).isInnerClass()) - this.gui.moveClassTree(reference, newName); - - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void removeMapping(EntryReference, Entry> reference) { - removeMapping(reference, true); - } - - public void removeMapping(EntryReference, Entry> reference, boolean jumpToReference) { - project.getMapper().removeByObf(reference.getNameableEntry()); - - if (reference.entry instanceof ClassEntry) - this.gui.moveClassTree(reference, false, true); - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void changeDocs(EntryReference, Entry> reference, String updatedDocs) { - changeDocs(reference, updatedDocs, true); - } - - public void changeDocs(EntryReference, Entry> reference, String updatedDocs, boolean jumpToReference) { - changeDoc(reference.entry, Utils.isBlank(updatedDocs) ? null : updatedDocs); - - refreshCurrentClass(jumpToReference ? reference : null, RefreshMode.JAVADOCS); - } - - private void changeDoc(Entry obfEntry, String newDoc) { - EntryRemapper mapper = project.getMapper(); - if (mapper.getDeobfMapping(obfEntry) == null) { - markAsDeobfuscated(obfEntry, false); // NPE - } - mapper.mapFromObf(obfEntry, mapper.getDeobfMapping(obfEntry).withDocs(newDoc), false); - } - - private void markAsDeobfuscated(Entry obfEntry, boolean renaming) { - EntryRemapper mapper = project.getMapper(); - mapper.mapFromObf(obfEntry, new EntryMapping(mapper.deobfuscate(obfEntry).getName()), renaming); - } - - public void markAsDeobfuscated(EntryReference, Entry> reference) { - markAsDeobfuscated(reference, true); - } - - public void markAsDeobfuscated(EntryReference, Entry> reference, boolean jumpToReference) { - EntryRemapper mapper = project.getMapper(); - Entry entry = reference.getNameableEntry(); - mapper.mapFromObf(entry, new EntryMapping(mapper.deobfuscate(entry).getName())); - - if (reference.entry instanceof ClassEntry && !((ClassEntry) reference.entry).isInnerClass()) - this.gui.moveClassTree(reference, true, false); - - refreshCurrentClass(jumpToReference ? reference : null); - } - - public void openStats(Set includedMembers) { - ProgressDialog.runOffThread(gui.getFrame(), progress -> { - String data = new StatsGenerator(project).generate(progress, includedMembers); - - try { - File statsFile = File.createTempFile("stats", ".html"); - - try (FileWriter w = new FileWriter(statsFile)) { - w.write( - Utils.readResourceToString("/stats.html") - .replace("/*data*/", data) - ); - } - - Desktop.getDesktop().open(statsFile); - } catch (IOException e) { - throw new Error(e); - } - }); - } - - public void setDecompiler(DecompilerService service) { - uncommentedSource = null; - decompilerService = service; - decompiler = createDecompiler(); - refreshCurrentClass(null, RefreshMode.FULL); - } - - public EnigmaClient getClient() { - return client; - } - - public EnigmaServer getServer() { - return server; - } - - public void createClient(String username, String ip, int port, char[] password) throws IOException { - client = new EnigmaClient(this, ip, port); - client.connect(); - client.sendPacket(new LoginC2SPacket(project.getJarChecksum(), password, username)); - gui.setConnectionState(ConnectionState.CONNECTED); - } - - public void createServer(int port, char[] password) throws IOException { - server = new IntegratedEnigmaServer(project.getJarChecksum(), password, EntryRemapper.mapped(project.getJarIndex(), new HashEntryTree<>(project.getMapper().getObfToDeobf())), port); - server.start(); - client = new EnigmaClient(this, "127.0.0.1", port); - client.connect(); - client.sendPacket(new LoginC2SPacket(project.getJarChecksum(), password, EnigmaServer.OWNER_USERNAME)); - gui.setConnectionState(ConnectionState.HOSTING); - } - - public synchronized void disconnectIfConnected(String reason) { - if (client == null && server == null) { - return; - } - - if (client != null) { - client.disconnect(); - } - if (server != null) { - server.stop(); - } - client = null; - server = null; - SwingUtilities.invokeLater(() -> { - if (reason != null) { - JOptionPane.showMessageDialog(gui.getFrame(), I18n.translate(reason), I18n.translate("disconnect.disconnected"), JOptionPane.INFORMATION_MESSAGE); - } - gui.setConnectionState(ConnectionState.NOT_CONNECTED); - }); - } - - public void sendPacket(Packet packet) { - if (client != null) { - client.sendPacket(packet); - } - } - - public void addMessage(Message message) { - gui.addMessage(message); - } - - public void updateUserList(List users) { - gui.setUserList(users); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/MessageListCellRenderer.java b/src/main/java/cuchaz/enigma/gui/MessageListCellRenderer.java deleted file mode 100644 index c9e38cbf..00000000 --- a/src/main/java/cuchaz/enigma/gui/MessageListCellRenderer.java +++ /dev/null @@ -1,24 +0,0 @@ -package cuchaz.enigma.gui; - -import java.awt.Component; - -import javax.swing.DefaultListCellRenderer; -import javax.swing.JList; - -import cuchaz.enigma.utils.Message; - -// For now, just render the translated text. -// TODO: Icons or something later? -public class MessageListCellRenderer extends DefaultListCellRenderer { - - @Override - public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { - super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus); - Message message = (Message) value; - if (message != null) { - setText(message.translate()); - } - return this; - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/MethodTreeCellRenderer.java b/src/main/java/cuchaz/enigma/gui/MethodTreeCellRenderer.java deleted file mode 100644 index 05d90a97..00000000 --- a/src/main/java/cuchaz/enigma/gui/MethodTreeCellRenderer.java +++ /dev/null @@ -1,42 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui; - -import cuchaz.enigma.analysis.MethodInheritanceTreeNode; -import cuchaz.enigma.config.Config; - -import javax.swing.*; -import javax.swing.tree.TreeCellRenderer; -import java.awt.*; - -class MethodTreeCellRenderer implements TreeCellRenderer { - - private final TreeCellRenderer parent; - - MethodTreeCellRenderer(TreeCellRenderer parent) { - this.parent = parent; - } - - @Override - public Component getTreeCellRendererComponent(JTree tree, Object value, boolean selected, boolean expanded, boolean leaf, int row, boolean hasFocus) { - Component ret = parent.getTreeCellRendererComponent(tree, value, selected, expanded, leaf, row, hasFocus); - Config config = Config.getInstance(); - if (!(value instanceof MethodInheritanceTreeNode) || ((MethodInheritanceTreeNode) value).isImplemented()) { - ret.setForeground(new Color(config.defaultTextColor)); - ret.setFont(ret.getFont().deriveFont(Font.PLAIN)); - } else { - ret.setForeground(new Color(config.numberColor)); - ret.setFont(ret.getFont().deriveFont(Font.ITALIC)); - } - return ret; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/QuickFindAction.java b/src/main/java/cuchaz/enigma/gui/QuickFindAction.java deleted file mode 100644 index b7fa2eba..00000000 --- a/src/main/java/cuchaz/enigma/gui/QuickFindAction.java +++ /dev/null @@ -1,45 +0,0 @@ -package cuchaz.enigma.gui; - -import de.sciss.syntaxpane.SyntaxDocument; -import de.sciss.syntaxpane.actions.DefaultSyntaxAction; - -import javax.swing.text.JTextComponent; -import java.awt.event.ActionEvent; - -public final class QuickFindAction extends DefaultSyntaxAction { - public QuickFindAction() { - super("quick-find"); - } - - @Override - public void actionPerformed(JTextComponent target, SyntaxDocument document, int dot, ActionEvent event) { - Data data = Data.get(target); - data.showFindDialog(target); - } - - private static class Data { - private static final String KEY = "enigma-find-data"; - private EnigmaQuickFindDialog findDialog; - - private Data() { - } - - public static Data get(JTextComponent target) { - Object o = target.getDocument().getProperty(KEY); - if (o instanceof Data) { - return (Data) o; - } - - Data data = new Data(); - target.getDocument().putProperty(KEY, data); - return data; - } - - public void showFindDialog(JTextComponent target) { - if (findDialog == null) { - findDialog = new EnigmaQuickFindDialog(target); - } - findDialog.showFor(target); - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/RefreshMode.java b/src/main/java/cuchaz/enigma/gui/RefreshMode.java deleted file mode 100644 index 87cb83b2..00000000 --- a/src/main/java/cuchaz/enigma/gui/RefreshMode.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.gui; - -public enum RefreshMode { - MINIMAL, - JAVADOCS, - FULL -} diff --git a/src/main/java/cuchaz/enigma/gui/SourceRemapper.java b/src/main/java/cuchaz/enigma/gui/SourceRemapper.java deleted file mode 100644 index f38f44ea..00000000 --- a/src/main/java/cuchaz/enigma/gui/SourceRemapper.java +++ /dev/null @@ -1,64 +0,0 @@ -package cuchaz.enigma.gui; - -import cuchaz.enigma.analysis.Token; - -import java.util.HashMap; -import java.util.Map; - -public class SourceRemapper { - private final String source; - private final Iterable tokens; - - public SourceRemapper(String source, Iterable tokens) { - this.source = source; - this.tokens = tokens; - } - - public Result remap(Remapper remapper) { - StringBuffer remappedSource = new StringBuffer(source); - Map remappedTokens = new HashMap<>(); - - int accumulatedOffset = 0; - for (Token token : tokens) { - Token movedToken = token.move(accumulatedOffset); - - String remappedName = remapper.remap(token, movedToken); - if (remappedName != null) { - accumulatedOffset += movedToken.getRenameOffset(remappedName); - movedToken.rename(remappedSource, remappedName); - } - - if (!token.equals(movedToken)) { - remappedTokens.put(token, movedToken); - } - } - - return new Result(remappedSource.toString(), remappedTokens); - } - - public static class Result { - private final String remappedSource; - private final Map remappedTokens; - - Result(String remappedSource, Map remappedTokens) { - this.remappedSource = remappedSource; - this.remappedTokens = remappedTokens; - } - - public String getSource() { - return remappedSource; - } - - public Token getRemappedToken(Token token) { - return remappedTokens.getOrDefault(token, token); - } - - public boolean isEmpty() { - return remappedTokens.isEmpty(); - } - } - - public interface Remapper { - String remap(Token token, Token movedToken); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/TokenListCellRenderer.java b/src/main/java/cuchaz/enigma/gui/TokenListCellRenderer.java deleted file mode 100644 index 7375111e..00000000 --- a/src/main/java/cuchaz/enigma/gui/TokenListCellRenderer.java +++ /dev/null @@ -1,35 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui; - -import cuchaz.enigma.analysis.Token; - -import javax.swing.*; -import java.awt.*; - -public class TokenListCellRenderer implements ListCellRenderer { - - private GuiController controller; - private DefaultListCellRenderer defaultRenderer; - - public TokenListCellRenderer(GuiController controller) { - this.controller = controller; - this.defaultRenderer = new DefaultListCellRenderer(); - } - - @Override - public Component getListCellRendererComponent(JList list, Token token, int index, boolean isSelected, boolean hasFocus) { - JLabel label = (JLabel) this.defaultRenderer.getListCellRendererComponent(list, token, index, isSelected, hasFocus); - label.setText(this.controller.getReadableToken(token).toString()); - return label; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java deleted file mode 100644 index 43b82651..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/AboutDialog.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.dialog; - -import cuchaz.enigma.Constants; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import java.awt.*; -import java.io.IOException; - -public class AboutDialog { - - public static void show(JFrame parent) { - // init frame - final JFrame frame = new JFrame(String.format(I18n.translate("menu.help.about.title"), Constants.NAME)); - final Container pane = frame.getContentPane(); - pane.setLayout(new FlowLayout()); - - // load the content - try { - String html = Utils.readResourceToString("/about.html"); - html = String.format(html, Constants.NAME, Constants.VERSION); - JLabel label = new JLabel(html); - label.setHorizontalAlignment(JLabel.CENTER); - pane.add(label); - } catch (IOException ex) { - throw new Error(ex); - } - - // show the link - String html = "%s"; - html = String.format(html, Constants.URL, Constants.URL); - JButton link = new JButton(html); - link.addActionListener(event -> Utils.openUrl(Constants.URL)); - link.setBorderPainted(false); - link.setOpaque(false); - link.setBackground(Color.WHITE); - link.setCursor(new Cursor(Cursor.HAND_CURSOR)); - link.setFocusable(false); - JPanel linkPanel = new JPanel(); - linkPanel.add(link); - pane.add(linkPanel); - - // show ok button - JButton okButton = new JButton(I18n.translate("menu.help.about.ok")); - pane.add(okButton); - okButton.addActionListener(arg0 -> frame.dispose()); - - // show the frame - pane.doLayout(); - frame.setSize(ScaleUtil.getDimension(400, 220)); - frame.setResizable(false); - frame.setLocationRelativeTo(parent); - frame.setVisible(true); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ChangeDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ChangeDialog.java deleted file mode 100644 index 64219ab8..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/ChangeDialog.java +++ /dev/null @@ -1,50 +0,0 @@ -package cuchaz.enigma.gui.dialog; - -import java.awt.BorderLayout; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; - -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.utils.I18n; - -public class ChangeDialog { - - public static void show(Gui gui) { - // init frame - JFrame frame = new JFrame(I18n.translate("menu.view.change.title")); - JPanel textPanel = new JPanel(); - JPanel buttonPanel = new JPanel(); - frame.setLayout(new BorderLayout()); - frame.add(BorderLayout.NORTH, textPanel); - frame.add(BorderLayout.SOUTH, buttonPanel); - - // show text - JLabel text = new JLabel((I18n.translate("menu.view.change.summary"))); - text.setHorizontalAlignment(JLabel.CENTER); - textPanel.add(text); - - // show ok button - JButton okButton = new JButton(I18n.translate("menu.view.change.ok")); - buttonPanel.add(okButton); - okButton.addActionListener(event -> frame.dispose()); - okButton.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - frame.dispose(); - } - } - }); - - // show the frame - frame.pack(); - frame.setVisible(true); - frame.setResizable(false); - frame.setLocationRelativeTo(gui.getFrame()); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java deleted file mode 100644 index c5f505cf..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/ConnectToServerDialog.java +++ /dev/null @@ -1,82 +0,0 @@ -package cuchaz.enigma.gui.dialog; - -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.Frame; - -public class ConnectToServerDialog { - - public static Result show(Frame parentComponent) { - JTextField usernameField = new JTextField(System.getProperty("user.name"), 20); - JPanel usernameRow = new JPanel(); - usernameRow.add(new JLabel(I18n.translate("prompt.connect.username"))); - usernameRow.add(usernameField); - JTextField ipField = new JTextField(20); - JPanel ipRow = new JPanel(); - ipRow.add(new JLabel(I18n.translate("prompt.connect.ip"))); - ipRow.add(ipField); - JTextField portField = new JTextField(String.valueOf(EnigmaServer.DEFAULT_PORT), 10); - JPanel portRow = new JPanel(); - portRow.add(new JLabel(I18n.translate("prompt.port"))); - portRow.add(portField); - JPasswordField passwordField = new JPasswordField(20); - JPanel passwordRow = new JPanel(); - passwordRow.add(new JLabel(I18n.translate("prompt.password"))); - passwordRow.add(passwordField); - - int response = JOptionPane.showConfirmDialog(parentComponent, new Object[]{usernameRow, ipRow, portRow, passwordRow}, I18n.translate("prompt.connect.title"), JOptionPane.OK_CANCEL_OPTION); - if (response != JOptionPane.OK_OPTION) { - return null; - } - - String username = usernameField.getText(); - String ip = ipField.getText(); - int port; - try { - port = Integer.parseInt(portField.getText()); - } catch (NumberFormatException e) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.nan"), I18n.translate("prompt.connect.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - if (port < 0 || port >= 65536) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.invalid"), I18n.translate("prompt.connect.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - char[] password = passwordField.getPassword(); - - return new Result(username, ip, port, password); - } - - public static class Result { - private final String username; - private final String ip; - private final int port; - private final char[] password; - - public Result(String username, String ip, int port, char[] password) { - this.username = username; - this.ip = ip; - this.port = port; - this.password = password; - } - - public String getUsername() { - return username; - } - - public String getIp() { - return ip; - } - - public int getPort() { - return port; - } - - public char[] getPassword() { - return password; - } - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java deleted file mode 100644 index 908b42e9..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/CrashDialog.java +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.dialog; - -import cuchaz.enigma.Constants; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import java.awt.*; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.FileWriter; -import java.io.File; -import java.io.IOException; - -public class CrashDialog { - - private static CrashDialog instance = null; - - private JFrame frame; - private JTextArea text; - - private CrashDialog(JFrame parent) { - // init frame - frame = new JFrame(String.format(I18n.translate("crash.title"), Constants.NAME)); - final Container pane = frame.getContentPane(); - pane.setLayout(new BorderLayout()); - - JLabel label = new JLabel(String.format(I18n.translate("crash.summary"), Constants.NAME)); - label.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10)); - pane.add(label, BorderLayout.NORTH); - - // report panel - text = new JTextArea(); - text.setTabSize(2); - pane.add(new JScrollPane(text), BorderLayout.CENTER); - - // buttons panel - JPanel buttonsPanel = new JPanel(); - buttonsPanel.setLayout(new BoxLayout(buttonsPanel, BoxLayout.LINE_AXIS)); - JButton exportButton = new JButton(I18n.translate("crash.export")); - exportButton.addActionListener(event -> { - JFileChooser chooser = new JFileChooser(); - chooser.setSelectedFile(new File("enigma_crash.log")); - if (chooser.showSaveDialog(null) == JFileChooser.APPROVE_OPTION) { - try { - File file = chooser.getSelectedFile(); - FileWriter writer = new FileWriter(file); - writer.write(instance.text.getText()); - writer.close(); - } catch (IOException ex) { - ex.printStackTrace(); - } - } - }); - buttonsPanel.add(exportButton); - buttonsPanel.add(Box.createHorizontalGlue()); - buttonsPanel.add(Utils.unboldLabel(new JLabel(I18n.translate("crash.exit.warning")))); - JButton ignoreButton = new JButton(I18n.translate("crash.ignore")); - ignoreButton.addActionListener(event -> { - // close (hide) the dialog - frame.setVisible(false); - }); - buttonsPanel.add(ignoreButton); - JButton exitButton = new JButton(I18n.translate("crash.exit")); - exitButton.addActionListener(event -> { - // exit enigma - System.exit(1); - }); - buttonsPanel.add(exitButton); - pane.add(buttonsPanel, BorderLayout.SOUTH); - - // show the frame - frame.setSize(ScaleUtil.getDimension(600, 400)); - frame.setLocationRelativeTo(parent); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - } - - public static void init(JFrame parent) { - instance = new CrashDialog(parent); - } - - public static void show(Throwable ex) { - // get the error report - StringWriter buf = new StringWriter(); - ex.printStackTrace(new PrintWriter(buf)); - String report = buf.toString(); - - // show it! - instance.text.setText(report); - instance.frame.doLayout(); - instance.frame.setVisible(true); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java deleted file mode 100644 index eea1dff1..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/CreateServerDialog.java +++ /dev/null @@ -1,65 +0,0 @@ -package cuchaz.enigma.gui.dialog; - -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.*; - -public class CreateServerDialog { - - public static Result show(Frame parentComponent) { - JTextField portField = new JTextField(String.valueOf(EnigmaServer.DEFAULT_PORT), 10); - JPanel portRow = new JPanel(); - portRow.add(new JLabel(I18n.translate("prompt.port"))); - portRow.add(portField); - JPasswordField passwordField = new JPasswordField(20); - JPanel passwordRow = new JPanel(); - passwordRow.add(new JLabel(I18n.translate("prompt.password"))); - passwordRow.add(passwordField); - - int response = JOptionPane.showConfirmDialog(parentComponent, new Object[]{portRow, passwordRow}, I18n.translate("prompt.create_server.title"), JOptionPane.OK_CANCEL_OPTION); - if (response != JOptionPane.OK_OPTION) { - return null; - } - - int port; - try { - port = Integer.parseInt(portField.getText()); - } catch (NumberFormatException e) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.nan"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - if (port < 0 || port >= 65536) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.port.invalid"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - - char[] password = passwordField.getPassword(); - if (password.length > EnigmaServer.MAX_PASSWORD_LENGTH) { - JOptionPane.showMessageDialog(parentComponent, I18n.translate("prompt.password.too_long"), I18n.translate("prompt.create_server.title"), JOptionPane.ERROR_MESSAGE); - return null; - } - - return new Result(port, password); - } - - public static class Result { - private final int port; - private final char[] password; - - public Result(int port, char[] password) { - this.port = port; - this.password = password; - } - - public int getPort() { - return port; - } - - public char[] getPassword() { - return password; - } - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java deleted file mode 100644 index 7e414419..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/JavadocDialog.java +++ /dev/null @@ -1,159 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.dialog; - -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import javax.swing.text.html.HTML; - -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; - -public class JavadocDialog { - - private static JavadocDialog instance = null; - - private JFrame frame; - - private JavadocDialog(JFrame parent, JTextArea text, Callback callback) { - // init frame - frame = new JFrame(I18n.translate("javadocs.edit")); - final Container pane = frame.getContentPane(); - pane.setLayout(new BorderLayout()); - - // editor panel - text.setTabSize(2); - pane.add(new JScrollPane(text), BorderLayout.CENTER); - text.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - switch (event.getKeyCode()) { - case KeyEvent.VK_ENTER: - if (event.isControlDown()) - callback.closeUi(frame, true); - break; - case KeyEvent.VK_ESCAPE: - callback.closeUi(frame, false); - break; - default: - break; - } - } - }); - - // buttons panel - JPanel buttonsPanel = new JPanel(); - FlowLayout buttonsLayout = new FlowLayout(); - buttonsLayout.setAlignment(FlowLayout.RIGHT); - buttonsPanel.setLayout(buttonsLayout); - buttonsPanel.add(Utils.unboldLabel(new JLabel(I18n.translate("javadocs.instruction")))); - JButton cancelButton = new JButton(I18n.translate("javadocs.cancel")); - cancelButton.addActionListener(event -> { - // close (hide) the dialog - callback.closeUi(frame, false); - }); - buttonsPanel.add(cancelButton); - JButton saveButton = new JButton(I18n.translate("javadocs.save")); - saveButton.addActionListener(event -> { - // exit enigma - callback.closeUi(frame, true); - }); - buttonsPanel.add(saveButton); - pane.add(buttonsPanel, BorderLayout.SOUTH); - - // tags panel - JMenuBar tagsMenu = new JMenuBar(); - - // add javadoc tags - for (JavadocTag tag : JavadocTag.values()) { - JButton tagButton = new JButton(tag.getText()); - tagButton.addActionListener(action -> { - boolean textSelected = text.getSelectedText() != null; - String tagText = tag.isInline() ? "{" + tag.getText() + " }" : tag.getText() + " "; - - if (textSelected) { - if (tag.isInline()) { - tagText = "{" + tag.getText() + " " + text.getSelectedText() + "}"; - } else { - tagText = tag.getText() + " " + text.getSelectedText(); - } - text.replaceSelection(tagText); - } else { - text.insert(tagText, text.getCaretPosition()); - } - - if (tag.isInline()) { - text.setCaretPosition(text.getCaretPosition() - 1); - } - text.grabFocus(); - }); - tagsMenu.add(tagButton); - } - - // add html tags - JComboBox htmlList = new JComboBox(); - htmlList.setPreferredSize(new Dimension()); - for (HTML.Tag htmlTag : HTML.getAllTags()) { - htmlList.addItem(htmlTag.toString()); - } - htmlList.addActionListener(action -> { - String tagText = "<" + htmlList.getSelectedItem().toString() + ">"; - text.insert(tagText, text.getCaretPosition()); - text.grabFocus(); - }); - tagsMenu.add(htmlList); - - pane.add(tagsMenu, BorderLayout.NORTH); - - // show the frame - frame.setSize(ScaleUtil.getDimension(600, 400)); - frame.setLocationRelativeTo(parent); - frame.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); - } - - public static void init(JFrame parent, JTextArea area, Callback callback) { - instance = new JavadocDialog(parent, area, callback); - instance.frame.doLayout(); - instance.frame.setVisible(true); - } - - public interface Callback { - void closeUi(JFrame frame, boolean save); - } - - private enum JavadocTag { - CODE(true), - LINK(true), - LINKPLAIN(true), - RETURN(false), - SEE(false), - THROWS(false); - - private boolean inline; - - private JavadocTag(boolean inline) { - this.inline = inline; - } - - public String getText() { - return "@" + this.name().toLowerCase(); - } - - public boolean isInline() { - return this.inline; - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java deleted file mode 100644 index e33ae821..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/ProgressDialog.java +++ /dev/null @@ -1,109 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.dialog; - -import cuchaz.enigma.Constants; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import java.awt.*; -import java.util.concurrent.CompletableFuture; - -public class ProgressDialog implements ProgressListener, AutoCloseable { - - private JFrame frame; - private JLabel labelTitle; - private JLabel labelText; - private JProgressBar progress; - - public ProgressDialog(JFrame parent) { - - // init frame - this.frame = new JFrame(String.format(I18n.translate("progress.operation"), Constants.NAME)); - final Container pane = this.frame.getContentPane(); - FlowLayout layout = new FlowLayout(); - layout.setAlignment(FlowLayout.LEFT); - pane.setLayout(layout); - - this.labelTitle = new JLabel(); - pane.add(this.labelTitle); - - // set up the progress bar - JPanel panel = new JPanel(); - pane.add(panel); - panel.setLayout(new BorderLayout()); - this.labelText = Utils.unboldLabel(new JLabel()); - this.progress = new JProgressBar(); - this.labelText.setBorder(BorderFactory.createEmptyBorder(0, 0, 10, 0)); - panel.add(this.labelText, BorderLayout.NORTH); - panel.add(this.progress, BorderLayout.CENTER); - panel.setPreferredSize(ScaleUtil.getDimension(360, 50)); - - // show the frame - pane.doLayout(); - this.frame.setSize(ScaleUtil.getDimension(400, 120)); - this.frame.setResizable(false); - this.frame.setLocationRelativeTo(parent); - this.frame.setVisible(true); - this.frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); - } - - public static CompletableFuture runOffThread(final JFrame parent, final ProgressRunnable runnable) { - CompletableFuture future = new CompletableFuture<>(); - new Thread(() -> - { - try (ProgressDialog progress = new ProgressDialog(parent)) { - runnable.run(progress); - future.complete(null); - } catch (Exception ex) { - future.completeExceptionally(ex); - throw new Error(ex); - } - }).start(); - return future; - } - - @Override - public void close() { - this.frame.dispose(); - } - - @Override - public void init(int totalWork, String title) { - this.labelTitle.setText(title); - this.progress.setMinimum(0); - this.progress.setMaximum(totalWork); - this.progress.setValue(0); - } - - @Override - public void step(int numDone, String message) { - this.labelText.setText(message); - if (numDone != -1) { - this.progress.setValue(numDone); - this.progress.setIndeterminate(false); - } else { - this.progress.setIndeterminate(true); - } - - // update the frame - this.frame.validate(); - this.frame.repaint(); - } - - public interface ProgressRunnable { - void run(ProgressListener listener) throws Exception; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java deleted file mode 100644 index b283a377..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/SearchDialog.java +++ /dev/null @@ -1,261 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.dialog; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.event.*; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import javax.swing.*; -import javax.swing.event.DocumentEvent; -import javax.swing.event.DocumentListener; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.gui.util.AbstractListCellRenderer; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.search.SearchEntry; -import cuchaz.enigma.utils.search.SearchUtil; - -public class SearchDialog { - - private final JTextField searchField; - private DefaultListModel classListModel; - private final JList classList; - private final JDialog dialog; - - private final Gui parent; - private final SearchUtil su; - private SearchUtil.SearchControl currentSearch; - - public SearchDialog(Gui parent) { - this.parent = parent; - - su = new SearchUtil<>(); - - dialog = new JDialog(parent.getFrame(), I18n.translate("menu.view.search"), true); - JPanel contentPane = new JPanel(); - contentPane.setBorder(ScaleUtil.createEmptyBorder(4, 4, 4, 4)); - contentPane.setLayout(new BorderLayout(ScaleUtil.scale(4), ScaleUtil.scale(4))); - - searchField = new JTextField(); - searchField.getDocument().addDocumentListener(new DocumentListener() { - - @Override - public void insertUpdate(DocumentEvent e) { - updateList(); - } - - @Override - public void removeUpdate(DocumentEvent e) { - updateList(); - } - - @Override - public void changedUpdate(DocumentEvent e) { - updateList(); - } - - }); - searchField.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent e) { - if (e.getKeyCode() == KeyEvent.VK_DOWN) { - int next = classList.isSelectionEmpty() ? 0 : classList.getSelectedIndex() + 1; - classList.setSelectedIndex(next); - classList.ensureIndexIsVisible(next); - } else if (e.getKeyCode() == KeyEvent.VK_UP) { - int prev = classList.isSelectionEmpty() ? classList.getModel().getSize() : classList.getSelectedIndex() - 1; - classList.setSelectedIndex(prev); - classList.ensureIndexIsVisible(prev); - } else if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { - close(); - } - } - }); - searchField.addActionListener(e -> openSelected()); - contentPane.add(searchField, BorderLayout.NORTH); - - classListModel = new DefaultListModel<>(); - classList = new JList<>(); - classList.setModel(classListModel); - classList.setCellRenderer(new ListCellRendererImpl()); - classList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); - classList.addMouseListener(new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent mouseEvent) { - if (mouseEvent.getClickCount() >= 2) { - int idx = classList.locationToIndex(mouseEvent.getPoint()); - SearchEntryImpl entry = classList.getModel().getElementAt(idx); - openEntry(entry); - } - } - }); - contentPane.add(new JScrollPane(classList, JScrollPane.VERTICAL_SCROLLBAR_AS_NEEDED, JScrollPane.HORIZONTAL_SCROLLBAR_NEVER), BorderLayout.CENTER); - - JPanel buttonBar = new JPanel(); - buttonBar.setLayout(new FlowLayout(FlowLayout.RIGHT)); - JButton open = new JButton(I18n.translate("prompt.open")); - open.addActionListener(event -> openSelected()); - buttonBar.add(open); - JButton cancel = new JButton(I18n.translate("prompt.cancel")); - cancel.addActionListener(event -> close()); - buttonBar.add(cancel); - contentPane.add(buttonBar, BorderLayout.SOUTH); - - // apparently the class list doesn't update by itself when the list - // state changes and the dialog is hidden - dialog.addComponentListener(new ComponentAdapter() { - @Override - public void componentShown(ComponentEvent e) { - classList.updateUI(); - } - }); - - dialog.setContentPane(contentPane); - dialog.setSize(ScaleUtil.getDimension(400, 500)); - dialog.setLocationRelativeTo(parent.getFrame()); - } - - public void show() { - su.clear(); - parent.getController().project.getJarIndex().getEntryIndex().getClasses().parallelStream() - .filter(e -> !e.isInnerClass()) - .map(e -> SearchEntryImpl.from(e, parent.getController())) - .map(SearchUtil.Entry::from) - .sequential() - .forEach(su::add); - - updateList(); - - searchField.requestFocus(); - searchField.selectAll(); - - dialog.setVisible(true); - } - - private void openSelected() { - SearchEntryImpl selectedValue = classList.getSelectedValue(); - if (selectedValue != null) { - openEntry(selectedValue); - } - } - - private void openEntry(SearchEntryImpl e) { - close(); - su.hit(e); - parent.getController().navigateTo(e.obf); - if (e.deobf != null) { - parent.getDeobfPanel().deobfClasses.setSelectionClass(e.deobf); - } else { - parent.getObfPanel().obfClasses.setSelectionClass(e.obf); - } - } - - private void close() { - dialog.setVisible(false); - } - - // Updates the list of class names - private void updateList() { - if (currentSearch != null) currentSearch.stop(); - - DefaultListModel classListModel = new DefaultListModel<>(); - this.classListModel = classListModel; - classList.setModel(classListModel); - - currentSearch = su.asyncSearch(searchField.getText(), (idx, e) -> SwingUtilities.invokeLater(() -> classListModel.insertElementAt(e, idx))); - } - - public void dispose() { - dialog.dispose(); - } - - private static final class SearchEntryImpl implements SearchEntry { - - public final ClassEntry obf; - public final ClassEntry deobf; - - private SearchEntryImpl(ClassEntry obf, ClassEntry deobf) { - this.obf = obf; - this.deobf = deobf; - } - - @Override - public List getSearchableNames() { - if (deobf != null) { - return Arrays.asList(obf.getSimpleName(), deobf.getSimpleName()); - } else { - return Collections.singletonList(obf.getSimpleName()); - } - } - - @Override - public String getIdentifier() { - return obf.getFullName(); - } - - @Override - public String toString() { - return String.format("SearchEntryImpl { obf: %s, deobf: %s }", obf, deobf); - } - - public static SearchEntryImpl from(ClassEntry e, GuiController controller) { - ClassEntry deobf = controller.project.getMapper().deobfuscate(e); - if (deobf.equals(e)) deobf = null; - return new SearchEntryImpl(e, deobf); - } - - } - - private static final class ListCellRendererImpl extends AbstractListCellRenderer { - - private final JLabel mainName; - private final JLabel secondaryName; - - public ListCellRendererImpl() { - this.setLayout(new BorderLayout()); - - mainName = new JLabel(); - this.add(mainName, BorderLayout.WEST); - - secondaryName = new JLabel(); - secondaryName.setFont(secondaryName.getFont().deriveFont(Font.ITALIC)); - secondaryName.setForeground(Color.GRAY); - this.add(secondaryName, BorderLayout.EAST); - } - - @Override - public void updateUiForEntry(JList list, SearchEntryImpl value, int index, boolean isSelected, boolean cellHasFocus) { - if (value.deobf == null) { - mainName.setText(value.obf.getSimpleName()); - mainName.setToolTipText(value.obf.getFullName()); - secondaryName.setText(""); - secondaryName.setToolTipText(""); - } else { - mainName.setText(value.deobf.getSimpleName()); - mainName.setToolTipText(value.deobf.getFullName()); - secondaryName.setText(value.obf.getSimpleName()); - secondaryName.setToolTipText(value.obf.getFullName()); - } - } - - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/dialog/StatsDialog.java b/src/main/java/cuchaz/enigma/gui/dialog/StatsDialog.java deleted file mode 100644 index 868eba79..00000000 --- a/src/main/java/cuchaz/enigma/gui/dialog/StatsDialog.java +++ /dev/null @@ -1,82 +0,0 @@ -package cuchaz.enigma.gui.dialog; - -import java.awt.BorderLayout; -import java.util.Arrays; -import java.util.Locale; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -import javax.swing.JButton; -import javax.swing.JCheckBox; -import javax.swing.JFrame; -import javax.swing.JPanel; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.gui.stats.StatsMember; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.I18n; - -public class StatsDialog { - - public static void show(Gui gui) { - // init frame - JFrame frame = new JFrame(I18n.translate("menu.file.stats.title")); - JPanel checkboxesPanel = new JPanel(); - JPanel buttonPanel = new JPanel(); - frame.setLayout(new BorderLayout()); - frame.add(BorderLayout.NORTH, checkboxesPanel); - frame.add(BorderLayout.SOUTH, buttonPanel); - - // show checkboxes - Map checkboxes = Arrays - .stream(StatsMember.values()) - .collect(Collectors.toMap(m -> m, m -> { - JCheckBox checkbox = new JCheckBox(I18n.translate("type." + m.name().toLowerCase(Locale.ROOT))); - checkboxesPanel.add(checkbox); - return checkbox; - })); - - // show generate button - JButton button = new JButton(I18n.translate("menu.file.stats.generate")); - buttonPanel.add(button); - button.setEnabled(false); - button.addActionListener(action -> { - frame.dispose(); - generateStats(gui, checkboxes); - }); - - // add action listener to each checkbox - checkboxes.entrySet().forEach(checkbox -> { - checkbox.getValue().addActionListener(action -> { - if (!button.isEnabled()) { - button.setEnabled(true); - } else if (checkboxes.entrySet().stream().allMatch(entry -> !entry.getValue().isSelected())) { - button.setEnabled(false); - } - }); - }); - - // show the frame - frame.pack(); - frame.setVisible(true); - frame.setSize(ScaleUtil.getDimension(500, 120)); - frame.setResizable(false); - frame.setLocationRelativeTo(gui.getFrame()); - } - - private static void generateStats(Gui gui, Map checkboxes) { - // get members from selected checkboxes - Set includedMembers = checkboxes - .entrySet() - .stream() - .filter(entry -> entry.getValue().isSelected()) - .map(Map.Entry::getKey) - .collect(Collectors.toSet()); - - // checks if a projet is open - if (gui.getController().project != null) { - gui.getController().openStats(includedMembers); - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/elements/CollapsibleTabbedPane.java b/src/main/java/cuchaz/enigma/gui/elements/CollapsibleTabbedPane.java deleted file mode 100644 index fb497b11..00000000 --- a/src/main/java/cuchaz/enigma/gui/elements/CollapsibleTabbedPane.java +++ /dev/null @@ -1,40 +0,0 @@ -package cuchaz.enigma.gui.elements; - -import java.awt.event.MouseEvent; - -import javax.swing.JTabbedPane; - -public class CollapsibleTabbedPane extends JTabbedPane { - - public CollapsibleTabbedPane() { - } - - public CollapsibleTabbedPane(int tabPlacement) { - super(tabPlacement); - } - - public CollapsibleTabbedPane(int tabPlacement, int tabLayoutPolicy) { - super(tabPlacement, tabLayoutPolicy); - } - - @Override - protected void processMouseEvent(MouseEvent e) { - int id = e.getID(); - if (id == MouseEvent.MOUSE_PRESSED) { - if (!isEnabled()) return; - int tabIndex = getUI().tabForCoordinate(this, e.getX(), e.getY()); - if (tabIndex >= 0 && isEnabledAt(tabIndex)) { - if (tabIndex == getSelectedIndex()) { - if (isFocusOwner() && isRequestFocusEnabled()) { - requestFocus(); - } else { - setSelectedIndex(-1); - } - return; - } - } - } - super.processMouseEvent(e); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java deleted file mode 100644 index dc2cf8fd..00000000 --- a/src/main/java/cuchaz/enigma/gui/elements/MenuBar.java +++ /dev/null @@ -1,386 +0,0 @@ -package cuchaz.enigma.gui.elements; - -import cuchaz.enigma.config.Config; -import cuchaz.enigma.config.Themes; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.gui.dialog.AboutDialog; -import cuchaz.enigma.gui.dialog.ChangeDialog; -import cuchaz.enigma.gui.dialog.ConnectToServerDialog; -import cuchaz.enigma.gui.dialog.CreateServerDialog; -import cuchaz.enigma.gui.dialog.StatsDialog; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.Pair; - -import java.awt.Desktop; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; -import java.io.File; -import java.io.IOException; -import java.net.URISyntaxException; -import java.net.URL; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.*; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import javax.swing.*; - -public class MenuBar extends JMenuBar { - - public final JMenuItem closeJarMenu; - public final List openMappingsMenus; - public final JMenuItem saveMappingsMenu; - public final List saveMappingsMenus; - public final JMenuItem closeMappingsMenu; - public final JMenuItem dropMappingsMenu; - public final JMenuItem exportSourceMenu; - public final JMenuItem exportJarMenu; - public final JMenuItem connectToServerMenu; - public final JMenuItem startServerMenu; - private final Gui gui; - - public MenuBar(Gui gui) { - this.gui = gui; - - /* - * File menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.file")); - this.add(menu); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.jar.open")); - menu.add(item); - item.addActionListener(event -> { - this.gui.jarFileChooser.setVisible(true); - String file = this.gui.jarFileChooser.getFile(); - // checks if the file name is not empty - if (file != null) { - Path path = Paths.get(this.gui.jarFileChooser.getDirectory()).resolve(file); - // checks if the file name corresponds to an existing file - if (Files.exists(path)) { - gui.getController().openJar(path); - } - } - }); - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.jar.close")); - menu.add(item); - item.addActionListener(event -> this.gui.getController().closeJar()); - this.closeJarMenu = item; - } - menu.addSeparator(); - JMenu openMenu = new JMenu(I18n.translate("menu.file.mappings.open")); - menu.add(openMenu); - { - openMappingsMenus = new ArrayList<>(); - for (MappingFormat format : MappingFormat.values()) { - if (format.getReader() != null) { - JMenuItem item = new JMenuItem(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT))); - openMenu.add(item); - item.addActionListener(event -> { - if (this.gui.enigmaMappingsFileChooser.showOpenDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { - File selectedFile = this.gui.enigmaMappingsFileChooser.getSelectedFile(); - this.gui.getController().openMappings(format, selectedFile.toPath()); - } - }); - openMappingsMenus.add(item); - } - } - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.mappings.save")); - menu.add(item); - item.addActionListener(event -> { - this.gui.getController().saveMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath()); - }); - item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S, InputEvent.CTRL_DOWN_MASK)); - this.saveMappingsMenu = item; - } - JMenu saveMenu = new JMenu(I18n.translate("menu.file.mappings.save_as")); - menu.add(saveMenu); - { - saveMappingsMenus = new ArrayList<>(); - for (MappingFormat format : MappingFormat.values()) { - if (format.getWriter() != null) { - JMenuItem item = new JMenuItem(I18n.translate("mapping_format." + format.name().toLowerCase(Locale.ROOT))); - saveMenu.add(item); - item.addActionListener(event -> { - // TODO: Use a specific file chooser for it - if (this.gui.enigmaMappingsFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { - this.gui.getController().saveMappings(this.gui.enigmaMappingsFileChooser.getSelectedFile().toPath(), format); - this.saveMappingsMenu.setEnabled(true); - } - }); - saveMappingsMenus.add(item); - } - } - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.mappings.close")); - menu.add(item); - item.addActionListener(event -> { - if (this.gui.getController().isDirty()) { - this.gui.showDiscardDiag((response -> { - if (response == JOptionPane.YES_OPTION) { - gui.saveMapping(); - this.gui.getController().closeMappings(); - } else if (response == JOptionPane.NO_OPTION) - this.gui.getController().closeMappings(); - return null; - }), I18n.translate("prompt.close.save"), I18n.translate("prompt.close.discard"), I18n.translate("prompt.close.cancel")); - } else - this.gui.getController().closeMappings(); - - }); - this.closeMappingsMenu = item; - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.mappings.drop")); - menu.add(item); - item.addActionListener(event -> this.gui.getController().dropMappings()); - this.dropMappingsMenu = item; - } - menu.addSeparator(); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.export.source")); - menu.add(item); - item.addActionListener(event -> { - if (this.gui.exportSourceFileChooser.showSaveDialog(this.gui.getFrame()) == JFileChooser.APPROVE_OPTION) { - this.gui.getController().exportSource(this.gui.exportSourceFileChooser.getSelectedFile().toPath()); - } - }); - this.exportSourceMenu = item; - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.export.jar")); - menu.add(item); - item.addActionListener(event -> { - this.gui.exportJarFileChooser.setVisible(true); - if (this.gui.exportJarFileChooser.getFile() != null) { - Path path = Paths.get(this.gui.exportJarFileChooser.getDirectory(), this.gui.exportJarFileChooser.getFile()); - this.gui.getController().exportJar(path); - } - }); - this.exportJarMenu = item; - } - menu.addSeparator(); - { - JMenuItem stats = new JMenuItem(I18n.translate("menu.file.stats")); - menu.add(stats); - stats.addActionListener(event -> StatsDialog.show(this.gui)); - } - menu.addSeparator(); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.file.exit")); - menu.add(item); - item.addActionListener(event -> this.gui.close()); - } - } - - /* - * Decompiler menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.decompiler")); - this.add(menu); - - ButtonGroup decompilerGroup = new ButtonGroup(); - - for (Config.Decompiler decompiler : Config.Decompiler.values()) { - JRadioButtonMenuItem decompilerButton = new JRadioButtonMenuItem(decompiler.name); - decompilerGroup.add(decompilerButton); - if (decompiler.equals(Config.getInstance().decompiler)) { - decompilerButton.setSelected(true); - } - menu.add(decompilerButton); - decompilerButton.addActionListener(event -> { - gui.getController().setDecompiler(decompiler.service); - - try { - Config.getInstance().decompiler = decompiler; - Config.getInstance().saveConfig(); - } catch (IOException e) { - throw new RuntimeException(e); - } - }); - } - } - - /* - * View menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.view")); - this.add(menu); - { - JMenu themes = new JMenu(I18n.translate("menu.view.themes")); - menu.add(themes); - ButtonGroup themeGroup = new ButtonGroup(); - for (Config.LookAndFeel lookAndFeel : Config.LookAndFeel.values()) { - JRadioButtonMenuItem themeButton = new JRadioButtonMenuItem(I18n.translate("menu.view.themes." + lookAndFeel.name().toLowerCase(Locale.ROOT))); - themeGroup.add(themeButton); - if (lookAndFeel.equals(Config.getInstance().lookAndFeel)) { - themeButton.setSelected(true); - } - themes.add(themeButton); - themeButton.addActionListener(event -> Themes.setLookAndFeel(gui, lookAndFeel)); - } - } - { - JMenu languages = new JMenu(I18n.translate("menu.view.languages")); - menu.add(languages); - ButtonGroup languageGroup = new ButtonGroup(); - for (String lang : I18n.getAvailableLanguages()) { - JRadioButtonMenuItem languageButton = new JRadioButtonMenuItem(I18n.getLanguageName(lang)); - languageGroup.add(languageButton); - if (lang.equals(Config.getInstance().language)) { - languageButton.setSelected(true); - } - languages.add(languageButton); - languageButton.addActionListener(event -> { - I18n.setLanguage(lang); - ChangeDialog.show(this.gui); - }); - } - } - { - JMenu scale = new JMenu(I18n.translate("menu.view.scale")); - { - ButtonGroup scaleGroup = new ButtonGroup(); - Map map = IntStream.of(100, 125, 150, 175, 200) - .mapToObj(scaleFactor -> { - float realScaleFactor = scaleFactor / 100f; - JRadioButtonMenuItem menuItem = new JRadioButtonMenuItem(String.format("%d%%", scaleFactor)); - menuItem.addActionListener(event -> ScaleUtil.setScaleFactor(realScaleFactor)); - menuItem.addActionListener(event -> ChangeDialog.show(this.gui)); - scaleGroup.add(menuItem); - scale.add(menuItem); - return new Pair<>(realScaleFactor, menuItem); - }) - .collect(Collectors.toMap(x -> x.a, x -> x.b)); - - JMenuItem customScale = new JMenuItem(I18n.translate("menu.view.scale.custom")); - customScale.addActionListener(event -> { - String answer = (String) JOptionPane.showInputDialog(gui.getFrame(), I18n.translate("menu.view.scale.custom.title"), I18n.translate("menu.view.scale.custom.title"), - JOptionPane.QUESTION_MESSAGE, null, null, Float.toString(ScaleUtil.getScaleFactor() * 100)); - if (answer == null) return; - float newScale = 1.0f; - try { - newScale = Float.parseFloat(answer) / 100f; - } catch (NumberFormatException ignored) { - } - ScaleUtil.setScaleFactor(newScale); - ChangeDialog.show(this.gui); - }); - scale.add(customScale); - ScaleUtil.addListener((newScale, _oldScale) -> { - JRadioButtonMenuItem mi = map.get(newScale); - if (mi != null) { - mi.setSelected(true); - } else { - scaleGroup.clearSelection(); - } - }); - JRadioButtonMenuItem mi = map.get(ScaleUtil.getScaleFactor()); - if (mi != null) { - mi.setSelected(true); - } - } - menu.add(scale); - } - menu.addSeparator(); - { - JMenuItem search = new JMenuItem(I18n.translate("menu.view.search")); - search.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_SPACE, InputEvent.SHIFT_MASK)); - menu.add(search); - search.addActionListener(event -> { - if (this.gui.getController().project != null) { - this.gui.getSearchDialog().show(); - } - }); - } - } - - /* - * Collab menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.collab")); - this.add(menu); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.collab.connect")); - menu.add(item); - item.addActionListener(event -> { - if (this.gui.getController().getClient() != null) { - this.gui.getController().disconnectIfConnected(null); - return; - } - ConnectToServerDialog.Result result = ConnectToServerDialog.show(this.gui.getFrame()); - if (result == null) { - return; - } - this.gui.getController().disconnectIfConnected(null); - try { - this.gui.getController().createClient(result.getUsername(), result.getIp(), result.getPort(), result.getPassword()); - } catch (IOException e) { - JOptionPane.showMessageDialog(this.gui.getFrame(), e.toString(), I18n.translate("menu.collab.connect.error"), JOptionPane.ERROR_MESSAGE); - this.gui.getController().disconnectIfConnected(null); - } - Arrays.fill(result.getPassword(), (char)0); - }); - this.connectToServerMenu = item; - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.collab.server.start")); - menu.add(item); - item.addActionListener(event -> { - if (this.gui.getController().getServer() != null) { - this.gui.getController().disconnectIfConnected(null); - return; - } - CreateServerDialog.Result result = CreateServerDialog.show(this.gui.getFrame()); - if (result == null) { - return; - } - this.gui.getController().disconnectIfConnected(null); - try { - this.gui.getController().createServer(result.getPort(), result.getPassword()); - } catch (IOException e) { - JOptionPane.showMessageDialog(this.gui.getFrame(), e.toString(), I18n.translate("menu.collab.server.start.error"), JOptionPane.ERROR_MESSAGE); - this.gui.getController().disconnectIfConnected(null); - } - }); - this.startServerMenu = item; - } - } - - /* - * Help menu - */ - { - JMenu menu = new JMenu(I18n.translate("menu.help")); - this.add(menu); - { - JMenuItem item = new JMenuItem(I18n.translate("menu.help.about")); - menu.add(item); - item.addActionListener(event -> AboutDialog.show(this.gui.getFrame())); - } - { - JMenuItem item = new JMenuItem(I18n.translate("menu.help.github")); - menu.add(item); - item.addActionListener(event -> { - try { - Desktop.getDesktop().browse(new URL("https://github.com/FabricMC/Enigma").toURI()); - } catch (URISyntaxException | IOException ignored) { - } - }); - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java b/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java deleted file mode 100644 index b92041c3..00000000 --- a/src/main/java/cuchaz/enigma/gui/elements/PopupMenuBar.java +++ /dev/null @@ -1,125 +0,0 @@ -package cuchaz.enigma.gui.elements; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -public class PopupMenuBar extends JPopupMenu { - - public final JMenuItem renameMenu; - public final JMenuItem editJavadocMenu; - public final JMenuItem showInheritanceMenu; - public final JMenuItem showImplementationsMenu; - public final JMenuItem showCallsMenu; - public final JMenuItem showCallsSpecificMenu; - public final JMenuItem openEntryMenu; - public final JMenuItem openPreviousMenu; - public final JMenuItem openNextMenu; - public final JMenuItem toggleMappingMenu; - - public PopupMenuBar(Gui gui) { - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.rename")); - menu.addActionListener(event -> gui.startRename()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_R, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.renameMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.javadoc")); - menu.addActionListener(event -> gui.startDocChange()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.editJavadocMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.inheritance")); - menu.addActionListener(event -> gui.showInheritance()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_I, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.showInheritanceMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.implementations")); - menu.addActionListener(event -> gui.showImplementations()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_M, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.showImplementationsMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.calls")); - menu.addActionListener(event -> gui.showCalls(true)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.showCallsMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.calls.specific")); - menu.addActionListener(event -> gui.showCalls(false)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, InputEvent.CTRL_DOWN_MASK + InputEvent.SHIFT_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.showCallsSpecificMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.declaration")); - menu.addActionListener(event -> gui.getController().navigateTo(gui.cursorReference.entry)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_N, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.openEntryMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.back")); - menu.addActionListener(event -> gui.getController().openPreviousReference()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_P, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.openPreviousMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.forward")); - menu.addActionListener(event -> gui.getController().openNextReference()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_E, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.openNextMenu = menu; - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.mark_deobfuscated")); - menu.addActionListener(event -> gui.toggleMapping()); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, InputEvent.CTRL_DOWN_MASK)); - menu.setEnabled(false); - this.add(menu); - this.toggleMappingMenu = menu; - } - { - this.add(new JSeparator()); - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.zoom.in")); - menu.addActionListener(event -> gui.editor.offsetEditorZoom(2)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_PLUS, InputEvent.CTRL_DOWN_MASK)); - this.add(menu); - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.zoom.out")); - menu.addActionListener(event -> gui.editor.offsetEditorZoom(-2)); - menu.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_MINUS, InputEvent.CTRL_DOWN_MASK)); - this.add(menu); - } - { - JMenuItem menu = new JMenuItem(I18n.translate("popup_menu.zoom.reset")); - menu.addActionListener(event -> gui.editor.resetEditorZoom()); - this.add(menu); - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java deleted file mode 100644 index f5f66287..00000000 --- a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserAny.java +++ /dev/null @@ -1,10 +0,0 @@ -package cuchaz.enigma.gui.filechooser; - -import javax.swing.*; - -public class FileChooserAny extends JFileChooser { - public FileChooserAny() { - this.setFileSelectionMode(JFileChooser.FILES_AND_DIRECTORIES); - this.setAcceptAllFileFilterUsed(false); - } -} \ No newline at end of file diff --git a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java deleted file mode 100644 index cea11a68..00000000 --- a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFile.java +++ /dev/null @@ -1,8 +0,0 @@ -package cuchaz.enigma.gui.filechooser; - -import javax.swing.*; - -public class FileChooserFile extends JFileChooser { - public FileChooserFile() { - } -} diff --git a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java b/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java deleted file mode 100644 index c16e0afc..00000000 --- a/src/main/java/cuchaz/enigma/gui/filechooser/FileChooserFolder.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.gui.filechooser; - -import javax.swing.*; - -public class FileChooserFolder extends JFileChooser { - - public FileChooserFolder() { - this.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY); - this.setAcceptAllFileFilterUsed(false); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java b/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java deleted file mode 100644 index cef64943..00000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/BoxHighlightPainter.java +++ /dev/null @@ -1,69 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.highlight; - -import cuchaz.enigma.config.Config; - -import javax.swing.text.BadLocationException; -import javax.swing.text.Highlighter; -import javax.swing.text.JTextComponent; -import java.awt.*; - -public class BoxHighlightPainter implements Highlighter.HighlightPainter { - private Color fillColor; - private Color borderColor; - - protected BoxHighlightPainter(Color fillColor, Color borderColor) { - this.fillColor = fillColor; - this.borderColor = borderColor; - } - - public static BoxHighlightPainter create(Config.AlphaColorEntry entry, Config.AlphaColorEntry entryOutline) { - return new BoxHighlightPainter(entry != null ? entry.get() : null, entryOutline != null ? entryOutline.get() : null); - } - - public static Rectangle getBounds(JTextComponent text, int start, int end) { - try { - // determine the bounds of the text - Rectangle startRect = text.modelToView(start); - Rectangle endRect = text.modelToView(end); - Rectangle bounds = startRect.union(endRect); - - // adjust the box so it looks nice - bounds.x -= 2; - bounds.width += 2; - bounds.y += 1; - bounds.height -= 2; - - return bounds; - } catch (BadLocationException ex) { - // don't care... just return something - return new Rectangle(0, 0, 0, 0); - } - } - - @Override - public void paint(Graphics g, int start, int end, Shape shape, JTextComponent text) { - Rectangle bounds = getBounds(text, start, end); - - // fill the area - if (this.fillColor != null) { - g.setColor(this.fillColor); - g.fillRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 4, 4); - } - - // draw a box around the area - g.setColor(this.borderColor); - g.drawRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 4, 4); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/highlight/SelectionHighlightPainter.java b/src/main/java/cuchaz/enigma/gui/highlight/SelectionHighlightPainter.java deleted file mode 100644 index 81a70a92..00000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/SelectionHighlightPainter.java +++ /dev/null @@ -1,31 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.highlight; - -import cuchaz.enigma.config.Config; - -import javax.swing.text.Highlighter; -import javax.swing.text.JTextComponent; -import java.awt.*; - -public class SelectionHighlightPainter implements Highlighter.HighlightPainter { - - @Override - public void paint(Graphics g, int start, int end, Shape shape, JTextComponent text) { - // draw a thick border - Graphics2D g2d = (Graphics2D) g; - Rectangle bounds = BoxHighlightPainter.getBounds(text, start, end); - g2d.setColor(new Color(Config.getInstance().selectionHighlightColor)); - g2d.setStroke(new BasicStroke(2.0f)); - g2d.drawRoundRect(bounds.x, bounds.y, bounds.width, bounds.height, 4, 4); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/highlight/TokenHighlightType.java b/src/main/java/cuchaz/enigma/gui/highlight/TokenHighlightType.java deleted file mode 100644 index ae23f324..00000000 --- a/src/main/java/cuchaz/enigma/gui/highlight/TokenHighlightType.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.gui.highlight; - -public enum TokenHighlightType { - OBFUSCATED, - DEOBFUSCATED, - PROPOSED -} diff --git a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java deleted file mode 100644 index 922f8f24..00000000 --- a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorClassNode.java +++ /dev/null @@ -1,72 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.node; - -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -import javax.swing.tree.DefaultMutableTreeNode; - -public class ClassSelectorClassNode extends DefaultMutableTreeNode { - - private final ClassEntry obfEntry; - private ClassEntry classEntry; - - public ClassSelectorClassNode(ClassEntry obfEntry, ClassEntry classEntry) { - this.obfEntry = obfEntry; - this.classEntry = classEntry; - this.setUserObject(classEntry); - } - - public ClassEntry getObfEntry() { - return obfEntry; - } - - public ClassEntry getClassEntry() { - return this.classEntry; - } - - @Override - public String toString() { - return this.classEntry.getSimpleName(); - } - - @Override - public boolean equals(Object other) { - return other instanceof ClassSelectorClassNode && equals((ClassSelectorClassNode) other); - } - - @Override - public int hashCode() { - return 17 + (classEntry != null ? classEntry.hashCode() : 0); - } - - @Override - public Object getUserObject() { - return classEntry; - } - - @Override - public void setUserObject(Object userObject) { - String packageName = ""; - if (classEntry.getPackageName() != null) - packageName = classEntry.getPackageName() + "/"; - if (userObject instanceof String) - this.classEntry = new ClassEntry(packageName + userObject); - else if (userObject instanceof ClassEntry) - this.classEntry = (ClassEntry) userObject; - super.setUserObject(classEntry); - } - - public boolean equals(ClassSelectorClassNode other) { - return this.classEntry.equals(other.classEntry); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java b/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java deleted file mode 100644 index caa985c9..00000000 --- a/src/main/java/cuchaz/enigma/gui/node/ClassSelectorPackageNode.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.gui.node; - -import javax.swing.tree.DefaultMutableTreeNode; - -public class ClassSelectorPackageNode extends DefaultMutableTreeNode { - - private String packageName; - - public ClassSelectorPackageNode(String packageName) { - this.packageName = packageName != null ? packageName : "(none)"; - } - - public String getPackageName() { - return packageName; - } - - @Override - public Object getUserObject() { - return packageName; - } - - @Override - public void setUserObject(Object userObject) { - if (userObject instanceof String) - this.packageName = (String) userObject; - super.setUserObject(userObject); - } - - @Override - public String toString() { - return !packageName.equals("(none)") ? this.packageName : "(none)"; - } - - @Override - public boolean equals(Object other) { - return other instanceof ClassSelectorPackageNode && equals((ClassSelectorPackageNode) other); - } - - @Override - public int hashCode() { - return packageName.hashCode(); - } - - public boolean equals(ClassSelectorPackageNode other) { - return other != null && this.packageName.equals(other.packageName); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java b/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java deleted file mode 100644 index c24226b3..00000000 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelDeobf.java +++ /dev/null @@ -1,26 +0,0 @@ -package cuchaz.enigma.gui.panels; - -import cuchaz.enigma.gui.ClassSelector; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.*; - -public class PanelDeobf extends JPanel { - - public final ClassSelector deobfClasses; - private final Gui gui; - - public PanelDeobf(Gui gui) { - this.gui = gui; - - this.deobfClasses = new ClassSelector(gui, ClassSelector.DEOBF_CLASS_COMPARATOR, true); - this.deobfClasses.setSelectionListener(gui.getController()::navigateTo); - this.deobfClasses.setRenameSelectionListener(gui::onPanelRename); - - this.setLayout(new BorderLayout()); - this.add(new JLabel(I18n.translate("info_panel.classes.deobfuscated")), BorderLayout.NORTH); - this.add(new JScrollPane(this.deobfClasses), BorderLayout.CENTER); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java b/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java deleted file mode 100644 index 8637afd9..00000000 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelEditor.java +++ /dev/null @@ -1,171 +0,0 @@ -package cuchaz.enigma.gui.panels; - -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.config.Config; -import cuchaz.enigma.gui.BrowserCaret; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.gui.util.ScaleUtil; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.awt.event.MouseAdapter; -import java.awt.event.MouseEvent; - -public class PanelEditor extends JEditorPane { - private boolean mouseIsPressed = false; - public int fontSize = 12; - - public PanelEditor(Gui gui) { - this.setEditable(false); - this.setSelectionColor(new Color(31, 46, 90)); - this.setCaret(new BrowserCaret()); - this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); - this.addCaretListener(event -> gui.onCaretMove(event.getDot(), mouseIsPressed)); - final PanelEditor self = this; - this.addMouseListener(new MouseAdapter() { - @Override - public void mousePressed(MouseEvent mouseEvent) { - mouseIsPressed = true; - } - - @Override - public void mouseReleased(MouseEvent e) { - switch (e.getButton()) { - case MouseEvent.BUTTON3: // Right click - self.setCaretPosition(self.viewToModel(e.getPoint())); - break; - - case 4: // Back navigation - gui.getController().openPreviousReference(); - break; - - case 5: // Forward navigation - gui.getController().openNextReference(); - break; - } - mouseIsPressed = false; - } - }); - this.addKeyListener(new KeyAdapter() { - @Override - public void keyPressed(KeyEvent event) { - if (event.isControlDown()) { - gui.setShouldNavigateOnClick(false); - switch (event.getKeyCode()) { - case KeyEvent.VK_I: - gui.popupMenu.showInheritanceMenu.doClick(); - break; - - case KeyEvent.VK_M: - gui.popupMenu.showImplementationsMenu.doClick(); - break; - - case KeyEvent.VK_N: - gui.popupMenu.openEntryMenu.doClick(); - break; - - case KeyEvent.VK_P: - gui.popupMenu.openPreviousMenu.doClick(); - break; - - case KeyEvent.VK_E: - gui.popupMenu.openNextMenu.doClick(); - break; - - case KeyEvent.VK_C: - if (event.isShiftDown()) { - gui.popupMenu.showCallsSpecificMenu.doClick(); - } else { - gui.popupMenu.showCallsMenu.doClick(); - } - break; - - case KeyEvent.VK_O: - gui.popupMenu.toggleMappingMenu.doClick(); - break; - - case KeyEvent.VK_R: - gui.popupMenu.renameMenu.doClick(); - break; - - case KeyEvent.VK_D: - gui.popupMenu.editJavadocMenu.doClick(); - break; - - case KeyEvent.VK_F5: - gui.getController().refreshCurrentClass(); - break; - - case KeyEvent.VK_F: - // prevent navigating on click when quick find activated - break; - - case KeyEvent.VK_ADD: - case KeyEvent.VK_EQUALS: - case KeyEvent.VK_PLUS: - self.offsetEditorZoom(2); - break; - case KeyEvent.VK_SUBTRACT: - case KeyEvent.VK_MINUS: - self.offsetEditorZoom(-2); - break; - - default: - gui.setShouldNavigateOnClick(true); // CTRL - break; - } - } - } - - @Override - public void keyTyped(KeyEvent event) { - if (!gui.popupMenu.renameMenu.isEnabled()) return; - - if (!event.isControlDown() && !event.isAltDown() && Character.isJavaIdentifierPart(event.getKeyChar())) { - EnigmaProject project = gui.getController().project; - EntryReference, Entry> reference = project.getMapper().deobfuscate(gui.cursorReference); - Entry entry = reference.getNameableEntry(); - - String name = String.valueOf(event.getKeyChar()); - if (entry instanceof ClassEntry && ((ClassEntry) entry).getParent() == null) { - String packageName = ((ClassEntry) entry).getPackageName(); - if (packageName != null) { - name = packageName + "/" + name; - } - } - - gui.popupMenu.renameMenu.doClick(); - gui.renameTextField.setText(name); - } - } - - @Override - public void keyReleased(KeyEvent event) { - gui.setShouldNavigateOnClick(event.isControlDown()); - } - }); - } - - public void offsetEditorZoom(int zoomAmount) { - int newResult = this.fontSize + zoomAmount; - if (newResult > 8 && newResult < 72) { - this.fontSize = newResult; - this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); - } - } - - public void resetEditorZoom() { - this.fontSize = 12; - this.setFont(ScaleUtil.getFont(this.getFont().getFontName(), Font.PLAIN, this.fontSize)); - } - - @Override - public Color getCaretColor() { - return new Color(Config.getInstance().caretColor); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java b/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java deleted file mode 100644 index de069bc6..00000000 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelIdentifier.java +++ /dev/null @@ -1,32 +0,0 @@ -package cuchaz.enigma.gui.panels; - -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.gui.util.ScaleUtil; -import cuchaz.enigma.utils.Utils; - -import javax.swing.*; -import java.awt.*; - -public class PanelIdentifier extends JPanel { - - private final Gui gui; - - public PanelIdentifier(Gui gui) { - this.gui = gui; - - this.setLayout(new GridLayout(4, 1, 0, 0)); - this.setPreferredSize(ScaleUtil.getDimension(0, 100)); - this.setBorder(BorderFactory.createTitledBorder(I18n.translate("info_panel.identifier"))); - } - - public void clearReference() { - this.removeAll(); - JLabel label = new JLabel(I18n.translate("info_panel.identifier.none")); - Utils.unboldLabel(label); - label.setHorizontalAlignment(JLabel.CENTER); - this.add(label); - - gui.redraw(); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java b/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java deleted file mode 100644 index dd7f9f97..00000000 --- a/src/main/java/cuchaz/enigma/gui/panels/PanelObf.java +++ /dev/null @@ -1,37 +0,0 @@ -package cuchaz.enigma.gui.panels; - -import cuchaz.enigma.gui.ClassSelector; -import cuchaz.enigma.gui.Gui; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.utils.I18n; - -import javax.swing.*; -import java.awt.*; -import java.util.Comparator; - -public class PanelObf extends JPanel { - - public final ClassSelector obfClasses; - private final Gui gui; - - public PanelObf(Gui gui) { - this.gui = gui; - - Comparator obfClassComparator = (a, b) -> { - String aname = a.getFullName(); - String bname = b.getFullName(); - if (aname.length() != bname.length()) { - return aname.length() - bname.length(); - } - return aname.compareTo(bname); - }; - - this.obfClasses = new ClassSelector(gui, obfClassComparator, false); - this.obfClasses.setSelectionListener(gui.getController()::navigateTo); - this.obfClasses.setRenameSelectionListener(gui::onPanelRename); - - this.setLayout(new BorderLayout()); - this.add(new JLabel(I18n.translate("info_panel.classes.obfuscated")), BorderLayout.NORTH); - this.add(new JScrollPane(this.obfClasses), BorderLayout.CENTER); - } -} diff --git a/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java b/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java deleted file mode 100644 index e7835304..00000000 --- a/src/main/java/cuchaz/enigma/gui/stats/StatsGenerator.java +++ /dev/null @@ -1,197 +0,0 @@ -package cuchaz.enigma.gui.stats; - -import com.google.gson.GsonBuilder; -import cuchaz.enigma.EnigmaProject; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.analysis.index.EntryIndex; -import cuchaz.enigma.api.service.NameProposalService; -import cuchaz.enigma.api.service.ObfuscationTestService; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; -import cuchaz.enigma.utils.I18n; - -import java.util.*; - -public class StatsGenerator { - private final EntryIndex entryIndex; - private final EntryRemapper mapper; - private final EntryResolver entryResolver; - private final List obfuscationTestServices; - private final List nameProposalServices; - - public StatsGenerator(EnigmaProject project) { - entryIndex = project.getJarIndex().getEntryIndex(); - mapper = project.getMapper(); - entryResolver = project.getJarIndex().getEntryResolver(); - obfuscationTestServices = project.getEnigma().getServices().get(ObfuscationTestService.TYPE); - nameProposalServices = project.getEnigma().getServices().get(NameProposalService.TYPE); - } - - public String generate(ProgressListener progress, Set includedMembers) { - includedMembers = EnumSet.copyOf(includedMembers); - int totalWork = 0; - - if (includedMembers.contains(StatsMember.METHODS) || includedMembers.contains(StatsMember.PARAMETERS)) { - totalWork += entryIndex.getMethods().size(); - } - - if (includedMembers.contains(StatsMember.FIELDS)) { - totalWork += entryIndex.getFields().size(); - } - - if (includedMembers.contains(StatsMember.CLASSES)) { - totalWork += entryIndex.getClasses().size(); - } - - progress.init(totalWork, I18n.translate("progress.stats")); - - Map counts = new HashMap<>(); - - int numDone = 0; - if (includedMembers.contains(StatsMember.METHODS) || includedMembers.contains(StatsMember.PARAMETERS)) { - for (MethodEntry method : entryIndex.getMethods()) { - progress.step(numDone++, I18n.translate("type.methods")); - MethodEntry root = entryResolver - .resolveEntry(method, ResolutionStrategy.RESOLVE_ROOT) - .stream() - .findFirst() - .orElseThrow(AssertionError::new); - - if (root == method && !((MethodDefEntry) method).getAccess().isSynthetic()) { - if (includedMembers.contains(StatsMember.METHODS)) { - update(counts, method); - } - - if (includedMembers.contains(StatsMember.PARAMETERS)) { - int index = ((MethodDefEntry) method).getAccess().isStatic() ? 0 : 1; - for (TypeDescriptor argument : method.getDesc().getArgumentDescs()) { - update(counts, new LocalVariableEntry(method, index, "", true,null)); - index += argument.getSize(); - } - } - } - } - } - - if (includedMembers.contains(StatsMember.FIELDS)) { - for (FieldEntry field : entryIndex.getFields()) { - progress.step(numDone++, I18n.translate("type.fields")); - update(counts, field); - } - } - - if (includedMembers.contains(StatsMember.CLASSES)) { - for (ClassEntry clazz : entryIndex.getClasses()) { - progress.step(numDone++, I18n.translate("type.classes")); - update(counts, clazz); - } - } - - progress.step(-1, I18n.translate("progress.stats.data")); - - Tree tree = new Tree<>(); - - for (Map.Entry entry : counts.entrySet()) { - if (entry.getKey().startsWith("com.mojang")) continue; // just a few unmapped names, no point in having a subsection - tree.getNode(entry.getKey()).value = entry.getValue(); - } - - tree.collapse(tree.root); - return new GsonBuilder().setPrettyPrinting().create().toJson(tree.root); - } - - private void update(Map counts, Entry entry) { - if (isObfuscated(entry)) { - String parent = mapper.deobfuscate(entry.getAncestry().get(0)).getName().replace('/', '.'); - counts.put(parent, counts.getOrDefault(parent, 0) + 1); - } - } - - private boolean isObfuscated(Entry entry) { - String name = entry.getName(); - - if (!obfuscationTestServices.isEmpty()) { - for (ObfuscationTestService service : obfuscationTestServices) { - if (service.testDeobfuscated(entry)) { - return false; - } - } - } - - if (!nameProposalServices.isEmpty()) { - for (NameProposalService service : nameProposalServices) { - if (service.proposeName(entry, mapper).isPresent()) { - return false; - } - } - } - - String mappedName = mapper.deobfuscate(entry).getName(); - if (mappedName != null && !mappedName.isEmpty() && !mappedName.equals(name)) { - return false; - } - - return true; - } - - private static class Tree { - public final Node root; - private final Map> nodes = new HashMap<>(); - - public static class Node { - public String name; - public T value; - public List> children = new ArrayList<>(); - private final transient Map> namedChildren = new HashMap<>(); - - public Node(String name, T value) { - this.name = name; - this.value = value; - } - } - - public Tree() { - root = new Node<>("", null); - } - - public Node getNode(String name) { - Node node = nodes.get(name); - - if (node == null) { - node = root; - - for (String part : name.split("\\.")) { - Node child = node.namedChildren.get(part); - - if (child == null) { - child = new Node<>(part, null); - node.namedChildren.put(part, child); - node.children.add(child); - } - - node = child; - } - - nodes.put(name, node); - } - - return node; - } - - public void collapse(Node node) { - while (node.children.size() == 1) { - Node child = node.children.get(0); - node.name = node.name.isEmpty() ? child.name : node.name + "." + child.name; - node.children = child.children; - node.value = child.value; - } - - for (Node child : node.children) { - collapse(child); - } - } - } -} diff --git a/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java b/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java deleted file mode 100644 index 70b4f40d..00000000 --- a/src/main/java/cuchaz/enigma/gui/stats/StatsMember.java +++ /dev/null @@ -1,8 +0,0 @@ -package cuchaz.enigma.gui.stats; - -public enum StatsMember { - METHODS, - FIELDS, - PARAMETERS, - CLASSES -} diff --git a/src/main/java/cuchaz/enigma/gui/util/AbstractListCellRenderer.java b/src/main/java/cuchaz/enigma/gui/util/AbstractListCellRenderer.java deleted file mode 100644 index 612e3e92..00000000 --- a/src/main/java/cuchaz/enigma/gui/util/AbstractListCellRenderer.java +++ /dev/null @@ -1,77 +0,0 @@ -package cuchaz.enigma.gui.util; - -import java.awt.Component; -import java.awt.event.MouseEvent; - -import javax.swing.*; -import javax.swing.border.Border; - -public abstract class AbstractListCellRenderer extends JPanel implements ListCellRenderer { - - private static final Border NO_FOCUS_BORDER = BorderFactory.createEmptyBorder(1, 1, 1, 1); - - private Border noFocusBorder; - - public AbstractListCellRenderer() { - setBorder(getNoFocusBorder()); - } - - protected Border getNoFocusBorder() { - if (noFocusBorder == null) { - Border border = UIManager.getLookAndFeel().getDefaults().getBorder("List.List.cellNoFocusBorder"); - noFocusBorder = border != null ? border : NO_FOCUS_BORDER; - } - return noFocusBorder; - } - - protected Border getBorder(boolean isSelected, boolean cellHasFocus) { - Border b = null; - if (cellHasFocus) { - UIDefaults defaults = UIManager.getLookAndFeel().getDefaults(); - if (isSelected) { - b = defaults.getBorder("List.focusSelectedCellHighlightBorder"); - } - if (b == null) { - b = defaults.getBorder("List.focusCellHighlightBorder"); - } - } else { - b = getNoFocusBorder(); - } - return b; - } - - public abstract void updateUiForEntry(JList list, E value, int index, boolean isSelected, boolean cellHasFocus); - - @Override - public Component getListCellRendererComponent(JList list, E value, int index, boolean isSelected, boolean cellHasFocus) { - updateUiForEntry(list, value, index, isSelected, cellHasFocus); - - if (isSelected) { - setBackground(list.getSelectionBackground()); - setForeground(list.getSelectionForeground()); - } else { - setBackground(list.getBackground()); - setForeground(list.getForeground()); - } - - setEnabled(list.isEnabled()); - setFont(list.getFont()); - - setBorder(getBorder(isSelected, cellHasFocus)); - - // This isn't the width of the cell, but it's close enough for where it's needed (getComponentAt in getToolTipText) - setSize(list.getWidth(), getPreferredSize().height); - - return this; - } - - @Override - public String getToolTipText(MouseEvent event) { - Component c = getComponentAt(event.getPoint()); - if (c instanceof JComponent) { - return ((JComponent) c).getToolTipText(); - } - return getToolTipText(); - } - -} diff --git a/src/main/java/cuchaz/enigma/gui/util/History.java b/src/main/java/cuchaz/enigma/gui/util/History.java deleted file mode 100644 index 94f31051..00000000 --- a/src/main/java/cuchaz/enigma/gui/util/History.java +++ /dev/null @@ -1,49 +0,0 @@ -package cuchaz.enigma.gui.util; - -import com.google.common.collect.Queues; - -import java.util.Deque; - -public class History { - private final Deque previous = Queues.newArrayDeque(); - private final Deque next = Queues.newArrayDeque(); - private T current; - - public History(T initial) { - current = initial; - } - - public T getCurrent() { - return current; - } - - public void push(T value) { - previous.addLast(current); - current = value; - next.clear(); - } - - public void replace(T value) { - current = value; - } - - public boolean canGoBack() { - return !previous.isEmpty(); - } - - public T goBack() { - next.addFirst(current); - current = previous.removeLast(); - return current; - } - - public boolean canGoForward() { - return !next.isEmpty(); - } - - public T goForward() { - previous.addLast(current); - current = next.removeFirst(); - return current; - } -} diff --git a/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java b/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java deleted file mode 100644 index d045c6d5..00000000 --- a/src/main/java/cuchaz/enigma/gui/util/ScaleChangeListener.java +++ /dev/null @@ -1,8 +0,0 @@ -package cuchaz.enigma.gui.util; - -@FunctionalInterface -public interface ScaleChangeListener { - - void onScaleChanged(float scale, float oldScale); - -} diff --git a/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java b/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java deleted file mode 100644 index 9f722e9f..00000000 --- a/src/main/java/cuchaz/enigma/gui/util/ScaleUtil.java +++ /dev/null @@ -1,110 +0,0 @@ -package cuchaz.enigma.gui.util; - -import java.awt.Dimension; -import java.awt.Font; -import java.io.IOException; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.List; - -import javax.swing.BorderFactory; -import javax.swing.UIManager; -import javax.swing.border.Border; - -import com.github.swingdpi.UiDefaultsScaler; -import com.github.swingdpi.plaf.BasicTweaker; -import com.github.swingdpi.plaf.MetalTweaker; -import com.github.swingdpi.plaf.NimbusTweaker; -import com.github.swingdpi.plaf.WindowsTweaker; -import cuchaz.enigma.config.Config; -import de.sciss.syntaxpane.DefaultSyntaxKit; - -public class ScaleUtil { - - private static List listeners = new ArrayList<>(); - - public static float getScaleFactor() { - return Config.getInstance().scaleFactor; - } - - public static void setScaleFactor(float scaleFactor) { - float oldScale = getScaleFactor(); - float clamped = Math.min(Math.max(0.25f, scaleFactor), 10.0f); - Config.getInstance().scaleFactor = clamped; - try { - Config.getInstance().saveConfig(); - } catch (IOException e) { - e.printStackTrace(); - } - listeners.forEach(l -> l.onScaleChanged(clamped, oldScale)); - } - - public static void addListener(ScaleChangeListener listener) { - listeners.add(listener); - } - - public static void removeListener(ScaleChangeListener listener) { - listeners.remove(listener); - } - - public static Dimension getDimension(int width, int height) { - return new Dimension(scale(width), scale(height)); - } - - public static Font getFont(String fontName, int plain, int fontSize) { - return scaleFont(new Font(fontName, plain, fontSize)); - } - - public static Font scaleFont(Font font) { - return createTweakerForCurrentLook(getScaleFactor()).modifyFont("", font); - } - - public static float scale(float f) { - return f * getScaleFactor(); - } - - public static float invert(float f) { - return f / getScaleFactor(); - } - - public static int scale(int i) { - return (int) (i * getScaleFactor()); - } - - public static Border createEmptyBorder(int top, int left, int bottom, int right) { - return BorderFactory.createEmptyBorder(scale(top), scale(left), scale(bottom), scale(right)); - } - - public static int invert(int i) { - return (int) (i / getScaleFactor()); - } - - public static void applyScaling() { - float scale = getScaleFactor(); - UiDefaultsScaler.updateAndApplyGlobalScaling((int) (100 * scale), true); - try { - Field defaultFontField = DefaultSyntaxKit.class.getDeclaredField("DEFAULT_FONT"); - defaultFontField.setAccessible(true); - Font font = (Font) defaultFontField.get(null); - font = font.deriveFont(12 * scale); - defaultFontField.set(null, font); - } catch (NoSuchFieldException | IllegalAccessException e) { - e.printStackTrace(); - } - } - - private static BasicTweaker createTweakerForCurrentLook(float dpiScaling) { - String testString = UIManager.getLookAndFeel().getName().toLowerCase(); - if (testString.contains("windows")) { - return new WindowsTweaker(dpiScaling, testString.contains("classic")); - } - if (testString.contains("metal")) { - return new MetalTweaker(dpiScaling); - } - if (testString.contains("nimbus")) { - return new NimbusTweaker(dpiScaling); - } - return new BasicTweaker(dpiScaling); - } - -} diff --git a/src/main/java/cuchaz/enigma/network/DedicatedEnigmaServer.java b/src/main/java/cuchaz/enigma/network/DedicatedEnigmaServer.java deleted file mode 100644 index 2cfe8233..00000000 --- a/src/main/java/cuchaz/enigma/network/DedicatedEnigmaServer.java +++ /dev/null @@ -1,164 +0,0 @@ -package cuchaz.enigma.network; - -import com.google.common.io.MoreFiles; -import cuchaz.enigma.*; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.mapping.serde.MappingFormat; -import cuchaz.enigma.utils.Utils; -import joptsimple.OptionParser; -import joptsimple.OptionSet; -import joptsimple.OptionSpec; - -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.Executors; -import java.util.concurrent.LinkedBlockingDeque; -import java.util.concurrent.TimeUnit; - -public class DedicatedEnigmaServer extends EnigmaServer { - - private final EnigmaProfile profile; - private final MappingFormat mappingFormat; - private final Path mappingsFile; - private final PrintWriter log; - private BlockingQueue tasks = new LinkedBlockingDeque<>(); - - public DedicatedEnigmaServer( - byte[] jarChecksum, - char[] password, - EnigmaProfile profile, - MappingFormat mappingFormat, - Path mappingsFile, - PrintWriter log, - EntryRemapper mappings, - int port - ) { - super(jarChecksum, password, mappings, port); - this.profile = profile; - this.mappingFormat = mappingFormat; - this.mappingsFile = mappingsFile; - this.log = log; - } - - @Override - protected void runOnThread(Runnable task) { - tasks.add(task); - } - - @Override - public void log(String message) { - super.log(message); - log.println(message); - } - - public static void main(String[] args) { - OptionParser parser = new OptionParser(); - - OptionSpec jarOpt = parser.accepts("jar", "Jar file to open at startup") - .withRequiredArg() - .required() - .withValuesConvertedBy(Main.PathConverter.INSTANCE); - - OptionSpec mappingsOpt = parser.accepts("mappings", "Mappings file to open at startup") - .withRequiredArg() - .required() - .withValuesConvertedBy(Main.PathConverter.INSTANCE); - - OptionSpec profileOpt = parser.accepts("profile", "Profile json to apply at startup") - .withRequiredArg() - .withValuesConvertedBy(Main.PathConverter.INSTANCE); - - OptionSpec portOpt = parser.accepts("port", "Port to run the server on") - .withOptionalArg() - .ofType(Integer.class) - .defaultsTo(EnigmaServer.DEFAULT_PORT); - - OptionSpec passwordOpt = parser.accepts("password", "The password to join the server") - .withRequiredArg() - .defaultsTo(""); - - OptionSpec logFileOpt = parser.accepts("log", "The log file to write to") - .withRequiredArg() - .withValuesConvertedBy(Main.PathConverter.INSTANCE) - .defaultsTo(Paths.get("log.txt")); - - OptionSet parsedArgs = parser.parse(args); - Path jar = parsedArgs.valueOf(jarOpt); - Path mappingsFile = parsedArgs.valueOf(mappingsOpt); - Path profileFile = parsedArgs.valueOf(profileOpt); - int port = parsedArgs.valueOf(portOpt); - char[] password = parsedArgs.valueOf(passwordOpt).toCharArray(); - if (password.length > EnigmaServer.MAX_PASSWORD_LENGTH) { - System.err.println("Password too long, must be at most " + EnigmaServer.MAX_PASSWORD_LENGTH + " characters"); - System.exit(1); - } - Path logFile = parsedArgs.valueOf(logFileOpt); - - System.out.println("Starting Enigma server"); - DedicatedEnigmaServer server; - try { - byte[] checksum = Utils.zipSha1(parsedArgs.valueOf(jarOpt)); - - EnigmaProfile profile = EnigmaProfile.read(profileFile); - Enigma enigma = Enigma.builder().setProfile(profile).build(); - System.out.println("Indexing Jar..."); - EnigmaProject project = enigma.openJar(jar, ProgressListener.none()); - - MappingFormat mappingFormat = MappingFormat.ENIGMA_DIRECTORY; - EntryRemapper mappings; - if (!Files.exists(mappingsFile)) { - mappings = EntryRemapper.empty(project.getJarIndex()); - } else { - System.out.println("Reading mappings..."); - if (Files.isDirectory(mappingsFile)) { - mappingFormat = MappingFormat.ENIGMA_DIRECTORY; - } else if ("zip".equalsIgnoreCase(MoreFiles.getFileExtension(mappingsFile))) { - mappingFormat = MappingFormat.ENIGMA_ZIP; - } else { - mappingFormat = MappingFormat.ENIGMA_FILE; - } - mappings = EntryRemapper.mapped(project.getJarIndex(), mappingFormat.read(mappingsFile, ProgressListener.none(), profile.getMappingSaveParameters())); - } - - PrintWriter log = new PrintWriter(Files.newBufferedWriter(logFile)); - - server = new DedicatedEnigmaServer(checksum, password, profile, mappingFormat, mappingsFile, log, mappings, port); - server.start(); - System.out.println("Server started"); - } catch (IOException | MappingParseException e) { - System.err.println("Error starting server!"); - e.printStackTrace(); - System.exit(1); - return; - } - - // noinspection RedundantSuppression - // noinspection Convert2MethodRef - javac 8 bug - Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> server.runOnThread(() -> server.saveMappings()), 0, 1, TimeUnit.MINUTES); - Runtime.getRuntime().addShutdownHook(new Thread(server::saveMappings)); - - while (true) { - try { - server.tasks.take().run(); - } catch (InterruptedException e) { - break; - } - } - } - - @Override - public synchronized void stop() { - super.stop(); - System.exit(0); - } - - private void saveMappings() { - mappingFormat.write(getMappings().getObfToDeobf(), getMappings().takeMappingDelta(), mappingsFile, ProgressListener.none(), profile.getMappingSaveParameters()); - log.flush(); - } -} diff --git a/src/main/java/cuchaz/enigma/network/EnigmaClient.java b/src/main/java/cuchaz/enigma/network/EnigmaClient.java deleted file mode 100644 index bfa53d73..00000000 --- a/src/main/java/cuchaz/enigma/network/EnigmaClient.java +++ /dev/null @@ -1,85 +0,0 @@ -package cuchaz.enigma.network; - -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.network.packet.LoginC2SPacket; -import cuchaz.enigma.network.packet.Packet; -import cuchaz.enigma.network.packet.PacketRegistry; - -import javax.swing.SwingUtilities; -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.DataOutput; -import java.io.DataOutputStream; -import java.io.EOFException; -import java.io.IOException; -import java.net.Socket; -import java.net.SocketException; - -public class EnigmaClient { - - private final GuiController controller; - - private final String ip; - private final int port; - private Socket socket; - private DataOutput output; - - public EnigmaClient(GuiController controller, String ip, int port) { - this.controller = controller; - this.ip = ip; - this.port = port; - } - - public void connect() throws IOException { - socket = new Socket(ip, port); - output = new DataOutputStream(socket.getOutputStream()); - Thread thread = new Thread(() -> { - try { - DataInput input = new DataInputStream(socket.getInputStream()); - while (true) { - int packetId; - try { - packetId = input.readUnsignedByte(); - } catch (EOFException | SocketException e) { - break; - } - Packet packet = PacketRegistry.createS2CPacket(packetId); - if (packet == null) { - throw new IOException("Received invalid packet id " + packetId); - } - packet.read(input); - SwingUtilities.invokeLater(() -> packet.handle(controller)); - } - } catch (IOException e) { - controller.disconnectIfConnected(e.toString()); - return; - } - controller.disconnectIfConnected("Disconnected"); - }); - thread.setName("Client I/O thread"); - thread.setDaemon(true); - thread.start(); - } - - public synchronized void disconnect() { - if (socket != null && !socket.isClosed()) { - try { - socket.close(); - } catch (IOException e1) { - System.err.println("Failed to close socket"); - e1.printStackTrace(); - } - } - } - - - public void sendPacket(Packet packet) { - try { - output.writeByte(PacketRegistry.getC2SId(packet)); - packet.write(output); - } catch (IOException e) { - controller.disconnectIfConnected(e.toString()); - } - } - -} diff --git a/src/main/java/cuchaz/enigma/network/EnigmaServer.java b/src/main/java/cuchaz/enigma/network/EnigmaServer.java deleted file mode 100644 index b0e15a3c..00000000 --- a/src/main/java/cuchaz/enigma/network/EnigmaServer.java +++ /dev/null @@ -1,292 +0,0 @@ -package cuchaz.enigma.network; - -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.network.packet.KickS2CPacket; -import cuchaz.enigma.network.packet.MessageS2CPacket; -import cuchaz.enigma.network.packet.Packet; -import cuchaz.enigma.network.packet.PacketRegistry; -import cuchaz.enigma.network.packet.RemoveMappingS2CPacket; -import cuchaz.enigma.network.packet.RenameS2CPacket; -import cuchaz.enigma.network.packet.UserListS2CPacket; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.utils.Message; - -import java.io.DataInput; -import java.io.DataInputStream; -import java.io.DataOutput; -import java.io.DataOutputStream; -import java.io.EOFException; -import java.io.IOException; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.CopyOnWriteArrayList; - -public abstract class EnigmaServer { - - // https://discordapp.com/channels/507304429255393322/566418023372816394/700292322918793347 - public static final int DEFAULT_PORT = 34712; - public static final int PROTOCOL_VERSION = 0; - public static final String OWNER_USERNAME = "Owner"; - public static final int CHECKSUM_SIZE = 20; - public static final int MAX_PASSWORD_LENGTH = 255; // length is written as a byte in the login packet - - private final int port; - private ServerSocket socket; - private List clients = new CopyOnWriteArrayList<>(); - private Map usernames = new HashMap<>(); - private Set unapprovedClients = new HashSet<>(); - - private final byte[] jarChecksum; - private final char[] password; - - public static final int DUMMY_SYNC_ID = 0; - private final EntryRemapper mappings; - private Map, Integer> syncIds = new HashMap<>(); - private Map> inverseSyncIds = new HashMap<>(); - private Map> clientsNeedingConfirmation = new HashMap<>(); - private int nextSyncId = DUMMY_SYNC_ID + 1; - - private static int nextIoId = 0; - - public EnigmaServer(byte[] jarChecksum, char[] password, EntryRemapper mappings, int port) { - this.jarChecksum = jarChecksum; - this.password = password; - this.mappings = mappings; - this.port = port; - } - - public void start() throws IOException { - socket = new ServerSocket(port); - log("Server started on " + socket.getInetAddress() + ":" + port); - Thread thread = new Thread(() -> { - try { - while (!socket.isClosed()) { - acceptClient(); - } - } catch (SocketException e) { - System.out.println("Server closed"); - } catch (IOException e) { - e.printStackTrace(); - } - }); - thread.setName("Server client listener"); - thread.setDaemon(true); - thread.start(); - } - - private void acceptClient() throws IOException { - Socket client = socket.accept(); - clients.add(client); - Thread thread = new Thread(() -> { - try { - DataInput input = new DataInputStream(client.getInputStream()); - while (true) { - int packetId; - try { - packetId = input.readUnsignedByte(); - } catch (EOFException | SocketException e) { - break; - } - Packet packet = PacketRegistry.createC2SPacket(packetId); - if (packet == null) { - throw new IOException("Received invalid packet id " + packetId); - } - packet.read(input); - runOnThread(() -> packet.handle(new ServerPacketHandler(client, this))); - } - } catch (IOException e) { - kick(client, e.toString()); - e.printStackTrace(); - return; - } - kick(client, "disconnect.disconnected"); - }); - thread.setName("Server I/O thread #" + (nextIoId++)); - thread.setDaemon(true); - thread.start(); - } - - public void stop() { - runOnThread(() -> { - if (socket != null && !socket.isClosed()) { - for (Socket client : clients) { - kick(client, "disconnect.server_closed"); - } - try { - socket.close(); - } catch (IOException e) { - System.err.println("Failed to close server socket"); - e.printStackTrace(); - } - } - }); - } - - public void kick(Socket client, String reason) { - if (!clients.remove(client)) return; - - sendPacket(client, new KickS2CPacket(reason)); - - clientsNeedingConfirmation.values().removeIf(list -> { - list.remove(client); - return list.isEmpty(); - }); - String username = usernames.remove(client); - try { - client.close(); - } catch (IOException e) { - System.err.println("Failed to close server client socket"); - e.printStackTrace(); - } - - if (username != null) { - System.out.println("Kicked " + username + " because " + reason); - sendMessage(Message.disconnect(username)); - } - sendUsernamePacket(); - } - - public boolean isUsernameTaken(String username) { - return usernames.containsValue(username); - } - - public void setUsername(Socket client, String username) { - usernames.put(client, username); - sendUsernamePacket(); - } - - private void sendUsernamePacket() { - List usernames = new ArrayList<>(this.usernames.values()); - Collections.sort(usernames); - sendToAll(new UserListS2CPacket(usernames)); - } - - public String getUsername(Socket client) { - return usernames.get(client); - } - - public void sendPacket(Socket client, Packet packet) { - if (!client.isClosed()) { - int packetId = PacketRegistry.getS2CId(packet); - try { - DataOutput output = new DataOutputStream(client.getOutputStream()); - output.writeByte(packetId); - packet.write(output); - } catch (IOException e) { - if (!(packet instanceof KickS2CPacket)) { - kick(client, e.toString()); - e.printStackTrace(); - } - } - } - } - - public void sendToAll(Packet packet) { - for (Socket client : clients) { - sendPacket(client, packet); - } - } - - public void sendToAllExcept(Socket excluded, Packet packet) { - for (Socket client : clients) { - if (client != excluded) { - sendPacket(client, packet); - } - } - } - - public boolean canModifyEntry(Socket client, Entry entry) { - if (unapprovedClients.contains(client)) { - return false; - } - - Integer syncId = syncIds.get(entry); - if (syncId == null) { - return true; - } - Set clients = clientsNeedingConfirmation.get(syncId); - return clients == null || !clients.contains(client); - } - - public int lockEntry(Socket exception, Entry entry) { - int syncId = nextSyncId; - nextSyncId++; - // sync id is sent as an unsigned short, can't have more than 65536 - if (nextSyncId == 65536) { - nextSyncId = DUMMY_SYNC_ID + 1; - } - Integer oldSyncId = syncIds.get(entry); - if (oldSyncId != null) { - clientsNeedingConfirmation.remove(oldSyncId); - } - syncIds.put(entry, syncId); - inverseSyncIds.put(syncId, entry); - Set clients = new HashSet<>(this.clients); - clients.remove(exception); - clientsNeedingConfirmation.put(syncId, clients); - return syncId; - } - - public void confirmChange(Socket client, int syncId) { - if (usernames.containsKey(client)) { - unapprovedClients.remove(client); - } - - Set clients = clientsNeedingConfirmation.get(syncId); - if (clients != null) { - clients.remove(client); - if (clients.isEmpty()) { - clientsNeedingConfirmation.remove(syncId); - syncIds.remove(inverseSyncIds.remove(syncId)); - } - } - } - - public void sendCorrectMapping(Socket client, Entry entry, boolean refreshClassTree) { - EntryMapping oldMapping = mappings.getDeobfMapping(entry); - String oldName = oldMapping == null ? null : oldMapping.getTargetName(); - if (oldName == null) { - sendPacket(client, new RemoveMappingS2CPacket(DUMMY_SYNC_ID, entry)); - } else { - sendPacket(client, new RenameS2CPacket(0, entry, oldName, refreshClassTree)); - } - } - - protected abstract void runOnThread(Runnable task); - - public void log(String message) { - System.out.println(message); - } - - protected boolean isRunning() { - return !socket.isClosed(); - } - - public byte[] getJarChecksum() { - return jarChecksum; - } - - public char[] getPassword() { - return password; - } - - public EntryRemapper getMappings() { - return mappings; - } - - public void sendMessage(Message message) { - log(String.format("[MSG] %s", message.translate())); - sendToAll(new MessageS2CPacket(message)); - } - -} diff --git a/src/main/java/cuchaz/enigma/network/IntegratedEnigmaServer.java b/src/main/java/cuchaz/enigma/network/IntegratedEnigmaServer.java deleted file mode 100644 index 21c6825b..00000000 --- a/src/main/java/cuchaz/enigma/network/IntegratedEnigmaServer.java +++ /dev/null @@ -1,16 +0,0 @@ -package cuchaz.enigma.network; - -import cuchaz.enigma.translation.mapping.EntryRemapper; - -import javax.swing.*; - -public class IntegratedEnigmaServer extends EnigmaServer { - public IntegratedEnigmaServer(byte[] jarChecksum, char[] password, EntryRemapper mappings, int port) { - super(jarChecksum, password, mappings, port); - } - - @Override - protected void runOnThread(Runnable task) { - SwingUtilities.invokeLater(task); - } -} diff --git a/src/main/java/cuchaz/enigma/network/ServerPacketHandler.java b/src/main/java/cuchaz/enigma/network/ServerPacketHandler.java deleted file mode 100644 index 86185536..00000000 --- a/src/main/java/cuchaz/enigma/network/ServerPacketHandler.java +++ /dev/null @@ -1,22 +0,0 @@ -package cuchaz.enigma.network; - -import java.net.Socket; - -public class ServerPacketHandler { - - private final Socket client; - private final EnigmaServer server; - - public ServerPacketHandler(Socket client, EnigmaServer server) { - this.client = client; - this.server = server; - } - - public Socket getClient() { - return client; - } - - public EnigmaServer getServer() { - return server; - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/ChangeDocsC2SPacket.java b/src/main/java/cuchaz/enigma/network/packet/ChangeDocsC2SPacket.java deleted file mode 100644 index 4d5d86f3..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/ChangeDocsC2SPacket.java +++ /dev/null @@ -1,59 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.utils.Message; -import cuchaz.enigma.utils.Utils; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class ChangeDocsC2SPacket implements Packet { - private Entry entry; - private String newDocs; - - ChangeDocsC2SPacket() { - } - - public ChangeDocsC2SPacket(Entry entry, String newDocs) { - this.entry = entry; - this.newDocs = newDocs; - } - - @Override - public void read(DataInput input) throws IOException { - this.entry = PacketHelper.readEntry(input); - this.newDocs = PacketHelper.readString(input); - } - - @Override - public void write(DataOutput output) throws IOException { - PacketHelper.writeEntry(output, entry); - PacketHelper.writeString(output, newDocs); - } - - @Override - public void handle(ServerPacketHandler handler) { - EntryMapping mapping = handler.getServer().getMappings().getDeobfMapping(entry); - - boolean valid = handler.getServer().canModifyEntry(handler.getClient(), entry); - if (!valid) { - String oldDocs = mapping == null ? null : mapping.getJavadoc(); - handler.getServer().sendPacket(handler.getClient(), new ChangeDocsS2CPacket(EnigmaServer.DUMMY_SYNC_ID, entry, oldDocs == null ? "" : oldDocs)); - return; - } - - if (mapping == null) { - mapping = new EntryMapping(handler.getServer().getMappings().deobfuscate(entry).getName()); - } - handler.getServer().getMappings().mapFromObf(entry, mapping.withDocs(Utils.isBlank(newDocs) ? null : newDocs)); - - int syncId = handler.getServer().lockEntry(handler.getClient(), entry); - handler.getServer().sendToAllExcept(handler.getClient(), new ChangeDocsS2CPacket(syncId, entry, newDocs)); - handler.getServer().sendMessage(Message.editDocs(handler.getServer().getUsername(handler.getClient()), entry)); - } - -} diff --git a/src/main/java/cuchaz/enigma/network/packet/ChangeDocsS2CPacket.java b/src/main/java/cuchaz/enigma/network/packet/ChangeDocsS2CPacket.java deleted file mode 100644 index bf5b7cb8..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/ChangeDocsS2CPacket.java +++ /dev/null @@ -1,44 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class ChangeDocsS2CPacket implements Packet { - private int syncId; - private Entry entry; - private String newDocs; - - ChangeDocsS2CPacket() { - } - - public ChangeDocsS2CPacket(int syncId, Entry entry, String newDocs) { - this.syncId = syncId; - this.entry = entry; - this.newDocs = newDocs; - } - - @Override - public void read(DataInput input) throws IOException { - this.syncId = input.readUnsignedShort(); - this.entry = PacketHelper.readEntry(input); - this.newDocs = PacketHelper.readString(input); - } - - @Override - public void write(DataOutput output) throws IOException { - output.writeShort(syncId); - PacketHelper.writeEntry(output, entry); - PacketHelper.writeString(output, newDocs); - } - - @Override - public void handle(GuiController controller) { - controller.changeDocs(new EntryReference<>(entry, entry.getName()), newDocs, false); - controller.sendPacket(new ConfirmChangeC2SPacket(syncId)); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/ConfirmChangeC2SPacket.java b/src/main/java/cuchaz/enigma/network/packet/ConfirmChangeC2SPacket.java deleted file mode 100644 index 78ef9645..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/ConfirmChangeC2SPacket.java +++ /dev/null @@ -1,33 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.network.ServerPacketHandler; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class ConfirmChangeC2SPacket implements Packet { - private int syncId; - - ConfirmChangeC2SPacket() { - } - - public ConfirmChangeC2SPacket(int syncId) { - this.syncId = syncId; - } - - @Override - public void read(DataInput input) throws IOException { - this.syncId = input.readUnsignedShort(); - } - - @Override - public void write(DataOutput output) throws IOException { - output.writeShort(syncId); - } - - @Override - public void handle(ServerPacketHandler handler) { - handler.getServer().confirmChange(handler.getClient(), syncId); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/KickS2CPacket.java b/src/main/java/cuchaz/enigma/network/packet/KickS2CPacket.java deleted file mode 100644 index bd007d31..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/KickS2CPacket.java +++ /dev/null @@ -1,33 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.gui.GuiController; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class KickS2CPacket implements Packet { - private String reason; - - KickS2CPacket() { - } - - public KickS2CPacket(String reason) { - this.reason = reason; - } - - @Override - public void read(DataInput input) throws IOException { - this.reason = PacketHelper.readString(input); - } - - @Override - public void write(DataOutput output) throws IOException { - PacketHelper.writeString(output, reason); - } - - @Override - public void handle(GuiController controller) { - controller.disconnectIfConnected(reason); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/LoginC2SPacket.java b/src/main/java/cuchaz/enigma/network/packet/LoginC2SPacket.java deleted file mode 100644 index 722cbbf3..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/LoginC2SPacket.java +++ /dev/null @@ -1,75 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.utils.Message; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.Arrays; - -public class LoginC2SPacket implements Packet { - private byte[] jarChecksum; - private char[] password; - private String username; - - LoginC2SPacket() { - } - - public LoginC2SPacket(byte[] jarChecksum, char[] password, String username) { - this.jarChecksum = jarChecksum; - this.password = password; - this.username = username; - } - - @Override - public void read(DataInput input) throws IOException { - if (input.readUnsignedShort() != EnigmaServer.PROTOCOL_VERSION) { - throw new IOException("Mismatching protocol"); - } - this.jarChecksum = new byte[EnigmaServer.CHECKSUM_SIZE]; - input.readFully(jarChecksum); - this.password = new char[input.readUnsignedByte()]; - for (int i = 0; i < password.length; i++) { - password[i] = input.readChar(); - } - this.username = PacketHelper.readString(input); - } - - @Override - public void write(DataOutput output) throws IOException { - output.writeShort(EnigmaServer.PROTOCOL_VERSION); - output.write(jarChecksum); - output.writeByte(password.length); - for (char c : password) { - output.writeChar(c); - } - PacketHelper.writeString(output, username); - } - - @Override - public void handle(ServerPacketHandler handler) { - boolean usernameTaken = handler.getServer().isUsernameTaken(username); - handler.getServer().setUsername(handler.getClient(), username); - handler.getServer().log(username + " logged in with IP " + handler.getClient().getInetAddress().toString() + ":" + handler.getClient().getPort()); - - if (!Arrays.equals(password, handler.getServer().getPassword())) { - handler.getServer().kick(handler.getClient(), "disconnect.wrong_password"); - return; - } - - if (usernameTaken) { - handler.getServer().kick(handler.getClient(), "disconnect.username_taken"); - return; - } - - if (!Arrays.equals(jarChecksum, handler.getServer().getJarChecksum())) { - handler.getServer().kick(handler.getClient(), "disconnect.wrong_jar"); - return; - } - - handler.getServer().sendPacket(handler.getClient(), new SyncMappingsS2CPacket(handler.getServer().getMappings().getObfToDeobf())); - handler.getServer().sendMessage(Message.connect(username)); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedC2SPacket.java b/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedC2SPacket.java deleted file mode 100644 index 98d20d96..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedC2SPacket.java +++ /dev/null @@ -1,48 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.utils.Message; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class MarkDeobfuscatedC2SPacket implements Packet { - private Entry entry; - - MarkDeobfuscatedC2SPacket() { - } - - public MarkDeobfuscatedC2SPacket(Entry entry) { - this.entry = entry; - } - - @Override - public void read(DataInput input) throws IOException { - this.entry = PacketHelper.readEntry(input); - } - - @Override - public void write(DataOutput output) throws IOException { - PacketHelper.writeEntry(output, entry); - } - - @Override - public void handle(ServerPacketHandler handler) { - boolean valid = handler.getServer().canModifyEntry(handler.getClient(), entry); - if (!valid) { - handler.getServer().sendCorrectMapping(handler.getClient(), entry, true); - return; - } - - handler.getServer().getMappings().mapFromObf(entry, new EntryMapping(handler.getServer().getMappings().deobfuscate(entry).getName())); - handler.getServer().log(handler.getServer().getUsername(handler.getClient()) + " marked " + entry + " as deobfuscated"); - - int syncId = handler.getServer().lockEntry(handler.getClient(), entry); - handler.getServer().sendToAllExcept(handler.getClient(), new MarkDeobfuscatedS2CPacket(syncId, entry)); - handler.getServer().sendMessage(Message.markDeobf(handler.getServer().getUsername(handler.getClient()), entry)); - - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedS2CPacket.java b/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedS2CPacket.java deleted file mode 100644 index b7d6eda3..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/MarkDeobfuscatedS2CPacket.java +++ /dev/null @@ -1,40 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class MarkDeobfuscatedS2CPacket implements Packet { - private int syncId; - private Entry entry; - - MarkDeobfuscatedS2CPacket() { - } - - public MarkDeobfuscatedS2CPacket(int syncId, Entry entry) { - this.syncId = syncId; - this.entry = entry; - } - - @Override - public void read(DataInput input) throws IOException { - this.syncId = input.readUnsignedShort(); - this.entry = PacketHelper.readEntry(input); - } - - @Override - public void write(DataOutput output) throws IOException { - output.writeShort(syncId); - PacketHelper.writeEntry(output, entry); - } - - @Override - public void handle(GuiController controller) { - controller.markAsDeobfuscated(new EntryReference<>(entry, entry.getName()), false); - controller.sendPacket(new ConfirmChangeC2SPacket(syncId)); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/MessageC2SPacket.java b/src/main/java/cuchaz/enigma/network/packet/MessageC2SPacket.java deleted file mode 100644 index b8e0f14f..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/MessageC2SPacket.java +++ /dev/null @@ -1,39 +0,0 @@ -package cuchaz.enigma.network.packet; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.utils.Message; - -public class MessageC2SPacket implements Packet { - - private String message; - - MessageC2SPacket() { - } - - public MessageC2SPacket(String message) { - this.message = message; - } - - @Override - public void read(DataInput input) throws IOException { - message = PacketHelper.readString(input); - } - - @Override - public void write(DataOutput output) throws IOException { - PacketHelper.writeString(output, message); - } - - @Override - public void handle(ServerPacketHandler handler) { - String message = this.message.trim(); - if (!message.isEmpty()) { - handler.getServer().sendMessage(Message.chat(handler.getServer().getUsername(handler.getClient()), message)); - } - } - -} diff --git a/src/main/java/cuchaz/enigma/network/packet/MessageS2CPacket.java b/src/main/java/cuchaz/enigma/network/packet/MessageS2CPacket.java deleted file mode 100644 index edeaae0b..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/MessageS2CPacket.java +++ /dev/null @@ -1,36 +0,0 @@ -package cuchaz.enigma.network.packet; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.utils.Message; - -public class MessageS2CPacket implements Packet { - - private Message message; - - MessageS2CPacket() { - } - - public MessageS2CPacket(Message message) { - this.message = message; - } - - @Override - public void read(DataInput input) throws IOException { - message = Message.read(input); - } - - @Override - public void write(DataOutput output) throws IOException { - message.write(output); - } - - @Override - public void handle(GuiController handler) { - handler.addMessage(message); - } - -} diff --git a/src/main/java/cuchaz/enigma/network/packet/Packet.java b/src/main/java/cuchaz/enigma/network/packet/Packet.java deleted file mode 100644 index 2f16dfb9..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/Packet.java +++ /dev/null @@ -1,15 +0,0 @@ -package cuchaz.enigma.network.packet; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public interface Packet { - - void read(DataInput input) throws IOException; - - void write(DataOutput output) throws IOException; - - void handle(H handler); - -} diff --git a/src/main/java/cuchaz/enigma/network/packet/PacketHelper.java b/src/main/java/cuchaz/enigma/network/packet/PacketHelper.java deleted file mode 100644 index 464606e0..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/PacketHelper.java +++ /dev/null @@ -1,135 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.nio.charset.StandardCharsets; - -public class PacketHelper { - - private static final int ENTRY_CLASS = 0, ENTRY_FIELD = 1, ENTRY_METHOD = 2, ENTRY_LOCAL_VAR = 3; - private static final int MAX_STRING_LENGTH = 65535; - - public static Entry readEntry(DataInput input) throws IOException { - return readEntry(input, null, true); - } - - public static Entry readEntry(DataInput input, Entry parent, boolean includeParent) throws IOException { - int type = input.readUnsignedByte(); - - if (includeParent && input.readBoolean()) { - parent = readEntry(input, null, true); - } - - String name = readString(input); - - String javadocs = null; - if (input.readBoolean()) { - javadocs = readString(input); - } - - switch (type) { - case ENTRY_CLASS: { - if (parent != null && !(parent instanceof ClassEntry)) { - throw new IOException("Class requires class parent"); - } - return new ClassEntry((ClassEntry) parent, name, javadocs); - } - case ENTRY_FIELD: { - if (!(parent instanceof ClassEntry)) { - throw new IOException("Field requires class parent"); - } - TypeDescriptor desc = new TypeDescriptor(readString(input)); - return new FieldEntry((ClassEntry) parent, name, desc, javadocs); - } - case ENTRY_METHOD: { - if (!(parent instanceof ClassEntry)) { - throw new IOException("Method requires class parent"); - } - MethodDescriptor desc = new MethodDescriptor(readString(input)); - return new MethodEntry((ClassEntry) parent, name, desc, javadocs); - } - case ENTRY_LOCAL_VAR: { - if (!(parent instanceof MethodEntry)) { - throw new IOException("Local variable requires method parent"); - } - int index = input.readUnsignedShort(); - boolean parameter = input.readBoolean(); - return new LocalVariableEntry((MethodEntry) parent, index, name, parameter, javadocs); - } - default: throw new IOException("Received unknown entry type " + type); - } - } - - public static void writeEntry(DataOutput output, Entry entry) throws IOException { - writeEntry(output, entry, true); - } - - public static void writeEntry(DataOutput output, Entry entry, boolean includeParent) throws IOException { - // type - if (entry instanceof ClassEntry) { - output.writeByte(ENTRY_CLASS); - } else if (entry instanceof FieldEntry) { - output.writeByte(ENTRY_FIELD); - } else if (entry instanceof MethodEntry) { - output.writeByte(ENTRY_METHOD); - } else if (entry instanceof LocalVariableEntry) { - output.writeByte(ENTRY_LOCAL_VAR); - } else { - throw new IOException("Don't know how to serialize entry of type " + entry.getClass().getSimpleName()); - } - - // parent - if (includeParent) { - output.writeBoolean(entry.getParent() != null); - if (entry.getParent() != null) { - writeEntry(output, entry.getParent(), true); - } - } - - // name - writeString(output, entry.getName()); - - // javadocs - output.writeBoolean(entry.getJavadocs() != null); - if (entry.getJavadocs() != null) { - writeString(output, entry.getJavadocs()); - } - - // type-specific stuff - if (entry instanceof FieldEntry) { - writeString(output, ((FieldEntry) entry).getDesc().toString()); - } else if (entry instanceof MethodEntry) { - writeString(output, ((MethodEntry) entry).getDesc().toString()); - } else if (entry instanceof LocalVariableEntry) { - LocalVariableEntry localVar = (LocalVariableEntry) entry; - output.writeShort(localVar.getIndex()); - output.writeBoolean(localVar.isArgument()); - } - } - - public static String readString(DataInput input) throws IOException { - int length = input.readUnsignedShort(); - byte[] bytes = new byte[length]; - input.readFully(bytes); - return new String(bytes, StandardCharsets.UTF_8); - } - - public static void writeString(DataOutput output, String str) throws IOException { - byte[] bytes = str.getBytes(StandardCharsets.UTF_8); - if (bytes.length > MAX_STRING_LENGTH) { - throw new IOException("String too long, was " + bytes.length + " bytes, max " + MAX_STRING_LENGTH + " allowed"); - } - output.writeShort(bytes.length); - output.write(bytes); - } - -} diff --git a/src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java b/src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java deleted file mode 100644 index ba5d9dec..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/PacketRegistry.java +++ /dev/null @@ -1,64 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.network.ServerPacketHandler; - -import java.util.HashMap; -import java.util.Map; -import java.util.function.Supplier; - -public class PacketRegistry { - - private static final Map>, Integer> c2sPacketIds = new HashMap<>(); - private static final Map>> c2sPacketCreators = new HashMap<>(); - private static final Map>, Integer> s2cPacketIds = new HashMap<>(); - private static final Map>> s2cPacketCreators = new HashMap<>(); - - private static > void registerC2S(int id, Class clazz, Supplier creator) { - c2sPacketIds.put(clazz, id); - c2sPacketCreators.put(id, creator); - } - - private static > void registerS2C(int id, Class clazz, Supplier creator) { - s2cPacketIds.put(clazz, id); - s2cPacketCreators.put(id, creator); - } - - static { - registerC2S(0, LoginC2SPacket.class, LoginC2SPacket::new); - registerC2S(1, ConfirmChangeC2SPacket.class, ConfirmChangeC2SPacket::new); - registerC2S(2, RenameC2SPacket.class, RenameC2SPacket::new); - registerC2S(3, RemoveMappingC2SPacket.class, RemoveMappingC2SPacket::new); - registerC2S(4, ChangeDocsC2SPacket.class, ChangeDocsC2SPacket::new); - registerC2S(5, MarkDeobfuscatedC2SPacket.class, MarkDeobfuscatedC2SPacket::new); - registerC2S(6, MessageC2SPacket.class, MessageC2SPacket::new); - - registerS2C(0, KickS2CPacket.class, KickS2CPacket::new); - registerS2C(1, SyncMappingsS2CPacket.class, SyncMappingsS2CPacket::new); - registerS2C(2, RenameS2CPacket.class, RenameS2CPacket::new); - registerS2C(3, RemoveMappingS2CPacket.class, RemoveMappingS2CPacket::new); - registerS2C(4, ChangeDocsS2CPacket.class, ChangeDocsS2CPacket::new); - registerS2C(5, MarkDeobfuscatedS2CPacket.class, MarkDeobfuscatedS2CPacket::new); - registerS2C(6, MessageS2CPacket.class, MessageS2CPacket::new); - registerS2C(7, UserListS2CPacket.class, UserListS2CPacket::new); - } - - public static int getC2SId(Packet packet) { - return c2sPacketIds.get(packet.getClass()); - } - - public static Packet createC2SPacket(int id) { - Supplier> creator = c2sPacketCreators.get(id); - return creator == null ? null : creator.get(); - } - - public static int getS2CId(Packet packet) { - return s2cPacketIds.get(packet.getClass()); - } - - public static Packet createS2CPacket(int id) { - Supplier> creator = s2cPacketCreators.get(id); - return creator == null ? null : creator.get(); - } - -} diff --git a/src/main/java/cuchaz/enigma/network/packet/RemoveMappingC2SPacket.java b/src/main/java/cuchaz/enigma/network/packet/RemoveMappingC2SPacket.java deleted file mode 100644 index a3f3d91d..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/RemoveMappingC2SPacket.java +++ /dev/null @@ -1,55 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.utils.Message; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class RemoveMappingC2SPacket implements Packet { - private Entry entry; - - RemoveMappingC2SPacket() { - } - - public RemoveMappingC2SPacket(Entry entry) { - this.entry = entry; - } - - @Override - public void read(DataInput input) throws IOException { - this.entry = PacketHelper.readEntry(input); - } - - @Override - public void write(DataOutput output) throws IOException { - PacketHelper.writeEntry(output, entry); - } - - @Override - public void handle(ServerPacketHandler handler) { - boolean valid = handler.getServer().canModifyEntry(handler.getClient(), entry); - - if (valid) { - try { - handler.getServer().getMappings().removeByObf(entry); - } catch (IllegalNameException e) { - valid = false; - } - } - - if (!valid) { - handler.getServer().sendCorrectMapping(handler.getClient(), entry, true); - return; - } - - handler.getServer().log(handler.getServer().getUsername(handler.getClient()) + " removed the mapping for " + entry); - - int syncId = handler.getServer().lockEntry(handler.getClient(), entry); - handler.getServer().sendToAllExcept(handler.getClient(), new RemoveMappingS2CPacket(syncId, entry)); - handler.getServer().sendMessage(Message.removeMapping(handler.getServer().getUsername(handler.getClient()), entry)); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/RemoveMappingS2CPacket.java b/src/main/java/cuchaz/enigma/network/packet/RemoveMappingS2CPacket.java deleted file mode 100644 index 7bb1b00d..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/RemoveMappingS2CPacket.java +++ /dev/null @@ -1,40 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class RemoveMappingS2CPacket implements Packet { - private int syncId; - private Entry entry; - - RemoveMappingS2CPacket() { - } - - public RemoveMappingS2CPacket(int syncId, Entry entry) { - this.syncId = syncId; - this.entry = entry; - } - - @Override - public void read(DataInput input) throws IOException { - this.syncId = input.readUnsignedShort(); - this.entry = PacketHelper.readEntry(input); - } - - @Override - public void write(DataOutput output) throws IOException { - output.writeShort(syncId); - PacketHelper.writeEntry(output, entry); - } - - @Override - public void handle(GuiController controller) { - controller.removeMapping(new EntryReference<>(entry, entry.getName()), false); - controller.sendPacket(new ConfirmChangeC2SPacket(syncId)); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/RenameC2SPacket.java b/src/main/java/cuchaz/enigma/network/packet/RenameC2SPacket.java deleted file mode 100644 index 03e95d6f..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/RenameC2SPacket.java +++ /dev/null @@ -1,64 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.network.ServerPacketHandler; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.utils.Message; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class RenameC2SPacket implements Packet { - private Entry entry; - private String newName; - private boolean refreshClassTree; - - RenameC2SPacket() { - } - - public RenameC2SPacket(Entry entry, String newName, boolean refreshClassTree) { - this.entry = entry; - this.newName = newName; - this.refreshClassTree = refreshClassTree; - } - - @Override - public void read(DataInput input) throws IOException { - this.entry = PacketHelper.readEntry(input); - this.newName = PacketHelper.readString(input); - this.refreshClassTree = input.readBoolean(); - } - - @Override - public void write(DataOutput output) throws IOException { - PacketHelper.writeEntry(output, entry); - PacketHelper.writeString(output, newName); - output.writeBoolean(refreshClassTree); - } - - @Override - public void handle(ServerPacketHandler handler) { - boolean valid = handler.getServer().canModifyEntry(handler.getClient(), entry); - - if (valid) { - try { - handler.getServer().getMappings().mapFromObf(entry, new EntryMapping(newName)); - } catch (IllegalNameException e) { - valid = false; - } - } - - if (!valid) { - handler.getServer().sendCorrectMapping(handler.getClient(), entry, refreshClassTree); - return; - } - - handler.getServer().log(handler.getServer().getUsername(handler.getClient()) + " renamed " + entry + " to " + newName); - - int syncId = handler.getServer().lockEntry(handler.getClient(), entry); - handler.getServer().sendToAllExcept(handler.getClient(), new RenameS2CPacket(syncId, entry, newName, refreshClassTree)); - handler.getServer().sendMessage(Message.rename(handler.getServer().getUsername(handler.getClient()), entry, newName)); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/RenameS2CPacket.java b/src/main/java/cuchaz/enigma/network/packet/RenameS2CPacket.java deleted file mode 100644 index 058f0e58..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/RenameS2CPacket.java +++ /dev/null @@ -1,48 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; - -public class RenameS2CPacket implements Packet { - private int syncId; - private Entry entry; - private String newName; - private boolean refreshClassTree; - - RenameS2CPacket() { - } - - public RenameS2CPacket(int syncId, Entry entry, String newName, boolean refreshClassTree) { - this.syncId = syncId; - this.entry = entry; - this.newName = newName; - this.refreshClassTree = refreshClassTree; - } - - @Override - public void read(DataInput input) throws IOException { - this.syncId = input.readUnsignedShort(); - this.entry = PacketHelper.readEntry(input); - this.newName = PacketHelper.readString(input); - this.refreshClassTree = input.readBoolean(); - } - - @Override - public void write(DataOutput output) throws IOException { - output.writeShort(syncId); - PacketHelper.writeEntry(output, entry); - PacketHelper.writeString(output, newName); - output.writeBoolean(refreshClassTree); - } - - @Override - public void handle(GuiController controller) { - controller.rename(new EntryReference<>(entry, entry.getName()), newName, refreshClassTree, false); - controller.sendPacket(new ConfirmChangeC2SPacket(syncId)); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java b/src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java deleted file mode 100644 index e6378d1d..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/SyncMappingsS2CPacket.java +++ /dev/null @@ -1,88 +0,0 @@ -package cuchaz.enigma.network.packet; - -import cuchaz.enigma.gui.GuiController; -import cuchaz.enigma.network.EnigmaServer; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.Collection; -import java.util.List; -import java.util.stream.Collectors; - -public class SyncMappingsS2CPacket implements Packet { - private EntryTree mappings; - - SyncMappingsS2CPacket() { - } - - public SyncMappingsS2CPacket(EntryTree mappings) { - this.mappings = mappings; - } - - @Override - public void read(DataInput input) throws IOException { - mappings = new HashEntryTree<>(); - int size = input.readInt(); - for (int i = 0; i < size; i++) { - readEntryTreeNode(input, null); - } - } - - private void readEntryTreeNode(DataInput input, Entry parent) throws IOException { - Entry entry = PacketHelper.readEntry(input, parent, false); - EntryMapping mapping = null; - if (input.readBoolean()) { - String name = input.readUTF(); - if (input.readBoolean()) { - String javadoc = input.readUTF(); - mapping = new EntryMapping(name, javadoc); - } else { - mapping = new EntryMapping(name); - } - } - mappings.insert(entry, mapping); - int size = input.readUnsignedShort(); - for (int i = 0; i < size; i++) { - readEntryTreeNode(input, entry); - } - } - - @Override - public void write(DataOutput output) throws IOException { - List> roots = mappings.getRootNodes().collect(Collectors.toList()); - output.writeInt(roots.size()); - for (EntryTreeNode node : roots) { - writeEntryTreeNode(output, node); - } - } - - private static void writeEntryTreeNode(DataOutput output, EntryTreeNode node) throws IOException { - PacketHelper.writeEntry(output, node.getEntry(), false); - EntryMapping value = node.getValue(); - output.writeBoolean(value != null); - if (value != null) { - PacketHelper.writeString(output, value.getTargetName()); - output.writeBoolean(value.getJavadoc() != null); - if (value.getJavadoc() != null) { - PacketHelper.writeString(output, value.getJavadoc()); - } - } - Collection> children = node.getChildNodes(); - output.writeShort(children.size()); - for (EntryTreeNode child : children) { - writeEntryTreeNode(output, child); - } - } - - @Override - public void handle(GuiController controller) { - controller.openMappings(mappings); - controller.sendPacket(new ConfirmChangeC2SPacket(EnigmaServer.DUMMY_SYNC_ID)); - } -} diff --git a/src/main/java/cuchaz/enigma/network/packet/UserListS2CPacket.java b/src/main/java/cuchaz/enigma/network/packet/UserListS2CPacket.java deleted file mode 100644 index 89048485..00000000 --- a/src/main/java/cuchaz/enigma/network/packet/UserListS2CPacket.java +++ /dev/null @@ -1,44 +0,0 @@ -package cuchaz.enigma.network.packet; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -import cuchaz.enigma.gui.GuiController; - -public class UserListS2CPacket implements Packet { - - private List users; - - UserListS2CPacket() { - } - - public UserListS2CPacket(List users) { - this.users = users; - } - - @Override - public void read(DataInput input) throws IOException { - int len = input.readUnsignedShort(); - users = new ArrayList<>(len); - for (int i = 0; i < len; i++) { - users.add(input.readUTF()); - } - } - - @Override - public void write(DataOutput output) throws IOException { - output.writeShort(users.size()); - for (String user : users) { - PacketHelper.writeString(output, user); - } - } - - @Override - public void handle(GuiController handler) { - handler.updateUserList(users); - } - -} diff --git a/src/main/java/cuchaz/enigma/source/Decompiler.java b/src/main/java/cuchaz/enigma/source/Decompiler.java deleted file mode 100644 index c9666d52..00000000 --- a/src/main/java/cuchaz/enigma/source/Decompiler.java +++ /dev/null @@ -1,5 +0,0 @@ -package cuchaz.enigma.source; - -public interface Decompiler { - Source getSource(String className); -} diff --git a/src/main/java/cuchaz/enigma/source/DecompilerService.java b/src/main/java/cuchaz/enigma/source/DecompilerService.java deleted file mode 100644 index 377ccbc1..00000000 --- a/src/main/java/cuchaz/enigma/source/DecompilerService.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.source; - -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.api.service.EnigmaService; -import cuchaz.enigma.api.service.EnigmaServiceType; - -public interface DecompilerService extends EnigmaService { - EnigmaServiceType TYPE = EnigmaServiceType.create("decompiler"); - - Decompiler create(ClassProvider classProvider, SourceSettings settings); -} diff --git a/src/main/java/cuchaz/enigma/source/Decompilers.java b/src/main/java/cuchaz/enigma/source/Decompilers.java deleted file mode 100644 index 7d154a6a..00000000 --- a/src/main/java/cuchaz/enigma/source/Decompilers.java +++ /dev/null @@ -1,9 +0,0 @@ -package cuchaz.enigma.source; - -import cuchaz.enigma.source.cfr.CfrDecompiler; -import cuchaz.enigma.source.procyon.ProcyonDecompiler; - -public class Decompilers { - public static final DecompilerService PROCYON = ProcyonDecompiler::new; - public static final DecompilerService CFR = CfrDecompiler::new; -} diff --git a/src/main/java/cuchaz/enigma/source/Source.java b/src/main/java/cuchaz/enigma/source/Source.java deleted file mode 100644 index 43c4de0c..00000000 --- a/src/main/java/cuchaz/enigma/source/Source.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.source; - -import cuchaz.enigma.translation.mapping.EntryRemapper; - -public interface Source { - String asString(); - - Source addJavadocs(EntryRemapper remapper); - - SourceIndex index(); -} diff --git a/src/main/java/cuchaz/enigma/source/SourceIndex.java b/src/main/java/cuchaz/enigma/source/SourceIndex.java deleted file mode 100644 index 6a335ec9..00000000 --- a/src/main/java/cuchaz/enigma/source/SourceIndex.java +++ /dev/null @@ -1,174 +0,0 @@ -package cuchaz.enigma.source; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import com.google.common.collect.Multimap; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.analysis.Token; -import cuchaz.enigma.gui.SourceRemapper; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.util.Collection; -import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import java.util.stream.Collectors; - -public class SourceIndex { - private String source; - private List lineOffsets; - private final TreeMap, Entry>> tokenToReference; - private final Multimap, Entry>, Token> referenceToTokens; - private final Map, Token> declarationToToken; - - public SourceIndex() { - tokenToReference = new TreeMap<>(); - referenceToTokens = HashMultimap.create(); - declarationToToken = Maps.newHashMap(); - } - - public SourceIndex(String source) { - this(); - setSource(source); - } - - public void setSource(String source) { - this.source = source; - lineOffsets = Lists.newArrayList(); - lineOffsets.add(0); - - for (int i = 0; i < this.source.length(); i++) { - if (this.source.charAt(i) == '\n') { - lineOffsets.add(i + 1); - } - } - } - - public String getSource() { - return source; - } - - public int getLineNumber(int position) { - int line = 0; - - for (int offset : lineOffsets) { - if (offset > position) { - break; - } - - line++; - } - - return line; - } - - public int getColumnNumber(int position) { - return position - lineOffsets.get(getLineNumber(position) - 1) + 1; - } - - public int getPosition(int line, int column) { - return lineOffsets.get(line - 1) + column - 1; - } - - public Iterable> declarations() { - return declarationToToken.keySet(); - } - - public Iterable declarationTokens() { - return declarationToToken.values(); - } - - public Token getDeclarationToken(Entry entry) { - return declarationToToken.get(entry); - } - - public void addDeclaration(Token token, Entry deobfEntry) { - if (token != null) { - EntryReference, Entry> reference = new EntryReference<>(deobfEntry, token.text); - tokenToReference.put(token, reference); - referenceToTokens.put(reference, token); - declarationToToken.put(deobfEntry, token); - } - } - - public Iterable, Entry>> references() { - return referenceToTokens.keySet(); - } - - public EntryReference, Entry> getReference(Token token) { - if (token == null) { - return null; - } - - return tokenToReference.get(token); - } - - public Iterable referenceTokens() { - return tokenToReference.keySet(); - } - - public Token getReferenceToken(int pos) { - Token token = tokenToReference.floorKey(new Token(pos, pos, null)); - - if (token != null && token.contains(pos)) { - return token; - } - - return null; - } - - public Collection getReferenceTokens(EntryReference, Entry> deobfReference) { - return referenceToTokens.get(deobfReference); - } - - public void addReference(Token token, Entry deobfEntry, Entry deobfContext) { - if (token != null) { - EntryReference, Entry> deobfReference = new EntryReference<>(deobfEntry, token.text, deobfContext); - tokenToReference.put(token, deobfReference); - referenceToTokens.put(deobfReference, token); - } - } - - public void resolveReferences(EntryResolver resolver) { - // resolve all the classes in the source references - for (Token token : Lists.newArrayList(referenceToTokens.values())) { - EntryReference, Entry> reference = tokenToReference.get(token); - EntryReference, Entry> resolvedReference = resolver.resolveFirstReference(reference, ResolutionStrategy.RESOLVE_CLOSEST); - - // replace the reference - tokenToReference.replace(token, resolvedReference); - - Collection tokens = referenceToTokens.removeAll(reference); - referenceToTokens.putAll(resolvedReference, tokens); - } - } - - public SourceIndex remapTo(SourceRemapper.Result result) { - SourceIndex remapped = new SourceIndex(result.getSource()); - - for (Map.Entry, Token> entry : declarationToToken.entrySet()) { - remapped.declarationToToken.put(entry.getKey(), result.getRemappedToken(entry.getValue())); - } - - for (Map.Entry, Entry>, Collection> entry : referenceToTokens.asMap().entrySet()) { - EntryReference, Entry> reference = entry.getKey(); - Collection oldTokens = entry.getValue(); - - Collection newTokens = oldTokens - .stream() - .map(result::getRemappedToken) - .collect(Collectors.toList()); - - remapped.referenceToTokens.putAll(reference, newTokens); - } - - for (Map.Entry, Entry>> entry : tokenToReference.entrySet()) { - remapped.tokenToReference.put(result.getRemappedToken(entry.getKey()), entry.getValue()); - } - - return remapped; - } -} diff --git a/src/main/java/cuchaz/enigma/source/SourceSettings.java b/src/main/java/cuchaz/enigma/source/SourceSettings.java deleted file mode 100644 index f6c68e98..00000000 --- a/src/main/java/cuchaz/enigma/source/SourceSettings.java +++ /dev/null @@ -1,11 +0,0 @@ -package cuchaz.enigma.source; - -public class SourceSettings { - public final boolean removeImports; - public final boolean removeVariableFinal; - - public SourceSettings(boolean removeImports, boolean removeVariableFinal) { - this.removeImports = removeImports; - this.removeVariableFinal = removeVariableFinal; - } -} diff --git a/src/main/java/cuchaz/enigma/source/cfr/CfrDecompiler.java b/src/main/java/cuchaz/enigma/source/cfr/CfrDecompiler.java deleted file mode 100644 index 9e37f168..00000000 --- a/src/main/java/cuchaz/enigma/source/cfr/CfrDecompiler.java +++ /dev/null @@ -1,108 +0,0 @@ -package cuchaz.enigma.source.cfr; - -import com.google.common.io.ByteStreams; -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.source.Decompiler; -import cuchaz.enigma.source.Source; -import cuchaz.enigma.source.SourceSettings; -import org.benf.cfr.reader.apiunreleased.ClassFileSource2; -import org.benf.cfr.reader.apiunreleased.JarContent; -import org.benf.cfr.reader.bytecode.analysis.parse.utils.Pair; -import org.benf.cfr.reader.entities.ClassFile; -import org.benf.cfr.reader.mapping.MappingFactory; -import org.benf.cfr.reader.mapping.ObfuscationMapping; -import org.benf.cfr.reader.relationship.MemberNameResolver; -import org.benf.cfr.reader.state.DCCommonState; -import org.benf.cfr.reader.state.TypeUsageCollectingDumper; -import org.benf.cfr.reader.util.AnalysisType; -import org.benf.cfr.reader.util.CannotLoadClassException; -import org.benf.cfr.reader.util.collections.ListFactory; -import org.benf.cfr.reader.util.getopt.Options; -import org.benf.cfr.reader.util.getopt.OptionsImpl; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.tree.ClassNode; - -import java.io.IOException; -import java.io.InputStream; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; - - -public class CfrDecompiler implements Decompiler { - private final DCCommonState state; - - public CfrDecompiler(ClassProvider classProvider, SourceSettings sourceSettings) { - Map options = new HashMap<>(); - - state = new DCCommonState(OptionsImpl.getFactory().create(options), new ClassFileSource2() { - @Override - public JarContent addJarContent(String s, AnalysisType analysisType) { - return null; - } - - @Override - public void informAnalysisRelativePathDetail(String usePath, String classFilePath) { - - } - - @Override - public Collection addJar(String jarPath) { - return null; - } - - @Override - public String getPossiblyRenamedPath(String path) { - return path; - } - - @Override - public Pair getClassFileContent(String path) { - ClassNode node = classProvider.getClassNode(path.substring(0, path.lastIndexOf('.'))); - - if (node == null) { - try (InputStream classResource = CfrDecompiler.class.getClassLoader().getResourceAsStream(path)) { - if (classResource != null) { - return new Pair<>(ByteStreams.toByteArray(classResource), path); - } - } catch (IOException ignored) {} - - return null; - } - - ClassWriter cw = new ClassWriter(0); - node.accept(cw); - return new Pair<>(cw.toByteArray(), path); - } - }); - } - - @Override - public Source getSource(String className) { - DCCommonState state = this.state; - Options options = state.getOptions(); - - ObfuscationMapping mapping = MappingFactory.get(options, state); - state = new DCCommonState(state, mapping); - ClassFile tree = state.getClassFileMaybePath(className); - - state.configureWith(tree); - - // To make sure we're analysing the cached version - try { - tree = state.getClassFile(tree.getClassType()); - } catch (CannotLoadClassException ignored) {} - - if (options.getOption(OptionsImpl.DECOMPILE_INNER_CLASSES)) { - tree.loadInnerClasses(state); - } - - if (options.getOption(OptionsImpl.RENAME_DUP_MEMBERS)) { - MemberNameResolver.resolveNames(state, ListFactory.newList(state.getClassCache().getLoadedTypes())); - } - - TypeUsageCollectingDumper typeUsageCollector = new TypeUsageCollectingDumper(options, tree); - tree.analyseTop(state, typeUsageCollector); - return new CfrSource(tree, state, typeUsageCollector.getRealTypeUsageInformation()); - } -} diff --git a/src/main/java/cuchaz/enigma/source/cfr/CfrSource.java b/src/main/java/cuchaz/enigma/source/cfr/CfrSource.java deleted file mode 100644 index d4f2da6a..00000000 --- a/src/main/java/cuchaz/enigma/source/cfr/CfrSource.java +++ /dev/null @@ -1,38 +0,0 @@ -package cuchaz.enigma.source.cfr; - -import cuchaz.enigma.source.Source; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import org.benf.cfr.reader.entities.ClassFile; -import org.benf.cfr.reader.state.DCCommonState; -import org.benf.cfr.reader.state.TypeUsageInformation; - -public class CfrSource implements Source { - private final ClassFile tree; - private final SourceIndex index; - private final String string; - - public CfrSource(ClassFile tree, DCCommonState state, TypeUsageInformation typeUsages) { - this.tree = tree; - - EnigmaDumper dumper = new EnigmaDumper(typeUsages); - tree.dump(state.getObfuscationMapping().wrap(dumper)); - index = dumper.getIndex(); - string = dumper.getString(); - } - - @Override - public String asString() { - return string; - } - - @Override - public Source addJavadocs(EntryRemapper remapper) { - return this; // TODO - } - - @Override - public SourceIndex index() { - return index; - } -} diff --git a/src/main/java/cuchaz/enigma/source/cfr/EnigmaDumper.java b/src/main/java/cuchaz/enigma/source/cfr/EnigmaDumper.java deleted file mode 100644 index 09e0a9b2..00000000 --- a/src/main/java/cuchaz/enigma/source/cfr/EnigmaDumper.java +++ /dev/null @@ -1,433 +0,0 @@ -package cuchaz.enigma.source.cfr; - -import cuchaz.enigma.analysis.Token; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; -import org.benf.cfr.reader.bytecode.analysis.types.*; -import org.benf.cfr.reader.bytecode.analysis.variables.NamedVariable; -import org.benf.cfr.reader.entities.Field; -import org.benf.cfr.reader.entities.Method; -import org.benf.cfr.reader.mapping.NullMapping; -import org.benf.cfr.reader.mapping.ObfuscationMapping; -import org.benf.cfr.reader.state.TypeUsageInformation; -import org.benf.cfr.reader.util.collections.SetFactory; -import org.benf.cfr.reader.util.output.DelegatingDumper; -import org.benf.cfr.reader.util.output.Dumpable; -import org.benf.cfr.reader.util.output.Dumper; -import org.benf.cfr.reader.util.output.TypeContext; - -import java.util.Set; -import java.util.stream.Collectors; - -public class EnigmaDumper implements Dumper { - private int outputCount = 0; - private int indent; - private boolean atStart = true; - private boolean pendingCR = false; - private final StringBuilder sb = new StringBuilder(); - private final TypeUsageInformation typeUsageInformation; - private final Set emitted = SetFactory.newSet(); - private final SourceIndex index = new SourceIndex(); - private int position; - - - public EnigmaDumper(TypeUsageInformation typeUsageInformation) { - this.typeUsageInformation = typeUsageInformation; - } - - private void append(String s) { - sb.append(s); - position += s.length(); - } - - private String getDesc(JavaTypeInstance type) { - if (!type.isUsableType() && type != RawJavaType.VOID) { - throw new IllegalArgumentException(type.toString()); - } - - if (type instanceof JavaGenericBaseInstance) { - return getDesc(type.getDeGenerifiedType()); - } - - if (type instanceof JavaRefTypeInstance) { - return "L" + type.getRawName().replace('.', '/') + ";"; - } - - if (type instanceof JavaArrayTypeInstance) { - return "[" + getDesc(((JavaArrayTypeInstance) type).removeAnArrayIndirection()); - } - - if (type instanceof RawJavaType) { - switch ((RawJavaType) type) { - case BOOLEAN: - return "Z"; - case BYTE: - return "B"; - case CHAR: - return "C"; - case SHORT: - return "S"; - case INT: - return "I"; - case LONG: - return "J"; - case FLOAT: - return "F"; - case DOUBLE: - return "D"; - case VOID: - return "V"; - default: - throw new AssertionError(); - } - } - - throw new AssertionError(); - } - - private MethodEntry getMethodEntry(MethodPrototype method) { - if (method == null || method.getClassType() == null) { - return null; - } - - MethodDescriptor desc = new MethodDescriptor( - method.getArgs().stream().map(type -> new TypeDescriptor(getDesc(type))).collect(Collectors.toList()), - new TypeDescriptor(method.getName().equals("") || method.getName().equals("") ? "V" : getDesc(method.getReturnType())) - ); - - return new MethodEntry(getClassEntry(method.getClassType()), method.getName(), desc); - } - - private LocalVariableEntry getParameterEntry(MethodPrototype method, int parameterIndex, String name) { - int variableIndex = method.isInstanceMethod() ? 1 : 0; - for (int i = 0; i < parameterIndex; i++) { - variableIndex += method.getArgs().get(i).getStackType().getComputationCategory(); - } - - return new LocalVariableEntry(getMethodEntry(method), variableIndex, name, true, null); - } - - private FieldEntry getFieldEntry(JavaTypeInstance owner, String name, JavaTypeInstance type) { - return new FieldEntry(getClassEntry(owner), name, new TypeDescriptor(getDesc(type))); - } - - private ClassEntry getClassEntry(JavaTypeInstance type) { - return new ClassEntry(type.getRawName().replace('.', '/')); - } - - @Override - public Dumper beginBlockComment(boolean inline) { - print("/*").newln(); - return this; - } - - @Override - public Dumper endBlockComment() { - print(" */").newln(); - return this; - } - - @Override - public Dumper label(String s, boolean inline) { - processPendingCR(); - append(s); - append(":"); - return this; - } - - @Override - public Dumper comment(String s) { - append("// "); - append(s); - append("\n"); - return this; - } - - @Override - public void enqueuePendingCarriageReturn() { - pendingCR = true; - } - - @Override - public Dumper removePendingCarriageReturn() { - pendingCR = false; - return this; - } - - private void processPendingCR() { - if (pendingCR) { - append("\n"); - atStart = true; - pendingCR = false; - } - } - - @Override - public Dumper identifier(String s, Object ref, boolean defines) { - return print(s); - } - - @Override - public Dumper methodName(String name, MethodPrototype method, boolean special, boolean defines) { - doIndent(); - Token token = new Token(position, position + name.length(), name); - Entry entry = getMethodEntry(method); - - if (entry != null) { - if (defines) { - index.addDeclaration(token, entry); - } else { - index.addReference(token, entry, null); - } - } - - return identifier(name, null, defines); - } - - @Override - public Dumper parameterName(String name, MethodPrototype method, int index, boolean defines) { - doIndent(); - Token token = new Token(position, position + name.length(), name); - Entry entry = getParameterEntry(method, index, name); - - if (entry != null) { - if (defines) { - this.index.addDeclaration(token, entry); - } else { - this.index.addReference(token, entry, null); - } - } - - return identifier(name, null, defines); - } - - @Override - public Dumper variableName(String name, NamedVariable variable, boolean defines) { - return identifier(name, null, defines); - } - - @Override - public Dumper packageName(JavaRefTypeInstance t) { - String s = t.getPackageName(); - - if (!s.isEmpty()) { - keyword("package ").print(s).endCodeln().newln(); - } - - return this; - } - - @Override - public Dumper fieldName(String name, Field field, JavaTypeInstance owner, boolean hiddenDeclaration, boolean defines) { - doIndent(); - Token token = new Token(position, position + name.length(), name); - Entry entry = field == null ? null : getFieldEntry(owner, name, field.getJavaTypeInstance()); - - if (entry != null) { - if (defines) { - index.addDeclaration(token, entry); - } else { - index.addReference(token, entry, null); - } - } - - identifier(name, null, defines); - return this; - } - - @Override - public Dumper print(String s) { - processPendingCR(); - doIndent(); - append(s); - atStart = s.endsWith("\n"); - outputCount++; - return this; - } - - @Override - public Dumper print(char c) { - return print(String.valueOf(c)); - } - - @Override - public Dumper newln() { - append("\n"); - atStart = true; - outputCount++; - return this; - } - - @Override - public Dumper endCodeln() { - append(";\n"); - atStart = true; - outputCount++; - return this; - } - - @Override - public Dumper keyword(String s) { - print(s); - return this; - } - - @Override - public Dumper operator(String s) { - print(s); - return this; - } - - @Override - public Dumper separator(String s) { - print(s); - return this; - } - - @Override - public Dumper literal(String s, Object o) { - print(s); - return this; - } - - private void doIndent() { - if (!atStart) return; - String indents = " "; - - for (int x = 0; x < indent; ++x) { - append(indents); - } - - atStart = false; - } - - @Override - public void indent(int diff) { - indent += diff; - } - - @Override - public Dumper dump(Dumpable d) { - if (d == null) { - keyword("null"); - return this; - } - - d.dump(this); - return this; - } - - @Override - public TypeUsageInformation getTypeUsageInformation() { - return typeUsageInformation; - } - - @Override - public ObfuscationMapping getObfuscationMapping() { - return NullMapping.INSTANCE; - } - - @Override - public String toString() { - return sb.toString(); - } - - @Override - public void addSummaryError(Method method, String s) {} - - @Override - public void close() { - } - - @Override - public boolean canEmitClass(JavaTypeInstance type) { - return emitted.add(type); - } - - @Override - public int getOutputCount() { - return outputCount; - } - - @Override - public Dumper dump(JavaTypeInstance type) { - return dump(type, TypeContext.None, false); - } - - @Override - public Dumper dump(JavaTypeInstance type, boolean defines) { - return dump(type, TypeContext.None, false); - } - - @Override - public Dumper dump(JavaTypeInstance type, TypeContext context) { - return dump(type, context, false); - } - - private Dumper dump(JavaTypeInstance type, TypeContext context, boolean defines) { - doIndent(); - if (type instanceof JavaRefTypeInstance) { - int start = position; - type.dumpInto(this, typeUsageInformation, TypeContext.None); - int end = position; - Token token = new Token(start, end, sb.toString().substring(start, end)); - - if (defines) { - index.addDeclaration(token, getClassEntry(type)); - } else { - index.addReference(token, getClassEntry(type), null); - } - - return this; - } - - type.dumpInto(this, typeUsageInformation, context); - return this; - } - - @Override - public Dumper withTypeUsageInformation(TypeUsageInformation innerclassTypeUsageInformation) { - return new WithTypeUsageInformationDumper(this, innerclassTypeUsageInformation); - } - - public SourceIndex getIndex() { - index.setSource(getString()); - return index; - } - - public String getString() { - return sb.toString(); - } - - public static class WithTypeUsageInformationDumper extends DelegatingDumper { - private final TypeUsageInformation typeUsageInformation; - - WithTypeUsageInformationDumper(Dumper delegate, TypeUsageInformation typeUsageInformation) { - super(delegate); - this.typeUsageInformation = typeUsageInformation; - } - - @Override - public TypeUsageInformation getTypeUsageInformation() { - return typeUsageInformation; - } - - @Override - public Dumper dump(JavaTypeInstance javaTypeInstance) { - return dump(javaTypeInstance, TypeContext.None); - } - - @Override - public Dumper dump(JavaTypeInstance javaTypeInstance, TypeContext typeContext) { - javaTypeInstance.dumpInto(this, typeUsageInformation, typeContext); - return this; - } - - @Override - public Dumper withTypeUsageInformation(TypeUsageInformation innerclassTypeUsageInformation) { - return new WithTypeUsageInformationDumper(delegate, innerclassTypeUsageInformation); - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/EntryParser.java b/src/main/java/cuchaz/enigma/source/procyon/EntryParser.java deleted file mode 100644 index 2fae61a6..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/EntryParser.java +++ /dev/null @@ -1,49 +0,0 @@ -package cuchaz.enigma.source.procyon; - -import com.strobel.assembler.metadata.FieldDefinition; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.Signature; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.FieldDefEntry; -import cuchaz.enigma.translation.representation.entry.MethodDefEntry; - -public class EntryParser { - public static FieldDefEntry parse(FieldDefinition definition) { - ClassEntry owner = parse(definition.getDeclaringType()); - TypeDescriptor descriptor = new TypeDescriptor(definition.getErasedSignature()); - Signature signature = Signature.createTypedSignature(definition.getSignature()); - AccessFlags access = new AccessFlags(definition.getModifiers()); - return new FieldDefEntry(owner, definition.getName(), descriptor, signature, access, null); - } - - public static ClassDefEntry parse(TypeDefinition def) { - String name = def.getInternalName(); - Signature signature = Signature.createSignature(def.getSignature()); - AccessFlags access = new AccessFlags(def.getModifiers()); - ClassEntry superClass = def.getBaseType() != null ? parse(def.getBaseType()) : null; - ClassEntry[] interfaces = def.getExplicitInterfaces().stream().map(EntryParser::parse).toArray(ClassEntry[]::new); - return new ClassDefEntry(name, signature, access, superClass, interfaces); - } - - public static ClassEntry parse(TypeReference typeReference) { - return new ClassEntry(typeReference.getInternalName()); - } - - public static MethodDefEntry parse(MethodDefinition definition) { - ClassEntry classEntry = parse(definition.getDeclaringType()); - MethodDescriptor descriptor = new MethodDescriptor(definition.getErasedSignature()); - Signature signature = Signature.createSignature(definition.getSignature()); - AccessFlags access = new AccessFlags(definition.getModifiers()); - return new MethodDefEntry(classEntry, definition.getName(), descriptor, signature, access, null); - } - - public static TypeDescriptor parseTypeDescriptor(TypeReference type) { - return new TypeDescriptor(type.getErasedSignature()); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/ProcyonDecompiler.java b/src/main/java/cuchaz/enigma/source/procyon/ProcyonDecompiler.java deleted file mode 100644 index 37bc0c86..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/ProcyonDecompiler.java +++ /dev/null @@ -1,81 +0,0 @@ -package cuchaz.enigma.source.procyon; - -import com.strobel.assembler.metadata.ITypeLoader; -import com.strobel.assembler.metadata.MetadataSystem; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.decompiler.DecompilerContext; -import com.strobel.decompiler.DecompilerSettings; -import com.strobel.decompiler.languages.java.BraceStyle; -import com.strobel.decompiler.languages.java.JavaFormattingOptions; -import com.strobel.decompiler.languages.java.ast.AstBuilder; -import com.strobel.decompiler.languages.java.ast.CompilationUnit; -import com.strobel.decompiler.languages.java.ast.InsertParenthesesVisitor; -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.api.EnigmaPluginContext; -import cuchaz.enigma.source.Source; -import cuchaz.enigma.source.Decompiler; -import cuchaz.enigma.source.SourceSettings; -import cuchaz.enigma.source.procyon.transformers.*; -import cuchaz.enigma.source.procyon.typeloader.CompiledSourceTypeLoader; -import cuchaz.enigma.source.procyon.typeloader.NoRetryMetadataSystem; -import cuchaz.enigma.source.procyon.typeloader.SynchronizedTypeLoader; -import cuchaz.enigma.utils.Utils; - -public class ProcyonDecompiler implements Decompiler { - private final SourceSettings settings; - private final DecompilerSettings decompilerSettings; - private final MetadataSystem metadataSystem; - - public ProcyonDecompiler(ClassProvider classProvider, SourceSettings settings) { - ITypeLoader typeLoader = new SynchronizedTypeLoader(new CompiledSourceTypeLoader(classProvider)); - - metadataSystem = new NoRetryMetadataSystem(typeLoader); - metadataSystem.setEagerMethodLoadingEnabled(true); - - decompilerSettings = DecompilerSettings.javaDefaults(); - decompilerSettings.setMergeVariables(Utils.getSystemPropertyAsBoolean("enigma.mergeVariables", true)); - decompilerSettings.setForceExplicitImports(Utils.getSystemPropertyAsBoolean("enigma.forceExplicitImports", true)); - decompilerSettings.setForceExplicitTypeArguments(Utils.getSystemPropertyAsBoolean("enigma.forceExplicitTypeArguments", true)); - decompilerSettings.setShowDebugLineNumbers(Utils.getSystemPropertyAsBoolean("enigma.showDebugLineNumbers", false)); - decompilerSettings.setShowSyntheticMembers(Utils.getSystemPropertyAsBoolean("enigma.showSyntheticMembers", false)); - decompilerSettings.setTypeLoader(typeLoader); - - JavaFormattingOptions formattingOptions = decompilerSettings.getJavaFormattingOptions(); - formattingOptions.ClassBraceStyle = BraceStyle.EndOfLine; - formattingOptions.InterfaceBraceStyle = BraceStyle.EndOfLine; - formattingOptions.EnumBraceStyle = BraceStyle.EndOfLine; - - this.settings = settings; - } - - @Override - public Source getSource(String className) { - TypeReference type = metadataSystem.lookupType(className); - if (type == null) { - throw new Error(String.format("Unable to find desc: %s", className)); - } - - TypeDefinition resolvedType = type.resolve(); - - DecompilerContext context = new DecompilerContext(); - context.setCurrentType(resolvedType); - context.setSettings(decompilerSettings); - - AstBuilder builder = new AstBuilder(context); - builder.addType(resolvedType); - builder.runTransformations(null); - CompilationUnit source = builder.getCompilationUnit(); - - new ObfuscatedEnumSwitchRewriterTransform(context).run(source); - new VarargsFixer(context).run(source); - new RemoveObjectCasts(context).run(source); - new Java8Generics().run(source); - new InvalidIdentifierFix().run(source); - if (settings.removeImports) DropImportAstTransform.INSTANCE.run(source); - if (settings.removeVariableFinal) DropVarModifiersAstTransform.INSTANCE.run(source); - source.acceptVisitor(new InsertParenthesesVisitor(), null); - - return new ProcyonSource(source, decompilerSettings); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/ProcyonSource.java b/src/main/java/cuchaz/enigma/source/procyon/ProcyonSource.java deleted file mode 100644 index 53c8c70b..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/ProcyonSource.java +++ /dev/null @@ -1,49 +0,0 @@ -package cuchaz.enigma.source.procyon; - -import com.strobel.decompiler.DecompilerSettings; -import com.strobel.decompiler.PlainTextOutput; -import com.strobel.decompiler.languages.java.JavaOutputVisitor; -import com.strobel.decompiler.languages.java.ast.CompilationUnit; -import cuchaz.enigma.source.Source; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.source.procyon.index.SourceIndexVisitor; -import cuchaz.enigma.source.procyon.transformers.AddJavadocsAstTransform; -import cuchaz.enigma.translation.mapping.EntryRemapper; - -import java.io.StringWriter; - -public class ProcyonSource implements Source { - private final DecompilerSettings settings; - private final CompilationUnit tree; - private String string; - - public ProcyonSource(CompilationUnit tree, DecompilerSettings settings) { - this.settings = settings; - this.tree = tree; - } - - @Override - public SourceIndex index() { - SourceIndex index = new SourceIndex(asString()); - tree.acceptVisitor(new SourceIndexVisitor(), index); - return index; - } - - @Override - public String asString() { - if (string == null) { - StringWriter writer = new StringWriter(); - tree.acceptVisitor(new JavaOutputVisitor(new PlainTextOutput(writer), settings), null); - string = writer.toString(); - } - - return string; - } - - @Override - public Source addJavadocs(EntryRemapper remapper) { - CompilationUnit remappedTree = (CompilationUnit) tree.clone(); - new AddJavadocsAstTransform(remapper).run(remappedTree); - return new ProcyonSource(remappedTree, settings); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexClassVisitor.java b/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexClassVisitor.java deleted file mode 100644 index f6eeb159..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexClassVisitor.java +++ /dev/null @@ -1,95 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.source.procyon.index; - -import com.strobel.assembler.metadata.FieldDefinition; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.decompiler.languages.TextLocation; -import com.strobel.decompiler.languages.java.ast.*; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.source.procyon.EntryParser; -import cuchaz.enigma.translation.representation.entry.*; - -public class SourceIndexClassVisitor extends SourceIndexVisitor { - private ClassDefEntry classEntry; - - public SourceIndexClassVisitor(ClassDefEntry classEntry) { - this.classEntry = classEntry; - } - - @Override - public Void visitTypeDeclaration(TypeDeclaration node, SourceIndex index) { - // is this this class, or a subtype? - TypeDefinition def = node.getUserData(Keys.TYPE_DEFINITION); - ClassDefEntry classEntry = EntryParser.parse(def); - if (!classEntry.equals(this.classEntry)) { - // it's a subtype, recurse - index.addDeclaration(TokenFactory.createToken(index, node.getNameToken()), classEntry); - return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index); - } - - return visitChildren(node, index); - } - - @Override - public Void visitSimpleType(SimpleType node, SourceIndex index) { - TypeReference ref = node.getUserData(Keys.TYPE_REFERENCE); - if (node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY) { - ClassEntry classEntry = new ClassEntry(ref.getInternalName()); - index.addReference(TokenFactory.createToken(index, node.getIdentifierToken()), classEntry, this.classEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitMethodDeclaration(MethodDeclaration node, SourceIndex index) { - MethodDefinition def = node.getUserData(Keys.METHOD_DEFINITION); - MethodDefEntry methodEntry = EntryParser.parse(def); - AstNode tokenNode = node.getNameToken(); - if (methodEntry.isConstructor() && methodEntry.getName().equals("")) { - // for static initializers, check elsewhere for the token node - tokenNode = node.getModifiers().firstOrNullObject(); - } - index.addDeclaration(TokenFactory.createToken(index, tokenNode), methodEntry); - return node.acceptVisitor(new SourceIndexMethodVisitor(methodEntry), index); - } - - @Override - public Void visitConstructorDeclaration(ConstructorDeclaration node, SourceIndex index) { - MethodDefinition def = node.getUserData(Keys.METHOD_DEFINITION); - MethodDefEntry methodEntry = EntryParser.parse(def); - index.addDeclaration(TokenFactory.createToken(index, node.getNameToken()), methodEntry); - return node.acceptVisitor(new SourceIndexMethodVisitor(methodEntry), index); - } - - @Override - public Void visitFieldDeclaration(FieldDeclaration node, SourceIndex index) { - FieldDefinition def = node.getUserData(Keys.FIELD_DEFINITION); - FieldDefEntry fieldEntry = EntryParser.parse(def); - assert (node.getVariables().size() == 1); - VariableInitializer variable = node.getVariables().firstOrNullObject(); - index.addDeclaration(TokenFactory.createToken(index, variable.getNameToken()), fieldEntry); - return visitChildren(node, index); - } - - @Override - public Void visitEnumValueDeclaration(EnumValueDeclaration node, SourceIndex index) { - // treat enum declarations as field declarations - FieldDefinition def = node.getUserData(Keys.FIELD_DEFINITION); - FieldDefEntry fieldEntry = EntryParser.parse(def); - index.addDeclaration(TokenFactory.createToken(index, node.getNameToken()), fieldEntry); - return visitChildren(node, index); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexMethodVisitor.java b/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexMethodVisitor.java deleted file mode 100644 index 0e8bc51a..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexMethodVisitor.java +++ /dev/null @@ -1,218 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.source.procyon.index; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; -import com.strobel.assembler.metadata.*; -import com.strobel.decompiler.ast.Variable; -import com.strobel.decompiler.languages.TextLocation; -import com.strobel.decompiler.languages.java.ast.*; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.source.procyon.EntryParser; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; - -import java.lang.Error; -import java.util.HashMap; -import java.util.Map; - -public class SourceIndexMethodVisitor extends SourceIndexVisitor { - private final MethodDefEntry methodEntry; - - private Multimap unmatchedIdentifier = HashMultimap.create(); - private Map> identifierEntryCache = new HashMap<>(); - - public SourceIndexMethodVisitor(MethodDefEntry methodEntry) { - this.methodEntry = methodEntry; - } - - @Override - public Void visitInvocationExpression(InvocationExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - - // get the behavior entry - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - MethodEntry methodEntry = null; - if (ref instanceof MethodReference) { - methodEntry = new MethodEntry(classEntry, ref.getName(), new MethodDescriptor(ref.getErasedSignature())); - } - if (methodEntry != null) { - // get the node for the token - AstNode tokenNode = null; - if (node.getTarget() instanceof MemberReferenceExpression) { - tokenNode = ((MemberReferenceExpression) node.getTarget()).getMemberNameToken(); - } else if (node.getTarget() instanceof SuperReferenceExpression) { - tokenNode = node.getTarget(); - } else if (node.getTarget() instanceof ThisReferenceExpression) { - tokenNode = node.getTarget(); - } - if (tokenNode != null) { - index.addReference(TokenFactory.createToken(index, tokenNode), methodEntry, this.methodEntry); - } - } - - // Check for identifier - node.getArguments().stream().filter(expression -> expression instanceof IdentifierExpression) - .forEach(expression -> this.checkIdentifier((IdentifierExpression) expression, index)); - return visitChildren(node, index); - } - - @Override - public Void visitMemberReferenceExpression(MemberReferenceExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - if (ref instanceof FieldReference) { - // make sure this is actually a field - String erasedSignature = ref.getErasedSignature(); - if (erasedSignature.indexOf('(') >= 0) { - throw new Error("Expected a field here! got " + ref); - } - - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new TypeDescriptor(erasedSignature)); - index.addReference(TokenFactory.createToken(index, node.getMemberNameToken()), fieldEntry, this.methodEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitSimpleType(SimpleType node, SourceIndex index) { - TypeReference ref = node.getUserData(Keys.TYPE_REFERENCE); - if (node.getIdentifierToken().getStartLocation() != TextLocation.EMPTY) { - ClassEntry classEntry = new ClassEntry(ref.getInternalName()); - index.addReference(TokenFactory.createToken(index, node.getIdentifierToken()), classEntry, this.methodEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitParameterDeclaration(ParameterDeclaration node, SourceIndex index) { - ParameterDefinition def = node.getUserData(Keys.PARAMETER_DEFINITION); - int parameterIndex = def.getSlot(); - - if (parameterIndex >= 0) { - MethodDefEntry ownerMethod = methodEntry; - if (def.getMethod() instanceof MethodDefinition) { - ownerMethod = EntryParser.parse((MethodDefinition) def.getMethod()); - } - - TypeDescriptor parameterType = EntryParser.parseTypeDescriptor(def.getParameterType()); - LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(ownerMethod, parameterIndex, node.getName(), true, parameterType, null); - Identifier identifier = node.getNameToken(); - // cache the argument entry and the identifier - identifierEntryCache.put(identifier.getName(), localVariableEntry); - index.addDeclaration(TokenFactory.createToken(index, identifier), localVariableEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitIdentifierExpression(IdentifierExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - if (ref != null) { - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - FieldEntry fieldEntry = new FieldEntry(classEntry, ref.getName(), new TypeDescriptor(ref.getErasedSignature())); - index.addReference(TokenFactory.createToken(index, node.getIdentifierToken()), fieldEntry, this.methodEntry); - } else - this.checkIdentifier(node, index); - return visitChildren(node, index); - } - - private void checkIdentifier(IdentifierExpression node, SourceIndex index) { - if (identifierEntryCache.containsKey(node.getIdentifier())) // If it's in the argument cache, create a token! - index.addDeclaration(TokenFactory.createToken(index, node.getIdentifierToken()), identifierEntryCache.get(node.getIdentifier())); - else - unmatchedIdentifier.put(node.getIdentifier(), node.getIdentifierToken()); // Not matched actually, put it! - } - - private void addDeclarationToUnmatched(String key, SourceIndex index) { - Entry entry = identifierEntryCache.get(key); - - // This cannot happened in theory - if (entry == null) - return; - for (Identifier identifier : unmatchedIdentifier.get(key)) - index.addDeclaration(TokenFactory.createToken(index, identifier), entry); - unmatchedIdentifier.removeAll(key); - } - - @Override - public Void visitObjectCreationExpression(ObjectCreationExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - if (ref != null && node.getType() instanceof SimpleType) { - SimpleType simpleTypeNode = (SimpleType) node.getType(); - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - MethodEntry constructorEntry = new MethodEntry(classEntry, "", new MethodDescriptor(ref.getErasedSignature())); - index.addReference(TokenFactory.createToken(index, simpleTypeNode.getIdentifierToken()), constructorEntry, this.methodEntry); - } - - return visitChildren(node, index); - } - - @Override - public Void visitVariableDeclaration(VariableDeclarationStatement node, SourceIndex index) { - AstNodeCollection variables = node.getVariables(); - - // Single assignation - if (variables.size() == 1) { - VariableInitializer initializer = variables.firstOrNullObject(); - if (initializer != null && node.getType() instanceof SimpleType) { - Identifier identifier = initializer.getNameToken(); - Variable variable = initializer.getUserData(Keys.VARIABLE); - if (variable != null) { - VariableDefinition originalVariable = variable.getOriginalVariable(); - if (originalVariable != null) { - int variableIndex = originalVariable.getSlot(); - if (variableIndex >= 0) { - MethodDefEntry ownerMethod = EntryParser.parse(originalVariable.getDeclaringMethod()); - TypeDescriptor variableType = EntryParser.parseTypeDescriptor(originalVariable.getVariableType()); - LocalVariableDefEntry localVariableEntry = new LocalVariableDefEntry(ownerMethod, variableIndex, initializer.getName(), false, variableType, null); - identifierEntryCache.put(identifier.getName(), localVariableEntry); - addDeclarationToUnmatched(identifier.getName(), index); - index.addDeclaration(TokenFactory.createToken(index, identifier), localVariableEntry); - } - } - } - } - } - return visitChildren(node, index); - } - - @Override - public Void visitMethodGroupExpression(MethodGroupExpression node, SourceIndex index) { - MemberReference ref = node.getUserData(Keys.MEMBER_REFERENCE); - - if (ref instanceof MethodReference) { - // get the behavior entry - ClassEntry classEntry = new ClassEntry(ref.getDeclaringType().getInternalName()); - MethodEntry methodEntry = new MethodEntry(classEntry, ref.getName(), new MethodDescriptor(ref.getErasedSignature())); - - // get the node for the token - AstNode methodNameToken = node.getMethodNameToken(); - AstNode targetToken = node.getTarget(); - - if (methodNameToken != null) { - index.addReference(TokenFactory.createToken(index, methodNameToken), methodEntry, this.methodEntry); - } - - if (targetToken != null && !(targetToken instanceof ThisReferenceExpression)) { - index.addReference(TokenFactory.createToken(index, targetToken), methodEntry.getParent(), this.methodEntry); - } - } - - return visitChildren(node, index); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexVisitor.java b/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexVisitor.java deleted file mode 100644 index dad505f7..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/index/SourceIndexVisitor.java +++ /dev/null @@ -1,40 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.source.procyon.index; - -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.Keys; -import com.strobel.decompiler.languages.java.ast.TypeDeclaration; -import cuchaz.enigma.source.SourceIndex; -import cuchaz.enigma.source.procyon.EntryParser; -import cuchaz.enigma.translation.representation.entry.ClassDefEntry; - -public class SourceIndexVisitor extends DepthFirstAstVisitor { - @Override - public Void visitTypeDeclaration(TypeDeclaration node, SourceIndex index) { - TypeDefinition def = node.getUserData(Keys.TYPE_DEFINITION); - ClassDefEntry classEntry = EntryParser.parse(def); - index.addDeclaration(TokenFactory.createToken(index, node.getNameToken()), classEntry); - - return node.acceptVisitor(new SourceIndexClassVisitor(classEntry), index); - } - - @Override - protected Void visitChildren(AstNode node, SourceIndex index) { - for (final AstNode child : node.getChildren()) { - child.acceptVisitor(this, index); - } - return null; - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/index/TokenFactory.java b/src/main/java/cuchaz/enigma/source/procyon/index/TokenFactory.java deleted file mode 100644 index 62e7c102..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/index/TokenFactory.java +++ /dev/null @@ -1,46 +0,0 @@ -package cuchaz.enigma.source.procyon.index; - -import com.strobel.decompiler.languages.Region; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.ConstructorDeclaration; -import com.strobel.decompiler.languages.java.ast.Identifier; -import com.strobel.decompiler.languages.java.ast.TypeDeclaration; -import cuchaz.enigma.analysis.Token; -import cuchaz.enigma.source.SourceIndex; - -import java.util.regex.Pattern; - -public class TokenFactory { - private static final Pattern ANONYMOUS_INNER = Pattern.compile("\\$\\d+$"); - - public static Token createToken(SourceIndex index, AstNode node) { - String name = node instanceof Identifier ? ((Identifier) node).getName() : ""; - Region region = node.getRegion(); - - if (region.getBeginLine() == 0) { - System.err.println("Got bad region from Procyon for node " + node); - return null; - } - - int start = index.getPosition(region.getBeginLine(), region.getBeginColumn()); - int end = index.getPosition(region.getEndLine(), region.getEndColumn()); - String text = index.getSource().substring(start, end); - Token token = new Token(start, end, text); - - boolean isAnonymousInner = - node instanceof Identifier && - name.indexOf('$') >= 0 && node.getParent() instanceof ConstructorDeclaration && - name.lastIndexOf('$') >= 0 && - !ANONYMOUS_INNER.matcher(name).matches(); - - if (isAnonymousInner) { - TypeDeclaration type = node.getParent().getParent() instanceof TypeDeclaration ? (TypeDeclaration) node.getParent().getParent() : null; - if (type != null) { - name = type.getName(); - token.end = token.start + name.length(); - } - } - - return token; - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/AddJavadocsAstTransform.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/AddJavadocsAstTransform.java deleted file mode 100644 index 70fc8c6b..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/AddJavadocsAstTransform.java +++ /dev/null @@ -1,134 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.google.common.base.Function; -import com.google.common.base.Strings; -import com.strobel.assembler.metadata.ParameterDefinition; -import com.strobel.decompiler.languages.java.ast.*; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; -import cuchaz.enigma.source.procyon.EntryParser; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryRemapper; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.entry.*; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Objects; -import java.util.stream.Stream; - -public final class AddJavadocsAstTransform implements IAstTransform { - - private final EntryRemapper remapper; - - public AddJavadocsAstTransform(EntryRemapper remapper) { - this.remapper = remapper; - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(remapper), null); - } - - static class Visitor extends DepthFirstAstVisitor { - - private final EntryRemapper remapper; - - Visitor(EntryRemapper remapper) { - this.remapper = remapper; - } - - private void addDoc(T node, Function> retriever) { - final Comment[] comments = getComments(node, retriever); - if (comments != null) { - node.insertChildrenBefore(node.getFirstChild(), Roles.COMMENT, comments); - } - } - - private Comment[] getComments(T node, Function> retriever) { - final EntryMapping mapping = remapper.getDeobfMapping(retriever.apply(node)); - final String docs = mapping == null ? null : Strings.emptyToNull(mapping.getJavadoc()); - return docs == null ? null : Stream.of(docs.split("\\R")).map(st -> new Comment(st, - CommentType.Documentation)).toArray(Comment[]::new); - } - - private Comment[] getParameterComments(ParameterDeclaration node, Function> retriever) { - final EntryMapping mapping = remapper.getDeobfMapping(retriever.apply(node)); - final Comment[] ret = getComments(node, retriever); - if (ret != null) { - final String paramPrefix = "@param " + mapping.getTargetName() + " "; - final String indent = Strings.repeat(" ", paramPrefix.length()); - ret[0].setContent(paramPrefix + ret[0].getContent()); - for (int i = 1; i < ret.length; i++) { - ret[i].setContent(indent + ret[i].getContent()); - } - } - return ret; - } - - private void visitMethod(AstNode node) { - final MethodDefEntry methodDefEntry = EntryParser.parse(node.getUserData(Keys.METHOD_DEFINITION)); - final Comment[] baseComments = getComments(node, $ -> methodDefEntry); - List comments = new ArrayList<>(); - if (baseComments != null) - Collections.addAll(comments, baseComments); - - for (ParameterDeclaration dec : node.getChildrenByRole(Roles.PARAMETER)) { - ParameterDefinition def = dec.getUserData(Keys.PARAMETER_DEFINITION); - final Comment[] paramComments = getParameterComments(dec, $ -> new LocalVariableDefEntry(methodDefEntry, def.getSlot(), def.getName(), - true, - EntryParser.parseTypeDescriptor(def.getParameterType()), null)); - if (paramComments != null) - Collections.addAll(comments, paramComments); - } - - if (!comments.isEmpty()) { - if (remapper.getObfResolver().resolveEntry(methodDefEntry, ResolutionStrategy.RESOLVE_ROOT).stream().noneMatch(e -> Objects.equals(e, methodDefEntry))) { - comments.add(0, new Comment("{@inheritDoc}", CommentType.Documentation)); - } - final AstNode oldFirst = node.getFirstChild(); - for (Comment comment : comments) { - node.insertChildBefore(oldFirst, comment, Roles.COMMENT); - } - } - } - - @Override - protected Void visitChildren(AstNode node, Void data) { - for (final AstNode child : node.getChildren()) { - child.acceptVisitor(this, data); - } - return null; - } - - @Override - public Void visitMethodDeclaration(MethodDeclaration node, Void data) { - visitMethod(node); - return super.visitMethodDeclaration(node, data); - } - - @Override - public Void visitConstructorDeclaration(ConstructorDeclaration node, Void data) { - visitMethod(node); - return super.visitConstructorDeclaration(node, data); - } - - @Override - public Void visitFieldDeclaration(FieldDeclaration node, Void data) { - addDoc(node, dec -> EntryParser.parse(dec.getUserData(Keys.FIELD_DEFINITION))); - return super.visitFieldDeclaration(node, data); - } - - @Override - public Void visitTypeDeclaration(TypeDeclaration node, Void data) { - addDoc(node, dec -> EntryParser.parse(dec.getUserData(Keys.TYPE_DEFINITION))); - return super.visitTypeDeclaration(node, data); - } - - @Override - public Void visitEnumValueDeclaration(EnumValueDeclaration node, Void data) { - addDoc(node, dec -> EntryParser.parse(dec.getUserData(Keys.FIELD_DEFINITION))); - return super.visitEnumValueDeclaration(node, data); - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/DropImportAstTransform.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/DropImportAstTransform.java deleted file mode 100644 index 39e599d3..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/DropImportAstTransform.java +++ /dev/null @@ -1,33 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.ImportDeclaration; -import com.strobel.decompiler.languages.java.ast.PackageDeclaration; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -public final class DropImportAstTransform implements IAstTransform { - public static final DropImportAstTransform INSTANCE = new DropImportAstTransform(); - - private DropImportAstTransform() { - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(), null); - } - - static class Visitor extends DepthFirstAstVisitor { - @Override - public Void visitPackageDeclaration(PackageDeclaration node, Void data) { - node.remove(); - return null; - } - - @Override - public Void visitImportDeclaration(ImportDeclaration node, Void data) { - node.remove(); - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/DropVarModifiersAstTransform.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/DropVarModifiersAstTransform.java deleted file mode 100644 index b8c087b9..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/DropVarModifiersAstTransform.java +++ /dev/null @@ -1,37 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.decompiler.languages.java.ast.*; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -import javax.lang.model.element.Modifier; - -public final class DropVarModifiersAstTransform implements IAstTransform { - public static final DropVarModifiersAstTransform INSTANCE = new DropVarModifiersAstTransform(); - - private DropVarModifiersAstTransform() { - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(), null); - } - - static class Visitor extends DepthFirstAstVisitor { - @Override - public Void visitParameterDeclaration(ParameterDeclaration node, Void data) { - for (JavaModifierToken modifierToken : node.getChildrenByRole(EntityDeclaration.MODIFIER_ROLE)) { - if (modifierToken.getModifier() == Modifier.FINAL) { - modifierToken.remove(); - } - } - - return null; - } - - @Override - public Void visitVariableDeclaration(VariableDeclarationStatement node, Void data) { - node.removeModifier(Modifier.FINAL); - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/InvalidIdentifierFix.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/InvalidIdentifierFix.java deleted file mode 100644 index 34d95fa5..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/InvalidIdentifierFix.java +++ /dev/null @@ -1,29 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.Identifier; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -/** - * Created by Thiakil on 13/07/2018. - */ -public class InvalidIdentifierFix implements IAstTransform { - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(), null); - } - - class Visitor extends DepthFirstAstVisitor{ - @Override - public Void visitIdentifier(Identifier node, Void data) { - super.visitIdentifier(node, data); - if (node.getName().equals("do") || node.getName().equals("if")){ - Identifier newIdentifier = Identifier.create(node.getName() + "_", node.getStartLocation()); - newIdentifier.copyUserDataFrom(node); - node.replaceWith(newIdentifier); - } - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/Java8Generics.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/Java8Generics.java deleted file mode 100644 index 8accfc7c..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/Java8Generics.java +++ /dev/null @@ -1,107 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.assembler.metadata.BuiltinTypes; -import com.strobel.assembler.metadata.CommonTypeReferences; -import com.strobel.assembler.metadata.Flags; -import com.strobel.assembler.metadata.IGenericInstance; -import com.strobel.assembler.metadata.IMemberDefinition; -import com.strobel.assembler.metadata.JvmType; -import com.strobel.assembler.metadata.MemberReference; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.decompiler.languages.java.ast.ArrayCreationExpression; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.AstNodeCollection; -import com.strobel.decompiler.languages.java.ast.AstType; -import com.strobel.decompiler.languages.java.ast.CastExpression; -import com.strobel.decompiler.languages.java.ast.ComposedType; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.Expression; -import com.strobel.decompiler.languages.java.ast.Identifier; -import com.strobel.decompiler.languages.java.ast.InvocationExpression; -import com.strobel.decompiler.languages.java.ast.Keys; -import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression; -import com.strobel.decompiler.languages.java.ast.ObjectCreationExpression; -import com.strobel.decompiler.languages.java.ast.Roles; -import com.strobel.decompiler.languages.java.ast.SimpleType; -import com.strobel.decompiler.languages.java.ast.WildcardType; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -/** - * Created by Thiakil on 12/07/2018. - */ -public class Java8Generics implements IAstTransform { - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(), null); - } - - static class Visitor extends DepthFirstAstVisitor{ - - @Override - public Void visitInvocationExpression(InvocationExpression node, Void data) { - super.visitInvocationExpression(node, data); - if (node.getTarget() instanceof MemberReferenceExpression){ - MemberReferenceExpression referenceExpression = (MemberReferenceExpression) node.getTarget(); - if (referenceExpression.getTypeArguments().stream().map(t->{ - TypeReference tr = t.toTypeReference(); - if (tr.getDeclaringType() != null){//ensure that inner types are resolved so we can get the TypeDefinition below - TypeReference resolved = tr.resolve(); - if (resolved != null) - return resolved; - } - return tr; - }).anyMatch(t -> t.isWildcardType() || (t instanceof TypeDefinition && ((TypeDefinition) t).isAnonymous()))) { - //these are invalid for invocations, let the compiler work it out - referenceExpression.getTypeArguments().clear(); - } else if (referenceExpression.getTypeArguments().stream().allMatch(t->t.toTypeReference().equals(CommonTypeReferences.Object))){ - //all are , thereby redundant and/or bad - referenceExpression.getTypeArguments().clear(); - } - } - return null; - } - - @Override - public Void visitObjectCreationExpression(ObjectCreationExpression node, Void data) { - super.visitObjectCreationExpression(node, data); - AstType type = node.getType(); - if (type instanceof SimpleType && !((SimpleType) type).getTypeArguments().isEmpty()){ - SimpleType simpleType = (SimpleType) type; - AstNodeCollection typeArguments = simpleType.getTypeArguments(); - if (typeArguments.size() == 1 && typeArguments.firstOrNullObject().toTypeReference().equals(CommonTypeReferences.Object)){ - //all are , thereby redundant and/or bad - typeArguments.firstOrNullObject().getChildByRole(Roles.IDENTIFIER).replaceWith(Identifier.create("")); - } - } - return null; - } - - @Override - public Void visitCastExpression(CastExpression node, Void data) { - boolean doReplace = false; - TypeReference typeReference = node.getType().toTypeReference(); - if (typeReference.isArray() && typeReference.getElementType().isGenericType()){ - doReplace = true; - } else if (typeReference.isGenericType()) { - Expression target = node.getExpression(); - if (typeReference instanceof IGenericInstance && ((IGenericInstance)typeReference).getTypeArguments().stream().anyMatch(t->t.isWildcardType())){ - doReplace = true; - } else if (target instanceof InvocationExpression) { - InvocationExpression invocationExpression = (InvocationExpression)target; - if (invocationExpression.getTarget() instanceof MemberReferenceExpression && !((MemberReferenceExpression) invocationExpression.getTarget()).getTypeArguments().isEmpty()) { - ((MemberReferenceExpression) invocationExpression.getTarget()).getTypeArguments().clear(); - doReplace = true; - } - } - } - super.visitCastExpression(node, data); - if (doReplace){ - node.replaceWith(node.getExpression()); - } - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/ObfuscatedEnumSwitchRewriterTransform.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/ObfuscatedEnumSwitchRewriterTransform.java deleted file mode 100644 index 32bb72f4..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/ObfuscatedEnumSwitchRewriterTransform.java +++ /dev/null @@ -1,414 +0,0 @@ -/* - * Originally: - * EnumSwitchRewriterTransform.java - * - * Copyright (c) 2013 Mike Strobel - * - * This source code is based on Mono.Cecil from Jb Evain, Copyright (c) Jb Evain; - * and ILSpy/ICSharpCode from SharpDevelop, Copyright (c) AlphaSierraPapa. - * - * This source code is subject to terms and conditions of the Apache License, Version 2.0. - * A copy of the license can be found in the License.html file at the root of this distribution. - * By using this source code in any fashion, you are agreeing to be bound by the terms of the - * Apache License, Version 2.0. - * - * You must not remove this notice, or any other, from this software. - */ - -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.assembler.metadata.BuiltinTypes; -import com.strobel.assembler.metadata.FieldDefinition; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.core.SafeCloseable; -import com.strobel.core.VerifyArgument; -import com.strobel.decompiler.DecompilerContext; -import com.strobel.decompiler.languages.java.ast.AssignmentExpression; -import com.strobel.decompiler.languages.java.ast.AstBuilder; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.CaseLabel; -import com.strobel.decompiler.languages.java.ast.ContextTrackingVisitor; -import com.strobel.decompiler.languages.java.ast.Expression; -import com.strobel.decompiler.languages.java.ast.IdentifierExpression; -import com.strobel.decompiler.languages.java.ast.IndexerExpression; -import com.strobel.decompiler.languages.java.ast.InvocationExpression; -import com.strobel.decompiler.languages.java.ast.Keys; -import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression; -import com.strobel.decompiler.languages.java.ast.PrimitiveExpression; -import com.strobel.decompiler.languages.java.ast.SwitchSection; -import com.strobel.decompiler.languages.java.ast.SwitchStatement; -import com.strobel.decompiler.languages.java.ast.TypeDeclaration; -import com.strobel.decompiler.languages.java.ast.TypeReferenceExpression; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -import java.util.ArrayList; -import java.util.IdentityHashMap; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - * Copy of {@link com.strobel.decompiler.languages.java.ast.transforms.EnumSwitchRewriterTransform} modified to: - * - Not rely on a field containing "$SwitchMap$" (Proguard strips it) - * - Ignore classes *with* SwitchMap$ names (so the original can handle it) - * - Ignores inner synthetics that are not package private - */ -@SuppressWarnings("Duplicates") -public class ObfuscatedEnumSwitchRewriterTransform implements IAstTransform { - private final DecompilerContext _context; - - public ObfuscatedEnumSwitchRewriterTransform(final DecompilerContext context) { - _context = VerifyArgument.notNull(context, "context"); - } - - @Override - public void run(final AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(_context), null); - } - - private final static class Visitor extends ContextTrackingVisitor { - private final static class SwitchMapInfo { - final String enclosingType; - final Map> switches = new LinkedHashMap<>(); - final Map> mappings = new LinkedHashMap<>(); - - TypeDeclaration enclosingTypeDeclaration; - - SwitchMapInfo(final String enclosingType) { - this.enclosingType = enclosingType; - } - } - - private final Map _switchMaps = new LinkedHashMap<>(); - private boolean _isSwitchMapWrapper; - - protected Visitor(final DecompilerContext context) { - super(context); - } - - @Override - public Void visitTypeDeclaration(final TypeDeclaration typeDeclaration, final Void p) { - final boolean oldIsSwitchMapWrapper = _isSwitchMapWrapper; - final TypeDefinition typeDefinition = typeDeclaration.getUserData(Keys.TYPE_DEFINITION); - final boolean isSwitchMapWrapper = isSwitchMapWrapper(typeDefinition); - - if (isSwitchMapWrapper) { - final String internalName = typeDefinition.getInternalName(); - - SwitchMapInfo info = _switchMaps.get(internalName); - - if (info == null) { - _switchMaps.put(internalName, info = new SwitchMapInfo(internalName)); - } - - info.enclosingTypeDeclaration = typeDeclaration; - } - - _isSwitchMapWrapper = isSwitchMapWrapper; - - try { - super.visitTypeDeclaration(typeDeclaration, p); - } - finally { - _isSwitchMapWrapper = oldIsSwitchMapWrapper; - } - - rewrite(); - - return null; - } - - @Override - public Void visitSwitchStatement(final SwitchStatement node, final Void data) { - final Expression test = node.getExpression(); - - if (test instanceof IndexerExpression) { - final IndexerExpression indexer = (IndexerExpression) test; - final Expression array = indexer.getTarget(); - final Expression argument = indexer.getArgument(); - - if (!(array instanceof MemberReferenceExpression)) { - return super.visitSwitchStatement(node, data); - } - - final MemberReferenceExpression arrayAccess = (MemberReferenceExpression) array; - final Expression arrayOwner = arrayAccess.getTarget(); - final String mapName = arrayAccess.getMemberName(); - - if (mapName == null || mapName.startsWith("$SwitchMap$") || !(arrayOwner instanceof TypeReferenceExpression)) { - return super.visitSwitchStatement(node, data); - } - - final TypeReferenceExpression enclosingTypeExpression = (TypeReferenceExpression) arrayOwner; - final TypeReference enclosingType = enclosingTypeExpression.getType().getUserData(Keys.TYPE_REFERENCE); - - if (!isSwitchMapWrapper(enclosingType) || !(argument instanceof InvocationExpression)) { - return super.visitSwitchStatement(node, data); - } - - final InvocationExpression invocation = (InvocationExpression) argument; - final Expression invocationTarget = invocation.getTarget(); - - if (!(invocationTarget instanceof MemberReferenceExpression)) { - return super.visitSwitchStatement(node, data); - } - - final MemberReferenceExpression memberReference = (MemberReferenceExpression) invocationTarget; - - if (!"ordinal".equals(memberReference.getMemberName())) { - return super.visitSwitchStatement(node, data); - } - - final String enclosingTypeName = enclosingType.getInternalName(); - - SwitchMapInfo info = _switchMaps.get(enclosingTypeName); - - if (info == null) { - _switchMaps.put(enclosingTypeName, info = new SwitchMapInfo(enclosingTypeName)); - - final TypeDefinition resolvedType = enclosingType.resolve(); - - if (resolvedType != null) { - AstBuilder astBuilder = context.getUserData(Keys.AST_BUILDER); - - if (astBuilder == null) { - astBuilder = new AstBuilder(context); - } - - try (final SafeCloseable importSuppression = astBuilder.suppressImports()) { - final TypeDeclaration declaration = astBuilder.createType(resolvedType); - - declaration.acceptVisitor(this, data); - } - } - } - - List switches = info.switches.get(mapName); - - if (switches == null) { - info.switches.put(mapName, switches = new ArrayList<>()); - } - - switches.add(node); - } - - return super.visitSwitchStatement(node, data); - } - - @Override - public Void visitAssignmentExpression(final AssignmentExpression node, final Void data) { - final TypeDefinition currentType = context.getCurrentType(); - final MethodDefinition currentMethod = context.getCurrentMethod(); - - if (_isSwitchMapWrapper && - currentType != null && - currentMethod != null && - currentMethod.isTypeInitializer()) { - - final Expression left = node.getLeft(); - final Expression right = node.getRight(); - - if (left instanceof IndexerExpression && - right instanceof PrimitiveExpression) { - - String mapName = null; - - final Expression array = ((IndexerExpression) left).getTarget(); - final Expression argument = ((IndexerExpression) left).getArgument(); - - if (array instanceof MemberReferenceExpression) { - mapName = ((MemberReferenceExpression) array).getMemberName(); - } - else if (array instanceof IdentifierExpression) { - mapName = ((IdentifierExpression) array).getIdentifier(); - } - - if (mapName == null || mapName.startsWith("$SwitchMap$")) { - return super.visitAssignmentExpression(node, data); - } - - if (!(argument instanceof InvocationExpression)) { - return super.visitAssignmentExpression(node, data); - } - - final InvocationExpression invocation = (InvocationExpression) argument; - final Expression invocationTarget = invocation.getTarget(); - - if (!(invocationTarget instanceof MemberReferenceExpression)) { - return super.visitAssignmentExpression(node, data); - } - - final MemberReferenceExpression memberReference = (MemberReferenceExpression) invocationTarget; - final Expression memberTarget = memberReference.getTarget(); - - if (!(memberTarget instanceof MemberReferenceExpression) || !"ordinal".equals(memberReference.getMemberName())) { - return super.visitAssignmentExpression(node, data); - } - - final MemberReferenceExpression outerMemberReference = (MemberReferenceExpression) memberTarget; - final Expression outerMemberTarget = outerMemberReference.getTarget(); - - if (!(outerMemberTarget instanceof TypeReferenceExpression)) { - return super.visitAssignmentExpression(node, data); - } - - final String enclosingType = currentType.getInternalName(); - - SwitchMapInfo info = _switchMaps.get(enclosingType); - - if (info == null) { - _switchMaps.put(enclosingType, info = new SwitchMapInfo(enclosingType)); - - AstBuilder astBuilder = context.getUserData(Keys.AST_BUILDER); - - if (astBuilder == null) { - astBuilder = new AstBuilder(context); - } - - info.enclosingTypeDeclaration = astBuilder.createType(currentType); - } - - final PrimitiveExpression value = (PrimitiveExpression) right; - - assert value.getValue() instanceof Integer; - - Map mapping = info.mappings.get(mapName); - - if (mapping == null) { - info.mappings.put(mapName, mapping = new LinkedHashMap<>()); - } - - final IdentifierExpression enumValue = new IdentifierExpression( Expression.MYSTERY_OFFSET, outerMemberReference.getMemberName()); - - enumValue.putUserData(Keys.MEMBER_REFERENCE, outerMemberReference.getUserData(Keys.MEMBER_REFERENCE)); - - mapping.put(((Number) value.getValue()).intValue(), enumValue); - } - } - - return super.visitAssignmentExpression(node, data); - } - - private void rewrite() { - if (_switchMaps.isEmpty()) { - return; - } - - for (final SwitchMapInfo info : _switchMaps.values()) { - rewrite(info); - } - - // - // Remove switch map type wrappers that are no longer referenced. - // - - outer: - for (final SwitchMapInfo info : _switchMaps.values()) { - for (final String mapName : info.switches.keySet()) { - final List switches = info.switches.get(mapName); - - if (switches != null && !switches.isEmpty()) { - continue outer; - } - } - - final TypeDeclaration enclosingTypeDeclaration = info.enclosingTypeDeclaration; - - if (enclosingTypeDeclaration != null) { - enclosingTypeDeclaration.remove(); - } - } - } - - private void rewrite(final SwitchMapInfo info) { - if (info.switches.isEmpty()) { - return; - } - - for (final String mapName : info.switches.keySet()) { - final List switches = info.switches.get(mapName); - final Map mappings = info.mappings.get(mapName); - - if (switches != null && mappings != null) { - for (int i = 0; i < switches.size(); i++) { - if (rewriteSwitch(switches.get(i), mappings)) { - switches.remove(i--); - } - } - } - } - } - - private boolean rewriteSwitch(final SwitchStatement s, final Map mappings) { - final Map replacements = new IdentityHashMap<>(); - - for (final SwitchSection section : s.getSwitchSections()) { - for (final CaseLabel caseLabel : section.getCaseLabels()) { - final Expression expression = caseLabel.getExpression(); - - if (expression.isNull()) { - continue; - } - - if (expression instanceof PrimitiveExpression) { - final Object value = ((PrimitiveExpression) expression).getValue(); - - if (value instanceof Integer) { - final Expression replacement = mappings.get(value); - - if (replacement != null) { - replacements.put(expression, replacement); - continue; - } - } - } - - // - // If we can't rewrite all cases, we abort. - // - - return false; - } - } - - final IndexerExpression indexer = (IndexerExpression) s.getExpression(); - final InvocationExpression argument = (InvocationExpression) indexer.getArgument(); - final MemberReferenceExpression memberReference = (MemberReferenceExpression) argument.getTarget(); - final Expression newTest = memberReference.getTarget(); - - newTest.remove(); - indexer.replaceWith(newTest); - - for (final Map.Entry entry : replacements.entrySet()) { - entry.getKey().replaceWith(entry.getValue().clone()); - } - - return true; - } - - private static boolean isSwitchMapWrapper(final TypeReference type) { - if (type == null) { - return false; - } - - final TypeDefinition definition = type instanceof TypeDefinition ? (TypeDefinition) type - : type.resolve(); - - if (definition == null || !definition.isSynthetic() || !definition.isInnerClass() || !definition.isPackagePrivate()) { - return false; - } - - for (final FieldDefinition field : definition.getDeclaredFields()) { - if (!field.getName().startsWith("$SwitchMap$") && - BuiltinTypes.Integer.makeArrayType().equals(field.getFieldType())) { - - return true; - } - } - - return false; - } - } -} \ No newline at end of file diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/RemoveObjectCasts.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/RemoveObjectCasts.java deleted file mode 100644 index cf0376f3..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/RemoveObjectCasts.java +++ /dev/null @@ -1,39 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.assembler.metadata.BuiltinTypes; -import com.strobel.decompiler.DecompilerContext; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.CastExpression; -import com.strobel.decompiler.languages.java.ast.ContextTrackingVisitor; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; - -/** - * Created by Thiakil on 11/07/2018. - */ -public class RemoveObjectCasts implements IAstTransform { - private final DecompilerContext _context; - - public RemoveObjectCasts(DecompilerContext context) { - _context = context; - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(_context), null); - } - - private final static class Visitor extends ContextTrackingVisitor{ - - protected Visitor(DecompilerContext context) { - super(context); - } - - @Override - public Void visitCastExpression(CastExpression node, Void data) { - if (node.getType().toTypeReference().equals(BuiltinTypes.Object)){ - node.replaceWith(node.getExpression()); - } - return super.visitCastExpression(node, data); - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/transformers/VarargsFixer.java b/src/main/java/cuchaz/enigma/source/procyon/transformers/VarargsFixer.java deleted file mode 100644 index d3ddaab6..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/transformers/VarargsFixer.java +++ /dev/null @@ -1,197 +0,0 @@ -package cuchaz.enigma.source.procyon.transformers; - -import com.strobel.assembler.metadata.MemberReference; -import com.strobel.assembler.metadata.MetadataFilters; -import com.strobel.assembler.metadata.MetadataHelper; -import com.strobel.assembler.metadata.MethodBinder; -import com.strobel.assembler.metadata.MethodDefinition; -import com.strobel.assembler.metadata.MethodReference; -import com.strobel.assembler.metadata.TypeReference; -import com.strobel.core.StringUtilities; -import com.strobel.core.VerifyArgument; -import com.strobel.decompiler.DecompilerContext; -import com.strobel.decompiler.languages.java.ast.ArrayCreationExpression; -import com.strobel.decompiler.languages.java.ast.ArrayInitializerExpression; -import com.strobel.decompiler.languages.java.ast.AstNode; -import com.strobel.decompiler.languages.java.ast.AstNodeCollection; -import com.strobel.decompiler.languages.java.ast.CastExpression; -import com.strobel.decompiler.languages.java.ast.ContextTrackingVisitor; -import com.strobel.decompiler.languages.java.ast.DepthFirstAstVisitor; -import com.strobel.decompiler.languages.java.ast.Expression; -import com.strobel.decompiler.languages.java.ast.InvocationExpression; -import com.strobel.decompiler.languages.java.ast.JavaResolver; -import com.strobel.decompiler.languages.java.ast.Keys; -import com.strobel.decompiler.languages.java.ast.MemberReferenceExpression; -import com.strobel.decompiler.languages.java.ast.ObjectCreationExpression; -import com.strobel.decompiler.languages.java.ast.transforms.IAstTransform; -import com.strobel.decompiler.semantics.ResolveResult; - -import java.util.ArrayList; -import java.util.List; - -/** - * Created by Thiakil on 12/07/2018. - */ -public class VarargsFixer implements IAstTransform { - private final DecompilerContext _context; - - public VarargsFixer(final DecompilerContext context) { - _context = VerifyArgument.notNull(context, "context"); - } - - @Override - public void run(AstNode compilationUnit) { - compilationUnit.acceptVisitor(new Visitor(_context), null); - } - - class Visitor extends ContextTrackingVisitor { - private final JavaResolver _resolver; - protected Visitor(DecompilerContext context) { - super(context); - _resolver = new JavaResolver(context); - } - - //remove `new Object[0]` on varagrs as the normal tranformer doesnt do them - @Override - public Void visitInvocationExpression(InvocationExpression node, Void data) { - super.visitInvocationExpression(node, data); - MemberReference definition = node.getUserData(Keys.MEMBER_REFERENCE); - if (definition instanceof MethodDefinition && ((MethodDefinition) definition).isVarArgs()){ - AstNodeCollection arguments = node.getArguments(); - Expression lastParam = arguments.lastOrNullObject(); - if (!lastParam.isNull() && lastParam instanceof ArrayCreationExpression){ - ArrayCreationExpression varargArray = (ArrayCreationExpression)lastParam; - if (varargArray.getInitializer().isNull() || varargArray.getInitializer().getElements().isEmpty()){ - lastParam.remove(); - } else { - for (Expression e : varargArray.getInitializer().getElements()){ - arguments.insertBefore(varargArray, e.clone()); - } - varargArray.remove(); - } - } - } - return null; - } - - //applies the vararg transform to object creation - @Override - public Void visitObjectCreationExpression(ObjectCreationExpression node, Void data) { - super.visitObjectCreationExpression(node, data); - final AstNodeCollection arguments = node.getArguments(); - final Expression lastArgument = arguments.lastOrNullObject(); - - Expression arrayArg = lastArgument; - - if (arrayArg instanceof CastExpression) - arrayArg = ((CastExpression) arrayArg).getExpression(); - - if (arrayArg == null || - arrayArg.isNull() || - !(arrayArg instanceof ArrayCreationExpression && - node.getTarget() instanceof MemberReferenceExpression)) { - - return null; - } - - final ArrayCreationExpression newArray = (ArrayCreationExpression) arrayArg; - final MemberReferenceExpression target = (MemberReferenceExpression) node.getTarget(); - - if (!newArray.getAdditionalArraySpecifiers().hasSingleElement()) { - return null; - } - - final MethodReference method = (MethodReference) node.getUserData(Keys.MEMBER_REFERENCE); - - if (method == null) { - return null; - } - - final MethodDefinition resolved = method.resolve(); - - if (resolved == null || !resolved.isVarArgs()) { - return null; - } - - final List candidates; - final Expression invocationTarget = target.getTarget(); - - if (invocationTarget == null || invocationTarget.isNull()) { - candidates = MetadataHelper.findMethods( - context.getCurrentType(), - MetadataFilters.matchName(resolved.getName()) - ); - } - else { - final ResolveResult targetResult = _resolver.apply(invocationTarget); - - if (targetResult == null || targetResult.getType() == null) { - return null; - } - - candidates = MetadataHelper.findMethods( - targetResult.getType(), - MetadataFilters.matchName(resolved.getName()) - ); - } - - final List argTypes = new ArrayList<>(); - - for (final Expression argument : arguments) { - final ResolveResult argResult = _resolver.apply(argument); - - if (argResult == null || argResult.getType() == null) { - return null; - } - - argTypes.add(argResult.getType()); - } - - final MethodBinder.BindResult c1 = MethodBinder.selectMethod(candidates, argTypes); - - if (c1.isFailure() || c1.isAmbiguous()) { - return null; - } - - argTypes.remove(argTypes.size() - 1); - - final ArrayInitializerExpression initializer = newArray.getInitializer(); - final boolean hasElements = !initializer.isNull() && !initializer.getElements().isEmpty(); - - if (hasElements) { - for (final Expression argument : initializer.getElements()) { - final ResolveResult argResult = _resolver.apply(argument); - - if (argResult == null || argResult.getType() == null) { - return null; - } - - argTypes.add(argResult.getType()); - } - } - - final MethodBinder.BindResult c2 = MethodBinder.selectMethod(candidates, argTypes); - - if (c2.isFailure() || - c2.isAmbiguous() || - !StringUtilities.equals(c2.getMethod().getErasedSignature(), c1.getMethod().getErasedSignature())) { - - return null; - } - - lastArgument.remove(); - - if (!hasElements) { - lastArgument.remove(); - return null; - } - - for (final Expression newArg : initializer.getElements()) { - newArg.remove(); - arguments.add(newArg); - } - - return null; - } - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingClasspathTypeLoader.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingClasspathTypeLoader.java deleted file mode 100644 index e702956e..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingClasspathTypeLoader.java +++ /dev/null @@ -1,33 +0,0 @@ -package cuchaz.enigma.source.procyon.typeloader; - -import com.strobel.assembler.metadata.Buffer; -import com.strobel.assembler.metadata.ClasspathTypeLoader; -import com.strobel.assembler.metadata.ITypeLoader; - -/** - * Caching version of {@link ClasspathTypeLoader} - */ -public class CachingClasspathTypeLoader extends CachingTypeLoader { - private static ITypeLoader extraClassPathLoader = null; - - public static void setExtraClassPathLoader(ITypeLoader loader){ - extraClassPathLoader = loader; - } - - private final ITypeLoader classpathLoader = new ClasspathTypeLoader(); - - @Override - protected byte[] doLoad(String className) { - Buffer parentBuf = new Buffer(); - if (classpathLoader.tryLoadType(className, parentBuf)) { - return parentBuf.array(); - } - if (extraClassPathLoader != null){ - parentBuf.reset(); - if (extraClassPathLoader.tryLoadType(className, parentBuf)){ - return parentBuf.array(); - } - } - return EMPTY_ARRAY;//need to return *something* as null means no store - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingTypeLoader.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingTypeLoader.java deleted file mode 100644 index 5be5ddd9..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CachingTypeLoader.java +++ /dev/null @@ -1,38 +0,0 @@ -package cuchaz.enigma.source.procyon.typeloader; - -import com.google.common.collect.Maps; -import com.strobel.assembler.metadata.Buffer; -import com.strobel.assembler.metadata.ITypeLoader; - -import java.util.Map; - -/** - * Common cache functions - */ -public abstract class CachingTypeLoader implements ITypeLoader { - protected static final byte[] EMPTY_ARRAY = {}; - - private final Map cache = Maps.newHashMap(); - - protected abstract byte[] doLoad(String className); - - @Override - public boolean tryLoadType(String className, Buffer out) { - - // check the cache - byte[] data = this.cache.computeIfAbsent(className, this::doLoad); - - if (data == EMPTY_ARRAY) { - return false; - } - - out.reset(data.length); - System.arraycopy(data, 0, out.array(), out.position(), data.length); - out.position(0); - return true; - } - - public void clearCache() { - this.cache.clear(); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CompiledSourceTypeLoader.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/CompiledSourceTypeLoader.java deleted file mode 100644 index e703d3b3..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/CompiledSourceTypeLoader.java +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.source.procyon.typeloader; - -import com.google.common.collect.Lists; -import com.strobel.assembler.metadata.Buffer; -import com.strobel.assembler.metadata.ITypeLoader; -import cuchaz.enigma.ClassProvider; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import org.objectweb.asm.ClassVisitor; -import org.objectweb.asm.ClassWriter; -import org.objectweb.asm.Opcodes; -import org.objectweb.asm.tree.AbstractInsnNode; -import org.objectweb.asm.tree.ClassNode; -import org.objectweb.asm.tree.MethodInsnNode; -import org.objectweb.asm.tree.MethodNode; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; -import java.util.function.Function; - -public class CompiledSourceTypeLoader extends CachingTypeLoader { - //Store one instance as the classpath shouldn't change during load - private static final ITypeLoader CLASSPATH_TYPE_LOADER = new CachingClasspathTypeLoader(); - - private final ClassProvider compiledSource; - private final LinkedList> visitors = new LinkedList<>(); - - public CompiledSourceTypeLoader(ClassProvider compiledSource) { - this.compiledSource = compiledSource; - } - - public void addVisitor(Function visitor) { - this.visitors.addFirst(visitor); - } - - @Override - protected byte[] doLoad(String className) { - byte[] data = loadType(className); - if (data == null) { - return loadClasspath(className); - } - - return data; - } - - private byte[] loadClasspath(String name) { - Buffer parentBuf = new Buffer(); - if (CLASSPATH_TYPE_LOADER.tryLoadType(name, parentBuf)) { - return parentBuf.array(); - } - return EMPTY_ARRAY; - } - - private byte[] loadType(String className) { - ClassEntry entry = new ClassEntry(className); - - // find the class in the jar - ClassNode node = findClassNode(entry); - if (node == null) { - // couldn't find it - return null; - } - - removeRedundantClassCalls(node); - - ClassWriter writer = new ClassWriter(0); - - ClassVisitor visitor = writer; - for (Function visitorFunction : this.visitors) { - visitor = visitorFunction.apply(visitor); - } - - node.accept(visitor); - - // we have a transformed class! - return writer.toByteArray(); - } - - private void removeRedundantClassCalls(ClassNode node) { - // remove .getClass() calls that are seemingly injected - // DUP - // INVOKEVIRTUAL java/lang/Object.getClass ()Ljava/lang/Class; - // POP - for (MethodNode methodNode : node.methods) { - AbstractInsnNode insnNode = methodNode.instructions.getFirst(); - while (insnNode != null) { - if (insnNode instanceof MethodInsnNode && insnNode.getOpcode() == Opcodes.INVOKEVIRTUAL) { - MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode; - if (methodInsnNode.name.equals("getClass") && methodInsnNode.owner.equals("java/lang/Object") && methodInsnNode.desc.equals("()Ljava/lang/Class;")) { - AbstractInsnNode previous = methodInsnNode.getPrevious(); - AbstractInsnNode next = methodInsnNode.getNext(); - if (previous.getOpcode() == Opcodes.DUP && next.getOpcode() == Opcodes.POP) { - insnNode = previous.getPrevious();//reset the iterator so it gets the new next instruction - methodNode.instructions.remove(previous); - methodNode.instructions.remove(methodInsnNode); - methodNode.instructions.remove(next); - } - } - } - insnNode = insnNode.getNext(); - } - } - } - - private ClassNode findClassNode(ClassEntry entry) { - // try to find the class in the jar - for (String className : getClassNamesToTry(entry)) { - ClassNode node = compiledSource.getClassNode(className); - if (node != null) { - return node; - } - } - - // didn't find it ;_; - return null; - } - - private Collection getClassNamesToTry(ClassEntry entry) { - List classNamesToTry = Lists.newArrayList(); - classNamesToTry.add(entry.getFullName()); - - ClassEntry outerClass = entry.getOuterClass(); - if (outerClass != null) { - classNamesToTry.addAll(getClassNamesToTry(outerClass)); - } - - return classNamesToTry; - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/NoRetryMetadataSystem.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/NoRetryMetadataSystem.java deleted file mode 100644 index c4732b04..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/NoRetryMetadataSystem.java +++ /dev/null @@ -1,38 +0,0 @@ -package cuchaz.enigma.source.procyon.typeloader; - -import com.strobel.assembler.metadata.ITypeLoader; -import com.strobel.assembler.metadata.MetadataSystem; -import com.strobel.assembler.metadata.TypeDefinition; -import com.strobel.assembler.metadata.TypeReference; - -import java.util.Collections; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public final class NoRetryMetadataSystem extends MetadataSystem { - private final Set failedTypes = Collections.newSetFromMap(new ConcurrentHashMap<>()); - - public NoRetryMetadataSystem(final ITypeLoader typeLoader) { - super(typeLoader); - } - - @Override - protected synchronized TypeDefinition resolveType(final String descriptor, final boolean mightBePrimitive) { - if (failedTypes.contains(descriptor)) { - return null; - } - - final TypeDefinition result = super.resolveType(descriptor, mightBePrimitive); - - if (result == null) { - failedTypes.add(descriptor); - } - - return result; - } - - @Override - public synchronized TypeDefinition resolve(final TypeReference type) { - return super.resolve(type); - } -} diff --git a/src/main/java/cuchaz/enigma/source/procyon/typeloader/SynchronizedTypeLoader.java b/src/main/java/cuchaz/enigma/source/procyon/typeloader/SynchronizedTypeLoader.java deleted file mode 100644 index 86c6ecc6..00000000 --- a/src/main/java/cuchaz/enigma/source/procyon/typeloader/SynchronizedTypeLoader.java +++ /dev/null @@ -1,20 +0,0 @@ -package cuchaz.enigma.source.procyon.typeloader; - -import com.strobel.assembler.metadata.Buffer; -import com.strobel.assembler.metadata.ITypeLoader; - -/** - * Typeloader with synchronized tryLoadType method - */ -public class SynchronizedTypeLoader implements ITypeLoader { - private final ITypeLoader delegate; - - public SynchronizedTypeLoader(ITypeLoader delegate) { - this.delegate = delegate; - } - - @Override - public synchronized boolean tryLoadType(String internalName, Buffer buffer) { - return delegate.tryLoadType(internalName, buffer); - } -} diff --git a/src/main/java/cuchaz/enigma/throwables/IllegalNameException.java b/src/main/java/cuchaz/enigma/throwables/IllegalNameException.java deleted file mode 100644 index 0155ad27..00000000 --- a/src/main/java/cuchaz/enigma/throwables/IllegalNameException.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.throwables; - -public class IllegalNameException extends RuntimeException { - - private String name; - private String reason; - - public IllegalNameException(String name, String reason) { - this.name = name; - this.reason = reason; - } - - public String getReason() { - return this.reason; - } - - @Override - public String getMessage() { - StringBuilder buf = new StringBuilder(); - buf.append("Illegal name: "); - buf.append(this.name); - if (this.reason != null) { - buf.append(" because "); - buf.append(this.reason); - } - return buf.toString(); - } -} diff --git a/src/main/java/cuchaz/enigma/throwables/MappingConflict.java b/src/main/java/cuchaz/enigma/throwables/MappingConflict.java deleted file mode 100644 index 95cd4494..00000000 --- a/src/main/java/cuchaz/enigma/throwables/MappingConflict.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.throwables; - -public class MappingConflict extends Exception { - public MappingConflict(String clazz, String name, String nameExisting) { - super(String.format("Conflicting mappings found for %s. The mapping file is %s and the second is %s", clazz, name, nameExisting)); - } -} diff --git a/src/main/java/cuchaz/enigma/throwables/MappingParseException.java b/src/main/java/cuchaz/enigma/throwables/MappingParseException.java deleted file mode 100644 index b7e6d426..00000000 --- a/src/main/java/cuchaz/enigma/throwables/MappingParseException.java +++ /dev/null @@ -1,39 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.throwables; - -import java.io.File; -import java.util.function.Supplier; - -public class MappingParseException extends Exception { - - private int line; - private String message; - private String filePath; - - public MappingParseException(File file, int line, String message) { - this.line = line; - this.message = message; - filePath = file.getAbsolutePath(); - } - - public MappingParseException(Supplier filenameProvider, int line, String message) { - this.line = line; - this.message = message; - filePath = filenameProvider.get(); - } - - @Override - public String getMessage() { - return "Line " + line + ": " + message + " in file " + filePath; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java b/src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java deleted file mode 100644 index 18c966cd..00000000 --- a/src/main/java/cuchaz/enigma/translation/LocalNameGenerator.java +++ /dev/null @@ -1,44 +0,0 @@ -package cuchaz.enigma.translation; - -import cuchaz.enigma.translation.mapping.NameValidator; -import cuchaz.enigma.translation.representation.TypeDescriptor; - -import java.util.Collection; -import java.util.Locale; - -public class LocalNameGenerator { - public static String generateArgumentName(int index, TypeDescriptor desc, Collection arguments) { - boolean uniqueType = arguments.stream().filter(desc::equals).count() <= 1; - String translatedName; - int nameIndex = index + 1; - StringBuilder nameBuilder = new StringBuilder(getTypeName(desc)); - if (!uniqueType || NameValidator.isReserved(nameBuilder.toString())) { - nameBuilder.append(nameIndex); - } - translatedName = nameBuilder.toString(); - return translatedName; - } - - public static String generateLocalVariableName(int index, TypeDescriptor desc) { - int nameIndex = index + 1; - return getTypeName(desc) + nameIndex; - } - - private static String getTypeName(TypeDescriptor desc) { - // Unfortunately each of these have different name getters, so they have different code paths - if (desc.isPrimitive()) { - TypeDescriptor.Primitive argCls = desc.getPrimitive(); - return argCls.name().toLowerCase(Locale.ROOT); - } else if (desc.isArray()) { - // List types would require this whole block again, so just go with aListx - return "arr"; - } else if (desc.isType()) { - String typeName = desc.getTypeEntry().getSimpleName().replace("$", ""); - typeName = typeName.substring(0, 1).toLowerCase(Locale.ROOT) + typeName.substring(1); - return typeName; - } else { - System.err.println("Encountered invalid argument type descriptor " + desc.toString()); - return "var"; - } - } -} diff --git a/src/main/java/cuchaz/enigma/translation/MappingTranslator.java b/src/main/java/cuchaz/enigma/translation/MappingTranslator.java deleted file mode 100644 index 529d0edb..00000000 --- a/src/main/java/cuchaz/enigma/translation/MappingTranslator.java +++ /dev/null @@ -1,24 +0,0 @@ -package cuchaz.enigma.translation; - -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.EntryMap; - -public class MappingTranslator implements Translator { - private final EntryMap mappings; - private final EntryResolver resolver; - - public MappingTranslator(EntryMap mappings, EntryResolver resolver) { - this.mappings = mappings; - this.resolver = resolver; - } - - @SuppressWarnings("unchecked") - @Override - public T translate(T translatable) { - if (translatable == null) { - return null; - } - return (T) translatable.translate(this, resolver, mappings); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/SignatureUpdater.java b/src/main/java/cuchaz/enigma/translation/SignatureUpdater.java deleted file mode 100644 index 37830535..00000000 --- a/src/main/java/cuchaz/enigma/translation/SignatureUpdater.java +++ /dev/null @@ -1,92 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation; - -import com.google.common.collect.Lists; - -import java.io.IOException; -import java.io.StringReader; -import java.util.List; - -public class SignatureUpdater { - - public static String update(String signature, ClassNameUpdater updater) { - try { - StringBuilder buf = new StringBuilder(); - - // read the signature character-by-character - StringReader reader = new StringReader(signature); - int i; - while ((i = reader.read()) != -1) { - char c = (char) i; - - // does this character start a class name? - if (c == 'L') { - // update the class name and add it to the buffer - buf.append('L'); - String className = readClass(reader); - if (className == null) { - throw new IllegalArgumentException("Malformed signature: " + signature); - } - buf.append(updater.update(className)); - buf.append(';'); - } else { - // copy the character into the buffer - buf.append(c); - } - } - - return buf.toString(); - } catch (IOException ex) { - // I'm pretty sure a StringReader will never throw one of these - throw new Error(ex); - } - } - - private static String readClass(StringReader reader) throws IOException { - // read all the characters in the buffer until we hit a ';' - // remember to treat generics correctly - StringBuilder buf = new StringBuilder(); - int depth = 0; - int i; - while ((i = reader.read()) != -1) { - char c = (char) i; - - if (c == '<') { - depth++; - } else if (c == '>') { - depth--; - } else if (depth == 0) { - if (c == ';') { - return buf.toString(); - } else { - buf.append(c); - } - } - } - - return null; - } - - public static List getClasses(String signature) { - final List classNames = Lists.newArrayList(); - update(signature, className -> { - classNames.add(className); - return className; - }); - return classNames; - } - - public interface ClassNameUpdater { - String update(String className); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/Translatable.java b/src/main/java/cuchaz/enigma/translation/Translatable.java deleted file mode 100644 index 0370ef13..00000000 --- a/src/main/java/cuchaz/enigma/translation/Translatable.java +++ /dev/null @@ -1,9 +0,0 @@ -package cuchaz.enigma.translation; - -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.EntryMap; - -public interface Translatable { - Translatable translate(Translator translator, EntryResolver resolver, EntryMap mappings); -} diff --git a/src/main/java/cuchaz/enigma/translation/TranslationDirection.java b/src/main/java/cuchaz/enigma/translation/TranslationDirection.java deleted file mode 100644 index 2ecb30be..00000000 --- a/src/main/java/cuchaz/enigma/translation/TranslationDirection.java +++ /dev/null @@ -1,36 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation; - -public enum TranslationDirection { - - DEOBFUSCATING { - @Override - public T choose(T deobfChoice, T obfChoice) { - if (deobfChoice == null) { - return obfChoice; - } - return deobfChoice; - } - }, - OBFUSCATING { - @Override - public T choose(T deobfChoice, T obfChoice) { - if (obfChoice == null) { - return deobfChoice; - } - return obfChoice; - } - }; - - public abstract T choose(T deobfChoice, T obfChoice); -} diff --git a/src/main/java/cuchaz/enigma/translation/Translator.java b/src/main/java/cuchaz/enigma/translation/Translator.java deleted file mode 100644 index c70141f2..00000000 --- a/src/main/java/cuchaz/enigma/translation/Translator.java +++ /dev/null @@ -1,61 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation; - -import com.google.common.collect.HashMultimap; -import com.google.common.collect.Multimap; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; - -public interface Translator { - T translate(T translatable); - - default Collection translate(Collection translatable) { - return translatable.stream() - .map(this::translate) - .collect(Collectors.toList()); - } - - default Set translate(Set translatable) { - return translatable.stream() - .map(this::translate) - .collect(Collectors.toSet()); - } - - default Map translateKeys(Map translatable) { - Map result = new HashMap<>(translatable.size()); - for (Map.Entry entry : translatable.entrySet()) { - result.put(translate(entry.getKey()), entry.getValue()); - } - return result; - } - - default Map translate(Map translatable) { - Map result = new HashMap<>(translatable.size()); - for (Map.Entry entry : translatable.entrySet()) { - result.put(translate(entry.getKey()), translate(entry.getValue())); - } - return result; - } - - default Multimap translate(Multimap translatable) { - Multimap result = HashMultimap.create(translatable.size(), 1); - for (Map.Entry> entry : translatable.asMap().entrySet()) { - result.putAll(translate(entry.getKey()), translate(entry.getValue())); - } - return result; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/VoidTranslator.java b/src/main/java/cuchaz/enigma/translation/VoidTranslator.java deleted file mode 100644 index c010833b..00000000 --- a/src/main/java/cuchaz/enigma/translation/VoidTranslator.java +++ /dev/null @@ -1,10 +0,0 @@ -package cuchaz.enigma.translation; - -public enum VoidTranslator implements Translator { - INSTANCE; - - @Override - public T translate(T translatable) { - return translatable; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/AccessModifier.java b/src/main/java/cuchaz/enigma/translation/mapping/AccessModifier.java deleted file mode 100644 index 5b79b794..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/AccessModifier.java +++ /dev/null @@ -1,25 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.translation.representation.AccessFlags; - -public enum AccessModifier { - UNCHANGED, PUBLIC, PROTECTED, PRIVATE; - - public String getFormattedName() { - return "ACC:" + super.toString(); - } - - public AccessFlags transform(AccessFlags access) { - switch (this) { - case PUBLIC: - return access.setPublic(); - case PROTECTED: - return access.setProtected(); - case PRIVATE: - return access.setPrivate(); - case UNCHANGED: - default: - return access; - } - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryMap.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryMap.java deleted file mode 100644 index e1a32533..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/EntryMap.java +++ /dev/null @@ -1,24 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.translation.representation.entry.Entry; - -import javax.annotation.Nullable; -import java.util.stream.Stream; - -public interface EntryMap { - void insert(Entry entry, T value); - - @Nullable - T remove(Entry entry); - - @Nullable - T get(Entry entry); - - default boolean contains(Entry entry) { - return get(entry) != null; - } - - Stream> getAllEntries(); - - boolean isEmpty(); -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java deleted file mode 100644 index c607817c..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/EntryMapping.java +++ /dev/null @@ -1,75 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; - -public class EntryMapping { - private final String targetName; - private final AccessModifier accessModifier; - private final @Nullable String javadoc; - - public EntryMapping(@Nonnull String targetName) { - this(targetName, AccessModifier.UNCHANGED); - } - - public EntryMapping(@Nonnull String targetName, @Nullable String javadoc) { - this(targetName, AccessModifier.UNCHANGED, javadoc); - } - - public EntryMapping(@Nonnull String targetName, AccessModifier accessModifier) { - this(targetName, accessModifier, null); - } - - public EntryMapping(@Nonnull String targetName, AccessModifier accessModifier, @Nullable String javadoc) { - this.targetName = targetName; - this.accessModifier = accessModifier; - this.javadoc = javadoc; - } - - @Nonnull - public String getTargetName() { - return targetName; - } - - @Nonnull - public AccessModifier getAccessModifier() { - if (accessModifier == null) { - return AccessModifier.UNCHANGED; - } - return accessModifier; - } - - @Nullable - public String getJavadoc() { - return javadoc; - } - - public EntryMapping withName(String newName) { - return new EntryMapping(newName, accessModifier, javadoc); - } - - public EntryMapping withModifier(AccessModifier newModifier) { - return new EntryMapping(targetName, newModifier, javadoc); - } - - public EntryMapping withDocs(String newDocs) { - return new EntryMapping(targetName, accessModifier, newDocs); - } - - @Override - public boolean equals(Object obj) { - if (obj == this) return true; - - if (obj instanceof EntryMapping) { - EntryMapping mapping = (EntryMapping) obj; - return mapping.targetName.equals(targetName) && mapping.accessModifier.equals(accessModifier); - } - - return false; - } - - @Override - public int hashCode() { - return targetName.hashCode() + accessModifier.hashCode() * 31; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java deleted file mode 100644 index ad36c97f..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/EntryRemapper.java +++ /dev/null @@ -1,105 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.MappingTranslator; -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.tree.DeltaTrackingTree; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.Entry; - -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.function.UnaryOperator; -import java.util.stream.Stream; - -public class EntryRemapper { - private final DeltaTrackingTree obfToDeobf; - - private final EntryResolver obfResolver; - private final Translator deobfuscator; - - private final MappingValidator validator; - - private EntryRemapper(JarIndex jarIndex, EntryTree obfToDeobf) { - this.obfToDeobf = new DeltaTrackingTree<>(obfToDeobf); - - this.obfResolver = jarIndex.getEntryResolver(); - - this.deobfuscator = new MappingTranslator(obfToDeobf, obfResolver); - - this.validator = new MappingValidator(obfToDeobf, deobfuscator, jarIndex); - } - - public static EntryRemapper mapped(JarIndex index, EntryTree obfToDeobf) { - return new EntryRemapper(index, obfToDeobf); - } - - public static EntryRemapper empty(JarIndex index) { - return new EntryRemapper(index, new HashEntryTree<>()); - } - - public > void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping) { - mapFromObf(obfuscatedEntry, deobfMapping, true); - } - - public > void mapFromObf(E obfuscatedEntry, @Nullable EntryMapping deobfMapping, boolean renaming) { - Collection resolvedEntries = obfResolver.resolveEntry(obfuscatedEntry, renaming ? ResolutionStrategy.RESOLVE_ROOT : ResolutionStrategy.RESOLVE_CLOSEST); - - if (renaming && deobfMapping != null) { - for (E resolvedEntry : resolvedEntries) { - validator.validateRename(resolvedEntry, deobfMapping.getTargetName()); - } - } - - for (E resolvedEntry : resolvedEntries) { - obfToDeobf.insert(resolvedEntry, deobfMapping); - } - } - - public void removeByObf(Entry obfuscatedEntry) { - mapFromObf(obfuscatedEntry, null); - } - - @Nullable - public EntryMapping getDeobfMapping(Entry entry) { - return obfToDeobf.get(entry); - } - - public boolean hasDeobfMapping(Entry obfEntry) { - return obfToDeobf.contains(obfEntry); - } - - public T deobfuscate(T translatable) { - return deobfuscator.translate(translatable); - } - - public Translator getDeobfuscator() { - return deobfuscator; - } - - public Stream> getObfEntries() { - return obfToDeobf.getAllEntries(); - } - - public Collection> getObfChildren(Entry obfuscatedEntry) { - return obfToDeobf.getChildren(obfuscatedEntry); - } - - public DeltaTrackingTree getObfToDeobf() { - return obfToDeobf; - } - - public MappingDelta takeMappingDelta() { - return obfToDeobf.takeDelta(); - } - - public boolean isDirty() { - return obfToDeobf.isDirty(); - } - - public EntryResolver getObfResolver() { - return obfResolver; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/EntryResolver.java b/src/main/java/cuchaz/enigma/translation/mapping/EntryResolver.java deleted file mode 100644 index 521f72d0..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/EntryResolver.java +++ /dev/null @@ -1,41 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import com.google.common.collect.Streams; -import cuchaz.enigma.analysis.EntryReference; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.util.Collection; -import java.util.Set; -import java.util.stream.Collectors; - -public interface EntryResolver { - > Collection resolveEntry(E entry, ResolutionStrategy strategy); - - default > E resolveFirstEntry(E entry, ResolutionStrategy strategy) { - return resolveEntry(entry, strategy).stream().findFirst().orElse(entry); - } - - default , C extends Entry> Collection> resolveReference(EntryReference reference, ResolutionStrategy strategy) { - Collection entry = resolveEntry(reference.entry, strategy); - if (reference.context != null) { - Collection context = resolveEntry(reference.context, strategy); - return Streams.zip(entry.stream(), context.stream(), (e, c) -> new EntryReference<>(e, c, reference)) - .collect(Collectors.toList()); - } else { - return entry.stream() - .map(e -> new EntryReference<>(e, null, reference)) - .collect(Collectors.toList()); - } - } - - default , C extends Entry> EntryReference resolveFirstReference(EntryReference reference, ResolutionStrategy strategy) { - E entry = resolveFirstEntry(reference.entry, strategy); - C context = resolveFirstEntry(reference.context, strategy); - return new EntryReference<>(entry, context, reference); - } - - Set> resolveEquivalentEntries(Entry entry); - - Set resolveEquivalentMethods(MethodEntry methodEntry); -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/IndexEntryResolver.java b/src/main/java/cuchaz/enigma/translation/mapping/IndexEntryResolver.java deleted file mode 100644 index 78231ddd..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/IndexEntryResolver.java +++ /dev/null @@ -1,227 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import com.google.common.collect.Sets; -import cuchaz.enigma.analysis.IndexTreeBuilder; -import cuchaz.enigma.analysis.MethodImplementationsTreeNode; -import cuchaz.enigma.analysis.MethodInheritanceTreeNode; -import cuchaz.enigma.analysis.index.BridgeMethodIndex; -import cuchaz.enigma.analysis.index.EntryIndex; -import cuchaz.enigma.analysis.index.InheritanceIndex; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.VoidTranslator; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import javax.annotation.Nullable; -import java.util.*; -import java.util.stream.Collectors; - -public class IndexEntryResolver implements EntryResolver { - private final EntryIndex entryIndex; - private final InheritanceIndex inheritanceIndex; - private final BridgeMethodIndex bridgeMethodIndex; - - private final IndexTreeBuilder treeBuilder; - - public IndexEntryResolver(JarIndex index) { - this.entryIndex = index.getEntryIndex(); - this.inheritanceIndex = index.getInheritanceIndex(); - this.bridgeMethodIndex = index.getBridgeMethodIndex(); - - this.treeBuilder = new IndexTreeBuilder(index); - } - - @Override - @SuppressWarnings("unchecked") - public > Collection resolveEntry(E entry, ResolutionStrategy strategy) { - if (entry == null) { - return Collections.emptySet(); - } - - Entry classChild = getClassChild(entry); - if (classChild != null && !(classChild instanceof ClassEntry)) { - AccessFlags access = entryIndex.getEntryAccess(classChild); - - // If we're looking for the closest and this entry exists, we're done looking - if (strategy == ResolutionStrategy.RESOLVE_CLOSEST && access != null) { - return Collections.singleton(entry); - } - - if (access == null || !access.isPrivate()) { - Collection> resolvedChildren = resolveChildEntry(classChild, strategy); - if (!resolvedChildren.isEmpty()) { - return resolvedChildren.stream() - .map(resolvedChild -> (E) entry.replaceAncestor(classChild, resolvedChild)) - .collect(Collectors.toList()); - } - } - } - - return Collections.singleton(entry); - } - - @Nullable - private Entry getClassChild(Entry entry) { - if (entry instanceof ClassEntry) { - return null; - } - - // get the entry in the hierarchy that is the child of a class - List> ancestry = entry.getAncestry(); - for (int i = ancestry.size() - 1; i > 0; i--) { - Entry child = ancestry.get(i); - Entry cast = child.castParent(ClassEntry.class); - if (cast != null && !(cast instanceof ClassEntry)) { - // we found the entry which is a child of a class, we are now able to resolve the owner of this entry - return cast; - } - } - - return null; - } - - private Set> resolveChildEntry(Entry entry, ResolutionStrategy strategy) { - ClassEntry ownerClass = entry.getParent(); - - if (entry instanceof MethodEntry) { - MethodEntry bridgeMethod = bridgeMethodIndex.getBridgeFromSpecialized((MethodEntry) entry); - if (bridgeMethod != null && ownerClass.equals(bridgeMethod.getParent())) { - Set> resolvedBridge = resolveChildEntry(bridgeMethod, strategy); - if (!resolvedBridge.isEmpty()) { - return resolvedBridge; - } else { - return Collections.singleton(bridgeMethod); - } - } - } - - Set> resolvedEntries = new HashSet<>(); - - for (ClassEntry parentClass : inheritanceIndex.getParents(ownerClass)) { - Entry parentEntry = entry.withParent(parentClass); - - if (strategy == ResolutionStrategy.RESOLVE_ROOT) { - resolvedEntries.addAll(resolveRoot(parentEntry, strategy)); - } else { - resolvedEntries.addAll(resolveClosest(parentEntry, strategy)); - } - } - - return resolvedEntries; - } - - private Collection> resolveRoot(Entry entry, ResolutionStrategy strategy) { - // When resolving root, we want to first look for the lowest entry before returning ourselves - Set> parentResolution = resolveChildEntry(entry, strategy); - - if (parentResolution.isEmpty()) { - AccessFlags parentAccess = entryIndex.getEntryAccess(entry); - if (parentAccess != null && !parentAccess.isPrivate()) { - return Collections.singleton(entry); - } - } - - return parentResolution; - } - - private Collection> resolveClosest(Entry entry, ResolutionStrategy strategy) { - // When resolving closest, we want to first check if we exist before looking further down - AccessFlags parentAccess = entryIndex.getEntryAccess(entry); - if (parentAccess != null && !parentAccess.isPrivate()) { - return Collections.singleton(entry); - } else { - return resolveChildEntry(entry, strategy); - } - } - - @Override - public Set> resolveEquivalentEntries(Entry entry) { - MethodEntry relevantMethod = entry.findAncestor(MethodEntry.class); - if (relevantMethod == null || !entryIndex.hasMethod(relevantMethod)) { - return Collections.singleton(entry); - } - - Set equivalentMethods = resolveEquivalentMethods(relevantMethod); - Set> equivalentEntries = new HashSet<>(equivalentMethods.size()); - - for (MethodEntry equivalentMethod : equivalentMethods) { - Entry equivalentEntry = entry.replaceAncestor(relevantMethod, equivalentMethod); - equivalentEntries.add(equivalentEntry); - } - - return equivalentEntries; - } - - @Override - public Set resolveEquivalentMethods(MethodEntry methodEntry) { - AccessFlags access = entryIndex.getMethodAccess(methodEntry); - if (access == null) { - throw new IllegalArgumentException("Could not find method " + methodEntry); - } - - if (!canInherit(methodEntry, access)) { - return Collections.singleton(methodEntry); - } - - Set methodEntries = Sets.newHashSet(); - resolveEquivalentMethods(methodEntries, treeBuilder.buildMethodInheritance(VoidTranslator.INSTANCE, methodEntry)); - return methodEntries; - } - - private void resolveEquivalentMethods(Set methodEntries, MethodInheritanceTreeNode node) { - MethodEntry methodEntry = node.getMethodEntry(); - if (methodEntries.contains(methodEntry)) { - return; - } - - AccessFlags flags = entryIndex.getMethodAccess(methodEntry); - if (flags != null && canInherit(methodEntry, flags)) { - // collect the entry - methodEntries.add(methodEntry); - } - - // look at bridge methods! - MethodEntry bridgedMethod = bridgeMethodIndex.getBridgeFromSpecialized(methodEntry); - while (bridgedMethod != null) { - methodEntries.addAll(resolveEquivalentMethods(bridgedMethod)); - bridgedMethod = bridgeMethodIndex.getBridgeFromSpecialized(bridgedMethod); - } - - // look at interface methods too - for (MethodImplementationsTreeNode implementationsNode : treeBuilder.buildMethodImplementations(VoidTranslator.INSTANCE, methodEntry)) { - resolveEquivalentMethods(methodEntries, implementationsNode); - } - - // recurse - for (int i = 0; i < node.getChildCount(); i++) { - resolveEquivalentMethods(methodEntries, (MethodInheritanceTreeNode) node.getChildAt(i)); - } - } - - private void resolveEquivalentMethods(Set methodEntries, MethodImplementationsTreeNode node) { - MethodEntry methodEntry = node.getMethodEntry(); - AccessFlags flags = entryIndex.getMethodAccess(methodEntry); - if (flags != null && !flags.isPrivate() && !flags.isStatic()) { - // collect the entry - methodEntries.add(methodEntry); - } - - // look at bridge methods! - MethodEntry bridgedMethod = bridgeMethodIndex.getBridgeFromSpecialized(methodEntry); - while (bridgedMethod != null) { - methodEntries.addAll(resolveEquivalentMethods(bridgedMethod)); - bridgedMethod = bridgeMethodIndex.getBridgeFromSpecialized(bridgedMethod); - } - - // recurse - for (int i = 0; i < node.getChildCount(); i++) { - resolveEquivalentMethods(methodEntries, (MethodImplementationsTreeNode) node.getChildAt(i)); - } - } - - private boolean canInherit(MethodEntry entry, AccessFlags access) { - return !entry.isConstructor() && !access.isPrivate() && !access.isStatic() && !access.isFinal(); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java deleted file mode 100644 index 1407bb60..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingDelta.java +++ /dev/null @@ -1,54 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.util.stream.Stream; - -public class MappingDelta implements Translatable { - public static final Object PLACEHOLDER = new Object(); - - private final EntryTree baseMappings; - - private final EntryTree changes; - - public MappingDelta(EntryTree baseMappings, EntryTree changes) { - this.baseMappings = baseMappings; - this.changes = changes; - } - - public MappingDelta(EntryTree baseMappings) { - this(baseMappings, new HashEntryTree<>()); - } - - public static MappingDelta added(EntryTree mappings) { - EntryTree changes = new HashEntryTree<>(); - mappings.getAllEntries().forEach(entry -> changes.insert(entry, PLACEHOLDER)); - - return new MappingDelta<>(new HashEntryTree<>(), changes); - } - - public EntryTree getBaseMappings() { - return baseMappings; - } - - public EntryTree getChanges() { - return changes; - } - - public Stream> getChangedRoots() { - return changes.getRootNodes().map(EntryTreeNode::getEntry); - } - - @Override - public MappingDelta translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - return new MappingDelta<>( - translator.translate(baseMappings), - translator.translate(changes) - ); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingFileNameFormat.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingFileNameFormat.java deleted file mode 100644 index e40bfe75..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingFileNameFormat.java +++ /dev/null @@ -1,10 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import com.google.gson.annotations.SerializedName; - -public enum MappingFileNameFormat { - @SerializedName("by_obf") - BY_OBF, - @SerializedName("by_deobf") - BY_DEOBF -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingPair.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingPair.java deleted file mode 100644 index 5d39e3d2..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingPair.java +++ /dev/null @@ -1,32 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.translation.representation.entry.Entry; - -import javax.annotation.Nullable; - -public class MappingPair, M> { - private final E entry; - private M mapping; - - public MappingPair(E entry, @Nullable M mapping) { - this.entry = entry; - this.mapping = mapping; - } - - public MappingPair(E entry) { - this(entry, null); - } - - public E getEntry() { - return entry; - } - - @Nullable - public M getMapping() { - return mapping; - } - - public void setMapping(M mapping) { - this.mapping = mapping; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingSaveParameters.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingSaveParameters.java deleted file mode 100644 index 07065d6a..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingSaveParameters.java +++ /dev/null @@ -1,16 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import com.google.gson.annotations.SerializedName; - -public class MappingSaveParameters { - @SerializedName("file_name_format") - private final MappingFileNameFormat fileNameFormat; - - public MappingSaveParameters(MappingFileNameFormat fileNameFormat) { - this.fileNameFormat = fileNameFormat; - } - - public MappingFileNameFormat getFileNameFormat() { - return fileNameFormat; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java deleted file mode 100644 index dffcb0c6..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingValidator.java +++ /dev/null @@ -1,76 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.analysis.index.InheritanceIndex; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; - -import java.util.Collection; -import java.util.HashSet; -import java.util.stream.Collectors; - -public class MappingValidator { - private final EntryTree obfToDeobf; - private final Translator deobfuscator; - private final JarIndex index; - - public MappingValidator(EntryTree obfToDeobf, Translator deobfuscator, JarIndex index) { - this.obfToDeobf = obfToDeobf; - this.deobfuscator = deobfuscator; - this.index = index; - } - - public void validateRename(Entry entry, String name) throws IllegalNameException { - Collection> equivalentEntries = index.getEntryResolver().resolveEquivalentEntries(entry); - for (Entry equivalentEntry : equivalentEntries) { - equivalentEntry.validateName(name); - validateUnique(equivalentEntry, name); - } - } - - private void validateUnique(Entry entry, String name) { - ClassEntry containingClass = entry.getContainingClass(); - Collection relatedClasses = getRelatedClasses(containingClass); - - for (ClassEntry relatedClass : relatedClasses) { - Entry relatedEntry = entry.replaceAncestor(containingClass, relatedClass); - Entry translatedEntry = deobfuscator.translate(relatedEntry); - - Collection> translatedSiblings = obfToDeobf.getSiblings(relatedEntry).stream() - .map(deobfuscator::translate) - .collect(Collectors.toList()); - - if (!isUnique(translatedEntry, translatedSiblings, name)) { - Entry parent = translatedEntry.getParent(); - if (parent != null) { - throw new IllegalNameException(name, "Name is not unique in " + parent + "!"); - } else { - throw new IllegalNameException(name, "Name is not unique!"); - } - } - } - } - - private Collection getRelatedClasses(ClassEntry classEntry) { - InheritanceIndex inheritanceIndex = index.getInheritanceIndex(); - - Collection relatedClasses = new HashSet<>(); - relatedClasses.add(classEntry); - relatedClasses.addAll(inheritanceIndex.getChildren(classEntry)); - relatedClasses.addAll(inheritanceIndex.getAncestors(classEntry)); - - return relatedClasses; - } - - private boolean isUnique(Entry entry, Collection> siblings, String name) { - for (Entry sibling : siblings) { - if (entry.canConflictWith(sibling) && sibling.getName().equals(name)) { - return false; - } - } - return true; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/MappingsChecker.java b/src/main/java/cuchaz/enigma/translation/mapping/MappingsChecker.java deleted file mode 100644 index 5d9794fb..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/MappingsChecker.java +++ /dev/null @@ -1,99 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.analysis.index.JarIndex; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.stream.Collectors; - -public class MappingsChecker { - private final JarIndex index; - private final EntryTree mappings; - - public MappingsChecker(JarIndex index, EntryTree mappings) { - this.index = index; - this.mappings = mappings; - } - - public Dropped dropBrokenMappings(ProgressListener progress) { - Dropped dropped = new Dropped(); - - Collection> obfEntries = mappings.getAllEntries() - .filter(e -> e instanceof ClassEntry || e instanceof MethodEntry || e instanceof FieldEntry || e instanceof LocalVariableEntry) - .collect(Collectors.toList()); - - progress.init(obfEntries.size(), "Checking for dropped mappings"); - - int steps = 0; - for (Entry entry : obfEntries) { - progress.step(steps++, entry.toString()); - tryDropEntry(dropped, entry); - } - - dropped.apply(mappings); - - return dropped; - } - - private void tryDropEntry(Dropped dropped, Entry entry) { - if (shouldDropEntry(entry)) { - EntryMapping mapping = mappings.get(entry); - if (mapping != null) { - dropped.drop(entry, mapping); - } - } - } - - private boolean shouldDropEntry(Entry entry) { - if (!index.getEntryIndex().hasEntry(entry)) { - return true; - } - Collection> resolvedEntries = index.getEntryResolver().resolveEntry(entry, ResolutionStrategy.RESOLVE_ROOT); - return !resolvedEntries.contains(entry); - } - - public static class Dropped { - private final Map, String> droppedMappings = new HashMap<>(); - - public void drop(Entry entry, EntryMapping mapping) { - droppedMappings.put(entry, mapping.getTargetName()); - } - - void apply(EntryTree mappings) { - for (Entry entry : droppedMappings.keySet()) { - EntryTreeNode node = mappings.findNode(entry); - if (node == null) { - continue; - } - - for (Entry childEntry : node.getChildrenRecursively()) { - mappings.remove(childEntry); - } - } - } - - public Map, String> getDroppedMappings() { - return droppedMappings; - } - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/NameValidator.java b/src/main/java/cuchaz/enigma/translation/mapping/NameValidator.java deleted file mode 100644 index 5bc2f67a..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/NameValidator.java +++ /dev/null @@ -1,53 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -import java.util.Arrays; -import java.util.List; -import java.util.regex.Pattern; - -public class NameValidator { - private static final Pattern IDENTIFIER_PATTERN; - private static final Pattern CLASS_PATTERN; - private static final List ILLEGAL_IDENTIFIERS = Arrays.asList( - "abstract", "continue", "for", "new", "switch", "assert", "default", "goto", "package", "synchronized", - "boolean", "do", "if", "private", "this", "break", "double", "implements", "protected", "throw", "byte", - "else", "import", "public", "throws", "case", "enum", "instanceof", "return", "transient", "catch", - "extends", "int", "short", "try", "char", "final", "interface", "static", "void", "class", "finally", - "long", "strictfp", "volatile", "const", "float", "native", "super", "while", "_" - ); - - static { - String identifierRegex = "[A-Za-z_<][A-Za-z0-9_>]*"; - IDENTIFIER_PATTERN = Pattern.compile(identifierRegex); - CLASS_PATTERN = Pattern.compile(String.format("^(%s(\\.|/))*(%s)$", identifierRegex, identifierRegex)); - } - - public static void validateClassName(String name) { - if (!CLASS_PATTERN.matcher(name).matches() || ILLEGAL_IDENTIFIERS.contains(name)) { - throw new IllegalNameException(name, "This doesn't look like a legal class name"); - } - } - - public static void validateIdentifier(String name) { - if (!IDENTIFIER_PATTERN.matcher(name).matches() || ILLEGAL_IDENTIFIERS.contains(name)) { - throw new IllegalNameException(name, "This doesn't look like a legal identifier"); - } - } - - public static boolean isReserved(String name) { - return ILLEGAL_IDENTIFIERS.contains(name); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/ResolutionStrategy.java b/src/main/java/cuchaz/enigma/translation/mapping/ResolutionStrategy.java deleted file mode 100644 index 1c28e028..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/ResolutionStrategy.java +++ /dev/null @@ -1,6 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -public enum ResolutionStrategy { - RESOLVE_ROOT, - RESOLVE_CLOSEST -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/VoidEntryResolver.java b/src/main/java/cuchaz/enigma/translation/mapping/VoidEntryResolver.java deleted file mode 100644 index 2eab55fd..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/VoidEntryResolver.java +++ /dev/null @@ -1,27 +0,0 @@ -package cuchaz.enigma.translation.mapping; - -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.util.Collection; -import java.util.Collections; -import java.util.Set; - -public enum VoidEntryResolver implements EntryResolver { - INSTANCE; - - @Override - public > Collection resolveEntry(E entry, ResolutionStrategy strategy) { - return Collections.singleton(entry); - } - - @Override - public Set> resolveEquivalentEntries(Entry entry) { - return Collections.singleton(entry); - } - - @Override - public Set resolveEquivalentMethods(MethodEntry methodEntry) { - return Collections.singleton(methodEntry); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java deleted file mode 100644 index af92ffbe..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaFormat.java +++ /dev/null @@ -1,9 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -public class EnigmaFormat { - public static final String COMMENT = "COMMENT"; - public static final String CLASS = "CLASS"; - public static final String FIELD = "FIELD"; - public static final String METHOD = "METHOD"; - public static final String PARAMETER = "ARG"; -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java deleted file mode 100644 index 53bbaa3b..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsReader.java +++ /dev/null @@ -1,319 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import com.google.common.base.Charsets; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.AccessModifier; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingPair; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.*; -import cuchaz.enigma.utils.I18n; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayDeque; -import java.util.Arrays; -import java.util.Deque; -import java.util.List; -import java.util.Locale; -import java.util.stream.Collectors; - -public enum EnigmaMappingsReader implements MappingsReader { - FILE { - @Override - public EntryTree read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { - progress.init(1, I18n.translate("progress.mappings.enigma_file.loading")); - - EntryTree mappings = new HashEntryTree<>(); - readFile(path, mappings); - - progress.step(1, I18n.translate("progress.mappings.enigma_file.done")); - - return mappings; - } - }, - DIRECTORY { - @Override - public EntryTree read(Path root, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { - EntryTree mappings = new HashEntryTree<>(); - - List files = Files.walk(root) - .filter(f -> !Files.isDirectory(f)) - .filter(f -> f.toString().endsWith(".mapping")) - .collect(Collectors.toList()); - - progress.init(files.size(), I18n.translate("progress.mappings.enigma_directory.loading")); - int step = 0; - - for (Path file : files) { - progress.step(step++, root.relativize(file).toString()); - if (Files.isHidden(file)) { - continue; - } - readFile(file, mappings); - } - - return mappings; - } - }, - ZIP { - @Override - public EntryTree read(Path zip, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException { - try (FileSystem fs = FileSystems.newFileSystem(zip, (ClassLoader) null)) { - return DIRECTORY.read(fs.getPath("/"), progress, saveParameters); - } - } - }; - - protected void readFile(Path path, EntryTree mappings) throws IOException, MappingParseException { - List lines = Files.readAllLines(path, Charsets.UTF_8); - Deque> mappingStack = new ArrayDeque<>(); - - for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { - String line = lines.get(lineNumber); - int indentation = countIndentation(line); - - line = formatLine(line); - if (line == null) { - continue; - } - - cleanMappingStack(indentation, mappingStack, mappings); - - try { - MappingPair pair = parseLine(mappingStack.peek(), line); - if (pair != null) { - mappingStack.push(pair); - if (pair.getMapping() != null) { - - } - } - } catch (Throwable t) { - t.printStackTrace(); - throw new MappingParseException(path::toString, lineNumber, t.toString()); - } - } - - // Clean up rest - cleanMappingStack(0, mappingStack, mappings); - } - - private void cleanMappingStack(int indentation, Deque> mappingStack, EntryTree mappings) { - while (indentation < mappingStack.size()) { - MappingPair pair = mappingStack.pop(); - if (pair.getMapping() != null) { - mappings.insert(pair.getEntry(), pair.getMapping().bake()); - } - } - } - - @Nullable - private String formatLine(String line) { - line = stripComment(line); - line = line.trim(); - - if (line.isEmpty()) { - return null; - } - - return line; - } - - private String stripComment(String line) { - //Dont support comments on javadoc lines - if (line.trim().startsWith(EnigmaFormat.COMMENT)) { - return line; - } - - int commentPos = line.indexOf('#'); - if (commentPos >= 0) { - return line.substring(0, commentPos); - } - return line; - } - - private int countIndentation(String line) { - int indent = 0; - for (int i = 0; i < line.length(); i++) { - if (line.charAt(i) != '\t') { - break; - } - indent++; - } - return indent; - } - - private MappingPair parseLine(@Nullable MappingPair parent, String line) { - String[] tokens = line.trim().split("\\s"); - String keyToken = tokens[0].toUpperCase(Locale.ROOT); - Entry parentEntry = parent == null ? null : parent.getEntry(); - - switch (keyToken) { - case EnigmaFormat.CLASS: - return parseClass(parentEntry, tokens); - case EnigmaFormat.FIELD: - return parseField(parentEntry, tokens); - case EnigmaFormat.METHOD: - return parseMethod(parentEntry, tokens); - case EnigmaFormat.PARAMETER: - return parseArgument(parentEntry, tokens); - case EnigmaFormat.COMMENT: - readJavadoc(parent, tokens); - return null; - default: - throw new RuntimeException("Unknown token '" + keyToken + "'"); - } - } - - private void readJavadoc(MappingPair parent, String[] tokens) { - if (parent == null) - throw new IllegalStateException("Javadoc has no parent!"); - // Empty string to concat - String jdLine = tokens.length > 1 ? String.join(" ", Arrays.copyOfRange(tokens,1,tokens.length)) : ""; - if (parent.getMapping() == null) { - parent.setMapping(new RawEntryMapping(parent.getEntry().getName(), AccessModifier.UNCHANGED)); - } - parent.getMapping().addJavadocLine(MappingHelper.unescape(jdLine)); - } - - private MappingPair parseClass(@Nullable Entry parent, String[] tokens) { - String obfuscatedName = ClassEntry.getInnerName(tokens[1]); - ClassEntry obfuscatedEntry; - if (parent instanceof ClassEntry) { - obfuscatedEntry = new ClassEntry((ClassEntry) parent, obfuscatedName); - } else { - obfuscatedEntry = new ClassEntry(obfuscatedName); - } - - String mapping = null; - AccessModifier modifier = AccessModifier.UNCHANGED; - - if (tokens.length == 3) { - AccessModifier parsedModifier = parseModifier(tokens[2]); - if (parsedModifier != null) { - modifier = parsedModifier; - mapping = obfuscatedName; - } else { - mapping = tokens[2]; - } - } else if (tokens.length == 4) { - mapping = tokens[2]; - modifier = parseModifier(tokens[3]); - } - - if (mapping != null) { - return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); - } else { - return new MappingPair<>(obfuscatedEntry); - } - } - - private MappingPair parseField(@Nullable Entry parent, String[] tokens) { - if (!(parent instanceof ClassEntry)) { - throw new RuntimeException("Field must be a child of a class!"); - } - - ClassEntry ownerEntry = (ClassEntry) parent; - - String obfuscatedName = tokens[1]; - String mapping = obfuscatedName; - AccessModifier modifier = AccessModifier.UNCHANGED; - TypeDescriptor descriptor; - - if (tokens.length == 3) { - mapping = tokens[1]; - descriptor = new TypeDescriptor(tokens[2]); - } else if (tokens.length == 4) { - AccessModifier parsedModifier = parseModifier(tokens[3]); - if (parsedModifier != null) { - descriptor = new TypeDescriptor(tokens[2]); - modifier = parsedModifier; - } else { - mapping = tokens[2]; - descriptor = new TypeDescriptor(tokens[3]); - } - } else if (tokens.length == 5) { - descriptor = new TypeDescriptor(tokens[3]); - mapping = tokens[2]; - modifier = parseModifier(tokens[4]); - } else { - throw new RuntimeException("Invalid field declaration"); - } - - FieldEntry obfuscatedEntry = new FieldEntry(ownerEntry, obfuscatedName, descriptor); - if (mapping != null) { - return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); - } else { - return new MappingPair<>(obfuscatedEntry); - } - } - - private MappingPair parseMethod(@Nullable Entry parent, String[] tokens) { - if (!(parent instanceof ClassEntry)) { - throw new RuntimeException("Method must be a child of a class!"); - } - - ClassEntry ownerEntry = (ClassEntry) parent; - - String obfuscatedName = tokens[1]; - String mapping = null; - AccessModifier modifier = AccessModifier.UNCHANGED; - MethodDescriptor descriptor; - - if (tokens.length == 3) { - descriptor = new MethodDescriptor(tokens[2]); - } else if (tokens.length == 4) { - AccessModifier parsedModifier = parseModifier(tokens[3]); - if (parsedModifier != null) { - modifier = parsedModifier; - mapping = obfuscatedName; - descriptor = new MethodDescriptor(tokens[2]); - } else { - mapping = tokens[2]; - descriptor = new MethodDescriptor(tokens[3]); - } - } else if (tokens.length == 5) { - mapping = tokens[2]; - modifier = parseModifier(tokens[4]); - descriptor = new MethodDescriptor(tokens[3]); - } else { - throw new RuntimeException("Invalid method declaration"); - } - - MethodEntry obfuscatedEntry = new MethodEntry(ownerEntry, obfuscatedName, descriptor); - if (mapping != null) { - return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping, modifier)); - } else { - return new MappingPair<>(obfuscatedEntry); - } - } - - private MappingPair parseArgument(@Nullable Entry parent, String[] tokens) { - if (!(parent instanceof MethodEntry)) { - throw new RuntimeException("Method arg must be a child of a method!"); - } - - MethodEntry ownerEntry = (MethodEntry) parent; - LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerEntry, Integer.parseInt(tokens[1]), "", true, null); - String mapping = tokens[2]; - - return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); - } - - @Nullable - private AccessModifier parseModifier(String token) { - if (token.startsWith("ACC:")) { - return AccessModifier.valueOf(token.substring(4)); - } - return null; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java deleted file mode 100644 index be0fceb5..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/EnigmaMappingsWriter.java +++ /dev/null @@ -1,316 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - * - * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.mapping.serde; - -import java.io.IOException; -import java.io.PrintWriter; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.file.DirectoryStream; -import java.nio.file.FileSystem; -import java.nio.file.FileSystems; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Objects; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.translation.MappingTranslator; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.AccessModifier; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingDelta; -import cuchaz.enigma.translation.mapping.MappingFileNameFormat; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.VoidEntryResolver; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.LFPrintWriter; - -public enum EnigmaMappingsWriter implements MappingsWriter { - FILE { - @Override - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { - Collection classes = mappings.getRootNodes() - .filter(entry -> entry instanceof ClassEntry) - .map(entry -> (ClassEntry) entry) - .collect(Collectors.toList()); - - progress.init(classes.size(), I18n.translate("progress.mappings.enigma_file.writing")); - - int steps = 0; - try (PrintWriter writer = new LFPrintWriter(Files.newBufferedWriter(path))) { - for (ClassEntry classEntry : classes) { - progress.step(steps++, classEntry.getFullName()); - writeRoot(writer, mappings, classEntry); - } - } catch (IOException e) { - e.printStackTrace(); - } - } - }, - DIRECTORY { - @Override - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { - Collection changedClasses = delta.getChangedRoots() - .filter(entry -> entry instanceof ClassEntry) - .map(entry -> (ClassEntry) entry) - .collect(Collectors.toList()); - - applyDeletions(path, changedClasses, mappings, delta.getBaseMappings(), saveParameters.getFileNameFormat()); - - progress.init(changedClasses.size(), I18n.translate("progress.mappings.enigma_directory.writing")); - - AtomicInteger steps = new AtomicInteger(); - - Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE); - changedClasses.parallelStream().forEach(classEntry -> { - progress.step(steps.getAndIncrement(), classEntry.getFullName()); - - try { - ClassEntry fileEntry = classEntry; - if (saveParameters.getFileNameFormat() == MappingFileNameFormat.BY_DEOBF) { - fileEntry = translator.translate(fileEntry); - } - - Path classPath = resolve(path, fileEntry); - Files.createDirectories(classPath.getParent()); - Files.deleteIfExists(classPath); - - try (PrintWriter writer = new LFPrintWriter(Files.newBufferedWriter(classPath))) { - writeRoot(writer, mappings, classEntry); - } - } catch (Throwable t) { - System.err.println("Failed to write class '" + classEntry.getFullName() + "'"); - t.printStackTrace(); - } - }); - } - - private void applyDeletions(Path root, Collection changedClasses, EntryTree mappings, EntryTree oldMappings, MappingFileNameFormat fileNameFormat) { - Translator oldMappingTranslator = new MappingTranslator(oldMappings, VoidEntryResolver.INSTANCE); - - Stream deletedClassStream = changedClasses.stream() - .filter(e -> !Objects.equals(oldMappings.get(e), mappings.get(e))); - - if (fileNameFormat == MappingFileNameFormat.BY_DEOBF) { - deletedClassStream = deletedClassStream.map(oldMappingTranslator::translate); - } - - Collection deletedClasses = deletedClassStream.collect(Collectors.toList()); - - for (ClassEntry classEntry : deletedClasses) { - try { - Files.deleteIfExists(resolve(root, classEntry)); - } catch (IOException e) { - System.err.println("Failed to delete deleted class '" + classEntry + "'"); - e.printStackTrace(); - } - } - - for (ClassEntry classEntry : deletedClasses) { - String packageName = classEntry.getPackageName(); - if (packageName != null) { - Path packagePath = Paths.get(packageName); - try { - deleteDeadPackages(root, packagePath); - } catch (IOException e) { - System.err.println("Failed to delete dead package '" + packageName + "'"); - e.printStackTrace(); - } - } - } - } - - private void deleteDeadPackages(Path root, Path packagePath) throws IOException { - for (int i = packagePath.getNameCount() - 1; i >= 0; i--) { - Path subPath = packagePath.subpath(0, i + 1); - Path packagePart = root.resolve(subPath); - if (isEmpty(packagePart)) { - Files.deleteIfExists(packagePart); - } - } - } - - private boolean isEmpty(Path path) { - try (DirectoryStream stream = Files.newDirectoryStream(path)) { - return !stream.iterator().hasNext(); - } catch (IOException e) { - return false; - } - } - - private Path resolve(Path root, ClassEntry classEntry) { - return root.resolve(classEntry.getFullName() + ".mapping"); - } - }, - ZIP { - @Override - public void write(EntryTree mappings, MappingDelta delta, Path zip, ProgressListener progress, MappingSaveParameters saveParameters) { - try (FileSystem fs = FileSystems.newFileSystem(new URI("jar:file", null, zip.toUri().getPath(), ""), Collections.singletonMap("create", "true"))) { - DIRECTORY.write(mappings, delta, fs.getPath("/"), progress, saveParameters); - } catch (IOException e) { - e.printStackTrace(); - } catch (URISyntaxException e) { - throw new RuntimeException("Unexpected error creating URI for " + zip, e); - } - } - }; - - protected void writeRoot(PrintWriter writer, EntryTree mappings, ClassEntry classEntry) { - Collection> children = groupChildren(mappings.getChildren(classEntry)); - - EntryMapping classEntryMapping = mappings.get(classEntry); - - writer.println(writeClass(classEntry, classEntryMapping).trim()); - if (classEntryMapping != null && classEntryMapping.getJavadoc() != null) { - writeDocs(writer, classEntryMapping, 0); - } - - for (Entry child : children) { - writeEntry(writer, mappings, child, 1); - } - - } - - private void writeDocs(PrintWriter writer, EntryMapping mapping, int depth) { - String jd = mapping.getJavadoc(); - if (jd != null) { - for (String line : jd.split("\\R")) { - writer.println(indent(EnigmaFormat.COMMENT + " " + MappingHelper.escape(line), depth + 1)); - } - } - } - - protected void writeEntry(PrintWriter writer, EntryTree mappings, Entry entry, int depth) { - EntryTreeNode node = mappings.findNode(entry); - if (node == null) { - return; - } - - EntryMapping mapping = node.getValue(); - - if (entry instanceof ClassEntry) { - String line = writeClass((ClassEntry) entry, mapping); - writer.println(indent(line, depth)); - } else if (entry instanceof MethodEntry) { - String line = writeMethod((MethodEntry) entry, mapping); - writer.println(indent(line, depth)); - } else if (entry instanceof FieldEntry) { - String line = writeField((FieldEntry) entry, mapping); - writer.println(indent(line, depth)); - } else if (entry instanceof LocalVariableEntry && mapping != null) { - String line = writeArgument((LocalVariableEntry) entry, mapping); - writer.println(indent(line, depth)); - } - if (mapping != null && mapping.getJavadoc() != null) { - writeDocs(writer, mapping, depth); - } - - Collection> children = groupChildren(node.getChildren()); - for (Entry child : children) { - writeEntry(writer, mappings, child, depth + 1); - } - } - - private Collection> groupChildren(Collection> children) { - Collection> result = new ArrayList<>(children.size()); - - children.stream().filter(e -> e instanceof FieldEntry) - .map(e -> (FieldEntry) e) - .sorted() - .forEach(result::add); - - children.stream().filter(e -> e instanceof MethodEntry) - .map(e -> (MethodEntry) e) - .sorted() - .forEach(result::add); - - children.stream().filter(e -> e instanceof LocalVariableEntry) - .map(e -> (LocalVariableEntry) e) - .sorted() - .forEach(result::add); - - children.stream().filter(e -> e instanceof ClassEntry) - .map(e -> (ClassEntry) e) - .sorted() - .forEach(result::add); - - return result; - } - - protected String writeClass(ClassEntry entry, EntryMapping mapping) { - StringBuilder builder = new StringBuilder(EnigmaFormat.CLASS +" "); - builder.append(entry.getName()).append(' '); - writeMapping(builder, mapping); - - return builder.toString(); - } - - protected String writeMethod(MethodEntry entry, EntryMapping mapping) { - StringBuilder builder = new StringBuilder(EnigmaFormat.METHOD + " "); - builder.append(entry.getName()).append(' '); - if (mapping != null && !mapping.getTargetName().equals(entry.getName())) { - writeMapping(builder, mapping); - } - - builder.append(entry.getDesc().toString()); - - return builder.toString(); - } - - protected String writeField(FieldEntry entry, EntryMapping mapping) { - StringBuilder builder = new StringBuilder(EnigmaFormat.FIELD + " "); - builder.append(entry.getName()).append(' '); - if (mapping != null && !mapping.getTargetName().equals(entry.getName())) { - writeMapping(builder, mapping); - } - - builder.append(entry.getDesc().toString()); - - return builder.toString(); - } - - protected String writeArgument(LocalVariableEntry entry, EntryMapping mapping) { - return EnigmaFormat.PARAMETER + " " + entry.getIndex() + ' ' + mapping.getTargetName(); - } - - private void writeMapping(StringBuilder builder, EntryMapping mapping) { - if (mapping != null) { - builder.append(mapping.getTargetName()).append(' '); - if (mapping.getAccessModifier() != AccessModifier.UNCHANGED) { - builder.append(mapping.getAccessModifier().getFormattedName()).append(' '); - } - } - } - - private String indent(String line, int depth) { - StringBuilder builder = new StringBuilder(); - for (int i = 0; i < depth; i++) { - builder.append("\t"); - } - builder.append(line.trim()); - return builder.toString(); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java deleted file mode 100644 index 6c8c3430..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingFormat.java +++ /dev/null @@ -1,59 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingDelta; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; - -import javax.annotation.Nullable; -import java.io.IOException; -import java.nio.file.Path; - -public enum MappingFormat { - ENIGMA_FILE(EnigmaMappingsWriter.FILE, EnigmaMappingsReader.FILE), - ENIGMA_DIRECTORY(EnigmaMappingsWriter.DIRECTORY, EnigmaMappingsReader.DIRECTORY), - ENIGMA_ZIP(EnigmaMappingsWriter.ZIP, EnigmaMappingsReader.ZIP), - TINY_V2(new TinyV2Writer("intermediary", "named"), new TinyV2Reader()), - TINY_FILE(TinyMappingsWriter.INSTANCE, TinyMappingsReader.INSTANCE), - SRG_FILE(SrgMappingsWriter.INSTANCE, null), - PROGUARD(null, ProguardMappingsReader.INSTANCE); - - - private final MappingsWriter writer; - private final MappingsReader reader; - - MappingFormat(MappingsWriter writer, MappingsReader reader) { - this.writer = writer; - this.reader = reader; - } - - public void write(EntryTree mappings, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) { - write(mappings, MappingDelta.added(mappings), path, progressListener, saveParameters); - } - - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) { - if (writer == null) { - throw new IllegalStateException(name() + " does not support writing"); - } - writer.write(mappings, delta, path, progressListener, saveParameters); - } - - public EntryTree read(Path path, ProgressListener progressListener, MappingSaveParameters saveParameters) throws IOException, MappingParseException { - if (reader == null) { - throw new IllegalStateException(name() + " does not support reading"); - } - return reader.read(path, progressListener, saveParameters); - } - - @Nullable - public MappingsWriter getWriter() { - return writer; - } - - @Nullable - public MappingsReader getReader() { - return reader; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java deleted file mode 100644 index 7c8f6cc6..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingHelper.java +++ /dev/null @@ -1,51 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -public final class MappingHelper { - private static final String TO_ESCAPE = "\\\n\r\0\t"; - private static final String ESCAPED = "\\nr0t"; - - public static String escape(String raw) { - StringBuilder builder = new StringBuilder(raw.length() + 1); - for (int i = 0; i < raw.length(); i++) { - final char c = raw.charAt(i); - final int r = TO_ESCAPE.indexOf(c); - if (r < 0) { - builder.append(c); - } else { - builder.append('\\').append(ESCAPED.charAt(r)); - } - } - return builder.toString(); - } - - public static String unescape(String str) { - int pos = str.indexOf('\\'); - if (pos < 0) return str; - - StringBuilder ret = new StringBuilder(str.length() - 1); - int start = 0; - - do { - ret.append(str, start, pos); - pos++; - int type; - - if (pos >= str.length()) { - throw new RuntimeException("incomplete escape sequence at the end"); - } else if ((type = ESCAPED.indexOf(str.charAt(pos))) < 0) { - throw new RuntimeException("invalid escape character: \\" + str.charAt(pos)); - } else { - ret.append(TO_ESCAPE.charAt(type)); - } - - start = pos + 1; - } while ((pos = str.indexOf('\\', start)) >= 0); - - ret.append(str, start, str.length()); - - return ret.toString(); - } - - private MappingHelper() { - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java deleted file mode 100644 index 4c60787d..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsReader.java +++ /dev/null @@ -1,14 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; - -import java.io.IOException; -import java.nio.file.Path; - -public interface MappingsReader { - EntryTree read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException; -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java deleted file mode 100644 index 88159867..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/MappingsWriter.java +++ /dev/null @@ -1,17 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingDelta; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; - -import java.nio.file.Path; - -public interface MappingsWriter { - void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters); - - default void write(EntryTree mappings, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { - write(mappings, MappingDelta.added(mappings), path, progress, saveParameters); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/ProguardMappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/ProguardMappingsReader.java deleted file mode 100644 index b5ede394..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/ProguardMappingsReader.java +++ /dev/null @@ -1,134 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.command.MappingCommandsUtil; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -public class ProguardMappingsReader implements MappingsReader { - public static final ProguardMappingsReader INSTANCE = new ProguardMappingsReader(); - private static final String NAME = "[a-zA-Z0-9_\\-.$<>]+"; - private static final String TYPE = NAME + "(?:\\[])*"; - private static final String TYPE_LIST = "|(?:(?:" + TYPE + ",)*" + TYPE + ")"; - private static final Pattern CLASS = Pattern.compile("(" + NAME + ") -> (" + NAME + "):"); - private static final Pattern FIELD = Pattern.compile(" {4}(" + TYPE + ") (" + NAME + ") -> (" + NAME + ")"); - private static final Pattern METHOD = Pattern.compile(" {4}(?:[0-9]+:[0-9]+:)?(" + TYPE + ") (" + NAME + ")\\((" + TYPE_LIST + ")\\) -> (" + NAME + ")"); - - public ProguardMappingsReader() {} - - @Override - public EntryTree read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws MappingParseException, IOException { - EntryTree mappings = new HashEntryTree<>(); - - int lineNumber = 0; - ClassEntry currentClass = null; - for (String line : Files.readAllLines(path, StandardCharsets.UTF_8)) { - lineNumber++; - - if (line.startsWith("#") || line.isEmpty()) { - continue; - } - - Matcher classMatcher = CLASS.matcher(line); - Matcher fieldMatcher = FIELD.matcher(line); - Matcher methodMatcher = METHOD.matcher(line); - - if (classMatcher.matches()) { - String name = classMatcher.group(1); - String targetName = classMatcher.group(2); - - mappings.insert(currentClass = new ClassEntry(name.replace('.', '/')), new EntryMapping(ClassEntry.getInnerName(targetName.replace('.', '/')))); - } else if (fieldMatcher.matches()) { - String type = fieldMatcher.group(1); - String name = fieldMatcher.group(2); - String targetName = fieldMatcher.group(3); - - if (currentClass == null) { - throw new MappingParseException(path::toString, lineNumber, "field mapping not inside class: " + line); - } - - mappings.insert(new FieldEntry(currentClass, name, new TypeDescriptor(getDescriptor(type))), new EntryMapping(targetName)); - } else if (methodMatcher.matches()) { - String returnType = methodMatcher.group(1); - String name = methodMatcher.group(2); - String[] parameterTypes = methodMatcher.group(3).isEmpty() ? new String[0] : methodMatcher.group(3).split(","); - String targetName = methodMatcher.group(4); - - if (currentClass == null) { - throw new MappingParseException(path::toString, lineNumber, "method mapping not inside class: " + line); - } - - mappings.insert(new MethodEntry(currentClass, name, new MethodDescriptor(getDescriptor(returnType, parameterTypes))), new EntryMapping(targetName)); - } else { - throw new MappingParseException(path::toString, lineNumber, "invalid mapping line: " + line); - } - } - - return MappingCommandsUtil.invert(mappings); - } - - private String getDescriptor(String type) { - StringBuilder descriptor = new StringBuilder(); - - while (type.endsWith("[]")) { - descriptor.append("["); - type = type.substring(0, type.length() - 2); - } - - switch (type) { - case "byte": - return descriptor + "B"; - case "char": - return descriptor + "C"; - case "short": - return descriptor + "S"; - case "int": - return descriptor + "I"; - case "long": - return descriptor + "J"; - case "float": - return descriptor + "F"; - case "double": - return descriptor + "D"; - case "boolean": - return descriptor + "Z"; - case "void": - return descriptor + "V"; - } - - descriptor.append("L"); - descriptor.append(type.replace('.', '/')); - descriptor.append(";"); - - return descriptor.toString(); - } - - private String getDescriptor(String returnType, String[] parameterTypes) { - StringBuilder descriptor = new StringBuilder(); - descriptor.append('('); - - for (String parameterType : parameterTypes) { - descriptor.append(getDescriptor(parameterType)); - } - - descriptor.append(')'); - descriptor.append(getDescriptor(returnType)); - - return descriptor.toString(); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java deleted file mode 100644 index afb40e9a..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/RawEntryMapping.java +++ /dev/null @@ -1,30 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import cuchaz.enigma.translation.mapping.AccessModifier; -import cuchaz.enigma.translation.mapping.EntryMapping; - -import java.util.ArrayList; -import java.util.List; - -final class RawEntryMapping { - private final String targetName; - private final AccessModifier access; - private List javadocs = new ArrayList<>(); - - RawEntryMapping(String targetName) { - this(targetName, null); - } - - RawEntryMapping(String targetName, AccessModifier access) { - this.access = access; - this.targetName = targetName; - } - - void addJavadocLine(String line) { - javadocs.add(line); - } - - EntryMapping bake() { - return new EntryMapping(targetName, access, javadocs.isEmpty() ? null : String.join("\n", javadocs)); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java deleted file mode 100644 index f67f8fcd..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/SrgMappingsWriter.java +++ /dev/null @@ -1,118 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import com.google.common.collect.Lists; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.translation.MappingTranslator; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingDelta; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.VoidEntryResolver; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.I18n; -import cuchaz.enigma.utils.LFPrintWriter; - -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Comparator; -import java.util.List; -import java.util.stream.Collectors; - -public enum SrgMappingsWriter implements MappingsWriter { - INSTANCE; - - @Override - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { - try { - Files.deleteIfExists(path); - Files.createFile(path); - } catch (IOException e) { - e.printStackTrace(); - } - - List classLines = new ArrayList<>(); - List fieldLines = new ArrayList<>(); - List methodLines = new ArrayList<>(); - - Collection> rootEntries = Lists.newArrayList(mappings).stream() - .map(EntryTreeNode::getEntry) - .collect(Collectors.toList()); - progress.init(rootEntries.size(), I18n.translate("progress.mappings.srg_file.generating")); - - int steps = 0; - for (Entry entry : sorted(rootEntries)) { - progress.step(steps++, entry.getName()); - writeEntry(classLines, fieldLines, methodLines, mappings, entry); - } - - progress.init(3, I18n.translate("progress.mappings.srg_file.writing")); - try (PrintWriter writer = new LFPrintWriter(Files.newBufferedWriter(path))) { - progress.step(0, I18n.translate("type.classes")); - classLines.forEach(writer::println); - progress.step(1, I18n.translate("type.fields")); - fieldLines.forEach(writer::println); - progress.step(2, I18n.translate("type.methods")); - methodLines.forEach(writer::println); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void writeEntry(List classes, List fields, List methods, EntryTree mappings, Entry entry) { - EntryTreeNode node = mappings.findNode(entry); - if (node == null) { - return; - } - - Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE); - if (entry instanceof ClassEntry) { - classes.add(generateClassLine((ClassEntry) entry, translator)); - } else if (entry instanceof FieldEntry) { - fields.add(generateFieldLine((FieldEntry) entry, translator)); - } else if (entry instanceof MethodEntry) { - methods.add(generateMethodLine((MethodEntry) entry, translator)); - } - - for (Entry child : sorted(node.getChildren())) { - writeEntry(classes, fields, methods, mappings, child); - } - } - - private String generateClassLine(ClassEntry sourceEntry, Translator translator) { - ClassEntry targetEntry = translator.translate(sourceEntry); - return "CL: " + sourceEntry.getFullName() + " " + targetEntry.getFullName(); - } - - private String generateMethodLine(MethodEntry sourceEntry, Translator translator) { - MethodEntry targetEntry = translator.translate(sourceEntry); - return "MD: " + describeMethod(sourceEntry) + " " + describeMethod(targetEntry); - } - - private String describeMethod(MethodEntry entry) { - return entry.getParent().getFullName() + "/" + entry.getName() + " " + entry.getDesc(); - } - - private String generateFieldLine(FieldEntry sourceEntry, Translator translator) { - FieldEntry targetEntry = translator.translate(sourceEntry); - return "FD: " + describeField(sourceEntry) + " " + describeField(targetEntry); - } - - private String describeField(FieldEntry entry) { - return entry.getParent().getFullName() + "/" + entry.getName(); - } - - private Collection> sorted(Iterable> iterable) { - ArrayList> sorted = Lists.newArrayList(iterable); - sorted.sort(Comparator.comparing(Entry::getName)); - return sorted; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java deleted file mode 100644 index 773c95eb..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsReader.java +++ /dev/null @@ -1,115 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import com.google.common.base.Charsets; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingPair; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.I18n; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; - -public enum TinyMappingsReader implements MappingsReader { - INSTANCE; - - @Override - public EntryTree read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { - return read(path, Files.readAllLines(path, Charsets.UTF_8), progress); - } - - private EntryTree read(Path path, List lines, ProgressListener progress) throws MappingParseException { - EntryTree mappings = new HashEntryTree<>(); - lines.remove(0); - - progress.init(lines.size(), I18n.translate("progress.mappings.tiny_file.loading")); - - for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { - progress.step(lineNumber, ""); - - String line = lines.get(lineNumber); - - if (line.trim().startsWith("#")) { - continue; - } - - try { - MappingPair mapping = parseLine(line); - mappings.insert(mapping.getEntry(), mapping.getMapping()); - } catch (Throwable t) { - t.printStackTrace(); - throw new MappingParseException(path::toString, lineNumber, t.toString()); - } - } - - return mappings; - } - - private MappingPair parseLine(String line) { - String[] tokens = line.split("\t"); - - String key = tokens[0]; - switch (key) { - case "CLASS": - return parseClass(tokens); - case "FIELD": - return parseField(tokens); - case "METHOD": - return parseMethod(tokens); - case "MTH-ARG": - return parseArgument(tokens); - default: - throw new RuntimeException("Unknown token '" + key + "'!"); - } - } - - private MappingPair parseClass(String[] tokens) { - ClassEntry obfuscatedEntry = new ClassEntry(tokens[1]); - String mapping = tokens[2]; - if (mapping.indexOf('$') > 0) { - // inner classes should map to only the final part - mapping = mapping.substring(mapping.lastIndexOf('$') + 1); - } - return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); - } - - private MappingPair parseField(String[] tokens) { - ClassEntry ownerClass = new ClassEntry(tokens[1]); - TypeDescriptor descriptor = new TypeDescriptor(tokens[2]); - - FieldEntry obfuscatedEntry = new FieldEntry(ownerClass, tokens[3], descriptor); - String mapping = tokens[4]; - return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); - } - - private MappingPair parseMethod(String[] tokens) { - ClassEntry ownerClass = new ClassEntry(tokens[1]); - MethodDescriptor descriptor = new MethodDescriptor(tokens[2]); - - MethodEntry obfuscatedEntry = new MethodEntry(ownerClass, tokens[3], descriptor); - String mapping = tokens[4]; - return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); - } - - private MappingPair parseArgument(String[] tokens) { - ClassEntry ownerClass = new ClassEntry(tokens[1]); - MethodDescriptor ownerDescriptor = new MethodDescriptor(tokens[2]); - MethodEntry ownerMethod = new MethodEntry(ownerClass, tokens[3], ownerDescriptor); - int variableIndex = Integer.parseInt(tokens[4]); - - String mapping = tokens[5]; - LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null); - return new MappingPair<>(obfuscatedEntry, new EntryMapping(mapping)); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsWriter.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsWriter.java deleted file mode 100644 index c82f2623..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyMappingsWriter.java +++ /dev/null @@ -1,148 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import com.google.common.base.Joiner; -import com.google.common.collect.Lists; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.translation.MappingTranslator; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingDelta; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.VoidEntryResolver; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; - -import java.io.BufferedWriter; -import java.io.IOException; -import java.io.Writer; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Comparator; -import java.util.HashSet; -import java.util.Set; - -public class TinyMappingsWriter implements MappingsWriter { - private static final String VERSION_CONSTANT = "v1"; - private static final Joiner TAB_JOINER = Joiner.on('\t'); - - //Possibly add a gui or a way to select the namespaces when exporting from the gui - public static final TinyMappingsWriter INSTANCE = new TinyMappingsWriter("intermediary", "named"); - - // HACK: as of enigma 0.13.1, some fields seem to appear duplicated? - private final Set writtenLines = new HashSet<>(); - private final String nameObf; - private final String nameDeobf; - - public TinyMappingsWriter(String nameObf, String nameDeobf) { - this.nameObf = nameObf; - this.nameDeobf = nameDeobf; - } - - @Override - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress, MappingSaveParameters saveParameters) { - try { - Files.deleteIfExists(path); - Files.createFile(path); - } catch (IOException e) { - e.printStackTrace(); - } - - try (BufferedWriter writer = Files.newBufferedWriter(path, StandardCharsets.UTF_8)) { - writeLine(writer, new String[]{VERSION_CONSTANT, nameObf, nameDeobf}); - - Lists.newArrayList(mappings).stream() - .map(EntryTreeNode::getEntry).sorted(Comparator.comparing(Object::toString)) - .forEach(entry -> writeEntry(writer, mappings, entry)); - } catch (IOException e) { - e.printStackTrace(); - } - } - - private void writeEntry(Writer writer, EntryTree mappings, Entry entry) { - EntryTreeNode node = mappings.findNode(entry); - if (node == null) { - return; - } - - Translator translator = new MappingTranslator(mappings, VoidEntryResolver.INSTANCE); - - EntryMapping mapping = mappings.get(entry); - if (mapping != null && !entry.getName().equals(mapping.getTargetName())) { - if (entry instanceof ClassEntry) { - writeClass(writer, (ClassEntry) entry, translator); - } else if (entry instanceof FieldEntry) { - writeLine(writer, serializeEntry(entry, mapping.getTargetName())); - } else if (entry instanceof MethodEntry) { - writeLine(writer, serializeEntry(entry, mapping.getTargetName())); - } - } - - writeChildren(writer, mappings, node); - } - - private void writeChildren(Writer writer, EntryTree mappings, EntryTreeNode node) { - node.getChildren().stream() - .filter(e -> e instanceof FieldEntry).sorted() - .forEach(child -> writeEntry(writer, mappings, child)); - - node.getChildren().stream() - .filter(e -> e instanceof MethodEntry).sorted() - .forEach(child -> writeEntry(writer, mappings, child)); - - node.getChildren().stream() - .filter(e -> e instanceof ClassEntry).sorted() - .forEach(child -> writeEntry(writer, mappings, child)); - } - - private void writeClass(Writer writer, ClassEntry entry, Translator translator) { - ClassEntry translatedEntry = translator.translate(entry); - - String obfClassName = entry.getFullName(); - String deobfClassName = translatedEntry.getFullName(); - writeLine(writer, new String[]{"CLASS", obfClassName, deobfClassName}); - } - - private void writeLine(Writer writer, String[] data) { - try { - String line = TAB_JOINER.join(data) + "\n"; - if (writtenLines.add(line)) { - writer.write(line); - } - } catch (IOException e) { - throw new RuntimeException(e); - } - } - - private String[] serializeEntry(Entry entry, String... extraFields) { - String[] data = null; - - if (entry instanceof FieldEntry) { - data = new String[4 + extraFields.length]; - data[0] = "FIELD"; - data[1] = entry.getContainingClass().getFullName(); - data[2] = ((FieldEntry) entry).getDesc().toString(); - data[3] = entry.getName(); - } else if (entry instanceof MethodEntry) { - data = new String[4 + extraFields.length]; - data[0] = "METHOD"; - data[1] = entry.getContainingClass().getFullName(); - data[2] = ((MethodEntry) entry).getDesc().toString(); - data[3] = entry.getName(); - } else if (entry instanceof ClassEntry) { - data = new String[2 + extraFields.length]; - data[0] = "CLASS"; - data[1] = ((ClassEntry) entry).getFullName(); - } - - if (data != null) { - System.arraycopy(extraFields, 0, data, data.length - extraFields.length, extraFields.length); - } - - return data; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java deleted file mode 100644 index d81cbdb9..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Reader.java +++ /dev/null @@ -1,295 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.throwables.MappingParseException; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingPair; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.HashEntryTree; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.I18n; - -import java.io.IOException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.BitSet; -import java.util.List; - -final class TinyV2Reader implements MappingsReader { - - private static final String MINOR_VERSION = "0"; - // 0 indent - private static final int IN_HEADER = 0; - private static final int IN_CLASS = IN_HEADER + 1; - // 1 indent - private static final int IN_METHOD = IN_CLASS + 1; - private static final int IN_FIELD = IN_METHOD + 1; - // 2 indent - private static final int IN_PARAMETER = IN_FIELD + 1; - // general properties - private static final int STATE_SIZE = IN_PARAMETER + 1; - private static final int[] INDENT_CLEAR_START = {IN_HEADER, IN_METHOD, IN_PARAMETER, STATE_SIZE}; - - @Override - public EntryTree read(Path path, ProgressListener progress, MappingSaveParameters saveParameters) throws IOException, MappingParseException { - return read(path, Files.readAllLines(path, StandardCharsets.UTF_8), progress); - } - - private EntryTree read(Path path, List lines, ProgressListener progress) throws MappingParseException { - EntryTree mappings = new HashEntryTree<>(); - - progress.init(lines.size(), I18n.translate("progress.mappings.tiny_v2.loading")); - - BitSet state = new BitSet(STATE_SIZE); - @SuppressWarnings({"unchecked", "rawtypes"}) - MappingPair, RawEntryMapping>[] holds = new MappingPair[STATE_SIZE]; - boolean escapeNames = false; - - for (int lineNumber = 0; lineNumber < lines.size(); lineNumber++) { - try { - progress.step(lineNumber, ""); - String line = lines.get(lineNumber); - - int indent = 0; - while (line.charAt(indent) == '\t') - indent++; - - String[] parts = line.substring(indent).split("\t", -1); - if (parts.length == 0 || indent >= INDENT_CLEAR_START.length) - throw new IllegalArgumentException("Invalid format"); - - // clean and register stuff in stack - for (int i = INDENT_CLEAR_START[indent]; i < STATE_SIZE; i++) { - state.clear(i); - if (holds[i] != null) { - RawEntryMapping mapping = holds[i].getMapping(); - if (mapping != null) { - EntryMapping baked = mapping.bake(); - if (baked != null) { - mappings.insert(holds[i].getEntry(), baked); - } - } - holds[i] = null; - } - } - - switch (indent) { - case 0: - switch (parts[0]) { - case "tiny": // header - if (lineNumber != 0) { - throw new IllegalArgumentException("Header can only be on the first line"); - } - if (parts.length < 5) { - throw new IllegalArgumentException("Not enough header columns, needs at least 5"); - } - if (!"2".equals(parts[1]) || !MINOR_VERSION.equals(parts[2])) { - throw new IllegalArgumentException("Unsupported TinyV2 version, requires major " + "2" + " and minor " + MINOR_VERSION + ""); - } - state.set(IN_HEADER); - break; - case "c": // class - state.set(IN_CLASS); - holds[IN_CLASS] = parseClass(parts, escapeNames); - break; - default: - unsupportKey(parts); - } - - break; - case 1: - if (state.get(IN_HEADER)) { - if (parts[0].equals("esacpe-names")) { - escapeNames = true; - } - - break; - } - - if (state.get(IN_CLASS)) { - switch (parts[0]) { - case "m": // method - state.set(IN_METHOD); - holds[IN_METHOD] = parseMethod(holds[IN_CLASS], parts, escapeNames); - break; - case "f": // field - state.set(IN_FIELD); - holds[IN_FIELD] = parseField(holds[IN_CLASS], parts, escapeNames); - break; - case "c": // class javadoc - addJavadoc(holds[IN_CLASS], parts); - break; - default: - unsupportKey(parts); - } - break; - } - - unsupportKey(parts); - case 2: - if (state.get(IN_METHOD)) { - switch (parts[0]) { - case "p": // parameter - state.set(IN_PARAMETER); - holds[IN_PARAMETER] = parseArgument(holds[IN_METHOD], parts, escapeNames); - break; - case "v": // local variable - // TODO add local var mapping - break; - case "c": // method javadoc - addJavadoc(holds[IN_METHOD], parts); - break; - default: - unsupportKey(parts); - } - break; - } - - if (state.get(IN_FIELD)) { - switch (parts[0]) { - case "c": // field javadoc - addJavadoc(holds[IN_FIELD], parts); - break; - default: - unsupportKey(parts); - } - break; - } - unsupportKey(parts); - case 3: - if (state.get(IN_PARAMETER)) { - switch (parts[0]) { - case "c": - addJavadoc(holds[IN_PARAMETER], parts); - break; - default: - unsupportKey(parts); - } - break; - } - unsupportKey(parts); - default: - unsupportKey(parts); - } - - } catch (Throwable t) { - t.printStackTrace(); - throw new MappingParseException(path::toString, lineNumber + 1, t.toString()); - } - } - - return mappings; - } - - private void unsupportKey(String[] parts) { - throw new IllegalArgumentException("Unsupported key " + parts[0]); - } - - private void addJavadoc(MappingPair pair, String[] parts) { - if (parts.length != 2) { - throw new IllegalArgumentException("Invalid javadoc declaration"); - } - - addJavadoc(pair, parts[1]); - } - - private MappingPair parseClass(String[] tokens, boolean escapeNames) { - ClassEntry obfuscatedEntry = new ClassEntry(unescapeOpt(tokens[1], escapeNames)); - if (tokens.length <= 2) - return new MappingPair<>(obfuscatedEntry); - String token2 = unescapeOpt(tokens[2], escapeNames); - String mapping = token2.substring(token2.lastIndexOf('$') + 1); - return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); - } - - private MappingPair parseField(MappingPair parent, String[] tokens, boolean escapeNames) { - ClassEntry ownerClass = (ClassEntry) parent.getEntry(); - TypeDescriptor descriptor = new TypeDescriptor(unescapeOpt(tokens[1], escapeNames)); - - FieldEntry obfuscatedEntry = new FieldEntry(ownerClass, unescapeOpt(tokens[2], escapeNames), descriptor); - if (tokens.length <= 3) - return new MappingPair<>(obfuscatedEntry); - String mapping = unescapeOpt(tokens[3], escapeNames); - return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); - } - - private MappingPair parseMethod(MappingPair parent, String[] tokens, boolean escapeNames) { - ClassEntry ownerClass = (ClassEntry) parent.getEntry(); - MethodDescriptor descriptor = new MethodDescriptor(unescapeOpt(tokens[1], escapeNames)); - - MethodEntry obfuscatedEntry = new MethodEntry(ownerClass, unescapeOpt(tokens[2], escapeNames), descriptor); - if (tokens.length <= 3) - return new MappingPair<>(obfuscatedEntry); - String mapping = unescapeOpt(tokens[3], escapeNames); - return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); - } - - - - private void addJavadoc(MappingPair pair, String javadoc) { - RawEntryMapping mapping = pair.getMapping(); - if (mapping == null) { - throw new IllegalArgumentException("Javadoc requires a mapping in enigma!"); - } - mapping.addJavadocLine(unescape(javadoc)); - } - - - - private MappingPair parseArgument(MappingPair parent, String[] tokens, boolean escapeNames) { - MethodEntry ownerMethod = (MethodEntry) parent.getEntry(); - int variableIndex = Integer.parseInt(tokens[1]); - - // tokens[2] is the useless obf name - - LocalVariableEntry obfuscatedEntry = new LocalVariableEntry(ownerMethod, variableIndex, "", true, null); - if (tokens.length <= 3) - return new MappingPair<>(obfuscatedEntry); - String mapping = unescapeOpt(tokens[3], escapeNames); - return new MappingPair<>(obfuscatedEntry, new RawEntryMapping(mapping)); - } - - private static final String TO_ESCAPE = "\\\n\r\0\t"; - private static final String ESCAPED = "\\nr0t"; - - private static String unescapeOpt(String raw, boolean escapedStrings) { - return escapedStrings ? unescape(raw) : raw; - } - - private static String unescape(String str) { - // copied from matcher, lazy! - int pos = str.indexOf('\\'); - if (pos < 0) return str; - - StringBuilder ret = new StringBuilder(str.length() - 1); - int start = 0; - - do { - ret.append(str, start, pos); - pos++; - int type; - - if (pos >= str.length()) { - throw new RuntimeException("incomplete escape sequence at the end"); - } else if ((type = ESCAPED.indexOf(str.charAt(pos))) < 0) { - throw new RuntimeException("invalid escape character: \\" + str.charAt(pos)); - } else { - ret.append(TO_ESCAPE.charAt(type)); - } - - start = pos + 1; - } while ((pos = str.indexOf('\\', start)) >= 0); - - ret.append(str, start, str.length()); - - return ret.toString(); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java b/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java deleted file mode 100644 index 95e04c34..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/serde/TinyV2Writer.java +++ /dev/null @@ -1,169 +0,0 @@ -package cuchaz.enigma.translation.mapping.serde; - -import com.google.common.base.Strings; -import cuchaz.enigma.ProgressListener; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.MappingDelta; -import cuchaz.enigma.translation.mapping.MappingSaveParameters; -import cuchaz.enigma.translation.mapping.tree.EntryTree; -import cuchaz.enigma.translation.mapping.tree.EntryTreeNode; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.Entry; -import cuchaz.enigma.translation.representation.entry.FieldEntry; -import cuchaz.enigma.translation.representation.entry.LocalVariableEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.utils.LFPrintWriter; - -import java.io.IOException; -import java.io.PrintWriter; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.Deque; -import java.util.LinkedList; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.StreamSupport; - -public final class TinyV2Writer implements MappingsWriter { - - private static final String MINOR_VERSION = "0"; - private final String obfHeader; - private final String deobfHeader; - - public TinyV2Writer(String obfHeader, String deobfHeader) { - this.obfHeader = obfHeader; - this.deobfHeader = deobfHeader; - } - - @Override - public void write(EntryTree mappings, MappingDelta delta, Path path, ProgressListener progress, MappingSaveParameters parameters) { - List> classes = StreamSupport.stream(mappings.spliterator(), false).filter(node -> node.getEntry() instanceof ClassEntry).collect(Collectors.toList()); - - try (PrintWriter writer = new LFPrintWriter(Files.newBufferedWriter(path))) { - writer.println("tiny\t2\t" + MINOR_VERSION + "\t" + obfHeader + "\t" + deobfHeader); - - // no escape names - - for (EntryTreeNode node : classes) { - writeClass(writer, node, mappings); - } - } catch (IOException ex) { - ex.printStackTrace(); // TODO add some better logging system - } - } - - private void writeClass(PrintWriter writer, EntryTreeNode node, EntryMap tree) { - writer.print("c\t"); - ClassEntry classEntry = (ClassEntry) node.getEntry(); - String fullName = classEntry.getFullName(); - writer.print(fullName); - Deque parts = new LinkedList<>(); - do { - EntryMapping mapping = tree.get(classEntry); - if (mapping != null) { - parts.addFirst(mapping.getTargetName()); - } else { - parts.addFirst(classEntry.getName()); - } - classEntry = classEntry.getOuterClass(); - } while (classEntry != null); - - String mappedName = String.join("$", parts); - - writer.print("\t"); - - writer.print(mappedName); // todo escaping when we have v2 fixed later - - writer.println(); - - writeComment(writer, node.getValue(), 1); - - for (EntryTreeNode child : node.getChildNodes()) { - Entry entry = child.getEntry(); - if (entry instanceof FieldEntry) { - writeField(writer, child); - } else if (entry instanceof MethodEntry) { - writeMethod(writer, child); - } - } - } - - private void writeMethod(PrintWriter writer, EntryTreeNode node) { - writer.print(indent(1)); - writer.print("m\t"); - writer.print(((MethodEntry) node.getEntry()).getDesc().toString()); - writer.print("\t"); - writer.print(node.getEntry().getName()); - writer.print("\t"); - EntryMapping mapping = node.getValue(); - if (mapping == null) { - writer.println(node.getEntry().getName()); // todo fix v2 name inference - } else { - writer.println(mapping.getTargetName()); - - writeComment(writer, mapping, 2); - } - - for (EntryTreeNode child : node.getChildNodes()) { - Entry entry = child.getEntry(); - if (entry instanceof LocalVariableEntry) { - writeParameter(writer, child); - } - // TODO write actual local variables - } - } - - private void writeField(PrintWriter writer, EntryTreeNode node) { - if (node.getValue() == null) - return; // Shortcut - - writer.print(indent(1)); - writer.print("f\t"); - writer.print(((FieldEntry) node.getEntry()).getDesc().toString()); - writer.print("\t"); - writer.print(node.getEntry().getName()); - writer.print("\t"); - EntryMapping mapping = node.getValue(); - if (mapping == null) { - writer.println(node.getEntry().getName()); // todo fix v2 name inference - } else { - writer.println(mapping.getTargetName()); - - writeComment(writer, mapping, 2); - } - } - - private void writeParameter(PrintWriter writer, EntryTreeNode node) { - if (node.getValue() == null) - return; // Shortcut - - writer.print(indent(2)); - writer.print("p\t"); - writer.print(((LocalVariableEntry) node.getEntry()).getIndex()); - writer.print("\t"); - writer.print(node.getEntry().getName()); - writer.print("\t"); - EntryMapping mapping = node.getValue(); - if (mapping == null) { - writer.println(); // todo ??? - } else { - writer.println(mapping.getTargetName()); - - writeComment(writer, mapping, 3); - } - } - - private void writeComment(PrintWriter writer, EntryMapping mapping, int indent) { - if (mapping != null && mapping.getJavadoc() != null) { - writer.print(indent(indent)); - writer.print("c\t"); - writer.print(MappingHelper.escape(mapping.getJavadoc())); - writer.println(); - } - } - - private String indent(int level) { - return Strings.repeat("\t", level); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java deleted file mode 100644 index 255fa5fb..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/DeltaTrackingTree.java +++ /dev/null @@ -1,110 +0,0 @@ -package cuchaz.enigma.translation.mapping.tree; - -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.MappingDelta; -import cuchaz.enigma.translation.representation.entry.Entry; - -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.Iterator; -import java.util.stream.Stream; - -public class DeltaTrackingTree implements EntryTree { - private final EntryTree delegate; - - private EntryTree deltaReference; - private EntryTree changes = new HashEntryTree<>(); - - public DeltaTrackingTree(EntryTree delegate) { - this.delegate = delegate; - this.deltaReference = new HashEntryTree<>(delegate); - } - - public DeltaTrackingTree() { - this(new HashEntryTree<>()); - } - - @Override - public void insert(Entry entry, T value) { - trackChange(entry); - delegate.insert(entry, value); - } - - @Nullable - @Override - public T remove(Entry entry) { - trackChange(entry); - return delegate.remove(entry); - } - - public void trackChange(Entry entry) { - changes.insert(entry, MappingDelta.PLACEHOLDER); - } - - @Nullable - @Override - public T get(Entry entry) { - return delegate.get(entry); - } - - @Override - public Collection> getChildren(Entry entry) { - return delegate.getChildren(entry); - } - - @Override - public Collection> getSiblings(Entry entry) { - return delegate.getSiblings(entry); - } - - @Nullable - @Override - public EntryTreeNode findNode(Entry entry) { - return delegate.findNode(entry); - } - - @Override - public Stream> getRootNodes() { - return delegate.getRootNodes(); - } - - @Override - public DeltaTrackingTree translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - DeltaTrackingTree translatedTree = new DeltaTrackingTree<>(delegate.translate(translator, resolver, mappings)); - translatedTree.changes = changes.translate(translator, resolver, mappings); - return translatedTree; - } - - @Override - public Stream> getAllEntries() { - return delegate.getAllEntries(); - } - - @Override - public boolean isEmpty() { - return delegate.isEmpty(); - } - - @Override - public Iterator> iterator() { - return delegate.iterator(); - } - - public MappingDelta takeDelta() { - MappingDelta delta = new MappingDelta<>(deltaReference, changes); - resetDelta(); - return delta; - } - - private void resetDelta() { - deltaReference = new HashEntryTree<>(delegate); - changes = new HashEntryTree<>(); - } - - public boolean isDirty() { - return !changes.isEmpty(); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java deleted file mode 100644 index daaefcc1..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTree.java +++ /dev/null @@ -1,26 +0,0 @@ -package cuchaz.enigma.translation.mapping.tree; - -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.representation.entry.Entry; - -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.stream.Stream; - -public interface EntryTree extends EntryMap, Iterable>, Translatable { - Collection> getChildren(Entry entry); - - Collection> getSiblings(Entry entry); - - @Nullable - EntryTreeNode findNode(Entry entry); - - Stream> getRootNodes(); - - @Override - EntryTree translate(Translator translator, EntryResolver resolver, EntryMap mappings); -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTreeNode.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTreeNode.java deleted file mode 100644 index affcd504..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/EntryTreeNode.java +++ /dev/null @@ -1,40 +0,0 @@ -package cuchaz.enigma.translation.mapping.tree; - -import cuchaz.enigma.translation.representation.entry.Entry; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.Collection; -import java.util.stream.Collectors; - -public interface EntryTreeNode { - @Nullable - T getValue(); - - Entry getEntry(); - - boolean isEmpty(); - - Collection> getChildren(); - - Collection> getChildNodes(); - - default Collection> getNodesRecursively() { - Collection> nodes = new ArrayList<>(); - nodes.add(this); - for (EntryTreeNode node : getChildNodes()) { - nodes.addAll(node.getNodesRecursively()); - } - return nodes; - } - - default Collection> getChildrenRecursively() { - return getNodesRecursively().stream() - .map(EntryTreeNode::getEntry) - .collect(Collectors.toList()); - } - - default boolean hasValue() { - return getValue() != null; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java deleted file mode 100644 index 570941cd..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/HashEntryTree.java +++ /dev/null @@ -1,188 +0,0 @@ -package cuchaz.enigma.translation.mapping.tree; - -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.representation.entry.Entry; - -import javax.annotation.Nullable; -import java.util.*; -import java.util.function.Function; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; - -public class HashEntryTree implements EntryTree { - private final Map, HashTreeNode> root = new HashMap<>(); - - public HashEntryTree() { - } - - public HashEntryTree(EntryTree tree) { - for (EntryTreeNode node : tree) { - insert(node.getEntry(), node.getValue()); - } - } - - @Override - public void insert(Entry entry, T value) { - List> path = computePath(entry, true); - path.get(path.size() - 1).putValue(value); - if (value == null) { - removeDeadAlong(path); - } - } - - @Override - @Nullable - public T remove(Entry entry) { - List> path = computePath(entry, false); - if (path.isEmpty()) { - return null; - } - - T value = path.get(path.size() - 1).removeValue(); - - removeDeadAlong(path); - - return value; - } - - @Override - @Nullable - public T get(Entry entry) { - HashTreeNode node = findNode(entry); - if (node == null) { - return null; - } - return node.getValue(); - } - - @Override - public boolean contains(Entry entry) { - return get(entry) != null; - } - - @Override - public Collection> getChildren(Entry entry) { - HashTreeNode leaf = findNode(entry); - if (leaf == null) { - return Collections.emptyList(); - } - return leaf.getChildren(); - } - - @Override - public Collection> getSiblings(Entry entry) { - Entry parent = entry.getParent(); - if (parent == null) { - return getSiblings(entry, root.keySet()); - } - return getSiblings(entry, getChildren(parent)); - } - - private Collection> getSiblings(Entry entry, Collection> generation) { - Set> siblings = new HashSet<>(generation); - siblings.remove(entry); - return siblings; - } - - @Override - @Nullable - public HashTreeNode findNode(Entry target) { - List> parentChain = target.getAncestry(); - if (parentChain.isEmpty()) { - return null; - } - - HashTreeNode node = root.get(parentChain.get(0)); - for (int i = 1; i < parentChain.size(); i++) { - if (node == null) { - return null; - } - node = node.getChild(parentChain.get(i)); - } - - return node; - } - - private List> computePath(Entry target, boolean make) { - List> ancestry = target.getAncestry(); - if (ancestry.isEmpty()) { - return Collections.emptyList(); - } - - List> path = new ArrayList<>(ancestry.size()); - - Entry rootEntry = ancestry.get(0); - HashTreeNode node = make ? root.computeIfAbsent(rootEntry, HashTreeNode::new) : root.get(rootEntry); - if (node == null) { - return Collections.emptyList(); - } - - path.add(node); - - for (int i = 1; i < ancestry.size(); i++) { - Entry ancestor = ancestry.get(i); - node = make ? node.computeChild(ancestor) : node.getChild(ancestor); - if (node == null) { - return Collections.emptyList(); - } - - path.add(node); - } - - return path; - } - - private void removeDeadAlong(List> path) { - for (int i = path.size() - 1; i >= 0; i--) { - HashTreeNode node = path.get(i); - if (node.isEmpty()) { - if (i > 0) { - HashTreeNode parentNode = path.get(i - 1); - parentNode.remove(node.getEntry()); - } else { - root.remove(node.getEntry()); - } - } else { - break; - } - } - } - - @Override - public Iterator> iterator() { - Collection> nodes = new ArrayList<>(); - for (EntryTreeNode node : root.values()) { - nodes.addAll(node.getNodesRecursively()); - } - return nodes.iterator(); - } - - @Override - public Stream> getAllEntries() { - return StreamSupport.stream(spliterator(), false) - .filter(EntryTreeNode::hasValue) - .map(EntryTreeNode::getEntry); - } - - @Override - public Stream> getRootNodes() { - return root.values().stream().map(Function.identity()); - } - - @Override - public boolean isEmpty() { - return root.isEmpty(); - } - - @Override - public HashEntryTree translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - HashEntryTree translatedTree = new HashEntryTree<>(); - for (EntryTreeNode node : this) { - translatedTree.insert(translator.translate(node.getEntry()), node.getValue()); - } - return translatedTree; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/mapping/tree/HashTreeNode.java b/src/main/java/cuchaz/enigma/translation/mapping/tree/HashTreeNode.java deleted file mode 100644 index 0a990bd5..00000000 --- a/src/main/java/cuchaz/enigma/translation/mapping/tree/HashTreeNode.java +++ /dev/null @@ -1,75 +0,0 @@ -package cuchaz.enigma.translation.mapping.tree; - -import cuchaz.enigma.translation.representation.entry.Entry; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -public class HashTreeNode implements EntryTreeNode, Iterable> { - private final Entry entry; - private final Map, HashTreeNode> children = new HashMap<>(); - private T value; - - HashTreeNode(Entry entry) { - this.entry = entry; - } - - void putValue(T value) { - this.value = value; - } - - T removeValue() { - T value = this.value; - this.value = null; - return value; - } - - @Nullable - HashTreeNode getChild(Entry entry) { - return children.get(entry); - } - - @Nonnull - HashTreeNode computeChild(Entry entry) { - return children.computeIfAbsent(entry, HashTreeNode::new); - } - - void remove(Entry entry) { - children.remove(entry); - } - - @Override - @Nullable - public T getValue() { - return value; - } - - @Override - public Entry getEntry() { - return entry; - } - - @Override - public boolean isEmpty() { - return children.isEmpty() && value == null; - } - - @Override - public Collection> getChildren() { - return children.keySet(); - } - - @Override - public Collection> getChildNodes() { - return children.values(); - } - - @Override - public Iterator> iterator() { - return children.values().iterator(); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java b/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java deleted file mode 100644 index b280eef2..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/AccessFlags.java +++ /dev/null @@ -1,116 +0,0 @@ -package cuchaz.enigma.translation.representation; - -import cuchaz.enigma.analysis.Access; -import org.objectweb.asm.Opcodes; - -import java.lang.reflect.Modifier; - -public class AccessFlags { - public static final AccessFlags PRIVATE = new AccessFlags(Opcodes.ACC_PRIVATE); - public static final AccessFlags PUBLIC = new AccessFlags(Opcodes.ACC_PUBLIC); - - private int flags; - - public AccessFlags(int flags) { - this.flags = flags; - } - - public boolean isPrivate() { - return Modifier.isPrivate(this.flags); - } - - public boolean isProtected() { - return Modifier.isProtected(this.flags); - } - - public boolean isPublic() { - return Modifier.isPublic(this.flags); - } - - public boolean isSynthetic() { - return (this.flags & Opcodes.ACC_SYNTHETIC) != 0; - } - - public boolean isStatic() { - return Modifier.isStatic(this.flags); - } - - public boolean isEnum() { - return (flags & Opcodes.ACC_ENUM) != 0; - } - - public boolean isBridge() { - return (flags & Opcodes.ACC_BRIDGE) != 0; - } - - public boolean isFinal() { - return (flags & Opcodes.ACC_FINAL) != 0; - } - - public boolean isInterface() { - return (flags & Opcodes.ACC_INTERFACE) != 0; - } - - public AccessFlags setPrivate() { - this.setVisibility(Opcodes.ACC_PRIVATE); - return this; - } - - public AccessFlags setProtected() { - this.setVisibility(Opcodes.ACC_PROTECTED); - return this; - } - - public AccessFlags setPublic() { - this.setVisibility(Opcodes.ACC_PUBLIC); - return this; - } - - public AccessFlags setBridge() { - flags |= Opcodes.ACC_BRIDGE; - return this; - } - - @Deprecated - public AccessFlags setBridged() { - return setBridge(); - } - - public void setVisibility(int visibility) { - this.resetVisibility(); - this.flags |= visibility; - } - - private void resetVisibility() { - this.flags &= ~(Opcodes.ACC_PRIVATE | Opcodes.ACC_PROTECTED | Opcodes.ACC_PUBLIC); - } - - public int getFlags() { - return this.flags; - } - - @Override - public boolean equals(Object obj) { - return obj instanceof AccessFlags && ((AccessFlags) obj).flags == flags; - } - - @Override - public int hashCode() { - return flags; - } - - @Override - public String toString() { - StringBuilder builder = new StringBuilder(Access.get(this).toString().toLowerCase()); - if (isStatic()) { - builder.append(" static"); - } - if (isSynthetic()) { - builder.append(" synthetic"); - } - if (isBridge()) { - builder.append(" bridge"); - } - return builder.toString(); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/Lambda.java b/src/main/java/cuchaz/enigma/translation/representation/Lambda.java deleted file mode 100644 index 63eb5630..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/Lambda.java +++ /dev/null @@ -1,105 +0,0 @@ -package cuchaz.enigma.translation.representation; - -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.translation.representation.entry.MethodEntry; -import cuchaz.enigma.translation.representation.entry.ParentedEntry; - -import java.util.Objects; - -public class Lambda implements Translatable { - private final String invokedName; - private final MethodDescriptor invokedType; - private final MethodDescriptor samMethodType; - private final ParentedEntry implMethod; - private final MethodDescriptor instantiatedMethodType; - - public Lambda(String invokedName, MethodDescriptor invokedType, MethodDescriptor samMethodType, ParentedEntry implMethod, MethodDescriptor instantiatedMethodType) { - this.invokedName = invokedName; - this.invokedType = invokedType; - this.samMethodType = samMethodType; - this.implMethod = implMethod; - this.instantiatedMethodType = instantiatedMethodType; - } - - @Override - public Lambda translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - MethodEntry samMethod = new MethodEntry(getInterface(), invokedName, samMethodType); - EntryMapping samMethodMapping = resolveMapping(resolver, mappings, samMethod); - - return new Lambda( - samMethodMapping != null ? samMethodMapping.getTargetName() : invokedName, - invokedType.translate(translator, resolver, mappings), - samMethodType.translate(translator, resolver, mappings), - implMethod.translate(translator, resolver, mappings), - instantiatedMethodType.translate(translator, resolver, mappings) - ); - } - - private EntryMapping resolveMapping(EntryResolver resolver, EntryMap mappings, MethodEntry methodEntry) { - for (MethodEntry entry : resolver.resolveEntry(methodEntry, ResolutionStrategy.RESOLVE_ROOT)) { - EntryMapping mapping = mappings.get(entry); - if (mapping != null) { - return mapping; - } - } - return null; - } - - public ClassEntry getInterface() { - return invokedType.getReturnDesc().getTypeEntry(); - } - - public String getInvokedName() { - return invokedName; - } - - public MethodDescriptor getInvokedType() { - return invokedType; - } - - public MethodDescriptor getSamMethodType() { - return samMethodType; - } - - public ParentedEntry getImplMethod() { - return implMethod; - } - - public MethodDescriptor getInstantiatedMethodType() { - return instantiatedMethodType; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Lambda lambda = (Lambda) o; - return Objects.equals(invokedName, lambda.invokedName) && - Objects.equals(invokedType, lambda.invokedType) && - Objects.equals(samMethodType, lambda.samMethodType) && - Objects.equals(implMethod, lambda.implMethod) && - Objects.equals(instantiatedMethodType, lambda.instantiatedMethodType); - } - - @Override - public int hashCode() { - return Objects.hash(invokedName, invokedType, samMethodType, implMethod, instantiatedMethodType); - } - - @Override - public String toString() { - return "Lambda{" + - "invokedName='" + invokedName + '\'' + - ", invokedType=" + invokedType + - ", samMethodType=" + samMethodType + - ", implMethod=" + implMethod + - ", instantiatedMethodType=" + instantiatedMethodType + - '}'; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/MethodDescriptor.java b/src/main/java/cuchaz/enigma/translation/representation/MethodDescriptor.java deleted file mode 100644 index 37a70148..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/MethodDescriptor.java +++ /dev/null @@ -1,132 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation; - -import com.google.common.collect.Lists; -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import cuchaz.enigma.utils.Utils; - -import java.util.ArrayList; -import java.util.List; -import java.util.function.Function; - -public class MethodDescriptor implements Translatable { - - private List argumentDescs; - private TypeDescriptor returnDesc; - - public MethodDescriptor(String desc) { - try { - this.argumentDescs = Lists.newArrayList(); - int i = 0; - while (i < desc.length()) { - char c = desc.charAt(i); - if (c == '(') { - assert (this.argumentDescs.isEmpty()); - assert (this.returnDesc == null); - i++; - } else if (c == ')') { - i++; - break; - } else { - String type = TypeDescriptor.parseFirst(desc.substring(i)); - this.argumentDescs.add(new TypeDescriptor(type)); - i += type.length(); - } - } - this.returnDesc = new TypeDescriptor(TypeDescriptor.parseFirst(desc.substring(i))); - } catch (Exception ex) { - throw new IllegalArgumentException("Unable to parse method descriptor: " + desc, ex); - } - } - - public MethodDescriptor(List argumentDescs, TypeDescriptor returnDesc) { - this.argumentDescs = argumentDescs; - this.returnDesc = returnDesc; - } - - public List getArgumentDescs() { - return this.argumentDescs; - } - - public TypeDescriptor getReturnDesc() { - return this.returnDesc; - } - - @Override - public String toString() { - StringBuilder buf = new StringBuilder(); - buf.append("("); - for (TypeDescriptor desc : this.argumentDescs) { - buf.append(desc); - } - buf.append(")"); - buf.append(this.returnDesc); - return buf.toString(); - } - - public Iterable types() { - List descs = Lists.newArrayList(); - descs.addAll(this.argumentDescs); - descs.add(this.returnDesc); - return descs; - } - - @Override - public boolean equals(Object other) { - return other instanceof MethodDescriptor && equals((MethodDescriptor) other); - } - - public boolean equals(MethodDescriptor other) { - return this.argumentDescs.equals(other.argumentDescs) && this.returnDesc.equals(other.returnDesc); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.argumentDescs.hashCode(), this.returnDesc.hashCode()); - } - - public boolean hasClass(ClassEntry classEntry) { - for (TypeDescriptor desc : types()) { - if (desc.containsType() && desc.getTypeEntry().equals(classEntry)) { - return true; - } - } - return false; - } - - public MethodDescriptor remap(Function remapper) { - List argumentDescs = new ArrayList<>(this.argumentDescs.size()); - for (TypeDescriptor desc : this.argumentDescs) { - argumentDescs.add(desc.remap(remapper)); - } - return new MethodDescriptor(argumentDescs, returnDesc.remap(remapper)); - } - - @Override - public MethodDescriptor translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - List translatedArguments = new ArrayList<>(argumentDescs.size()); - for (TypeDescriptor argument : argumentDescs) { - translatedArguments.add(translator.translate(argument)); - } - return new MethodDescriptor(translatedArguments, translator.translate(returnDesc)); - } - - public boolean canConflictWith(MethodDescriptor descriptor) { - return descriptor.argumentDescs.equals(argumentDescs); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/Signature.java b/src/main/java/cuchaz/enigma/translation/representation/Signature.java deleted file mode 100644 index 424088ab..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/Signature.java +++ /dev/null @@ -1,98 +0,0 @@ -package cuchaz.enigma.translation.representation; - -import cuchaz.enigma.bytecode.translators.TranslationSignatureVisitor; -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.representation.entry.ClassEntry; -import org.objectweb.asm.signature.SignatureReader; -import org.objectweb.asm.signature.SignatureVisitor; -import org.objectweb.asm.signature.SignatureWriter; - -import java.util.function.Function; -import java.util.regex.Pattern; - -public class Signature implements Translatable { - private static final Pattern OBJECT_PATTERN = Pattern.compile(".*:Ljava/lang/Object;:.*"); - - private final String signature; - private final boolean isType; - - private Signature(String signature, boolean isType) { - if (signature != null && OBJECT_PATTERN.matcher(signature).matches()) { - signature = signature.replaceAll(":Ljava/lang/Object;:", "::"); - } - - this.signature = signature; - this.isType = isType; - } - - public static Signature createTypedSignature(String signature) { - if (signature != null && !signature.isEmpty()) { - return new Signature(signature, true); - } - return new Signature(null, true); - } - - public static Signature createSignature(String signature) { - if (signature != null && !signature.isEmpty()) { - return new Signature(signature, false); - } - return new Signature(null, false); - } - - public String getSignature() { - return signature; - } - - public boolean isType() { - return isType; - } - - public Signature remap(Function remapper) { - if (signature == null) { - return this; - } - SignatureWriter writer = new SignatureWriter(); - SignatureVisitor visitor = new TranslationSignatureVisitor(remapper, writer); - if (isType) { - new SignatureReader(signature).acceptType(visitor); - } else { - new SignatureReader(signature).accept(visitor); - } - return new Signature(writer.toString(), isType); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof Signature) { - Signature other = (Signature) obj; - return (other.signature == null && signature == null || other.signature != null - && signature != null && other.signature.equals(signature)) - && other.isType == this.isType; - } - return false; - } - - @Override - public int hashCode() { - int hash = (isType ? 1 : 0) << 16; - if (signature != null) { - hash |= signature.hashCode(); - } - - return hash; - } - - @Override - public String toString() { - return signature; - } - - @Override - public Translatable translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - return remap(name -> translator.translate(new ClassEntry(name)).getFullName()); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java b/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java deleted file mode 100644 index f7ba849e..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/TypeDescriptor.java +++ /dev/null @@ -1,268 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation; - -import com.google.common.base.Preconditions; -import com.google.common.collect.Maps; -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.representation.entry.ClassEntry; - -import java.util.Map; -import java.util.function.Function; - -public class TypeDescriptor implements Translatable { - - protected final String desc; - - public TypeDescriptor(String desc) { - Preconditions.checkNotNull(desc, "Desc cannot be null"); - - // don't deal with generics - // this is just for raw jvm types - if (desc.charAt(0) == 'T' || desc.indexOf('<') >= 0 || desc.indexOf('>') >= 0) { - throw new IllegalArgumentException("don't use with generic types or templates: " + desc); - } - - this.desc = desc; - } - - public static String parseFirst(String in) { - - if (in == null || in.length() <= 0) { - throw new IllegalArgumentException("No desc to parse, input is empty!"); - } - - // read one desc from the input - - char c = in.charAt(0); - - // first check for void - if (c == 'V') { - return "V"; - } - - // then check for primitives - Primitive primitive = Primitive.get(c); - if (primitive != null) { - return in.substring(0, 1); - } - - // then check for classes - if (c == 'L') { - return readClass(in); - } - - // then check for templates - if (c == 'T') { - return readClass(in); - } - - // then check for arrays - int dim = countArrayDimension(in); - if (dim > 0) { - String arrayType = TypeDescriptor.parseFirst(in.substring(dim)); - return in.substring(0, dim + arrayType.length()); - } - - throw new IllegalArgumentException("don't know how to parse: " + in); - } - - private static int countArrayDimension(String in) { - int i = 0; - while (i < in.length() && in.charAt(i) == '[') - i++; - return i; - } - - private static String readClass(String in) { - // read all the characters in the buffer until we hit a ';' - // include the parameters too - StringBuilder buf = new StringBuilder(); - int depth = 0; - for (int i = 0; i < in.length(); i++) { - char c = in.charAt(i); - buf.append(c); - - if (c == '<') { - depth++; - } else if (c == '>') { - depth--; - } else if (depth == 0 && c == ';') { - return buf.toString(); - } - } - return null; - } - - public static TypeDescriptor of(String name) { - return new TypeDescriptor("L" + name + ";"); - } - - @Override - public String toString() { - return this.desc; - } - - public boolean isVoid() { - return this.desc.length() == 1 && this.desc.charAt(0) == 'V'; - } - - public boolean isPrimitive() { - return this.desc.length() == 1 && Primitive.get(this.desc.charAt(0)) != null; - } - - public Primitive getPrimitive() { - if (!isPrimitive()) { - throw new IllegalStateException("not a primitive"); - } - return Primitive.get(this.desc.charAt(0)); - } - - public boolean isType() { - return this.desc.charAt(0) == 'L' && this.desc.charAt(this.desc.length() - 1) == ';'; - } - - public ClassEntry getTypeEntry() { - if (isType()) { - String name = this.desc.substring(1, this.desc.length() - 1); - - int pos = name.indexOf('<'); - if (pos >= 0) { - // remove the parameters from the class name - name = name.substring(0, pos); - } - - return new ClassEntry(name); - - } else if (isArray() && getArrayType().isType()) { - return getArrayType().getTypeEntry(); - } else { - throw new IllegalStateException("desc doesn't have a class"); - } - } - - public boolean isArray() { - return this.desc.charAt(0) == '['; - } - - public int getArrayDimension() { - if (!isArray()) { - throw new IllegalStateException("not an array"); - } - return countArrayDimension(this.desc); - } - - public TypeDescriptor getArrayType() { - if (!isArray()) { - throw new IllegalStateException("not an array"); - } - return new TypeDescriptor(this.desc.substring(getArrayDimension())); - } - - public boolean containsType() { - return isType() || (isArray() && getArrayType().containsType()); - } - - @Override - public boolean equals(Object other) { - return other instanceof TypeDescriptor && equals((TypeDescriptor) other); - } - - public boolean equals(TypeDescriptor other) { - return this.desc.equals(other.desc); - } - - @Override - public int hashCode() { - return this.desc.hashCode(); - } - - public TypeDescriptor remap(Function remapper) { - String desc = this.desc; - if (isType() || (isArray() && containsType())) { - String replacedName = remapper.apply(this.getTypeEntry().getFullName()); - if (replacedName != null) { - if (this.isType()) { - desc = "L" + replacedName + ";"; - } else { - desc = getArrayPrefix(this.getArrayDimension()) + "L" + replacedName + ";"; - } - } - } - return new TypeDescriptor(desc); - } - - private static String getArrayPrefix(int dimension) { - StringBuilder buf = new StringBuilder(); - for (int i = 0; i < dimension; i++) { - buf.append("["); - } - return buf.toString(); - } - - public int getSize() { - switch (desc.charAt(0)) { - case 'J': - case 'D': - if (desc.length() == 1) { - return 2; - } else { - return 1; - } - default: - return 1; - } - } - - @Override - public Translatable translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - return remap(name -> translator.translate(new ClassEntry(name)).getFullName()); - } - - public enum Primitive { - BYTE('B'), - CHARACTER('C'), - SHORT('S'), - INTEGER('I'), - LONG('J'), - FLOAT('F'), - DOUBLE('D'), - BOOLEAN('Z'); - - private static final Map lookup; - - static { - lookup = Maps.newTreeMap(); - for (Primitive val : values()) { - lookup.put(val.getCode(), val); - } - } - - private char code; - - Primitive(char code) { - this.code = code; - } - - public static Primitive get(char code) { - return lookup.get(code); - } - - public char getCode() { - return this.code; - } - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java deleted file mode 100644 index 69307651..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassDefEntry.java +++ /dev/null @@ -1,93 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.Signature; - -import javax.annotation.Nullable; -import java.util.Arrays; - -public class ClassDefEntry extends ClassEntry implements DefEntry { - private final AccessFlags access; - private final Signature signature; - private final ClassEntry superClass; - private final ClassEntry[] interfaces; - - public ClassDefEntry(String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, ClassEntry[] interfaces) { - this(getOuterClass(className), getInnerName(className), signature, access, superClass, interfaces, null); - } - - public ClassDefEntry(ClassEntry parent, String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, ClassEntry[] interfaces) { - this(parent, className, signature, access, superClass, interfaces, null); - } - - public ClassDefEntry(ClassEntry parent, String className, Signature signature, AccessFlags access, @Nullable ClassEntry superClass, - ClassEntry[] interfaces, String javadocs) { - super(parent, className, javadocs); - Preconditions.checkNotNull(signature, "Class signature cannot be null"); - Preconditions.checkNotNull(access, "Class access cannot be null"); - - this.signature = signature; - this.access = access; - this.superClass = superClass; - this.interfaces = interfaces != null ? interfaces : new ClassEntry[0]; - } - - public static ClassDefEntry parse(int access, String name, String signature, String superName, String[] interfaces) { - ClassEntry superClass = superName != null ? new ClassEntry(superName) : null; - ClassEntry[] interfaceClasses = Arrays.stream(interfaces).map(ClassEntry::new).toArray(ClassEntry[]::new); - return new ClassDefEntry(name, Signature.createSignature(signature), new AccessFlags(access), superClass, interfaceClasses); - } - - public Signature getSignature() { - return signature; - } - - @Override - public AccessFlags getAccess() { - return access; - } - - @Nullable - public ClassEntry getSuperClass() { - return superClass; - } - - public ClassEntry[] getInterfaces() { - return interfaces; - } - - @Override - public ClassDefEntry translate(Translator translator, @Nullable EntryMapping mapping) { - Signature translatedSignature = translator.translate(signature); - String translatedName = mapping != null ? mapping.getTargetName() : name; - AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; - ClassEntry translatedSuper = translator.translate(superClass); - ClassEntry[] translatedInterfaces = Arrays.stream(interfaces).map(translator::translate).toArray(ClassEntry[]::new); - String docs = mapping != null ? mapping.getJavadoc() : null; - return new ClassDefEntry(parent, translatedName, translatedSignature, translatedAccess, translatedSuper, translatedInterfaces, docs); - } - - @Override - public ClassDefEntry withName(String name) { - return new ClassDefEntry(parent, name, signature, access, superClass, interfaces, javadocs); - } - - @Override - public ClassDefEntry withParent(ClassEntry parent) { - return new ClassDefEntry(parent, name, signature, access, superClass, interfaces, javadocs); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java deleted file mode 100644 index d6171f11..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/ClassEntry.java +++ /dev/null @@ -1,214 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation.entry; - -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.NameValidator; -import cuchaz.enigma.translation.representation.TypeDescriptor; - -import javax.annotation.Nonnull; -import javax.annotation.Nullable; -import java.util.List; -import java.util.Objects; - -public class ClassEntry extends ParentedEntry implements Comparable { - private final String fullName; - - public ClassEntry(String className) { - this(getOuterClass(className), getInnerName(className), null); - } - - public ClassEntry(@Nullable ClassEntry parent, String className) { - this(parent, className, null); - } - - public ClassEntry(@Nullable ClassEntry parent, String className, @Nullable String javadocs) { - super(parent, className, javadocs); - if (parent != null) { - fullName = parent.getFullName() + "$" + name; - } else { - fullName = name; - } - - if (parent == null && className.indexOf('.') >= 0) { - throw new IllegalArgumentException("Class name must be in JVM format. ie, path/to/package/class$inner : " + className); - } - } - - @Override - public Class getParentType() { - return ClassEntry.class; - } - - @Override - public String getName() { - return this.name; - } - - public String getFullName() { - return fullName; - } - - @Override - public ClassEntry translate(Translator translator, @Nullable EntryMapping mapping) { - if (name.charAt(0) == '[') { - String translatedName = translator.translate(new TypeDescriptor(name)).toString(); - return new ClassEntry(parent, translatedName); - } - - String translatedName = mapping != null ? mapping.getTargetName() : name; - String docs = mapping != null ? mapping.getJavadoc() : null; - return new ClassEntry(parent, translatedName, docs); - } - - @Override - public ClassEntry getContainingClass() { - return this; - } - - @Override - public int hashCode() { - return fullName.hashCode(); - } - - @Override - public boolean equals(Object other) { - return other instanceof ClassEntry && equals((ClassEntry) other); - } - - public boolean equals(ClassEntry other) { - return other != null && Objects.equals(parent, other.parent) && this.name.equals(other.name); - } - - @Override - public boolean canConflictWith(Entry entry) { - return true; - } - - @Override - public void validateName(String name) throws IllegalNameException { - NameValidator.validateClassName(name); - } - - @Override - public ClassEntry withName(String name) { - return new ClassEntry(parent, name, javadocs); - } - - @Override - public ClassEntry withParent(ClassEntry parent) { - return new ClassEntry(parent, name, javadocs); - } - - @Override - public String toString() { - return getFullName(); - } - - public String getPackageName() { - return getPackageName(fullName); - } - - public String getSimpleName() { - int packagePos = name.lastIndexOf('/'); - if (packagePos > 0) { - return name.substring(packagePos + 1); - } - return name; - } - - public boolean isInnerClass() { - return parent != null; - } - - @Nullable - public ClassEntry getOuterClass() { - return parent; - } - - @Nonnull - public ClassEntry getOutermostClass() { - if (parent == null) { - return this; - } - return parent.getOutermostClass(); - } - - public ClassEntry buildClassEntry(List classChain) { - assert (classChain.contains(this)); - StringBuilder buf = new StringBuilder(); - for (ClassEntry chainEntry : classChain) { - if (buf.length() == 0) { - buf.append(chainEntry.getFullName()); - } else { - buf.append("$"); - buf.append(chainEntry.getSimpleName()); - } - - if (chainEntry == this) { - break; - } - } - return new ClassEntry(buf.toString()); - } - - public boolean isJre() { - String packageName = getPackageName(); - return packageName != null && (packageName.startsWith("java") || packageName.startsWith("javax")); - } - - public static String getPackageName(String name) { - int pos = name.lastIndexOf('/'); - if (pos > 0) { - return name.substring(0, pos); - } - return null; - } - - @Nullable - public static ClassEntry getOuterClass(String name) { - int index = name.lastIndexOf('$'); - if (index >= 0) { - return new ClassEntry(name.substring(0, index)); - } - return null; - } - - public static String getInnerName(String name) { - int innerClassPos = name.lastIndexOf('$'); - if (innerClassPos > 0) { - return name.substring(innerClassPos + 1); - } - return name; - } - - @Override - public String getSourceRemapName() { - ClassEntry outerClass = getOuterClass(); - if (outerClass != null) { - return outerClass.getSourceRemapName() + "." + name; - } - return getSimpleName(); - } - - @Override - public int compareTo(ClassEntry entry) { - String fullName = getFullName(); - String otherFullName = entry.getFullName(); - if (fullName.length() != otherFullName.length()) { - return fullName.length() - otherFullName.length(); - } - return fullName.compareTo(otherFullName); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/DefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/DefEntry.java deleted file mode 100644 index 82536c73..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/DefEntry.java +++ /dev/null @@ -1,7 +0,0 @@ -package cuchaz.enigma.translation.representation.entry; - -import cuchaz.enigma.translation.representation.AccessFlags; - -public interface DefEntry

> extends Entry

{ - AccessFlags getAccess(); -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java deleted file mode 100644 index 72b03913..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/Entry.java +++ /dev/null @@ -1,107 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation.entry; - -import cuchaz.enigma.throwables.IllegalNameException; -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.mapping.NameValidator; - -import javax.annotation.Nullable; -import java.util.ArrayList; -import java.util.List; - -public interface Entry

> extends Translatable { - String getName(); - - String getJavadocs(); - - default String getSourceRemapName() { - return getName(); - } - - @Nullable - P getParent(); - - Class

getParentType(); - - Entry

withName(String name); - - Entry

withParent(P parent); - - boolean canConflictWith(Entry entry); - - @Nullable - default ClassEntry getContainingClass() { - P parent = getParent(); - if (parent == null) { - return null; - } - if (parent instanceof ClassEntry) { - return (ClassEntry) parent; - } - return parent.getContainingClass(); - } - - default List> getAncestry() { - P parent = getParent(); - List> entries = new ArrayList<>(); - if (parent != null) { - entries.addAll(parent.getAncestry()); - } - entries.add(this); - return entries; - } - - @Nullable - @SuppressWarnings("unchecked") - default > E findAncestor(Class type) { - List> ancestry = getAncestry(); - for (int i = ancestry.size() - 1; i >= 0; i--) { - Entry ancestor = ancestry.get(i); - if (type.isAssignableFrom(ancestor.getClass())) { - return (E) ancestor; - } - } - return null; - } - - @SuppressWarnings("unchecked") - default > Entry

replaceAncestor(E target, E replacement) { - if (replacement.equals(target)) { - return this; - } - - if (equals(target)) { - return (Entry

) replacement; - } - - P parent = getParent(); - if (parent == null) { - return this; - } - - return withParent((P) parent.replaceAncestor(target, replacement)); - } - - default void validateName(String name) throws IllegalNameException { - NameValidator.validateIdentifier(name); - } - - @SuppressWarnings("unchecked") - @Nullable - default > Entry castParent(Class parentType) { - if (parentType.equals(getParentType())) { - return (Entry) this; - } - return null; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java deleted file mode 100644 index f9282b28..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldDefEntry.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.Signature; -import cuchaz.enigma.translation.representation.TypeDescriptor; - -import javax.annotation.Nullable; - -public class FieldDefEntry extends FieldEntry implements DefEntry { - private final AccessFlags access; - private final Signature signature; - - public FieldDefEntry(ClassEntry owner, String name, TypeDescriptor desc, Signature signature, AccessFlags access) { - this(owner, name, desc, signature, access, null); - } - - public FieldDefEntry(ClassEntry owner, String name, TypeDescriptor desc, Signature signature, AccessFlags access, String javadocs) { - super(owner, name, desc, javadocs); - Preconditions.checkNotNull(access, "Field access cannot be null"); - Preconditions.checkNotNull(signature, "Field signature cannot be null"); - this.access = access; - this.signature = signature; - } - - public static FieldDefEntry parse(ClassEntry owner, int access, String name, String desc, String signature) { - return new FieldDefEntry(owner, name, new TypeDescriptor(desc), Signature.createTypedSignature(signature), new AccessFlags(access), null); - } - - @Override - public AccessFlags getAccess() { - return access; - } - - public Signature getSignature() { - return signature; - } - - @Override - public FieldDefEntry translate(Translator translator, @Nullable EntryMapping mapping) { - TypeDescriptor translatedDesc = translator.translate(desc); - Signature translatedSignature = translator.translate(signature); - String translatedName = mapping != null ? mapping.getTargetName() : name; - AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; - String docs = mapping != null ? mapping.getJavadoc() : null; - return new FieldDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess, docs); - } - - @Override - public FieldDefEntry withName(String name) { - return new FieldDefEntry(parent, name, desc, signature, access, javadocs); - } - - @Override - public FieldDefEntry withParent(ClassEntry owner) { - return new FieldDefEntry(owner, this.name, this.desc, signature, access, javadocs); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java deleted file mode 100644 index bef0edf4..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/FieldEntry.java +++ /dev/null @@ -1,96 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.TypeDescriptor; -import cuchaz.enigma.utils.Utils; - -import javax.annotation.Nullable; - -public class FieldEntry extends ParentedEntry implements Comparable { - protected final TypeDescriptor desc; - - public FieldEntry(ClassEntry parent, String name, TypeDescriptor desc) { - this(parent, name, desc, null); - } - - public FieldEntry(ClassEntry parent, String name, TypeDescriptor desc, String javadocs) { - super(parent, name, javadocs); - - Preconditions.checkNotNull(parent, "Owner cannot be null"); - Preconditions.checkNotNull(desc, "Field descriptor cannot be null"); - - this.desc = desc; - } - - public static FieldEntry parse(String owner, String name, String desc) { - return new FieldEntry(new ClassEntry(owner), name, new TypeDescriptor(desc), null); - } - - @Override - public Class getParentType() { - return ClassEntry.class; - } - - public TypeDescriptor getDesc() { - return this.desc; - } - - @Override - public FieldEntry withName(String name) { - return new FieldEntry(parent, name, desc, null); - } - - @Override - public FieldEntry withParent(ClassEntry parent) { - return new FieldEntry(parent, this.name, this.desc, null); - } - - @Override - protected FieldEntry translate(Translator translator, @Nullable EntryMapping mapping) { - String translatedName = mapping != null ? mapping.getTargetName() : name; - String docs = mapping != null ? mapping.getJavadoc() : null; - return new FieldEntry(parent, translatedName, translator.translate(desc), docs); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.parent, this.name, this.desc); - } - - @Override - public boolean equals(Object other) { - return other instanceof FieldEntry && equals((FieldEntry) other); - } - - public boolean equals(FieldEntry other) { - return this.parent.equals(other.parent) && name.equals(other.name) && desc.equals(other.desc); - } - - @Override - public boolean canConflictWith(Entry entry) { - return entry instanceof FieldEntry && ((FieldEntry) entry).parent.equals(parent); - } - - @Override - public String toString() { - return this.parent.getFullName() + "." + this.name + ":" + this.desc; - } - - @Override - public int compareTo(FieldEntry entry) { - return (name + desc.toString()).compareTo(entry.name + entry.desc.toString()); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java deleted file mode 100644 index aad4236d..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableDefEntry.java +++ /dev/null @@ -1,51 +0,0 @@ -package cuchaz.enigma.translation.representation.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.TypeDescriptor; - -import javax.annotation.Nullable; - -/** - * TypeDescriptor... - * Created by Thog - * 19/10/2016 - */ -public class LocalVariableDefEntry extends LocalVariableEntry { - protected final TypeDescriptor desc; - - public LocalVariableDefEntry(MethodEntry ownerEntry, int index, String name, boolean parameter, TypeDescriptor desc, String javadoc) { - super(ownerEntry, index, name, parameter, javadoc); - Preconditions.checkNotNull(desc, "Variable desc cannot be null"); - - this.desc = desc; - } - - public TypeDescriptor getDesc() { - return desc; - } - - @Override - public LocalVariableDefEntry translate(Translator translator, @Nullable EntryMapping mapping) { - TypeDescriptor translatedDesc = translator.translate(desc); - String translatedName = mapping != null ? mapping.getTargetName() : name; - String javadoc = mapping != null ? mapping.getJavadoc() : javadocs; - return new LocalVariableDefEntry(parent, index, translatedName, parameter, translatedDesc, javadoc); - } - - @Override - public LocalVariableDefEntry withName(String name) { - return new LocalVariableDefEntry(parent, index, name, parameter, desc, javadocs); - } - - @Override - public LocalVariableDefEntry withParent(MethodEntry entry) { - return new LocalVariableDefEntry(entry, index, name, parameter, desc, javadocs); - } - - @Override - public String toString() { - return this.parent + "(" + this.index + ":" + this.name + ":" + this.desc + ")"; - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java deleted file mode 100644 index 3ccb1fa1..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/LocalVariableEntry.java +++ /dev/null @@ -1,93 +0,0 @@ -package cuchaz.enigma.translation.representation.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.utils.Utils; - -import javax.annotation.Nullable; - -/** - * TypeDescriptor... - * Created by Thog - * 19/10/2016 - */ -public class LocalVariableEntry extends ParentedEntry implements Comparable { - - protected final int index; - protected final boolean parameter; - - public LocalVariableEntry(MethodEntry parent, int index, String name, boolean parameter, String javadoc) { - super(parent, name, javadoc); - - Preconditions.checkNotNull(parent, "Variable owner cannot be null"); - Preconditions.checkArgument(index >= 0, "Index must be positive"); - - this.index = index; - this.parameter = parameter; - } - - @Override - public Class getParentType() { - return MethodEntry.class; - } - - public boolean isArgument() { - return this.parameter; - } - - public int getIndex() { - return index; - } - - @Override - public String getName() { - return this.name; - } - - @Override - public LocalVariableEntry translate(Translator translator, @Nullable EntryMapping mapping) { - String translatedName = mapping != null ? mapping.getTargetName() : name; - String javadoc = mapping != null ? mapping.getJavadoc() : null; - return new LocalVariableEntry(parent, index, translatedName, parameter, javadoc); - } - - @Override - public LocalVariableEntry withName(String name) { - return new LocalVariableEntry(parent, index, name, parameter, javadocs); - } - - @Override - public LocalVariableEntry withParent(MethodEntry parent) { - return new LocalVariableEntry(parent, index, name, parameter, javadocs); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.parent, this.index); - } - - @Override - public boolean equals(Object other) { - return other instanceof LocalVariableEntry && equals((LocalVariableEntry) other); - } - - public boolean equals(LocalVariableEntry other) { - return this.parent.equals(other.parent) && this.index == other.index; - } - - @Override - public boolean canConflictWith(Entry entry) { - return entry instanceof LocalVariableEntry && ((LocalVariableEntry) entry).parent.equals(parent); - } - - @Override - public String toString() { - return this.parent + "(" + this.index + ":" + this.name + ")"; - } - - @Override - public int compareTo(LocalVariableEntry entry) { - return Integer.compare(index, entry.index); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java deleted file mode 100644 index 4e75a5c8..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodDefEntry.java +++ /dev/null @@ -1,71 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.AccessFlags; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.translation.representation.Signature; - -import javax.annotation.Nullable; - -public class MethodDefEntry extends MethodEntry implements DefEntry { - private final AccessFlags access; - private final Signature signature; - - public MethodDefEntry(ClassEntry owner, String name, MethodDescriptor descriptor, Signature signature, AccessFlags access) { - this(owner, name, descriptor, signature, access, null); - } - - public MethodDefEntry(ClassEntry owner, String name, MethodDescriptor descriptor, Signature signature, AccessFlags access, String docs) { - super(owner, name, descriptor, docs); - Preconditions.checkNotNull(access, "Method access cannot be null"); - Preconditions.checkNotNull(signature, "Method signature cannot be null"); - this.access = access; - this.signature = signature; - } - - public static MethodDefEntry parse(ClassEntry owner, int access, String name, String desc, String signature) { - return new MethodDefEntry(owner, name, new MethodDescriptor(desc), Signature.createSignature(signature), new AccessFlags(access), null); - } - - @Override - public AccessFlags getAccess() { - return access; - } - - public Signature getSignature() { - return signature; - } - - @Override - public MethodDefEntry translate(Translator translator, @Nullable EntryMapping mapping) { - MethodDescriptor translatedDesc = translator.translate(descriptor); - Signature translatedSignature = translator.translate(signature); - String translatedName = mapping != null ? mapping.getTargetName() : name; - AccessFlags translatedAccess = mapping != null ? mapping.getAccessModifier().transform(access) : access; - String docs = mapping != null ? mapping.getJavadoc() : null; - return new MethodDefEntry(parent, translatedName, translatedDesc, translatedSignature, translatedAccess, docs); - } - - @Override - public MethodDefEntry withName(String name) { - return new MethodDefEntry(parent, name, descriptor, signature, access, javadocs); - } - - @Override - public MethodDefEntry withParent(ClassEntry parent) { - return new MethodDefEntry(new ClassEntry(parent.getFullName()), name, descriptor, signature, access, javadocs); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java deleted file mode 100644 index e1ffad37..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/MethodEntry.java +++ /dev/null @@ -1,105 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.representation.MethodDescriptor; -import cuchaz.enigma.utils.Utils; - -import javax.annotation.Nullable; - -public class MethodEntry extends ParentedEntry implements Comparable { - - protected final MethodDescriptor descriptor; - - public MethodEntry(ClassEntry parent, String name, MethodDescriptor descriptor) { - this(parent, name, descriptor, null); - } - - public MethodEntry(ClassEntry parent, String name, MethodDescriptor descriptor, String javadocs) { - super(parent, name, javadocs); - - Preconditions.checkNotNull(parent, "Parent cannot be null"); - Preconditions.checkNotNull(descriptor, "Method descriptor cannot be null"); - - this.descriptor = descriptor; - } - - public static MethodEntry parse(String owner, String name, String desc) { - return new MethodEntry(new ClassEntry(owner), name, new MethodDescriptor(desc), null); - } - - @Override - public Class getParentType() { - return ClassEntry.class; - } - - public MethodDescriptor getDesc() { - return this.descriptor; - } - - public boolean isConstructor() { - return name.equals("") || name.equals(""); - } - - @Override - public MethodEntry translate(Translator translator, @Nullable EntryMapping mapping) { - String translatedName = mapping != null ? mapping.getTargetName() : name; - String docs = mapping != null ? mapping.getJavadoc() : null; - return new MethodEntry(parent, translatedName, translator.translate(descriptor), docs); - } - - @Override - public MethodEntry withName(String name) { - return new MethodEntry(parent, name, descriptor, javadocs); - } - - @Override - public MethodEntry withParent(ClassEntry parent) { - return new MethodEntry(new ClassEntry(parent.getFullName()), name, descriptor, javadocs); - } - - @Override - public int hashCode() { - return Utils.combineHashesOrdered(this.parent, this.name, this.descriptor); - } - - @Override - public boolean equals(Object other) { - return other instanceof MethodEntry && equals((MethodEntry) other); - } - - public boolean equals(MethodEntry other) { - return this.parent.equals(other.getParent()) && this.name.equals(other.getName()) && this.descriptor.equals(other.getDesc()); - } - - @Override - public boolean canConflictWith(Entry entry) { - if (entry instanceof MethodEntry) { - MethodEntry methodEntry = (MethodEntry) entry; - return methodEntry.parent.equals(parent) && methodEntry.descriptor.canConflictWith(descriptor); - } - return false; - } - - @Override - public String toString() { - return this.parent.getFullName() + "." + this.name + this.descriptor; - } - - @Override - public int compareTo(MethodEntry entry) { - return (name + descriptor.toString()).compareTo(entry.name + entry.descriptor.toString()); - } -} diff --git a/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java b/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java deleted file mode 100644 index cbc5faf5..00000000 --- a/src/main/java/cuchaz/enigma/translation/representation/entry/ParentedEntry.java +++ /dev/null @@ -1,82 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.translation.representation.entry; - -import com.google.common.base.Preconditions; -import cuchaz.enigma.translation.Translatable; -import cuchaz.enigma.translation.Translator; -import cuchaz.enigma.translation.mapping.EntryMap; -import cuchaz.enigma.translation.mapping.EntryMapping; -import cuchaz.enigma.translation.mapping.EntryResolver; -import cuchaz.enigma.translation.mapping.ResolutionStrategy; - -import javax.annotation.Nullable; - -public abstract class ParentedEntry

> implements Entry

{ - protected final P parent; - protected final String name; - protected final @Nullable String javadocs; - - protected ParentedEntry(P parent, String name, String javadocs) { - this.parent = parent; - this.name = name; - this.javadocs = javadocs; - - Preconditions.checkNotNull(name, "Name cannot be null"); - } - - @Override - public abstract ParentedEntry

withParent(P parent); - - @Override - public abstract ParentedEntry

withName(String name); - - protected abstract ParentedEntry

translate(Translator translator, @Nullable EntryMapping mapping); - - @Override - public String getName() { - return name; - } - - @Override - @Nullable - public P getParent() { - return parent; - } - - @Nullable - @Override - public String getJavadocs() { - return javadocs; - } - - @Override - public ParentedEntry

translate(Translator translator, EntryResolver resolver, EntryMap mappings) { - P parent = getParent(); - EntryMapping mapping = resolveMapping(resolver, mappings); - if (parent == null) { - return translate(translator, mapping); - } - P translatedParent = translator.translate(parent); - return withParent(translatedParent).translate(translator, mapping); - } - - private EntryMapping resolveMapping(EntryResolver resolver, EntryMap mappings) { - for (ParentedEntry

entry : resolver.resolveEntry(this, ResolutionStrategy.RESOLVE_ROOT)) { - EntryMapping mapping = mappings.get(entry); - if (mapping != null) { - return mapping; - } - } - return null; - } -} diff --git a/src/main/java/cuchaz/enigma/utils/I18n.java b/src/main/java/cuchaz/enigma/utils/I18n.java deleted file mode 100644 index f91c916a..00000000 --- a/src/main/java/cuchaz/enigma/utils/I18n.java +++ /dev/null @@ -1,102 +0,0 @@ -package cuchaz.enigma.utils; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.charset.StandardCharsets; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Map; -import java.util.stream.Stream; - -import com.google.common.collect.ImmutableList; -import com.google.common.collect.Maps; -import com.google.common.reflect.ClassPath; -import com.google.common.reflect.ClassPath.ResourceInfo; -import com.google.gson.Gson; - -import cuchaz.enigma.config.Config; - -public class I18n { - public static final String DEFAULT_LANGUAGE = "en_us"; - private static final Gson GSON = new Gson(); - private static Map translations = Maps.newHashMap(); - private static Map defaultTranslations = Maps.newHashMap(); - private static Map languageNames = Maps.newHashMap(); - - static { - translations = load(Config.getInstance().language); - defaultTranslations = load(DEFAULT_LANGUAGE); - } - - @SuppressWarnings("unchecked") - public static Map load(String language) { - try (InputStream inputStream = I18n.class.getResourceAsStream("/lang/" + language + ".json")) { - if (inputStream != null) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream, StandardCharsets.UTF_8))) { - return GSON.fromJson(reader, Map.class); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - return Collections.emptyMap(); - } - - public static String translate(String key) { - String value = translations.get(key); - if (value != null) { - return value; - } - value = defaultTranslations.get(key); - if (value != null) { - return value; - } - return key; - } - - public static String getLanguageName(String language) { - return languageNames.get(language); - } - - public static void setLanguage(String language) { - Config.getInstance().language = language; - try { - Config.getInstance().saveConfig(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - public static ArrayList getAvailableLanguages() { - ArrayList list = new ArrayList(); - - try { - ImmutableList resources = ClassPath.from(Thread.currentThread().getContextClassLoader()).getResources().asList(); - Stream dirStream = resources.stream(); - dirStream.forEach(context -> { - String file = context.getResourceName(); - if (file.startsWith("lang/") && file.endsWith(".json")) { - String fileName = file.substring(5, file.length() - 5); - list.add(fileName); - loadLanguageName(fileName); - } - }); - } catch (IOException e) { - e.printStackTrace(); - } - return list; - } - - private static void loadLanguageName(String fileName) { - try (InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("lang/" + fileName + ".json")) { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream, StandardCharsets.UTF_8))) { - Map map = GSON.fromJson(reader, Map.class); - languageNames.put(fileName, map.get("language").toString()); - } - } catch (IOException e) { - e.printStackTrace(); - } - } -} diff --git a/src/main/java/cuchaz/enigma/utils/LFPrintWriter.java b/src/main/java/cuchaz/enigma/utils/LFPrintWriter.java deleted file mode 100644 index c12e9134..00000000 --- a/src/main/java/cuchaz/enigma/utils/LFPrintWriter.java +++ /dev/null @@ -1,16 +0,0 @@ -package cuchaz.enigma.utils; - -import java.io.PrintWriter; -import java.io.Writer; - -public class LFPrintWriter extends PrintWriter { - public LFPrintWriter(Writer out) { - super(out); - } - - @Override - public void println() { - // https://stackoverflow.com/a/14749004 - write('\n'); - } -} diff --git a/src/main/java/cuchaz/enigma/utils/Message.java b/src/main/java/cuchaz/enigma/utils/Message.java deleted file mode 100644 index d7c5f23e..00000000 --- a/src/main/java/cuchaz/enigma/utils/Message.java +++ /dev/null @@ -1,392 +0,0 @@ -package cuchaz.enigma.utils; - -import java.io.DataInput; -import java.io.DataOutput; -import java.io.IOException; -import java.util.Objects; - -import cuchaz.enigma.network.packet.PacketHelper; -import cuchaz.enigma.translation.representation.entry.Entry; - -public abstract class Message { - - public final String user; - - public static Chat chat(String user, String message) { - return new Chat(user, message); - } - - public static Connect connect(String user) { - return new Connect(user); - } - - public static Disconnect disconnect(String user) { - return new Disconnect(user); - } - - public static EditDocs editDocs(String user, Entry entry) { - return new EditDocs(user, entry); - } - - public static MarkDeobf markDeobf(String user, Entry entry) { - return new MarkDeobf(user, entry); - } - - public static RemoveMapping removeMapping(String user, Entry entry) { - return new RemoveMapping(user, entry); - } - - public static Rename rename(String user, Entry entry, String newName) { - return new Rename(user, entry, newName); - } - - public abstract String translate(); - - public abstract Type getType(); - - public static Message read(DataInput input) throws IOException { - byte typeId = input.readByte(); - if (typeId < 0 || typeId >= Type.values().length) { - throw new IOException(String.format("Invalid message type ID %d", typeId)); - } - Type type = Type.values()[typeId]; - String user = input.readUTF(); - switch (type) { - case CHAT: - String message = input.readUTF(); - return chat(user, message); - case CONNECT: - return connect(user); - case DISCONNECT: - return disconnect(user); - case EDIT_DOCS: - Entry entry = PacketHelper.readEntry(input); - return editDocs(user, entry); - case MARK_DEOBF: - entry = PacketHelper.readEntry(input); - return markDeobf(user, entry); - case REMOVE_MAPPING: - entry = PacketHelper.readEntry(input); - return removeMapping(user, entry); - case RENAME: - entry = PacketHelper.readEntry(input); - String newName = input.readUTF(); - return rename(user, entry, newName); - default: - throw new IllegalStateException("unreachable"); - } - } - - public void write(DataOutput output) throws IOException { - output.writeByte(getType().ordinal()); - PacketHelper.writeString(output, user); - } - - private Message(String user) { - this.user = user; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Message message = (Message) o; - return Objects.equals(user, message.user); - } - - @Override - public int hashCode() { - return Objects.hash(user); - } - - public enum Type { - CHAT, - CONNECT, - DISCONNECT, - EDIT_DOCS, - MARK_DEOBF, - REMOVE_MAPPING, - RENAME, - } - - public static final class Chat extends Message { - - public final String message; - - private Chat(String user, String message) { - super(user); - this.message = message; - } - - @Override - public void write(DataOutput output) throws IOException { - super.write(output); - PacketHelper.writeString(output, message); - } - - @Override - public String translate() { - return String.format(I18n.translate("message.chat.text"), user, message); - } - - @Override - public Type getType() { - return Type.CHAT; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - Chat chat = (Chat) o; - return Objects.equals(message, chat.message); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), message); - } - - @Override - public String toString() { - return String.format("Message.Chat { user: '%s', message: '%s' }", user, message); - } - - } - - public static final class Connect extends Message { - - private Connect(String user) { - super(user); - } - - @Override - public String translate() { - return String.format(I18n.translate("message.connect.text"), user); - } - - @Override - public Type getType() { - return Type.CONNECT; - } - - @Override - public String toString() { - return String.format("Message.Connect { user: '%s' }", user); - } - - } - - public static final class Disconnect extends Message { - - private Disconnect(String user) { - super(user); - } - - @Override - public String translate() { - return String.format(I18n.translate("message.disconnect.text"), user); - } - - @Override - public Type getType() { - return Type.DISCONNECT; - } - - @Override - public String toString() { - return String.format("Message.Disconnect { user: '%s' }", user); - } - - } - - public static final class EditDocs extends Message { - - public final Entry entry; - - private EditDocs(String user, Entry entry) { - super(user); - this.entry = entry; - } - - @Override - public void write(DataOutput output) throws IOException { - super.write(output); - PacketHelper.writeEntry(output, entry); - } - - @Override - public String translate() { - return String.format(I18n.translate("message.edit_docs.text"), user, entry); - } - - @Override - public Type getType() { - return Type.EDIT_DOCS; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - EditDocs editDocs = (EditDocs) o; - return Objects.equals(entry, editDocs.entry); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), entry); - } - - @Override - public String toString() { - return String.format("Message.EditDocs { user: '%s', entry: %s }", user, entry); - } - - } - - public static final class MarkDeobf extends Message { - - public final Entry entry; - - private MarkDeobf(String user, Entry entry) { - super(user); - this.entry = entry; - } - - @Override - public void write(DataOutput output) throws IOException { - super.write(output); - PacketHelper.writeEntry(output, entry); - } - - @Override - public String translate() { - return String.format(I18n.translate("message.mark_deobf.text"), user, entry); - } - - @Override - public Type getType() { - return Type.MARK_DEOBF; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - MarkDeobf markDeobf = (MarkDeobf) o; - return Objects.equals(entry, markDeobf.entry); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), entry); - } - - @Override - public String toString() { - return String.format("Message.MarkDeobf { user: '%s', entry: %s }", user, entry); - } - - } - - public static final class RemoveMapping extends Message { - - public final Entry entry; - - private RemoveMapping(String user, Entry entry) { - super(user); - this.entry = entry; - } - - @Override - public void write(DataOutput output) throws IOException { - super.write(output); - PacketHelper.writeEntry(output, entry); - } - - @Override - public String translate() { - return String.format(I18n.translate("message.remove_mapping.text"), user, entry); - } - - @Override - public Type getType() { - return Type.REMOVE_MAPPING; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - RemoveMapping that = (RemoveMapping) o; - return Objects.equals(entry, that.entry); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), entry); - } - - @Override - public String toString() { - return String.format("Message.RemoveMapping { user: '%s', entry: %s }", user, entry); - } - - } - - public static final class Rename extends Message { - - public final Entry entry; - public final String newName; - - private Rename(String user, Entry entry, String newName) { - super(user); - this.entry = entry; - this.newName = newName; - } - - @Override - public void write(DataOutput output) throws IOException { - super.write(output); - PacketHelper.writeEntry(output, entry); - PacketHelper.writeString(output, newName); - } - - @Override - public String translate() { - return String.format(I18n.translate("message.rename.text"), user, entry, newName); - } - - @Override - public Type getType() { - return Type.RENAME; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - Rename rename = (Rename) o; - return Objects.equals(entry, rename.entry) && - Objects.equals(newName, rename.newName); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), entry, newName); - } - - @Override - public String toString() { - return String.format("Message.Rename { user: '%s', entry: %s, newName: '%s' }", user, entry, newName); - } - - } - -} diff --git a/src/main/java/cuchaz/enigma/utils/Pair.java b/src/main/java/cuchaz/enigma/utils/Pair.java deleted file mode 100644 index bf02ceff..00000000 --- a/src/main/java/cuchaz/enigma/utils/Pair.java +++ /dev/null @@ -1,26 +0,0 @@ -package cuchaz.enigma.utils; - -import java.util.Objects; - -public class Pair { - public final A a; - public final B b; - - public Pair(A a, B b) { - this.a = a; - this.b = b; - } - - @Override - public int hashCode() { - return Objects.hashCode(a) * 31 + - Objects.hashCode(b); - } - - @Override - public boolean equals(Object o) { - return o instanceof Pair && - Objects.equals(a, ((Pair) o).a) && - Objects.equals(b, ((Pair) o).b); - } -} diff --git a/src/main/java/cuchaz/enigma/utils/ReadableToken.java b/src/main/java/cuchaz/enigma/utils/ReadableToken.java deleted file mode 100644 index de152fe3..00000000 --- a/src/main/java/cuchaz/enigma/utils/ReadableToken.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.utils; - -public class ReadableToken { - - public int line; - public int startColumn; - public int endColumn; - - public ReadableToken(int line, int startColumn, int endColumn) { - this.line = line; - this.startColumn = startColumn; - this.endColumn = endColumn; - } - - @Override - public String toString() { - return "line " + line + " columns " + startColumn + "-" + endColumn; - } -} diff --git a/src/main/java/cuchaz/enigma/utils/Utils.java b/src/main/java/cuchaz/enigma/utils/Utils.java deleted file mode 100644 index b45b00d1..00000000 --- a/src/main/java/cuchaz/enigma/utils/Utils.java +++ /dev/null @@ -1,179 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2015 Jeff Martin. - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the GNU Lesser General Public - * License v3.0 which accompanies this distribution, and is available at - * http://www.gnu.org/licenses/lgpl.html - *

- * Contributors: - * Jeff Martin - initial API and implementation - ******************************************************************************/ - -package cuchaz.enigma.utils; - -import com.google.common.io.CharStreams; -import org.objectweb.asm.Opcodes; - -import javax.swing.*; -import javax.swing.text.BadLocationException; -import javax.swing.text.JTextComponent; -import java.awt.*; -import java.awt.event.MouseEvent; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.URI; -import java.net.URISyntaxException; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; -import java.nio.file.Path; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.*; -import java.util.List; -import java.util.stream.Collectors; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -public class Utils { - - public static final int ASM_VERSION = Opcodes.ASM8; - - public static int combineHashesOrdered(Object... objs) { - final int prime = 67; - int result = 1; - for (Object obj : objs) { - result *= prime; - if (obj != null) { - result += obj.hashCode(); - } - } - return result; - } - - public static int combineHashesOrdered(List objs) { - final int prime = 67; - int result = 1; - for (Object obj : objs) { - result *= prime; - if (obj != null) { - result += obj.hashCode(); - } - } - return result; - } - - public static String readStreamToString(InputStream in) throws IOException { - return CharStreams.toString(new InputStreamReader(in, "UTF-8")); - } - - public static String readResourceToString(String path) throws IOException { - InputStream in = Utils.class.getResourceAsStream(path); - if (in == null) { - throw new IllegalArgumentException("Resource not found! " + path); - } - return readStreamToString(in); - } - - public static void openUrl(String url) { - if (Desktop.isDesktopSupported()) { - Desktop desktop = Desktop.getDesktop(); - try { - desktop.browse(new URI(url)); - } catch (IOException ex) { - throw new Error(ex); - } catch (URISyntaxException ex) { - throw new IllegalArgumentException(ex); - } - } - } - - public static JLabel unboldLabel(JLabel label) { - Font font = label.getFont(); - label.setFont(font.deriveFont(font.getStyle() & ~Font.BOLD)); - return label; - } - - public static void showToolTipNow(JComponent component) { - // HACKHACK: trick the tooltip manager into showing the tooltip right now - ToolTipManager manager = ToolTipManager.sharedInstance(); - int oldDelay = manager.getInitialDelay(); - manager.setInitialDelay(0); - manager.mouseMoved(new MouseEvent(component, MouseEvent.MOUSE_MOVED, System.currentTimeMillis(), 0, 0, 0, 0, false)); - manager.setInitialDelay(oldDelay); - } - - public static Rectangle safeModelToView(JTextComponent component, int modelPos) { - if (modelPos < 0) { - modelPos = 0; - } else if (modelPos >= component.getText().length()) { - modelPos = component.getText().length(); - } - try { - return component.modelToView(modelPos); - } catch (BadLocationException e) { - throw new RuntimeException(e); - } - } - - public static boolean getSystemPropertyAsBoolean(String property, boolean defValue) { - String value = System.getProperty(property); - return value == null ? defValue : Boolean.parseBoolean(value); - } - - public static void delete(Path path) throws IOException { - if (Files.exists(path)) { - for (Path p : Files.walk(path).sorted(Comparator.reverseOrder()).collect(Collectors.toList())) { - Files.delete(p); - } - } - } - - public static byte[] zipSha1(Path path) throws IOException { - MessageDigest digest; - try { - digest = MessageDigest.getInstance("SHA-1"); - } catch (NoSuchAlgorithmException e) { - // Algorithm guaranteed to be supported - throw new RuntimeException(e); - } - try (ZipFile zip = new ZipFile(path.toFile())) { - List entries = Collections.list(zip.entries()); - // only compare classes (some implementations may not generate directory entries) - entries.removeIf(entry -> !entry.getName().toLowerCase(Locale.ROOT).endsWith(".class")); - // different implementations may add zip entries in a different order - entries.sort(Comparator.comparing(ZipEntry::getName)); - byte[] buffer = new byte[8192]; - for (ZipEntry entry : entries) { - digest.update(entry.getName().getBytes(StandardCharsets.UTF_8)); - try (InputStream in = zip.getInputStream(entry)) { - int n; - while ((n = in.read(buffer)) != -1) { - digest.update(buffer, 0, n); - } - } - } - } - return digest.digest(); - } - - public static String caplisiseCamelCase(String input){ - StringJoiner stringJoiner = new StringJoiner(" "); - for (String word : input.toLowerCase(Locale.ROOT).split("_")) { - stringJoiner.add(word.substring(0, 1).toUpperCase(Locale.ROOT) + word.substring(1)); - } - return stringJoiner.toString(); - } - - public static boolean isBlank(String input) { - if (input == null) { - return true; - } - for (int i = 0; i < input.length(); i++) { - if (!Character.isWhitespace(input.charAt(i))) { - return false; - } - } - return true; - } -} diff --git a/src/main/java/cuchaz/enigma/utils/search/SearchEntry.java b/src/main/java/cuchaz/enigma/utils/search/SearchEntry.java deleted file mode 100644 index 48b255f8..00000000 --- a/src/main/java/cuchaz/enigma/utils/search/SearchEntry.java +++ /dev/null @@ -1,17 +0,0 @@ -package cuchaz.enigma.utils.search; - -import java.util.List; - -public interface SearchEntry { - - List getSearchableNames(); - - /** - * Returns a type that uniquely identifies this search entry across possible changes. - * This is used for tracking the amount of times this entry has been selected. - * - * @return a unique identifier for this search entry - */ - String getIdentifier(); - -} diff --git a/src/main/java/cuchaz/enigma/utils/search/SearchUtil.java b/src/main/java/cuchaz/enigma/utils/search/SearchUtil.java deleted file mode 100644 index a51afbb0..00000000 --- a/src/main/java/cuchaz/enigma/utils/search/SearchUtil.java +++ /dev/null @@ -1,268 +0,0 @@ -package cuchaz.enigma.utils.search; - -import java.util.*; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; -import java.util.function.BiFunction; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import cuchaz.enigma.utils.Pair; - -public class SearchUtil { - - private final Map> entries = new HashMap<>(); - private final Map hitCount = new HashMap<>(); - private final Executor searchExecutor = Executors.newWorkStealingPool(); - - public void add(T entry) { - Entry e = Entry.from(entry); - entries.put(entry, e); - } - - public void add(Entry entry) { - entries.put(entry.searchEntry, entry); - } - - public void addAll(Collection entries) { - this.entries.putAll(entries.parallelStream().collect(Collectors.toMap(e -> e, Entry::from))); - } - - public void remove(T entry) { - entries.remove(entry); - } - - public void clear() { - entries.clear(); - } - - public void clearHits() { - hitCount.clear(); - } - - public Stream search(String term) { - return entries.values().parallelStream() - .map(e -> new Pair<>(e, e.getScore(term, hitCount.getOrDefault(e.searchEntry.getIdentifier(), 0)))) - .filter(e -> e.b > 0) - .sorted(Comparator.comparingDouble(o -> -o.b)) - .map(e -> e.a.searchEntry) - .sequential(); - } - - public SearchControl asyncSearch(String term, SearchResultConsumer consumer) { - Map hitCount = new HashMap<>(this.hitCount); - Map> entries = new HashMap<>(this.entries); - float[] scores = new float[entries.size()]; - Lock scoresLock = new ReentrantLock(); - AtomicInteger size = new AtomicInteger(); - AtomicBoolean control = new AtomicBoolean(false); - AtomicInteger elapsed = new AtomicInteger(); - for (Entry value : entries.values()) { - searchExecutor.execute(() -> { - try { - if (control.get()) return; - float score = value.getScore(term, hitCount.getOrDefault(value.searchEntry.getIdentifier(), 0)); - if (score <= 0) return; - score = -score; // sort descending - try { - scoresLock.lock(); - if (control.get()) return; - int dataSize = size.getAndIncrement(); - int index = Arrays.binarySearch(scores, 0, dataSize, score); - if (index < 0) { - index = ~index; - } - System.arraycopy(scores, index, scores, index + 1, dataSize - index); - scores[index] = score; - consumer.add(index, value.searchEntry); - } finally { - scoresLock.unlock(); - } - } finally { - elapsed.incrementAndGet(); - } - }); - } - - return new SearchControl() { - @Override - public void stop() { - control.set(true); - } - - @Override - public boolean isFinished() { - return entries.size() == elapsed.get(); - } - - @Override - public float getProgress() { - return (float) elapsed.get() / entries.size(); - } - }; - } - - public void hit(T entry) { - if (entries.containsKey(entry)) { - hitCount.compute(entry.getIdentifier(), (_id, i) -> i == null ? 1 : i + 1); - } - } - - public static final class Entry { - - public final T searchEntry; - private final String[][] components; - - private Entry(T searchEntry, String[][] components) { - this.searchEntry = searchEntry; - this.components = components; - } - - public float getScore(String term, int hits) { - String ucTerm = term.toUpperCase(Locale.ROOT); - float maxScore = (float) Arrays.stream(components) - .mapToDouble(name -> getScoreFor(ucTerm, name)) - .max().orElse(0.0); - return maxScore * (hits + 1); - } - - /** - * Computes the score for the given name against the given search term. - * - * @param term the search term (expected to be upper-case) - * @param name the entry name, split at word boundaries (see {@link Entry#wordwiseSplit(String)}) - * @return the computed score for the entry - */ - private static float getScoreFor(String term, String[] name) { - int totalLength = Arrays.stream(name).mapToInt(String::length).sum(); - float scorePerChar = 1f / totalLength; - - // This map contains a snapshot of all the states the search has - // been in. The keys are the remaining characters of the search - // term, the values are the maximum scores for that remaining - // search term part. - Map snapshots = new HashMap<>(); - snapshots.put(term, 0f); - - // For each component, start at each existing snapshot, searching - // for the next longest match, and calculate the new score for each - // match length until the maximum. Then the new scores are put back - // into the snapshot map. - for (int componentIndex = 0; componentIndex < name.length; componentIndex++) { - String component = name[componentIndex]; - float posMultiplier = (name.length - componentIndex) * 0.3f; - Map newSnapshots = new HashMap<>(); - for (Map.Entry snapshot : snapshots.entrySet()) { - String remaining = snapshot.getKey(); - float score = snapshot.getValue(); - component = component.toUpperCase(Locale.ROOT); - int l = compareEqualLength(remaining, component); - for (int i = 1; i <= l; i++) { - float baseScore = scorePerChar * i; - float chainBonus = (i - 1) * 0.5f; - merge(newSnapshots, Collections.singletonMap(remaining.substring(i), score + baseScore * posMultiplier + chainBonus), Math::max); - } - } - merge(snapshots, newSnapshots, Math::max); - } - - // Only return the score for when the search term was completely - // consumed. - return snapshots.getOrDefault("", 0f); - } - - private static void merge(Map self, Map source, BiFunction combiner) { - source.forEach((k, v) -> self.compute(k, (_k, v1) -> v1 == null ? v : v == null ? v1 : combiner.apply(v, v1))); - } - - public static Entry from(T e) { - String[][] components = e.getSearchableNames().parallelStream() - .map(Entry::wordwiseSplit) - .toArray(String[][]::new); - return new Entry<>(e, components); - } - - private static int compareEqualLength(String s1, String s2) { - int len = 0; - while (len < s1.length() && len < s2.length() && s1.charAt(len) == s2.charAt(len)) { - len += 1; - } - return len; - } - - /** - * Splits the given input into components, trying to detect word parts. - *

- * Example of how words get split (using | as seperator): - *

MinecraftClientGame -> Minecraft|Client|Game

- *

HTTPInputStream -> HTTP|Input|Stream

- *

class_932 -> class|_|932

- *

X11FontManager -> X|11|Font|Manager

- *

openHTTPConnection -> open|HTTP|Connection

- *

open_http_connection -> open|_|http|_|connection

- * - * @param input the input to split - * @return the resulting components - */ - private static String[] wordwiseSplit(String input) { - List list = new ArrayList<>(); - while (!input.isEmpty()) { - int take; - if (Character.isLetter(input.charAt(0))) { - if (input.length() == 1) { - take = 1; - } else { - boolean nextSegmentIsUppercase = Character.isUpperCase(input.charAt(0)) && Character.isUpperCase(input.charAt(1)); - if (nextSegmentIsUppercase) { - int nextLowercase = 1; - while (Character.isUpperCase(input.charAt(nextLowercase))) { - nextLowercase += 1; - if (nextLowercase == input.length()) { - nextLowercase += 1; - break; - } - } - take = nextLowercase - 1; - } else { - int nextUppercase = 1; - while (nextUppercase < input.length() && Character.isLowerCase(input.charAt(nextUppercase))) { - nextUppercase += 1; - } - take = nextUppercase; - } - } - } else if (Character.isDigit(input.charAt(0))) { - int nextNonNum = 1; - while (nextNonNum < input.length() && Character.isLetter(input.charAt(nextNonNum)) && !Character.isLowerCase(input.charAt(nextNonNum))) { - nextNonNum += 1; - } - take = nextNonNum; - } else { - take = 1; - } - list.add(input.substring(0, take)); - input = input.substring(take); - } - return list.toArray(new String[0]); - } - - } - - @FunctionalInterface - public interface SearchResultConsumer { - void add(int index, T entry); - } - - public interface SearchControl { - void stop(); - - boolean isFinished(); - - float getProgress(); - } - -} diff --git a/src/main/resources/META-INF/services/cuchaz.enigma.api.EnigmaPlugin b/src/main/resources/META-INF/services/cuchaz.enigma.api.EnigmaPlugin deleted file mode 100644 index 136a3e78..00000000 --- a/src/main/resources/META-INF/services/cuchaz.enigma.api.EnigmaPlugin +++ /dev/null @@ -1 +0,0 @@ -cuchaz.enigma.analysis.BuiltinPlugin diff --git a/src/main/resources/about.html b/src/main/resources/about.html deleted file mode 100644 index b75c1bf0..00000000 --- a/src/main/resources/about.html +++ /dev/null @@ -1,6 +0,0 @@ - -

%s

-

A tool for debofuscation of Java code

-

-

Version: %s

- \ No newline at end of file diff --git a/src/main/resources/lang/en_us.json b/src/main/resources/lang/en_us.json deleted file mode 100644 index dbf4b935..00000000 --- a/src/main/resources/lang/en_us.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - "language": "English", - - "mapping_format.enigma_file": "Enigma File", - "mapping_format.enigma_directory": "Enigma Directory", - "mapping_format.enigma_zip": "Enigma ZIP", - "mapping_format.tiny_v2": "Tiny v2", - "mapping_format.tiny_file": "Tiny File", - "mapping_format.srg_file": "SRG File", - "mapping_format.proguard": "Proguard", - "type.methods": "Methods", - "type.fields": "Fields", - "type.parameters": "Parameters", - "type.classes": "Classes", - - "menu.file": "File", - "menu.file.jar.open": "Open Jar...", - "menu.file.jar.close": "Close Jar", - "menu.file.mappings.open": "Open Mappings...", - "menu.file.mappings.save": "Save Mappings", - "menu.file.mappings.save_as": "Save Mappings As...", - "menu.file.mappings.close": "Close Mappings", - "menu.file.mappings.drop": "Drop Invalid Mappings", - "menu.file.export.source": "Export Source...", - "menu.file.export.jar": "Export Jar...", - "menu.file.stats": "Mapping Stats...", - "menu.file.stats.title": "Choose Included Members", - "menu.file.stats.generate": "Generate Stats", - "menu.file.exit": "Exit", - "menu.decompiler": "Decompiler", - "menu.view": "View", - "menu.view.themes": "Themes", - "menu.view.themes.default": "Default", - "menu.view.themes.darcula": "Darcula", - "menu.view.themes.system": "System", - "menu.view.themes.none": "None (JVM Default)", - "menu.view.languages": "Languages", - "menu.view.scale": "Scale", - "menu.view.scale.custom": "Custom...", - "menu.view.scale.custom.title": "Custom Scale", - "menu.view.change.title": "Changes", - "menu.view.change.summary": "Changes will be applied after the next restart.", - "menu.view.change.ok": "Ok", - "menu.view.search": "Search", - "menu.collab": "Collab", - "menu.collab.connect": "Connect to server", - "menu.collab.connect.error": "Error connecting to server", - "menu.collab.disconnect": "Disconnect", - "menu.collab.server.start": "Start server", - "menu.collab.server.start.error": "Error starting server", - "menu.collab.server.stop": "Stop server", - "menu.help": "Help", - "menu.help.about": "About", - "menu.help.about.title": "%s - About", - "menu.help.about.ok": "Ok", - "menu.help.github": "Github Page", - - "popup_menu.rename": "Rename", - "popup_menu.javadoc": "Edit Javadoc", - "popup_menu.inheritance": "Show Inheritance", - "popup_menu.implementations": "Show Implementations", - "popup_menu.calls": "Show Calls (All Implementations)", - "popup_menu.calls.specific": "Show Calls (Specific)", - "popup_menu.declaration": "Go to Declaration", - "popup_menu.back": "Go back", - "popup_menu.forward": "Go forward", - "popup_menu.mark_deobfuscated": "Mark as deobfuscated", - "popup_menu.reset_obfuscated": "Reset to obfuscated", - "popup_menu.zoom.in": "Zoom in", - "popup_menu.zoom.out": "Zoom out", - "popup_menu.zoom.reset": "Reset zoom", - - "info_panel.classes.obfuscated": "Obfuscated Classes", - "info_panel.classes.deobfuscated": "De-obfuscated Classes", - "info_panel.identifier": "Identifier Info", - "info_panel.identifier.none": "No identifier selected", - "info_panel.identifier.variable": "Variable", - "info_panel.identifier.field": "Field", - "info_panel.identifier.method": "Method", - "info_panel.identifier.constructor": "Constructor", - "info_panel.identifier.class": "Class", - "info_panel.identifier.type_descriptor": "TypeDescriptor", - "info_panel.identifier.method_descriptor": "MethodDescriptor", - "info_panel.identifier.modifier": "Modifier", - "info_panel.identifier.index": "Index", - "info_panel.editor.class.decompiling": "(decompiling...)", - "info_panel.editor.class.not_found": "Unable to find class:", - "info_panel.tree.inheritance": "Inheritance", - "info_panel.tree.implementations": "Implementations", - "info_panel.tree.calls": "Call Graph", - - "log_panel.messages": "Messages", - "log_panel.users": "Users", - - "progress.operation": "%s - Operation in progress", - "progress.jar.indexing": "Indexing jar", - "progress.jar.indexing.entries": "Entries...", - "progress.jar.indexing.references": "Entry references...", - "progress.jar.indexing.methods": "Bridge methods...", - "progress.jar.indexing.process": "Processing...", - "progress.jar.writing": "Writing jar...", - "progress.sources.writing": "Writing sources...", - "progress.classes.deobfuscating": "Deobfuscating classes...", - "progress.classes.decompiling": "Decompiling classes...", - "progress.mappings.enigma_file.loading": "Loading mapping file", - "progress.mappings.enigma_file.done": "Done!", - "progress.mappings.enigma_file.writing": "Writing classes", - "progress.mappings.enigma_directory.loading": "Loading mapping files", - "progress.mappings.enigma_directory.writing": "Writing classes", - "progress.mappings.tiny_file.loading": "Loading mapping file", - "progress.mappings.tiny_v2.loading": "Loading mapping file", - "progress.mappings.srg_file.generating": "Generating mappings", - "progress.mappings.srg_file.writing": "Writing mappings", - "progress.stats": "Generating stats", - "progress.stats.data": "Generating data", - - "javadocs.edit": "Edit Javadocs", - "javadocs.instruction": "Edit javadocs here.", - "javadocs.cancel": "Cancel", - "javadocs.save": "Save", - - "prompt.close.title": "Save your changes?", - "prompt.close.summary": "Your mappings have not been saved yet. Do you want to save?", - "prompt.close.save": "Save and close", - "prompt.close.discard": "Discard changes", - "prompt.close.cancel": "Cancel", - "prompt.open": "Open", - "prompt.cancel": "Cancel", - "prompt.connect.title": "Connect to server", - "prompt.connect.username": "Username", - "prompt.connect.ip": "IP", - "prompt.port": "Port", - "prompt.port.nan": "Port is not a number", - "prompt.port.invalid": "Port is out of range, should be between 0-65535", - "prompt.password": "Password", - "prompt.password.too_long": "Password is too long, it must be at most 255 characters.", - "prompt.create_server.title": "Create server", - - "disconnect.disconnected": "Disconnected", - "disconnect.server_closed": "Server closed", - "disconnect.wrong_jar": "Jar checksums don't match (you have the wrong jar)!", - "disconnect.wrong_password": "Incorrect password", - "disconnect.username_taken": "Username is taken", - - "message.chat.text": "%s: %s", - "message.connect.text": "[+] %s", - "message.disconnect.text": "[-] %s", - "message.edit_docs.text": "%s edited docs for %s", - "message.mark_deobf.text": "%s marked %s as deobfuscated", - "message.remove_mapping.text": "%s removed mappings for %s", - "message.rename.text": "%s renamed %s to %s", - - "status.disconnected": "Disconnected.", - "status.connected": "Connected.", - "status.connected_user_count": "Connected (%d users).", - "status.ready": "Ready.", - - "crash.title": "%s - Crash Report", - "crash.summary": "%s has crashed! =(", - "crash.export": "Export", - "crash.ignore": "Ignore", - "crash.exit": "Exit", - "crash.exit.warning": "If you choose exit, you will lose any unsaved work." -} diff --git a/src/main/resources/lang/fr_fr.json b/src/main/resources/lang/fr_fr.json deleted file mode 100644 index d169b9a0..00000000 --- a/src/main/resources/lang/fr_fr.json +++ /dev/null @@ -1,164 +0,0 @@ -{ - "language": "Français", - - "mapping_format.enigma_file": "Fichier Enigma", - "mapping_format.enigma_directory": "Répertoire Enigma", - "mapping_format.enigma_zip": "ZIP Enigma", - "mapping_format.tiny_v2": "Tiny v2", - "mapping_format.tiny_file": "Fichier Tiny", - "mapping_format.srg_file": "Fichier SRG", - "mapping_format.proguard": "Proguard", - "type.methods": "Méthodes", - "type.fields": "Champs", - "type.parameters": "Paramètres", - "type.classes": "Classes", - - "menu.file": "Fichier", - "menu.file.jar.open": "Ouvrir le jar...", - "menu.file.jar.close": "Fermer le jar", - "menu.file.mappings.open": "Ouvrir les mappings...", - "menu.file.mappings.save": "Enregistrer les mappings", - "menu.file.mappings.save_as": "Enregistrer les mappings sous...", - "menu.file.mappings.close": "Fermer les mappings", - "menu.file.mappings.drop": "Supprimer les mappings invalides", - "menu.file.export.source": "Exporter la source...", - "menu.file.export.jar": "Exporter le jar...", - "menu.file.stats": "Statistiques des mappings...", - "menu.file.stats.title": "Choisir les membres inclus", - "menu.file.stats.generate": "Générer les statistiques", - "menu.file.exit": "Quitter", - "menu.decompiler": "Décompilateur", - "menu.view": "Affichage", - "menu.view.themes": "Thèmes", - "menu.view.themes.default": "Par défaut", - "menu.view.themes.darcula": "Darcula", - "menu.view.themes.system": "Système", - "menu.view.themes.none": "Aucun (JVM par défaut)", - "menu.view.languages": "Langues", - "menu.view.scale": "Échelle", - "menu.view.scale.custom": "Personnalisée...", - "menu.view.scale.custom.title": "Échelle personnalisée", - "menu.view.change.title": "Modifications", - "menu.view.change.summary": "Les modifications seront appliquées lors du prochain redémarrage.", - "menu.view.change.ok": "Ok", - "menu.view.search": "Rechercher", - "menu.collab": "Collab", - "menu.collab.connect": "Se connecter à un serveur", - "menu.collab.connect.error": "Erreur lors de la connexion au serveur", - "menu.collab.disconnect": "Se déconnecter", - "menu.collab.server.start": "Démarrer le serveur", - "menu.collab.server.start.error": "Erreur lors du démarrage du serveur", - "menu.collab.server.stop": "Arrêter le serveur", - "menu.help": "Aide", - "menu.help.about": "À propos", - "menu.help.about.title": "%s - À propos", - "menu.help.about.ok": "Ok", - "menu.help.github": "Page Github", - - "popup_menu.rename": "Renommer", - "popup_menu.javadoc": "Éditer le Javadoc", - "popup_menu.inheritance": "Afficher l'héritage", - "popup_menu.implementations": "Afficher les implémentations", - "popup_menu.calls": "Afficher les appels (tous)", - "popup_menu.calls.specific": "Afficher les appels (spécifiques)", - "popup_menu.declaration": "Aller à la déclaration", - "popup_menu.back": "Annuler", - "popup_menu.forward": "Restaurer", - "popup_menu.mark_deobfuscated": "Marquer comme déobfusqué", - "popup_menu.reset_obfuscated": "Réinitialiser à obfusqué", - "popup_menu.zoom.in": "Zoomer", - "popup_menu.zoom.out": "Dézoomer", - "popup_menu.zoom.reset": "Réinitialiser le zoom", - - "info_panel.classes.obfuscated": "Classes obfusquées", - "info_panel.classes.deobfuscated": "Classes déobfusquées", - "info_panel.identifier": "Informations sur l'identifiant", - "info_panel.identifier.none": "Aucun identifiant sélectionné", - "info_panel.identifier.variable": "Variable", - "info_panel.identifier.field": "Champ", - "info_panel.identifier.method": "Méthode", - "info_panel.identifier.constructor": "Constructeur", - "info_panel.identifier.class": "Classe", - "info_panel.identifier.type_descriptor": "Descripteur de type", - "info_panel.identifier.method_descriptor": "Descripteur de méthode", - "info_panel.identifier.modifier": "Modificateur", - "info_panel.identifier.index": "Index", - "info_panel.editor.class.decompiling": "(décompilation...)", - "info_panel.editor.class.not_found": "Impossible de trouver la classe :", - "info_panel.tree.inheritance": "Héritage", - "info_panel.tree.implementations": "Implémentations", - "info_panel.tree.calls": "Graphique des appels", - - "log_panel.messages": "Messages", - "log_panel.users": "Utilisateurs", - - "progress.operation": "%s - Opération en cours", - "progress.jar.indexing": "Indexation du jar", - "progress.jar.indexing.entries": "Entrées...", - "progress.jar.indexing.references": "Références des entrées...", - "progress.jar.indexing.methods": "Mise en place des méthodes...", - "progress.jar.indexing.process": "Traitement...", - "progress.jar.writing": "Écriture du jar...", - "progress.sources.writing": "Écriture des sources...", - "progress.classes.deobfuscating": "Déobfuscation des classes...", - "progress.classes.decompiling": "Décompilation des classes...", - "progress.mappings.enigma_file.loading": "Chargement du fichier de mappings", - "progress.mappings.enigma_file.done": "Terminé !", - "progress.mappings.enigma_file.writing": "Écriture des classes", - "progress.mappings.enigma_directory.loading": "Chargement des fichiers de mappings", - "progress.mappings.enigma_directory.writing": "Écriture des classes", - "progress.mappings.tiny_file.loading": "Chargement du fichier de mappings", - "progress.mappings.tiny_v2.loading": "Chargement du fichier de mappings", - "progress.mappings.srg_file.generating": "Génération des mappings", - "progress.mappings.srg_file.writing": "Écriture des mappings", - "progress.stats": "Génération des statistiques", - "progress.stats.data": "Génération des données", - - "javadocs.edit": "Éditer les Javadocs", - "javadocs.instruction": "Éditer les Javadocs ici.", - "javadocs.cancel": "Annuler", - "javadocs.save": "Enregistrer", - - "prompt.close.title": "Enregistrer les modifications ?", - "prompt.close.summary": "Vos mappings n'ont pas encore été enregistrés. Souhaitez-vous enregistrer ?", - "prompt.close.save": "Enregistrer et fermer", - "prompt.close.discard": "Annuler les modifications", - "prompt.close.cancel": "Annuler", - "prompt.open": "Ouvrir", - "prompt.cancel": "Annuler", - "prompt.connect.title": "Se connecter à un serveur", - "prompt.connect.username": "Nom d'utilisateur", - "prompt.connect.ip": "IP", - "prompt.port": "Port", - "prompt.port.nan": "Le port n'est pas un nombre", - "prompt.port.invalid": "Le port est hors de portée. Il doit être compris entre 0 et 65535.", - "prompt.password": "Mot de passe", - "prompt.password.too_long": "Le mot de passe est trop long. Il ne doit pas dépasser 255 caractères.", - "prompt.create_server.title": "Créer un serveur", - - "disconnect.disconnected": "Déconnecté", - "disconnect.server_closed": "Serveur fermé", - "disconnect.wrong_jar": "Les sommes de contrôle du jar ne correspondent pas (vous avez le mauvais jar) !", - "disconnect.wrong_password": "Mot de passe incorrect", - "disconnect.username_taken": "Le nom d'utilisateur est déjà pris", - - "message.chat.text": "%s : %s", - "message.connect.text": "[+] %s", - "message.disconnect.text": "[-] %s", - "message.edit_docs.text": "%s a édité les javadocs de %s", - "message.mark_deobf.text": "%s a marqué %s comme déobfusqué", - "message.remove_mapping.text": "%s a supprimé les mappings de %s", - "message.rename.text": "%s a renommé %s en %s", - - "status.disconnected": "Déconnecté.", - "status.connected": "Connecté.", - "status.connected_user_count": "Connecté (%d utilisateurs).", - "status.ready": "Prêt.", - - "crash.title": "%s - Rapport de plantage", - "crash.summary": "%s a planté ! =(", - "crash.export": "Exporter", - "crash.ignore": "Ignorer", - "crash.exit": "Quitter", - "crash.exit.warning": "Si vous choisissez Quitter, vous perdrez tout travail non sauvegardé." -} diff --git a/src/main/resources/lang/zh_cn.json b/src/main/resources/lang/zh_cn.json deleted file mode 100644 index f3f503aa..00000000 --- a/src/main/resources/lang/zh_cn.json +++ /dev/null @@ -1,118 +0,0 @@ -{ - "language": "Chinese", - - "mapping_format.enigma_file": "Enigma 文件", - "mapping_format.enigma_directory": "Enigma 目录", - "mapping_format.enigma_zip": "Enigma ZIP", - "mapping_format.tiny_v2": "Tiny v2", - "mapping_format.tiny_file": "Tiny File", - "mapping_format.srg_file": "SRG File", - "mapping_format.proguard": "Proguard", - "type.methods": "方法", - "type.fields": "字段", - "type.parameters": "参数", - "type.classes": "类", - - "menu.file": "文件", - "menu.file.jar.open": "打开 Jar...", - "menu.file.jar.close": "关闭 Jar", - "menu.file.mappings.open": "打开映射...", - "menu.file.mappings.save": "保存映射", - "menu.file.mappings.save_as": "将映射另存为...", - "menu.file.mappings.close": "关闭映射", - "menu.file.mappings.drop": "删除无效映射", - "menu.file.export.source": "导出源码...", - "menu.file.export.jar": "导出Jar...", - "menu.file.stats": "映射统计范围...", - "menu.file.stats.title": "选择包括的成员", - "menu.file.stats.generate": "生成统计范围", - "menu.file.exit": "退出", - "menu.decompiler": "反编译", - "menu.view": "查看", - "menu.view.themes": "主题", - "menu.view.themes.default": "Default", - "menu.view.themes.darcula": "Darcula", - "menu.view.themes.system": "System", - "menu.view.themes.none": "None (JVM Default)", - "menu.view.languages": "语言", - "menu.view.languages.title": "更改语言", - "menu.view.languages.summary": "新语言将在下次重新启动后应用.", - "menu.view.languages.ok": "确定", - "menu.view.search": "搜索", - "menu.help": "帮助", - "menu.help.about": "关于", - "menu.help.about.title": "%s - 关于", - "menu.help.about.ok": "确定", - "menu.help.github": "GitHub 页面", - - "popup_menu.rename": "改名", - "popup_menu.javadoc": "编辑注释", - "popup_menu.inheritance": "显示继承", - "popup_menu.implementations": "显示实现", - "popup_menu.calls": "显示 Calls", - "popup_menu.calls.specific": "显示 Calls (具体)", - "popup_menu.declaration": "Go to Declaration", - "popup_menu.back": "Go back", - "popup_menu.forward": "Go forward", - "popup_menu.mark_deobfuscated": "标记为反混淆", - "popup_menu.reset_obfuscated": "重置混淆", - - "info_panel.classes.obfuscated": "混淆类", - "info_panel.classes.deobfuscated": "反混淆类", - "info_panel.identifier": "标识符信息", - "info_panel.identifier.none": "未选择标识符", - "info_panel.identifier.variable": "变量", - "info_panel.identifier.field": "字段", - "info_panel.identifier.method": "方法", - "info_panel.identifier.constructor": "构造器", - "info_panel.identifier.class": "类", - "info_panel.identifier.type_descriptor": "类型描述符", - "info_panel.identifier.method_descriptor": "方法描述符", - "info_panel.identifier.modifier": "修饰语", - "info_panel.identifier.index": "索引", - "info_panel.editor.class.decompiling": "(反编译中...)", - "info_panel.editor.class.not_found": "找不到类:", - "info_panel.tree.inheritance": "继承", - "info_panel.tree.implementations": "实现", - "info_panel.tree.calls": "调用图", - - "progress.operation": "%s - 进行中", - "progress.jar.indexing": "索引jar", - "progress.jar.indexing.entries": "条目...", - "progress.jar.indexing.references": "条目引用...", - "progress.jar.indexing.methods": "桥接方法...", - "progress.jar.indexing.process": "处理中...", - "progress.jar.writing": "写出jar中...", - "progress.sources.writing": "写出源码中...", - "progress.classes.deobfuscating": "反混淆类中...", - "progress.classes.decompiling": "反编译类中...", - "progress.mappings.enigma_file.loading": "加载映射文件", - "progress.mappings.enigma_file.done": "完成!", - "progress.mappings.enigma_file.writing": "写出类", - "progress.mappings.enigma_directory.loading": "加载映射文件", - "progress.mappings.enigma_directory.writing": "写出类", - "progress.mappings.tiny_file.loading": "加载映射文件", - "progress.mappings.tiny_v2.loading": "加载映射文件", - "progress.mappings.srg_file.generating": "生成映射", - "progress.mappings.srg_file.writing": "写出映射", - "progress.stats": "生成统计范围", - "progress.stats.data": "生成数据", - - "javadocs.edit": "编辑注释", - "javadocs.instruction": "在此处编辑编辑注释.", - "javadocs.cancel": "取消", - "javadocs.save": "保存", - - "prompt.close.title": "保存更改?", - "prompt.close.summary": "您的映射尚未保存。你想保存吗?", - "prompt.close.save": "保存并关闭", - "prompt.close.discard": "放弃更改", - "prompt.close.cancel": "取消", - - "crash.title": "%s - 崩溃报告", - "crash.summary": "%s 已经崩溃! =(", - "crash.export": "输出", - "crash.ignore": "忽略", - "crash.exit": "退出", - "crash.exit.warning": "如果选择退出,将丢失所有未保存的工作." -} diff --git a/src/main/resources/profile.json b/src/main/resources/profile.json deleted file mode 100644 index e1af4cdb..00000000 --- a/src/main/resources/profile.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "services": { - "jar_indexer": [ - { - "id": "enigma:enum_initializer_indexer" - }, - { - "id": "enigma:specialized_bridge_method_indexer" - } - ], - "name_proposal": [ - { - "id": "enigma:enum_name_proposer" - }, - { - "id": "enigma:specialized_method_name_proposer" - } - ] - } -} \ No newline at end of file diff --git a/src/main/resources/stats.html b/src/main/resources/stats.html deleted file mode 100644 index fcff7c0f..00000000 --- a/src/main/resources/stats.html +++ /dev/null @@ -1,34 +0,0 @@ - - - - - - Stats - - - - - -
- - - - - - - -- cgit v1.2.3