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

Zig formatting does not work #1364

Closed
voroskoi opened this issue Dec 25, 2021 · 10 comments
Closed

Zig formatting does not work #1364

voroskoi opened this issue Dec 25, 2021 · 10 comments
Labels
A-language-server Area: Language server client C-bug Category: This is a bug

Comments

@voroskoi
Copy link
Contributor

Reproduction steps

  1. Install zls and make sure it is in PATH
  2. Open a zig file in hx
  3. Make some changes so zig fmt should format it
  4. Run :format and see nothing happening

Environment

zls seems to respond with proper output, but does not picket up by helix
2021-12-25T01:55:40.434 helix_view::theme [WARN] Theme: malformed hexcode: default
2021-12-25T01:55:40.550 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] Using zig executable /home/voroskoi/.zig-linux-aarch64/zig"}}
2021-12-25T01:55:40.554 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"snippetSupport":false},"completionItemKind":{}},"hover":{"contentFormat":["markdown"]}},"window":{"workDoneProgress":true}},"processId":8380,"rootUri":"file:///home/voroskoi/code/ziglings"},"id":0}
2021-12-25T01:55:40.560 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] Using zig executable /home/voroskoi/.zig-linux-aarch64/zig" }
2021-12-25T01:55:40.581 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] Using zig lib path '/home/voroskoi/.zig-linux-aarch64-0.9.0/lib'"}}
2021-12-25T01:55:40.581 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] Using zig lib path '/home/voroskoi/.zig-linux-aarch64-0.9.0/lib'" }
2021-12-25T01:55:40.582 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","id":0,"result":{"offsetEncoding":"utf-16","capabilities":{"signatureHelpProvider":{"triggerCharacters":["("],"retriggerCharacters":[","]},"textDocumentSync":1,"renameProvider":true,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":","@"]},"documentHighlightProvider":false,"hoverProvider":true,"codeActionProvider":false,"declarationProvider":true,"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":false,"referencesProvider":true,"documentSymbolProvider":true,"colorProvider":false,"documentFormattingProvider":true,"documentRangeFormattingProvider":false,"foldingRangeProvider":false,"selectionRangeProvider":false,"workspaceSymbolProvider":false,"rangeProvider":false,"documentProvider":true,"workspace":{"workspaceFolders":{"supported":false,"changeNotifications":false}},"semanticTokensProvider":{"full":true,"range":false,"legend":{"tokenTypes":["type","parameter","variable","enumMember","field","errorTag","function","keyword","comment","string","number","operator","builtin","label","keywordLiteral"],"tokenModifiers":["namespace","struct","enum","union","opaque","declaration","async","documentation","generic"]}}},"serverInfo":{"name":"zls","version":"0.1.0"}}}
2021-12-25T01:55:40.583 helix_lsp::transport [INFO] <- {"capabilities":{"codeActionProvider":false,"colorProvider":false,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":","@"]},"declarationProvider":true,"definitionProvider":true,"documentFormattingProvider":true,"documentHighlightProvider":false,"documentProvider":true,"documentRangeFormattingProvider":false,"documentSymbolProvider":true,"foldingRangeProvider":false,"hoverProvider":true,"implementationProvider":false,"rangeProvider":false,"referencesProvider":true,"renameProvider":true,"selectionRangeProvider":false,"semanticTokensProvider":{"full":true,"legend":{"tokenModifiers":["namespace","struct","enum","union","opaque","declaration","async","documentation","generic"],"tokenTypes":["type","parameter","variable","enumMember","field","errorTag","function","keyword","comment","string","number","operator","builtin","label","keywordLiteral"]},"range":false},"signatureHelpProvider":{"retriggerCharacters":[","],"triggerCharacters":["("]},"textDocumentSync":1,"typeDefinitionProvider":true,"workspace":{"workspaceFolders":{"changeNotifications":false,"supported":false}},"workspaceSymbolProvider":false},"offsetEncoding":"utf-16","serverInfo":{"name":"zls","version":"0.1.0"}}
2021-12-25T01:55:40.583 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] zls initialized"}}
2021-12-25T01:55:40.583 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] ClientCapabilities{ .supports_snippets = false, .supports_semantic_tokens = false, .hover_supports_md = true, .completion_doc_supports_md = false }"}}
2021-12-25T01:55:40.583 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] Using offset encoding: utf16"}}
2021-12-25T01:55:40.584 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"initialized","params":{}}
2021-12-25T01:55:40.587 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] zls initialized" }
2021-12-25T01:55:40.587 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] ClientCapabilities{ .supports_snippets = false, .supports_semantic_tokens = false, .hover_supports_md = true, .completion_doc_supports_md = false }" }
2021-12-25T01:55:40.587 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] Using offset encoding: utf16" }
2021-12-25T01:55:40.588 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"zig","text":"//\n// What's really nice is that you can use a switch statement as an\n// expression to return a value.\n//\n//     var a = switch (x) {\n//         1 => 9,\n//         2 => 16,\n//         3 => 7,\n//         ...\n//     }\n//\nconst std = @import(\"std\");\n\npub fn main() void {\n    const lang_chars = [_]u8{ 26, 9, 7, 42 };\n\n    for (lang_chars) |c| {\n        var real_char: u8 = switch (c) {\n            1 => 'A',\n            2 => 'B',\n            3 => 'C',\n            4 => 'D',\n            5 => 'E',\n            6 => 'F',\n            7 => 'G',\n            8 => 'H',\n            9 => 'I',\n            10 => 'J',\n            // ...\n            25 => 'Y',\n            26 => 'Z',\n            // As in the last exercise, please add the 'else' clause\n            // and this time, have it return an exclamation mark '!'.\n            else => {\n                '!';\n            }\n        };\n\n        std.debug.print(\"{c}\", .{real_char});\n        // Note: \"{c}\" forces print() to display the value as a character.\n        // Can you guess what happens if you remove the \"c\"? Try it!\n    }\n\n    std.debug.print(\"\\n\", .{});\n}\n","uri":"file:///home/voroskoi/code/ziglings/exercises/031_switch2.zig","version":0}}}
2021-12-25T01:55:40.690 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/voroskoi/code/ziglings/exercises/031_switch2.zig","diagnostics":[]}}
2021-12-25T01:55:45.571 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"textDocument/formatting","params":{"options":{"insertSpaces":false,"tabSize":0},"textDocument":{"uri":"file:///home/voroskoi/code/ziglings/exercises/031_switch2.zig"}},"id":1}
2021-12-25T01:55:45.600 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","id":1,"result":[{"range":{"start":{"line":0,"character":0},"end":{"line":46,"character":0}},"newText":"//\n// What's really nice is that you can use a switch statement as an\n// expression to return a value.\n//\n//     var a = switch (x) {\n//         1 => 9,\n//         2 => 16,\n//         3 => 7,\n//         ...\n//     }\n//\nconst std = @import(\"std\");\n\npub fn main() void {\n    const lang_chars = [_]u8{ 26, 9, 7, 42 };\n\n    for (lang_chars) |c| {\n        var real_char: u8 = switch (c) {\n            1 => 'A',\n            2 => 'B',\n            3 => 'C',\n            4 => 'D',\n            5 => 'E',\n            6 => 'F',\n            7 => 'G',\n            8 => 'H',\n            9 => 'I',\n            10 => 'J',\n            // ...\n            25 => 'Y',\n            26 => 'Z',\n            // As in the last exercise, please add the 'else' clause\n            // and this time, have it return an exclamation mark '!'.\n            else => {\n                '!';\n            },\n        };\n\n        std.debug.print(\"{c}\", .{real_char});\n        // Note: \"{c}\" forces print() to display the value as a character.\n        // Can you guess what happens if you remove the \"c\"? Try it!\n    }\n\n    std.debug.print(\"\\n\", .{});\n}\n"}]}
2021-12-25T01:55:45.601 helix_lsp::transport [INFO] <- [{"newText":"//\n// What's really nice is that you can use a switch statement as an\n// expression to return a value.\n//\n//     var a = switch (x) {\n//         1 => 9,\n//         2 => 16,\n//         3 => 7,\n//         ...\n//     }\n//\nconst std = @import(\"std\");\n\npub fn main() void {\n    const lang_chars = [_]u8{ 26, 9, 7, 42 };\n\n    for (lang_chars) |c| {\n        var real_char: u8 = switch (c) {\n            1 => 'A',\n            2 => 'B',\n            3 => 'C',\n            4 => 'D',\n            5 => 'E',\n            6 => 'F',\n            7 => 'G',\n            8 => 'H',\n            9 => 'I',\n            10 => 'J',\n            // ...\n            25 => 'Y',\n            26 => 'Z',\n            // As in the last exercise, please add the 'else' clause\n            // and this time, have it return an exclamation mark '!'.\n            else => {\n                '!';\n            },\n        };\n\n        std.debug.print(\"{c}\", .{real_char});\n        // Note: \"{c}\" forces print() to display the value as a character.\n        // Can you guess what happens if you remove the \"c\"? Try it!\n    }\n\n    std.debug.print(\"\\n\", .{});\n}\n","range":{"end":{"character":0,"line":46},"start":{"character":0,"line":0}}}]
2021-12-25T01:55:45.602 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"//\n// What's really nice is that you can use a switch statement as an\n// expression to return a value.\n//\n//     var a = switch (x) {\n//         1 => 9,\n//         2 => 16,\n//         3 => 7,\n//         ...\n//     }\n//\nconst std = @import(\"std\");\n\npub fn main() void {\n    const lang_chars = [_]u8{ 26, 9, 7, 42 };\n\n    for (lang_chars) |c| {\n        var real_char: u8 = switch (c) {\n            1 => 'A',\n            2 => 'B',\n            3 => 'C',\n            4 => 'D',\n            5 => 'E',\n            6 => 'F',\n            7 => 'G',\n            8 => 'H',\n            9 => 'I',\n            10 => 'J',\n            // ...\n            25 => 'Y',\n            26 => 'Z',\n            // As in the last exercise, please add the 'else' clause\n            // and this time, have it return an exclamation mark '!'.\n            else => {\n                '!';\n            }\n        };\n\n        std.debug.print(\"{c}\", .{real_char});\n        // Note: \"{c}\" forces print() to display the value as a character.\n        // Can you guess what happens if you remove the \"c\"? Try it!\n    }\n\n    std.debug.print(\"\\n\", .{});\n}\n"}],"textDocument":{"uri":"file:///home/voroskoi/code/ziglings/exercises/031_switch2.zig","version":1}}}
2021-12-25T01:55:45.603 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/voroskoi/code/ziglings/exercises/031_switch2.zig","diagnostics":[]}}
2021-12-25T01:57:33.114 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"textDocument/formatting","params":{"options":{"insertSpaces":false,"tabSize":0},"textDocument":{"uri":"file:///home/voroskoi/code/ziglings/exercises/031_switch2.zig"}},"id":2}
2021-12-25T01:57:33.143 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","id":2,"result":[{"range":{"start":{"line":0,"character":0},"end":{"line":46,"character":0}},"newText":"//\n// What's really nice is that you can use a switch statement as an\n// expression to return a value.\n//\n//     var a = switch (x) {\n//         1 => 9,\n//         2 => 16,\n//         3 => 7,\n//         ...\n//     }\n//\nconst std = @import(\"std\");\n\npub fn main() void {\n    const lang_chars = [_]u8{ 26, 9, 7, 42 };\n\n    for (lang_chars) |c| {\n        var real_char: u8 = switch (c) {\n            1 => 'A',\n            2 => 'B',\n            3 => 'C',\n            4 => 'D',\n            5 => 'E',\n            6 => 'F',\n            7 => 'G',\n            8 => 'H',\n            9 => 'I',\n            10 => 'J',\n            // ...\n            25 => 'Y',\n            26 => 'Z',\n            // As in the last exercise, please add the 'else' clause\n            // and this time, have it return an exclamation mark '!'.\n            else => {\n                '!';\n            },\n        };\n\n        std.debug.print(\"{c}\", .{real_char});\n        // Note: \"{c}\" forces print() to display the value as a character.\n        // Can you guess what happens if you remove the \"c\"? Try it!\n    }\n\n    std.debug.print(\"\\n\", .{});\n}\n"}]}
2021-12-25T01:57:33.144 helix_lsp::transport [INFO] <- [{"newText":"//\n// What's really nice is that you can use a switch statement as an\n// expression to return a value.\n//\n//     var a = switch (x) {\n//         1 => 9,\n//         2 => 16,\n//         3 => 7,\n//         ...\n//     }\n//\nconst std = @import(\"std\");\n\npub fn main() void {\n    const lang_chars = [_]u8{ 26, 9, 7, 42 };\n\n    for (lang_chars) |c| {\n        var real_char: u8 = switch (c) {\n            1 => 'A',\n            2 => 'B',\n            3 => 'C',\n            4 => 'D',\n            5 => 'E',\n            6 => 'F',\n            7 => 'G',\n            8 => 'H',\n            9 => 'I',\n            10 => 'J',\n            // ...\n            25 => 'Y',\n            26 => 'Z',\n            // As in the last exercise, please add the 'else' clause\n            // and this time, have it return an exclamation mark '!'.\n            else => {\n                '!';\n            },\n        };\n\n        std.debug.print(\"{c}\", .{real_char});\n        // Note: \"{c}\" forces print() to display the value as a character.\n        // Can you guess what happens if you remove the \"c\"? Try it!\n    }\n\n    std.debug.print(\"\\n\", .{});\n}\n","range":{"end":{"character":0,"line":46},"start":{"character":0,"line":0}}}]
2021-12-25T01:57:33.145 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"//\n// What's really nice is that you can use a switch statement as an\n// expression to return a value.\n//\n//     var a = switch (x) {\n//         1 => 9,\n//         2 => 16,\n//         3 => 7,\n//         ...\n//     }\n//\nconst std = @import(\"std\");\n\npub fn main() void {\n    const lang_chars = [_]u8{ 26, 9, 7, 42 };\n\n    for (lang_chars) |c| {\n        var real_char: u8 = switch (c) {\n            1 => 'A',\n            2 => 'B',\n            3 => 'C',\n            4 => 'D',\n            5 => 'E',\n            6 => 'F',\n            7 => 'G',\n            8 => 'H',\n            9 => 'I',\n            10 => 'J',\n            // ...\n            25 => 'Y',\n            26 => 'Z',\n            // As in the last exercise, please add the 'else' clause\n            // and this time, have it return an exclamation mark '!'.\n            else => {\n                '!';\n            }\n        };\n\n        std.debug.print(\"{c}\", .{real_char});\n        // Note: \"{c}\" forces print() to display the value as a character.\n        // Can you guess what happens if you remove the \"c\"? Try it!\n    }\n\n    std.debug.print(\"\\n\", .{});\n}\n"}],"textDocument":{"uri":"file:///home/voroskoi/code/ziglings/exercises/031_switch2.zig","version":2}}}
2021-12-25T01:57:33.147 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/voroskoi/code/ziglings/exercises/031_switch2.zig","diagnostics":[]}}

