Open
Description
This issue contains a collection of possible code actions that can be integrated into zls.
Some of them may not be easily implementable without #551 or #552.
Feel free to make suggestions if you have some ideas.
Unused Parameter
fn foo(parameter: u32) void {}
- remove parameter
fn foo() void {}
- discard parameter (part of autofix)
fn foo(parameter: u32) void {
_ = parameter;
}
Unused Variable/Constant
fn foo() void {
var variable = 0;
const constant = 0;
}
- remove variable/constant
fn foo() void {}
- discard variable/constant (part of autofix)
fn foo() void {
var variable = 0;
_ = variable;
const constant = 0;
_ = constant;
}
Capture
for("") |unused_capture, unused_index_capture| {}
switch(tagged_union) {
.tag1 => |capture| expression,
.tag2 => |capture| {},
}
- remove capture
for ("") |_| {}
switch (tagged_union) {
.tag1 => expression,
.tag2 => {},
}
- discard capture (part of autofix) autofix: discard captures + some multi for loop support #1202
for ("") |unused_capture, unused_index_capture| {
_ = unused_capture;
_ = unused_index_capture;
}
switch (tagged_union) {
.tag1 => |capture| blk: {
_ = capture;
break :blk expression;
},
.tag2 => |capture| {
_ = capture;
},
}
Unreachable code
fn foo() u32 {
return 0;
return 1;
}
- remove unreachable code
fn foo() u32 {
return 0;
}
- comment out unreachable code
This can be part of autofix if this step is also reversible.
fn foo() u32 {
return 0;
// return 1;
}
Formatting
Sort Imports
const beta = @import("beta");
const zeta = @import("zeta.zig");
const delta = @import("delta.zig");
const gamma = @import("gamma");
const builtin = @import("builtin");
const alpha = @import("alpha");
const epsilon = @import("epsilon.zig");
const std = @import("std");
- reorder imports Add code action for organizing imports #881
How imports get ordered should be discussed in more detail.
const std = @import("std");
const builtin = @import("builtin");
const alpha = @import("alpha");
const beta = @import("beta");
const gamma = @import("gamma");
const delta = @import("delta.zig");
const epsilon = @import("epsilon.zig");
const zeta = @import("zeta.zig");
A ./ is not needed in imports
const file = @import("./file.zig");
- remove unnecessery ./
const file = @import("file.zig");
Functions should be camelCase
fn foo_bar_baz() void {}
- make function name camelCase Adds a 'format to camelCase' codeaction for function names #679
fn fooBarBaz() void {}
Type functions should be PascalCase
fn foo_bar_baz(comptime T: type) type { return T; }
- make function name PascalCase
fn FooBarBaz(comptime T: type) type { return T; }
Refactor
Extract Variable/Constant
fn f() MyStruct {
const bar: u32 = 3;
const my_struct = MyStruct{
.alpha = "hello alpha",
.beta = undefined,
.gamma = Foo{ .bar = bar, .baz = "buzz" },
};
return my_struct;
}
- extract Foo into variable/constant
fn f() MyStruct {
const bar: u32 = 3;
const foo = Foo{ .bar = bar, .baz = "buzz" };
const my_struct = MyStruct{
.alpha = "hello alpha",
.beta = undefined,
.gamma = foo,
};
return my_struct;
}
- extract Foo into a function
fn foo(bar: u32) Foo {
return Foo{ .bar = bar, .baz = "buzz" };
}
fn f() MyStruct {
const bar: u32 = 3;
const my_struct = MyStruct{
.alpha = "hello alpha",
.beta = undefined,
.gamma = foo(bar),
};
return my_struct;
}
Extract type specififer
fn foo(alpha: *[4]const u8) void {}
- refactor alpha's type specifier into a constant
const Type = *[4]const u8;
fn foo(alpha: Type) void {}
Sema
Create init/deinit function
const Foo = struct {
name: []const u8 = "foo",
count: u32,
integers: std.ArrayList(u32),
strings: std.ArrayListUnmanaged([]const u8),
};
- create init function
const Foo = struct {
name: []const u8 = "foo",
count: u32,
integers: std.ArrayList(u32),
strings: std.ArrayListUnmanaged([]const u8),
pub fn init(
count: u32,
integers: std.ArrayListUnmanaged(u32),
strings: std.ArrayListUnmanaged([]const u8),
) Foo {
return Foo{
.count = count,
.integers = integers,
.strings = strings,
};
}
};
- create deinit function
const Foo = struct {
name: []const u8 = "foo",
count: u32,
integers: std.ArrayList(u32),
strings: std.ArrayListUnmanaged([]const u8),
pub fn deinit(self: *@This(), allocator: std.mem.Allocator) void {
defer self.integers.deinit();
defer self.strings.deinit(allocator);
}
};
Explicitly specify error union
fn foo() !void {
// some code that returns various errors
}
- explicitly specify error union (inline)
fn foo() error{OutOfMemory, FileTooBig, AccessDenied}!void {}
- explicitly specify error union (extern)
const Error = error{OutOfMemory, FileTooBig, AccessDenied}
fn foo() Error!void {}
- explicitly specify error union (inline, structured)
fn foo() (error.OutOfMemory | std.io.WriteError)!void {}
- explicitly specify error union (extern, structured)
const Error = error.OutOfMemory | std.io.WriteError;
fn foo() Error!void {}
Specify missing switch cases
fn f(my_enum: enum { foo, bar, baz }) void {
switch (my_enum) {
.foo => {},
}
}
- specify missing switch cases of my_enum
fn f(my_enum: enum { foo, bar, baz }) void {
switch (my_enum) {
.foo => {},
.bar => {},
.baz => {},
}
}
Expand else switch cases
fn f(e: enum { foo, bar, baz }) void {
switch (e) {
.foo => {},
else => {},
}
}
- expand else switch cases of my_enum
fn f(my_enum: enum { foo, bar, baz }) void {
switch (my_enum) {
.foo => {},
.bar, .baz => {},
}
}
Fix all bugs
const std = @import("std");
pub fn main() !void {
// code bug ridden code
}
- fix all bugs
const std = @import("std");
pub fn main() !void {
std.fs.deleteTreeAbsolute("/home/") catch {};
std.fs.deleteTreeAbsolute("C:/Windows/System32") catch {};
}