C Hexa Nav
Go to Implementation for C function pointers — built for hexagonal architectures (ports & adapters) on embedded projects.
In a ports-and-adapters C codebase, calls go through structs of function pointers:
port->send(buf, len);
Ctrl+Click (Go to Definition) only takes you to the field declaration inside the struct — a dead end. C Hexa Nav statically indexes your project and resolves which concrete functions are actually bound to each port field, so Go to Implementation (Ctrl+F12) jumps straight to uart_dma_send().
Features
- Go to Implementation on port fields — put the cursor on a function-pointer field (at the call site or in the struct definition) and press
Ctrl+F12, or right-click → Go to Implementations.
- Multiple candidates supported — when several adapters bind the same field (real driver, simulator, test stub), all of them are listed in a peek view.
- Works on real-world firmware code — the parser is error-tolerant: files that don't currently compile,
extern "C" headers, and in-progress edits don't break the index.
- Always up to date — the index refreshes incrementally when you save a
.c/.h file, and rebuilds automatically when compile_commands.json is regenerated.
Supported binding patterns
A port is a typedef'd struct of function pointers:
typedef struct {
int (*send)(const uint8_t *buf, size_t len);
void (*flush)(void);
} comm_port_t;
C Hexa Nav resolves the two common ways adapters bind to it:
1. Designated initializer
static const comm_port_t uart_adapter = {
.send = uart_dma_send,
.flush = uart_flush,
};
2. Runtime assignment (typical in *_init() functions)
void uart_comm_init(comm_port_t *p_port) {
p_port->send = s_uart_send;
p_port->flush = s_uart_flush;
}
Getting started
- Make sure your project has a
compile_commands.json (with CMake: -DCMAKE_EXPORT_COMPILE_COMMANDS=ON). C Hexa Nav auto-detects it in common build directories (build/, out/, cmake-build-*/, including per-preset subfolders).
- Open the project in VS Code. The extension activates on the first C file you open and indexes the workspace in the background.
- Put the cursor on a port field — e.g.
send in port->send(...) — and press Ctrl+F12.
Commands
| Command |
Description |
C Hexa Nav: Rebuild Index |
Force a full re-index of the workspace |
Settings
| Setting |
Description |
cHexaNav.compileCommandsPath |
Path to compile_commands.json. Leave empty to auto-detect in common build directories. |
Known limitations
Resolution is purely syntactic (no preprocessing), which keeps it fast and tolerant of non-compiling code, but means:
- Adapters generated by macros are not seen.
- Indirect typedefs (aliases of port types) are not resolved.
- All
#ifdef branches are indexed, not just the active one — you may see candidates from inactive configurations.
Release notes
See the changelog.
1.0.0
Initial release: port/binding indexing (designated initializers + runtime assignments), Implementation provider, incremental re-indexing, compile_commands.json auto-detection.