diff --git a/src/analyser/completions.zig b/src/analyser/completions.zig new file mode 100644 index 0000000..8bee981 --- /dev/null +++ b/src/analyser/completions.zig @@ -0,0 +1,145 @@ +const std = @import("std"); +const InternPool = @import("InternPool.zig"); +const types = @import("lsp.zig"); + +const Ast = std.zig.Ast; + +pub fn dotCompletions( + arena: std.mem.Allocator, + ip: *InternPool, + ty: InternPool.Index, + /// used for extracting doc comments + node: ?Ast.Node.Index, +) error{OutOfMemory}![]types.CompletionItem { + return try dotCompletionsInternal(arena, ip, ty, node); +} + +pub fn dotCompletionsInternal( + arena: std.mem.Allocator, + ip: *InternPool, + ty: InternPool.Index, + node: ?Ast.Node.Index, + follow_one_pointer: bool, +) error{OutOfMemory}![]types.CompletionItem { + _ = node; + + var completions = std.ArrayListUnmanaged(types.CompletionItem){}; + switch (ip.indexToKey(ty)) { + .simple => {}, + + .int_type => {}, + .pointer_type => |pointer_info| { + switch (pointer_info.size) { + .One => { + try completions.append(arena, .{ + .label = "*", + .kind = .Operator, + .detail = std.fmt.allocPrint(arena, "{}", .{pointer_info.elem_type.fmtType(ip)}), + }); + if (follow_one_pointer) { + try dotCompletionsInternal(arena, ip, pointer_info.elem_type, false); + } + }, + .Slice => { + var many_ptr_info = InternPool.Key{ .pointer_type = pointer_info }; + many_ptr_info.pointer_info.size = .Many; + + try completions.append(arena, .{ + .label = "ptr", + .kind = .Field, + .detail = std.fmt.allocPrint(arena, "{}", .{many_ptr_info.fmtType(ip)}), + }); + try completions.append(arena, .{ + .label = "len", + .kind = .Field, + .detail = "usize", + }); + }, + .Many, + .C, + => {}, + } + }, + .array_type => |array_info| { + try completions.append(arena, types.CompletionItem{ + .label = "len", + .labelDetails = std.fmt.allocPrint(arena, "{d}", .{array_info.len}), + .kind = .Field, + .detail = "usize", + }); + }, + .struct_type => |struct_info| { + for (struct_info.fields) |field| { + try completions.append(arena, types.CompletionItem{ + .label = field.name, + .kind = .Field, + // TODO include alignment and comptime + .detail = std.fmt.allocPrint(arena, "{}", .{field.ty.fmtType(ip)}), + }); + } + // TODO namespace + }, + .optional_type => |optional_info| { + try completions.append(arena, .{ + .label = "?", + .kind = .Operator, + .detail = std.fmt.allocPrint(arena, "{}", .{optional_info.payload_type.fmtType(ip)}), + }); + }, + .error_union_type => {}, + .error_set_type => |error_set_info| { + for (error_set_info.names) |name| { + try completions.append(arena, .{ + .label = name, + .kind = .Constant, + .detail = std.fmt.allocPrint(arena, "error.{s}", .{name}), + }); + } + }, + .enum_type => |enum_info| { + for (enum_info.fields) |field| { + try completions.append(arena, .{ + .label = field.name, + .kind = .Field, + .detail = std.fmt.allocPrint(arena, "{}", .{field.ty.fmtType(ip)}), + }); + } + // TODO namespace + }, + .function_type => {}, + .union_type => |union_info| { + for (union_info.fields) |field| { + try completions.append(arena, .{ + .label = field.name, + .kind = .Field, + .detail = if (field.alignment != 0) + std.fmt.allocPrint(arena, "align({d}) {}", .{ field.alignment, field.ty.fmtType(ip) }) + else + std.fmt.allocPrint(arena, "{}", .{field.ty.fmtType(ip)}), + }); + } + // TODO namespace + }, + .tuple_type => { + // TODO + }, + .vector_type => {}, + .anyframe_type => {}, + + .int_u64_value, + .int_i64_value, + .int_big_value, + .float_16_value, + .float_32_value, + .float_64_value, + .float_80_value, + .float_128_value, + => {}, + + .bytes, + .aggregate, + .union_value, + => {}, + } + return try completions.toOwnedSlice(arena); +}