Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,15 @@ adheres to [Semantic Versioning](https://semver.org/).
next to `HOME` (#692 class 5, 1 Windows failure in run 38008915302).
`Path.expanduser` reads `USERPROFILE` on Windows and ignores `HOME`, so
`~/state` resolved under the runner's real profile instead of the test root.
- The Kotlin walker tests pinned tree-sitter's error recovery instead of the
walker: their fixture `class A { fun m() {} class B { ... } }` is not valid
Kotlin (declarations need a newline or `;`), so the expected definitions
changed with the grammar release, and bumping tree-sitter-language-pack to
1.23.1 (#932) failed `unit` on `TestKotlin` (run 42350563661). The fixture is
now valid Kotlin, a test asserts it parses without error, and the pin moves
to `<1.24`, locked at 1.23.1, whose grammar parses a bare `object O { ... }`
as an `object_declaration`: `O` and `O.o` are now reported where 1.22.1
dropped `O` and left `o` unqualified.
- Four `validate_memory` tests write their file references the way the
platform writes paths (#692 class 5, 4 Windows failures in run 38008915302).
`f"{tmp_path}/a.py"` mixes `\` and `/` on Windows, and the extractor reads
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ codebase = [
#
#
#
"tree-sitter-language-pack>=1.12.5,<1.23",
"tree-sitter-language-pack>=1.12.5,<1.24",
"networkx>=3.0",
# source: ADR-0874
#
Expand Down
50 changes: 34 additions & 16 deletions tests_py/core/test_ast_extractor_walkers.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,14 @@

Every expectation below was measured against the implementation, not
predicted, then read back against the source to confirm it is the intended
contract rather than a bug being frozen. Three measured behaviours are
contract rather than a bug being frozen. Two measured behaviours are
surprising enough to name explicitly, and are pinned here as *current*
behaviour so that changing them becomes a deliberate act with a failing test,
not an accident:

* Swift `enum`/`struct` report kind ``class``. tree-sitter-swift parses all
three as ``class_declaration``, so ``_SWIFT_KIND_MAP``'s
``enum_declaration`` and ``struct_declaration`` entries never match.
* Kotlin ``object O { ... }`` emits no entry for ``O``, and its members are
attributed to no type (``o``/``function``, not ``O.o``/``method``).
* Ruby ``def self.name`` is not emitted at all — it parses as
``singleton_method``, which the walker does not handle.

Expand Down Expand Up @@ -63,9 +61,17 @@ class Inner { void deep() {} }
}
"""

# Valid Kotlin: members of `A` sit on their own lines, because Kotlin needs a
# newline or `;` between declarations. The earlier one-line `class A { fun m()
# {} class B {...} }` was a syntax error the walker only read through the
# grammar's error recovery, so its output tracked the grammar release, not the
# walker (tree-sitter-language-pack 1.23.1 recovers differently and lost `A.m`).
KOTLIN_SOURCE = b"""interface I { fun x() }
object O { fun o() {} }
class A { fun m() {} class B { fun deep() {} } }
class A {
fun m() {}
class B { fun deep() {} }
}
fun top() {}
"""

Expand Down Expand Up @@ -158,29 +164,41 @@ def test_full_definition_set_in_document_order(self) -> None:
assert _defs("kotlin", KOTLIN_SOURCE, extract_kotlin_definitions) == [
("I", "interface"),
("I.x", "method"),
("o", "function"),
("O", "class"),
("O.o", "method"),
("A", "class"),
("A.m", "method"),
("A.deep", "method"),
("B", "class"),
("B.deep", "method"),
("top", "function"),
]

def test_object_declaration_emits_no_type_entry(self) -> None:
"""Pins the surprise: a bare `object O` yields nothing for O, and its
member is unqualified. Changing this should require editing this
assertion.
def test_fixture_is_valid_kotlin(self) -> None:
"""The walker contract is pinned on source the grammar accepts. On a
syntax error the definitions come from error recovery, which changes
between grammar releases (the reason this fixture was rewritten).
"""
from tree_sitter_language_pack import get_parser

assert not get_parser("kotlin").parse(KOTLIN_SOURCE).root_node.has_error

def test_bare_object_declaration_emits_a_type_entry(self) -> None:
"""`object O { ... }` with no supertype is an `object_declaration`
carrying a `type_identifier` in tree-sitter-language-pack 1.23.1, so O
is reported and its member is qualified. The 1.22.1 grammar parsed it
as an `infix_expression` with an ERROR, which is why an earlier
version of this test pinned "no entry for O".
"""
from mcp_server.core.ast_extractors_jvm import extract_kotlin_definitions

got = _defs("kotlin", KOTLIN_SOURCE, extract_kotlin_definitions)
assert ("O", "class") not in got
assert ("o", "function") in got
assert ("O", "class") in got
assert ("O.o", "method") in got
assert ("o", "function") not in got

def test_object_with_a_supertype_does_emit_a_type_entry(self) -> None:
"""The contrast that explains the surprise above: with a supertype the
grammar produces a `type_identifier`, so `object_declaration` is a
reachable, observable branch and not dead code. Without this case the
branch's node-type string is unpinned.
"""A supertype does not change the shape: still an
`object_declaration` with a `type_identifier`, members qualified.
"""
from mcp_server.core.ast_extractors_jvm import extract_kotlin_definitions

Expand Down
18 changes: 9 additions & 9 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading