zls/src/analyser/completions.zig

167 lines
6.2 KiB
Zig
Raw Normal View History

2023-01-20 21:24:39 +00:00
const std = @import("std");
const InternPool = @import("InternPool.zig");
2023-01-23 20:28:15 +00:00
const types = @import("../lsp.zig");
2023-01-20 21:24:39 +00:00
const Ast = std.zig.Ast;
pub fn dotCompletions(
arena: std.mem.Allocator,
2023-01-24 16:00:14 +00:00
completions: *std.ArrayListUnmanaged(types.CompletionItem),
2023-01-20 21:24:39 +00:00
ip: *InternPool,
ty: InternPool.Index,
2023-01-23 20:28:15 +00:00
val: InternPool.Index,
2023-01-24 21:07:19 +00:00
node: ?Ast.Node.Index,
2023-01-24 16:00:14 +00:00
) error{OutOfMemory}!void {
2023-01-20 21:24:39 +00:00
_ = node;
2023-01-23 20:28:15 +00:00
const key = ip.indexToKey(ty);
const inner_key = switch (key) {
.pointer_type => |info| if (info.size == .One) ip.indexToKey(info.elem_type) else key,
else => key,
};
switch (inner_key) {
2023-02-08 20:01:15 +00:00
.simple_type => |simple| switch (simple) {
2023-01-23 20:28:15 +00:00
.type => {
const ty_key = ip.indexToKey(val);
const namespace = ty_key.getNamespace(ip.*);
if (namespace != .none) {
2023-01-23 20:28:15 +00:00
// TODO lookup in namespace
}
switch (ty_key) {
.error_set_type => |error_set_info| {
for (error_set_info.names) |name| {
const error_name = ip.indexToKey(name).bytes;
try completions.append(arena, .{
.label = error_name,
.kind = .Constant,
.detail = try std.fmt.allocPrint(arena, "error.{s}", .{std.zig.fmtId(error_name)}),
2023-01-23 20:28:15 +00:00
});
}
},
.union_type => {}, // TODO
.enum_type => |enum_index| {
const enum_info = ip.getEnum(enum_index);
var field_it = enum_info.fields.iterator();
while (field_it.next()) |entry| {
2023-01-23 20:28:15 +00:00
try completions.append(arena, .{
.label = entry.key_ptr.*,
2023-01-23 20:28:15 +00:00
.kind = .Constant,
// include field.val?
});
}
},
else => {},
}
},
else => {},
2023-01-23 20:28:15 +00:00
},
2023-01-20 21:24:39 +00:00
.pointer_type => |pointer_info| {
if (pointer_info.size == .Slice) {
2023-01-23 20:28:15 +00:00
var many_ptr_info = InternPool.Key{ .pointer_type = pointer_info };
many_ptr_info.pointer_type.size = .Many;
2023-01-20 21:24:39 +00:00
2023-01-23 20:28:15 +00:00
try completions.append(arena, .{
.label = "ptr",
.kind = .Field,
.detail = try std.fmt.allocPrint(arena, "{}", .{many_ptr_info.fmtType(ip.*)}),
2023-01-23 20:28:15 +00:00
});
try completions.append(arena, .{
.label = "len",
.kind = .Field,
.detail = "usize",
});
2023-01-24 21:07:19 +00:00
} else if (ip.indexToKey(pointer_info.elem_type) == .array_type) {
2023-01-23 20:28:15 +00:00
try completions.append(arena, .{
.label = "len",
.kind = .Field,
.detail = "usize",
});
2023-01-20 21:24:39 +00:00
}
},
.array_type => |array_info| {
try completions.append(arena, types.CompletionItem{
.label = "len",
.kind = .Field,
.detail = try std.fmt.allocPrint(arena, "usize ({d})", .{array_info.len}), // TODO how should this be displayed
2023-01-20 21:24:39 +00:00
});
},
.struct_type => |struct_index| {
const struct_info = ip.getStruct(struct_index);
var field_it = struct_info.fields.iterator();
while (field_it.next()) |entry| {
2023-01-20 21:24:39 +00:00
try completions.append(arena, types.CompletionItem{
.label = entry.key_ptr.*,
2023-01-20 21:24:39 +00:00
.kind = .Field,
// TODO include alignment and comptime
.detail = try std.fmt.allocPrint(arena, "{}", .{entry.value_ptr.ty.fmtType(ip.*)}),
2023-01-20 21:24:39 +00:00
});
}
},
.optional_type => |optional_info| {
try completions.append(arena, .{
.label = "?",
.kind = .Operator,
.detail = try std.fmt.allocPrint(arena, "{}", .{optional_info.payload_type.fmtType(ip.*)}),
2023-01-20 21:24:39 +00:00
});
},
.enum_type => |enum_index| {
const enum_info = ip.getEnum(enum_index);
for (enum_info.fields.keys()) |field_name, i| {
const field_val = enum_info.values.keys()[i];
2023-01-20 21:24:39 +00:00
try completions.append(arena, .{
2023-01-23 20:28:15 +00:00
.label = field_name,
2023-01-20 21:24:39 +00:00
.kind = .Field,
.detail = try std.fmt.allocPrint(arena, "{}", .{field_val.fmtValue(enum_info.tag_type, ip.*)}),
2023-01-20 21:24:39 +00:00
});
}
},
.union_type => |union_index| {
const union_info = ip.getUnion(union_index);
var field_it = union_info.fields.iterator();
while (field_it.next()) |entry| {
2023-01-20 21:24:39 +00:00
try completions.append(arena, .{
.label = entry.key_ptr.*,
2023-01-20 21:24:39 +00:00
.kind = .Field,
.detail = if (entry.value_ptr.alignment != 0)
try std.fmt.allocPrint(arena, "align({d}) {}", .{ entry.value_ptr.alignment, entry.value_ptr.ty.fmtType(ip.*) })
2023-01-20 21:24:39 +00:00
else
try std.fmt.allocPrint(arena, "{}", .{entry.value_ptr.ty.fmtType(ip.*)}),
2023-01-20 21:24:39 +00:00
});
}
},
2023-01-23 20:28:15 +00:00
.tuple_type => |tuple_info| {
2023-01-24 21:07:19 +00:00
for (tuple_info.types) |tuple_ty, i| {
2023-01-23 20:28:15 +00:00
try completions.append(arena, .{
.label = try std.fmt.allocPrint(arena, "{d}", .{i}),
2023-01-23 20:28:15 +00:00
.kind = .Field,
.detail = try std.fmt.allocPrint(arena, "{}", .{tuple_ty.fmtType(ip.*)}),
2023-01-23 20:28:15 +00:00
});
}
2023-01-20 21:24:39 +00:00
},
2023-01-23 20:28:15 +00:00
.int_type,
.error_set_type,
2023-01-23 20:28:15 +00:00
.error_union_type,
.function_type,
.vector_type,
2023-01-24 21:07:19 +00:00
.anyframe_type,
=> {},
2023-01-20 21:24:39 +00:00
2023-02-08 20:01:15 +00:00
.simple_value,
2023-01-20 21:24:39 +00:00
.int_u64_value,
.int_i64_value,
.int_big_value,
.float_16_value,
.float_32_value,
.float_64_value,
.float_80_value,
.float_128_value,
2023-01-23 20:28:15 +00:00
=> unreachable,
2023-01-20 21:24:39 +00:00
.bytes,
.aggregate,
.union_value,
2023-01-23 20:28:15 +00:00
=> unreachable,
2023-01-20 21:24:39 +00:00
}
}