PROBLEM
The TS analyzer disambiguates a get x() / set x() pair only in the dict key inside a class's methods map — sig#get / sig#set (TSNeo4jBackend._method_key, cldk/analysis/typescript/neo4j/neo4j_backend.py) — but TSCallable.signature is the same string for both, derived from the property name rather than the accessor kind (e.g. src/models.User.isAdmin). Only accessor_kind distinguishes them.
The two backends then diverge:
- In-memory (
cldk/analysis/typescript/codeanalyzer/codeanalyzer.py): _add_class iterates cl.methods.values() and _add_callable does self._callables[c.signature] = c. Both accessors share a signature, so the second silently overwrites the first. Every consumer of _iter_callables() / _callables — get_callables_overview, get_method_bodies, get_decorated_callables, get_callsites_for, get_method — sees one row per pair, last-writer-wins, with the loser's decorators, call sites and body text dropped.
- Neo4j: each accessor is its own
:Callable node, so the same query returns two rows sharing one signature, uncollapsed.
Net: overview row counts differ (1 vs 2), bodies and call sites reflect only the surviving accessor in-memory, and decorator handling diverges too — _OVERVIEW_RETURN aggregates with collect(DISTINCT d.name) while TSCallableOverview.from_callable keeps c.decorators with duplicates intact.
SCOPE BOUNDARY
Signature identity for TS accessors, and the decorator dedup semantics that fold into the same family. Not the analyzer's emission — this is an SDK-side identity problem. Not the Python or Java facades.
GOALS
CAVEATS AND KNOWN RISKS
- Latent, not observed. The current sample app has only an unpaired getter (
src/models.User.isAdmin), so nothing exercises this today. It surfaces the moment any analyzed app declares a paired accessor.
tests/analysis/typescript/test_typescript_bulk_parity_live.py (added for #298) runs against that same fixture and therefore cannot see either divergence — the suite is not wrong, it is under-fixtured. Extending the fixture is what makes the parity suite able to catch this.
- Changing
signature changes a public, user-visible field. Anyone holding TS signature strings is affected, so this is breaking for accessors and belongs in a major.
DEFINITION OF DONE
- On a fixture containing a paired
get/set, both backends return the same row count and the same per-accessor bodies, call sites and decorators.
- A callable decorated twice with one name behaves identically across backends.
- The live parity suite fails before the fix and passes after.
PROBLEM
The TS analyzer disambiguates a
get x()/set x()pair only in the dict key inside a class'smethodsmap —sig#get/sig#set(TSNeo4jBackend._method_key,cldk/analysis/typescript/neo4j/neo4j_backend.py) — butTSCallable.signatureis the same string for both, derived from the property name rather than the accessor kind (e.g.src/models.User.isAdmin). Onlyaccessor_kinddistinguishes them.The two backends then diverge:
cldk/analysis/typescript/codeanalyzer/codeanalyzer.py):_add_classiteratescl.methods.values()and_add_callabledoesself._callables[c.signature] = c. Both accessors share a signature, so the second silently overwrites the first. Every consumer of_iter_callables()/_callables—get_callables_overview,get_method_bodies,get_decorated_callables,get_callsites_for,get_method— sees one row per pair, last-writer-wins, with the loser's decorators, call sites and body text dropped.:Callablenode, so the same query returns two rows sharing onesignature, uncollapsed.Net: overview row counts differ (1 vs 2), bodies and call sites reflect only the surviving accessor in-memory, and decorator handling diverges too —
_OVERVIEW_RETURNaggregates withcollect(DISTINCT d.name)whileTSCallableOverview.from_callablekeepsc.decoratorswith duplicates intact.SCOPE BOUNDARY
Signature identity for TS accessors, and the decorator dedup semantics that fold into the same family. Not the analyzer's emission — this is an SDK-side identity problem. Not the Python or Java facades.
GOALS
accessor_kindintoTSCallable.signatureso a getter/setter pair no longer collides — mirroring the#get/#setdisambiguation_method_keyalready does, but at the signature level so both backends see it consistently._callablesmap and_methods_by_classvalues.collect(DISTINCT ...)versus list-with-duplicates, one way or the other.get x()/set x()and a callable decorated twice with the same name.CAVEATS AND KNOWN RISKS
src/models.User.isAdmin), so nothing exercises this today. It surfaces the moment any analyzed app declares a paired accessor.tests/analysis/typescript/test_typescript_bulk_parity_live.py(added for #298) runs against that same fixture and therefore cannot see either divergence — the suite is not wrong, it is under-fixtured. Extending the fixture is what makes the parity suite able to catch this.signaturechanges a public, user-visible field. Anyone holding TS signature strings is affected, so this is breaking for accessors and belongs in a major.DEFINITION OF DONE
get/set, both backends return the same row count and the same per-accessor bodies, call sites and decorators.