Repository navigation
[pull] main from DeusData:main - #137
Merged
Merged
Conversation
A C# attribute stack ([Foo][Bar][Baz]) compiles to separate sibling attribute_list nodes, one per bracket group — not one attribute_list holding several entries. find_jvm_modifiers() used ts_node_child_by_field_name(), which only ever returns the first child registered under a given field, so every attribute after the first bracket group was silently dropped and never produced a DECORATES edge (#1692). find_jvm_modifiers() now returns every matching wrapper (count + out array, capped at MAX_ATTR_WRAPPERS) instead of a single TSNode, and its two callers (extract_decorators, scan_route_annotations) iterate all of them. The multi-match child scan lives in a new helper, cbm_find_children_by_kind() (helpers.c/helpers.h), the multi-match sibling of the existing cbm_find_child_by_kind() — keeps find_jvm_modifiers() a short per-language dispatch that delegates the traversal, same shape it had before this fix. Both callers size `wrappers` at MAX_ATTR_WRAPPERS. scan_route_annotations appends the owner node after the wrappers, so its fill is capped one lower (MAX_ATTR_WRAPPERS_MINUS_1) rather than the array being declared one larger — the MAX_X / MAX_X_MINUS_1 pair this file already uses for MAX_BASES, MAX_PARAMS and MAX_RETURN_TYPES. No-op for the other languages on this switch: Java/Kotlin/Swift use the `modifiers` wrapper, a single node that never repeats, and PHP groups a `#[A] #[B] #[C]` stack under ONE attribute_list holding three attribute_group children, which the previous lookup already returned whole. Signed-off-by: Jumaga2015 <jumaga2015@gmail.com>
A C# method carrying three stacked attributes ([Foo][Bar("x")][Baz]) must
end up with three DECORATES edges, one per bracket group. The fixture is
indexed through the real production pipeline (rh_index) and asserts
rh_count_edges(..., "DECORATES") == 3, so it exercises the MCP path rather
than the extractor in isolation.
Verified to actually reproduce: with find_jvm_modifiers() reverted to its
first-child lookup the suite goes red (decorates=1, expected 3), and green
again with the fix in place.
C#-only by design. Parsing the equivalent fixtures with the vendored
grammars shows `[A] [B] [C]` yields three sibling `attribute_list` nodes in
C#, while PHP's `#[A] #[B] #[C]` yields ONE `attribute_list` holding three
`attribute_group` children — the pre-fix lookup already found all of them,
so PHP could not hit this bug and a stacked-PHP fixture would pass either
way. Java/Kotlin/Swift use the `modifiers` wrapper, a single node that never
repeats. PHP's DECORATES path stays covered by mkc_c3_php8_attribute
(tests/test_matrix_known_classes.c).
Registered in repro_main.c and Makefile.cbm's TEST_REPRO_SRCS.
Signed-off-by: Jumaga2015 <jumaga2015@gmail.com>
Fixes #1760 Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
Signed-off-by: astandrik <astandrik@yandex-team.ru>
Signed-off-by: astandrik <astandrik@yandex-team.ru>
Brings the branch onto current main (fe85a6b) as promised on the PR: the only conflict was internal/cbm/helpers.h, where both sides added declarations after cbm_find_child_by_kind; both blocks are kept (the PR's cbm_find_children_by_kind prototype, then main's Lisp-family gates). Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
check_projection_scope models declared names in a fixed 32-entry array and skipped the check entirely when a query declared more. Nothing bounded how many variables a pattern could declare, so the out-of-scope refusal added by #1922 switched itself off on a wide query: the same undeclared name was refused at 10 declared names and quietly accepted at 35, answering a column of empty strings. Skipping was deliberate — a wrong refusal costs the caller a working query, which is worse than the silence. The premise was wrong. A binding holds CYP_MAX_VARS node variables and CYP_MAX_EDGE_VARS edge variables in plain arrays, and binding_set and binding_set_edge drop anything past those without a word, so a query naming more cannot be answered at all. Its extra names bind to nothing and project as blanks, which reads as "the graph holds no such data". The choice was never refuse-or-stay-quiet; it was refuse, or answer wrong. So bound the input. check_pattern_var_capacity counts distinct node and edge variables across every pattern — they share one binding, and an OPTIONAL MATCH pattern sits in the same array — and refuses beyond what a binding holds, naming the limit and how to get under it. Leaving the name off a node frees its slot, because an unnamed node takes none. Bounding the input rather than each consumer also makes three other silent drops unreachable: binding_set past 16, binding_set_edge past 8, and the column collection in execute_default_projection. Those would otherwise need an error path threaded up through every caller, since both binding setters return void. The two `< 0` branches in check_projection_scope stay, with comments saying they can no longer fire. They keep the guard standing if either bound ever moves. Fixes #1995 Signed-off-by: Joshua Richter <jrichter5781@gmail.com>
…914) The POSIX parent-death watchdog (#407) was excluded on Windows with the comment "job objects handle this". They do not: the KILL_ON_JOB_CLOSE job in subprocess.c only wraps processes CBM spawns itself. An MCP stdio server is spawned BY the client as its child, and Windows never propagates a parent's termination to its children, so a force-killed client (editor crash, task manager, CI timeout) leaves the server lingering forever blocked on stdin. The orphan pins SQLite WAL read locks, blocking checkpoints (#1083) and feeding the delete_project permission-denied chain from #914. Windows has no reparenting to poll for, so instead of getppid polling the watchdog opens a SYNCHRONIZE handle to the parent at startup and waits on it: the kernel signals a process handle exactly once on termination, and the held handle pins the process object, so PID reuse cannot fool the wait. The 500 ms loop timeout exists only to re-check g_shutdown, mirroring the POSIX poll cadence. On a signaled parent the thread takes the same deliberate _exit(0) as POSIX: after the owning client is gone, kernel handle reclamation is the only trustworthy release for the daemon connection, file locks and the WAL read lock. When no trustworthy parent signal exists at startup (snapshot failed, reserved PID, parent already exited, or the handle cannot be opened), the client keeps running and leans on the stdin EOF path - the same fail-open choice as the POSIX initial_ppid <= 1 bail-out - while a watchdog thread creation failure stays fail-closed. Workers are unchanged: they are spawned inside CBM's own kill-on-close job, which is the containment the old comment assumed everyone had. The parent-watchdog shell test now runs on MSYS2 instead of skipping: an MSYS bash wrapper launches the native server over an anonymous pipe (an MSYS FIFO is not readable by native binaries), a writer helper holds the write end open so the exit can only come from the watchdog, and the kill resolves the child's Windows-physical parent (the pipeline subshell, not the wrapper script process - the watchdog watches the Toolhelp ParentProcessId) and TerminateProcesses exactly that one, because MSYS kill -9 does not reliably terminate the Windows process behind an MSYS pid. Verified against the pre-fix binary: same test, same tree, the old build leaves the server running after the parent dies; this build exits within one watchdog tick. Signed-off-by: 周文瑄 <zhouwx1997@126.com>
CI caught the macOS run exiting 1 AFTER the watchdog assertion passed
('ok: child exited after parent death' followed by exit code 1): the
kill_hard helper resolved the Windows pid with 'ps -W', an MSYS-only
flag. Under 'set -euo pipefail' the failing ps aborts the helper, the
'[[ -n ]] && kill_hard' statement inherits that status, and the EXIT
trap turns a passing test into a red job. Linux ps would fail the same
way. Guard the pipeline (empty winpid on POSIX, where the flag does not
exist) and restore the bare '|| true' tail on every cleanup kill, which
the original script had and my refactor dropped.
Signed-off-by: 周文瑄 <zhouwx1997@126.com>
The complexity pass (transitive_loop_depth / recursive) walked Function and Method nodes in temp-id order and each node's CALLS targets in adjacency order. Under parallel extraction the temp ids come from one shared atomic counter, so id order is worker-scheduling order and differs run to run. The cycle guard flags whichever member of a mutual-recursion cycle the DFS enters first, so `recursive` flipped between the members of a cycle across otherwise identical multi-worker runs while the CALLS edge set stayed identical -- a violation of the MT-byte-identical invariant. Evidence: on a 66-file Python fixture of equal-sized mutual-recursion cycles (24 pairs + 6 triangles, adjacent in the size-ordered work queue) a probe saw 3 distinct outputs in 5 runs at 4 workers. The new regression test is RED on main 5/5 (a 4-worker run diverges from the single-threaded run on the first cycle every time) and GREEN with this change. Fix: order the traversal by content only -- seeds sorted by (qualified_name, file_path, start_line), and each node's CALLS targets sorted the same way before recursing, through one bump-stack scratch sized to the CALLS edge count (a single upfront allocation that bails the way the existing calloc path does). Semantics are unchanged: the DFS entry node of a cycle is the one flagged, as before; which member that is now depends on the inputs alone, identically for sequential and parallel indexing. SCC-based marking of every cycle member is out of scope here. Test: pipeline_complexity_props_independent_of_worker_order indexes the fixture once single-threaded and six times with CBM_WORKERS=4 through the same harness as the sequential/parallel parity test, collects every Function's complexity props sorted by qualified_name, and asserts all parallel runs are identical to the sequential run. Distilled from #1925 with co-author credit. Verification: build/c/test-runner pipeline complexity extraction (ASan/UBSan) 617 passed, 0 failed; revert-check RED 5/5 on main, GREEN with the fix; make -f Makefile.cbm lint-ci clean; scripts/check-no-test-skips.sh OK. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com> Co-authored-by: Zhiyu <zhiyuzhang001@gmail.com>
The head of the first pattern is bound whether the query names it or not: execute_single falls back to the synthetic name "_n0". The capacity check counted only names, so an unnamed head plus 16 named nodes passed it and binding_set then dropped the 16th name without a word — the same silence this guard exists to remove. Count that slot, and name the synthetic variable once instead of twice. Signed-off-by: Joshua Richter <jrichter5781@gmail.com>
phase1_scan_functions() in pass_semantic_edges.c sorts the collected Function/Method node pointers so the func order is deterministic. When the graph has no Function or Method node at all -- a struct-only or config-only project -- node_ptrs is never allocated and the call becomes qsort(NULL, 0, ...). The func_count <= 0 early-out lives in phase 1b, which runs only after phase 1 has returned, so it never guards this call. A NULL qsort base is undefined behaviour. glibc declares the parameter nonnull, so UBSan on the Linux leg reports "null pointer passed as argument 1, which is declared to never be null" at the call. The macOS SDK carries no such attribute, so neither the default sanitizer build nor the Homebrew LLVM diag lane can flag it there. The existing pipeline_docstring_go_class test already reaches the call on Linux; the harness never gated on recoverable UBSan reports, so it went unnoticed. Guard the sort on func_count > 0. The new test pipeline_semantic_edges_no_functions indexes a Go struct-only fixture through the full pipeline and pins the fixture to what it claims (Struct >= 1, Function = Method = 0). On the Linux leg with UBSAN_OPTIONS=halt_on_error=1 the pipeline suite aborts at the qsort call before the fix and completes with it. Distilled from #1810 with co-author credit. Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com> Co-authored-by: Yusuf S. Demirci <ysf-samet@outlook.com>
The markerless stale-rendezvous recovery test reset the activation runtime parent to NULL instead of restoring g_cli_suite_runtime_parent, so every later cli test ran the activation probe against the developer's real /tmp/cbm-daemon-<uid>. Restore the suite value per the contract at tests/test_cli.c:61-65 and the sibling at :1310. Signed-off-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
…963) scripts/setup-windows.ps1 has 326 lines and its parse-coverage report read "113-113,113-113,245-327" — the same line named twice, and an end line that does not exist. Two separate faults, both in cbm_error_regions_push. Past-EOF end line. A tree-sitter node that ends at column 0 stopped right after the previous line's newline, so it holds no text on the row it points at. Adding 1 to that row named a line past the end of the file whenever the region ran to EOF. The node here is start=(244,2) end=(326,0). Clamp the end to the row above when the end column is 0 and the node spans more than one row. Duplicate range. Line 113 carries two separate ERROR nodes, at columns 25-29 and 31-32, and each pushed its own range. A line range says nothing new the second time. Drop a range that exactly repeats the one already open. The drop runs BEFORE the cap check, so a repeat is never miscounted as a range the cap threw away. Only an EXACT repeat is dropped, never a range that merely overlaps. Each range is judged separately afterwards by cbm_region_is_recovered, which asks whether definitions starting inside that range cover it. Two ranges holding the same numbers always get the same verdict, so dropping the repeat changes nothing. Two different ranges do not. Merging 3-3 into 2-3 hands the wider range's covering definition to an error that definition does not explain, and a real parse failure then vanishes from the report. That is not hypothetical. An earlier version of this commit merged on overlap and broke perl_malformed_source_remains_partial_issue1838, the test added with the Perl grammar refresh in 17b5a43. The malformed fixture produces two ERROR nodes, at lines 2-3 and 3-3. Merged, the 2-3 range looks fully covered by before_error and is removed, so parse_incomplete comes back false on a file that plainly does not parse. That test now pins this boundary. The real file reports "113-113,245-326". Two tests, both proved RED first with the exact expected text: coverage_repeated_error_line_reports_one_range_issue963 "2-2,2-2" != "2-2" coverage_range_never_ends_past_the_last_line_issue963 "1-5" != "1-4" Suites run on this change: parse_coverage 34, extraction 325, pipeline 264, mcp 246, index_resilience 7 — all passing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Signed-off-by: Joshua Richter <jrichter5781@gmail.com>
…cate-and-eof fix(coverage): stop reporting a duplicate range and a line past EOF (#963)
…le-count fix(cypher): refuse a query naming more variables than a binding holds
…guard fix(pipeline): skip the function sort when the graph has no functions
fix(main): exit Windows stdio servers when the spawning client dies (#914)
…very fix: recover markerless stale rendezvous sockets during activation
…tic-order fix(pipeline): make the complexity pass independent of worker id order
…leanup fix(codex): replace global guidance with an activation pointer
…ute-decorates fix(extract): scan every attribute_list sibling, not just the first (#1692)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )