refactor(core): consume the ObjC rendering and indexing layers from the library - #102
Merged
Merged
Conversation
…rary The ObjC renderer and interface indexer were never RuntimeViewer-specific — they turn ObjC metadata into semantic declarations and build a queryable index, which any MachOObjCSection consumer wants — yet ~1500 lines of them sat in this app's core layer. They now ship with MachOObjCSection, so RuntimeObjCSection drops from 617 lines to 471 and is left doing what it should: translating library results into RuntimeViewer domain types. The library reports progress and discovered relationships through a single ObjCIndexingEvent channel where this code had two; the adapter back onto RuntimeObjectsLoadingEvent lives in ObjCIndexingEvent+LoadingProgress. The concrete transformer modules likewise move to the libraries that own their vocabulary. What stays is the aggregate Transformer.Configuration: it spans both halves, and nothing outside RuntimeViewer persists them as a unit. Re-exports keep every existing Transformer.… reference compiling.
RuntimeObjCSection becomes the thin translation layer it should be; the renderer, indexer and transformer modules now ship with the libraries.
Points at the tags that carry the extracted layers: MachOObjCSection 0.8.102, MachOSwiftSection 0.15.0, swift-semantic-string 0.3.0. MachOKit goes to 0.52.100 because 0.8.102 requires it — the old 0.51.101 pin only held because the previously referenced MachOObjCSection 0.7.103 asked for far less. Package.resolved is regenerated with everything resolving remotely, so its pins are complete.
The 0.15.0 tag was recut to include the release commit (changelog plus the BundledVersion bump its release workflow requires), so the version now resolves to a different revision than the one recorded here.
MachOObjCSection 0003 removed the inheritance and protocol-adoption reverse tables from ObjCIndexing: the library parses and broadcasts what it finds, and no longer remembers how classes relate. RuntimeObjCRelationshipIndex is where those broadcasts become tables again, one per image, fed by the event stream during prepare(). The hazard here is not the three deleted APIs — the compiler catches those. It is that eventHandler quietly changed from an observer into the sole channel carrying relationship data, and RuntimeObjCSection installed one only when a progress stream was supplied. Six of the seven section-creation call sites pass no progress stream, background indexing among them, so keeping that condition would have emptied the Relationships pane for nearly every image while still compiling and still passing most tests. The handler is now unconditional; only the forwarding of .progress events depends on there being a stream. Equivalence is pinned by a baseline captured through relationships(for:) before the pin moved, since that is the only vantage point existing on both sides of the change. Output matches it verbatim: 307 NSObject subclasses, 9 NSCoding and 68 NSCopying conformers, identical in order and in imagePath. Three properties the match rests on get their own unit tests — inline and category adoptions sharing one table, arrival-order replay, and dedup keyed on all three fields so a class reaching one protocol twice with differing isSwiftStable stays twice. RuntimeObjCSectionFactory's aggregate indexer goes away rather than moving: it was only ever written to, since RuntimeRelationshipsResolver fans out across images itself. That also settles what to do about f41648a on feature/node-store-adoption, which added removeSubIndexer to plug the leak the aggregate caused — with no aggregate there is nothing to detach. Tables build on first query instead of behind a seal-the-index call. Requiring one would have reintroduced exactly the failure this change exists to remove: forget it, or miss it because prepare() threw, and every query silently returns nothing. Note: this cannot resolve against the remote pins yet. MachOSwiftSection 0.15.0 holds MachOObjCSection at exact 0.8.102, so building and testing this branch needs USING_LOCAL_DEPENDENCIES=1 until that pin moves to 0.8.103.
Contributor
There was a problem hiding this comment.
Pull request overview
Refactors RuntimeViewerCore to consume Objective-C declaration rendering and interface indexing from the upstream libraries (MachOObjCSection / MachOSwiftSection / swift-semantic-string), while reintroducing Objective-C relationship reverse tables in-app by rebuilding them from the library’s ObjCIndexingEvent stream (per Evolution 0007).
Changes:
- Replace the app-owned ObjC renderer/indexer with library-provided
ObjCInterfaceIndexer+ObjCInterfaceBuilder, mapping RuntimeViewer transformer settings into the new API. - Add
RuntimeObjCRelationshipIndexto rebuild inheritance/protocol-adoption tables fromObjCIndexingEvent, and update relationships resolution to query it. - Restructure/add tests: new snapshot + regression coverage for relationships and a focused
Transformer.Configurationpersistence suite; update dependency pins and documentation.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| RuntimeViewerCore/Tests/RuntimeViewerCoreTests/TransformerTests.swift | Removed legacy transformer tests after transformer engines/modules moved library-side. |
| RuntimeViewerCore/Tests/RuntimeViewerCoreTests/TransformerConfigurationTests.swift | New tests validating unified Transformer namespace + Transformer.Configuration persistence. |
| RuntimeViewerCore/Tests/RuntimeViewerCoreTests/TransformerAdditionalTests.swift | Removed extensive Swift-side transformer module tests now owned/tested upstream. |
| RuntimeViewerCore/Tests/RuntimeViewerCoreTests/Snapshots/relationships-baseline.txt | Added golden baseline snapshot for relationship equivalence checks. |
| RuntimeViewerCore/Tests/RuntimeViewerCoreTests/RuntimeObjCRelationshipIndexTests.swift | New unit tests pinning correctness properties of the rebuilt relationship tables. |
| RuntimeViewerCore/Tests/RuntimeViewerCoreTests/RelationshipsWithoutProgressStreamTests.swift | New regression test ensuring relationship data survives when no progress stream is supplied. |
| RuntimeViewerCore/Tests/RuntimeViewerCoreTests/RelationshipsEquivalenceSnapshotTests.swift | New end-to-end snapshot test for RuntimeEngine.relationships(for:) output equivalence. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Utils/ObjCDump+SemanticString.swift | Deleted app-owned ObjCDump→Semantic rendering implementation now provided by the library. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Utils/MachOImage+AddressFormatting.swift | Deleted local address formatting helpers (now using library/shared equivalents). |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Transformer/Transformer+ObjCIvarOffset.swift | Deleted ObjC transformer module moved to MachOObjCSection. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Transformer/Transformer+CType.swift | Deleted ObjC transformer module moved to MachOObjCSection. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Transformer/Transformer+Configuration.swift | Added RuntimeViewer-owned aggregate configuration spanning ObjC+Swift transformer halves. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Transformer/Transformer.swift | Updated re-exports to point at new transformer namespace/modules split across libraries. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Relationships/RuntimeRelationshipsResolver.swift | Switched ObjC relationship queries to use objcRelationshipIndex + new reference type. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Relationships/RuntimeObjCRelationshipIndex.swift | Added per-image relationship reverse-table builder fed by ObjCIndexingEvent. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Indexing/RuntimeSwiftInterfaceIndexer.swift | Updated commentary to reflect ObjC indexer type/name changes. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Indexing/RuntimeObjCInterfaceIndexer.swift | Deleted app-owned ObjC interface indexer (replaced by library indexer). |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Core/RuntimeObjCSection.swift | Rewired ObjC section construction to library indexer/builder; installed unconditional event handler; integrated relationship index. |
| RuntimeViewerCore/Sources/RuntimeViewerCore/Core/ObjCIndexingEvent+LoadingProgress.swift | Added mapping from library indexing phases to RuntimeViewer loading phases. |
| RuntimeViewerCore/Package.swift | Updated dependency pins and product dependencies for moved ObjC/Swift transformer & indexing/rendering layers. |
| RuntimeViewerCore/Package.resolved | Updated lockfile pins (currently inconsistent with manifest for MachOObjCSection). |
| Documentations/README.md | Updated evolution count/list to include new proposals. |
| Documentations/Evolutions/README.md | Added entry for Evolution 0007. |
| Documentations/Evolutions/0007-objc-relationship-index-returns-to-application.md | Added full Evolution 0007 design/rollout document for the relationship-index migration. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Comment on lines
95
to
98
| remote: .package( | ||
| url: "https://github.com/MxIris-Reverse-Engineering/MachOObjCSection", | ||
| exact: "0.7.103", | ||
| exact: "0.8.103", | ||
| ), |
Comment on lines
79
to
83
| "location" : "https://github.com/MxIris-Reverse-Engineering/MachOObjCSection", | ||
| "state" : { | ||
| "revision" : "63e4b8a61d54fe90bb30e87c0c93f6a8b9c181f9", | ||
| "version" : "0.7.103" | ||
| "revision" : "415430845bcafd2309cba7c822e260a3cb811523", | ||
| "version" : "0.8.102" | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Implements Evolution 0007 — ObjC 关系索引归还应用侧, the downstream adaptation of MachOObjCSection 0003.
Two halves, in order:
1. The rendering and indexing layers move to the library
The ObjC renderer and interface indexer were never RuntimeViewer-specific — they turn ObjC metadata into semantic declarations and build a queryable index, which any MachOObjCSection consumer wants — yet ~1500 lines of them sat in this app's core layer. They now ship with MachOObjCSection, so
RuntimeObjCSectiondrops from 617 lines to 471 and is left translating library results into RuntimeViewer domain types.The concrete transformer modules likewise move to the libraries that own their vocabulary. What stays is the aggregate
Transformer.Configuration: it spans both halves, and nothing outside RuntimeViewer persists them as a unit. Re-exports keep every existingTransformer.…reference compiling.2. The relationship tables come back to the application
MachOObjCSection 0003 removed the inheritance and protocol-adoption reverse tables from
ObjCIndexing: the library parses and broadcasts what it finds, and no longer remembers how classes relate.RuntimeObjCRelationshipIndexis where those broadcasts become tables again, one per image, fed by the event stream duringprepare().The hazard here is not the three deleted APIs — the compiler catches those. It is that
eventHandlerquietly changed from an observer into the sole channel carrying relationship data, whileRuntimeObjCSectioninstalled one only when a progress stream was supplied. Six of the seven section-creation call sites pass no progress stream, background indexing among them, so keeping that condition would have emptied the Relationships pane for nearly every image while still compiling and still passing most tests. The handler is now unconditional; only the forwarding of.progressevents depends on there being a stream.Tables build on first query instead of behind a seal-the-index call. Requiring one would have reintroduced exactly the failure this change exists to remove: forget it, or miss it because
prepare()threw, and every query silently returns nothing.RuntimeObjCSectionFactory's aggregate indexer goes away rather than moving — it was only ever written to, sinceRuntimeRelationshipsResolverfans out across images itself.Equivalence
No user-visible change is intended: the Relationships pane keeps its contents and its order.
Pinned by a baseline captured through
relationships(for:)before the pin moved, since that is the only vantage point existing on both sides of the change. Output matches it verbatim: 307NSObjectsubclasses, 9NSCodingand 68NSCopyingconformers, identical in order and inimagePath.Three properties the match rests on get their own unit tests — inline and category adoptions sharing one table, arrival-order replay, and dedup keyed on all three fields so a class reaching one protocol twice with differing
isSwiftStablestays twice.Dependency pins
Moves to the tags carrying the extracted layers: MachOObjCSection 0.8.102, MachOSwiftSection 0.15.0, swift-semantic-string 0.3.0. MachOKit goes to 0.52.100 because 0.8.102 requires it.
This branch cannot resolve against the remote pins yet. MachOSwiftSection 0.15.0 holds MachOObjCSection at
exact0.8.102, so building and testing needsUSING_LOCAL_DEPENDENCIES=1until that pin moves to 0.8.103. This is why the target isnextrather thanmain— next builds against the local sibling checkouts by design.Merge notes
RuntimeViewerCore/Package.resolvedconflicts with next in three places:originHash, MachInjector (next 0.5.0 vs 0.4.3 here) and swift-helper-service (next 0.3.1 vs 0.2.0 here). Take next's versions for both packages and re-resolve so SPM recomputesoriginHash; every pin unique to this branch merges cleanly and must be kept.feature/node-store-adoption) on five files,RuntimeObjCInterfaceIndexer.swiftmost substantially — both lines rewrote it. Whichever lands second needs a real merge, not a side pick.removeSubIndexerto plug the leak the aggregate indexer caused — with no aggregate there is nothing to detach.