lsp: go-to-definition on a field through a *Struct variable

resolveStructTypeName returned null unless the variable's type was exactly a struct, so 'board.castling' (board: *Board) couldn't locate the Board declaration. It now also returns the pointee struct name for a pointer-to-struct, read from the resolved symbol type. Verified: board.castling navigates to board.sx's castling field.
This commit is contained in:
agra
2026-05-31 11:39:52 +03:00
parent ef0d9a9477
commit 0cb4a5a342

View File

@@ -2163,6 +2163,7 @@ pub const Server = struct {
}
fn resolveStructTypeName(sema: SemaResult, doc: *const Document, var_name: []const u8) ?[]const u8 {
_ = doc;
var i = sema.symbols.len;
while (i > 0) {
i -= 1;
@@ -2170,27 +2171,10 @@ pub const Server = struct {
if (!std.mem.eql(u8, sym.name, var_name)) continue;
const ty = sym.ty orelse return null;
if (ty != .struct_type) return null;
if (sym.kind == .param) {
if (sym.def_span.start < doc.source.len and sym.def_span.end <= doc.source.len) {
return doc.source[sym.def_span.start..sym.def_span.end];
}
}
if (sym.kind == .variable) {
const root = doc.root orelse return null;
if (sym.def_span.start < doc.source.len) {
if (sx.sema.findNodeAtOffset(root, sym.def_span.start)) |node| {
if (node.data == .var_decl) {
if (node.data.var_decl.type_annotation) |ta| {
if (ta.data == .type_expr) return ta.data.type_expr.name;
}
}
}
}
}
// A struct value, or a pointer to one (`*Board`) — return the struct
// name so the caller can locate the type's declaration.
if (ty == .struct_type) return ty.struct_type;
if (ty.isPointer()) return ty.pointer_type.pointee_name;
return null;
}
return null;