An ObjC category (`@interface Foo (Cat)` in `Foo+Cat.h`) keys its class
node and methods off the base stem `Foo`, so they fold into `Foo.h`'s
class (#1556). extract() turns an id minted from an absolute input path
into the repo-relative form only when it starts with its own file's stem
prefix (`.../Foo+Cat`), so these ids kept the absolute form. A category
on a class outside the corpus (`NSString (Extra)`) got a node id with
the checkout path in it, and so did the methods of a category on an
in-corpus class. graph.json then carried the path (#502), two checkouts
of one repo gave different graphs, and an incremental rebuild in a moved
or copied checkout added duplicate nodes.
The remap now also registers a category file's base-stem prefix, after
the file's own prefixes. On SDWebImage, AFNetworking and Kingfisher,
334 / 51 / 17 ids carried the checkout path; now 0, two checkouts give
identical graphs, and absolute and relative input agree. Every edge,
compared by label and file, is unchanged. Through the CLI, SDWebImage's
graph drops 125 duplicate category nodes (a leaked copy beside the clean
copy reached through its include/ symlink) and one false reference.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
(cherry picked from commit 11fe66a3cf)