mirror of
https://github.com/DeusData/codebase-memory-mcp.git
synced 2026-10-21 05:59:35 +08:00
The test-impact engine selects tests by walking the graph, so it can only be as right as the graph. Three gaps made it wrong: One identity for a definition's mutually exclusive variants - A definition written once per #if/#else branch, per #[cfg], per platform file (foo_linux.c / foo_win.c, platform directories) or per Go build tag is ONE node. The graph buffer keeps every variant's span in a `variants` node property (definition labels only), so a change in any variant maps to the definition. - Extraction now sees definitions inside conditional blocks where it skipped them: C++/C#/ObjC class members under #if (one cursor walk, conditional block types per language in lang_specs), Elixir defs under if/unless, Fortran .F90/.F95/.F03/.F08, Rust #[cfg] twins (no more `name#cfg(...)` QNs that lost every call), C platform files and directories (non-static file-scope functions). - Haskell: the vendored scanner reads only an #if group's first branch. The grammar stays upstream; every further branch is parsed as its own same-length view (cpp_branch_views.c) and adds what the raw parse missed. haskell/bytestring: no new partial parses, +27 functions, IMPORTS 322 -> 329, 131 definitions with variant spans. - Incremental closure repair re-parses every file of such a definition when one of them changes (variant partners through DEFINES), so a repair equals a full index. No cross-language name guesses - A name-only resolution (unique_name, suffix_match, qualified_suffix, field_type_hint, and same_module across files that only share a path stem) never binds a symbol another language defines. - Bash imports are the files a script sources: every top-level command was read as an import of its name (`set -e` imported "set", bound to a TSX method in 137 scripts here). - This repository: cross-language CALLS 5,916 -> 5,091; the remainder are C/C++ pairs, builtins and same-stem module collisions (recorded). SPAWNS edges (per language, like the HTTP client patterns) - A call that starts a program (subprocess.run, exec.Command, child_process.spawn, posix_spawn, system, Process.Start, Command::new, ... about 30 languages, through the file's own imports) gets a SPAWNS edge to a Process node named after the program (literal first word, or <dynamic>) instead of a CALLS guess. No target resolution. Both resolvers ask at the same point (parity test). The engine follows the graph - Seeds map changed lines through every variant span; a test written once per #if branch is one test; when a change reaches a non-test `main`, the tests that spawn processes are reached too (the process runs main, and main reaches everything). Signed-off-by: Martin Vogel <martin.vogel.tech@gmail.com>
72 lines
3.4 KiB
C
72 lines
3.4 KiB
C
/*
|
|
* spawn_patterns.h — process-spawning call sites, per language.
|
|
*
|
|
* Like the HTTP client tables in service_patterns.h: a call that starts
|
|
* another program (subprocess.run, exec.Command, posix_spawn, Process.Start,
|
|
* Command::new, ...) becomes a SPAWNS edge to a Process node named after the
|
|
* program it starts. Nothing resolves the program to code: the edge records
|
|
* that the caller leaves the graph through a process boundary, and which
|
|
* program it starts when the call spells it as a literal.
|
|
*/
|
|
#ifndef CBM_SPAWN_PATTERNS_H
|
|
#define CBM_SPAWN_PATTERNS_H
|
|
|
|
#include "cbm.h"
|
|
|
|
#include <stdbool.h>
|
|
#include <stddef.h>
|
|
|
|
/* How a table spelling matches a call. */
|
|
typedef enum {
|
|
/* The full spelling, written out or reached through the file's imports
|
|
* (`sp.run` with `import subprocess as sp`, `run` from
|
|
* `from subprocess import run`, Go `exec.Command` from "os/exec"). */
|
|
CBM_SPAWN_QUALIFIED = 0,
|
|
/* A bare name (`system`, `popen`, `exec`): the spelling alone. A
|
|
* definition of that name in the calling module (or one the call reaches
|
|
* through an import) still makes it an ordinary call. */
|
|
CBM_SPAWN_BARE,
|
|
/* A bare name that counts when the file imports `module`
|
|
* (Haskell `callProcess` with System.Process, a destructured
|
|
* `const { spawn } = require("child_process")`). */
|
|
CBM_SPAWN_BARE_IMPORTED,
|
|
/* Groovy `"git status".execute()`: the receiver is the command line. */
|
|
CBM_SPAWN_STRING_RECEIVER,
|
|
} cbm_spawn_rule_t;
|
|
|
|
typedef struct {
|
|
const char *api; /* canonical spelling: "subprocess.run", "os/exec.Command", "system" */
|
|
const char *module; /* the import a CBM_SPAWN_BARE_IMPORTED name needs, else NULL */
|
|
unsigned char rule; /* cbm_spawn_rule_t */
|
|
signed char arg; /* argument holding the program or command line */
|
|
signed char alt; /* second place to look, -1 for none (CreateProcess: name or line),
|
|
* or CBM_SPAWN_ANY_LITERAL */
|
|
} cbm_spawn_api_t;
|
|
|
|
/* `alt` value: the program is the first literal anywhere in the argument,
|
|
* which is an options tuple or struct (Elixir {:spawn, "cat"}, Zig
|
|
* .{ .argv = &.{"ls"} }). Elsewhere only a leading literal or a collection's
|
|
* first element is the program. */
|
|
#define CBM_SPAWN_ANY_LITERAL (-2)
|
|
|
|
/* The spawn API a call names, or NULL. `imports` are the calling file's own
|
|
* import statements (local name -> module path) as extracted, external
|
|
* modules included: subprocess or os/exec never resolve to project nodes, so
|
|
* the resolver's import map does not hold them. Whether the call is a spawn
|
|
* after all is the resolver's to decide: an evidence-backed resolution onto
|
|
* project code (an import, the same module, the LSP; never a name guess)
|
|
* makes it an ordinary call (src/pipeline/pass_spawns.c). */
|
|
const cbm_spawn_api_t *cbm_spawn_match(CBMLanguage lang, const char *callee,
|
|
const CBMImport *imports, int count);
|
|
|
|
/* The program a matched spawn starts: the first literal in its program
|
|
* argument, that literal's first word, without directories
|
|
* ("/usr/bin/git status" -> "git"). CBM_SPAWN_DYNAMIC when the program is
|
|
* not a literal. Writes into buf (at least CBM_SPAWN_PROGRAM_MAX bytes). */
|
|
#define CBM_SPAWN_DYNAMIC "<dynamic>"
|
|
#define CBM_SPAWN_PROGRAM_MAX 64
|
|
void cbm_spawn_program(const cbm_spawn_api_t *api, CBMLanguage lang, const CBMCall *call, char *buf,
|
|
size_t n);
|
|
|
|
#endif
|