Skip to content

Close no-LSP reference-completeness gaps (TS/C++/C/PHP/Vue) + typed node columns - #160

Merged
zzet merged 9 commits into
mainfrom
feat/reference-completeness-parity
Jun 23, 2026
Merged

Close no-LSP reference-completeness gaps (TS/C++/C/PHP/Vue) + typed node columns#160
zzet merged 9 commits into
mainfrom
feat/reference-completeness-parity

Conversation

@zzet

@zzet zzet commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Closes a set of reference / resolution-completeness gaps in the no-LSP (index-time tree-sitter only) extraction across TypeScript, C++, C, PHP, and Vue/Nuxt, measured via find_usages total_edges/total_nodes. The TS JSX+heritage and Swift class-twin work already landed on main; this branch was rebased onto main (the merge reconciled the divergent Swift fix to main's version) and adds the remaining coverage, plus a P3 storage-schema change.

Empirical results (isolated index, all unresolved::<T> = 0)

probe (repo) before after target
ExcalidrawElement (excalidraw) 567 624 492
AppState (excalidraw) 349 389 365
App (excalidraw) 17 51 31

All probes now meet or beat their no-LSP coverage target.

Reference-completeness

  • TypeScript type-use coverage — generic constraints (<T extends X>), structural type-alias bodies (object/function types via AST walk), interface-member typeof/method-param/per-member counting, default type-only imports. Lifts AppState/App over target; ExcalidrawElement improves with no regression.
  • Value-ref shadow census — an inner-scope local (let X) shadowing a file-scope const X no longer binds a false value-ref edge.
  • C++ smart-pointer pointee unwrapunique_ptr<Widget>Widget in return-type inference, so make_widget()->draw() chains to the pointee.
  • C/C++ include-root search — a non-relative #include "foo/bar.h" resolves to the uniquely-matching indexed header (ambiguous/bare matches refused).
  • Laravel facade → backing classCache::get() binds to the backing service's method via a config-extensible facade table.
  • Vue/Nuxt templates — strip the Nuxt Lazy auto-import prefix + skip framework builtins; bind composable-destructured handlers (const { close: c } = useModal() + @click="c").

Storage schema

  • Per-file files sidecar — a per-file metadata table (BLAKE3 content hash from the Merkle leaf, byte size, node count, JSON parse-error locations) written by the indexer; index_health now reports per-file parse errors + node counts. The Merkle tree stays the authoritative change detector.
  • Typed/indexable node columns — promote is_async/is_static/is_abstract/is_exported/return_type/updated_at from the meta blob to typed SQLite columns (stripped on write, restored on read, like signature/visibility/doc/external), and add start_column/end_column as first-class Node fields with their own columns. A SQL filter on is_async now resolves without decoding the blob. Older DBs are ALTERed in place; the wire-contract fingerprint is bumped for the additive Node fields.

Each item has unit tests; the parser/resolver/graph/store_sqlite packages are -race green and the cmd/gortex wire-contract golden is updated. Includes a security bump of golang.org/x/image to v0.43.0 (CVE-2026-46601/46602) to clear the dependency scan.

zzet added 8 commits June 22, 2026 23:50
…e type name

A class/struct/enum/actor whose stored property name is the case-twin of the
type name (e.g. Session class with a 'session' property) was indexed without a
container node, so all references to it stayed unresolved. Recover the missing
container node so find_usages/get_symbol resolve the type.
* main:
  Credit the enricher on AST-baseline heritage edges (stamp semantic_source)
  Recover Swift type containers from parse errors via brace-matched fallback
  Capture TypeScript JSX, type-only import/export, and heritage references

# Conflicts:
#	internal/parser/languages/swift.go
Extend the no-LSP TypeScript reference extraction so types named only in
positions the annotation/heritage/cast passes miss still land cross-file:

- generic-parameter constraints (<T extends Foo>) on classes, interfaces,
  functions, and type aliases
- structural type-alias bodies — object-type literals and function types
  walked as an AST subtree so a type used deep inside { … } or (x: T) => U
  is reachable (the text decomposer collapsed those to one token)
- interface members: typeof queries (InstanceType<typeof App>), method
  parameter types, and per-member counting so each member naming a type is
  a distinct usage site
- default type-only imports (import type App from "mod")

On excalidraw this lifts AppState 349->389 and App 17->51 find_usages
total_edges (both over the codegraph baseline) with ExcalidrawElement
567->624 and unresolved type targets at zero.
The value-reference resolver's shadow census only counted same-file
parameters and fields. An inner-scope local declarator (`let X` / `X :=`)
materialised as a KindLocal node also shadows a file-scope constant of the
same name, so a candidate read inside that scope could be mis-bound to the
constant it does not actually read. Extend the per-file declarator census to
include KindLocal so such reads are left unbound.
A factory returning unique_ptr<Widget> / shared_ptr<Widget> / weak_ptr<Widget>
/ optional<Widget> recorded the wrapper as its return type, so a chained call
(make_widget()->draw()) could not infer Widget as the receiver and draw stayed
unresolved. Add UnwrapCppSmartPointer (peels nested wrappers, drops a deleter
arg, keeps a pointee namespace) and apply it in NormalizeCppType and
cppReturnType before stripping template args. Free functions now also record a
return type, so a bare factory call gets the same chained-receiver inference
methods already had.
A quoted include only resolved relative to the including file's directory, so
a header reachable through an include directory (`#include "foo/bar.h"` with
the file at include/foo/bar.h) stayed an external stub. Index file nodes by
basename and, for a multi-segment include with no directory-relative match,
bind it to the uniquely-matching indexed header whose path ends with that
suffix. Ambiguous matches and bare single-segment headers are refused so no
false edge is created.
A facade static call (Cache::get()) emitted a name-only call placeholder, so it
resolved to an arbitrary same-named method instead of the service the facade
proxies. Add a facade -> backing-class table (config-extensible via
RegisterPHPFacade) and stamp the backing class as the call's receiver_type, so
the resolver's existing receiver-type cascade binds the call to that class's
method. Non-facade static calls are left unstamped.
Two Vue/Nuxt template gaps left edges missing or misnamed:
- A Nuxt lazy-hydrated usage (<LazyBaseButton>) referenced LazyBaseButton
  rather than the BaseButton component it wraps, and Nuxt framework components
  (<NuxtLink>, <NuxtPage>, …) became bogus cross-file references. Strip the
  Lazy auto-import prefix and skip the framework builtins.
- A template handler bound to a composable-destructured local
  (const { close: c } = useModal() + @click="c") landed on the renamed local
  instead of the composable member. Map destructured locals back to their
  original member and bind the handler to it (via=composable_handler).
Existing kebab/PascalCase component and @click function-handler coverage is
unchanged.
@zzet zzet changed the title Close codegraph reference-completeness parity gaps (TS/C++/C/PHP/Vue) TS/C++/C/PHP/Vue improvements Jun 23, 2026
The dependency vulnerability scan (trivy-fs) flags golang.org/x/image v0.42.0
for CVE-2026-46601 and CVE-2026-46602 (fixed in v0.43.0). govulncheck stays
green because the affected symbols are not reachable, but the presence-based
scan fails. Bump to the fixed release.
@zzet
zzet merged commit a22b7e3 into main Jun 23, 2026
9 checks passed
@zzet zzet changed the title TS/C++/C/PHP/Vue improvements Close no-LSP reference-completeness gaps (TS/C++/C/PHP/Vue) + typed node columns Jun 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant