Skip to content

Code Actions & Autofix #689

Open
Open
@Techatrix

Description

@Techatrix

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 => {},
}
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");
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 {}
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 {};
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requesthelp wantedExtra attention is neededuxUser experience improvement

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions