$ show romainguy/kotlin-explorer
Kotlin Explorer is a desktop application built with Compose Desktop and Swing that disassembles Kotlin source code into multiple bytecode representations: JVM bytecode (via javap), Android DEX bytecode (via dexdump), and Android OAT assembly (via oatdump on a connected device). It orchestrates the full toolchainβcompiling Kotlin with kotlinc, optionally optimizing with R8, and running the compiled codeβall within a GUI that provides syntax-highlighted source and disassembly views, jump arrows for branch instructions, and integrated documentation for AArch64 opcodes. The application persists user settings (SDK paths, window geometry, source code) to disk and supports macOS, Windows, and Linux. The architecture is a single desktop application with a clear separation of concerns: UI components (menus, text areas, splitters) in Kotlin Explorer.kt and related files, build/disassembly orchestration in Disassembly.kt, and parsing logic in dedicated parsers for each bytecode format (ByteCodeParser, DexDumpParser, OatDumpParser). The codebase demonstrates strong Kotlin idioms, coroutine-based concurrency, and careful integration of Swing components within Compose. It relies on external toolchains (JDK, Android SDK, Kotlin compiler) and a connected Android device for OAT disassembly. Key reusable components include a generic PeekingIterator for lookahead parsing, a thread-safe ProgressUpdater for coroutine progress reporting, a suspend helper for running external processes with cancellation, and a CodeBuilder that constructs formatted disassembly text with line numbers and instruction metadata. The test infrastructure uses a Builder abstraction that can run the real toolchain or fall back to committed test data, enabling offline testing.
The LLM identified 4 files worth highlighting for reuse:
A generic iterator wrapper that provides a peek() method to look at the next element without consuming it, along with consumeUntil() overloads that consume elements until a predicate is met. This is a classic parsing utility that can be extracted and reused in any sequential parsing or tokenization task. It demonstrates clean Kotlin idioms (inline functions, reified generics) and is self-contained with no internal dependencies.
A thread-safe progress and status message updater designed for coroutine-based workflows. It uses an AtomicInteger for progress tracking and a synchronized list for status messages, exposing a Flow for UI observation. This component can be extracted and reused in any application that needs to report progress from background coroutines to a UI layer, demonstrating careful concurrency design without framework coupling.
A suspend function that runs an external command, collects stdout/stderr, and supports cancellation via coroutine cancellation. It handles process lifecycle, timeout, and error reporting. This is a reusable utility for any JVM application that needs to invoke external tools asynchronously, with proper resource cleanup and cancellation propagation. It is self-contained and uses only standard Kotlin coroutines and Java ProcessBuilder.
A builder that constructs formatted disassembly text from parsed bytecode instructions. It handles line numbering, instruction counts, branch counts, and jump table generation. The builder pattern allows incremental construction of structured text output with optional metadata. While somewhat specific to disassembly, the core pattern of building formatted text with line references and annotations is reusable for any code generation or pretty-printing task. It demonstrates clean separation of formatting logic from data models.