Repository: Col-E/Recaf Branch: master Commit: a9d4b982d69d Files: 1323 Total size: 7.0 MB Directory structure: gitextract_kfvnwn9t/ ├── .gitattributes ├── .github/ │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ ├── feature_request.md │ │ └── other.md │ └── workflows/ │ └── build.yml ├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── PRIMER.md ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── build.gradle ├── codecov.yml ├── docs/ │ ├── README.md │ └── index.html ├── gradle/ │ ├── libs.versions.toml │ ├── tasks.gradle │ └── wrapper/ │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── gradlew ├── gradlew.bat ├── jitpack.yml ├── libs/ │ ├── README.md │ └── kotlin-metadata.jar ├── recaf-core/ │ ├── build.gradle │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── software/ │ │ │ └── coley/ │ │ │ └── recaf/ │ │ │ ├── Bootstrap.java │ │ │ ├── ExitCodes.java │ │ │ ├── ExitDebugLoggingHook.java │ │ │ ├── Recaf.java │ │ │ ├── RecafConstants.java │ │ │ ├── analytics/ │ │ │ │ ├── SystemInformation.java │ │ │ │ └── logging/ │ │ │ │ ├── DebuggingLogger.java │ │ │ │ ├── InterceptingLogger.java │ │ │ │ ├── LogConsumer.java │ │ │ │ ├── Logging.java │ │ │ │ └── RecafLoggingFilter.java │ │ │ ├── behavior/ │ │ │ │ ├── Closing.java │ │ │ │ ├── PriorityKeys.java │ │ │ │ └── PrioritySortable.java │ │ │ ├── cdi/ │ │ │ │ ├── EagerInitialization.java │ │ │ │ ├── EagerInitializationExtension.java │ │ │ │ ├── InitializationEvent.java │ │ │ │ ├── InitializationStage.java │ │ │ │ └── UiInitializationEvent.java │ │ │ ├── config/ │ │ │ │ ├── BasicCollectionConfigValue.java │ │ │ │ ├── BasicConfigContainer.java │ │ │ │ ├── BasicConfigValue.java │ │ │ │ ├── BasicMapConfigValue.java │ │ │ │ ├── ConfigCollectionValue.java │ │ │ │ ├── ConfigContainer.java │ │ │ │ ├── ConfigGroups.java │ │ │ │ ├── ConfigMapValue.java │ │ │ │ ├── ConfigPersistence.java │ │ │ │ ├── ConfigValue.java │ │ │ │ └── RestoreAwareConfigContainer.java │ │ │ ├── info/ │ │ │ │ ├── Accessed.java │ │ │ │ ├── AndroidChunkFileInfo.java │ │ │ │ ├── AndroidClassInfo.java │ │ │ │ ├── ApkFileInfo.java │ │ │ │ ├── ArscFileInfo.java │ │ │ │ ├── AudioFileInfo.java │ │ │ │ ├── BasicAndroidChunkFileInfo.java │ │ │ │ ├── BasicAndroidClassInfo.java │ │ │ │ ├── BasicApkFileInfo.java │ │ │ │ ├── BasicArscFileInfo.java │ │ │ │ ├── BasicAudioFileInfo.java │ │ │ │ ├── BasicBinaryXmlFileInfo.java │ │ │ │ ├── BasicClassInfo.java │ │ │ │ ├── BasicDexFileInfo.java │ │ │ │ ├── BasicFileInfo.java │ │ │ │ ├── BasicImageFileInfo.java │ │ │ │ ├── BasicInnerClassInfo.java │ │ │ │ ├── BasicJModFileInfo.java │ │ │ │ ├── BasicJarFileInfo.java │ │ │ │ ├── BasicJvmClassInfo.java │ │ │ │ ├── BasicModulesFileInfo.java │ │ │ │ ├── BasicNativeLibraryFileInfo.java │ │ │ │ ├── BasicTextFileInfo.java │ │ │ │ ├── BasicVideoFileInfo.java │ │ │ │ ├── BasicWarFileInfo.java │ │ │ │ ├── BasicZipFileInfo.java │ │ │ │ ├── BinaryXmlFileInfo.java │ │ │ │ ├── ClassInfo.java │ │ │ │ ├── DexFileInfo.java │ │ │ │ ├── FileInfo.java │ │ │ │ ├── ImageFileInfo.java │ │ │ │ ├── Info.java │ │ │ │ ├── InnerClassInfo.java │ │ │ │ ├── JModFileInfo.java │ │ │ │ ├── JarFileInfo.java │ │ │ │ ├── JvmClassInfo.java │ │ │ │ ├── ModulesFileInfo.java │ │ │ │ ├── Named.java │ │ │ │ ├── NativeLibraryFileInfo.java │ │ │ │ ├── StubClassInfo.java │ │ │ │ ├── StubFieldMember.java │ │ │ │ ├── StubFileInfo.java │ │ │ │ ├── StubMember.java │ │ │ │ ├── StubMethodMember.java │ │ │ │ ├── TextFileInfo.java │ │ │ │ ├── VideoFileInfo.java │ │ │ │ ├── WarFileInfo.java │ │ │ │ ├── ZipFileInfo.java │ │ │ │ ├── annotation/ │ │ │ │ │ ├── Annotated.java │ │ │ │ │ ├── AnnotationArrayReference.java │ │ │ │ │ ├── AnnotationElement.java │ │ │ │ │ ├── AnnotationEnumReference.java │ │ │ │ │ ├── AnnotationInfo.java │ │ │ │ │ ├── BasicAnnotationArrayReference.java │ │ │ │ │ ├── BasicAnnotationElement.java │ │ │ │ │ ├── BasicAnnotationEnumReference.java │ │ │ │ │ ├── BasicAnnotationInfo.java │ │ │ │ │ ├── BasicTypeAnnotationInfo.java │ │ │ │ │ └── TypeAnnotationInfo.java │ │ │ │ ├── builder/ │ │ │ │ │ ├── AbstractClassInfoBuilder.java │ │ │ │ │ ├── AndroidClassInfoBuilder.java │ │ │ │ │ ├── ApkFileInfoBuilder.java │ │ │ │ │ ├── ArscFileInfoBuilder.java │ │ │ │ │ ├── AudioFileInfoBuilder.java │ │ │ │ │ ├── BinaryXmlFileInfoBuilder.java │ │ │ │ │ ├── ChunkFileInfoBuilder.java │ │ │ │ │ ├── DexFileInfoBuilder.java │ │ │ │ │ ├── FileInfoBuilder.java │ │ │ │ │ ├── ImageFileInfoBuilder.java │ │ │ │ │ ├── JModFileInfoBuilder.java │ │ │ │ │ ├── JarFileInfoBuilder.java │ │ │ │ │ ├── JvmClassInfoBuilder.java │ │ │ │ │ ├── ModulesFileInfoBuilder.java │ │ │ │ │ ├── NativeLibraryFileInfoBuilder.java │ │ │ │ │ ├── TextFileInfoBuilder.java │ │ │ │ │ ├── VideoFileInfoBuilder.java │ │ │ │ │ ├── WarFileInfoBuilder.java │ │ │ │ │ └── ZipFileInfoBuilder.java │ │ │ │ ├── member/ │ │ │ │ │ ├── BasicFieldMember.java │ │ │ │ │ ├── BasicLocalVariable.java │ │ │ │ │ ├── BasicMember.java │ │ │ │ │ ├── BasicMethodMember.java │ │ │ │ │ ├── ClassMember.java │ │ │ │ │ ├── FieldMember.java │ │ │ │ │ ├── LocalVariable.java │ │ │ │ │ └── MethodMember.java │ │ │ │ └── properties/ │ │ │ │ ├── BasicProperty.java │ │ │ │ ├── BasicPropertyContainer.java │ │ │ │ ├── Property.java │ │ │ │ ├── PropertyContainer.java │ │ │ │ └── builtin/ │ │ │ │ ├── BinaryXmlDecodedProperty.java │ │ │ │ ├── CachedDecompileProperty.java │ │ │ │ ├── HasMappedReferenceProperty.java │ │ │ │ ├── IllegalClassSuspectProperty.java │ │ │ │ ├── InputFilePathProperty.java │ │ │ │ ├── MemberIndexAcceleratorProperty.java │ │ │ │ ├── OriginalClassNameProperty.java │ │ │ │ ├── PathOriginalNameProperty.java │ │ │ │ ├── PathPrefixProperty.java │ │ │ │ ├── PathSuffixProperty.java │ │ │ │ ├── ReferencedClassesProperty.java │ │ │ │ ├── RemapOriginTaskProperty.java │ │ │ │ ├── RemoteClassloaderProperty.java │ │ │ │ ├── StringDefinitionsProperty.java │ │ │ │ ├── ThrowableProperty.java │ │ │ │ ├── UnknownAttributesProperty.java │ │ │ │ ├── VersionedClassProperty.java │ │ │ │ ├── ZipAccessTimeProperty.java │ │ │ │ ├── ZipCommentProperty.java │ │ │ │ ├── ZipCompressionProperty.java │ │ │ │ ├── ZipCreationTimeProperty.java │ │ │ │ ├── ZipEntryIndexProperty.java │ │ │ │ ├── ZipMarkerProperty.java │ │ │ │ ├── ZipModificationTimeProperty.java │ │ │ │ └── ZipPrefixDataProperty.java │ │ │ ├── launch/ │ │ │ │ ├── LaunchArguments.java │ │ │ │ ├── LaunchCommand.java │ │ │ │ └── LaunchHandler.java │ │ │ ├── path/ │ │ │ │ ├── AbstractPathNode.java │ │ │ │ ├── AnnotationPathNode.java │ │ │ │ ├── BundlePathNode.java │ │ │ │ ├── CatchPathNode.java │ │ │ │ ├── ClassMemberPathNode.java │ │ │ │ ├── ClassPathNode.java │ │ │ │ ├── DirectoryPathNode.java │ │ │ │ ├── EmbeddedResourceContainerPathNode.java │ │ │ │ ├── FilePathNode.java │ │ │ │ ├── IncompletePathException.java │ │ │ │ ├── InnerClassPathNode.java │ │ │ │ ├── InstructionPathNode.java │ │ │ │ ├── LineNumberPathNode.java │ │ │ │ ├── LocalVariablePathNode.java │ │ │ │ ├── PathNode.java │ │ │ │ ├── PathNodes.java │ │ │ │ ├── ResourcePathNode.java │ │ │ │ ├── ThrowsPathNode.java │ │ │ │ └── WorkspacePathNode.java │ │ │ ├── plugin/ │ │ │ │ ├── Plugin.java │ │ │ │ └── PluginInformation.java │ │ │ ├── services/ │ │ │ │ ├── Service.java │ │ │ │ ├── ServiceConfig.java │ │ │ │ ├── assembler/ │ │ │ │ │ ├── AbstractAssemblerPipeline.java │ │ │ │ │ ├── AndroidAssemblerPipeline.java │ │ │ │ │ ├── AndroidAssemblerPipelineConfig.java │ │ │ │ │ ├── AssemblerPipeline.java │ │ │ │ │ ├── AssemblerPipelineConfig.java │ │ │ │ │ ├── AssemblerPipelineGeneralConfig.java │ │ │ │ │ ├── AssemblerPipelineManager.java │ │ │ │ │ ├── ExpressionCompileException.java │ │ │ │ │ ├── ExpressionCompiler.java │ │ │ │ │ ├── ExpressionResult.java │ │ │ │ │ ├── JvmAssemblerPipeline.java │ │ │ │ │ ├── JvmAssemblerPipelineConfig.java │ │ │ │ │ ├── Snippet.java │ │ │ │ │ ├── SnippetListener.java │ │ │ │ │ ├── SnippetManager.java │ │ │ │ │ ├── SnippetManagerConfig.java │ │ │ │ │ └── WorkspaceFieldValueLookup.java │ │ │ │ ├── attach/ │ │ │ │ │ ├── AttachManager.java │ │ │ │ │ ├── AttachManagerConfig.java │ │ │ │ │ ├── BasicAttachManager.java │ │ │ │ │ ├── JmxBeanServerConnection.java │ │ │ │ │ ├── NamedMBeanInfo.java │ │ │ │ │ └── PostScanListener.java │ │ │ │ ├── callgraph/ │ │ │ │ │ ├── CachedLinkResolver.java │ │ │ │ │ ├── CallGraph.java │ │ │ │ │ ├── CallGraphConfig.java │ │ │ │ │ ├── CallGraphService.java │ │ │ │ │ ├── ClassLookup.java │ │ │ │ │ ├── ClassMethodsContainer.java │ │ │ │ │ ├── LinkedClass.java │ │ │ │ │ ├── MethodRef.java │ │ │ │ │ └── MethodVertex.java │ │ │ │ ├── comment/ │ │ │ │ │ ├── ClassComments.java │ │ │ │ │ ├── CommentContainerListener.java │ │ │ │ │ ├── CommentInsertingVisitor.java │ │ │ │ │ ├── CommentKey.java │ │ │ │ │ ├── CommentManager.java │ │ │ │ │ ├── CommentManagerConfig.java │ │ │ │ │ ├── CommentUpdateListener.java │ │ │ │ │ ├── DelegatingClassComments.java │ │ │ │ │ ├── DelegatingWorkspaceComments.java │ │ │ │ │ ├── PersistClassComments.java │ │ │ │ │ ├── PersistWorkspaceComments.java │ │ │ │ │ └── WorkspaceComments.java │ │ │ │ ├── compile/ │ │ │ │ │ ├── CompileMap.java │ │ │ │ │ ├── CompilerDiagnostic.java │ │ │ │ │ ├── CompilerResult.java │ │ │ │ │ ├── ForwardingListener.java │ │ │ │ │ ├── JavacArguments.java │ │ │ │ │ ├── JavacArgumentsBuilder.java │ │ │ │ │ ├── JavacCompiler.java │ │ │ │ │ ├── JavacCompilerConfig.java │ │ │ │ │ ├── JavacListener.java │ │ │ │ │ ├── ResourceVirtualJavaFileObject.java │ │ │ │ │ ├── VirtualFileManager.java │ │ │ │ │ ├── VirtualJavaFileObject.java │ │ │ │ │ ├── VirtualUnitMap.java │ │ │ │ │ └── stub/ │ │ │ │ │ ├── ClassStubGenerator.java │ │ │ │ │ ├── ExpressionHostingClassStubGenerator.java │ │ │ │ │ └── InnerClassStubGenerator.java │ │ │ │ ├── config/ │ │ │ │ │ ├── ConfigManager.java │ │ │ │ │ ├── ConfigManagerConfig.java │ │ │ │ │ └── ManagedConfigListener.java │ │ │ │ ├── decompile/ │ │ │ │ │ ├── AbstractAndroidDecompiler.java │ │ │ │ │ ├── AbstractDecompiler.java │ │ │ │ │ ├── AbstractJvmDecompiler.java │ │ │ │ │ ├── AndroidDecompiler.java │ │ │ │ │ ├── BaseDecompilerConfig.java │ │ │ │ │ ├── DecompileResult.java │ │ │ │ │ ├── Decompiler.java │ │ │ │ │ ├── DecompilerConfig.java │ │ │ │ │ ├── DecompilerManager.java │ │ │ │ │ ├── DecompilerManagerConfig.java │ │ │ │ │ ├── JvmDecompiler.java │ │ │ │ │ ├── NoopAndroidDecompiler.java │ │ │ │ │ ├── NoopDecompilerConfig.java │ │ │ │ │ ├── NoopJvmDecompiler.java │ │ │ │ │ ├── cfr/ │ │ │ │ │ │ ├── CfrConfig.java │ │ │ │ │ │ ├── CfrDecompiler.java │ │ │ │ │ │ ├── ClassSource.java │ │ │ │ │ │ └── SinkFactoryImpl.java │ │ │ │ │ ├── fallback/ │ │ │ │ │ │ ├── FallbackConfig.java │ │ │ │ │ │ ├── FallbackDecompiler.java │ │ │ │ │ │ └── print/ │ │ │ │ │ │ ├── ClassPrinter.java │ │ │ │ │ │ ├── MethodPrinter.java │ │ │ │ │ │ ├── PrintUtils.java │ │ │ │ │ │ └── Printer.java │ │ │ │ │ ├── filter/ │ │ │ │ │ │ ├── JvmBytecodeFilter.java │ │ │ │ │ │ └── OutputTextFilter.java │ │ │ │ │ ├── procyon/ │ │ │ │ │ │ ├── ProcyonConfig.java │ │ │ │ │ │ ├── ProcyonDecompiler.java │ │ │ │ │ │ └── WorkspaceTypeLoader.java │ │ │ │ │ └── vineflower/ │ │ │ │ │ ├── BaseSource.java │ │ │ │ │ ├── ClassSource.java │ │ │ │ │ ├── DecompiledOutputSink.java │ │ │ │ │ ├── DummyResultSaver.java │ │ │ │ │ ├── LibrarySource.java │ │ │ │ │ ├── VineflowerConfig.java │ │ │ │ │ ├── VineflowerDecompiler.java │ │ │ │ │ ├── VineflowerLogger.java │ │ │ │ │ └── WorkspaceEntriesCache.java │ │ │ │ ├── deobfuscation/ │ │ │ │ │ └── transform/ │ │ │ │ │ ├── generic/ │ │ │ │ │ │ ├── CallResultInliningTransformer.java │ │ │ │ │ │ ├── CycleClassRemovingTransformer.java │ │ │ │ │ │ ├── DeadCodeRemovingTransformer.java │ │ │ │ │ │ ├── DuplicateAnnotationRemovingTransformer.java │ │ │ │ │ │ ├── DuplicateCatchMergingTransformer.java │ │ │ │ │ │ ├── EnumNameRestorationTransformer.java │ │ │ │ │ │ ├── ExceptionCollectionTransformer.java │ │ │ │ │ │ ├── FrameRemovingTransformer.java │ │ │ │ │ │ ├── GotoInliningTransformer.java │ │ │ │ │ │ ├── IllegalAnnotationRemovingTransformer.java │ │ │ │ │ │ ├── IllegalNameMappingTransformer.java │ │ │ │ │ │ ├── IllegalSignatureRemovingTransformer.java │ │ │ │ │ │ ├── IllegalVarargsRemovingTransformer.java │ │ │ │ │ │ ├── KotlinMetadataCollectionTransformer.java │ │ │ │ │ │ ├── KotlinNameRestorationTransformer.java │ │ │ │ │ │ ├── LongAnnotationRemovingTransformer.java │ │ │ │ │ │ ├── LongExceptionRemovingTransformer.java │ │ │ │ │ │ ├── OpaqueConstantFoldingTransformer.java │ │ │ │ │ │ ├── OpaquePredicateFoldingTransformer.java │ │ │ │ │ │ ├── RedundantTryCatchRemovingTransformer.java │ │ │ │ │ │ ├── SourceNameRestorationTransformer.java │ │ │ │ │ │ ├── StaticValueCollectionTransformer.java │ │ │ │ │ │ ├── StaticValueInliningTransformer.java │ │ │ │ │ │ ├── UnknownAttributeRemovingTransformer.java │ │ │ │ │ │ ├── VariableFoldingTransformer.java │ │ │ │ │ │ └── VariableTableNormalizingTransformer.java │ │ │ │ │ └── specific/ │ │ │ │ │ └── DashOpaqueSeedFoldingTransformer.java │ │ │ │ ├── file/ │ │ │ │ │ └── RecafDirectoriesConfig.java │ │ │ │ ├── inheritance/ │ │ │ │ │ ├── ClassPathNodeProvider.java │ │ │ │ │ ├── InheritanceGraph.java │ │ │ │ │ ├── InheritanceGraphService.java │ │ │ │ │ ├── InheritanceGraphServiceConfig.java │ │ │ │ │ └── InheritanceVertex.java │ │ │ │ ├── json/ │ │ │ │ │ ├── GsonProvider.java │ │ │ │ │ └── GsonProviderConfig.java │ │ │ │ ├── mapping/ │ │ │ │ │ ├── BasicMappingsRemapper.java │ │ │ │ │ ├── IntermediateMappings.java │ │ │ │ │ ├── MappingApplicationListener.java │ │ │ │ │ ├── MappingApplier.java │ │ │ │ │ ├── MappingApplierConfig.java │ │ │ │ │ ├── MappingApplierService.java │ │ │ │ │ ├── MappingListeners.java │ │ │ │ │ ├── MappingListenersConfig.java │ │ │ │ │ ├── MappingResults.java │ │ │ │ │ ├── Mappings.java │ │ │ │ │ ├── MappingsAdapter.java │ │ │ │ │ ├── UniqueKeyMappings.java │ │ │ │ │ ├── WorkspaceBackedRemapper.java │ │ │ │ │ ├── WorkspaceClassRemapper.java │ │ │ │ │ ├── aggregate/ │ │ │ │ │ │ ├── AggregateMappingManager.java │ │ │ │ │ │ ├── AggregateMappingManagerConfig.java │ │ │ │ │ │ ├── AggregatedMappings.java │ │ │ │ │ │ └── AggregatedMappingsListener.java │ │ │ │ │ ├── data/ │ │ │ │ │ │ ├── AbstractMappingKey.java │ │ │ │ │ │ ├── ClassMapping.java │ │ │ │ │ │ ├── ClassMappingKey.java │ │ │ │ │ │ ├── FieldMapping.java │ │ │ │ │ │ ├── FieldMappingKey.java │ │ │ │ │ │ ├── MappingKey.java │ │ │ │ │ │ ├── MemberMapping.java │ │ │ │ │ │ ├── MethodMapping.java │ │ │ │ │ │ ├── MethodMappingKey.java │ │ │ │ │ │ ├── VariableMapping.java │ │ │ │ │ │ └── VariableMappingKey.java │ │ │ │ │ ├── format/ │ │ │ │ │ │ ├── AbstractMappingFileFormat.java │ │ │ │ │ │ ├── EnigmaMappings.java │ │ │ │ │ │ ├── InvalidMappingException.java │ │ │ │ │ │ ├── JadxMappings.java │ │ │ │ │ │ ├── MappingFileFormat.java │ │ │ │ │ │ ├── MappingFormatManager.java │ │ │ │ │ │ ├── MappingFormatManagerConfig.java │ │ │ │ │ │ ├── MappingTreeReader.java │ │ │ │ │ │ ├── ProguardMappings.java │ │ │ │ │ │ ├── SimpleMappings.java │ │ │ │ │ │ ├── SrgMappings.java │ │ │ │ │ │ ├── TinyV1Mappings.java │ │ │ │ │ │ └── TinyV2Mappings.java │ │ │ │ │ └── gen/ │ │ │ │ │ ├── MappingGenerator.java │ │ │ │ │ ├── MappingGeneratorConfig.java │ │ │ │ │ ├── filter/ │ │ │ │ │ │ ├── ExcludeClassesFilter.java │ │ │ │ │ │ ├── ExcludeEnumMethodsFilter.java │ │ │ │ │ │ ├── ExcludeExistingMappedFilter.java │ │ │ │ │ │ ├── ExcludeModifiersNameFilter.java │ │ │ │ │ │ ├── ExcludeNameFilter.java │ │ │ │ │ │ ├── IncludeClassesFilter.java │ │ │ │ │ │ ├── IncludeKeywordNameFilter.java │ │ │ │ │ │ ├── IncludeLongNameFilter.java │ │ │ │ │ │ ├── IncludeModifiersNameFilter.java │ │ │ │ │ │ ├── IncludeNameFilter.java │ │ │ │ │ │ ├── IncludeNonAsciiNameFilter.java │ │ │ │ │ │ ├── IncludeNonJavaIdentifierNameFilter.java │ │ │ │ │ │ ├── IncludeWhitespaceNameFilter.java │ │ │ │ │ │ └── NameGeneratorFilter.java │ │ │ │ │ └── naming/ │ │ │ │ │ ├── AbstractNameGeneratorProvider.java │ │ │ │ │ ├── AlphabetNameGenerator.java │ │ │ │ │ ├── AlphabetNameGeneratorProvider.java │ │ │ │ │ ├── DeconflictingNameGenerator.java │ │ │ │ │ ├── IncrementingNameGenerator.java │ │ │ │ │ ├── IncrementingNameGeneratorProvider.java │ │ │ │ │ ├── NameGenerator.java │ │ │ │ │ ├── NameGeneratorProvider.java │ │ │ │ │ ├── NameGeneratorProviders.java │ │ │ │ │ └── NameGeneratorProvidersConfig.java │ │ │ │ ├── phantom/ │ │ │ │ │ ├── GeneratedPhantomWorkspaceResource.java │ │ │ │ │ ├── JPhantomGenerator.java │ │ │ │ │ ├── JPhantomGeneratorConfig.java │ │ │ │ │ ├── PhantomGenerationException.java │ │ │ │ │ └── PhantomGenerator.java │ │ │ │ ├── plugin/ │ │ │ │ │ ├── AllocationException.java │ │ │ │ │ ├── BasicPluginManager.java │ │ │ │ │ ├── CdiClassAllocator.java │ │ │ │ │ ├── ClassAllocator.java │ │ │ │ │ ├── LoadedPlugin.java │ │ │ │ │ ├── PluginClassLoader.java │ │ │ │ │ ├── PluginClassLoaderImpl.java │ │ │ │ │ ├── PluginContainer.java │ │ │ │ │ ├── PluginContainerImpl.java │ │ │ │ │ ├── PluginException.java │ │ │ │ │ ├── PluginGraph.java │ │ │ │ │ ├── PluginId.java │ │ │ │ │ ├── PluginInfo.java │ │ │ │ │ ├── PluginLoader.java │ │ │ │ │ ├── PluginManager.java │ │ │ │ │ ├── PluginManagerConfig.java │ │ │ │ │ ├── PluginSource.java │ │ │ │ │ ├── PluginUnloader.java │ │ │ │ │ ├── PreparedPlugin.java │ │ │ │ │ ├── discovery/ │ │ │ │ │ │ ├── DirectoryPluginDiscoverer.java │ │ │ │ │ │ ├── DiscoveredPluginSource.java │ │ │ │ │ │ ├── PathPluginDiscoverer.java │ │ │ │ │ │ └── PluginDiscoverer.java │ │ │ │ │ └── zip/ │ │ │ │ │ ├── ZipArchiveView.java │ │ │ │ │ ├── ZipPluginLoader.java │ │ │ │ │ ├── ZipPreparedPlugin.java │ │ │ │ │ └── ZipSource.java │ │ │ │ ├── script/ │ │ │ │ │ ├── GenerateResult.java │ │ │ │ │ ├── JavacScriptEngine.java │ │ │ │ │ ├── ScriptEngine.java │ │ │ │ │ ├── ScriptEngineConfig.java │ │ │ │ │ ├── ScriptFile.java │ │ │ │ │ ├── ScriptManager.java │ │ │ │ │ ├── ScriptManagerConfig.java │ │ │ │ │ └── ScriptResult.java │ │ │ │ ├── search/ │ │ │ │ │ ├── AndroidClassSearchVisitor.java │ │ │ │ │ ├── CancellableSearchFeedback.java │ │ │ │ │ ├── FileSearchVisitor.java │ │ │ │ │ ├── JvmClassSearchVisitor.java │ │ │ │ │ ├── ResultSink.java │ │ │ │ │ ├── SearchFeedback.java │ │ │ │ │ ├── SearchService.java │ │ │ │ │ ├── SearchServiceConfig.java │ │ │ │ │ ├── SearchVisitor.java │ │ │ │ │ ├── match/ │ │ │ │ │ │ ├── BiNumberMatcher.java │ │ │ │ │ │ ├── BiStringMatcher.java │ │ │ │ │ │ ├── MultiNumberMatcher.java │ │ │ │ │ │ ├── MultiStringMatcher.java │ │ │ │ │ │ ├── NumberPredicate.java │ │ │ │ │ │ ├── NumberPredicateProvider.java │ │ │ │ │ │ ├── RangeNumberMatcher.java │ │ │ │ │ │ ├── StringPredicate.java │ │ │ │ │ │ └── StringPredicateProvider.java │ │ │ │ │ ├── query/ │ │ │ │ │ │ ├── AbstractValueQuery.java │ │ │ │ │ │ ├── AndroidClassQuery.java │ │ │ │ │ │ ├── DeclarationQuery.java │ │ │ │ │ │ ├── FileQuery.java │ │ │ │ │ │ ├── InstructionQuery.java │ │ │ │ │ │ ├── JvmClassQuery.java │ │ │ │ │ │ ├── NumberQuery.java │ │ │ │ │ │ ├── Query.java │ │ │ │ │ │ ├── ReferenceQuery.java │ │ │ │ │ │ └── StringQuery.java │ │ │ │ │ └── result/ │ │ │ │ │ ├── ClassReference.java │ │ │ │ │ ├── ClassReferenceResult.java │ │ │ │ │ ├── MemberReference.java │ │ │ │ │ ├── MemberReferenceResult.java │ │ │ │ │ ├── NumberResult.java │ │ │ │ │ ├── Result.java │ │ │ │ │ ├── Results.java │ │ │ │ │ └── StringResult.java │ │ │ │ ├── source/ │ │ │ │ │ ├── AstMapper.java │ │ │ │ │ ├── AstResolveResult.java │ │ │ │ │ ├── AstService.java │ │ │ │ │ ├── AstServiceConfig.java │ │ │ │ │ └── ResolverAdapter.java │ │ │ │ ├── text/ │ │ │ │ │ └── TextFormatConfig.java │ │ │ │ ├── transform/ │ │ │ │ │ ├── CancellableTransformationFeedback.java │ │ │ │ │ ├── ClassTransformer.java │ │ │ │ │ ├── JvmClassTransformer.java │ │ │ │ │ ├── JvmTransformResult.java │ │ │ │ │ ├── JvmTransformerContext.java │ │ │ │ │ ├── TransformResult.java │ │ │ │ │ ├── TransformationApplier.java │ │ │ │ │ ├── TransformationApplierConfig.java │ │ │ │ │ ├── TransformationApplierService.java │ │ │ │ │ ├── TransformationException.java │ │ │ │ │ ├── TransformationFeedback.java │ │ │ │ │ ├── TransformationManager.java │ │ │ │ │ └── TransformationManagerConfig.java │ │ │ │ ├── tutorial/ │ │ │ │ │ ├── TutorialConfig.java │ │ │ │ │ ├── TutorialWorkspace.java │ │ │ │ │ └── TutorialWorkspaceResource.java │ │ │ │ └── workspace/ │ │ │ │ ├── BasicWorkspaceManager.java │ │ │ │ ├── WorkspaceCloseCondition.java │ │ │ │ ├── WorkspaceCloseListener.java │ │ │ │ ├── WorkspaceManager.java │ │ │ │ ├── WorkspaceManagerConfig.java │ │ │ │ ├── WorkspaceOpenListener.java │ │ │ │ ├── WorkspaceProcessingConfig.java │ │ │ │ ├── WorkspaceProcessingService.java │ │ │ │ ├── WorkspaceProcessor.java │ │ │ │ ├── io/ │ │ │ │ │ ├── BasicClassPatcher.java │ │ │ │ │ ├── BasicInfoImporter.java │ │ │ │ │ ├── BasicResourceImporter.java │ │ │ │ │ ├── ByteArrayWorkspaceExportConsumer.java │ │ │ │ │ ├── ClassPatcher.java │ │ │ │ │ ├── InfoImporter.java │ │ │ │ │ ├── InfoImporterConfig.java │ │ │ │ │ ├── PathWorkspaceExportConsumer.java │ │ │ │ │ ├── ResourceImporter.java │ │ │ │ │ ├── ResourceImporterConfig.java │ │ │ │ │ ├── WorkspaceCompressType.java │ │ │ │ │ ├── WorkspaceExportConsumer.java │ │ │ │ │ ├── WorkspaceExportOptions.java │ │ │ │ │ ├── WorkspaceExporter.java │ │ │ │ │ └── WorkspaceOutputType.java │ │ │ │ ├── patch/ │ │ │ │ │ ├── PatchApplier.java │ │ │ │ │ ├── PatchFeedback.java │ │ │ │ │ ├── PatchGenerationException.java │ │ │ │ │ ├── PatchProvider.java │ │ │ │ │ ├── PatchSerialization.java │ │ │ │ │ ├── ResourcePatchApplierConfig.java │ │ │ │ │ ├── ResourcePatchProviderConfig.java │ │ │ │ │ └── model/ │ │ │ │ │ ├── JvmAssemblerPatch.java │ │ │ │ │ ├── RemovePath.java │ │ │ │ │ ├── TextFilePatch.java │ │ │ │ │ └── WorkspacePatch.java │ │ │ │ └── processors/ │ │ │ │ └── ThrowablePropertyAssigningProcessor.java │ │ │ ├── util/ │ │ │ │ ├── AccessFlag.java │ │ │ │ ├── AccessPatcher.java │ │ │ │ ├── AsmInsnUtil.java │ │ │ │ ├── BlwUtil.java │ │ │ │ ├── ByteHeaderUtil.java │ │ │ │ ├── CancelSignal.java │ │ │ │ ├── ClassDefiner.java │ │ │ │ ├── ClassLoaderInternals.java │ │ │ │ ├── ClasspathUtil.java │ │ │ │ ├── CollectionUtils.java │ │ │ │ ├── DesktopUtil.java │ │ │ │ ├── DevDetection.java │ │ │ │ ├── EscapeUtil.java │ │ │ │ ├── ExcludeFromJacocoGeneratedReport.java │ │ │ │ ├── Handles.java │ │ │ │ ├── IOUtil.java │ │ │ │ ├── InternalPath.java │ │ │ │ ├── JavaDowngraderUtil.java │ │ │ │ ├── JavaVersion.java │ │ │ │ ├── JdkValidation.java │ │ │ │ ├── Keywords.java │ │ │ │ ├── MemoizedFunctions.java │ │ │ │ ├── ModulesIOUtil.java │ │ │ │ ├── MultiMap.java │ │ │ │ ├── MultiMapBuilder.java │ │ │ │ ├── NumberUtil.java │ │ │ │ ├── PlatformType.java │ │ │ │ ├── ReflectUtil.java │ │ │ │ ├── RegexUtil.java │ │ │ │ ├── ResourceUtil.java │ │ │ │ ├── SelfReferenceUtil.java │ │ │ │ ├── ShortcutUtil.java │ │ │ │ ├── Streams.java │ │ │ │ ├── StringDecodingResult.java │ │ │ │ ├── StringDiff.java │ │ │ │ ├── StringUtil.java │ │ │ │ ├── TestEnvironment.java │ │ │ │ ├── Types.java │ │ │ │ ├── UnsafeIO.java │ │ │ │ ├── UnsafeUtil.java │ │ │ │ ├── ZipCreationUtils.java │ │ │ │ ├── analysis/ │ │ │ │ │ ├── Branching.java │ │ │ │ │ ├── Nullness.java │ │ │ │ │ ├── ReAnalyzer.java │ │ │ │ │ ├── ReFrame.java │ │ │ │ │ ├── ReInterpreter.java │ │ │ │ │ ├── eval/ │ │ │ │ │ │ ├── EvaluationException.java │ │ │ │ │ │ ├── EvaluationFailureResult.java │ │ │ │ │ │ ├── EvaluationResult.java │ │ │ │ │ │ ├── EvaluationThrowsResult.java │ │ │ │ │ │ ├── EvaluationYieldResult.java │ │ │ │ │ │ ├── Evaluator.java │ │ │ │ │ │ ├── FieldCache.java │ │ │ │ │ │ ├── FieldCacheManager.java │ │ │ │ │ │ ├── InstanceFactory.java │ │ │ │ │ │ ├── InstanceMapper.java │ │ │ │ │ │ ├── InstancedObjectValue.java │ │ │ │ │ │ └── MethodInvokeHandler.java │ │ │ │ │ ├── gen/ │ │ │ │ │ │ ├── GenUtils.java │ │ │ │ │ │ ├── InstanceMapperGenerator.java │ │ │ │ │ │ ├── InstanceMethodInvokeHandlerGenerator.java │ │ │ │ │ │ ├── InstanceStaticMapperGenerator.java │ │ │ │ │ │ └── LookupGenerator.java │ │ │ │ │ ├── lookup/ │ │ │ │ │ │ ├── BasicGetStaticLookup.java │ │ │ │ │ │ ├── BasicInvokeStaticLookup.java │ │ │ │ │ │ ├── BasicInvokeVirtualLookup.java │ │ │ │ │ │ ├── BasicLookupUtils.java │ │ │ │ │ │ ├── GetFieldLookup.java │ │ │ │ │ │ ├── GetStaticLookup.java │ │ │ │ │ │ ├── InvokeStaticLookup.java │ │ │ │ │ │ └── InvokeVirtualLookup.java │ │ │ │ │ └── value/ │ │ │ │ │ ├── ArrayValue.java │ │ │ │ │ ├── DoubleValue.java │ │ │ │ │ ├── FloatValue.java │ │ │ │ │ ├── IllegalValueException.java │ │ │ │ │ ├── IntValue.java │ │ │ │ │ ├── LongValue.java │ │ │ │ │ ├── ObjectValue.java │ │ │ │ │ ├── ReValue.java │ │ │ │ │ ├── StringValue.java │ │ │ │ │ ├── UninitializedValue.java │ │ │ │ │ └── impl/ │ │ │ │ │ ├── ArrayValueImpl.java │ │ │ │ │ ├── BoxedBooleanValueImpl.java │ │ │ │ │ ├── BoxedByteValueImpl.java │ │ │ │ │ ├── BoxedCharacterValueImpl.java │ │ │ │ │ ├── BoxedDoubleValueImpl.java │ │ │ │ │ ├── BoxedFloatValueImpl.java │ │ │ │ │ ├── BoxedIntegerValueImpl.java │ │ │ │ │ ├── BoxedLongValueImpl.java │ │ │ │ │ ├── BoxedShortValueImpl.java │ │ │ │ │ ├── DoubleValueImpl.java │ │ │ │ │ ├── FloatValueImpl.java │ │ │ │ │ ├── IntValueImpl.java │ │ │ │ │ ├── LongValueImpl.java │ │ │ │ │ ├── ObjectValueBoxImpl.java │ │ │ │ │ ├── ObjectValueImpl.java │ │ │ │ │ ├── StringValueImpl.java │ │ │ │ │ └── UninitializedValueImpl.java │ │ │ │ ├── android/ │ │ │ │ │ ├── AndroidRes.java │ │ │ │ │ ├── AndroidXmlUtil.java │ │ │ │ │ └── DexIOUtil.java │ │ │ │ ├── io/ │ │ │ │ │ ├── ByteArraySource.java │ │ │ │ │ ├── ByteBufferSource.java │ │ │ │ │ ├── ByteSource.java │ │ │ │ │ ├── ByteSourceConsumer.java │ │ │ │ │ ├── ByteSourceElement.java │ │ │ │ │ ├── ByteSources.java │ │ │ │ │ ├── LocalFileHeaderSource.java │ │ │ │ │ ├── MemorySegmentDataSource.java │ │ │ │ │ └── PathByteSource.java │ │ │ │ ├── kotlin/ │ │ │ │ │ ├── KotlinMetadata.java │ │ │ │ │ └── model/ │ │ │ │ │ ├── KtClass.java │ │ │ │ │ ├── KtClassKind.java │ │ │ │ │ ├── KtConstructor.java │ │ │ │ │ ├── KtElement.java │ │ │ │ │ ├── KtFunction.java │ │ │ │ │ ├── KtNullability.java │ │ │ │ │ ├── KtParameter.java │ │ │ │ │ ├── KtProperty.java │ │ │ │ │ ├── KtType.java │ │ │ │ │ └── KtVariable.java │ │ │ │ ├── threading/ │ │ │ │ │ ├── Batch.java │ │ │ │ │ ├── CountDown.java │ │ │ │ │ ├── DirectBatch.java │ │ │ │ │ ├── ExecutorServiceDelegate.java │ │ │ │ │ ├── PhasingExecutorService.java │ │ │ │ │ ├── ScheduledExecutorServiceDelegate.java │ │ │ │ │ ├── ThreadPoolFactory.java │ │ │ │ │ └── ThreadUtil.java │ │ │ │ └── visitors/ │ │ │ │ ├── AnnotationArrayVisitor.java │ │ │ │ ├── BogusNameRemovingVisitor.java │ │ │ │ ├── ClassAnnotationInsertingVisitor.java │ │ │ │ ├── ClassAnnotationRemovingVisitor.java │ │ │ │ ├── ClassHollowingVisitor.java │ │ │ │ ├── DuplicateAnnotationRemovingVisitor.java │ │ │ │ ├── FieldAnnotationInsertingVisitor.java │ │ │ │ ├── FieldAnnotationRemovingVisitor.java │ │ │ │ ├── FieldInsertingVisitor.java │ │ │ │ ├── FieldPredicate.java │ │ │ │ ├── FieldReplacingVisitor.java │ │ │ │ ├── FrameSkippingVisitor.java │ │ │ │ ├── IllegalAnnotationRemovingVisitor.java │ │ │ │ ├── IllegalSignatureRemovingVisitor.java │ │ │ │ ├── IllegalVarargsRemovingVisitor.java │ │ │ │ ├── IndexCountingMethodVisitor.java │ │ │ │ ├── KotlinMetadataVisitor.java │ │ │ │ ├── LongAnnotationRemovingVisitor.java │ │ │ │ ├── LongExceptionRemovingVisitor.java │ │ │ │ ├── MemberCopyingVisitor.java │ │ │ │ ├── MemberFilteringVisitor.java │ │ │ │ ├── MemberPredicate.java │ │ │ │ ├── MemberRemovingVisitor.java │ │ │ │ ├── MemberStubAddingVisitor.java │ │ │ │ ├── MethodAnnotationInsertingVisitor.java │ │ │ │ ├── MethodAnnotationRemovingVisitor.java │ │ │ │ ├── MethodInsertingVisitor.java │ │ │ │ ├── MethodNoopingVisitor.java │ │ │ │ ├── MethodPredicate.java │ │ │ │ ├── MethodReplacingVisitor.java │ │ │ │ ├── MethodVariableRemovingVisitor.java │ │ │ │ ├── SignatureRemovingVisitor.java │ │ │ │ ├── SkippingAnnotationVisitor.java │ │ │ │ ├── SkippingClassVisitor.java │ │ │ │ ├── SkippingFieldVisitor.java │ │ │ │ ├── SkippingMethodVisitor.java │ │ │ │ ├── SyntheticRemovingVisitor.java │ │ │ │ ├── TypeVisitor.java │ │ │ │ ├── UnknownAttributeRemovingVisitor.java │ │ │ │ ├── VariableRemovingClassVisitor.java │ │ │ │ ├── VariableRemovingMethodVisitor.java │ │ │ │ └── WorkspaceClassWriter.java │ │ │ └── workspace/ │ │ │ └── model/ │ │ │ ├── BasicWorkspace.java │ │ │ ├── EmptyWorkspace.java │ │ │ ├── Workspace.java │ │ │ ├── WorkspaceModificationListener.java │ │ │ ├── bundle/ │ │ │ │ ├── AndroidClassBundle.java │ │ │ │ ├── BasicAndroidClassBundle.java │ │ │ │ ├── BasicBundle.java │ │ │ │ ├── BasicFileBundle.java │ │ │ │ ├── BasicJvmClassBundle.java │ │ │ │ ├── BasicVersionedJvmClassBundle.java │ │ │ │ ├── Bundle.java │ │ │ │ ├── BundleListener.java │ │ │ │ ├── ClassBundle.java │ │ │ │ ├── FileBundle.java │ │ │ │ ├── JvmClassBundle.java │ │ │ │ └── VersionedJvmClassBundle.java │ │ │ └── resource/ │ │ │ ├── AgentServerRemoteVmResource.java │ │ │ ├── AndroidApiResource.java │ │ │ ├── BasicWorkspaceDirectoryResource.java │ │ │ ├── BasicWorkspaceFileResource.java │ │ │ ├── BasicWorkspaceResource.java │ │ │ ├── ResourceAndroidClassListener.java │ │ │ ├── ResourceFileListener.java │ │ │ ├── ResourceJvmClassListener.java │ │ │ ├── RuntimeWorkspaceResource.java │ │ │ ├── WorkspaceDirectoryResource.java │ │ │ ├── WorkspaceDirectoryResourceBuilder.java │ │ │ ├── WorkspaceFileResource.java │ │ │ ├── WorkspaceFileResourceBuilder.java │ │ │ ├── WorkspaceRemoteVmResource.java │ │ │ ├── WorkspaceResource.java │ │ │ └── WorkspaceResourceBuilder.java │ │ └── resources/ │ │ ├── android/ │ │ │ ├── api-outline-30.jar │ │ │ ├── attrs.json │ │ │ └── res-map.txt │ │ └── logback.xml │ ├── test/ │ │ ├── java/ │ │ │ └── software/ │ │ │ └── coley/ │ │ │ └── recaf/ │ │ │ ├── BootstrapTest.java │ │ │ ├── info/ │ │ │ │ ├── ClassInfoTest.java │ │ │ │ ├── JvmClassInfoTest.java │ │ │ │ ├── annotation/ │ │ │ │ │ ├── AnnotatedTest.java │ │ │ │ │ ├── AnnotationInfoTest.java │ │ │ │ │ └── TypeAnnotationInfoTest.java │ │ │ │ └── member/ │ │ │ │ ├── FieldMemberTest.java │ │ │ │ └── MethodMemberTest.java │ │ │ ├── path/ │ │ │ │ └── PathNodeTest.java │ │ │ ├── services/ │ │ │ │ ├── assembler/ │ │ │ │ │ └── ExpressionCompilerTest.java │ │ │ │ ├── callgraph/ │ │ │ │ │ └── CallGraphTest.java │ │ │ │ ├── comment/ │ │ │ │ │ └── CommentManagerTest.java │ │ │ │ ├── compile/ │ │ │ │ │ └── JavacCompilerTest.java │ │ │ │ ├── decompile/ │ │ │ │ │ ├── DecompileManagerTest.java │ │ │ │ │ └── FallbackDecompilerTest.java │ │ │ │ ├── deobfuscation/ │ │ │ │ │ ├── BaseDeobfuscationTest.java │ │ │ │ │ ├── CycleRemovingTest.java │ │ │ │ │ ├── EvaluatorTest.java │ │ │ │ │ ├── FoldingDeobfuscationTest.java │ │ │ │ │ ├── IllegalAttributeDeobfuscationTest.java │ │ │ │ │ ├── MiscDeobfuscationTest.java │ │ │ │ │ ├── RegressionDeobfuscationTest.java │ │ │ │ │ ├── StaticValueInliningTest.java │ │ │ │ │ └── TryCatchDeobfuscationTest.java │ │ │ │ ├── inheritance/ │ │ │ │ │ ├── InheritanceAndRenamingTest.java │ │ │ │ │ └── InheritanceGraphTest.java │ │ │ │ ├── json/ │ │ │ │ │ └── GsonProviderTest.java │ │ │ │ ├── mapping/ │ │ │ │ │ ├── MappingApplierTest.java │ │ │ │ │ ├── aggregate/ │ │ │ │ │ │ ├── AggregateMappingManagerTest.java │ │ │ │ │ │ └── AggregateMappingsTest.java │ │ │ │ │ ├── format/ │ │ │ │ │ │ ├── MappingImplementationTest.java │ │ │ │ │ │ └── MappingIntermediateTest.java │ │ │ │ │ └── gen/ │ │ │ │ │ └── MappingGeneratorTest.java │ │ │ │ ├── phantom/ │ │ │ │ │ └── PhantomGeneratorTest.java │ │ │ │ ├── plugin/ │ │ │ │ │ └── PluginManagerTest.java │ │ │ │ ├── script/ │ │ │ │ │ └── JavacScriptEngineTest.java │ │ │ │ ├── search/ │ │ │ │ │ └── SearchServiceTest.java │ │ │ │ ├── source/ │ │ │ │ │ └── AstServiceTest.java │ │ │ │ ├── transform/ │ │ │ │ │ ├── TransformationApplierTest.java │ │ │ │ │ └── TransformationManagerTest.java │ │ │ │ └── workspace/ │ │ │ │ ├── io/ │ │ │ │ │ ├── InfoImporterTest.java │ │ │ │ │ ├── ResourceImporterTest.java │ │ │ │ │ └── WorkspaceExporterTest.java │ │ │ │ └── patch/ │ │ │ │ └── PatchingTest.java │ │ │ ├── util/ │ │ │ │ ├── AccessFlagTest.java │ │ │ │ ├── AsmInsnUtilTest.java │ │ │ │ ├── EscapeUtilTest.java │ │ │ │ ├── NumberUtilTest.java │ │ │ │ ├── StringDiffTest.java │ │ │ │ ├── StringUtilTest.java │ │ │ │ ├── TypesTest.java │ │ │ │ └── android/ │ │ │ │ └── AndroidResConversion.java │ │ │ └── workspace/ │ │ │ └── model/ │ │ │ └── WorkspaceModelTest.java │ │ └── resources/ │ │ └── android/ │ │ ├── attrs.xml │ │ └── attrs_manifest.xml │ └── testFixtures/ │ ├── java/ │ │ └── software/ │ │ └── coley/ │ │ └── recaf/ │ │ └── test/ │ │ ├── TestBase.java │ │ ├── TestClassUtils.java │ │ ├── TestConfigSetup.java │ │ └── dummy/ │ │ ├── AccessibleFields.java │ │ ├── AccessibleMethods.java │ │ ├── AccessibleMethodsChild.java │ │ ├── AnnotationImpl.java │ │ ├── AnonymousLambda.java │ │ ├── ArrayTypeAnno.java │ │ ├── ClassWithAnnotation.java │ │ ├── ClassWithAnonymousInner.java │ │ ├── ClassWithConstructor.java │ │ ├── ClassWithEmbeddedInners.java │ │ ├── ClassWithExceptions.java │ │ ├── ClassWithFieldsAndMethods.java │ │ ├── ClassWithInner.java │ │ ├── ClassWithInnerAndMembers.java │ │ ├── ClassWithInvisAnnotation.java │ │ ├── ClassWithLambda.java │ │ ├── ClassWithMethodReference.java │ │ ├── ClassWithMultipleMethods.java │ │ ├── ClassWithRequiredConstructor.java │ │ ├── ClassWithStaticInit.java │ │ ├── ClassWithToString.java │ │ ├── DiamondA.java │ │ ├── DiamondB.java │ │ ├── DiamondC.java │ │ ├── DummyEmptyMap.java │ │ ├── DummyEnum.java │ │ ├── DummyEnumPrinter.java │ │ ├── DummyRecord.java │ │ ├── HelloWorld.java │ │ ├── Inheritance.java │ │ ├── InvisAnnotationImpl.java │ │ ├── MethodWithTypeAnno.java │ │ ├── MultipleInterfacesClass.java │ │ ├── OverlapCaller.java │ │ ├── OverlapClassAB.java │ │ ├── OverlapInterfaceA.java │ │ ├── OverlapInterfaceB.java │ │ ├── SealedCircle.java │ │ ├── SealedOtherShape.java │ │ ├── SealedShape.java │ │ ├── SealedSquare.java │ │ ├── StringConsumer.java │ │ ├── StringConsumerUser.java │ │ ├── StringList.java │ │ ├── StringListUser.java │ │ ├── StringSupplier.java │ │ ├── TypeAnnotationImpl.java │ │ ├── VariedModifierFields.java │ │ └── VariedModifierMethods.java │ └── resources/ │ ├── lorem-long-ascii.txt │ ├── lorem-long-cn.txt │ ├── lorem-long-ru.txt │ ├── lorem-short-ascii.txt │ ├── lorem-short-cn.txt │ ├── lorem-short-ru.txt │ └── name-prefix-suffix.jar ├── recaf-ui/ │ ├── build.gradle │ └── src/ │ ├── main/ │ │ ├── java/ │ │ │ └── software/ │ │ │ └── coley/ │ │ │ └── recaf/ │ │ │ ├── Main.java │ │ │ ├── RecafApplication.java │ │ │ ├── path/ │ │ │ │ ├── AssemblerPathData.java │ │ │ │ └── AssemblerPathNode.java │ │ │ ├── services/ │ │ │ │ ├── cell/ │ │ │ │ │ ├── CellConfigurationService.java │ │ │ │ │ ├── CellConfigurationServiceConfig.java │ │ │ │ │ ├── context/ │ │ │ │ │ │ ├── AbstractContextMenuProviderFactory.java │ │ │ │ │ │ ├── AnnotationContextMenuAdapter.java │ │ │ │ │ │ ├── AnnotationContextMenuProviderFactory.java │ │ │ │ │ │ ├── AssemblerContextMenuAdapter.java │ │ │ │ │ │ ├── AssemblerContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicAnnotationContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicAssemblerContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicBlacklistingContextSource.java │ │ │ │ │ │ ├── BasicBundleContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicClassContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicContextSource.java │ │ │ │ │ │ ├── BasicDirectoryContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicFieldContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicFileContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicInnerClassContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicMethodContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicPackageContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicResourceContextMenuProviderFactory.java │ │ │ │ │ │ ├── BasicWhitelistingContextSource.java │ │ │ │ │ │ ├── BundleContextMenuAdapter.java │ │ │ │ │ │ ├── BundleContextMenuProviderFactory.java │ │ │ │ │ │ ├── ClassContextMenuAdapter.java │ │ │ │ │ │ ├── ClassContextMenuProviderFactory.java │ │ │ │ │ │ ├── ContextMenuAdapter.java │ │ │ │ │ │ ├── ContextMenuProvider.java │ │ │ │ │ │ ├── ContextMenuProviderFactory.java │ │ │ │ │ │ ├── ContextMenuProviderService.java │ │ │ │ │ │ ├── ContextMenuProviderServiceConfig.java │ │ │ │ │ │ ├── ContextSource.java │ │ │ │ │ │ ├── DirectoryContextMenuAdapter.java │ │ │ │ │ │ ├── DirectoryContextMenuProviderFactory.java │ │ │ │ │ │ ├── FieldContextMenuAdapter.java │ │ │ │ │ │ ├── FieldContextMenuProviderFactory.java │ │ │ │ │ │ ├── FileContextMenuAdapter.java │ │ │ │ │ │ ├── FileContextMenuProviderFactory.java │ │ │ │ │ │ ├── InnerClassContextMenuAdapter.java │ │ │ │ │ │ ├── InnerClassContextMenuProviderFactory.java │ │ │ │ │ │ ├── MethodContextMenuAdapter.java │ │ │ │ │ │ ├── MethodContextMenuProviderFactory.java │ │ │ │ │ │ ├── PackageContextMenuAdapter.java │ │ │ │ │ │ ├── PackageContextMenuProviderFactory.java │ │ │ │ │ │ ├── ResourceContextMenuAdapter.java │ │ │ │ │ │ └── ResourceContextMenuProviderFactory.java │ │ │ │ │ ├── icon/ │ │ │ │ │ │ ├── AnnotationIconProviderFactory.java │ │ │ │ │ │ ├── BasicAnnotationIconProviderFactory.java │ │ │ │ │ │ ├── BasicBundleIconProviderFactory.java │ │ │ │ │ │ ├── BasicCatchIconProviderFactory.java │ │ │ │ │ │ ├── BasicClassIconProviderFactory.java │ │ │ │ │ │ ├── BasicDirectoryIconProviderFactory.java │ │ │ │ │ │ ├── BasicFieldIconProviderFactory.java │ │ │ │ │ │ ├── BasicFileIconProviderFactory.java │ │ │ │ │ │ ├── BasicInnerClassIconProviderFactory.java │ │ │ │ │ │ ├── BasicInstructionIconProviderFactory.java │ │ │ │ │ │ ├── BasicMethodIconProviderFactory.java │ │ │ │ │ │ ├── BasicPackageIconProviderFactory.java │ │ │ │ │ │ ├── BasicResourceIconProviderFactory.java │ │ │ │ │ │ ├── BasicThrowsProviderFactory.java │ │ │ │ │ │ ├── BasicVariableIconProviderFactory.java │ │ │ │ │ │ ├── BundleIconProviderFactory.java │ │ │ │ │ │ ├── CatchIconProviderFactory.java │ │ │ │ │ │ ├── ClassIconProviderFactory.java │ │ │ │ │ │ ├── DirectoryIconProviderFactory.java │ │ │ │ │ │ ├── FieldIconProviderFactory.java │ │ │ │ │ │ ├── FileIconProviderFactory.java │ │ │ │ │ │ ├── IconProvider.java │ │ │ │ │ │ ├── IconProviderFactory.java │ │ │ │ │ │ ├── IconProviderService.java │ │ │ │ │ │ ├── IconProviderServiceConfig.java │ │ │ │ │ │ ├── InnerClassIconProviderFactory.java │ │ │ │ │ │ ├── InstructionIconProviderFactory.java │ │ │ │ │ │ ├── MethodIconProviderFactory.java │ │ │ │ │ │ ├── PackageIconProviderFactory.java │ │ │ │ │ │ ├── ResourceIconProviderFactory.java │ │ │ │ │ │ ├── ThrowsIconProviderFactory.java │ │ │ │ │ │ └── VariableIconProviderFactory.java │ │ │ │ │ └── text/ │ │ │ │ │ ├── TextProvider.java │ │ │ │ │ ├── TextProviderFactory.java │ │ │ │ │ ├── TextProviderService.java │ │ │ │ │ └── TextProviderServiceConfig.java │ │ │ │ ├── config/ │ │ │ │ │ ├── ConfigComponentFactory.java │ │ │ │ │ ├── ConfigComponentManager.java │ │ │ │ │ ├── ConfigComponentManagerConfig.java │ │ │ │ │ ├── ConfigIconManager.java │ │ │ │ │ ├── ConfigIconManagerConfig.java │ │ │ │ │ ├── KeyedConfigComponentFactory.java │ │ │ │ │ ├── TypedConfigComponentFactory.java │ │ │ │ │ └── factories/ │ │ │ │ │ ├── AndroidDecompilerComponentFactory.java │ │ │ │ │ ├── BooleanComponentFactory.java │ │ │ │ │ ├── EnumComponentFactory.java │ │ │ │ │ ├── IntegerComponentFactory.java │ │ │ │ │ ├── JvmDecompilerComponentFactory.java │ │ │ │ │ ├── ProcyonLanguageComponentFactory.java │ │ │ │ │ └── StringComponentFactory.java │ │ │ │ ├── info/ │ │ │ │ │ ├── association/ │ │ │ │ │ │ ├── FileTypeSyntaxAssociationService.java │ │ │ │ │ │ └── FileTypeSyntaxAssociationServiceConfig.java │ │ │ │ │ └── summary/ │ │ │ │ │ ├── ResourceSummarizer.java │ │ │ │ │ ├── ResourceSummaryService.java │ │ │ │ │ ├── ResourceSummaryServiceConfig.java │ │ │ │ │ ├── SummaryConsumer.java │ │ │ │ │ └── builtin/ │ │ │ │ │ ├── AntiDecompilationSummarizer.java │ │ │ │ │ ├── EntryPointSummarizer.java │ │ │ │ │ ├── HashSummarizer.java │ │ │ │ │ └── JarSigningSummarizer.java │ │ │ │ ├── mapping/ │ │ │ │ │ └── MappingHelper.java │ │ │ │ ├── navigation/ │ │ │ │ │ ├── Actions.java │ │ │ │ │ ├── ActionsConfig.java │ │ │ │ │ ├── ClassNavigable.java │ │ │ │ │ ├── FileNavigable.java │ │ │ │ │ ├── Navigable.java │ │ │ │ │ ├── NavigableAddListener.java │ │ │ │ │ ├── NavigableRemoveListener.java │ │ │ │ │ ├── NavigationManager.java │ │ │ │ │ ├── NavigationManagerConfig.java │ │ │ │ │ ├── UnsupportedContentException.java │ │ │ │ │ └── UpdatableNavigable.java │ │ │ │ ├── translation/ │ │ │ │ │ └── LangConfig.java │ │ │ │ ├── tutorial/ │ │ │ │ │ ├── TutorialWorkspaceBuilder.java │ │ │ │ │ └── content/ │ │ │ │ │ ├── Chapter1.java │ │ │ │ │ ├── Chapter2.java │ │ │ │ │ ├── Chapter3.java │ │ │ │ │ ├── Chapter4.java │ │ │ │ │ ├── Chapter5.java │ │ │ │ │ ├── Chapter6.java │ │ │ │ │ └── Chapter7.java │ │ │ │ └── window/ │ │ │ │ ├── WindowFactory.java │ │ │ │ ├── WindowFactoryConfig.java │ │ │ │ ├── WindowManager.java │ │ │ │ ├── WindowManagerConfig.java │ │ │ │ ├── WindowStyling.java │ │ │ │ └── WindowStylingConfig.java │ │ │ ├── ui/ │ │ │ │ ├── LanguageStylesheets.java │ │ │ │ ├── RecafTheme.java │ │ │ │ ├── config/ │ │ │ │ │ ├── Binding.java │ │ │ │ │ ├── BindingCreator.java │ │ │ │ │ ├── ClassEditingConfig.java │ │ │ │ │ ├── ExportConfig.java │ │ │ │ │ ├── KeybindingConfig.java │ │ │ │ │ ├── MemberDisplayFormatConfig.java │ │ │ │ │ ├── RecentFilesConfig.java │ │ │ │ │ ├── WindowScaleConfig.java │ │ │ │ │ └── WorkspaceExplorerConfig.java │ │ │ │ ├── contextmenu/ │ │ │ │ │ ├── AnnotationMenuBuilder.java │ │ │ │ │ ├── BundleMenuBuilder.java │ │ │ │ │ ├── ContextMenuBuilder.java │ │ │ │ │ ├── DirectoryMenuBuilder.java │ │ │ │ │ ├── InfoMenuBuilder.java │ │ │ │ │ ├── ItemSink.java │ │ │ │ │ ├── MemberMenuBuilder.java │ │ │ │ │ ├── MenuBuilder.java │ │ │ │ │ ├── MenuHandler.java │ │ │ │ │ ├── ResourceMenuBuilder.java │ │ │ │ │ ├── WorkspaceMenuBuilder.java │ │ │ │ │ └── actions/ │ │ │ │ │ ├── AnnotationAction.java │ │ │ │ │ ├── BundleAction.java │ │ │ │ │ ├── DirectoryAction.java │ │ │ │ │ ├── InfoAction.java │ │ │ │ │ ├── MemberAction.java │ │ │ │ │ ├── ResourceAction.java │ │ │ │ │ └── WorkspaceAction.java │ │ │ │ ├── control/ │ │ │ │ │ ├── AbstractSearchBar.java │ │ │ │ │ ├── ActionButton.java │ │ │ │ │ ├── ActionMenu.java │ │ │ │ │ ├── ActionMenuItem.java │ │ │ │ │ ├── AutoScrollPane.java │ │ │ │ │ ├── BoundBiDiComboBox.java │ │ │ │ │ ├── BoundCheckBox.java │ │ │ │ │ ├── BoundComboBox.java │ │ │ │ │ ├── BoundHyperlink.java │ │ │ │ │ ├── BoundIntSpinner.java │ │ │ │ │ ├── BoundLabel.java │ │ │ │ │ ├── BoundMultiToggleIcon.java │ │ │ │ │ ├── BoundTab.java │ │ │ │ │ ├── BoundTextField.java │ │ │ │ │ ├── BoundToggleIcon.java │ │ │ │ │ ├── ClosableActionMenuItem.java │ │ │ │ │ ├── DynamicNumericTextField.java │ │ │ │ │ ├── FontIconView.java │ │ │ │ │ ├── GraphicActionButton.java │ │ │ │ │ ├── IconView.java │ │ │ │ │ ├── ImageCanvas.java │ │ │ │ │ ├── ModalPaneComponent.java │ │ │ │ │ ├── ObservableCheckBox.java │ │ │ │ │ ├── ObservableComboBox.java │ │ │ │ │ ├── ObservableSpinner.java │ │ │ │ │ ├── PannableView.java │ │ │ │ │ ├── PathNodeTree.java │ │ │ │ │ ├── ReorderableListCell.java │ │ │ │ │ ├── ResizableCanvas.java │ │ │ │ │ ├── SubLabeled.java │ │ │ │ │ ├── Tooltipable.java │ │ │ │ │ ├── VirtualizedScrollPaneWrapper.java │ │ │ │ │ ├── graph/ │ │ │ │ │ │ ├── MethodCallGraphPane.java │ │ │ │ │ │ └── MethodCallGraphsPane.java │ │ │ │ │ ├── popup/ │ │ │ │ │ │ ├── AddMemberPopup.java │ │ │ │ │ │ ├── ChangeClassVersionPopup.java │ │ │ │ │ │ ├── ClassSelectionPopup.java │ │ │ │ │ │ ├── DecompileAllPopup.java │ │ │ │ │ │ ├── ItemListSelectionPopup.java │ │ │ │ │ │ ├── ItemTreeSelectionPopup.java │ │ │ │ │ │ ├── NamePopup.java │ │ │ │ │ │ ├── OpenUrlPopup.java │ │ │ │ │ │ ├── OverrideMethodPopup.java │ │ │ │ │ │ └── SelectionPopup.java │ │ │ │ │ ├── richtext/ │ │ │ │ │ │ ├── AbstractLineItemTracking.java │ │ │ │ │ │ ├── Editor.java │ │ │ │ │ │ ├── EditorComponent.java │ │ │ │ │ │ ├── SafeCodeArea.java │ │ │ │ │ │ ├── ScrollbarPaddingUtil.java │ │ │ │ │ │ ├── bracket/ │ │ │ │ │ │ │ ├── BracketMatchGraphicFactory.java │ │ │ │ │ │ │ └── SelectedBracketTracking.java │ │ │ │ │ │ ├── inheritance/ │ │ │ │ │ │ │ ├── Inheritance.java │ │ │ │ │ │ │ ├── InheritanceGutterGraphicFactory.java │ │ │ │ │ │ │ ├── InheritanceInvalidationListener.java │ │ │ │ │ │ │ └── InheritanceTracking.java │ │ │ │ │ │ ├── linegraphics/ │ │ │ │ │ │ │ ├── AbstractLineGraphicFactory.java │ │ │ │ │ │ │ ├── AbstractTextBoundLineGraphicFactory.java │ │ │ │ │ │ │ ├── LineContainer.java │ │ │ │ │ │ │ ├── LineGraphicFactory.java │ │ │ │ │ │ │ ├── LineNumberFactory.java │ │ │ │ │ │ │ └── RootLineGraphicFactory.java │ │ │ │ │ │ ├── problem/ │ │ │ │ │ │ │ ├── Problem.java │ │ │ │ │ │ │ ├── ProblemGutterGraphicFactory.java │ │ │ │ │ │ │ ├── ProblemInvalidationListener.java │ │ │ │ │ │ │ ├── ProblemLevel.java │ │ │ │ │ │ │ ├── ProblemPhase.java │ │ │ │ │ │ │ ├── ProblemSquiggleGraphicFactory.java │ │ │ │ │ │ │ └── ProblemTracking.java │ │ │ │ │ │ ├── search/ │ │ │ │ │ │ │ └── SearchBar.java │ │ │ │ │ │ ├── source/ │ │ │ │ │ │ │ ├── JavaContextActionManager.java │ │ │ │ │ │ │ └── JavaContextActionSupport.java │ │ │ │ │ │ ├── suggest/ │ │ │ │ │ │ │ ├── AssemblerTabCompleter.java │ │ │ │ │ │ │ ├── CompletionPopup.java │ │ │ │ │ │ │ ├── CompletionPopupFocuser.java │ │ │ │ │ │ │ ├── CompletionPopupUpdater.java │ │ │ │ │ │ │ ├── CompletionValueGraphicMapper.java │ │ │ │ │ │ │ ├── CompletionValueTextifier.java │ │ │ │ │ │ │ ├── ExistingWordTabCompleter.java │ │ │ │ │ │ │ ├── TabCompleter.java │ │ │ │ │ │ │ └── TabCompletionConfig.java │ │ │ │ │ │ └── syntax/ │ │ │ │ │ │ ├── AbstractSyntaxHighlighter.java │ │ │ │ │ │ ├── RegexLanguages.java │ │ │ │ │ │ ├── RegexRule.java │ │ │ │ │ │ ├── RegexSyntaxHighlighter.java │ │ │ │ │ │ ├── StyleResult.java │ │ │ │ │ │ ├── SyntaxHighlighter.java │ │ │ │ │ │ └── SyntaxUtil.java │ │ │ │ │ └── tree/ │ │ │ │ │ ├── FilterableTreeItem.java │ │ │ │ │ ├── TreeFiltering.java │ │ │ │ │ ├── TreeItems.java │ │ │ │ │ ├── WorkspaceRootTreeNode.java │ │ │ │ │ ├── WorkspaceTree.java │ │ │ │ │ ├── WorkspaceTreeCell.java │ │ │ │ │ ├── WorkspaceTreeFilterPane.java │ │ │ │ │ └── WorkspaceTreeNode.java │ │ │ │ ├── dnd/ │ │ │ │ │ ├── DragAndDrop.java │ │ │ │ │ ├── FileDropListener.java │ │ │ │ │ └── WorkspaceLoadingDropListener.java │ │ │ │ ├── docking/ │ │ │ │ │ ├── DockingManager.java │ │ │ │ │ └── EmbeddedBento.java │ │ │ │ ├── media/ │ │ │ │ │ ├── CombinedPlayer.java │ │ │ │ │ ├── FxPlayer.java │ │ │ │ │ ├── MediaHacker.java │ │ │ │ │ ├── Player.java │ │ │ │ │ ├── SpectrumEvent.java │ │ │ │ │ └── SpectrumListener.java │ │ │ │ ├── menubar/ │ │ │ │ │ ├── AnalysisMenu.java │ │ │ │ │ ├── ConfigMenu.java │ │ │ │ │ ├── FileMenu.java │ │ │ │ │ ├── HelpMenu.java │ │ │ │ │ ├── MainMenu.java │ │ │ │ │ ├── MainMenuProvider.java │ │ │ │ │ ├── MappingMenu.java │ │ │ │ │ ├── ScriptMenu.java │ │ │ │ │ ├── SearchMenu.java │ │ │ │ │ └── WorkspaceAwareMenu.java │ │ │ │ ├── pane/ │ │ │ │ │ ├── CommentEditPane.java │ │ │ │ │ ├── CommentListPane.java │ │ │ │ │ ├── ConfigPane.java │ │ │ │ │ ├── DocumentationPane.java │ │ │ │ │ ├── LoggingPane.java │ │ │ │ │ ├── MappingApplicationPane.java │ │ │ │ │ ├── MappingGeneratorPane.java │ │ │ │ │ ├── MappingProgressPane.java │ │ │ │ │ ├── RemoteVirtualMachinesPane.java │ │ │ │ │ ├── ScriptManagerPane.java │ │ │ │ │ ├── SystemInformationPane.java │ │ │ │ │ ├── WelcomePane.java │ │ │ │ │ ├── WorkspaceBuilderPane.java │ │ │ │ │ ├── WorkspaceExplorerPane.java │ │ │ │ │ ├── WorkspaceInformationPane.java │ │ │ │ │ ├── editing/ │ │ │ │ │ │ ├── AbstractClassInfoProvider.java │ │ │ │ │ │ ├── AbstractContentPane.java │ │ │ │ │ │ ├── AbstractDecompilePane.java │ │ │ │ │ │ ├── AbstractDecompilerPaneConfigurator.java │ │ │ │ │ │ ├── ClassPane.java │ │ │ │ │ │ ├── DecompileFailureButton.java │ │ │ │ │ │ ├── FileDisplayMode.java │ │ │ │ │ │ ├── FilePane.java │ │ │ │ │ │ ├── ProblemOverlay.java │ │ │ │ │ │ ├── SideTabsInjector.java │ │ │ │ │ │ ├── ToolsContainerComponent.java │ │ │ │ │ │ ├── android/ │ │ │ │ │ │ │ ├── AndroidClassEditorType.java │ │ │ │ │ │ │ ├── AndroidClassInfoProvider.java │ │ │ │ │ │ │ ├── AndroidClassPane.java │ │ │ │ │ │ │ ├── AndroidDecompilerPane.java │ │ │ │ │ │ │ └── AndroidDecompilerPaneConfigurator.java │ │ │ │ │ │ ├── assembler/ │ │ │ │ │ │ │ ├── AssemblerAstConsumer.java │ │ │ │ │ │ │ ├── AssemblerBuildConsumer.java │ │ │ │ │ │ │ ├── AssemblerContextActionSupport.java │ │ │ │ │ │ │ ├── AssemblerPane.java │ │ │ │ │ │ │ ├── AssemblerToolTabs.java │ │ │ │ │ │ │ ├── AstBuildConsumerComponent.java │ │ │ │ │ │ │ ├── AstPhase.java │ │ │ │ │ │ │ ├── AstUsages.java │ │ │ │ │ │ │ ├── ContextualAssemblerComponent.java │ │ │ │ │ │ │ ├── ControlFlowLines.java │ │ │ │ │ │ │ ├── ControlFlowLinesConfig.java │ │ │ │ │ │ │ ├── JvmAssemblerBuildConsumer.java │ │ │ │ │ │ │ ├── JvmExpressionCompilerPane.java │ │ │ │ │ │ │ ├── JvmStackAnalysisPane.java │ │ │ │ │ │ │ ├── JvmVariablesPane.java │ │ │ │ │ │ │ ├── LabelData.java │ │ │ │ │ │ │ ├── SnippetsPane.java │ │ │ │ │ │ │ ├── TypeTableCell.java │ │ │ │ │ │ │ ├── ValueTableCell.java │ │ │ │ │ │ │ ├── VariableData.java │ │ │ │ │ │ │ └── resolve/ │ │ │ │ │ │ │ ├── AssemblyResolution.java │ │ │ │ │ │ │ ├── AssemblyResolver.java │ │ │ │ │ │ │ ├── ClassAnnotationResolution.java │ │ │ │ │ │ │ ├── ClassExtends.java │ │ │ │ │ │ │ ├── ClassImplements.java │ │ │ │ │ │ │ ├── EmptyResolution.java │ │ │ │ │ │ │ ├── FieldAnnotationResolution.java │ │ │ │ │ │ │ ├── FieldResolution.java │ │ │ │ │ │ │ ├── IndependentAnnotationResolution.java │ │ │ │ │ │ │ ├── InnerClassResolution.java │ │ │ │ │ │ │ ├── InstructionResolution.java │ │ │ │ │ │ │ ├── LabelDeclarationResolution.java │ │ │ │ │ │ │ ├── LabelReferenceResolution.java │ │ │ │ │ │ │ ├── MethodAnnotationResolution.java │ │ │ │ │ │ │ ├── MethodResolution.java │ │ │ │ │ │ │ ├── TypeReferenceResolution.java │ │ │ │ │ │ │ └── VariableDeclarationResolution.java │ │ │ │ │ │ ├── binary/ │ │ │ │ │ │ │ ├── DecodingXmlPane.java │ │ │ │ │ │ │ ├── ElfPane.java │ │ │ │ │ │ │ ├── PePane.java │ │ │ │ │ │ │ └── hex/ │ │ │ │ │ │ │ ├── HexAdapter.java │ │ │ │ │ │ │ ├── HexConfig.java │ │ │ │ │ │ │ ├── HexEditor.java │ │ │ │ │ │ │ ├── HexUtil.java │ │ │ │ │ │ │ ├── cell/ │ │ │ │ │ │ │ │ ├── EditableAsciiCell.java │ │ │ │ │ │ │ │ ├── EditableHexCell.java │ │ │ │ │ │ │ │ ├── HexCell.java │ │ │ │ │ │ │ │ ├── HexCellBase.java │ │ │ │ │ │ │ │ ├── HexRow.java │ │ │ │ │ │ │ │ └── HexRowHeader.java │ │ │ │ │ │ │ └── ops/ │ │ │ │ │ │ │ ├── HexAccess.java │ │ │ │ │ │ │ ├── HexNavigation.java │ │ │ │ │ │ │ └── HexOperations.java │ │ │ │ │ │ ├── jvm/ │ │ │ │ │ │ │ ├── DecompilerPaneConfig.java │ │ │ │ │ │ │ ├── JvmClassEditorType.java │ │ │ │ │ │ │ ├── JvmClassInfoProvider.java │ │ │ │ │ │ │ ├── JvmClassPane.java │ │ │ │ │ │ │ ├── JvmDecompilerPane.java │ │ │ │ │ │ │ ├── JvmDecompilerPaneConfigurator.java │ │ │ │ │ │ │ └── lowlevel/ │ │ │ │ │ │ │ ├── ClassElement.java │ │ │ │ │ │ │ ├── ClassItem.java │ │ │ │ │ │ │ ├── JvmLowLevelPane.java │ │ │ │ │ │ │ └── LazyClassElement.java │ │ │ │ │ │ ├── media/ │ │ │ │ │ │ │ ├── AudioPane.java │ │ │ │ │ │ │ ├── ImagePane.java │ │ │ │ │ │ │ ├── MediaPane.java │ │ │ │ │ │ │ └── VideoPane.java │ │ │ │ │ │ ├── tabs/ │ │ │ │ │ │ │ ├── FieldsAndMethodsPane.java │ │ │ │ │ │ │ ├── InheritancePane.java │ │ │ │ │ │ │ └── KotlinMetadataPane.java │ │ │ │ │ │ └── text/ │ │ │ │ │ │ └── TextPane.java │ │ │ │ │ └── search/ │ │ │ │ │ ├── AbstractMemberSearchPane.java │ │ │ │ │ ├── AbstractSearchPane.java │ │ │ │ │ ├── ClassReferenceSearchPane.java │ │ │ │ │ ├── InstructionSearchPane.java │ │ │ │ │ ├── MemberDeclarationSearchPane.java │ │ │ │ │ ├── MemberReferenceSearchPane.java │ │ │ │ │ ├── NumberSearchPane.java │ │ │ │ │ ├── SearchContextSource.java │ │ │ │ │ └── StringSearchPane.java │ │ │ │ ├── window/ │ │ │ │ │ ├── AbstractIdentifiableStage.java │ │ │ │ │ ├── ConfigWindow.java │ │ │ │ │ ├── DeobfuscationWindow.java │ │ │ │ │ ├── IdentifiableStage.java │ │ │ │ │ ├── MappingApplicationWindow.java │ │ │ │ │ ├── MappingGeneratorWindow.java │ │ │ │ │ ├── MappingProgressWindow.java │ │ │ │ │ ├── QuickNavWindow.java │ │ │ │ │ ├── RecafScene.java │ │ │ │ │ ├── RecafStage.java │ │ │ │ │ ├── RemoteVirtualMachinesWindow.java │ │ │ │ │ ├── ScriptManagerWindow.java │ │ │ │ │ └── SystemInformationWindow.java │ │ │ │ └── wizard/ │ │ │ │ ├── Wizard.java │ │ │ │ └── WizardStage.java │ │ │ ├── util/ │ │ │ │ ├── Animations.java │ │ │ │ ├── ClipboardUtil.java │ │ │ │ ├── Colors.java │ │ │ │ ├── DirectoryChooserBuilder.java │ │ │ │ ├── Effects.java │ │ │ │ ├── ErrorDialogs.java │ │ │ │ ├── FileChooserBuilder.java │ │ │ │ ├── FileChooserBundle.java │ │ │ │ ├── FxThreadUtil.java │ │ │ │ ├── Icons.java │ │ │ │ ├── IntRange.java │ │ │ │ ├── JFXValidation.java │ │ │ │ ├── Lang.java │ │ │ │ ├── Menus.java │ │ │ │ ├── NodeEvents.java │ │ │ │ ├── RecafURLStreamHandlerProvider.java │ │ │ │ ├── SVG.java │ │ │ │ ├── SceneUtils.java │ │ │ │ ├── SynchronizedSimpleStringProperty.java │ │ │ │ ├── SynchronizedStringBinding.java │ │ │ │ ├── TextDisplayUtil.java │ │ │ │ ├── ToStringConverter.java │ │ │ │ └── Translatable.java │ │ │ └── workspace/ │ │ │ ├── PathExportingManager.java │ │ │ ├── PathLoadingManager.java │ │ │ └── WorkspacePreLoadListener.java │ │ └── resources/ │ │ ├── icons/ │ │ │ └── Jetbrains-LICENSE.txt │ │ ├── style/ │ │ │ ├── code-editor.css │ │ │ ├── docking.css │ │ │ ├── hex.css │ │ │ ├── recaf.css │ │ │ └── tweaks.css │ │ ├── syntax/ │ │ │ ├── enigma.css │ │ │ ├── enigma.json │ │ │ ├── jasm.css │ │ │ ├── jasm.json │ │ │ ├── java.css │ │ │ ├── java.json │ │ │ ├── json.css │ │ │ ├── json.json │ │ │ ├── xml.css │ │ │ └── xml.json │ │ └── translations/ │ │ ├── cs_CZ.lang │ │ ├── de_DE.lang │ │ ├── en_US.lang │ │ ├── ja_JP.lang │ │ ├── pl_PL.lang │ │ ├── ru_RU.lang │ │ ├── sv_SE.lang │ │ └── zh_CN.lang │ └── test/ │ └── java/ │ └── software/ │ └── coley/ │ └── recaf/ │ ├── services/ │ │ └── script/ │ │ └── ScriptManagerTest.java │ └── ui/ │ ├── BaseFxTest.java │ └── control/ │ ├── richtext/ │ │ ├── bracket/ │ │ │ └── SelectedBracketTrackingTest.java │ │ ├── problem/ │ │ │ └── ProblemTrackingTest.java │ │ └── syntax/ │ │ └── RegexSyntaxHighlighterTest.java │ └── tree/ │ └── WorkspaceTreeNodeTest.java ├── settings.gradle └── setup/ ├── code-style-eclipsej.xml └── code-style-intellij.xml ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ # Auto detect text files and perform LF normalization * text=auto # Java sources *.java text diff=java eol=lf *.gradle text diff=java eol=lf # These files are text and should be normalized (Convert crlf => lf) *.css text diff=css eol=lf *.html text diff=html eol=lf *.md text diff=markdown eol=lf *.js text eol=lf *.csv text eol=lf *.json text eol=lf *.properties text eol=lf *.svg text eol=lf *.xml text eol=lf *.yaml text eol=lf *.yml text eol=lf *.toml text eol=lf *.lang text eol=lf # These files are binary and should be left untouched *.png binary *.gif binary *.jpg binary *.jpeg binary # Common build-tool wrapper scripts mvnw text eol=lf gradlew text eol=lf *.sh text eol=lf *.bat text eol=crlf *.cmd text eol=crlf ================================================ FILE: .github/ISSUE_TEMPLATE/bug_report.md ================================================ --- name: Bug report about: Create a report to notify developers of unintended behavior --- **Describe the bug** > A clear and concise description of what the bug is. **To Reproduce** Steps to reproduce the behavior: 1. Open sample '...' _(provide sample download if possible)_ 2. Navigate to '....' 3. Do something '....' 4. See error **Exception** If applicable, add the exception/stacktrace. ``` stacktrace goes here ``` **Screenshots** If applicable, add screenshots to help explain your problem. ================================================ FILE: .github/ISSUE_TEMPLATE/feature_request.md ================================================ --- name: Feature request about: Suggest a feature to improve Recaf --- ## Feature_Name Description of the feature ================================================ FILE: .github/ISSUE_TEMPLATE/other.md ================================================ --- name: Other about: If it isn't a bug or a feature request, choose this --- ================================================ FILE: .github/workflows/build.yml ================================================ name: CI/CD on: push: branches: - master pull_request: branches: - master workflow_dispatch: inputs: is-a-release: description: Publish release? (Only works on master, and for untagged versions) type: boolean permissions: contents: write jobs: test: name: Run test suite strategy: fail-fast: false matrix: os: [ ubuntu-latest ] java-version: [ 22 ] runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout uses: actions/checkout@v3 - name: Setup JDK uses: actions/setup-java@v3 with: distribution: temurin java-version: 22 check-latest: true # The project version extract NEEDS to have the gradle wrapper already downloaded. # So we have a dummy step here just to initialize it. - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 # Run the tests and upload results/coverage - name: Run tests run: ./gradlew test - name: Upload test coverage to CodeCov.io uses: codecov/codecov-action@v3 env: CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }} - name: Upload test artifacts if: always() uses: actions/upload-artifact@v4 with: name: test-artifacts retention-days: 21 path: | **/TEST-* **/hs_err_pid* # Build the distribution jar and upload it, without bundling JavaFX in the jar - name: Create distribution jar run: ./gradlew assemble -x compileTestJava -Dskip_jfx_bundle=true - name: Upload distribution jar if: always() uses: actions/upload-artifact@v4 with: name: snapshot-build retention-days: 30 path: | recaf-ui/build/libs/recaf-ui-*-all.jar # Publishes the test results from prior task work publish-test-results: name: Publish tests results needs: test if: always() runs-on: ubuntu-latest permissions: checks: write pull-requests: write steps: - name: Download artifacts uses: actions/download-artifact@v4 with: name: test-artifacts - name: Publish test results uses: EnricoMi/publish-unit-test-result-action@v2 with: check_name: Unit test results files: | **/*.xml # Builds the projects and attempts to publish a release if the current project version # does not match any existing tags in the repository. build-and-release: name: Publish release needs: test if: inputs.is-a-release && github.repository == 'Col-E/Recaf' && github.ref == 'refs/heads/master' strategy: fail-fast: false runs-on: ubuntu-latest timeout-minutes: 20 steps: - name: Checkout uses: actions/checkout@v3 with: fetch-depth: 0 # Required depth for JReleaser - name: Setup Java JDK uses: actions/setup-java@v3 with: distribution: temurin java-version: 22 # The project version extract NEEDS to have the gradle wrapper already downloaded. # So we have a dummy step here just to initialize it. - name: Setup Gradle uses: gradle/actions/setup-gradle@v4 # Set environment variable for the project version: "var_to_set=$(command_to_run)" >> sink # - For maven: echo "PROJECT_VERSION=$(./mvnw help:evaluate -Dexpression=project.version -q -DforceStdout)" >> $GITHUB_ENV # - For gradle: echo "PROJECT_VERSION=$(./gradlew properties | grep -Po '(?<=version: ).*')" >> $GITHUB_ENV - name: Extract project version to environment variable run: echo "PROJECT_VERSION=$(./gradlew properties | grep -Po '(?<=version\W ).*')" >> $GITHUB_ENV # Check if a tag exists that matches the current project version. # Write the existence state to the step output 'tagExists'. - name: Check the package version has corresponding Git tag id: tagged shell: bash run: | git show-ref --tags --verify --quiet -- "refs/tags/${{ env.PROJECT_VERSION }}" && echo "tagExists=1" >> $GITHUB_OUTPUT || echo "tagExists=0" >> $GITHUB_OUTPUT git show-ref --tags --verify --quiet -- "refs/tags/${{ env.PROJECT_VERSION }}" && echo "Tag for current version exists" || echo "Tag for current version does not exist" # If the tag could not be fetched, show a message and abort the job. # The wonky if logic is a workaround for: https://github.com/actions/runner/issues/1173 - name: Abort if tag exists, or existence check fails if: ${{ false && steps.tagged.outputs.tagExists }} run: | echo "Output of 'tagged' step: ${{ steps.tagged.outputs.tagExists }}" echo "Failed to check if tag exists." echo "PROJECT_VERSION: ${{ env.PROJECT_VERSION }}" echo "Tags $(git tag | wc -l):" git tag git show-ref --tags --verify -- "refs/tags/${{ env.PROJECT_VERSION }}" exit 1 # Run build to generate the release artifacts. # Tag does not exist AND trigger was manual. Deploy release artifacts! - name: Build release artifacts run: ./gradlew publish # TODO: Publish all modules' artifacts into a single directory # Make release with JReleaser, only running when the project version does not exist as a tag on the repository. - name: Publish release uses: jreleaser/release-action@v2 with: arguments: full-release env: JRELEASER_PROJECT_VERSION: ${{ env.PROJECT_VERSION }} JRELEASER_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} JRELEASER_GPG_PASSPHRASE: ${{ secrets.JRELEASER_GPG_PASSPHRASE }} JRELEASER_GPG_PUBLIC_KEY: ${{ secrets.JRELEASER_GPG_PUBLIC_KEY }} JRELEASER_GPG_SECRET_KEY: ${{ secrets.JRELEASER_GPG_SECRET_KEY }} JRELEASER_MAVENCENTRAL_USERNAME: ${{ secrets.JRELEASER_MAVENCENTRAL_USERNAME }} JRELEASER_MAVENCENTRAL_TOKEN: ${{ secrets.JRELEASER_MAVENCENTRAL_TOKEN }} # Upload JRelease debug log - name: JReleaser output uses: actions/upload-artifact@v4 if: always() with: name: jreleaser-release path: | out/jreleaser/trace.log out/jreleaser/output.properties ================================================ FILE: .gitignore ================================================ # IntelliJ out/ .idea/ .idea_modules/ *.iws *.iml # Eclipse .settings/ .classpath .checkstyle .project # Gradle target/ build/ generated/ gradle-app.setting .gradle .gradletasknamecache !gradle-wrapper.jar **/build/ # Misc hs_err_pid* *.log *.ctxt temp/ # IntelliJ lib/ ================================================ FILE: CONTRIBUTING.md ================================================ # Contributing to Recaf The following is a series of guidelines for contributing to Recaf. They're not _"rules"_ per say, rather they're more like goals to strive towards. Regardless of how closely you adhere to the following guidelines I really appreciate you taking the time to contribute, it means a lot :+1: **Table of Contents** - [What if I am not a programmer?](#what-if-i-am-not-a-programmer) - [What should I know before I get started?](#what-should-i-know-before-getting-started) - [Is there a todo list?](#is-there-a-to-do-list) - [Reporting Bugs](#reporting-bugs) - [Suggesting Features](#suggesting-features) - [Coding Guidelines](#coding-guidelines) - [Pull Requests](#pull-requests) **TLDR?** - Follow the code style. - Document and comment your code. - Make sure the tests pass after making changes. - Translations and feature ideas are appreciated too. **Questions?** You can DM `invokecoley` on discord, or join the [Recaf discord](https://discord.gg/Bya5HaA). ## What if I am not a programmer? [There is plenty to contribute that isn't based in code.](https://www.youtube.com/watch?v=GAqfMNB-YBU&t=603) For example, you can contribute ideas, add translations, or write documentation: - [Documentation source](https://github.com/Col-E/recaf-site) - [Documentation site](https://recaf.coley.software/) ## What should I know before getting started? It depends on what changes you are making. For instance, changing the user-interface requires very minimal or no reverse-engineering prior knowledge. If you do need JVM reversal knowledge to work on a feature you can check the [primer guide](PRIMER.md) which points to several good resources and outlines key details. For a general understanding of how Recaf works and how to begin creating contributions you can read our [getting started](https://recaf.coley.software/dev/getting-started.html) page as well. ## Is there a to-do list? Unfortunately the to-do list is scattered around a few places. We're working on eventually consolidating everything into one place. ## Reporting Bugs When creating an issue select the `Bug report` button. This will provide a template that you can fill in the details for your bug. Please include as much information as possible. This can include: - Clear and descriptive title - Log files - Steps to reproduce the bug - An explanation of what you _\*expected\*_ to happen - The file being analyzed _(Do not share anything you do not own the rights to)_ ## Suggesting Features When creating an issue select the `Feature request` button. This will provide a template that you can fill in the details for your feature idea. Be as descriptive as possible with your idea. **Note**: Not all ideas may be within Recaf's scope. In these cases the feature should be implemented as a script or plugin. ## Coding Guidelines **Style**: IDE code formatting rules can be found in the [`/setup` directory](setup/). **Commits**: Try and keep commits small and focused on one thing at a time. ## Pull Requests When creating a pull request please consider the following when filling in the template: - Clear and descriptive title - A clear description of what changes are included in the pull Github's PR system will validate that your changes compile and pass the unit tests as well. ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2017-2025 Matthew Coley Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: PRIMER.md ================================================ # What should I know before getting started? ## JVM / Class file format ### General concepts A basic understanding of the JVM / class file format is _highly_ reccomended before contributing. Here are some articles that should bring you up to speed: - [JVM Architecture 101: Get to Know Your Virtual Machine](https://blog.overops.com/jvm-architecture-101-get-to-know-your-virtual-machine/) - [JVM Internals](https://blog.jamesdbloom.com/JVMInternals.html) - [Java Code To Byte Code](https://blog.jamesdbloom.com/JavaCodeToByteCode_PartOne.html) ### Terminology **Qualified name**: Package separators using the `.` character. These are names used by runtime functions like `Class.forName(name)`. For example: - `java.lang.String` - `com.example.MyClass.InnerClass` **Internal name**: Package separators using the `/` character. Inner classes specified with the `$` character. These are names how classes are specified internally in the class file. For example: - `java/lang/String` - `com/example/MyClass$InnerClass` Primitives *(Not the boxed types)* use single characters: | Primitive | Internal | |-----------|----------| | `long` | `J` | | `int` | `I` | | `short` | `S` | | `byte` | `B` | | `boolean` | `Z` | | `float` | `F` | | `double` | `D` | | `void` | `V` | **Descriptor**: Used to describe field and method types. These are essentially the same as internal names, but class names are wrapped in a prefix (`L`) and suffix character (`;`). For example: * `Ljava/lang/String;` * `I` _(primitives stay the same)_ Method descriptors are formatted like so: * `double method(int i, String s)` = `(ILjava/lang/String;)D` * `void method()` = `()V` Arrays are prefixed with a `[` for each level of the array. * `int[]` = `[I` * `String[][]` = `[[Ljava/lang/String;` ### Quirks **Wide types**: `double` and `long` typed variables take up two slots _(On the stack and in the local variable table)_. For example, declaring two doubles in a static method will use slots 0, then 2. Slots 0-3 are all in-use. **Lambdas**: The content of a lambda is defined in compiler-generated hidden methods and are invoked with `INVOKEDYNAMIC`. Decompilers will in-line the code so that it looks more similar to the source representation. ================================================ FILE: PULL_REQUEST_TEMPLATE.md ================================================ ## What's new * Summary of additions ## What's fixed * Summary of bugs fixed ================================================ FILE: README.md ================================================ # Recaf [](https://discord.gg/Bya5HaA) [](https://codecov.io/gh/Col-E/Recaf)  [](CONTRIBUTING.md)  An easy to use modern Java bytecode editor that abstracts away the complexities of Java programs. ## Download - [Launcher](https://github.com/Col-E/Recaf-Launcher) - Usage & instructions found on the launcher repo - [Snapshot releases](https://github.com/Col-E/Recaf-Launcher/blob/master/MANUAL.md) - See [CI actions](https://github.com/Col-E/Recaf/actions/workflows/build.yml) for release artifacts - [Independent releases](https://github.com/Col-E/Recaf/releases) _(None for 4X currently)_ ## Features - Edit Java bytecode with ease from a high or low level _(minus the annoying parts)_ - Editor features within Recaf abstract away complex details of compiled Java applications like: - The constant pool - Stack frame calculation - Using wide instructions when needed - And more! - Easy to use navigable interface with context-sensitive actions - Support for standard Java _and_ Android applications - Multiple decompilers to switch between, with all of their parameters made fully configurable - Built in compiler to allow recompiling decompiled classes, even if some referenced classes are missing *(When supported, support may vary depending on code complexity and obfuscation)* - A bytecode assembler with a simple syntax, and supporting tooling - See the state of local variables and stack values at any point in methods - Access variables by names instead of indices for clearer disassembled code - Convert snippets of Java source code to bytecode sequences automatically - Searching for a variety of different content: Strings/numeric constants, classes and member references, instruction patterns - Tools for deobfuscating obfuscated code - Specially crafted class files with the intent of crashing reverse engineering tools are automatically patched when opened in Recaf - Specially crafted jar/zip files are read as the JVM does, bypassing sneaky tricks that can trick reverse engineering tools into showing the wrong data - Support for automatically renaming obfuscated classes and their members - Support for manually renaming classes and their members *_(And exporting these mappings to a variety of mapping formats for use in other tools)_* - Bytecode transformers for simplifying common obfuscation strategies - Attach to running Java process with instrumentation capabilities - And much more A complete list of features can be found in the [user documentation](https://recaf.coley.software/user/index.html). ## Scripting & Plugins Recaf exposes almost all of its functionality through modular API's. Automating behaviors can be done easily with scripts, or with plugins for more complex situations. Additional features can also be added via plugins, which can register hooks in API's that offer them. To create your own script or plugin, see the [developer documentation](https://recaf.coley.software/dev/index.html), specifically the _"plugins & scripts"_ section. ## Command Line Recaf can run as a command line application, which can be especially useful when paired with scripts provided at startup. You can see all the current launch arguments by passing `--help` as an application argument. ## Development Setup Clone the repository via `git clone https://github.com/Col-E/Recaf.git` Open the project in an IDE or generate the build with gradle. **IDE**: 1. Import the project from the `build.gradle` file 2. Create a run configuration with the main class `software.coley.recaf.Main` **Without IDE**: 1. Run `gradlew build` - Output will be located at: `recaf-ui/build/libs/recaf-ui-{VERSION}-all.jar` ================================================ FILE: build.gradle ================================================ plugins { alias(libs.plugins.benmanes.versions) apply false alias(libs.plugins.coverage.report.aggregator) alias(libs.plugins.checker.processor) apply false } allprojects { group = 'software.coley' version = '4.0.0-SNAPSHOT' } subprojects { apply plugin: 'java' apply plugin: 'jacoco' apply plugin: 'maven-publish' apply plugin: 'com.github.ben-manes.versions' repositories { mavenLocal() mavenCentral() google() maven { url = 'https://jitpack.io' name = 'JitPack' } } // ======================= DEPENDENCIES ======================== dependencies { // Enforce jakarta annotations everywhere as the standard for Nullable/Nonnull implementation(libs.jakarta.annotation) // Local libraries for internal use only // (none of the types from these libraries should be part of a public API) implementation fileTree(dir: "$rootProject.projectDir/libs", include: ['*.jar']) } configurations.configureEach { // Annoying annotations that replace desired tab completions. exclude group: 'org.checkerframework' // Other annotations we don't use which are transitive deps of deps exclude group: 'com.google.code.findbugs' exclude group: 'com.google.errorprone' exclude group: 'com.google.j2objc' exclude group: 'org.jetbrains', module: 'annotations' // Used by ANTLR runtime, has a lot of IL8N related files which we don't use. // Removing this dependency doesn't inhibit the behavior of libraries using the // runtime in practice though. exclude group: 'com.ibm.icu' } // ========================== COMPILE ========================== // https://docs.gradle.org/current/userguide/toolchains.html // gradlew -q javaToolchains - see the list of detected toolchains. java { toolchain { languageVersion = JavaLanguageVersion.of(System.getenv('TARGET_VERSION') ?: '22') } } // Append options for unchecked/deprecation tasks.withType(JavaCompile).configureEach { options.compilerArgs << '-Xlint:unchecked' << '-Xlint:deprecation' << '-g' << '-parameters' options.encoding = 'UTF-8' options.incremental = true } // Enable automatic generation of null checks on annotated methods afterEvaluate { Project p -> p.plugins.apply('gov.tak.gradle.plugins.checker-processor') } // ========================== TESTING ========================== // All modules should have the same test framework setup. test { useJUnitPlatform() // Required for Mockito in newer JDK's which disable useful features by default for 'integrity' reasons. jvmArgs '-XX:+EnableDynamicAgentLoading' systemProperty 'junit.jupiter.execution.parallel.enabled', true systemProperty 'junit.jupiter.execution.parallel.mode.default', 'concurrent' testLogging { showStandardStreams = true events "passed", "skipped", "failed" } } // All modules with Java components should share the same test dependencies. plugins.withType(JavaPlugin).configureEach { dependencies { testImplementation(libs.junit.api) testImplementation(libs.junit.params) testImplementation(libs.mockito) testImplementation(libs.assertj) testRuntimeOnly(libs.junit.engine) testRuntimeOnly(libs.junit.launcher) } } // Need to tell any test-fixture-plugin to include dependencies // in its own configuration. Otherwise it can get confused. plugins.withType(JavaTestFixturesPlugin).configureEach { dependencies { testFixturesApi(libs.junit.api) testFixturesApi(libs.junit.params) testFixturesApi(libs.mockito) } } // Configure report outputs, and jacoco packages to target. tasks.withType(Test).configureEach { reports.html.required = false reports.junitXml.required = true // We want to cover all recaf classes, but not the test classes themselves (or auto-gen classes). // The exclusion list is applied after the inclusion list, so this ends up working out. jacoco { includes = ['software/coley/recaf/**'] excludes = ['software/coley/recaf/**Test**', 'software/coley/recaf/test/**', '**/**WeldClientProxy'] } } // Setup artifact publishing to maven local publishing { publications { mavenJava(MavenPublication) { from components.java } } repositories { mavenLocal() } } } // Always emit HTML & XML aggregate reports jacocoAggregation { outputHtml = true outputXml = true } // Build aggregate report for test coverage when subproject 'test' tasks complete. // But only do so when the 'test' tasks have executed. // You can skip tests by specifying '-x test' in your gradle task arguments. tasks.register('test') { dependsOn(subprojects.test) doLast { if (subprojects.test.stream().anyMatch(Task::getDidWork)) buildJacocoAggregate.execute() } } tasks.register('build') { // Build will run tests, unless skipped by '-x test'. // Even if skipped, this will still lead to the subproject build tasks being executed, such as: // - recaf-ui:shadowJar dependsOn(tasks.named('test')) } ================================================ FILE: codecov.yml ================================================ coverage: precision: 2 round: down status: project: default: informational: true patch: default: informational: true ignore: - "**/src/test/" - "**/src/testFixtures" ================================================ FILE: docs/README.md ================================================ # Github pages directory Github pages requires this directory be named `docs`. If you were looking for documentation go here: - [User documentation](https://recaf.coley.software/user/index.html) - [Developer documentation](https://recaf.coley.software/dev/index.html) ================================================ FILE: docs/index.html ================================================
recaf.coley.software
* Searching for usages of these keys will show what listeners/classes fire in which order.
*
* @author Matt Coley
*/
public final class PriorityKeys {
public static final int EARLIEST = -1000;
public static final int EARLIER = -100;
public static final int EARLY = -10;
public static final int DEFAULT = 0;
public static final int LATE = 10;
public static final int LATER = 100;
public static final int LATEST = 1000;
private PriorityKeys() {}
}
================================================
FILE: recaf-core/src/main/java/software/coley/recaf/behavior/PrioritySortable.java
================================================
package software.coley.recaf.behavior;
import jakarta.annotation.Nonnull;
import software.coley.collections.Lists;
import java.util.List;
/**
* Priority sortable item.
*
* @author Matt Coley
*/
public interface PrioritySortable extends Comparable
* Alternatively, you could also observe the events {@link InitializationEvent} or {@link UiInitializationEvent}
* in a method with {@link Observes}. This would allow you to separate the initialization logic from the constructor
* and have it reside in a separate method.
*
* NOTE: Beans are not eagerly initialized while in a test environment.
*
* @author Matt Coley
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface EagerInitialization {
/**
* Determines when to run early initialization.
*
* Changing this value is mostly applicable to {@link ApplicationScoped} beans.
* Having the value set to {@link InitializationStage#IMMEDIATE} will result in the bean and all of
* its dependencies being created as soon as the application begins. For beans dealing with UI capabilities this
* will likely lead to problems. For those situations, use {@link InitializationStage#AFTER_UI_INIT} to delay
* initialization until after the UI has been populated.
*
* @return When the initialization should occur.
*/
InitializationStage value() default InitializationStage.IMMEDIATE;
}
================================================
FILE: recaf-core/src/main/java/software/coley/recaf/cdi/EagerInitializationExtension.java
================================================
package software.coley.recaf.cdi;
import jakarta.annotation.Nonnull;
import jakarta.enterprise.context.ApplicationScoped;
import jakarta.enterprise.event.Observes;
import jakarta.enterprise.inject.spi.Annotated;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.ProcessBean;
import jakarta.inject.Inject;
import java.util.ArrayList;
import java.util.List;
/**
* Extension to force creation of {@link EagerInitialization} annotated beans without the need to
* {@link Inject} and reference them externally.
*
* @author Matt Coley
*/
public class EagerInitializationExtension implements Extension {
private static final EagerInitializationExtension INSTANCE = new EagerInitializationExtension();
private static final List
* Plugin registering new {@link ConfigContainer} instances should use this as the {@link ConfigContainer#getGroup()}.
* This group is given special treatment in the UI.
*/
public static final String EXTERNAL = "external";
private ConfigGroups() {
}
/**
* @param container
* Container to get packages from.
*
* @return Group packages.
*/
public static String[] getGroupPackages(ConfigContainer container) {
return container.getGroup().split('\\' + PACKAGE_SPLIT);
}
}
================================================
FILE: recaf-core/src/main/java/software/coley/recaf/config/ConfigMapValue.java
================================================
package software.coley.recaf.config;
import java.util.Map;
/**
* An option stored in a {@link ConfigContainer} object representing a map.
*
* @param
* For an example, if our class is 'C' then this list will be {@code [foo/A, foo/A$B]}:
* {@code
* package foo;
*
* class A {
* class B {
* class C {} // This class
* }
* }
* }
*
* @return Breadcrumbs of the outer class.
*/
@Nonnull
List{@code
* class Foo {
* class Bar {
* class FizzBuzz {}
* }
* }
* }
* Because anonymous inner classes do not have a name declared, they cannot be yielded here.
*
* @param innerName
* Local name of inner class.
*
* @return Inner class of the matching name, or {@code null} if no such inner exists.
*/
@Nullable
default InnerClassInfo getInnerClassByInnerName(@Nonnull String innerName) {
for (InnerClassInfo innerClass : getInnerClasses())
if (innerName.equals(innerClass.getInnerName()))
return innerClass;
return null;
}
/**
* @return {@code true} when this class is an inner class of another class.
*/
default boolean isInnerClass() {
return getOuterClassName() != null || getOuterMethodName() != null;
}
/**
* @param className
* Name of a supposed outer class.
*
* @return {@code true} if this class is an inner class of the given outer class.
*/
default boolean isInnerClassOf(@Nonnull String className) {
// If we don't start with that class name, we can't possibly be an inner class.
if (!getName().startsWith(className + "$"))
return false;
return getOuterClassBreadcrumbs().contains(className);
}
/**
* @return {@code true} when this class is an anonymous inner class of another class.
*/
default boolean isAnonymousInnerClass() {
// Check if the 'full' name of the inner 'InnerClassName' is the current class (entry representing ourselves)
// Then if the 'OuterClassName' is null, this means our class does not expose a name because it is anonymous.
return getInnerClasses().stream()
.anyMatch(inner -> inner.getInnerClassName().equals(getName()) && inner.getOuterClassName() == null);
}
/**
* @return List of declared fields.
*/
@Nonnull
List
* Important note: Oracle's Java Virtual Machine implementation
* does not check the consistency of an InnerClasses attribute against a class
* file representing a class or interface referenced by the attribute.
*
* @author Matt Coley
* @author Amejonah
*/
public interface InnerClassInfo extends Accessed, Named {
@Nonnull
@Override
default String getName() {
return getInnerClassName();
}
/**
* @return The name of the outer declaring class for this inner class.
*/
@Nonnull
String getOuterDeclaringClassName();
/**
* Given the following example, the inner name is {@code Apple$Worm}.
*
* class Apple {
* class Worm {}
* }
*
*
* @return The internal name of an inner class.
*/
@Nonnull
String getInnerClassName();
/**
* Given the following example, the inner name is {@code Apple}.
*
* class Apple {
* class Worm {}
* }
*
*
* @return The internal name of the class to which the inner class belongs.
* May be {@code null} for anonymous classes.
*/
@Nullable
String getOuterClassName();
/**
* Given the following example, the inner name is {@code Worm}.
*
* class Apple {
* class Worm {}
* }
*
*
* @return The (simple) name of the inner class inside its enclosing class.
* May be {@code null} for anonymous inner classes.
*/
@Nullable
String getInnerName();
/**
* There are some wierd cases where there can be inner-class entries of classes defined by other classes.
* You can use this to filter those cases out.
*
* @return {@code true} when this inner-class entry denotes an inner-class
* reference to a class defined in another class.
*/
default boolean isExternalReference() {
return !getInnerClassName().startsWith(getOuterDeclaringClassName());
}
/**
* @return The access modifiers of the inner class as originally declared in the enclosing class.
*/
default int getInnerAccess() {
return getAccess();
}
/**
* @return Either {@link #getInnerName()} if not {@code null},
* otherwise the last "part" (after last $ or /) of {@link #getOuterClassName()}.
*/
@Nonnull
default String getSimpleName() {
// Check for inner name
String innerName = getInnerName();
if (innerName != null) return innerName;
// Substring from outer class prefix
String outerDeclaringClass = getOuterDeclaringClassName();
String outerName = getOuterClassName();
if (outerName != null) {
int outerDeclaringLength = outerDeclaringClass.length();
int lastIndex = 0;
int endIndex = Math.min(outerDeclaringLength, outerName.length());
for (; lastIndex < endIndex; lastIndex++) {
if (outerDeclaringClass.charAt(lastIndex) != outerName.charAt(lastIndex)) break;
}
// Edge case handling with outer name
if (lastIndex == 0)
return outerName;
else if (outerName.startsWith("$", lastIndex))
lastIndex++;
return outerName.substring(lastIndex);
}
// Class entry is for anonymous class.
String innerClassName = getInnerClassName();
return "Anonymous '" + innerClassName.substring(innerClassName.lastIndexOf('$') + 1) + "'";
}
}
================================================
FILE: recaf-core/src/main/java/software/coley/recaf/info/JModFileInfo.java
================================================
package software.coley.recaf.info;
/**
* Outline of a JVM JMod file.
* These files are found at {@code %JAVA%/jmods/}.
*
* @author Matt Coley
*/
public interface JModFileInfo extends ZipFileInfo {
/**
* Classes in the JMod archive are prefixed with this path.
*/
String CLASSES_PREFIX = "classes/";
}
================================================
FILE: recaf-core/src/main/java/software/coley/recaf/info/JarFileInfo.java
================================================
package software.coley.recaf.info;
/**
* Outline of a JAR file container.
*
* @author Matt Coley
*/
public interface JarFileInfo extends ZipFileInfo {
/**
* Multi-release JARs prefix class names with this, plus the target version.
* For example: Multiple versions of {@code foo/Bar.class}
*
*
* The first item is used for Java 8.
* The second item for Java 9 and 10.
* The third item for Java 11+.
*/
String MULTI_RELEASE_PREFIX = "META-INF/versions/";
}
================================================
FILE: recaf-core/src/main/java/software/coley/recaf/info/JvmClassInfo.java
================================================
package software.coley.recaf.info;
import jakarta.annotation.Nonnull;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.Opcodes;
import org.objectweb.asm.Type;
import software.coley.cafedude.classfile.ConstantPoolConstants;
import software.coley.recaf.info.builder.JvmClassInfoBuilder;
import software.coley.recaf.info.properties.builtin.ReferencedClassesProperty;
import software.coley.recaf.info.properties.builtin.StringDefinitionsProperty;
import software.coley.recaf.util.JavaVersion;
import software.coley.recaf.util.Types;
import software.coley.recaf.util.visitors.TypeVisitor;
import java.util.*;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* Outline of a JVM class.
*
* @author Matt Coley
*/
public interface JvmClassInfo extends ClassInfo {
/**
* Denotes the base version offset.
*
*
*/
int BASE_VERSION = 44;
/**
* @return New builder wrapping this class information.
*/
@Nonnull
default JvmClassInfoBuilder toJvmClassBuilder() {
return new JvmClassInfoBuilder(this);
}
/**
* @return Java class file version.
*/
int getVersion();
/**
* @return Bytecode of class.
*/
@Nonnull
byte[] getBytecode();
/**
* @return Class reader of {@link #getBytecode()}.
*/
@Nonnull
ClassReader getClassReader();
/**
* @return Default flags to use with {@link #getClassReader()}
*/
default int getClassReaderFlags() {
// There are some old classes with stack-frame data.
// These aren't strictly required on old classes, and ASM dies when re-writing them (
// - MethodWriter.visitFrame checks for pre Java 6 and throws
return getVersion() <= Opcodes.V1_5 ?
ClassReader.SKIP_FRAMES : 0;
}
/**
* @return Set of all classes referenced in the constant pool.
*/
@Nonnull
default NavigableSet