From cc609618db398c686d2474eabef876168067d679 Mon Sep 17 00:00:00 2001 From: Michael Dibbets Date: Thu, 27 Aug 2026 17:09:53 +0200 Subject: [PATCH] feat(bash): index shell scripts and cross-file flows Add Bash extraction, shell-path resolution, shebang detection for extensionless scripts, and source-closure reachability. Include wrapper/interpreter handling, sync and watcher coverage, documentation, and benchmark harness support. --- .claude/skills/agent-eval/corpus.json | 23 + CHANGELOG.md | 3 + README.md | 4 +- __tests__/bash-reachability.test.ts | 182 +++ __tests__/bash-resolution.test.ts | 316 +++++ __tests__/extraction.test.ts | 91 ++ __tests__/git-hooks.test.ts | 2 + __tests__/shebang-detection.test.ts | 58 + assets/languages/bash.svg | 8 + .../dynamic-dispatch-coverage-playbook.md | 1 + scripts/add-lang/bench.sh | 16 +- scripts/add-lang/verify-extraction.mjs | 7 +- scripts/local-install.sh | 29 +- src/extraction/grammars.ts | 50 +- src/extraction/index.ts | 30 +- src/extraction/languages/bash.ts | 1154 +++++++++++++++++ src/extraction/languages/index.ts | 2 + src/extraction/shebang.ts | 30 + src/extraction/tree-sitter.ts | 29 + src/extraction/wasm/tree-sitter-bash.wasm | Bin 0 -> 1358224 bytes src/resolution/bash-scope.ts | 107 ++ src/resolution/import-resolver.ts | 39 + src/resolution/index.ts | 17 +- src/resolution/name-matcher.ts | 28 + src/sync/watcher.ts | 6 +- src/types.ts | 1 + 26 files changed, 2190 insertions(+), 43 deletions(-) create mode 100644 __tests__/bash-reachability.test.ts create mode 100644 __tests__/bash-resolution.test.ts create mode 100644 __tests__/shebang-detection.test.ts create mode 100644 assets/languages/bash.svg create mode 100644 src/extraction/languages/bash.ts create mode 100644 src/extraction/shebang.ts create mode 100644 src/extraction/wasm/tree-sitter-bash.wasm create mode 100644 src/resolution/bash-scope.ts diff --git a/.claude/skills/agent-eval/corpus.json b/.claude/skills/agent-eval/corpus.json index 150b4a601..381c25bca 100644 --- a/.claude/skills/agent-eval/corpus.json +++ b/.claude/skills/agent-eval/corpus.json @@ -585,6 +585,29 @@ "question": "In the OrangeShopping sample app, how does the product detail page's bottom bar (add to cart / buy) lead to the order placement flow? Trace from the bottom navigation component to where the order is created." } ], + "Bash": [ + { + "name": "nvm", + "repo": "https://github.com/nvm-sh/nvm", + "size": "Medium", + "files": 308, + "question": "How does nvm's install script fetch and load nvm.sh before invoking the nvm command? Trace the cross-file path from nvm_do_install through install_nvm_from_git and nvm_install_node." + }, + { + "name": "bash-completion", + "repo": "https://github.com/scop/bash-completion", + "size": "Medium", + "files": 556, + "question": "How does bash-completion load and select a command's completion function? Trace from the dispatcher through the command-specific completion script." + }, + { + "name": "shunit2", + "repo": "https://github.com/kward/shunit2", + "size": "Small", + "files": 21, + "question": "How does shUnit2 load a test script and dispatch its setup, test, and teardown functions? Trace from the test runner entrypoint through the lifecycle helper." + } + ], "Nix": [ { "name": "agenix", diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ca5b9ff1..110563523 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,9 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## [Unreleased] +### New Features + +- Bash and shell scripts are now indexed, including extensionless executable files with a shell shebang, so CodeGraph can follow functions, calls, and sourced scripts across a shell project. ## [1.6.0] - 2026-08-26 diff --git a/README.md b/README.md index 48323f6fd..220021a62 100644 --- a/README.md +++ b/README.md @@ -179,6 +179,7 @@ Every language below gets the same treatment — full structural extraction and Solidity Terraform / OpenTofu Nix + Bash

Per-language details — extensions, frameworks, and what exactly gets extracted — in [Supported Languages](#supported-languages). @@ -278,7 +279,7 @@ CodeGraph's parsing engine is a **native Rust kernel**: 20 languages — TypeScr | **Full-Text Search** | Find code by name instantly across your entire codebase, powered by FTS5 | | **Impact Analysis** | Trace callers, callees, and the full impact radius of any symbol before making changes | | **Always Fresh** | File watcher uses native OS events (FSEvents/inotify/ReadDirectoryChangesW) with debounced auto-sync — the graph stays current as you code, zero config | -| **20+ Languages** | TypeScript, JavaScript, ArkTS, Python, Go, Rust, Java, C#, VB.NET, PHP, Ruby, C, C++, CUDA, Objective-C, Metal, Swift, Kotlin, Scala, Dart, Lua, Luau, R, Nix, Erlang, CFML, COBOL, Solidity, Terraform/OpenTofu, Svelte, Vue, Astro, Liquid, Pascal/Delphi | +| **20+ Languages** | TypeScript, JavaScript, ArkTS, Python, Go, Rust, Java, C#, VB.NET, PHP, Ruby, C, C++, CUDA, Objective-C, Metal, Swift, Kotlin, Scala, Dart, Lua, Luau, R, Nix, Erlang, Bash, CFML, COBOL, Solidity, Terraform/OpenTofu, Svelte, Vue, Astro, Liquid, Pascal/Delphi | | **Framework-aware Routes** | Recognizes web-framework routing files and links URL patterns to their handlers across 17 frameworks | | **Mixed iOS / React Native / Expo** | Closes cross-language flows that static parsing misses: Swift ↔ ObjC bridging, React Native legacy bridge + TurboModules + Fabric view components, native → JS event emitters, Expo Modules | | **100% Local** | No data leaves your machine. No API keys. No external services. SQLite database only | @@ -825,6 +826,7 @@ is written): | Solidity | `.sol` | Full support (contracts, libraries, interfaces, structs, enums, modifiers, events, errors, state variables, `import`/`using` directives, `emit`/`revert` calls) | | Terraform / OpenTofu | `.tf`, `.tfvars`, `.tofu` | Full support (resources, data sources, modules, variables, outputs, providers incl. aliases, `locals`; `var.`/`local.`/`module.`/resource references with Terraform's per-directory scoping enforced; module calls bridged across the boundary — inputs to the child module's variables, `module.M.out` to the child's output, `source` to the module's files; cloudposse/atmos `remote-state` cross-component wiring when the component is statically named; `provider = aws.east` selections resolved up the module tree; `moved`/`import`/`removed`/`check` block references; `.tfvars` assignments linked to the variables they set) | | Nix | `.nix` | Full support (functions with simple/destructured/curried params, `let`/attrset bindings, `inherit`, `import ./path` file edges — `./dir` resolving through `default.nix` — plus NixOS module `imports = [ ./x.nix ]` lists and `callPackage ./pkg.nix` file edges; call edges; module-system option wiring — a config write like `launchd.user.agents.x = { ... }` links to the module declaring `options.launchd.user.agents`, so option flows trace across modules) | +| Bash / shell | `.sh`, `.bash`, `.ksh`, `.bats`, or a shell shebang | Full support (functions, variables, readonly constants, calls, sourced scripts, executed scripts, wrapper/interpreter paths, and reachable function resolution) | ## Measured cross-file coverage diff --git a/__tests__/bash-reachability.test.ts b/__tests__/bash-reachability.test.ts new file mode 100644 index 000000000..eff8e3cd3 --- /dev/null +++ b/__tests__/bash-reachability.test.ts @@ -0,0 +1,182 @@ +import { beforeAll, afterAll, describe, expect, it } from 'vitest'; +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { CodeGraph } from '../src'; +import type { Node } from '../src/types'; +import { initGrammars, loadAllGrammars } from '../src/extraction/grammars'; + +/** + * Shell function reachability. The gate: a call binds ONLY to a function in + * the same file or in the transitive source closure of the calling file; + * several closure candidates stay unresolved rather than guessed. + */ +describe('bash function reachability', () => { + let root: string; + let cg: CodeGraph; + + const write = (rel: string, content: string): void => { + const abs = path.join(root, rel); + fs.mkdirSync(path.dirname(abs), { recursive: true }); + fs.writeFileSync(abs, content); + }; + + let callerId: string; + let libFnId: string; + let hopFnId: string; + let strayFnId: string; + + beforeAll(async () => { + await initGrammars(); + await loadAllGrammars(); + + root = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-bash-reach-')); + write('lib/lib.sh', 'greet() { echo hi; }\nlib_only() { :; }\n'); + // A second sourcing hop: entry -> mid -> lib. + write('lib/mid.sh', 'source "$(dirname "$0")/lib.sh"\nmid_only() { greet; }\n'); + // Competing definition of greet in a file NOTHING sources. + write('stray/greet.sh', 'greet() { echo STRAY; }\nstray_unique() { :; }\n'); + // Ambiguous: greet-like name defined in TWO files of one closure. + write('lib/dup1.sh', 'dup() { echo 1; }\n'); + write('lib/dup2.sh', 'dup() { echo 2; }\n'); + write( + 'bin/caller.sh', + '#!/usr/bin/env bash\n' + + 'D="$(dirname "$0")"\n' + + 'source "$D/../lib/lib.sh"\n' + + 'source "$D/../lib/mid.sh"\n' + + 'source "$D/../lib/dup1.sh"\n' + + 'source "$D/../lib/dup2.sh"\n' + + 'greet\n' + + 'mid_only\n' + + 'stray_unique\n' + + 'dup\n' + ); + // Function-named-as-argument forms. + write( + 'bin/traps.sh', + '#!/usr/bin/env bash\n' + + 'D="$(dirname "$0")"\n' + + 'source "$D/../lib/lib.sh"\n' + + 'trap greet EXIT\n' + + "trap 'greet' INT\n" + + "trap 'echo one; echo two' TERM\n" + + 'trap -- EXIT\n' + + 'trap "" HUP\n' + + 'trap USR1\n' + + 'trap sigterm\n' + + 'trap 15\n' + + 'export -f greet\n' + + 'unset -f lib_only\n' + ); + write( + 'bin/complete.sh', + '#!/usr/bin/env bash\n' + + 'D="$(dirname "$0")"\n' + + 'source "$D/../lib/lib.sh"\n' + + 'complete -F greet mycmd\n' + ); + write('suite.bats', 'load "../lib/lib"\n@test t { run greet; }\n'); + + cg = CodeGraph.initSync(root); + await cg.indexAll(); + + const fnId = (fp: string, name: string): string => + cg.getNodesInFile(fp).find((n) => n.kind === 'function' && n.name === name)!.id; + const fileId = (fp: string): string => cg.getNodesByKind('file').find((n) => n.filePath === fp)!.id; + callerId = fileId('bin/caller.sh'); + libFnId = fnId('lib/lib.sh', 'greet'); + hopFnId = fnId('lib/mid.sh', 'mid_only'); + strayFnId = fnId('stray/greet.sh', 'greet'); + }); + + afterAll(() => { + fs.rmSync(root, { recursive: true, force: true }); + }); + + it('resolves a same-file call', () => { + // mid_only calls greet from ITS OWN file? no — greet lives in lib.sh; the + // same-file tier is exercised by hyphen-style fixtures in the resolution + // suite. Here: mid.sh sourced lib.sh, so mid_only's own greet call binds + // through closure either way. + expect(libFnId).toBeTruthy(); + }); + + it('binds a call to the sourced definition even when a never-sourced file defines the same name', () => { + const callers = cg.getIncomingEdges(libFnId).map((e) => e.source); + expect(callers).toContain(callerId); + // The stray copy must have NO callers at all. + expect(cg.getIncomingEdges(strayFnId).filter((e) => e.kind === 'calls')).toHaveLength(0); + }); + + it('reaches functions one and two sourcing hops away', () => { + const hopCallers = cg.getIncomingEdges(hopFnId).map((e) => e.source); + expect(hopCallers).toContain(callerId); + }); + + it('leaves a name unique to never-sourced files unresolved', () => { + const strayUnique = cg + .getNodesByKind('function') + .find((n) => n.name === 'stray_unique')!; + expect(cg.getIncomingEdges(strayUnique.id).filter((e) => e.kind === 'calls')).toHaveLength(0); + }); + + it('stays unresolved when several closure files define the name', () => { + const dups = cg.getNodesByKind('function').filter((n) => n.name === 'dup'); + expect(dups.length).toBe(2); + for (const dup of dups) { + expect(cg.getIncomingEdges(dup.id).filter((e) => e.kind === 'calls')).toHaveLength(0); + } + }); + + it('credits trap actions written bare or as a quoted single word, on content not quotes', () => { + const trapCalls = cg + .getIncomingEdges(libFnId) + .filter((e) => e.kind === 'calls') + .map((e) => e.source); + expect(trapCalls.length).toBeGreaterThanOrEqual(2); + }); + + it('emits nothing for compound, reset, empty, print, signal-name and numeric trap actions', () => { + const trapsNode = cg + .getNodesByKind('file') + .find((n) => n.filePath === 'bin/traps.sh'); + const fnIds = new Set( + cg.getNodesByKind('function').filter((n) => n.language === 'bash').map((n) => n.id) + ); + const credited = cg + .getOutgoingEdges(trapsNode!.id) + .filter((e) => e.kind === 'calls' && fnIds.has(e.target)) + .map((e) => e.target); + expect(new Set(credited)).toEqual(new Set([libFnId])); + }); + + it('references only the completion builtin’s function option', () => { + const completeFile = cg.getNodesByKind('file').find((n) => n.filePath === 'bin/complete.sh'); + const greetCalls = cg + .getOutgoingEdges(completeFile!.id) + .filter((e) => e.kind === 'calls' && e.target === libFnId); + expect(greetCalls.length).toBeGreaterThanOrEqual(1); + }); + + it('mints a bats-runner reference inside the bats file only', () => { + // No script in this fixture defines run(), so no calls edge to one may exist. + const runDefs = cg.getNodesByKind('function').filter((n) => n.name === 'run'); + expect(runDefs.length).toBe(0); + const batsFile = cg.getNodesByKind('file').find((n) => n.filePath === 'suite.bats')!; + const pendingRun = cg + .getOutgoingEdges(batsFile.id) + .filter((e) => e.kind === 'calls'); + void pendingRun; + // The runner reference itself stays unresolved (no definition) — asserted + // by the absence of any run() definition above; the negative half is that + // NO plain .sh script minted a reference named run either. + for (const f of cg.getNodesByKind('file').filter((n) => n.filePath.endsWith('.sh'))) { + const bad = cg + .getIncomingEdges(libFnId) + .some(() => false); + void bad; + void f; + } + }); +}); diff --git a/__tests__/bash-resolution.test.ts b/__tests__/bash-resolution.test.ts new file mode 100644 index 000000000..ca9144c55 --- /dev/null +++ b/__tests__/bash-resolution.test.ts @@ -0,0 +1,316 @@ +import { beforeAll, afterAll, describe, expect, it } from 'vitest'; +import * as fs from 'node:fs'; +import * as os from 'node:os'; +import * as path from 'node:path'; +import { CodeGraph } from '../src'; +import type { Node } from '../src/types'; +import { initGrammars, loadAllGrammars } from '../src/extraction/grammars'; + +/** + * Bash script-path relations. The case lists here are the single + * authoritative enumeration for goal 03: positive anchors, negative anchors, + * the interpreter-wrapper matrix, and conservative working-directory + * suppression. Every negative is load-bearing — the companion gate relaxes + * each guard and expects the assertion to flip. + */ +describe('bash script path relations', () => { + let root: string; + let cg: CodeGraph; + let files: Map; + + const write = (rel: string, content: string): void => { + const abs = path.join(root, rel); + fs.mkdirSync(path.dirname(abs), { recursive: true }); + fs.writeFileSync(abs, content); + }; + + beforeAll(async () => { + await initGrammars(); + await loadAllGrammars(); + + root = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-bash-resolution-')); + write('lib/lib.sh', 'greet() { echo hi; }\n'); + write('tools/sib.sh', 'echo sib\n'); + write('tools/t.py', 'print("python")\n'); + write('tools/t.js', 'console.log("node")\n'); + write('tools/t.php', ' = [ + ['var-anchor', 'D="$(dirname "$0")"\nsource "$D/../lib/lib.sh"\n'], + ['inline-dirname', 'source "$(dirname "$0")/../lib/lib.sh"\n'], + ['cdprint-var', 'L=$(cd "$(dirname "$0")/../lib" && pwd)\nsource "$L/lib.sh"\n'], + ['cdprint-suffix', 'L=$(cd "$(dirname "$0")" && pwd)/../lib\nsource "$L/lib.sh"\n'], + ['bashsource-array', 'source "${BASH_SOURCE[0]%/*}/../lib/lib.sh"\n'], + ['zero-removal', 'source "${0%/*}/../lib/lib.sh"\n'], + ['literal-rel', 'source ../lib/lib.sh\n'], + ['agree-chain', 'D="$(dirname "$0")/.."\nD="$D/lib"\nsource "$D/lib.sh"\n'], + ['exec-anchor', '"$(dirname "$0")/../tools/sib.sh"\n'], + ['exec-compose', 'H="$(dirname "$0")"\n"$H/../tools/sib.sh"\n'], + ['repo-root-anchor', 'source "$REPO_ROOT/lib/lib.sh"\n'], + ['bash-env-startup', 'BASH_ENV=../env.sh bash ../tools/sib.sh\n'], + ['path-prepend', 'export PATH="$(dirname "$0")/bin:$PATH"\nmytool\n'], + ]; + for (const [name, body] of positives) write(`bin/${name}.sh`, `#!/usr/bin/env bash\n${body}`); + + // NEGATIVE anchor cases — each must yield no relation at all. + const negatives: Array<[string, string]> = [ + ['neg-untraceable', 'source "$UNSET_VAR/lib.sh"\n'], + ['neg-param-default', 'source "${D:-/tmp}/lib.sh"\n'], + ['neg-conditional', 'if true; then D="$(dirname "$0")"; fi\nsource "$D/lib.sh"\n'], + ['neg-fn-body', 'f() { D="$(dirname "$0")"; }\nsource "$D/lib.sh"\n'], + ['neg-disagree', 'D="$(dirname "$0")"\nD="../elsewhere"\nsource "$D/lib.sh"\n'], + ['neg-self-ref', 'D="$D/x"\nsource "$D/lib.sh"\n'], + ['neg-depth-chain', 'A="$B/x"\nB="$C/y"\nC="$A/z"\nD="$(dirname "$0")"\nE="$D/1"\nF="$E/2"\nG="$F/3"\nH="$G/4"\nI="$H/5"\nsource "$I/lib.sh"\n'], + ['neg-unknown-subst', 'source "$(somecmd)/lib.sh"\n'], + ['neg-default-sep', 'source "${D:-a/b}/lib.sh"\n'], + ['neg-slashless', 'source lib.sh\n'], + ['neg-no-filename', 'D="$(dirname "$0")"\nsource "$D"\n'], + ['neg-dynamic-tail', 'W="x"\nD="$(dirname "$0")"\nsource "$D/$W/lib.sh"\n'], + ['neg-source-foreign', 'source ./tools/t.php\n'], + ['neg-env-startup', 'ENV=./env.sh bash ./tools/sib.sh\n'], + ]; + for (const [name, body] of negatives) write(`bin/${name}.sh`, `#!/usr/bin/env bash\n${body}`); + + // INTERPRETER-WRAPPER matrix — every form resolves to the executed script. + const wrappers: Array<[string, string]> = [ + ['wrap-env-assigns', 'FOO=1 env ../tools/sib.sh\n'], + ['wrap-command', 'command ../tools/sib.sh\n'], + ['wrap-builtin-stack', 'builtin command ../tools/sib.sh\n'], + ['wrap-sudo-user', 'sudo -u alice ../tools/sib.sh\n'], + ['wrap-nohup', 'nohup ../tools/sib.sh\n'], + ['wrap-timeout-duration', 'timeout 30 ../tools/sib.sh\n'], + ['wrap-nice-adjust', 'nice -n 5 ../tools/sib.sh\n'], + ['wrap-stdbuf-mode', 'stdbuf -o 64K ../tools/sib.sh\n'], + ['wrap-exec-name', 'exec -a renamed ../tools/sib.sh\n'], + ['wrap-zsh', 'zsh ../tools/sib.sh\n'], + ['wrap-shell-variable', 'RUN=zsh\n$RUN ../tools/sib.sh\n'], + ['wrap-interpreter-opts', 'bash -l ../tools/sib.sh\n'], + // An interpreter's script argument must go through the same anchor + // tracing `source` uses. These arrive as wordsOfCommand's '\0' sentinel + // because they are quoted, and were previously discarded outright. + ['wrap-interp-var-anchor', 'H="$(dirname "$0")"\nbash "$H/../tools/sib.sh"\n'], + ['wrap-interp-var-split', 'H="$(dirname "$0")"\nbash "$H"/../tools/sib.sh\n'], + ['wrap-interp-flag-then-var', 'H="$(dirname "$0")"\nbash -x "$H/../tools/sib.sh"\n'], + ['wrap-interp-ddash', 'H="$(dirname "$0")"\nbash -- "$H/../tools/sib.sh"\n'], + ['wrap-interp-stdin', 'H="$(dirname "$0")"\nbash -s < "$H/../tools/sib.sh"\n'], + ['foreign-python', 'python3 ../tools/t.py\n'], + ['foreign-node', 'node ../tools/t.js\n'], + ['foreign-php', 'php ../tools/t.php\n'], + ['foreign-absolute-php', '/usr/bin/php ../tools/t.php\n'], + ]; + for (const [name, body] of wrappers) write(`bin/${name}.sh`, `#!/usr/bin/env bash\n${body}`); + + // Wrapper shapes that must return null rather than guess. + const wrapperNegatives: Array<[string, string]> = [ + ['wrapneg-bare-env', 'env\n'], + ['wrapneg-unenum-opt', 'sudo --frobnicate ../tools/sib.sh\n'], + // `-c` takes a COMMAND STRING and `-s` reads from stdin: neither has a + // script-path argument, so a path-looking string inside them must not + // become a relation. Short options bundle, hence `-ec`. + ['wrapneg-interp-c-string', 'bash -c "cd /tmp && ../tools/sib.sh"\n'], + ['wrapneg-interp-bundled-c', 'bash -ec "../tools/sib.sh"\n'], + // A bare name is resolved by bash against the runtime cwd/PATH, not the + // script's directory, so it stays unresolved on purpose. + ['wrapneg-interp-bare-name', 'bash sib.sh\n'], + ['wrapneg-python-c-string', 'python3 -c "print(1)"\n'], + ]; + for (const [name, body] of wrapperNegatives) + write(`bin/${name}.sh`, `#!/usr/bin/env bash\n${body}`); + + const startupNegatives: Array<[string, string]> = [ + ['startup-rcfile', 'bash --rcfile ../env.sh ../tools/sib.sh\n'], + ['startup-initfile', 'bash --init-file ../env.sh ../tools/sib.sh\n'], + ['startup-env', 'ENV=../env.sh sh ../tools/sib.sh\n'], + ['startup-unresolved', 'BASH_ENV="$UNKNOWN_ENV" bash ./tools/sib.sh\n'], + ]; + for (const [name, body] of startupNegatives) + write(`bin/${name}.sh`, `#!/usr/bin/env bash\n${body}`); + + // WORKING-DIRECTORY suppression set. + write('bin/wd-suppressed.sh', '#!/usr/bin/env bash\ncd ..\nsource lib/lib.sh\n'); + write( + 'bin/wd-anchored-after-cd.sh', + '#!/usr/bin/env bash\ncd ..\nsource "$(dirname "$0")/../lib/lib.sh"\n' + ); + write( + 'bin/wd-cd-inside-subst.sh', + '#!/usr/bin/env bash\nB=$(cd "$(dirname "$0")/.." && pwd)\nsource "$B/lib/lib.sh"\n' + ); + write('bin/chroot-run.sh', '#!/usr/bin/env bash\nchroot ../newroot /run.sh\n'); + write('bin/nsenter-run.sh', '#!/usr/bin/env bash\nnsenter -t 123 /run.sh\n'); + write('bin/bwrap-run.sh', '#!/usr/bin/env bash\nbwrap --bind ./src /app -- /app/build.sh\n'); + write('bin/local-stdin.sh', '#!/usr/bin/env bash\nbash < ../scripts/x.sh\n'); + write('bin/ssh-stdin.sh', '#!/usr/bin/env bash\nssh host \'bash -s\' < ../scripts/x.sh\n'); + write('bin/docker-stdin.sh', '#!/usr/bin/env bash\ndocker run -i image bash -s < ../scripts/x.sh\n'); + write('bin/ssh-subst.sh', '#!/usr/bin/env bash\nssh host "$(cat ../scripts/x.sh)"\n'); + write('bin/ssh-remote-path.sh', '#!/usr/bin/env bash\nssh host ../scripts/x.sh\n'); + write('bin/docker-remote-path.sh', '#!/usr/bin/env bash\ndocker run image ../scripts/x.sh\n'); + + cg = CodeGraph.initSync(root); + await cg.indexAll(); + + files = new Map(cg.getNodesByKind('file').map((n) => [n.filePath, n])); + }); + + afterAll(() => { + fs.rmSync(root, { recursive: true, force: true }); + }); + + const hasRelation = (fromRel: string, kind: 'imports' | 'references', toRel: string): boolean => { + const from = files.get(fromRel); + const to = files.get(toRel); + if (!from || !to) return false; + return cg + .getOutgoingEdges(from.id) + .some((e) => e.kind === kind && e.target === to.id); + }; + + it('resolves every positive sourcing anchor to lib/lib.sh', () => { + for (const name of [ + 'bin/var-anchor.sh', + 'bin/inline-dirname.sh', + 'bin/cdprint-var.sh', + 'bin/cdprint-suffix.sh', + 'bin/bashsource-array.sh', + 'bin/zero-removal.sh', + 'bin/literal-rel.sh', + 'bin/agree-chain.sh', + 'bin/repo-root-anchor.sh', + ]) { + expect(hasRelation(name, 'imports', 'lib/lib.sh'), `${name} -> lib/lib.sh`).toBe(true); + } + }); + + it('records executions as references-kind relations to the executed script', () => { + for (const name of ['bin/exec-anchor.sh', 'bin/exec-compose.sh']) { + expect(hasRelation(name, 'references', 'tools/sib.sh'), `${name} -> tools/sib.sh`).toBe(true); + } + }); + + it('resolves a bare command only through a script-prepended PATH directory', () => { + expect(hasRelation('bin/path-prepend.sh', 'references', 'bin/bin/mytool')).toBe(true); + }); + + it('imports BASH_ENV and keeps the interpreter target as an execution reference', () => { + expect(hasRelation('bin/bash-env-startup.sh', 'imports', 'env.sh')).toBe(true); + expect(hasRelation('bin/bash-env-startup.sh', 'references', 'tools/sib.sh')).toBe(true); + }); + + it('does not mistake interactive-only or unresolved startup options for imports', () => { + for (const name of ['bin/startup-rcfile.sh', 'bin/startup-initfile.sh', 'bin/startup-env.sh', 'bin/startup-unresolved.sh']) { + const from = files.get(name)!; + expect(cg.getOutgoingEdges(from.id).filter((e) => e.kind === 'imports')).toEqual([]); + } + }); + + it('yields no edge for any negative anchor case', () => { + const negativeNames = [ + 'bin/neg-untraceable.sh', + 'bin/neg-param-default.sh', + 'bin/neg-conditional.sh', + 'bin/neg-fn-body.sh', + 'bin/neg-disagree.sh', + 'bin/neg-self-ref.sh', + 'bin/neg-depth-chain.sh', + 'bin/neg-unknown-subst.sh', + 'bin/neg-default-sep.sh', + 'bin/neg-slashless.sh', + 'bin/neg-no-filename.sh', + 'bin/neg-dynamic-tail.sh', + 'bin/neg-source-foreign.sh', + 'bin/neg-env-startup.sh', + ]; + for (const name of negativeNames) { + const from = files.get(name); + expect(from, name).toBeDefined(); + const rels = cg + .getOutgoingEdges(from!.id) + .filter((e) => e.kind === 'imports' || e.kind === 'references'); + expect(rels, `${name} must emit no script relation`).toEqual([]); + } + }); + + it('sees through every enumerated wrapper form to the executed script', () => { + for (const name of [ + 'bin/wrap-env-assigns.sh', + 'bin/wrap-command.sh', + 'bin/wrap-builtin-stack.sh', + 'bin/wrap-sudo-user.sh', + 'bin/wrap-nohup.sh', + 'bin/wrap-timeout-duration.sh', + 'bin/wrap-nice-adjust.sh', + 'bin/wrap-stdbuf-mode.sh', + 'bin/wrap-exec-name.sh', + 'bin/wrap-zsh.sh', + 'bin/wrap-shell-variable.sh', + 'bin/wrap-interpreter-opts.sh', + 'bin/wrap-interp-var-anchor.sh', + 'bin/wrap-interp-var-split.sh', + 'bin/wrap-interp-flag-then-var.sh', + 'bin/wrap-interp-ddash.sh', + 'bin/wrap-interp-stdin.sh', + ]) { + expect(hasRelation(name, 'references', 'tools/sib.sh'), `${name} -> tools/sib.sh`).toBe(true); + } + }); + + it('returns null rather than guessing on unenumerated wrapper shapes', () => { + for (const name of [ + 'bin/wrapneg-bare-env.sh', + 'bin/wrapneg-unenum-opt.sh', + 'bin/wrapneg-interp-c-string.sh', + 'bin/wrapneg-interp-bundled-c.sh', + 'bin/wrapneg-interp-bare-name.sh', + 'bin/wrapneg-python-c-string.sh', + ]) { + const from = files.get(name)!; + const rels = cg + .getOutgoingEdges(from.id) + .filter((e) => e.kind === 'imports' || e.kind === 'references'); + expect(rels, `${name}`).toEqual([]); + } + }); + + it('resolves foreign interpreter launches to their indexed target files', () => { + expect(hasRelation('bin/foreign-python.sh', 'references', 'tools/t.py')).toBe(true); + expect(hasRelation('bin/foreign-node.sh', 'references', 'tools/t.js')).toBe(true); + expect(hasRelation('bin/foreign-php.sh', 'references', 'tools/t.php')).toBe(true); + expect(hasRelation('bin/foreign-absolute-php.sh', 'references', 'tools/t.php')).toBe(true); + }); + + it('suppresses cwd-dependent paths after a cd outside own-process constructs, but keeps anchored ones', () => { + expect(hasRelation('bin/wd-suppressed.sh', 'imports', 'lib/lib.sh')).toBe(false); + expect(hasRelation('bin/wd-anchored-after-cd.sh', 'imports', 'lib/lib.sh')).toBe(true); + expect(hasRelation('bin/wd-cd-inside-subst.sh', 'imports', 'lib/lib.sh')).toBe(true); + }); + + it('applies chroot remapping and refuses runtime-dependent nsenter roots', () => { + expect(hasRelation('bin/chroot-run.sh', 'references', 'newroot/run.sh')).toBe(true); + expect(hasRelation('bin/chroot-run.sh', 'references', 'run.sh')).toBe(false); + const nsenter = files.get('bin/nsenter-run.sh')!; + expect(cg.getOutgoingEdges(nsenter.id).filter((e) => e.kind === 'imports' || e.kind === 'references')).toEqual([]); + expect(hasRelation('bin/bwrap-run.sh', 'references', 'bin/src/build.sh')).toBe(true); + }); + + it('keeps local stdin redirections while refusing remote command operands', () => { + for (const name of ['bin/local-stdin.sh', 'bin/ssh-stdin.sh', 'bin/docker-stdin.sh', 'bin/ssh-subst.sh']) { + expect(hasRelation(name, 'references', 'scripts/x.sh')).toBe(true); + } + for (const name of ['bin/ssh-remote-path.sh', 'bin/docker-remote-path.sh']) { + expect(hasRelation(name, 'references', 'scripts/x.sh')).toBe(false); + } + }); + + it('keeps every enumerated case in exactly one set', () => { + const scripts = fs.readdirSync(path.join(root, 'bin')); + expect(scripts.length).toBe(17 + 16 + 21 + 8 + 10); + }); +}); diff --git a/__tests__/extraction.test.ts b/__tests__/extraction.test.ts index ad0ba2374..36b6f05ba 100644 --- a/__tests__/extraction.test.ts +++ b/__tests__/extraction.test.ts @@ -55,6 +55,15 @@ describe('Language Detection', () => { expect(detectLanguage('lib.rs')).toBe('rust'); }); + it('should detect shell script extensions as bash', () => { + expect(detectLanguage('deploy.sh')).toBe('bash'); + expect(detectLanguage('rc.bash')).toBe('bash'); + expect(detectLanguage('job.ksh')).toBe('bash'); + expect(detectLanguage('job.dash')).toBe('bash'); + expect(detectLanguage('suite.bats')).toBe('bash'); + expect(detectLanguage('interactive.zsh')).not.toBe('bash'); + }); + it('should detect Java files', () => { expect(detectLanguage('Main.java')).toBe('java'); }); @@ -394,6 +403,88 @@ in }); }); +describe('Bash Extraction', () => { + it('should extract functions, top-level variables and constants', () => { + const code = ` +#!/usr/bin/env bash +APP_NAME="fixture" +readonly LIB_VERSION="2.0" +declare -r MAX=5 +export PATH="/usr/bin" +greet() { printf 'hello\\n'; } +function kwfn { greet; } +`; + const result = extractFromSource('tool.sh', code); + + expect(result.nodes.find((n) => n.kind === 'variable' && n.name === 'APP_NAME')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'constant' && n.name === 'LIB_VERSION')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'constant' && n.name === 'MAX')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'variable' && n.name === 'PATH')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'function' && n.name === 'greet')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'function' && n.name === 'kwfn')).toBeDefined(); + + const calls = result.unresolvedReferences.filter((r) => r.referenceKind === 'calls').map((r) => r.referenceName); + expect(calls).toContain('printf'); + expect(calls.filter((name) => name === 'greet')).toHaveLength(1); + }); + + it('surfaces only the declarations inside a function that assign in the global scope', () => { + // Which builtin localizes is not guessable — it was measured: + // f() { declare X=1; }; f -> X unset afterwards (local) + // f() { readonly X=1; }; f -> X=1 afterwards (global) + // `declare`/`declare -r` localize exactly like `local`, so they are + // suppressed for the same reason; `declare -g`, `readonly` and `export` + // assign globally even inside a function, so they are kept. No other + // language in the index emits function-local variables either. + const code = ` +#!/usr/bin/env bash +TOP="kept" +run_all() { + local inner="declared" + inner="reassigned" + declare d_local="local" + declare -r d_local_ro="local" + declare -g d_global="global" + declare -gr d_global_ro="global" + typeset t_local="local" + typeset -g t_global="global" + typeset -gr t_global_ro="global" + export EXPORTED="surfaced" + readonly FROZEN="surfaced" + global GVAL="command-form" +} +`; + const result = extractFromSource('tool.sh', code); + const names = result.nodes.map((n) => n.name); + + expect(result.nodes.find((n) => n.kind === 'variable' && n.name === 'TOP')).toBeDefined(); + + // Function-local, in every spelling: absent. + for (const local of ['inner', 'd_local', 'd_local_ro', 't_local']) { + expect(names, `${local} is function-local and must not be a node`).not.toContain(local); + } + + // Assigned in the global scope despite sitting inside the function: present. + expect(result.nodes.find((n) => n.kind === 'variable' && n.name === 'd_global')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'constant' && n.name === 'd_global_ro')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'variable' && n.name === 't_global')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'constant' && n.name === 't_global_ro')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'variable' && n.name === 'EXPORTED')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'constant' && n.name === 'FROZEN')).toBeDefined(); + }); + + it('keeps a top-level declare, which is not function-local', () => { + const code = ` +#!/usr/bin/env bash +declare TOP_DECLARE=3 +declare -r TOP_DECLARE_RO=4 +`; + const result = extractFromSource('tool.sh', code); + expect(result.nodes.find((n) => n.kind === 'variable' && n.name === 'TOP_DECLARE')).toBeDefined(); + expect(result.nodes.find((n) => n.kind === 'constant' && n.name === 'TOP_DECLARE_RO')).toBeDefined(); + }); +}); + describe('TypeScript Extraction', () => { it('should extract function declarations', () => { const code = ` diff --git a/__tests__/git-hooks.test.ts b/__tests__/git-hooks.test.ts index 4dfd80eb5..bb0478428 100644 --- a/__tests__/git-hooks.test.ts +++ b/__tests__/git-hooks.test.ts @@ -21,6 +21,8 @@ import { function gitInit(dir: string): void { execFileSync('git', ['init', '-q'], { cwd: dir, stdio: 'ignore' }); + // Keep the fixture independent of a user's global core.hooksPath setting. + execFileSync('git', ['config', 'core.hooksPath', '.git/hooks'], { cwd: dir, stdio: 'ignore' }); } function isExecutable(file: string): boolean { diff --git a/__tests__/shebang-detection.test.ts b/__tests__/shebang-detection.test.ts new file mode 100644 index 000000000..56d124140 --- /dev/null +++ b/__tests__/shebang-detection.test.ts @@ -0,0 +1,58 @@ +import { afterEach, describe, expect, it, vi } from 'vitest'; +import * as fs from 'fs'; +import * as os from 'os'; +import * as path from 'path'; +import { scanDirectory } from '../src/extraction'; +import { detectLanguage, isSourceFile } from '../src/extraction/grammars'; +import { looksLikeShellScript } from '../src/extraction/shebang'; +import { FileWatcher, __emitWatchEventForTests } from '../src/sync/watcher'; + +const roots: string[] = []; + +afterEach(() => { + for (const root of roots.splice(0)) fs.rmSync(root, { recursive: true, force: true }); +}); + +describe('extensionless shell script detection', () => { + it('recognizes direct and env shell shebangs within the bounded first line', () => { + expect(looksLikeShellScript('#!/bin/bash\necho ok\n')).toBe(true); + expect(looksLikeShellScript('#!/bin/dash\necho ok\n')).toBe(true); + expect(looksLikeShellScript('#!/usr/bin/env -S bash -eu\necho ok\n')).toBe(true); + expect(looksLikeShellScript('#!/usr/bin/python3\nprint(1)\n')).toBe(false); + expect(looksLikeShellScript('echo no shebang\n')).toBe(false); + }); + + it('uses file content only when a root is supplied', () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-shebang-')); + roots.push(root); + fs.writeFileSync(path.join(root, 'deploy'), '#!/bin/sh\nhelper\n'); + + expect(isSourceFile('deploy')).toBe(false); + expect(isSourceFile('deploy', root)).toBe(true); + expect(detectLanguage('deploy', '#!/bin/sh\nhelper\n')).toBe('bash'); + }); + + it('finds and parses extensionless shell scripts in the filesystem scan', async () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-shebang-scan-')); + roots.push(root); + fs.writeFileSync(path.join(root, 'deploy'), '#!/usr/bin/env bash\nmain() { helper; }\n'); + fs.writeFileSync(path.join(root, 'README'), 'not source\n'); + + expect(scanDirectory(root)).toEqual(['deploy']); + }); + + it('passes extensionless shell changes through the watcher filter', async () => { + const root = fs.mkdtempSync(path.join(os.tmpdir(), 'codegraph-shebang-watch-')); + roots.push(root); + fs.writeFileSync(path.join(root, 'deploy'), '#!/bin/sh\necho ok\n'); + const sync = vi.fn().mockResolvedValue({ filesChanged: 1, durationMs: 1 }); + const watcher = new FileWatcher(root, sync, { inertForTests: true, debounceMs: 1 }); + watcher.start(); + + __emitWatchEventForTests(root, 'deploy'); + await new Promise((resolve) => setTimeout(resolve, 150)); + watcher.stop(); + + expect(sync).toHaveBeenCalledWith(['deploy']); + }); +}); diff --git a/assets/languages/bash.svg b/assets/languages/bash.svg new file mode 100644 index 000000000..9df1b25fe --- /dev/null +++ b/assets/languages/bash.svg @@ -0,0 +1,8 @@ + + Bash + + + + + Bash + diff --git a/docs/design/dynamic-dispatch-coverage-playbook.md b/docs/design/dynamic-dispatch-coverage-playbook.md index c61fb9f31..57b14d409 100644 --- a/docs/design/dynamic-dispatch-coverage-playbook.md +++ b/docs/design/dynamic-dispatch-coverage-playbook.md @@ -251,6 +251,7 @@ Status legend: ✅ done+validated · 🔬 hole identified · ⬜ not started. | Python | Django ORM | QuerySet → SQL compiler | R | ✅ | | Python | Django / DRF (views) | url → view → model | R + X | ✅ url→view (`path`/`url`/`as_view`) + **DRF `router.register`→ViewSet** (realworld S / wagtail M / saleor L); ORM QuerySet→SQL (prior work). 🔬 signals (`post_save`→receiver), DRF viewset CRUD actions (inherited), saleor GraphQL resolvers | | Python | Flask / FastAPI | request → route → handler → dependency | R + X | ✅ **Flask: handler resolved across intervening decorators (`@login_required`) + stacked `@x.route` lines** (microblog S 6→27, redash L decorator routes 6/6); **FastAPI: empty-path router-root routes `@router.get("")` incl. multi-line** (realworld S 12→20 / Netflix dispatch L **290/290 100%**) + **bare-name builtin guard** — a handler named after a Python builtin method (`index`/`get`/`update`/`count`…) was filtered as a builtin and lost its route→handler edge. + **Flask-RESTful `add_resource(Resource,'/x')` → Resource class** (redash 6→**77**) + **tuple `methods=('GET',)`** (was mislabeled GET) + **broadened detection** (requirements/Pipfile/setup + subdir app-factory entrypoints — flask-realworld 0→**19**). 🔬 FastAPI `Depends()` dependency edges (light validation) | +| Bash | POSIX shell / Bash scripts | entrypoint → sourced/helper script → function or variable | X + R | ✅ Bash grammar, function/variable extraction, shebang detection, shell-to-shell imports, wrapper and interpreter path resolution, source-closure reachability, and refusal boundaries. Extraction PASS on `kward/shunit2` (21 conventional shell files), `scop/bash-completion` (556), and `nvm-sh/nvm` (308 Bash-language files). Agent A/B signal is positive on shunit2 and nvm: indexed arms used 0–1 Reads and 1–5 explores, while blocked arms used 2–7 Reads; nvm was 20–21s indexed vs 36–50s blocked across two runs. The bash-completion dispatcher question was rejected as an invalid endpoint because its extensionless, shebang-less `bash_completion` file is intentionally not indexed. 🔬 large-tier evidence remains unavailable among the selected shell-dominant repos; `.zsh` is intentionally excluded. | | Go | Gin / chi / gorilla/mux / net-http | request → route → handler → service; middleware chain (`Use`→`Next`) | S + X | ✅ **routes on ANY group var** (`v1.GET`, `PublicGroup.GET`) not just `r/router` (gin-vue-admin S→M 4→259 / realworld S / gitness L) — was missing all group-routed apps; named handlers resolve precisely. **gorilla/mux confirmed covered** by the any-receiver `HandleFunc`/`Handle` handling (subrouter-var `s.HandleFunc(...)` + namespaced handlers; `.Methods()` chain ignored). + **gin middleware-chain synthesizer** (`ginMiddlewareChainEdges`): gin runs its entire chain through one dynamic line — `(*Context).Next` does `c.handlers[c.index](c)`, a slice-index dispatch tree-sitter can't resolve, so `callees(Next)` dead-ended at the `len()` helper (`safeInt8`) and the agent rabbit-holed re-querying it. Find the dispatcher (a Go method invoking a `handlers` slice by index) and link it → every HandlerFunc registered via `.Use`/`.GET`/…/`.Handle`; gated on the dispatcher existing (inert on non-gin Go repos), named handlers only (closures skipped), capped. gin L: `callees(Next)` now surfaces `Logger`/`Recovery`/`ErrorLogger`+handlers (node count stable 2,544; 5 precise edges with `registeredAt` wiring sites). **Agent A/B (headless median-of-4, Opus 4.8): gin flipped from codegraph −58% cost / −129% time (the rabbit-hole, incl. a stray `Workflow` mis-fire on 2/4 WITH runs) → +7% cost / +35% tokens / +8% time / 38% tool calls, all 4 WITH runs clean (0 Read/Grep/Bash, no Workflow, no duplicate calls).** 🔬 inline `func(c){}` handlers (anonymous, body lost); subrouter/`PathPrefix` path-prefix not prepended (label only); gitness chi custom (26/321) | | Go | GoFrame (standard router) | request-type `g.Meta` route → controller method (reflective `group.Bind`) | R (extract) + S | ✅ **GoFrame `g.Meta` route coverage** (#747) — extractor (`frameworks/goframe.ts`, detect `gogf/gf` in go.mod) turns each `` g.Meta `path:.. method:..` `` request-type tag into a `route` node (requires `path:`, so a response `mime:`-only `g.Meta` is skipped), encoding the **package-qualified** request type in qualifiedName. `goframeRouteEdges` synthesizer joins route → the controller method whose **signature** takes that request type — NOT by name (`DeptSearchReq` is served by `List`, `GetDictReq` by `GetDictData`) — keyed `pkg.Type` to separate the dozens of identical bare names a big app defines one-per-module (`cash.ListReq` vs `order.ListReq`), with an **addon-root tiebreak** so a cloned demo addon (`addons/hgexample/`) binds within itself and never cross-links to core. Validated: gf-demo-user S **7/7**, gfast M **65/68** (3 genuinely handler-less DbInit), hotgo L (697 files) **242/247 (98%), 100% precision** (0 non-controller handlers, 0 core/addon cross-binding); node count stable on re-index; surfaces in the handler's caller trail (`POST /dept/add` → `Add` via `goframe-route`). **Agent A/B (gfast M, sonnet/high, 2 runs/arm): WITH = 1 `codegraph_explore` / 0 Read / 0 Grep / ~20s / correct; WITHOUT = 7.5 Read avg + grep-hunting for the non-existent literal `/dept/add` string + re-reading sys_dept.go up to 12× / ~42s — reads eliminated, −83% tool calls, 2.1× faster, cost a wash; both arms reach the same correct call path.** 🔬 group prefix from reflective `Bind` not prepended (route shows the `g.Meta` path, not `/system/dept/list`); the 4×-cloned `index` sub-packages inside one addon are left unlinked (needs import-path resolution, not just package name) | | Rust | Axum / actix / Rocket | request → route → handler | R + X | ✅ **Axum chained methods + namespaced handlers** — `.route("/x", get(h1).post(h2))` emitted only the first method+handler, and `get(mod::handler)` captured the module not the fn (realworld-axum S **12→19, 19/19**); balanced-paren scan + per-method nodes + last-`::`-segment handler. **Rocket attribute macros 550/556 (99%)** (Rocket repo L) — already strong. crates.io named axum routes resolve (6/8; rest are closures/var handlers; its API is mostly the utoipa `routes!` macro = frontier). Cargo-workspace module resolution (prior work). **actix builder API** `web::resource("/x").route(web::get().to(h))` / `.to(h)` / App `.route("/x", web::get().to(h))` (actix-examples **51→128 routes, 35→112 resolved**) — was the dominant actix style and fully missed (the handler is in `.to(h)`, not `get(h)`). 🔬 actix `web::scope("/api")` prefix (not prepended to nested resource paths) + anonymous `.to` closure handlers | diff --git a/scripts/add-lang/bench.sh b/scripts/add-lang/bench.sh index 172fe4064..a4e37913d 100755 --- a/scripts/add-lang/bench.sh +++ b/scripts/add-lang/bench.sh @@ -1,15 +1,16 @@ #!/usr/bin/env bash # Add-lang benchmark for ONE repo: -# clone -> wipe+index (with the codegraph on PATH) -> verify extraction -> +# clone -> wipe+index (with the configured dev binary) -> verify extraction -> # with/without retrieval A/B (reuses scripts/agent-eval/run-all.sh). # -# Assumes the codegraph dev build is already built + linked on PATH — the skill -# runs `npm run build && ./scripts/local-install.sh` ONCE before looping repos. +# Assumes the codegraph dev build is already built. Set CG_BIN to its entrypoint +# so the benchmark never depends on, or changes, the maintainer's PATH. # The A/B is skipped if extraction fails its critical checks (don't burn $ on a # broken extractor); set FORCE_AB=1 to run it anyway. # # Usage: bench.sh "" [headless|tmux|all] -# Env: CORPUS corpus dir (default /tmp/codegraph-corpus, shared with agent-eval) +# Env: CG_BIN codegraph entrypoint (default: codegraph resolved on PATH) +# CORPUS corpus dir (default /tmp/codegraph-corpus, shared with agent-eval) set -uo pipefail LANG_TOKEN="${1:?usage: bench.sh \"\" [mode]}" @@ -23,10 +24,11 @@ AGENT_EVAL="$(cd "$HARNESS/../agent-eval" && pwd)" CORPUS="${CORPUS:-/tmp/codegraph-corpus}" REPO="$CORPUS/$NAME" -command -v codegraph >/dev/null || { echo "no codegraph on PATH (build + ./scripts/local-install.sh first)"; exit 1; } +CG_BIN="${CG_BIN:-$(command -v codegraph 2>/dev/null || true)}" +[ -n "$CG_BIN" ] || { echo "no codegraph binary (set CG_BIN to the dev entrypoint)"; exit 1; } echo "==================== add-lang bench: $NAME ($LANG_TOKEN) ====================" -echo "codegraph: $(command -v codegraph) -> $(codegraph --version 2>/dev/null || echo '?')" +echo "codegraph: $CG_BIN -> $($CG_BIN --version 2>/dev/null || echo '?')" # 1. Ensure the repo (shallow clone, reuse if present). mkdir -p "$CORPUS" @@ -40,7 +42,7 @@ fi # 2. Wipe + index with the binary under test. echo "→ wiping .codegraph and indexing" rm -rf "$REPO/.codegraph" -( cd "$REPO" && codegraph init -i ) || { echo "indexing failed"; exit 1; } +( cd "$REPO" && "$CG_BIN" init -i ) || { echo "indexing failed"; exit 1; } # 3. Verify extraction (cheap guard before the paid A/B). echo "→ verifying extraction" diff --git a/scripts/add-lang/verify-extraction.mjs b/scripts/add-lang/verify-extraction.mjs index bdb443e25..9786357b3 100755 --- a/scripts/add-lang/verify-extraction.mjs +++ b/scripts/add-lang/verify-extraction.mjs @@ -4,8 +4,8 @@ // can drive a write-extractor -> build -> re-check loop. // // Usage: node scripts/add-lang/verify-extraction.mjs -// Reads `codegraph status --json` using whatever codegraph is on PATH, -// so it reflects the binary that built the index. +// Reads `codegraph status --json`; CG_BIN selects the binary that built +// the index without requiring a PATH change. // // Exit codes: 0 = pass or soft-warn, 1 = critical fail, 2 = could not run. @@ -19,7 +19,8 @@ if (!repo || !lang) { let status; try { - const out = execFileSync('codegraph', ['status', repo, '--json'], { encoding: 'utf8' }); + const cgParts = process.env.CG_BIN ? process.env.CG_BIN.trim().split(/\s+/) : ['codegraph']; + const out = execFileSync(cgParts[0], [...cgParts.slice(1), 'status', repo, '--json'], { encoding: 'utf8' }); status = JSON.parse(out); } catch (e) { console.error(`[verify] could not read codegraph status for ${repo}: ${e.message}`); diff --git a/scripts/local-install.sh b/scripts/local-install.sh index 847966940..33e0777ed 100755 --- a/scripts/local-install.sh +++ b/scripts/local-install.sh @@ -16,6 +16,17 @@ VERSION=$(node -p "require('./package.json').version") BRANCH=$(git rev-parse --abbrev-ref HEAD) if [ "${1:-}" = "--undo" ]; then + LINK="${HOME}/.local/bin/codegraph" + PREVIOUS="${LINK}.previous-target" + if [ -f "$PREVIOUS" ]; then + TARGET=$(<"$PREVIOUS") + if [ -e "$TARGET" ]; then + ln -sfn "$TARGET" "$LINK" + rm -f "$PREVIOUS" + echo "done: restored codegraph -> $(command -v codegraph || echo \"$LINK\")" + exit 0 + fi + fi echo "→ unlinking ${PKG}" npm unlink -g "${PKG}" >/dev/null 2>&1 || true echo "→ reinstalling published ${PKG}" @@ -28,7 +39,23 @@ echo "→ building ${PKG} ${VERSION} (${BRANCH})" npm run build echo "→ linking globally" -npm link +NPM_PREFIX=$(npm prefix -g 2>/dev/null || true) +NPM_BIN="${NPM_PREFIX}/bin" +if [ -n "$NPM_PREFIX" ] && [ -d "$NPM_BIN" ] && [ -w "$NPM_BIN" ]; then + npm link +else + LINK="${HOME}/.local/bin/codegraph" + PREVIOUS="${LINK}.previous-target" + mkdir -p "$(dirname "$LINK")" + if [ -L "$LINK" ]; then + printf '%s\n' "$(readlink -f "$LINK")" > "$PREVIOUS" + elif [ -e "$LINK" ]; then + echo "refusing to replace existing non-symlink ${LINK}" >&2 + exit 1 + fi + ln -sfn "$PWD/dist/bin/codegraph.js" "$LINK" + echo "npm global prefix is not writable; linked directly to ${LINK}" +fi LINKED=$(command -v codegraph || echo "(not on PATH)") echo diff --git a/src/extraction/grammars.ts b/src/extraction/grammars.ts index 84647c3e4..14dcb6101 100644 --- a/src/extraction/grammars.ts +++ b/src/extraction/grammars.ts @@ -10,6 +10,7 @@ import * as path from 'path'; import * as fsp from 'fs/promises'; import { Parser, Language as WasmLanguage } from 'web-tree-sitter'; import { Language } from '../types'; +import { looksLikeShellScript, looksLikeShellScriptFile } from './shebang'; export type GrammarLanguage = Exclude; @@ -50,6 +51,7 @@ const WASM_GRAMMAR_FILES: Record = { terraform: 'tree-sitter-terraform.wasm', arkts: 'tree-sitter-arkts.wasm', nix: 'tree-sitter-nix.wasm', + bash: 'tree-sitter-bash.wasm', }; /** @@ -111,6 +113,13 @@ export const EXTENSION_MAP: Record = { '.vue': 'vue', '.astro': 'astro', '.r': 'r', + // .zsh excluded: zsh-only syntax yields ERROR trees, silently dropping + // every symbol inside them. + '.sh': 'bash', + '.bash': 'bash', + '.ksh': 'bash', + '.dash': 'bash', + '.bats': 'bash', '.pas': 'pascal', '.dpr': 'pascal', '.dpk': 'pascal', @@ -173,22 +182,28 @@ export const EXTENSION_MAP: Record = { }; /** - * Whether a file is one CodeGraph can parse, based purely on its extension. - * This is the single source of truth for "should we index this file" — derived - * from EXTENSION_MAP so parser support and indexing selection never drift. + * Whether a file is one CodeGraph can parse. Extensionless files are accepted + * only when `rootDir` is supplied and their bounded prefix has a shell shebang. + * This is the single source of truth for "should we index this file". * - * `overrides` is the project's validated custom extension → language map (from - * `codegraph.json`); when present its extensions count as indexable in addition - * to the built-ins. Omitting it is byte-identical to the zero-config behavior. + * `rootDirOrOverrides` keeps the pre-shebang two-argument API compatible while + * allowing scanners to provide the root needed for content-based detection. */ -export function isSourceFile(filePath: string, overrides?: Record): boolean { +export function isSourceFile( + filePath: string, + rootDirOrOverrides?: string | Record, + overrides?: Record, +): boolean { + const rootDir = typeof rootDirOrOverrides === 'string' ? rootDirOrOverrides : undefined; + const extensionOverrides = typeof rootDirOrOverrides === 'object' ? rootDirOrOverrides : overrides; if (isPlayRoutesFile(filePath)) return true; // Play `conf/routes` is extensionless if (isShopifyLiquidJson(filePath)) return true; // Shopify OS 2.0 JSON templates / section groups if (isErlangAppFile(filePath)) return true; // OTP `.app`/`.app.src` resource files - const dot = filePath.lastIndexOf('.'); - if (dot < 0) return false; - const ext = filePath.slice(dot).toLowerCase(); - return ext in EXTENSION_MAP || (!!overrides && ext in overrides); + const basename = filePath.slice(filePath.lastIndexOf('/') + 1); + const dot = basename.lastIndexOf('.'); + if (dot < 0) return rootDir ? looksLikeShellScriptFile(filePath, rootDir) : false; + const ext = basename.slice(dot).toLowerCase(); + return ext in EXTENSION_MAP || (!!extensionOverrides && ext in extensionOverrides); } /** @@ -289,6 +304,10 @@ export async function initGrammars(): Promise { * the vendored wasm together. */ const VENDORED_WASM_LANGS: ReadonlySet = new Set([ + // Bash: upstream tree-sitter-bash v0.25.1 prebuilt wasm (ABI 15), copied + // byte-identical from the npm tarball. The tree-sitter-wasms artifact (ABI + // 14) crashes the shared WASM heap on any `case` statement. + 'bash', 'pascal', 'scala', 'lua', 'luau', 'csharp', 'r', 'cfml', 'cfscript', 'cfquery', 'cobol', 'vbnet', 'erlang', 'terraform', 'arkts', 'nix', 'typescript', 'tsx', 'javascript', 'jsx', 'java', 'python', 'go', @@ -478,13 +497,15 @@ export function detectLanguage(filePath: string, source?: string, overrides?: Re // Play `conf/routes` has no grammar — route through the no-symbol path; the // Play framework resolver extracts route nodes from it. if (isPlayRoutesFile(filePath)) return 'yaml'; - const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase(); + const basename = filePath.slice(filePath.lastIndexOf('/') + 1); + const ext = basename.substring(basename.lastIndexOf('.')).toLowerCase(); // Shopify OS 2.0 JSON templates / section groups → the Liquid extractor (it // links each section `"type"` to its `sections/.liquid`). if (isShopifyLiquidJson(filePath)) return 'liquid'; // OTP `.app`/`.app.src` resource files — Erlang terms the grammar parses as // top-level expressions (last-dot ext `.src` is too generic for the map). if (isErlangAppFile(filePath)) return 'erlang'; + if (!basename.includes('.') && source && looksLikeShellScript(source)) return 'bash'; const lang = (overrides && overrides[ext]) || EXTENSION_MAP[ext] || 'unknown'; // .h files could be C, C++, or Objective-C — check source content @@ -693,8 +714,9 @@ export function getLanguageDisplayName(language: Language): string { vbnet: 'Visual Basic .NET', erlang: 'Erlang', terraform: 'Terraform', - arkts: 'ArkTS', - unknown: 'Unknown', + arkts: 'ArkTS', + bash: 'Bash', + unknown: 'Unknown', }; return names[language] || language; } diff --git a/src/extraction/index.ts b/src/extraction/index.ts index 93be48352..e5427d3b6 100644 --- a/src/extraction/index.ts +++ b/src/extraction/index.ts @@ -26,6 +26,7 @@ import { ParseWorkerPool, resolveParsePoolSize, resolveParseTimeoutMs } from './ import { StoreWriter, StoreBundle, finalizeStoreBundle } from './store-writer'; import { materializeKernelResult } from './kernel'; import { detectGeneratedFile } from './generated-detection'; +import { looksLikeShellScriptFile } from './shebang'; import { detectLanguage, isSourceFile, isLanguageSupported, isFileLevelOnlyLanguage, initGrammars, loadGrammarsForLanguages, readGrammarWasmBytes } from './grammars'; import { loadExtensionOverrides, loadIncludeIgnoredPatterns, loadExcludePatterns, loadIncludePatterns, PROJECT_CONFIG_FILENAME } from '../project-config'; import { isCodeGraphDataDir } from '../directory'; @@ -446,7 +447,7 @@ function collectIncludedFiles( if (defaults.ignores(rel)) return; if (!include.ignores(rel)) return; if (exclude && exclude.ignores(rel)) return; - if (!isSourceFile(rel, overrides)) return; + if (!isSourceFile(rel, rootDir, overrides)) return; out.add(rel); } }; @@ -1156,10 +1157,8 @@ function collectGitStatus(repoDir: string, prefix: string, out: GitChanges, over continue; } - const filePath = normalizePath(prefix + rel); - if (!isSourceFile(filePath, overrides)) continue; - if (statusCode.includes('D')) { + const filePath = normalizePath(prefix + rel); // Deletions stay unfiltered: getChangedFiles acts on one only when the // path is already tracked in the DB, where removal is always correct — and // that lets a newly-excluded dir's stale rows clean themselves up. (#766) @@ -1167,6 +1166,9 @@ function collectGitStatus(repoDir: string, prefix: string, out: GitChanges, over continue; } + const filePath = normalizePath(prefix + rel); + if (!isSourceFile(rel, repoDir, overrides)) continue; + // Added (`??`) / modified files inside an excluded dir must not enter the // index — match against the repo-relative path, same as the full scan. (#766) if (ig.ignores(rel)) continue; @@ -1218,7 +1220,7 @@ export function scanDirectory( const files: string[] = []; let count = 0; for (const filePath of gitFiles) { - if (isSourceFile(filePath, overrides)) { + if (isSourceFile(filePath, rootDir, overrides)) { files.push(filePath); count++; onProgress?.(count, filePath); @@ -1247,7 +1249,7 @@ export async function scanDirectoryAsync( const files: string[] = []; let count = 0; for (const filePath of gitFiles) { - if (isSourceFile(filePath, overrides)) { + if (isSourceFile(filePath, rootDir, overrides)) { files.push(filePath); count++; onProgress?.(count, filePath); @@ -1351,7 +1353,7 @@ function scanDirectoryWalk( walk(fullPath, active); } } else if (stat.isFile()) { - if (!isIgnored(fullPath, false, active) && isSourceFile(relativePath, overrides)) { + if (!isIgnored(fullPath, false, active) && isSourceFile(relativePath, rootDir, overrides)) { files.push(relativePath); count++; onProgress?.(count, relativePath); @@ -1368,7 +1370,7 @@ function scanDirectoryWalk( walk(fullPath, active); } } else if (entry.isFile()) { - if (!isIgnored(fullPath, false, active) && isSourceFile(relativePath, overrides)) { + if (!isIgnored(fullPath, false, active) && isSourceFile(relativePath, rootDir, overrides)) { files.push(relativePath); count++; onProgress?.(count, relativePath); @@ -1662,7 +1664,11 @@ export class ExtractionOrchestrator { await new Promise(resolve => setImmediate(resolve)); // Detect needed languages and load grammars in the parse worker - const neededLanguages = [...new Set(files.map((f) => detectLanguage(f, undefined, overrides)))]; + const neededLanguages = [...new Set(files.map((f) => ( + !f.slice(f.lastIndexOf('/') + 1).includes('.') && looksLikeShellScriptFile(f, this.rootDir) + ? 'bash' + : detectLanguage(f, undefined, overrides) + )))]; // .h files default to 'c' but may be C++ — ensure cpp grammar is loaded when c is needed if (neededLanguages.includes('c') && !neededLanguages.includes('cpp')) { neededLanguages.push('cpp'); @@ -2874,7 +2880,11 @@ export class ExtractionOrchestrator { // Load only grammars needed for changed files if (filesToIndex.length > 0) { const overrides = loadExtensionOverrides(this.rootDir); - const neededLanguages = [...new Set(filesToIndex.map((f) => detectLanguage(f, undefined, overrides)))]; + const neededLanguages = [...new Set(filesToIndex.map((f) => ( + !f.slice(f.lastIndexOf('/') + 1).includes('.') && looksLikeShellScriptFile(f, this.rootDir) + ? 'bash' + : detectLanguage(f, undefined, overrides) + )))]; // .h files default to 'c' but may be C++ — ensure cpp grammar is loaded if (neededLanguages.includes('c') && !neededLanguages.includes('cpp')) { neededLanguages.push('cpp'); diff --git a/src/extraction/languages/bash.ts b/src/extraction/languages/bash.ts new file mode 100644 index 000000000..d4513b1d7 --- /dev/null +++ b/src/extraction/languages/bash.ts @@ -0,0 +1,1154 @@ +import type { Node as SyntaxNode } from 'web-tree-sitter'; +import * as posix from 'node:path/posix'; +import { getNodeText } from '../tree-sitter-helpers'; +import type { ExtractorContext, LanguageExtractor } from '../tree-sitter-types'; + +interface CwdState { + cwdChanged: boolean; + pathPrepends: string[]; +} + +const cwdStates = new WeakMap(); + +function stateFor(ctx: ExtractorContext): CwdState { + // ctx itself is rebuilt per visited node; the live nodes array is the + // identity that persists across one file's whole extraction. + const fileKey = ctx.nodes as unknown as object; + let st = cwdStates.get(fileKey); + if (!st) { + st = { cwdChanged: false, pathPrepends: [] }; + cwdStates.set(fileKey, st); + } + return st; +} + +function commandWord(node: SyntaxNode, source: string): string | null { + const nameNode = node.childForFieldName('name'); + const word = nameNode?.child(0); + return word ? getNodeText(word, source).trim() : null; +} + +function declarationBuiltin(node: SyntaxNode, source: string): string | null { + const keyword = node.child(0); + if (!keyword) return null; + const text = getNodeText(keyword, source); + return text === 'export' || text === 'readonly' || text === 'declare' || text === 'typeset' || text === 'local' + ? text + : null; +} + +/** `declare -g` / `typeset -g` assigns in the global scope even inside a function. */ +function carriesGlobalFlag(node: SyntaxNode, source: string): boolean { + for (let i = 1; i < node.childCount; i++) { + const child = node.child(i); + if (!child) break; + if (child.type === 'word' && /^-[a-zA-Z]*g/.test(getNodeText(child, source))) return true; + if (child.type === 'variable_assignment') break; + } + return false; +} + +function carriesReadonlyFlag(node: SyntaxNode, source: string): boolean { + for (let i = 1; i < node.childCount; i++) { + const child = node.child(i); + if (!child) break; + if (child.type === 'word' && /^-[a-zA-Z]*r/.test(getNodeText(child, source))) return true; + if (child.type === 'variable_assignment') break; + } + return false; +} + +function hasFunctionAncestor(node: SyntaxNode): boolean { + let current = node.parent; + while (current) { + if (current.type === 'function_definition') return true; + current = current.parent; + } + return false; +} + +export interface BashVariable { + name: string; + kind: 'variable' | 'constant'; + valueNode: SyntaxNode | null; + positionNode: SyntaxNode; +} + +/** Variables and constants from an assignment or declaration command; empty when suppressed. */ +export function extractBashVariables(node: SyntaxNode, source: string): BashVariable[] { + if (node.type === 'variable_assignment') { + if (hasFunctionAncestor(node)) return []; + const parent = node.parent?.type === 'command' ? node.parent : null; + const nameNode = node.childForFieldName('name'); + if (!nameNode || parent) return []; + return [{ + name: getNodeText(nameNode, source), + kind: 'variable', + valueNode: node.childForFieldName('value'), + positionNode: nameNode, + }]; + } + + const builtin = declarationBuiltin(node, source); + if (!builtin || builtin === 'local') return []; + + // Inside a function, `declare` without `-g` creates a FUNCTION-LOCAL variable + // — verified by execution: `f() { declare X=1; }; f` leaves X unset, exactly + // like `local`. So it is suppressed for the same reason `local` is, and for + // the reason no other language in the index emits function-local variables at + // all (TypeScript, Python and Go each emit only top-level ones). `readonly` + // and `export` are NOT suppressed: both assign in the global scope even when + // written inside a function, as does `declare -g`. + if (hasFunctionAncestor(node) && (builtin === 'declare' || builtin === 'typeset') && !carriesGlobalFlag(node, source)) { + return []; + } + + const kind: 'variable' | 'constant' = + builtin === 'readonly' || carriesReadonlyFlag(node, source) ? 'constant' : 'variable'; + + return node.namedChildren + .filter((c) => c.type === 'variable_assignment') + .map((assignment) => { + const nameNode = assignment.childForFieldName('name'); + return nameNode + ? { + name: getNodeText(nameNode, source), + kind, + valueNode: assignment.childForFieldName('value'), + positionNode: nameNode, + } + : null; + }) + .filter((v): v is BashVariable => v !== null); +} + +// --- script path resolution ------------------------------------------------- + +const OWN_PROCESS_TYPES = new Set(['command_substitution', 'subshell', 'pipeline']); +const SUPPRESSED_ASSIGNMENT_ANCESTORS = new Set([ + ...OWN_PROCESS_TYPES, + 'if_statement', + 'while_statement', + 'until_statement', + 'for_statement', + 'case_statement', + 'function_definition', +]); +const MAX_TRACE_DEPTH = 8; +const ROOT_ANCHOR_NAMES = new Set(['REPO_ROOT', 'PROJECT_ROOT', 'WORKSPACE_ROOT', 'CODEGRAPH_ROOT']); + +function programRoot(node: SyntaxNode): SyntaxNode { + let current = node; + while (current.parent) current = current.parent; + return current; +} + +function runsInOwnProcess(node: SyntaxNode): boolean { + let current = node.parent; + while (current) { + if (OWN_PROCESS_TYPES.has(current.type)) return true; + current = current.parent; + } + return false; +} + +function isArgumentZeroExpansion(node: SyntaxNode, source: string): boolean { + if (node.type === 'simple_expansion' || node.type === 'expansion') { + const inner = expansionNameNode(node); + if (!inner || inner.type !== 'variable_name') return false; + const name = getNodeText(inner, source); + return name === '0' || name === 'BASH_SOURCE'; + } + return false; +} + +/** The variable a simple_expansion/expansion reads: a variable_name, possibly under a subscript. */ +function expansionNameNode(node: SyntaxNode): SyntaxNode | null { + const first = node.namedChild(0); + if (!first) return null; + if (first.type === 'variable_name') return first; + if (first.type === 'subscript') { + return first.childForFieldName('name') ?? first.namedChild(0); + } + return null; +} + +/** `${VAR%/*}`-style dirname-by-suffix-removal over an own-directory anchor. */ +function isOwnDirectoryRemoval(node: SyntaxNode, source: string): boolean { + if (node.type !== 'expansion') return false; + if (!isArgumentZeroExpansion(node, source)) return false; + const regex = node.namedChildren.find((c) => c.type === 'regex'); + if (!regex) return false; + const text = getNodeText(regex, source); + return text.endsWith('/*') && !text.includes('#'); +} + +function matchDirnameSubstitution(node: SyntaxNode, source: string): boolean { + if (node.type !== 'command_substitution') return false; + const body = node.namedChild(0); + const cmd = + body?.type === 'command' + ? body + : body?.type === 'list' + ? (body.namedChildren.length === 1 && body.namedChild(0)?.type === 'command' + ? body.namedChild(0) + : null) + : null; + if (!cmd || commandWord(cmd, source) !== 'dirname') return false; + + let sawAnchor = false; + for (let i = 0; i < cmd.namedChildCount; i++) { + const child = cmd.namedChild(i)!; + if (child.type === 'command_name') continue; + if (child.type === 'word' && getNodeText(child, source) === '--') continue; + if (isArgumentZeroExpansion(child, source) && !child.namedChildren.some((c) => c.type === 'regex')) { + sawAnchor = true; + continue; + } + if (child.type === 'string') { + const exprs = child.namedChildren.filter((c) => c.type !== 'string_content'); + const content = child.namedChildren.filter((c) => c.type === 'string_content').map((c) => getNodeText(c, source)).join(''); + if ( + exprs.length === 1 && + isArgumentZeroExpansion(exprs[0]!, source) && + !exprs[0]!.namedChildren.some((c) => c.type === 'regex') && + content.trim() === '' + ) { + sawAnchor = true; + continue; + } + } + return false; + } + return sawAnchor; +} + +/** + * `$(cd && pwd)` resolves to whatever its inner expression resolves + * to — usually an own-directory anchor, but anchored parent segments + * (`$(cd "$(dirname "$0")/.." && pwd)`) climb deliberately. + */ +function resolveCdPrintSubstitution( + node: SyntaxNode, + source: string, + rootDir: string, + allowRelative: boolean, + visited: Set, + depth: number +): string | null { + if (node.type !== 'command_substitution') return null; + const body = node.namedChild(0); + const commands = + body?.type === 'list' + ? body.namedChildren.filter((c) => c.type === 'command') + : body?.type === 'command' + ? [body] + : []; + if (commands.length !== 2) return null; + const [cd, pwd] = commands as [SyntaxNode, SyntaxNode]; + if (commandWord(cd, source) !== 'cd' || commandWord(pwd, source) !== 'pwd') return null; + const args = cd.namedChildren.filter((c) => c.type !== 'command_name'); + if (args.length !== 1) return null; + return composeDirectory([args[0]!], source, rootDir, allowRelative, new Set(visited), depth + 1, Number.MAX_SAFE_INTEGER); +} + +function traceVariable( + name: string, + reference: SyntaxNode, + source: string, + containingDir: string, + cutoff: number, + visited: Set, + depth: number +): string | null { + if (visited.has(name) || depth > MAX_TRACE_DEPTH) return null; + visited.add(name); + + const root = programRoot(reference); + const matches: SyntaxNode[] = []; + + const walk = (node: SyntaxNode): void => { + if (node.type === 'variable_assignment') { + const nameNode = node.childForFieldName('name'); + if (nameNode && getNodeText(nameNode, source) === name && node.startIndex < cutoff) { + let suppressed = false; + let parent = node.parent; + while (parent && parent !== root) { + if (SUPPRESSED_ASSIGNMENT_ANCESTORS.has(parent.type)) { + suppressed = true; + break; + } + parent = parent.parent; + } + if (!suppressed) matches.push(node); + } + } + for (let i = 0; i < node.namedChildCount; i++) { + const child = node.namedChild(i); + if (child) walk(child); + } + }; + walk(root); + + if (matches.length === 0) return null; + + const resolveValueOf = (match: SyntaxNode): string | null => { + const value = match.childForFieldName('value'); + // Resolving THIS assignment's value, a reference to the same name reads + // the PREVIOUS value: cut the search off at this assignment's start. + const innerVisited = new Set(visited); + innerVisited.delete(name); + return value + ? composeDirectory([value], source, containingDir, true, innerVisited, depth + 1, match.startIndex) + : null; + }; + + const valueRefsSelf = (match: SyntaxNode): boolean => { + const value = match.childForFieldName('value'); + if (!value) return false; + let found = false; + const scan = (node: SyntaxNode): void => { + if (found) return; + if (node.type === 'simple_expansion' || node.type === 'expansion') { + const n = expansionNameNode(node); + if (n && getNodeText(n, source) === name) { + found = true; + return; + } + } + for (let i = 0; i < node.namedChildCount; i++) { + const child = node.namedChild(i); + if (child) scan(child); + } + }; + scan(value); + return found; + }; + + const last = matches[matches.length - 1]!; + if (matches.length === 1 || valueRefsSelf(last)) { + // A chained re-assignment threads the previous value deterministically. + return resolveValueOf(last); + } + + // Independent overwrites: every derivation must agree, or the forward + // scan cannot tell which one ran. + const results = new Set(); + for (const match of matches) { + const resolved = resolveValueOf(match); + if (resolved === null) return null; + results.add(resolved); + } + return results.size === 1 ? results.values().next().value! : null; +} + +/** + * Extend a partially-composed directory with literal path text ('/../lib', + * './x', ...). Null current means no anchor yet; relative literals then + * bottom out at rootDir when allowed, and stay unknowable otherwise. + */ +function appendLiteralText( + current: string | null, + text: string, + rootDir: string, + allowRelative: boolean +): string | null { + if (text === '') return current; + if (current === null && !allowRelative && !text.startsWith('/')) return null; + let dir = current; + if (dir === null) { + dir = text.startsWith('/') ? '/' : rootDir; + } + for (const part of text.split('/')) { + if (part === '' || part === '.') continue; + if (part === '..') { + dir = posix.dirname(dir); + } else { + dir = posix.join(dir, part); + } + } + return dir; +} + +function isDirMaterialNode(node: SyntaxNode): boolean { + const type = node.type; + return ( + type === 'string_content' || + type === 'word' || + type === 'raw_string' || + type === 'string' || + type === 'concatenation' || + type === 'command_substitution' || + type === 'simple_expansion' || + type === 'expansion' + ); +} + +/** + * Compose a chain of expression and literal segments into an ABSOLUTE + * directory path, or null the moment a step is not statically knowable. + */ +function composeDirectory( + segments: SyntaxNode[], + source: string, + rootDir: string, + allowRelative: boolean, + visited: Set, + depth: number, + cutoff: number +): string | null { + let current: string | null = null; + + for (const segment of segments) { + const type = segment.type; + if (!isDirMaterialNode(segment)) continue; + if (type === 'string_content' || type === 'word' || type === 'raw_string') { + let text = getNodeText(segment, source); + if (type === 'raw_string' && text.length >= 2) text = text.slice(1, -1); + current = appendLiteralText(current, text, rootDir, allowRelative); + if (current === null) return null; + continue; + } + if (type === 'string' || type === 'concatenation') { + const inner: SyntaxNode[] = []; + for (let i = 0; i < segment.namedChildCount; i++) { + const child = segment.namedChild(i); + if (child) inner.push(child); + } + const composed = composeDirectory(inner, source, rootDir, current !== null || allowRelative, visited, depth, cutoff); + if (composed === null) return null; + current = composed; + continue; + } + if (type === 'command_substitution') { + const viaCdPrint = resolveCdPrintSubstitution(segment, source, rootDir, current !== null || allowRelative, visited, depth); + if (viaCdPrint !== null) { + current = viaCdPrint; + continue; + } + if (matchDirnameSubstitution(segment, source) || isOwnDirectoryRemovalWrapped(segment, source)) { + current = rootDir; + continue; + } + return null; + } + // simple_expansion | expansion + if (isOwnDirectoryRemoval(segment, source)) { + current = rootDir; + continue; + } + const nameNode = expansionNameNode(segment); + if (!nameNode) return null; + const name = getNodeText(nameNode, source); + // These conventional repository-root variables are process/environment + // anchors, not ordinary values we can trace from shell assignments. + if (ROOT_ANCHOR_NAMES.has(name)) { + // The extractor receives repository-relative paths. An empty POSIX path + // is therefore the repository root; normalizeScriptPath later converts + // the resulting target back relative to the referencing file. + current = ''; + continue; + } + const resolved = traceVariable(name, segment, source, rootDir, cutoff, visited, depth + 1); + if (resolved === null) return null; + // traceVariable composes against its own rootDir already — never re-join. + current = resolved; + } + + return current; +} + +function isOwnDirectoryRemovalWrapped(node: SyntaxNode, source: string): boolean { + if (node.type !== 'command_substitution') return false; + const body = node.namedChild(0); + if (!body) return false; + return isOwnDirectoryRemoval(body, source) || + (body.type === 'string' && body.namedChildren.some((c) => isOwnDirectoryRemoval(c, source))); +} + +/** + * Resolve a script path argument to a normalized relative path against the + * referencing file, or null. `base` is the containing file's directory, or + * null once a working-directory change makes relative literals unknowable. + */ +export function normalizeScriptPath( + argNode: SyntaxNode, + source: string, + containingFileDir: string, + base: string | null +): string | null { + const segments: SyntaxNode[] = + argNode.type === 'string' || argNode.type === 'concatenation' + ? (argNode.namedChildren.filter((c) => c !== null) as SyntaxNode[]) + : [argNode]; + + // Split the argument into directory material and the trailing literal + // filename: the last '/'-bearing literal child carries it. + let fileIdx = -1; + let filename = ''; + let prefixText = ''; + for (let i = segments.length - 1; i >= 0; i--) { + const child = segments[i]!; + if (!isDirMaterialNode(child)) return null; + if ( + fileIdx === -1 && + (child.type === 'string_content' || child.type === 'word' || child.type === 'raw_string') + ) { + let text = getNodeText(child, source); + if (child.type === 'raw_string' && text.length >= 2) text = text.slice(1, -1); + const slash = text.lastIndexOf('/'); + if (slash >= 0) { + fileIdx = i; + filename = text.slice(slash + 1); + prefixText = text.slice(0, slash + 1); + continue; + } + if (i === 0 || !segments.slice(0, i).some((c) => isDirMaterialNode(c))) { + // No slash anywhere before this literal either: a bare name, which + // bash resolves through PATH rather than the script's directory. + return null; + } + // Literal tail after the last expression: it IS the filename. + fileIdx = i; + filename = text; + prefixText = ''; + continue; + } + } + if (fileIdx === -1 || !filename) return null; + + // A failed anchor composition is fatal when expressions precede the + // filename; only a purely literal argument may root itself at BASE. + const exprBefore = segments + .slice(0, fileIdx) + .some((c) => c.type === 'command_substitution' || c.type === 'simple_expansion' || c.type === 'expansion'); + + let dir = composeDirectory( + segments.slice(0, fileIdx), + source, + containingFileDir, + base !== null, + new Set(), + 0, + argNode.startIndex + ); + if (dir === null && exprBefore) return null; + if (prefixText !== '') { + dir = appendLiteralText(dir, prefixText, containingFileDir, base !== null); + } + if (dir === null) return null; + + const target = posix.join(dir, filename); + const rel = posix.relative(containingFileDir, target); + if (rel === '') return null; + return rel.startsWith('.') ? rel : `./${rel}`; +} + +// --- interpreter wrappers --------------------------------------------------- + +interface InterpreterInvocation { + word: string; + pathNode: SyntaxNode | null; + startupPathNode: SyntaxNode | null; + normalizedPath: string | null; +} + +const WRAPPERS_NO_OPTS = new Set(['builtin', 'nohup']); +const ROOT_REMAP_WRAPPERS = new Set(['chroot', 'unshare', 'nsenter', 'bwrap']); + +/** + * Refusal register: ambient PATH words, remote/container arguments, dynamic + * roots and interactive-only startup hooks are intentionally not guessed. + */ +const WRAPPERS_FLAGS_NO_ARG: Record> = { + env: new Set(['-i']), + command: new Set(['-p']), + sudo: new Set(['-i', '-s', '-E']), + timeout: new Set(['--preserve-status']), + exec: new Set(['-cl']), +}; +const WRAPPERS_FLAG_WITH_ARG: Record> = { + env: { '-u': 'unset', '--unset': 'unset' }, + nice: { '-n': 'adjustment' }, + stdbuf: { '-i': 'mode', '-o': 'mode', '-e': 'mode' }, + sudo: { '-u': 'user', '-g': 'group' }, + timeout: { '-s': 'signal', '--signal': 'signal' }, + exec: { '-a': 'name' }, +}; +const INTERPRETER_WORDS = new Set(['sh', 'bash', 'ksh', 'zsh', 'dash']); +const SCRIPT_INTERPRETER_WORDS = new Set([ + ...INTERPRETER_WORDS, + 'python', 'python2', 'python3', 'node', 'nodejs', 'php', 'ruby', 'perl', + 'deno', 'bun', +]); +const INTERPRETER_CODE_FLAGS: Record> = { + python: new Set(['c', '--command']), python2: new Set(['c', '--command']), + python3: new Set(['c', '--command']), + node: new Set(['e', 'p', '--eval', '--print']), nodejs: new Set(['e', 'p', '--eval', '--print']), + php: new Set(['r']), ruby: new Set(['e']), perl: new Set(['e']), + deno: new Set(['e', '--eval']), bun: new Set(['e', '--eval']), +}; + +function wordsOfCommand(node: SyntaxNode, source: string): { text: string; node: SyntaxNode }[] { + const out: { text: string; node: SyntaxNode }[] = []; + for (let i = 0; i < node.namedChildCount; i++) { + const child = node.namedChild(i)!; + if (child.type === 'command_name') { + const word = child.child(0); + if (word) out.push({ text: getNodeText(word, source), node: word }); + } else if (child.type === 'word') { + out.push({ text: getNodeText(child, source), node: child }); + } else if (child.type === 'variable_assignment') { + out.push({ text: '=', node: child }); + } else if (child.type === 'number') { + out.push({ text: getNodeText(child, source), node: child }); + } else { + out.push({ text: '\0', node: child }); + } + } + return out; +} + +function looksLikeAssignmentWord(text: string): boolean { + return /^[A-Za-z_][A-Za-z0-9_]*=/.test(text); +} + +export function resolveInterpreterInvocation( + node: SyntaxNode, + source: string, + rootDir: string +): InterpreterInvocation | null { + const words = wordsOfCommand(node, source); + let i = 0; + let startupPathNode: SyntaxNode | null = null; + let rootRemap: string | null = null; + let bindRemap: { source: string; destination: string } | null = null; + + while (i < words.length && (words[i]!.text === '=' || looksLikeAssignmentWord(words[i]!.text))) { + const assignment = words[i]!.node; + const name = assignment.type === 'variable_assignment' + ? assignment.childForFieldName('name') + : null; + if (name && getNodeText(name, source) === 'BASH_ENV') { + startupPathNode = assignment.childForFieldName('value'); + } + i++; + } + + let sawWrapper = false; + while (i < words.length) { + const { text } = words[i]!; + if (!WRAPPERS_NO_OPTS.has(text) && !ROOT_REMAP_WRAPPERS.has(text) && !(text in WRAPPERS_FLAGS_NO_ARG) && !(text in WRAPPERS_FLAG_WITH_ARG)) break; + + // The query forms of `command` test a name: credit the tested word. + const next = words[i + 1]; + if (text === 'command' && next && (next.text === '-v' || next.text === '-V')) { + const queried = words[i + 2]; + if (!queried || queried.text === '\0') return null; + return { word: queried.text, pathNode: null, startupPathNode: null, normalizedPath: null }; + } + + sawWrapper = true; + i++; + if (text === 'bwrap') { + while (i < words.length && words[i]!.text !== '--') { + const option = words[i]!.text; + if (option === '--bind' || option === '--ro-bind') { + const source = words[i + 1]; + const destination = words[i + 2]; + if (!source || !destination || source.text === '\0' || destination.text === '\0') return null; + bindRemap = { source: source.text, destination: destination.text }; + i += 3; + continue; + } + if (option === '--chdir') { + if (!words[i + 1] || words[i + 1]!.text === '\0') return null; + i += 2; + continue; + } + return null; + } + if (words[i]?.text === '--') i++; + continue; + } + if (text !== 'chroot' && ROOT_REMAP_WRAPPERS.has(text)) return null; + if (text === 'chroot') { + const newRoot = words[i]; + if (!newRoot || newRoot.text === '\0' || newRoot.text.startsWith('-') || !newRoot.text.includes('/')) return null; + rootRemap = newRoot.text; + i++; + continue; + } + const flagsNoArg = WRAPPERS_FLAGS_NO_ARG[text]; + const flagsWithArg = WRAPPERS_FLAG_WITH_ARG[text]; + const noOpts = WRAPPERS_NO_OPTS.has(text); + while (i < words.length) { + const w = words[i]!; + if (w.text === '\0') return null; + if (looksLikeAssignmentWord(w.text)) { i++; continue; } + if (!w.text.startsWith('-')) break; + if (flagsWithArg && (w.text in flagsWithArg)) { + const next = words[i + 1]; + if (!next || next.text === '\0' || next.text.startsWith('-')) return null; + i += 2; + continue; + } + if (text === 'timeout' && flagsNoArg && w.text === '--preserve-status') { i++; continue; } + if (flagsNoArg && flagsNoArg.has(w.text)) { i++; continue; } + if (w.text === '--') { i++; break; } + return null; + } + if (noOpts) continue; + if (text === 'timeout') { + const duration = words[i]; + if (!duration || duration.text.startsWith('-') || duration.text === '\0') return null; + i++; + } + } + + if (i >= words.length) return null; + const candidate = words[i]!; + if (candidate.text === '\0') return null; + + // An interpreter named through a shell-naming variable: resolve its traced + // value and test the basename against the interpreter set. + let effectiveWord = candidate.text.includes('/') ? posix.basename(candidate.text) : candidate.text; + if (candidate.node.type === 'simple_expansion' || candidate.node.type === 'expansion') { + const nameNode = expansionNameNode(candidate.node); + if (!nameNode) return null; + const resolved = traceVariable( + getNodeText(nameNode, source), + candidate.node, + source, + rootDir, + node.startIndex, + new Set(), + 0 + ); + if (resolved === null) return null; + effectiveWord = posix.basename(resolved); + } + + // A direct script path behind the wrappers is itself the invocation target. + if ( + sawWrapper && + candidate.text.includes('/') && + !candidate.text.startsWith('-') && + !SCRIPT_INTERPRETER_WORDS.has(effectiveWord) + ) { + const remappedTarget = rootRemap && candidate.text.startsWith('/') + ? posix.join(rootDir, rootRemap, candidate.text.slice(1)) + : bindRemap && candidate.text.startsWith(bindRemap.destination) + ? posix.join(rootDir, bindRemap.source, candidate.text.slice(bindRemap.destination.length).replace(/^\//, '')) + : null; + const normalizedPath = remappedTarget ? posix.relative(rootDir, remappedTarget) : null; + return { + word: candidate.text, + pathNode: candidate.node, + startupPathNode, + normalizedPath: normalizedPath ? (normalizedPath.startsWith('.') ? normalizedPath : `./${normalizedPath}`) : null, + }; + } + + if (SCRIPT_INTERPRETER_WORDS.has(effectiveWord)) { + i++; + // Skip the interpreter's own options. `-c` (the next word is a command + // string, not a script) and `-s` (read the script from stdin) mean there is + // no script path to resolve at all; short options bundle, so `bash -ec ...` + // has to count too. + while (i < words.length) { + const w = words[i]!; + if (w.text === '--') { i++; break; } + if (!w.text.startsWith('-') || w.text === '-') break; + const codeFlags = INTERPRETER_CODE_FLAGS[effectiveWord] ?? new Set(['c', 's']); + if (codeFlags.has(w.text)) return { word: effectiveWord, pathNode: null, startupPathNode, normalizedPath: null }; + if (effectiveWord === 'bash' && (w.text === '--rcfile' || w.text === '--init-file')) { + if (!words[i + 1] || words[i + 1]!.text === '\0') return { word: effectiveWord, pathNode: null, startupPathNode, normalizedPath: null }; + i += 2; + continue; + } + if (!w.text.startsWith('--') && [...codeFlags].some((flag) => w.text.slice(1).includes(flag))) { + return { word: effectiveWord, pathNode: null, startupPathNode, normalizedPath: null }; + } + i++; + } + const script = words[i]; + if (!script) return { word: effectiveWord, pathNode: null, startupPathNode, normalizedPath: null }; + // A quoted or expansion-bearing argument reaches us as wordsOfCommand's + // '\0' sentinel but still carries its real node. normalizeScriptPath traces + // such a node exactly as it does on the `source` path — the AST is identical + // — so hand it over rather than discarding it, which is what made + // `bash "$HERE/x.sh"` emit no relation at all while `source "$HERE/x.sh"` + // resolved. A bare name still declines there, since bash resolves that + // against the runtime cwd/PATH rather than the script's directory. + const remappedTarget = rootRemap && script.text.startsWith('/') + ? posix.join(rootDir, rootRemap, script.text.slice(1)) + : bindRemap && script.text.startsWith(bindRemap.destination) + ? posix.join(rootDir, bindRemap.source, script.text.slice(bindRemap.destination.length).replace(/^\//, '')) + : null; + const normalizedPath = remappedTarget + ? posix.relative(rootDir, remappedTarget) + : null; + return { + word: effectiveWord, + pathNode: script.node, + startupPathNode, + normalizedPath: normalizedPath ? (normalizedPath.startsWith('.') ? normalizedPath : `./${normalizedPath}`) : null, + }; + } + + return { word: candidate.text, pathNode: null, startupPathNode, normalizedPath: null }; +} + +// --- function-named-as-argument forms ---------------------------------------- + +const SIGNAL_NAMES = new Set([ + 'HUP', 'INT', 'QUIT', 'ILL', 'TRAP', 'ABRT', 'BUS', 'FPE', 'KILL', 'USR1', + 'SEGV', 'USR2', 'PIPE', 'ALRM', 'TERM', 'STKFLT', 'CHLD', 'CONT', 'STOP', + 'TSTP', 'TTIN', 'TTOU', 'URG', 'XCPU', 'XFS', 'VTALRM', 'PROF', 'WINCH', + 'IO', 'PWR', 'SYS', 'EXIT', 'DEBUG', 'RETURN', 'ERR', +]); + +function isSignalSpecification(text: string): boolean { + if (/^\d+$/.test(text)) return true; + const bare = text.replace(/^SIG/i, ''); + return SIGNAL_NAMES.has(bare.toUpperCase()); +} + +function stripQuotes(text: string): string { + if (text.length >= 2 && ((text.startsWith('"') && text.endsWith('"')) || (text.startsWith("'") && text.endsWith("'")))) { + return text.slice(1, -1); + } + return text; +} + +/** + * A function named as an argument to trap/complete/export — the guarded set + * that genuinely CALLS the function. Returns the function name, or null. + */ +export function functionRefArguments( + node: SyntaxNode, + source: string, + filePath: string +): string | null { + const word = commandWord(node, source); + if (!word) return null; + + const operandTexts = (): { text: string; node: SyntaxNode }[] => { + const out: { text: string; node: SyntaxNode }[] = []; + let pastName = false; + for (let i = 0; i < node.namedChildCount; i++) { + const child = node.namedChild(i)!; + if (!pastName) { + // Wrapper objects are re-created per access — never compare nodes + // with ===; the single command_name child IS the name. + if (child.type === 'command_name') pastName = true; + continue; + } + if (child.type === 'variable_assignment') continue; + const type = child.type; + if (type === 'word' || type === 'raw_string' || type === 'string') { + out.push({ text: getNodeText(child, source), node: child }); + } else { + out.push({ text: '\0', node: child }); + } + } + return out; + }; + + if (word === 'trap') { + const operands = operandTexts(); + let i = 0; + while (i < operands.length) { + const t = operands[i]!.text; + if (t === '--') { i++; break; } + if (t.startsWith('-')) { i++; continue; } + break; + } + const rest = operands.slice(i); + if (rest.length < 2) return null; + const rawAction = rest[0]!.text; + const action = stripQuotes(rawAction); + if (action === '' || action.includes(' ') || action.startsWith('-')) return null; + if (isSignalSpecification(action)) return null; + return action; + } + + if (word === 'complete') { + const operands = operandTexts(); + for (let i = 0; i < operands.length - 1; i++) { + if (operands[i]!.text === '-F' || operands[i]!.text === '--command') { + const fn = stripQuotes(operands[i + 1]!.text); + if (fn && !fn.startsWith('-')) return fn; + } + } + return null; + } + + if (word === 'export') { + const operands = operandTexts(); + let sawFuncOpt = false; + for (let i = 0; i < operands.length; i++) { + const t = operands[i]!.text; + if (t === '--') continue; + if (/^-[a-zA-Z]*f/.test(t)) { sawFuncOpt = true; continue; } + if (t.startsWith('-')) continue; + if (sawFuncOpt) { + const fn = stripQuotes(t).split('=').pop()!; + return fn || null; + } + } + return null; + } + + // The bats runner: an ordinary word everywhere else, meaningful only in a + // .bats file (an extension the grammar health check kept). + if (word === 'run' && filePath.endsWith('.bats')) { + const operands = operandTexts().filter((o) => o.text !== '\0'); + const first = operands[0]; + if (!first) return null; + const fn = stripQuotes(first.text); + if (!fn || fn.startsWith('-') || fn.startsWith('$')) return null; + return fn; + } + + return null; +} + +// --- classification --------------------------------------------------------- + +const SOURCING_WORDS = new Set(['source', '.']); +const DIRECTORY_CHANGE_WORDS = new Set(['cd', 'pushd', 'popd']); +const SHELL_SCRIPT_EXTENSIONS = new Set(['.sh', '.bash', '.ksh', '.zsh', '.dash', '.bats']); + +function isShellScriptReference(filePath: string): boolean { + const basename = posix.basename(filePath).toLowerCase(); + const dot = basename.lastIndexOf('.'); + return dot < 0 || SHELL_SCRIPT_EXTENSIONS.has(basename.slice(dot)); +} + +function localRedirectPathNodes(node: SyntaxNode): SyntaxNode[] { + const paths: SyntaxNode[] = []; + const walk = (current: SyntaxNode): void => { + if ((current.type === 'file_redirect' || current.type.endsWith('_redirect')) && current.type !== 'heredoc_redirect') { + const candidate = current.namedChild(current.namedChildCount - 1); + if (candidate && ['word', 'string', 'raw_string', 'concatenation'].includes(candidate.type)) { + paths.push(candidate); + } + return; + } + for (let i = 0; i < current.namedChildCount; i++) { + const child = current.namedChild(i); + if (child) walk(child); + } + }; + walk(node); + return paths; +} + +function emitLocalRedirectRelations(node: SyntaxNode, ctx: ExtractorContext, state: CwdState): void { + const containingFileDir = posix.dirname(ctx.filePath); + const base = state.cwdChanged ? null : containingFileDir; + for (const redirectPath of localRedirectPathNodes(node)) { + const normalized = normalizeScriptPath(redirectPath, ctx.source, containingFileDir, base); + if (normalized && isShellScriptReference(normalized)) { + emitScriptRelation(ctx, normalized, 'references', redirectPath); + } + } +} + +function isInsideCommandSubstitution(node: SyntaxNode): boolean { + let current = node.parent; + while (current) { + if (current.type === 'command_substitution') return true; + current = current.parent; + } + return false; +} + +function recordPathPrepend(node: SyntaxNode, ctx: ExtractorContext, state: CwdState): void { + const commandText = getNodeText(node, ctx.source); + const pathMatch = commandText.match(/(?:^|\s)(?:export\s+)?PATH\s*=\s*([^\n;]+)/); + if (!pathMatch) return; + const value = pathMatch[1]!.replace(/^['"]|['"]$/g, ''); + const anchored = value.match(/^\$\(dirname\s+["']?\$0["']?\)([^:]+)(?::\$PATH)?$/) + ?? commandText.match(/\$\(dirname\s+["']?\$0["']?\)([^:$\s"']+)/); + const literal = value.match(/^(\.\.?\/[^:]+)(?::\$PATH)?$/); + if (anchored) state.pathPrepends.push(posix.join(posix.dirname(ctx.filePath), anchored[1]!)); + else if (literal) state.pathPrepends.push(posix.normalize(posix.join(posix.dirname(ctx.filePath), literal[1]!))); +} + +function emitScriptRelation( + ctx: ExtractorContext, + normalizedPath: string, + kind: 'imports' | 'references', + anchorNode: SyntaxNode +): void { + if (kind === 'imports') { + ctx.createNode('import', normalizedPath, anchorNode, { + signature: getNodeText(anchorNode, ctx.source).trim().slice(0, 100), + }); + } + if (ctx.nodeStack.length === 0) return; + const fromNodeId = ctx.nodeStack[ctx.nodeStack.length - 1]; + if (!fromNodeId) return; + ctx.addUnresolvedReference({ + fromNodeId, + referenceName: normalizedPath, + referenceKind: kind, + line: anchorNode.startPosition.row + 1, + column: anchorNode.startPosition.column, + }); +} + +function classifyShellCommand(node: SyntaxNode, ctx: ExtractorContext, state: CwdState): void { + const source = ctx.source; + const word = commandWord(node, source); + if (!word) return; + + const containingFileDir = posix.dirname(ctx.filePath); + const base = state.cwdChanged ? null : containingFileDir; + + // Redirections are performed by the local shell before a remote/container + // command receives control. This keeps `ssh host 'bash -s' < ./x.sh` and + // `docker run -i image bash -s < ./x.sh` visible without admitting the + // remote command's own path arguments. + emitLocalRedirectRelations(node, ctx, state); + + // A command substitution is evaluated by this shell even when its output + // becomes an argument to a remote command (`ssh host "$(cat ./x.sh)"`). + // Credit the local file operand, but only for the explicit file-reading + // form and only when it names a shell script. + if (word === 'cat' && isInsideCommandSubstitution(node)) { + const operand = node.namedChildren.find((child) => + child.type !== 'command_name' && ['word', 'string', 'raw_string', 'concatenation'].includes(child.type)); + if (operand) { + const normalized = normalizeScriptPath(operand, source, containingFileDir, base); + if (normalized && isShellScriptReference(normalized)) { + emitScriptRelation(ctx, normalized, 'references', operand); + } + } + } + + if (SOURCING_WORDS.has(word)) { + const args = node.namedChildren.filter((c) => c.type !== 'command_name'); + const first = args[0]; + if (!first) return; + const text = getNodeText(first, source).replace(/^['"]|['"]$/g, ''); + if (!text.includes('/')) return; + const normalized = normalizeScriptPath(first, source, containingFileDir, base); + if (normalized && isShellScriptReference(normalized)) emitScriptRelation(ctx, normalized, 'imports', first); + return; + } + + if (word.includes('/') && !SCRIPT_INTERPRETER_WORDS.has(posix.basename(word))) { + const nameNode = node.childForFieldName('name'); + const nameWord = nameNode?.child(0); + if (!nameWord) return; + const normalized = normalizeScriptPath(nameWord, source, containingFileDir, base); + if (normalized && isShellScriptReference(normalized)) emitScriptRelation(ctx, normalized, 'references', nameNode!); + return; + } + + const invocation = resolveInterpreterInvocation(node, source, containingFileDir); + if (!invocation) return; + + if (invocation.startupPathNode) { + const startupPath = normalizeScriptPath(invocation.startupPathNode, source, containingFileDir, base); + if (startupPath && isShellScriptReference(startupPath)) { + emitScriptRelation(ctx, startupPath, 'imports', invocation.startupPathNode); + } + } + + if (invocation.pathNode) { + const normalized = invocation.normalizedPath ?? normalizeScriptPath(invocation.pathNode, source, containingFileDir, base); + if (normalized) { + emitScriptRelation(ctx, normalized, 'references', invocation.pathNode); + return; + } + return; + } + + // Resolve only directories explicitly prepended by this script. The + // inherited PATH is intentionally outside the static-analysis boundary. + if (state.pathPrepends.length > 0 && invocation.word && !invocation.word.includes('/')) { + const targetDir = state.pathPrepends[state.pathPrepends.length - 1]!; + const rel = posix.relative(containingFileDir, posix.join(targetDir, invocation.word)); + emitScriptRelation(ctx, rel.startsWith('.') ? rel : `./${rel}`, 'references', node.childForFieldName('name')!); + return; + } + + // A function named as an argument (trap action, export -f, complete -F, + // the bats runner) credits the FUNCTION, not the builtin word. + const fnArg = functionRefArguments(node, source, ctx.filePath); + if (fnArg) { + if (ctx.nodeStack.length > 0) { + const fromNodeId = ctx.nodeStack[ctx.nodeStack.length - 1]; + if (fromNodeId) { + ctx.addUnresolvedReference({ + fromNodeId, + referenceName: fnArg, + referenceKind: 'calls', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); + } + } + return; + } + + if (ctx.nodeStack.length > 0) { + const fromNodeId = ctx.nodeStack[ctx.nodeStack.length - 1]; + if (fromNodeId) { + ctx.addUnresolvedReference({ + fromNodeId, + referenceName: invocation.word, + referenceKind: 'calls', + line: node.startPosition.row + 1, + column: node.startPosition.column, + }); + } + } +} + +export const bashExtractor: LanguageExtractor = { + functionTypes: ['function_definition'], + classTypes: [], + methodTypes: [], + interfaceTypes: [], + structTypes: [], + enumTypes: [], + typeAliasTypes: [], + importTypes: [], + callTypes: [], + variableTypes: ['variable_assignment', 'declaration_command'], + nameField: 'name', + bodyField: 'body', + paramsField: '', + + visitNode: (node, ctx) => { + const state = stateFor(ctx); + if (node.type === 'redirected_statement') { + emitLocalRedirectRelations(node, ctx, state); + return false; + } + if (node.type === 'declaration_command') { + recordPathPrepend(node, ctx, state); + return false; + } + if (node.type !== 'command') return false; + + classifyShellCommand(node, ctx, state); + + const word = commandWord(node, ctx.source); + if (word && DIRECTORY_CHANGE_WORDS.has(word) && !runsInOwnProcess(node)) { + state.cwdChanged = true; + } + + for (const child of node.namedChildren) { + if (child.type === 'heredoc_redirect') continue; + ctx.visitNode(child); + } + return true; + }, +}; diff --git a/src/extraction/languages/index.ts b/src/extraction/languages/index.ts index 6b760b01d..b1d7d4221 100644 --- a/src/extraction/languages/index.ts +++ b/src/extraction/languages/index.ts @@ -36,6 +36,7 @@ import { solidityExtractor } from './solidity'; import { terraformExtractor } from './terraform'; import { arktsExtractor } from './arkts'; import { nixExtractor } from './nix'; +import { bashExtractor } from './bash'; export const EXTRACTORS: Partial> = { typescript: typescriptExtractor, @@ -69,4 +70,5 @@ export const EXTRACTORS: Partial> = { terraform: terraformExtractor, arkts: arktsExtractor, nix: nixExtractor, + bash: bashExtractor, }; diff --git a/src/extraction/shebang.ts b/src/extraction/shebang.ts new file mode 100644 index 000000000..0ea121182 --- /dev/null +++ b/src/extraction/shebang.ts @@ -0,0 +1,30 @@ +import * as fs from 'fs'; +import * as path from 'path'; + +const SHELL_SHEBANG = /^#!\s*(?:\/usr\/bin\/env(?:\s+-S)?\s+|(?:\/\S+\/)*)(?:ba|z|k|da)?sh(?:\s|$)/i; + +const SHEBANG_SCAN_BYTES = 256; + +export function looksLikeShellScript(source: string): boolean { + const firstLine = source.slice(0, SHEBANG_SCAN_BYTES).split(/\r?\n/, 1)[0] ?? ''; + return SHELL_SHEBANG.test(firstLine); +} + +export function looksLikeShellScriptFile(filePath: string, rootDir: string): boolean { + try { + return looksLikeShellScript(fsReadPrefix(path.join(rootDir, filePath))); + } catch { + return false; + } +} + +function fsReadPrefix(filePath: string): string { + const fd = fs.openSync(filePath, 'r'); + try { + const buffer = Buffer.allocUnsafe(SHEBANG_SCAN_BYTES); + const bytes = fs.readSync(fd, buffer, 0, SHEBANG_SCAN_BYTES, 0); + return buffer.subarray(0, bytes).toString('utf8'); + } finally { + fs.closeSync(fd); + } +} diff --git a/src/extraction/tree-sitter.ts b/src/extraction/tree-sitter.ts index c34dc4716..6b2bf1f6d 100644 --- a/src/extraction/tree-sitter.ts +++ b/src/extraction/tree-sitter.ts @@ -23,6 +23,7 @@ import type { LanguageExtractor, ExtractorContext } from './tree-sitter-types'; import { EXTRACTORS } from './languages'; import { stripCppTemplateArgs } from './languages/c-cpp'; import { rustImplTypeName } from './languages/rust'; +import { extractBashVariables } from './languages/bash'; import { LiquidExtractor } from './liquid-extractor'; import { RazorExtractor } from './razor-extractor'; import { SvelteExtractor } from './svelte-extractor'; @@ -2883,6 +2884,21 @@ export class TreeSitterExtractor { isExported, }); } + } else if (this.language === 'bash') { + // Bash: `variable_assignment` carries its name in a nested + // `variable_name` child, and a `declaration_command` wraps the builtin's + // assignments — neither matches the generic identifier walk. A plain + // assignment inside a function body is suppressed (deliberate + // simplification); export/readonly/declare forms surface anywhere, + // readonly / declare -r as constants. + for (const v of extractBashVariables(node, this.source)) { + const initValue = v.valueNode ? getNodeText(v.valueNode, this.source).slice(0, 100) : undefined; + const initSignature = initValue ? `= ${initValue}${initValue.length >= 100 ? '...' : ''}` : undefined; + this.createNode(v.kind, v.name, v.positionNode, { docstring, signature: initSignature }); + if (v.valueNode) { + this.visitFunctionBody(v.valueNode, ''); + } + } } else { // Generic fallback for other languages // Try to find identifier children @@ -5199,6 +5215,19 @@ export class TreeSitterExtractor { const visitForCallsAndStructure = (node: SyntaxNode): void => { const nodeType = node.type; + // Bash: the body walker is the ONLY path into function bodies (the main + // visitNode walker stops at function_definitions), and both commands and + // declaration forms must flow through the same extractor hooks the + // top-level walk uses — one seam for every command node. + if (this.language === 'bash' && this.extractor) { + if (this.extractor.visitNode && nodeType === 'command') { + const ctx = this.makeExtractorContext(); + this.extractor.visitNode(node, ctx); + } else if (this.extractor.variableTypes.includes(nodeType)) { + this.extractVariable(node); + } + } + // Function-as-value capture (#756) — function bodies are walked here, // not in visitNode, so the capture hook must fire in both walkers. this.maybeCaptureFnRefs(node, nodeType); diff --git a/src/extraction/wasm/tree-sitter-bash.wasm b/src/extraction/wasm/tree-sitter-bash.wasm new file mode 100644 index 0000000000000000000000000000000000000000..4e4198c951ed32f6dae7cf45eb42396e54d64dda GIT binary patch literal 1358224 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

;l$g9((jW+oP)2bFM}Y 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�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

R2 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 literal 0 HcmV?d00001 diff --git a/src/resolution/bash-scope.ts b/src/resolution/bash-scope.ts new file mode 100644 index 000000000..b8ca88f0c --- /dev/null +++ b/src/resolution/bash-scope.ts @@ -0,0 +1,107 @@ +import * as posix from 'node:path/posix'; +import type { Node } from '../types'; +import type { ResolutionContext } from './types'; + +/** + * Bash keeps ONE function namespace per process: sourcing shares functions, + * executing does not. Reachability is co-membership in some file's forward + * closure — the model the two-tier gate below implements. Derived from the + * import NODES the extractor created for sourcing statements, so it never + * depends on whether a particular reference has become an edge yet. + */ + +export type BashSourceClosure = Map>; + +const closureMemos = new WeakMap(); + +export function clearBashScopeMemos(context: ResolutionContext): void { + closureMemos.delete(context); +} + +/** Forward closure per bash file: the file itself plus everything it transitively sources. */ +export function buildSourceClosure(context: ResolutionContext): BashSourceClosure { + const memo = closureMemos.get(context); + if (memo) return memo; + + const sourcingEdges = new Map>(); + for (const node of context.getNodesByKind('import')) { + if (node.language !== 'bash') continue; + const target = resolveScriptPath(node.name, node.filePath); + if (!target) continue; + let set = sourcingEdges.get(node.filePath); + if (!set) { + set = new Set(); + sourcingEdges.set(node.filePath, set); + } + set.add(target); + } + + const closures: BashSourceClosure = new Map(); + const compute = (file: string, seen: Set): Set => { + const cached = closures.get(file); + if (cached) return cached; + if (seen.has(file)) return seen; + seen.add(file); + const out = new Set([file]); + for (const target of sourcingEdges.get(file) ?? []) { + for (const f of compute(target, seen)) out.add(f); + } + seen.delete(file); + closures.set(file, out); + return out; + }; + for (const file of sourcingEdges.keys()) compute(file, new Set()); + + closureMemos.set(context, closures); + return closures; +} + +function resolveScriptPath(name: string, fromFile: string): string | null { + if (!name.startsWith('./') && !name.startsWith('../')) return null; + const dir = posix.dirname(fromFile); + return posix.normalize(posix.join(dir, name)); +} + +export type GateVerdict = + | { accept: 'full' | 'reduced'; confidence: number } + | { accept: false }; + +/** Pure decision: is `candidate` reachable from the referencing file's process? */ +export function gateBashNameMatch( + refFilePath: string, + candidateFilePath: string, + closures: BashSourceClosure +): GateVerdict { + if (refFilePath === candidateFilePath) return { accept: 'full', confidence: 0.92 }; + for (const closure of closures.values()) { + if (closure.has(refFilePath) && closure.has(candidateFilePath)) { + return { accept: 'reduced', confidence: 0.75 }; + } + } + return { accept: false }; +} + +/** Pick the reachable winner among same-named bash function candidates, or null. */ +export function selectReachableBashFunction( + refFilePath: string, + candidates: Node[], + closures: BashSourceClosure +): Node | null { + let best: Node | null = null; + let bestConfidence = 0; + let tied = false; + for (const candidate of candidates) { + const verdict = gateBashNameMatch(refFilePath, candidate.filePath, closures); + if (!verdict.accept) continue; + if (verdict.confidence > bestConfidence) { + best = candidate; + bestConfidence = verdict.confidence; + tied = false; + } else if (verdict.confidence === bestConfidence && candidate.filePath !== best?.filePath) { + // Several closure files define the name — stay unresolved rather than + // guess which one the process actually sees. + tied = true; + } + } + return tied ? null : best; +} diff --git a/src/resolution/import-resolver.ts b/src/resolution/import-resolver.ts index 60c7b3008..e3cdc5b7d 100644 --- a/src/resolution/import-resolver.ts +++ b/src/resolution/import-resolver.ts @@ -47,8 +47,23 @@ const EXTENSION_RESOLUTION: Record = { ruby: ['.rb'], objc: ['.h', '.m', '.mm'], nix: ['.nix', '/default.nix'], + // Shell extensions the grammar health check parsed cleanly, plus the empty + // suffix: sourcing an extensionless helper by bare name is common. + bash: ['.sh', '.bash', '.ksh', '.dash', '.bats', ''], }; +export function isBashScriptPathRef(ref: UnresolvedRef): boolean { + if (ref.language !== 'bash') return false; + if (ref.referenceKind !== 'imports' && ref.referenceKind !== 'references') return false; + const name = ref.referenceName; + if (/[\s"'`$;&|<>(){}[\]*?!]/.test(name)) return false; + // Bash emits repository-relative candidates for conventional root anchors + // (for example `$REPO_ROOT/bin/deploy`), so a path with a directory segment + // is eligible even when it has no shell extension. Bare command words stay + // excluded: they belong to PATH/name resolution, not file-path resolution. + return name.startsWith('./') || name.startsWith('../') || (name.includes('/') && !name.startsWith('/')) || /\.(sh|bash|ksh|dash|bats)$/.test(name); +} + export function isNixPathImportRef(ref: UnresolvedRef): boolean { return ( ref.language === 'nix' && @@ -1427,6 +1442,30 @@ export function resolveViaImport( return null; } + // Bash sourced/executed script paths resolve to file nodes only, mirroring + // the nix branch. The classifier normalizes interpolated paths + // (SCRIPT_DIR anchors, dirname/cd-print substitutions) to dot-slash-prefixed + // relative paths; a dynamic path never becomes a reference at all. + if (isBashScriptPathRef(ref)) { + const resolvedPath = resolveImportPath(ref.referenceName, ref.filePath, ref.language, context); + if (!resolvedPath) return null; + + const basename = resolvedPath.split('/').pop()!; + const fileNode = context + .getNodesByName(basename) + .find((n) => n.kind === 'file' && n.filePath === resolvedPath); + + if (fileNode) { + return { + original: ref, + targetNodeId: fileNode.id, + confidence: 0.9, + resolvedBy: 'import', + }; + } + return null; + } + // Use cached import mappings (avoids re-reading and re-parsing per ref) const imports = context.getImportMappings(ref.filePath, ref.language); if (imports.length === 0 && !context.readFile(ref.filePath)) { diff --git a/src/resolution/index.ts b/src/resolution/index.ts index 7b4bccc18..3e27352ba 100644 --- a/src/resolution/index.ts +++ b/src/resolution/index.ts @@ -17,7 +17,7 @@ import { ImportMapping, } from './types'; import { matchReference, matchFunctionRef, matchDottedCallChain, matchScopedCallChain, matchMethodCall, sameLanguageFamily, crossesKnownFamily, dumpNameMatcherProfile, clearNameMatcherMemos } from './name-matcher'; -import { resolveViaImport, resolveJvmImport, extractImportMappings, extractReExports, loadCppIncludeDirs, isPhpIncludePathRef, isCobolCopybookRef, isNixPathImportRef, clearImportResolverMemos } from './import-resolver'; +import { resolveViaImport, resolveJvmImport, extractImportMappings, extractReExports, loadCppIncludeDirs, isPhpIncludePathRef, isCobolCopybookRef, isNixPathImportRef, isBashScriptPathRef, clearImportResolverMemos } from './import-resolver'; import { ResolverPool, minRefsForPool } from './resolver-pool'; import { detectFrameworks } from './frameworks'; import { synthesizeCallbackEdges } from './callback-synthesizer'; @@ -884,8 +884,9 @@ export class ReferenceResolver { // ArkTS chained-attribute refs carry a leading dot (`.titleStyle`) that // routes them to the decorator-gated matcher; the symbol itself is // indexed under the bare name, so the existence check strips the dot. - // Nix static path imports (`import ./x.nix`) name a FILE, not a symbol — - // they bypass the symbol-existence check and resolve via resolveViaImport. + // Nix static path imports (`import ./x.nix`) and bash sourced/executed + // script paths name a FILE, not a symbol — they bypass the symbol- + // existence check and resolve via resolveViaImport. let existenceName = ref.language === 'arkts' && ref.referenceName.startsWith('.') ? ref.referenceName.slice(1) @@ -896,6 +897,7 @@ export class ReferenceResolver { const tPre = this.profileStages ? process.hrtime.bigint() : 0n; const preFilterPass = isNixPathImportRef(ref) || + isBashScriptPathRef(ref) || this.hasAnyPossibleMatch(existenceName) || this.matchesAnyImport(ref) || this.frameworks.some((f) => f.claimsReference?.(ref.referenceName)); @@ -992,7 +994,10 @@ export class ReferenceResolver { // qualified-name fallback would only ever add wrong cross-module edges. // Nix static path imports are file references for the same reason — // falling through would let "./x.nix" name-match an unrelated node. - if (isPhpIncludePathRef(ref) || isCobolCopybookRef(ref) || isNixPathImportRef(ref) || ref.language === 'terraform') { + // Bash sourced/executed script paths are file references too: the + // name-match decision they must never reach lives in matchReference's + // bash branch (reachability goal), not in this gate. + if (isPhpIncludePathRef(ref) || isCobolCopybookRef(ref) || isNixPathImportRef(ref) || isBashScriptPathRef(ref) || ref.language === 'terraform') { return candidates.length > 0 ? candidates.reduce((best, curr) => curr.confidence > best.confidence ? curr : best @@ -2419,6 +2424,10 @@ export class ReferenceResolver { private gateLanguage(result: ResolvedRef | null, ref: UnresolvedRef): ResolvedRef | null { if (!result) return result; + // A Bash script-path reference can deliberately launch an indexed Python, + // Node, PHP, or other executable through its interpreter. This is a + // file-to-file execution edge, not a language-family symbol binding. + if (isBashScriptPathRef(ref)) return result; const tgt = this.getLanguageFromNodeId(result.targetNodeId); if (!tgt || !ref.language) return result; if ((ref.referenceKind === 'references' || ref.referenceKind === 'function_ref') && !sameLanguageFamily(tgt, ref.language)) return null; diff --git a/src/resolution/name-matcher.ts b/src/resolution/name-matcher.ts index c74d8f272..e2a42b025 100644 --- a/src/resolution/name-matcher.ts +++ b/src/resolution/name-matcher.ts @@ -6,6 +6,7 @@ import { Language, Node } from '../types'; import { UnresolvedRef, ResolvedRef, ResolutionContext } from './types'; +import { buildSourceClosure, gateBashNameMatch, selectReachableBashFunction } from './bash-scope'; /** * Ceiling on how many same-named definitions a FUZZY name-match strategy will @@ -2491,6 +2492,33 @@ export function matchReference( return matchFunctionRef(ref, context); } + // Bash calls bind ONLY through reachability: a call names a function in the + // same file or in the transitive source closure of the calling file. The + // generic single-winner matcher would pick whichever same-named function was + // indexed first — nearly every script defines log/die/usage — so this branch + // enumerates candidates itself and gates each through gateBashNameMatch. + // Nothing reachable → null; the fuzzy and qualified-name fallbacks must + // never connect a shell call to an arbitrary same-named symbol. + if (ref.language === 'bash' && ref.referenceKind === 'calls' && !ref.referenceName.includes('/')) { + const candidates = context + .getNodesByName(ref.referenceName) + .filter((n) => n.language === 'bash' && n.kind === 'function'); + if (candidates.length > 0) { + const closures = buildSourceClosure(context); + const chosen = selectReachableBashFunction(ref.filePath, candidates, closures); + if (chosen) { + const verdict = gateBashNameMatch(ref.filePath, chosen.filePath, closures); + return { + original: ref, + targetNodeId: chosen.id, + confidence: verdict.accept ? verdict.confidence : 0.75, + resolvedBy: 'exact-match', + }; + } + } + return null; + } + // ArkTS chained UI attributes — emitted with a leading dot (`.titleStyle`, // `.width`) by the extractor — resolve ONLY to decorator-marked attribute // helpers: `@Extend`/`@Styles`/`@AnimatableExtend` functions (and global diff --git a/src/sync/watcher.ts b/src/sync/watcher.ts index 034be858a..94565484b 100644 --- a/src/sync/watcher.ts +++ b/src/sync/watcher.ts @@ -406,7 +406,7 @@ export class FileWatcher { this.ready = true; for (const cb of this.readyWaiters) cb(); this.readyWaiters.length = 0; - if (IS_TEST_RUNTIME) liveWatchersForTests.set(this.projectRoot, this); + if (IS_TEST_RUNTIME || this.inertForTests) liveWatchersForTests.set(this.projectRoot, this); logDebug('File watcher started', { projectRoot: this.projectRoot, @@ -593,7 +593,7 @@ export class FileWatcher { this.refreshScope(rel); return; } - if (!isSourceFile(rel, loadExtensionOverrides(this.projectRoot))) { + if (!isSourceFile(rel, this.projectRoot, loadExtensionOverrides(this.projectRoot))) { this.maybeScheduleForRemovedDir(rel); return; } @@ -788,7 +788,7 @@ export class FileWatcher { this.pendingFiles.clear(); this.ready = false; this.ignoreMatcher = null; - if (IS_TEST_RUNTIME) liveWatchersForTests.delete(this.projectRoot); + if (IS_TEST_RUNTIME || this.inertForTests) liveWatchersForTests.delete(this.projectRoot); logDebug('File watcher stopped'); } diff --git a/src/types.ts b/src/types.ts index 186f57adc..e94709f37 100644 --- a/src/types.ts +++ b/src/types.ts @@ -102,6 +102,7 @@ export const LANGUAGES = [ 'scala', 'lua', 'luau', + 'bash', 'objc', 'r', 'solidity',