In this example notice the , after '!';\n } which is added by zls, but textDocument/didChange overwrites it right after.

@voroskoi voroskoi added the C-bug Category: This is a bug label Dec 25, 2021
@kirawi kirawi added the A-language-server Area: Language server client label Dec 25, 2021
@paoda
Copy link

paoda commented Jan 18, 2022

With #1269 resolved, I was successfully able to reproduce this issue on master. (Specifically 22b728d)

~/.cache/helix/helix.log
2022-01-18T12:55:41.779 mio::poll [TRACE] registering event source with poller: token=Token(1), interests=READABLE | WRITABLE
2022-01-18T12:55:41.779 mio::poll [TRACE] registering event source with poller: token=Token(2), interests=READABLE | WRITABLE
2022-01-18T12:55:41.779 mio::poll [TRACE] registering event source with poller: token=Token(3), interests=READABLE | WRITABLE
2022-01-18T12:55:41.779 mio::poll [TRACE] registering event source with poller: token=Token(4), interests=READABLE | WRITABLE
2022-01-18T12:55:41.779 mio::poll [TRACE] registering event source with poller: token=Token(5), interests=READABLE | WRITABLE
2022-01-18T12:55:41.779 mio::poll [TRACE] registering event source with poller: token=Token(0), interests=READABLE
2022-01-18T12:55:41.779 mio::poll [TRACE] registering event source with poller: token=Token(1), interests=READABLE
2022-01-18T12:55:41.779 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] Using zig executable /home/paoda/.local/bin/zig"}}
2022-01-18T12:55:41.779 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"initialize","params":{"capabilities":{"textDocument":{"codeAction":{"codeActionLiteralSupport":{"codeActionKind":{"valueSet":["","quickfix","refactor","refactor.extract","refactor.inline","refactor.rewrite","source","source.organizeImports"]}}},"completion":{"completionItem":{"snippetSupport":false},"completionItemKind":{}},"hover":{"contentFormat":["markdown"]},"rename":{"dynamicRegistration":false,"honorsChangeAnnotations":false,"prepareSupport":false}},"window":{"workDoneProgress":true}},"processId":143714,"rootUri":"file:///home/paoda/Documents/dev/test/zig_new"},"id":0}
2022-01-18T12:55:41.780 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] Using zig executable /home/paoda/.local/bin/zig" }
2022-01-18T12:55:41.783 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] Using zig lib path '/opt/zigup/zig/0.10.0-dev.290+3901b6fb0/files/lib'"}}
2022-01-18T12:55:41.783 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] Using zig lib path '/opt/zigup/zig/0.10.0-dev.290+3901b6fb0/files/lib'" }
2022-01-18T12:55:41.787 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","id":0,"result":{"offsetEncoding":"utf-16","capabilities":{"signatureHelpProvider":{"triggerCharacters":["("],"retriggerCharacters":[","]},"textDocumentSync":1,"renameProvider":true,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":","@"]},"documentHighlightProvider":false,"hoverProvider":true,"codeActionProvider":false,"declarationProvider":true,"definitionProvider":true,"typeDefinitionProvider":true,"implementationProvider":false,"referencesProvider":true,"documentSymbolProvider":true,"colorProvider":false,"documentFormattingProvider":true,"documentRangeFormattingProvider":false,"foldingRangeProvider":false,"selectionRangeProvider":false,"workspaceSymbolProvider":false,"rangeProvider":false,"documentProvider":true,"workspace":{"workspaceFolders":{"supported":false,"changeNotifications":false}},"semanticTokensProvider":{"full":true,"range":false,"legend":{"tokenTypes":["type","parameter","variable","enumMember","field","errorTag","function","keyword","comment","string","number","operator","builtin","label","keywordLiteral"],"tokenModifiers":["namespace","struct","enum","union","opaque","declaration","async","documentation","generic"]}}},"serverInfo":{"name":"zls","version":"0.1.0"}}}
2022-01-18T12:55:41.787 helix_lsp::transport [INFO] <- {"capabilities":{"codeActionProvider":false,"colorProvider":false,"completionProvider":{"resolveProvider":false,"triggerCharacters":[".",":","@"]},"declarationProvider":true,"definitionProvider":true,"documentFormattingProvider":true,"documentHighlightProvider":false,"documentProvider":true,"documentRangeFormattingProvider":false,"documentSymbolProvider":true,"foldingRangeProvider":false,"hoverProvider":true,"implementationProvider":false,"rangeProvider":false,"referencesProvider":true,"renameProvider":true,"selectionRangeProvider":false,"semanticTokensProvider":{"full":true,"legend":{"tokenModifiers":["namespace","struct","enum","union","opaque","declaration","async","documentation","generic"],"tokenTypes":["type","parameter","variable","enumMember","field","errorTag","function","keyword","comment","string","number","operator","builtin","label","keywordLiteral"]},"range":false},"signatureHelpProvider":{"retriggerCharacters":[","],"triggerCharacters":["("]},"textDocumentSync":1,"typeDefinitionProvider":true,"workspace":{"workspaceFolders":{"changeNotifications":false,"supported":false}},"workspaceSymbolProvider":false},"offsetEncoding":"utf-16","serverInfo":{"name":"zls","version":"0.1.0"}}
2022-01-18T12:55:41.787 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] zls initialized"}}
2022-01-18T12:55:41.787 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] ClientCapabilities{ .supports_snippets = false, .supports_semantic_tokens = false, .hover_supports_md = true, .completion_doc_supports_md = false }"}}
2022-01-18T12:55:41.787 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] Using offset encoding: utf16"}}
2022-01-18T12:55:41.787 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] zls initialized" }
2022-01-18T12:55:41.787 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] ClientCapabilities{ .supports_snippets = false, .supports_semantic_tokens = false, .hover_supports_md = true, .completion_doc_supports_md = false }" }
2022-01-18T12:55:41.787 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-main] Using offset encoding: utf16" }
2022-01-18T12:55:41.787 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"initialized","params":{}}
2022-01-18T12:55:41.787 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"textDocument/didOpen","params":{"textDocument":{"languageId":"zig","text":"const std = @import(\"std\");\n\npub fn main() anyerror!void {\nstd.log.info(\"All your codebase are belong to us.\", .{});\n}\n\ntest \"basic test\" {\n    try std.testing.expectEqual(10, 3 + 7);\n}\n","uri":"file:///home/paoda/Documents/dev/test/zig_new/src/main.zig","version":0}}}
2022-01-18T12:55:41.787 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-doc_store] builtin config not found, falling back to defualt: file:///home/paoda/.config/builtin.zig"}}
2022-01-18T12:55:41.787 helix_term::application [INFO] window/logMessage: LogMessageParams { typ: Info, message: "[info-doc_store] builtin config not found, falling back to defualt: file:///home/paoda/.config/builtin.zig" }
2022-01-18T12:55:44.162 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///home/paoda/Documents/dev/test/zig_new/src/main.zig","diagnostics":[]}}
2022-01-18T12:55:44.838 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"textDocument/formatting","params":{"options":{"insertSpaces":false,"tabSize":0},"textDocument":{"uri":"file:///home/paoda/Documents/dev/test/zig_new/src/main.zig"}},"id":1}
2022-01-18T12:55:44.841 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","id":1,"result":[{"range":{"start":{"line":0,"character":0},"end":{"line":10,"character":0}},"newText":"const std = @import(\"std\");\n\npub fn main() anyerror!void {\n    std.log.info(\"All your codebase are belong to us.\", .{});\n}\n\ntest \"basic test\" {\n    try std.testing.expectEqual(10, 3 + 7);\n}\n"}]}
2022-01-18T12:55:44.841 helix_lsp::transport [INFO] <- [{"newText":"const std = @import(\"std\");\n\npub fn main() anyerror!void {\n    std.log.info(\"All your codebase are belong to us.\", .{});\n}\n\ntest \"basic test\" {\n    try std.testing.expectEqual(10, 3 + 7);\n}\n","range":{"end":{"character":0,"line":10},"start":{"character":0,"line":0}}}]
2022-01-18T12:55:46.381 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"shutdown","params":null,"id":2}
2022-01-18T12:55:46.381 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","method":"window/logMessage","params":{"type":3,"message":"[info-main] Server closing..."}}
2022-01-18T12:55:46.381 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","id":2,"result":null}
2022-01-18T12:55:46.381 helix_lsp::transport [INFO] <- null
2022-01-18T12:55:46.381 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"exit","params":null}
2022-01-18T12:55:46.381 helix_lsp::transport [ERROR] err: <- StreamClosed
2022-01-18T12:55:46.381 mio::poll [TRACE] deregistering event source from poller
2022-01-18T12:55:46.381 helix_lsp::transport [ERROR] err: <- StreamClosed
2022-01-18T12:55:46.381 mio::poll [TRACE] deregistering event source from poller
2022-01-18T12:55:46.382 mio::poll [TRACE] deregistering event source from poller
2022-01-18T12:55:46.382 mio::poll [TRACE] deregistering event source from poller
2022-01-18T12:55:46.382 mio::poll [TRACE] deregistering event source from poller

