Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

autofix removes extra line sometimes on pointless discard #2076

Closed
travisstaloch opened this issue Nov 5, 2024 · 6 comments
Closed

autofix removes extra line sometimes on pointless discard #2076

travisstaloch opened this issue Nov 5, 2024 · 6 comments
Labels
bug Something isn't working

Comments

@travisstaloch
Copy link
Contributor

Zig Version

0.14.0-dev.2126+e27b4647d

ZLS Version

0.14.0-dev.190+2451194

Client / Code Editor / Extensions

sublime text stable build 4180

Steps to Reproduce and Observed Behavior

here is the sequence of actions

fn debug(comptime fmt: []const u8, args: anytype) void {
    // std.debug.print(fmt ++ "\n", args);
}

ok - save file becomes

fn debug(comptime fmt: []const u8, args: anytype) void {
    _ = args; // autofix
    _ = fmt; // autofix
    // std.debug.print(fmt ++ "\n", args);
}

ok - uncomment

fn debug(comptime fmt: []const u8, args: anytype) void {
    _ = args; // autofix
    _ = fmt; // autofix
    std.debug.print(fmt ++ "\n", args);
}

oops - save becomes

fn debug(comptime fmt: []const u8, args: anytype) void {
    _ = args; // autofix
    _ = fmt; // autofix ++ "\n", args);
}

here the final line has been removed incorrectly. the removed length seems to be equal to the length of the last line

~/.config/zls.json

{
    "enable_snippets": true,
    "enable_autofix": true,
    "enable_inlay_hints": false,
    "inlay_hints_show_parameter_name": false,
    "semantic_tokens": "full",
    "enable_build_on_save": true,
    "build_on_save_step": "check"
}

i notice that adding a newline after the last autofixed line produces a good result

fn debug(comptime fmt: []const u8, args: anytype) void {
    _ = args; // autofix
    _ = fmt; // autofix
    
    std.debug.print(fmt ++ "\n", args);
}

save

fn debug(comptime fmt: []const u8, args: anytype) void {
    std.debug.print(fmt ++ "\n", args);
}

Expected Behavior

the pointless discards should be remove and result in

fn debug(comptime fmt: []const u8, args: anytype) void {
    std.debug.print(fmt ++ "\n", args);
}

Relevant log output

No response

@travisstaloch travisstaloch added the bug Something isn't working label Nov 5, 2024
@travisstaloch
Copy link
Contributor Author

This doesn't seem to reproduce with vscode or with adding this test to tests/lsp_features/code_actions.zig

test "remove discard with trailing text" {
    try testAutofix(
        \\fn debug(comptime fmt: []const u8, args: anytype) void {
        \\    _ = args; // autofix
        \\    _ = fmt; // autofix
        \\    @import("std").debug.print(fmt ++ "\n", args);
        \\}
        \\
    ,
        \\fn debug(comptime fmt: []const u8, args: anytype) void {
        \\    @import("std").debug.print(fmt ++ "\n", args);
        \\}
        \\
    );
}

That makes me think this might be a sublime text bug.

@Techatrix
Copy link
Member

Techatrix commented Nov 5, 2024

I can confirm that this is a bug with Sublime Text LSP.

We start with the following source file:

const std = @import("std");

fn debug(comptime fmt: []const u8, args: anytype) void {
    _ = args; // autofix
    _ = fmt; // autofix
    std.debug.print(fmt ++ "\n", args);
}

Sublime Text applies the first code action:

{
    "range": {
        "start": {
            "line": 2,
            "character": 56
        },
        "end": {
            "line": 3,
            "character": 24
        }
    },
    "newText": ""
}

This result in the following file:

const std = @import("std");

fn debug(comptime fmt: []const u8, args: anytype) void {
    _ = fmt; // autofix
    std.debug.print(fmt ++ "\n", args);
}

It then applies the second code action:

{
    "range": {
        "start": {
            "line": 3,
            "character": 24
        },
        "end": {
            "line": 4,
            "character": 23
        }
    },
    "newText": ""
}

Note that the "character" value of "start" is being "clamped" to the end of line.

This result in the corrupted source file:

const std = @import("std");

fn debug(comptime fmt: []const u8, args: anytype) void {
    _ = fmt; // autofix ++ "\n", args);
}

Sublime Text LSP needs to apply the code actions simultaniously. This behaviour can be easily noticed when using Ctrl+Z to undo the edit. The two code actions get undone individually.

Removing source.fixAll from lsp_code_actions_on_save to instead rely on enable_autofix can workaround the issue. I believe that this issue wasn't previously present until #2051 indirectly fixed lsp_code_actions_on_save.

@travisstaloch
Copy link
Contributor Author

travisstaloch commented Nov 5, 2024

Thanks for the detailed feedback 👍. I think I you're saying that fixing the first code action results in a second one with invalid ranges? I can also see the actions getting undone individually w/ ctrl+z.

I think you're right. I haven't noticed this issue until i pulled and rebuilt yesterday.

@Techatrix
Copy link
Member

I think I you're saying that fixing the first code action results in a second one with invalid ranges?

Yes. the code actions are meant to be applied to the "initial" document. Applying one of them modifies the document and invalidates the other code action's "range".

@travisstaloch
Copy link
Contributor Author

And thanks for the sublime lsp link 🙏. I just noticed that its a specific issue.

@travisstaloch
Copy link
Contributor Author

Closing since this appears to be a sublime lsp bug.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants