Problem
PyClass (codeanalyzer/schema/py_schema.py) has no decorators field. PyCallable
has one (py_schema.py:274, filled at syntactic_analysis/symbol_table_builder.py:334),
but the class branch of the builder never reads ClassDef.decorator_list, so every class
decorator is dropped silently — no field, no warning.
Verified on main (6f02581) against a fixture with @dataclass class Account:
CLASS 'app.Account' (has 'decorators' key? False)
method 'doubled' decorators=['property']
The methods carry theirs; the class carries nothing. This loses @dataclass,
@app.errorhandler, Django/pydantic class decorators, and @pytest.mark.* on test
classes — the decorators that classify what a class is.
Scope boundary
Adds decorators: List[str] to PyClass and populates it, mirroring how PyCallable
already works. Does not resolve decorator strings to ids (#128), does not
touch call-graph edges (#129), and does not add any new node type.
Goals
Caveats and known risks
- Schema v2 change, so it enters at
designing-cldk-changes, not a patch. It is
purely additive (new optional field, defaults to []), so the monotonicity gate and
every existing consumer are unaffected. - Sibling analyzers share the vocabulary. TypeScript has class decorators too;
whatever name and shape lands here should be the canonical one, not a Python rename. - Available from L1 (it is symbol-table data), so it must not be gated behind a level.
Definition of done
- The fixture above emits
decorators: ["dataclass"] on app.Account - An inner class with a decorator emits it too
- A class with no decorators emits
[], not a missing key analysis.json(-a 1) ⊆ ... ⊆ (-a 4) still holds- Neo4j
PY_DECORATED_BY traverses from a :PyClass node
Problem
PyClass(codeanalyzer/schema/py_schema.py) has nodecoratorsfield.PyCallablehas one (
py_schema.py:274, filled atsyntactic_analysis/symbol_table_builder.py:334),but the class branch of the builder never reads
ClassDef.decorator_list, so every classdecorator is dropped silently — no field, no warning.
Verified on
main(6f02581) against a fixture with@dataclass class Account:The methods carry theirs; the class carries nothing. This loses
@dataclass,@app.errorhandler, Django/pydantic class decorators, and@pytest.mark.*on testclasses — the decorators that classify what a class is.
Scope boundary
Adds
decorators: List[str]toPyClassand populates it, mirroring howPyCallablealready works. Does not resolve decorator strings to ids (#128), does not
touch call-graph edges (#129), and does not add any new node type.
Goals
PyClass.decorators: List[str] = [], unparsed source strings in source order:PyDecoratornode andPY_DECORATED_BYrelationship,widening its start label from
["PyCallable"]to includePyClass(
neo4j/schema.py:237), plus the flatdecorators: string[]propertySCHEMA_VERSION(additive)Caveats and known risks
designing-cldk-changes, not a patch. It ispurely additive (new optional field, defaults to
[]), so the monotonicity gate andevery existing consumer are unaffected.
whatever name and shape lands here should be the canonical one, not a Python rename.
Definition of done
decorators: ["dataclass"]onapp.Account[], not a missing keyanalysis.json(-a 1) ⊆ ... ⊆ (-a 4)still holdsPY_DECORATED_BYtraverses from a:PyClassnode