Skip to content

Test-driven completion #2544

@npc1054657282

Description

@npc1054657282

Motivation Currently, writing generic functions with type and anytype parameters is a blind experience. ZLS cannot provide completions within the function body because the type of the parameter is unknown until instantiation.

While ziglang/zig#615 aims to solve this perfectly by serving semantic info from the compiler, it is a long-term goal. Test-Driven Completion might be a pragmatic, cost-effective solution available today.

The general idea is as follows:

Step 1:
The user defines the generic function signature and immediately writes a usage example in its test block with the mock type defined in it.

fn TestDrivenCompletionExample(comptime E: type) type {
    _ = E;
    return struct {};
}
test TestDrivenCompletionExample {
    const MockE = enum(u8) {
        _,
        fn doSomething(self: @This()) u8 {
            return @intFromEnum(self);
        }
    };
    _ = TestDrivenCompletionExample(MockE);
}

ZLS can scan the test block of the generic function to collect its calling point. ZLS can then use the types passed in these tests as hints to instantiate the generic parameters virtually, enabling autocomplete.

Step 2:
User implements the function body. ZLS resolves E as MockE and provides accurate completion.

fn TestDrivenCompletionExample(comptime E: type) type {
    return struct {
        fn doSomething(e: E) @typeInfo(E).@"enum".tag_type {
            return e. // <--- Completion triggers here: suggests `doSomething`
        }
    };
}
test TestDrivenCompletionExample {
    const MockE = enum(u8) {
        _,
        fn doSomething(self: @This()) u8 {
            return @intFromEnum(self);
        }
    };
    const tdce = TestDrivenCompletionExample(MockE);
    const e: MockE = @enumFromInt(1);
    try std.testing.expect(tdce.doSomething(e) == 1);
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions