Is there a way to improve LSP for comptime types?

I’m working on a TTLV (tag-type-length-value) parser library. TTLV has a set of default tags represented as an enum. Since it supports extensions I wanted to support the following situations:

  1. Completely custom tags via a factory e.g. const MyTtlv = CustomTtlv(MyTags)
  2. Default implementation const DefaultTtlv = CustomTtlv(enums.TagType)
  3. Default implementation with extensions const MyTtlv = ttlv.extendDefault(MyExtensions, .{})

All of these are working, but the developer experience is not great for #3. MyTtlv.TagType comes up as just T: type

pub fn CustomTtlv(T: type) type {
    return struct {
        const Self = @This();

        pub const TagType = T;

Completion works fine if I use a pre-known type, but if it’s comptime, it has no idea what it is.

Definition of extendDefault

pub const ExtendOptions = struct {
    is_exhaustive: bool = false,
};

pub fn extendDefault(comptime Extensions: type, options: ExtendOptions) type {
    const default_type_info = @typeInfo(enums.TagType).@"enum";
    const default_fields = default_type_info.fields;
    const extension_fields = @typeInfo(Extensions).@"enum".fields;
    const fields = default_fields ++ extension_fields;

    const ExtendedTagType = @Type(.{
        .@"enum" = std.builtin.Type.Enum{
            .decls = &.{},
            .tag_type = default_type_info.tag_type,
            .fields = fields,
            .is_exhaustive = options.is_exhaustive,
        },
    });

    return CustomTtlv(ExtendedTagType);
}

to improve lsp resolution of comptime types the lsp would need to do either:

  • implement comptime itself (difficult and prone to implementation differences to the compiler)
  • ask the compiler (there are plans to implement a protocol for tools to interact with the compiler)
1 Like

I’ve seen such plans mentioned before. Can you link them?

3 Likes