feat(mcp): index struct fields and interface method sets #1
Reference in New Issue
Block a user
Delete Branch "feat/index-struct-fields-and-interface-methods"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
The framework indexer now captures the members of composite types — struct fields (with their tags) and interface method sets — closing a gap where
get_symbol/search_symbolscould name a type but not describe its shape.Type of change
Description
Problem.
formatNodetruncates every declaration at the first{, so the index stored only the one-line header of each type. For a struct that meant the field names, types, and struct tags were dropped — e.g. nothing in the index revealed thatdb-postgresConfig.Hostis set byenv:"EINHERJAR_PG_HOST,required". For an interface it meant the method set was dropped — you could not learn whatProviderrequires. This surfaced in practice while wiring an app: the index could be asked "doesConfighave aDSN()method?" and "what env vars configure Postgres?" and answer neither. (The separateDSN()-not-found incident was a stale deployed index, not a builder bug — the builder already indexes methods, and a redeploy fixes it. This PR fixes the structural truncation that no redeploy would have cured.)Approach. Extend the index schema with two optional,
omitemptymembers onSymbol:fields []Field— for struct types: name, type, raw struct tag (backticks stripped), doc, and anembeddedflag.methods []Method— for interface types: name, signature (without the leadingfunc), doc; embedded interfaces included.The builder fills these by inspecting each type's
TypeSpec(*ast.StructType/*ast.InterfaceType) via small helpers, using a new non-truncatingnodeStringprinter alongside the existingformatNode(which still produces the one-line header).search_symbolsnow also matches a query against field names/types/tags and interface method names/signatures, so an env-var key or a method name resolves to the declaring type.get_symbolneeded no logic change — it already returns the wholeSymbol.Alternatives considered. Storing a single untruncated "full definition" string per symbol — rejected because it would drag in function bodies and is far less queryable than structured fields/methods (no search-by-tag).
Versioning / schema. Index
SchemaVersionis intentionally unchanged (additive,omitemptyfields — older consumers parse the new index unchanged). The release version is a minor bump, v0.2.0 (new non-breaking functionality over v0.1.1);CHANGELOG.mdandRELEASE.mdare set accordingly — adjust the2026-06-10date if the release commit lands on a different day.Known limitations / follow-up. The committed
data/index.jsonplaceholder is untouched; the index is regenerated at image build (Dockerfilerunscmd/indexer), so the live service only gains the richer data after a rebuild/redeploy — please redeploy (this also clears the pre-existing stale-index issue). Generic type parameters and const values are out of scope here.Testing
go test ./...gofmt -l .produces no outputgo vet ./...is cleanNew
internal/index/builder_test.go(the package had no tests before) builds a temp module fixture and asserts: struct fields with tags and docs, embedded fields, interface methods with signatures and docs, embedded interfaces, and search-by-struct-tag. Reindexing the live framework confirmsdb-postgres.Confignow exposes all 12 fields with theirEINHERJAR_PG_*tags (andConfig.DSN), andProviderexposesGetExecutor/Begin/BeginTx/Ping/HandleError.Checklist
.gofile (CT-6) — newField/Methodtypes live inindex.gobeside the existingSymbol/Module/etc. type group; consistent with the file's established multi-type schema layoutCHANGELOG.md