zigtools / zls

A Zig language server supporting Zig developers with features like autocomplete and goto definition
MIT License
2.87k stars 290 forks source link

Code Actions & Autofix #689

Open Techatrix opened 2 years ago

Techatrix commented 2 years ago

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 {}

Unused Variable/Constant

fn foo() void {
    var variable = 0;
    const constant = 0;
}

Capture

for("") |unused_capture, unused_index_capture| {}
switch(tagged_union) {
    .tag1 => |capture| expression,
    .tag2 => |capture| {},
}

Unreachable code

fn foo() u32 {
    return 0;
    return 1;
}
fn foo() u32 {
    return 0;
}

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");

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
```zig
const file = @import("./file.zig");

Functions should be camelCase

fn foo_bar_baz() void {}

Type functions should be PascalCase

fn foo_bar_baz(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;
}
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;
}
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 {}
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),
};

Explicitly specify error union

fn foo() !void {
    // some code that returns various errors
}

Specify missing switch cases

fn f(my_enum: enum { foo, bar, baz }) void {
    switch (my_enum) {
        .foo => {},
    }
}

Expand else switch cases

fn f(e: enum { foo, bar, baz }) void {
    switch (e) {
        .foo => {},
        else => {},
    }
}

Fix all bugs

const std = @import("std");
pub fn main() !void {
    // code bug ridden code
}
matklad commented 1 year ago
ivanstepanovftw commented 3 months ago

Add support for const-var autofix.

    var a = 1;
    _ = a;
src/main.zig:18:9: error: local variable is never mutated
    var a = 1;
        ^
src/main.zig:18:9: note: consider using 'const'
    const a = 1;
    a = 10;
src/main.zig:19:5: error: cannot assign to constant
    a = 10;
    ^

Mentioned that this feature already implemented in https://www.reddit.com/r/Zig/comments/1debk2j/, but turns out that "no".

Techatrix commented 3 months ago

Add support for const-var autofix.

This code action has been implemented in #1607 but removed as an "autofix" in #1652 because it is not reversible. There is no error in zig ast-check for "constant variable is mutated; consider using 'var'". If Zig were to emit this kind of error, then it can be reintroduced as an autofix.

ivanstepanovftw commented 3 months ago

May Zig in near future start emitting this error?