more forward declarations
This commit is contained in:
@@ -1084,7 +1084,7 @@ pub const Server = struct {
|
||||
};
|
||||
|
||||
var hints = std.ArrayList(lsp.InlayHint).empty;
|
||||
collectInlayHints(self.allocator, root, sema.symbols, doc.source, &hints);
|
||||
collectInlayHints(self.allocator, root, sema.symbols, sema.fn_signatures, doc.source, &hints);
|
||||
self.collectCallHints(doc, root, &hints);
|
||||
const result_json = try lsp.inlayHintsJson(self.allocator, hints.items);
|
||||
try self.sendResponse(id_json, result_json);
|
||||
@@ -1094,37 +1094,46 @@ pub const Server = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
node: *const sx.ast.Node,
|
||||
symbols: []const sx.sema.Symbol,
|
||||
fn_signatures: std.StringHashMap(sx.sema.FnSignature),
|
||||
source: [:0]const u8,
|
||||
hints: *std.ArrayList(lsp.InlayHint),
|
||||
) void {
|
||||
switch (node.data) {
|
||||
.root => |r| {
|
||||
for (r.decls) |decl| collectInlayHints(allocator, decl, symbols, source, hints);
|
||||
for (r.decls) |decl| collectInlayHints(allocator, decl, symbols, fn_signatures, source, hints);
|
||||
},
|
||||
.block => |b| {
|
||||
for (b.stmts) |stmt| collectInlayHints(allocator, stmt, symbols, source, hints);
|
||||
for (b.stmts) |stmt| collectInlayHints(allocator, stmt, symbols, fn_signatures, source, hints);
|
||||
},
|
||||
.fn_decl => |fd| {
|
||||
collectInlayHints(allocator, fd.body, symbols, source, hints);
|
||||
collectInlayHints(allocator, fd.body, symbols, fn_signatures, source, hints);
|
||||
// Return type hint for arrow functions without explicit return type
|
||||
if (fd.return_type == null and fd.is_arrow) {
|
||||
if (fn_signatures.get(fd.name)) |sig| {
|
||||
if (sig.return_type != .void_type) {
|
||||
addReturnTypeHint(allocator, node.span, source, sig.return_type, hints);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
.lambda => |lm| {
|
||||
collectInlayHints(allocator, lm.body, symbols, source, hints);
|
||||
collectInlayHints(allocator, lm.body, symbols, fn_signatures, source, hints);
|
||||
},
|
||||
.if_expr => |ie| {
|
||||
if (ie.binding_name) |bname| {
|
||||
addBindingHint(allocator, bname, node.span, symbols, source, hints);
|
||||
}
|
||||
collectInlayHints(allocator, ie.then_branch, symbols, source, hints);
|
||||
if (ie.else_branch) |eb| collectInlayHints(allocator, eb, symbols, source, hints);
|
||||
collectInlayHints(allocator, ie.then_branch, symbols, fn_signatures, source, hints);
|
||||
if (ie.else_branch) |eb| collectInlayHints(allocator, eb, symbols, fn_signatures, source, hints);
|
||||
},
|
||||
.while_expr => |we| {
|
||||
if (we.binding_name) |bname| {
|
||||
addBindingHint(allocator, bname, node.span, symbols, source, hints);
|
||||
}
|
||||
collectInlayHints(allocator, we.body, symbols, source, hints);
|
||||
collectInlayHints(allocator, we.body, symbols, fn_signatures, source, hints);
|
||||
},
|
||||
.for_expr => |fe| {
|
||||
collectInlayHints(allocator, fe.body, symbols, source, hints);
|
||||
collectInlayHints(allocator, fe.body, symbols, fn_signatures, source, hints);
|
||||
},
|
||||
.var_decl => |vd| {
|
||||
// Only show hint when type is inferred (:= syntax)
|
||||
@@ -1135,9 +1144,22 @@ pub const Server = struct {
|
||||
.const_decl => |cd| {
|
||||
// Skip if explicit type annotation
|
||||
if (cd.type_annotation != null) return;
|
||||
// Handle lambda with return type hint
|
||||
if (cd.value.data == .lambda) {
|
||||
const lam = cd.value.data.lambda;
|
||||
collectInlayHints(allocator, lam.body, symbols, fn_signatures, source, hints);
|
||||
if (lam.return_type == null) {
|
||||
if (fn_signatures.get(cd.name)) |sig| {
|
||||
if (sig.return_type != .void_type) {
|
||||
addReturnTypeHint(allocator, cd.value.span, source, sig.return_type, hints);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
// Skip functions, types, structs, enums, unions, comptime, foreign, library
|
||||
switch (cd.value.data) {
|
||||
.lambda, .fn_decl, .type_expr, .struct_decl, .enum_decl, .union_decl,
|
||||
.fn_decl, .type_expr, .struct_decl, .enum_decl, .union_decl,
|
||||
.comptime_expr, .foreign_expr, .library_decl,
|
||||
=> return,
|
||||
else => {},
|
||||
@@ -1241,6 +1263,47 @@ pub const Server = struct {
|
||||
}
|
||||
}
|
||||
|
||||
fn addReturnTypeHint(
|
||||
allocator: std.mem.Allocator,
|
||||
span: sx.ast.Span,
|
||||
source: [:0]const u8,
|
||||
return_type: sx.types.Type,
|
||||
hints: *std.ArrayList(lsp.InlayHint),
|
||||
) void {
|
||||
// Find '(' from span start
|
||||
var pos: u32 = span.start;
|
||||
while (pos < source.len and source[pos] != '(') : (pos += 1) {}
|
||||
if (pos >= source.len) return;
|
||||
|
||||
// Match nested parens to find closing ')'
|
||||
var depth: u32 = 0;
|
||||
while (pos < source.len) : (pos += 1) {
|
||||
if (source[pos] == '(') {
|
||||
depth += 1;
|
||||
} else if (source[pos] == ')') {
|
||||
depth -= 1;
|
||||
if (depth == 0) break;
|
||||
}
|
||||
}
|
||||
if (pos >= source.len or depth != 0) return;
|
||||
|
||||
// Place hint right after ')'
|
||||
const loc = sx.errors.SourceLoc.compute(source, pos + 1);
|
||||
if (loc.line == 0 or loc.col == 0) return;
|
||||
|
||||
const type_name = return_type.displayName(allocator) catch return;
|
||||
const label = std.fmt.allocPrint(allocator, "-> {s}", .{type_name}) catch return;
|
||||
|
||||
hints.append(allocator, .{
|
||||
.line = loc.line - 1,
|
||||
.character = loc.col - 1,
|
||||
.label = label,
|
||||
.kind = 1,
|
||||
.padding_left = true,
|
||||
.padding_right = true,
|
||||
}) catch {};
|
||||
}
|
||||
|
||||
fn findSymbolAtSpan(symbols: []const sx.sema.Symbol, span_start: u32, name: []const u8) ?sx.sema.Symbol {
|
||||
for (symbols) |sym| {
|
||||
if (sym.def_span.start == span_start and std.mem.eql(u8, sym.name, name)) {
|
||||
|
||||
Reference in New Issue
Block a user