fix(ast_query): skip dependency dirs (node_modules/vendor) by default

ast_query walked every language-matching file under the search root, including
node_modules, vendor and bower_components — parsing third-party code and
flooding results with irrelevant matches (large token cost on every call,
worst for JS/TS node_modules). Skip these by name during the walk, alongside
the existing hidden-dir skip.

The walk root is now exempt from both skips, so targeting a dependency dir
explicitly (paths:["vendor/foo"]) still works — previously naming a hidden or
dependency dir as the root would have skipped everything. Documents the scope
in the tool description and help resource.

Adds a regression test covering default-skip and explicit-target inclusion.
This commit is contained in:
2026-06-20 01:15:37 +01:00
parent 99514ff8d6
commit 62971c9f8c
4 changed files with 86 additions and 1 deletions
+17 -1
View File
@@ -131,7 +131,10 @@ func (s *Server) runASTQueryWalk(ctx context.Context, p *astQueryParams, exts []
return nil
}
if info.IsDir() {
if strings.HasPrefix(info.Name(), ".") {
// Skip hidden and dependency dirs (third-party code that would
// flood results), but never the walk root itself — the caller
// explicitly targeted it, e.g. paths:["vendor/foo"].
if path != searchPath && (strings.HasPrefix(info.Name(), ".") || isDependencyDir(info.Name())) {
return filepath.SkipDir
}
return nil
@@ -172,6 +175,19 @@ func (s *Server) runASTQueryWalk(ctx context.Context, p *astQueryParams, exts []
return allResults
}
// isDependencyDir reports whether name is a well-known third-party dependency
// directory that ast_query skips by default. These hold vendored/installed code,
// not the caller's source, and parsing them wastes time and floods results with
// irrelevant matches. Target one explicitly via paths to query inside it.
func isDependencyDir(name string) bool {
switch name {
case "node_modules", "vendor", "bower_components":
return true
default:
return false
}
}
// hasAnySuffix reports whether path ends with any of the given suffixes.
func hasAnySuffix(path string, suffixes []string) bool {
for _, ext := range suffixes {