-
-
Notifications
You must be signed in to change notification settings - Fork 405
Description
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);
}