@rynoV
Copy link

rynoV commented Jun 16, 2022

2022-01-18T12:55:44.838 helix_lsp::transport [INFO] -> {"jsonrpc":"2.0","method":"textDocument/formatting","params":{"options":{"insertSpaces":false,"tabSize":0},"textDocument":{"uri":"file:///home/paoda/Documents/dev/test/zig_new/src/main.zig"}},"id":1}
2022-01-18T12:55:44.841 helix_lsp::transport [INFO] <- {"jsonrpc":"2.0","id":1,"result":[{"range":{"start":{"line":0,"character":0},"end":{"line":10,"character":0}},"newText":"const std = @import(\"std\");\n\npub fn main() anyerror!void {\n    std.log.info(\"All your codebase are belong to us.\", .{});\n}\n\ntest \"basic test\" {\n    try std.testing.expectEqual(10, 3 + 7);\n}\n"}]}
2022-01-18T12:55:44.841 helix_lsp::transport [INFO] <- [{"newText":"const std = @import(\"std\");\n\npub fn main() anyerror!void {\n    std.log.info(\"All your codebase are belong to us.\", .{});\n}\n\ntest \"basic test\" {\n    try std.testing.expectEqual(10, 3 + 7);\n}\n","range":{"end":{"character":0,"line":10},"start":{"character":0,"line":0}}}]

