The Python collision pre-scan (#3302) recorded module-level functions and
class methods but not module-level class names, so a class sharing an id
with a function or another class after normalization still lost one
declaration to first-wins add_node:
- `class Session` / `def session()` (requests/sessions.py): session() is
absent from the graph, and which one survives depends on declaration order
- `class Foo` / `class FOO`, `class Pair` / `class _Pair`
Record module-level classes in the same scope as functions and salt the
class id with the existing _underscore_salted_nid rule. Methods of a salted
class are minted under the salted id, so the pre-scan now keys their groups
under the class's resolved id; keying them under the plain one would drop
the existing `_get`/`get` protection inside that class. Same-file base-class
references go through the same salt (as C# already does), so
`class Sub(Session)` binds to the real class instead of minting a sourceless
`Session` stub. The pre-scan also looks through decorated_definition, so
`@dataclass class Session` and the `_x` / `@property x` method idiom are
covered too.
Ids change only for files that contain such a collision; cached AST results
for them keep the collapsed ids until the AST cache schema is bumped.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>