C/C++ Blitz
Source Insight–inspired C/C++ code navigation for VS Code, built for embedded
codebases where the Microsoft C/C++ extension's IntelliSense struggles (heavy
macros, non-standard ARM-family compilers). It works on Remote-SSH out of the box
with no platform-specific setup.
It indexes with tree-sitter's structural
parse — getting as close to a compiler's understanding as possible without a
compiler or preprocessor — and falls back to a name-based (grep) index only when
heavy macros or non-standard syntax defeat the parse. Navigation keeps working
even when code doesn't compile in a standard toolchain.
Tip: For the best experience, disable the Microsoft C/C++ extension's
IntelliSense. Otherwise VS Code merges its results with ours, which slows
down navigation and clutters the results.
Features
F12 — Go to Definition
Jump to symbol definitions using our tree-sitter / grep index.
The built-in F12 / Ctrl+Click / Peek / right-click "Go to Definition" all
resolve through our index — so disable the MS C/C++ extension's IntelliSense,
or VS Code will merge its results with ours. A dedicated C/C++ Blitz: Go to
Definition command is also available in the Command Palette and always returns
only our results. If a name has multiple definitions, you get a picker (or a
native peek).
F10 — Search Symbols
Fuzzy search over every symbol in the index, including goto labels.
Covers functions, prototypes, variables, macros, typedefs, struct/union/enum,
enum constants, labels, and basic C++ class/namespace/method. Search runs on a
dedicated worker off the UI thread, so typing never stutters on large indexes.
External Macros
Automatically synthesize symbols for compile-time-injected macros (-D flags, compiler built-ins, out-of-tree config).
Identifiers tested in #if / #ifdef but #defined nowhere in the indexed
tree are synthesized as first-class external macro symbols anchored at their
first use. They become searchable in F10 and resolve in the Code Insight
Symbol summary (which shows their Origin and jumps to the first use)
instead of showing "not found". You can annotate their Origin with the values
your build injects via cBlitz.externalMacros.predefined / .file.
Code Insight View
Activity-bar panel that follows the cursor and shows context for the symbol under it.
Displays Symbol / Definition / Declaration / Called by / Calls / References.
The Symbol summary expands into the symbol's kind, its declared Type (which
jumps to the underlying struct, and expands when the type is ambiguous), the
function signature, and the storage class. Click any entry to jump. References are
grouped per file with a code-line snippet (like Find All References); empty
categories are hidden by default (cBlitz.codeInsight.hideEmptyCategories), and
each category can be toggled via cBlitz.codeInsight.show.*.
While a lookup is slow (over 0.2s), the view title ticks the elapsed seconds
(Code Insight — 2.3) and then holds the final duration.
Status Bar
A persistent status-bar indicator shows the current index state at a glance.
- Idle:
C/C++ Blitz: N symbols — click to open the command menu
(Rescan, Rebuild, Search Symbols, Show Log).
- Indexing:
C/C++ Blitz: parsing 120/3400 · 12 s — live progress with
file count and elapsed time. Click to stop or run other commands.
- No index: shown when the workspace has not been indexed yet.
How it works
- A pool of background worker threads (default 8,
cBlitz.indexing.workerCount)
parses files with tree-sitter in parallel and writes to an on-disk SQLite
database via Node's built-in node:sqlite (WAL mode — no native module to
build or rebuild). The extension host only reads. The initial-index notification
shows live progress — done/total files and elapsed time. References for a
~300 MB codebase can reach tens of millions of rows — far too much for memory —
so everything lives in SQLite and is fetched with indexed point queries.
There is no parallel in-memory copy: even F10 search queries SQLite directly
(on its own worker), ranking a bounded candidate set per keystroke.
- Comments are never indexed.
#if 0 … #endif blocks are indexed (a
known, intentional limitation — there is no preprocessor).
- Fallback: if tree-sitter fails or produces low-confidence results (parse
error, unsupported file, timeout, very large file, or too many ERROR nodes),
the file is indexed with a regex (grep) scanner instead — symbols are still
found (refs/calls on a best-effort basis). Such rows are tagged
source = 'grep'.
- External macros are synthesized (
cBlitz.externalMacros.enabled, default
on): a table-wide pass inserts one definition-less symbol per #if/#ifdef
name that has no definition of any kind in the tree, anchored at its first use.
This is maintained incrementally — an external macro appears or disappears live
as edits add or remove its uses — and also covers grep-parsed heavy-macro files.
- The index is the cache: on restart, only changed or new files are re-parsed
(mtime diff) and deleted files are dropped.
- Incremental indexing is visible. Files added, changed, or removed in the
workspace reindex in the background behind a single coalesced notification
(count + elapsed). Navigation queries (F12 / F10 / Code Insight) briefly wait
for an in-flight reindex to settle (bounded by
cBlitz.indexing.deferQueriesMs)
so they reflect the latest edits.
Settings
| Setting |
Default |
Notes |
cBlitz.fileExtensions |
.c .h .cpp .cc .cxx .hpp .hh .hxx .inc |
File extensions to index |
cBlitz.exclude |
node_modules/.git/build/out/dist |
Glob patterns to exclude |
cBlitz.codeInsight.debounceMs |
200 |
Cursor-follow delay |
cBlitz.codeInsight.hideEmptyCategories |
true |
Hide categories with no entries for the current symbol |
cBlitz.codeInsight.show.* |
true |
Per-category visibility (symbol/definition/declaration/calledBy/calls/references) |
cBlitz.fuzzy.maxResults |
200 |
F10 result cap |
cBlitz.parse.maxFileSizeKB |
2048 |
Larger files fall back to grep |
cBlitz.parse.errorRatioThreshold |
0.25 |
ERROR-byte ratio threshold for grep fallback |
cBlitz.parse.timeoutMs |
5000 |
Per-file parse timeout before grep fallback |
cBlitz.indexing.workerCount |
8 |
Parallel worker threads for bulk indexing |
cBlitz.indexing.deferQueriesMs |
1500 |
How long F12/F10/Code Insight wait for an in-flight reindex before querying (0 = off) |
cBlitz.externalMacros.enabled |
true |
Synthesize external macro symbols for #if/#ifdef names not #defined in-tree. Toggling forces a rescan. |
cBlitz.externalMacros.predefined |
[] |
Names your build injects ("NAME" or "NAME=value", -D style) — annotates an external macro's Origin only; does not create symbols. |
cBlitz.externalMacros.file |
"" |
Path to a JSON file mapping injected macro names to values — annotates Origin; re-read live (no re-index needed). |
cBlitz.db.location |
workspace storage |
Database directory; an absolute path is allowed (e.g. a fast or large disk). On Remote-SSH this resolves on the remote host. |
Requirements
- VS Code 1.99+ (Electron 35+ / Node 22.13+ for
node:sqlite).
Limitations
- No compiler, preprocessor, macro expansion, or real type system — no overload
resolution, and symbol resolution is best-effort. Parameters and locals resolve
within their function, and member access (
a->x) is type-narrowed by walking
the declared-type chain, but when a type cannot be resolved it falls back to
every struct field named x. C++ symbols are matched by name only.
.h headers are parsed as C by default (C++-only headers will fall back to
grep).
- Unsaved-buffer edits re-index on a short debounce; saving always triggers
re-indexing.