I'm seeing this same issue with purescript-language-server (custom configuration), and the same pattern in my logs: language server returns formatted source like this but the file's content doesn't get updated.

My custom language config for reference
[[language]]
name = "purescript"
scope = "scope.purescript"
injection-regex = "^purescript$"
file-types = ["purs"]
comment-token = "--"
indent = { tab-width = 2, unit = "  " }
language-server = { command = "purescript-language-server", args = ["--stdio"] }
roots = ["packages.dhall", "spago.dhall"]
auto-format = true
grammar = "haskell"
diagnostic-severity = "Warning"

@hovsater
Copy link
Contributor

hovsater commented Jul 7, 2022

Turns out it's an off-by-one error in the Zig language server. Solved in zigtools/zls#505. Build zls from source if you want it working.

@voroskoi
Copy link
Contributor Author

voroskoi commented Jul 8, 2022

@kevinsjoberg: thanks for the info, this indeed fixes the problem. However I have one minor nit: when I use :w for saving the file the whole buffer gets selected like % is pressed.
Is this just me, or You see similar behavior? I have no idea how to disable this.

@sudormrfbin
Copy link
Member

sudormrfbin commented Jul 8, 2022

@voroskoi it might have been fixed by #2778.

@voroskoi
Copy link
Contributor Author

