mirror of
https://github.com/safishamsi/graphify.git
synced 2026-10-13 23:49:14 +00:00
`def sort[A: Ordering]` desugars to an implicit `Ordering[A]`, so a context
bound is a real dependency the function has on that typeclass -- and the
idiomatic form is more common in modern Scala than the desugared
`(implicit ...)` it compiles to. `context_bound` was not referenced anywhere
in the extractor, so the dependency was invisible wherever it appeared.
Two grammar shapes drive the implementation, both verified against
tree-sitter-scala 0.26.0 before writing the fix:
- `context_bound` is a direct child of `type_parameters`, one per bound, so
the walk belongs in the existing per-function Scala block and needs no new
handler.
- A higher-kinded parameter nests a further `type_parameters` for its own arity
brackets (`def program[F[_]: Async: Temporal]`), so the walk recurses rather
than reading direct children only -- otherwise both bounds on `program` are
missed.
`upper_bound` (`[T <: Comparable[T]]`) is a distinct node type and is
deliberately not matched: a subtype constraint is not a dependency, so an edge
there would assert something the source does not say. Bounds also get their
own `type_bound` context rather than reusing `parameter_type`, so a consumer
can tell a typeclass constraint from a parameter annotation.
One trap worth recording, because the neighbouring code invites it:
`type_parameters` and `parameters` carry the *same* field name on
`function_definition`, so `child_by_field_name("parameters")` returns whichever
comes first. The bounds are therefore located by node type, never by field
name -- a field lookup would read the function's real parameters as bounds. A
regression test pins that `xs: List[A]` still resolves under `parameter_type`
and never under `type_bound`.
Verified:
- uv run pytest tests/test_scala_context_bounds.py -q (10 passed)
- 6 of the 10 new tests fail on the pre-fix tree
- uv run pytest tests/ -q -> 28 failed, 6164 passed, 101 skipped; the 28
failures are byte-identical to the clean-tree baseline and none touch Scala
- uv run ruff check . -> clean
- uv run pyright -> 635 errors, identical to the clean-tree baseline
Co-Authored-By: Claude <noreply@anthropic.com>
(cherry picked from commit e293b64f6e)