Add regex filtering to clangd navigation

This commit is contained in:
2026-06-04 16:15:54 +02:00
parent ca452f46e1
commit 3c709f07e6
3 changed files with 28 additions and 0 deletions

View File

@@ -68,6 +68,7 @@ flat source tree and extracted components:
```powershell ```powershell
python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name execute_brush python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name execute_brush
python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name-regex "execute_.*preset"
python scripts/dev/clangd_nav.py definition --file src/node_panel_brush.cpp --line 511 --column 39 python scripts/dev/clangd_nav.py definition --file src/node_panel_brush.cpp --line 511 --column 39
python scripts/dev/clangd_nav.py references --file src/app_core/brush_ui.h --line 783 --column 45 python scripts/dev/clangd_nav.py references --file src/app_core/brush_ui.h --line 783 --column 45
``` ```
@@ -76,6 +77,8 @@ The helper talks to `clangd` using an existing `compile_commands.json`. It
defaults to `out/build/windows-clangcl-asan` and then `out/build/android-arm64`; defaults to `out/build/windows-clangcl-asan` and then `out/build/android-arm64`;
pass `--compile-commands-dir` or set `PP_CLANGD_COMPILE_COMMANDS_DIR` when using pass `--compile-commands-dir` or set `PP_CLANGD_COMPILE_COMMANDS_DIR` when using
another Ninja build tree. Use `--name` and `--max-results` to keep output small. another Ninja build tree. Use `--name` and `--max-results` to keep output small.
Use `--name-regex` for regex filtering against `qualifiedName`; matching is
case-insensitive by default, and `--no-ignore-case` makes it case-sensitive.
Treat symbol, hover, declaration, definition, and implementation lookups as the Treat symbol, hover, declaration, definition, and implementation lookups as the
reliable path. Reference lookups are riskier because a one-shot clangd process reliable path. Reference lookups are riskier because a one-shot clangd process
may not have a complete project index; the helper refuses reference queries may not have a complete project index; the helper refuses reference queries

View File

@@ -76,6 +76,7 @@ powershell -ExecutionPolicy Bypass -File scripts\automation\platform-build.ps1 -
powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug powershell -ExecutionPolicy Bypass -File scripts\automation\package-smoke.ps1 -Preset windows-msvc-default -Configuration Debug
cmake --fresh --preset windows-clangcl-asan cmake --fresh --preset windows-clangcl-asan
python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name execute_brush python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name execute_brush
python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name-regex "execute_.*preset"
python scripts/dev/clangd_nav.py definition --file src/node_panel_brush.cpp --line 511 --column 39 python scripts/dev/clangd_nav.py definition --file src/node_panel_brush.cpp --line 511 --column 39
``` ```
@@ -96,6 +97,9 @@ Known local toolchain state:
the current `compile_commands.json` from `windows-clangcl-asan`, the current `compile_commands.json` from `windows-clangcl-asan`,
`android-arm64`, or a caller-provided build directory. Symbol, hover, `android-arm64`, or a caller-provided build directory. Symbol, hover,
declaration, definition, and implementation lookups are the reliable use case. declaration, definition, and implementation lookups are the reliable use case.
Symbol listing supports substring filtering with `--name` and regex filtering
against `qualifiedName` with `--name-regex`; regex matching is case-insensitive
by default and can be made case-sensitive with `--no-ignore-case`.
Reference lookup is guarded because a one-shot clangd process may not have a Reference lookup is guarded because a one-shot clangd process may not have a
complete project index: pass `--background-index` for broader best-effort complete project index: pass `--background-index` for broader best-effort
results or `--allow-incomplete-references` for explicitly results or `--allow-incomplete-references` for explicitly

View File

@@ -3,6 +3,7 @@
Examples: Examples:
python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h
python scripts/dev/clangd_nav.py symbols --file src/app_core/brush_ui.h --name-regex "execute_.*preset"
python scripts/dev/clangd_nav.py definition --file src/node_panel_brush.cpp --line 410 --column 30 python scripts/dev/clangd_nav.py definition --file src/node_panel_brush.cpp --line 410 --column 30
python scripts/dev/clangd_nav.py references --file src/app_core/brush_ui.h --line 192 --column 43 python scripts/dev/clangd_nav.py references --file src/app_core/brush_ui.h --line 192 --column 43
""" """
@@ -14,6 +15,7 @@ import json
import os import os
from pathlib import Path from pathlib import Path
import queue import queue
import re
import subprocess import subprocess
import sys import sys
import threading import threading
@@ -324,6 +326,13 @@ def run(args: argparse.Namespace) -> int:
compile_commands_dir = _find_compile_commands_dir(repo_root, args.compile_commands_dir) compile_commands_dir = _find_compile_commands_dir(repo_root, args.compile_commands_dir)
file_path = _resolve_file(repo_root, args.file) file_path = _resolve_file(repo_root, args.file)
name_regex = None
if args.name_regex:
try:
name_regex = re.compile(args.name_regex, re.IGNORECASE if args.ignore_case else 0)
except re.error as exc:
raise SystemExit(f"invalid --name-regex: {exc}") from exc
if args.command == "references" and not args.background_index and not args.allow_incomplete_references: if args.command == "references" and not args.background_index and not args.allow_incomplete_references:
raise SystemExit( raise SystemExit(
"references may be incomplete without clangd background indexing. " "references may be incomplete without clangd background indexing. "
@@ -372,6 +381,11 @@ def run(args: argparse.Namespace) -> int:
symbol for symbol in flattened symbol for symbol in flattened
if needle in symbol["qualifiedName"].lower() if needle in symbol["qualifiedName"].lower()
] ]
if name_regex:
flattened = [
symbol for symbol in flattened
if name_regex.search(symbol["qualifiedName"])
]
result_count = len(flattened) result_count = len(flattened)
result, truncated = _limit_results(flattened, args.max_results) result, truncated = _limit_results(flattened, args.max_results)
elif command == "hover": elif command == "hover":
@@ -430,6 +444,13 @@ def main(argv: list[str]) -> int:
parser.add_argument("--clangd", default="clangd", help="clangd executable path.") parser.add_argument("--clangd", default="clangd", help="clangd executable path.")
parser.add_argument("--timeout", type=float, default=20.0, help="Request timeout in seconds.") parser.add_argument("--timeout", type=float, default=20.0, help="Request timeout in seconds.")
parser.add_argument("--name", help="Case-insensitive symbol-name filter for symbols command.") parser.add_argument("--name", help="Case-insensitive symbol-name filter for symbols command.")
parser.add_argument("--name-regex", help="Regex filter for symbols command, matched against qualifiedName.")
parser.add_argument(
"--ignore-case",
action=argparse.BooleanOptionalAction,
default=True,
help="Use case-insensitive --name-regex matching. Enabled by default.",
)
parser.add_argument("--max-results", type=int, default=100, help="Maximum locations/symbols to print; <=0 disables.") parser.add_argument("--max-results", type=int, default=100, help="Maximum locations/symbols to print; <=0 disables.")
parser.add_argument( parser.add_argument(
"--background-index", "--background-index",