voroskoi commented Jul 9, 2022

@sudormrfbin: thanks for the tip, I have tried with latest master, but sadly the behavior did not change.

Shall I open a separate bug report as this is a different problem now?

@jefftime
Copy link

From what I can tell, whole document gets selected after formatting due to the response from ZLS. I compared Rust's LSP formatting output to ZLS's. For both of these, I added some newlines to an empty project generated from cargo new and zig init-exe, and then ran the LSP formatter on each

Rust LSP format response:

Array([
    Object({
        "newText": String(
            "",
        ),
        "range": Object({
            "end": Object({
                "character": Number(
                    0,
                ),
                "line": Number(
                    5,
                ),
            }),
            "start": Object({
                "character": Number(
                    0,
                ),
                "line": Number(
                    1,
                ),
            }),
        }),
    }),
])

Zig LSP format response:

Array([
    Object({
        "newText": String(
            "const std = @import(\"std\");\n\npub fn main() anyerror!void {\n    std.log.info(\"Test\", .{});\n}\n",
        ),
        "range": Object({
            "end": Object({
                "character": Number(
                    0,
                ),
                "line": Number(
                    8,
                ),
            }),
            "start": Object({
                "character": Number(
                    0,
                ),
                "line": Number(
                    0,
                ),
            }),
        }),
    }),
])

I haven't looked into how Helix decides to place the cursor after formatting, but as you can see, ZLS returns the entire file in the newText when asked to format. I don't know enough about the LSP spec to say if this is proper behavior. Perhaps ZLS should only be returning edits in the newText field

I don't really know what Helix should do in this situation. Maybe it should remember the last cursor position and keep it unchanged after formatting, but the cursor could end up in a different spot than it was initially after being formatted

@bootradev
Copy link
Contributor

I've been following this issue for awhile and I'd like to chime in. On helix 22.05 (e4c9d40), with Windows cmd prompt, I can confirm that I don't get the whole file selection after save any more, it's treated like a file reload.

@jefftime
Copy link

jefftime commented Aug 24, 2022

My pull request to ZLS was just accepted to fix this issue. Helix should no longer be selecting the entire document after a format

@voroskoi
Copy link
Contributor Author

@jefftime: Thank You very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-language-server Area: Language server client C-bug Category: This is a bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants