Lsp-mode: zig goto definition not working: wrong-type-argument sequencep

Created on 16 Oct 2020  路  15Comments  路  Source: emacs-lsp/lsp-mode

Forgive me for not following the template. After posting this to lsp-ui, it was suggested that i raise this issue here. I'm using emacs 27.1 and lsp-mode/lsp-ui are freshly installed in the past two days. This issue happens when using https://github.com/zigtools/zls and suggested configs shown at bottom.

When selecting 'goto definition' from the right click context menu, i get the following:

Error running timer: (wrong-type-argument sequencep #s(hash-table size 65
 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("uri" "file:///.../file.zig" 
"range" #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 
data ("start" #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 
0.8125 data ("line" 471 "character" 15)) "end" #s(hash-table size 65 test equal 
rehash-size 1.5 rehash-threshold 0.8125 data ("line" 471 "character" 15)))))))

Also, i'm seeing the following on startup even though hover works fine. This has also been reported as a zls (zig language server) issue:

Error (use-package): lsp-ui/:config: 
  The connected server(s) does not support method textDocument/hover.

In zig's irc, they suggest this is likely some type of emacs error. Goto definition with zls is working pretty well in vscode, vim, kakoune. Any ideas what could be happening or do I need to provide more information? I'm mainly hoping to be able to use the goto definition feature with zig.

(require 'lsp)
(add-to-list 'lsp-language-id-configuration '(zig-mode . "zig"))
(lsp-register-client
  (make-lsp-client
    :new-connection (lsp-stdio-connection "/path/to/zls/here")
    :major-modes '(zig-mode)
    :server-id 'zls))

(use-package lsp-mode
  :commands lsp
  :hook ((zig-mode) . lsp)
  :bind (:map lsp-mode-map
              ;; ("TAB" . completion-at-point)
          ))

(use-package lsp-ui
  :hook (lsp-mode . lsp-ui-mode)
  :config
  (setq lsp-ui-sideline-enable t)
  (setq lsp-ui-sideline-show-hover nil)
  (setq lsp-ui-doc-position 'bottom)
  (lsp-ui-doc-show))

bug

All 15 comments

Can you follow https://emacs-lsp.github.io/lsp-mode/page/troubleshooting/ and provide an io log?
Also toggle-debug-on-error and showing the backtrace buffer as well

I believe I have the same problem. Here's a stack trace:

Debugger entered--Lisp error: (wrong-type-argument sequencep #<hash-table equal 2/2 0x3ab9145>)
  seq-length(#<hash-table equal 2/2 0x3ab9145>)
  #f(compiled-function (sequence) #<bytecode 0x6ebce1>)(#<hash-table equal 2/2 0x3ab9145>)
  apply(#f(compiled-function (sequence) #<bytecode 0x6ebce1>) #<hash-table equal 2/2 0x3ab9145> nil)
  seq-empty-p(#<hash-table equal 2/2 0x3ab9145>)
  lsp-find-locations("textDocument/definition" nil :display-action nil)
  lsp-find-definition()
  #<subr funcall-interactively>(lsp-find-definition)
  apply(#<subr funcall-interactively> lsp-find-definition)
  funcall-interactively(lsp-find-definition)
  #<subr call-interactively>(lsp-find-definition)
  apply(#<subr call-interactively> lsp-find-definition)
  explain-pause--wrap-call-interactively(#<subr call-interactively> lsp-find-definition)
  apply(explain-pause--wrap-call-interactively #<subr call-interactively> lsp-find-definition)
  call-interactively(lsp-find-definition)
  (if (commandp handler) (call-interactively handler) (funcall handler identifier))
  +lookup--run-handler(lsp-find-definition "template")
  (condition-case e (+lookup--run-handler handler identifier) ((debug error) (if doom-debug-p (progn (let ((inhibit-message (active-minibuffer-window))) (message #("DOOM Lookup handler %S threw an error: %s" 0 5 (face font-lock-comment-face)) handler e)))) 'fail))
  (let ((wconf (current-window-configuration)) (result (condition-case e (+lookup--run-handler handler identifier) ((debug error) (if doom-debug-p (progn (let ... ...))) 'fail)))) (cond ((eq result 'fail) (set-window-configuration wconf) nil) ((or (get handler '+lookup-async) (eq result 'deferred))) ((or result (null origin) (/= (point-marker) origin)) (prog1 (point-marker) (set-window-configuration wconf)))))
  (condition-case e (let ((wconf (current-window-configuration)) (result (condition-case e (+lookup--run-handler handler identifier) ((debug error) (if doom-debug-p (progn ...)) 'fail)))) (cond ((eq result 'fail) (set-window-configuration wconf) nil) ((or (get handler '+lookup-async) (eq result 'deferred))) ((or result (null origin) (/= (point-marker) origin)) (prog1 (point-marker) (set-window-configuration wconf))))) ((debug error user-error) (message "Lookup handler %S: %s" handler e) nil))
  +lookup--run-handlers(lsp-find-definition "template" #<marker at 325 in Main.hs>)
  run-hook-wrapped(+lookup--run-handlers lsp-find-definition "template" #<marker at 325 in Main.hs>)
  (if arg (let* ((handler (and t (intern-soft (completing-read "Select lookup handler: " (delete-dups ...) nil t))))) (if handler (+lookup--run-handlers handler identifier origin) (user-error "No lookup handler selected"))) (run-hook-wrapped handlers #'+lookup--run-handlers identifier origin))
  (let* ((origin (point-marker)) (handlers (plist-get (list :definition '+lookup-definition-functions :implementations '+lookup-implementations-functions :type-definition '+lookup-type-definition-functions :references '+lookup-references-functions :documentation '+lookup-documentation-functions :file '+lookup-file-functions) prop)) (result (if arg (let* ((handler (and t ...))) (if handler (+lookup--run-handlers handler identifier origin) (user-error "No lookup handler selected"))) (run-hook-wrapped handlers #'+lookup--run-handlers identifier origin)))) (if (cond ((null result) (message "No lookup handler could find %S" identifier) nil) ((markerp result) (funcall (or display-fn #'switch-to-buffer) (marker-buffer result)) (goto-char result) result) (result)) (progn (save-current-buffer (set-buffer (marker-buffer origin)) (better-jumper-set-jump (marker-position origin))) result)))
  +lookup--jump-to(:definition "template" nil nil)
  (cond ((null identifier) (user-error "Nothing under point")) ((+lookup--jump-to :definition identifier nil arg)) ((error "Couldn't find the definition of %S" identifier)))
  +lookup/definition("template" nil)
  #<subr funcall-interactively>(+lookup/definition "template" nil)
  apply(#<subr funcall-interactively> (+lookup/definition "template" nil))
  funcall-interactively(+lookup/definition "template" nil)
  #<subr call-interactively>(+lookup/definition nil nil)
  apply(#<subr call-interactively> (+lookup/definition nil nil))
  explain-pause--wrap-call-interactively(#<subr call-interactively> +lookup/definition nil nil)
  apply(explain-pause--wrap-call-interactively #<subr call-interactively> (+lookup/definition nil nil))
  call-interactively(+lookup/definition nil nil)
  command-execute(+lookup/definition)

I'm using Doom Emacs, which is why things are wrapped in this "lookup" stuff.

I tried a simple fix of replacing seq-empty-p with hash-table-empty-p, but unless I did something wrong, it didn't seem to work. It was a stab in the dark, and I'm still playing around with this.

Okay, I think I was close. Needed to do a check to make sure it wasn't nil, and also change the seq-empty-p to hash-table-empty-p.

I'll put up a PR shortly. However I really didn't dig deeper than notice the type mismatch, and make what I thought was the most likely fix. So I could have missed something deeper. Maybe it's indeed suppose to be a sequence, and not a hash table, but the function returning the hash table needs to be modified.

However, when making the change I did, the functionality seemed to work, so I have some degree of confidence.

Looking at Git logs, I think this commit is related: 92ec703bc368453ed08697d2d057fae4a96851a2. So @yyoncho might want to chime in.

I'm not sure how to provide a more verbose debug output of the error. I tried setting toggle-debug-on-error but that doesn't show any additional info.

Here is my lsp-log right after a failed 'goto definition':

Show lsp-log

[Trace - 06:46:47 PM] Sending request 'initialize - (1)'.
Params: {
  "processId": null,
  "rootPath": "/home/travis/Documents/Code/zig/zig-tmpl",
  "clientInfo": {
    "name": "emacs",
    "version": "GNU Emacs 27.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.5)\n of 2020-10-10"
  },
  "rootUri": "file:///home/travis/Documents/Code/zig/zig-tmpl",
  "capabilities": {
    "workspace": {
      "workspaceEdit": {
        "documentChanges": true,
        "resourceOperations": [
          "create",
          "rename",
          "delete"
        ]
      },
      "applyEdit": true,
      "symbol": {
        "symbolKind": {
          "valueSet": [
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20,
            21,
            22,
            23,
            24,
            25,
            26
          ]
        }
      },
      "executeCommand": {
        "dynamicRegistration": false
      },
      "didChangeWatchedFiles": {
        "dynamicRegistration": true
      },
      "workspaceFolders": true,
      "configuration": true
    },
    "textDocument": {
      "declaration": {
        "linkSupport": true
      },
      "definition": {
        "linkSupport": true
      },
      "implementation": {
        "linkSupport": true
      },
      "typeDefinition": {
        "linkSupport": true
      },
      "synchronization": {
        "willSave": true,
        "didSave": true,
        "willSaveWaitUntil": true
      },
      "documentSymbol": {
        "symbolKind": {
          "valueSet": [
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
            10,
            11,
            12,
            13,
            14,
            15,
            16,
            17,
            18,
            19,
            20,
            21,
            22,
            23,
            24,
            25,
            26
          ]
        },
        "hierarchicalDocumentSymbolSupport": true
      },
      "formatting": {
        "dynamicRegistration": true
      },
      "rangeFormatting": {
        "dynamicRegistration": true
      },
      "rename": {
        "dynamicRegistration": true,
        "prepareSupport": true
      },
      "codeAction": {
        "dynamicRegistration": true,
        "isPreferredSupport": true,
        "codeActionLiteralSupport": {
          "codeActionKind": {
            "valueSet": [
              "",
              "quickfix",
              "refactor",
              "refactor.extract",
              "refactor.inline",
              "refactor.rewrite",
              "source",
              "source.organizeImports"
            ]
          }
        }
      },
      "completion": {
        "completionItem": {
          "snippetSupport": true,
          "documentationFormat": [
            "markdown"
          ],
          "resolveAdditionalTextEditsSupport": true
        },
        "contextSupport": true
      },
      "signatureHelp": {
        "signatureInformation": {
          "parameterInformation": {
            "labelOffsetSupport": true
          }
        }
      },
      "documentLink": {
        "dynamicRegistration": true,
        "tooltipSupport": true
      },
      "hover": {
        "contentFormat": [
          "markdown",
          "plaintext"
        ]
      },
      "foldingRange": {
        "dynamicRegistration": true
      },
      "callHierarchy": {
        "dynamicRegistration": false
      },
      "publishDiagnostics": {
        "relatedInformation": true,
        "tagSupport": {
          "valueSet": [
            1,
            2
          ]
        },
        "versionSupport": true
      }
    },
    "window": {
      "workDoneProgress": true
    }
  },
  "initializationOptions": null,
  "workDoneToken": "1"
}


[Trace - 06:46:47 PM] Received response 'initialize - (1)' in 82ms.
Result: {
  "capabilities": {
    "semanticTokensProvider": {
      "legend": {
        "tokenModifiers": [
          "definition",
          "async",
          "documentation",
          "generic"
        ],
        "tokenTypes": [
          "namespace",
          "type",
          "struct",
          "enum",
          "union",
          "opaque",
          "parameter",
          "variable",
          "tagField",
          "field",
          "errorTag",
          "function",
          "keyword",
          "comment",
          "string",
          "number",
          "operator",
          "builtin",
          "label",
          "keywordLiteral"
        ]
      },
      "documentProvider": true
    },
    "workspace": {
      "workspaceFolders": {
        "changeNotifications": true,
        "supported": true
      }
    },
    "documentProvider": true,
    "rangeProvider": null,
    "workspaceSymbolProvider": null,
    "selectionRangeProvider": null,
    "foldingRangeProvider": null,
    "documentRangeFormattingProvider": null,
    "documentFormattingProvider": true,
    "colorProvider": null,
    "documentSymbolProvider": true,
    "referencesProvider": true,
    "implementationProvider": null,
    "typeDefinitionProvider": true,
    "definitionProvider": true,
    "declarationProvider": true,
    "codeActionProvider": null,
    "hoverProvider": true,
    "documentHighlightProvider": null,
    "completionProvider": {
      "triggerCharacters": [
        ".",
        ":",
        "@"
      ],
      "resolveProvider": null
    },
    "renameProvider": true,
    "textDocumentSync": 1,
    "signatureHelpProvider": {
      "triggerCharacters": [
        "(",
        ","
      ]
    }
  }
}


[Trace - 06:46:47 PM] Sending notification 'initialized'.
Params: {
}


[Trace - 06:46:47 PM] Sending notification 'textDocument/didOpen'.
Params: {
  "textDocument": {
    "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig",
    "languageId": "zig",
    "version": 0,
    "text": "const std = @import(\"std\");\nusingnamespace @import(\"tmpl_ast.zig\");\n\nfn countVariables(str: []const u8) usize {\n    var result: usize = 0;\n    for (str) |c, i| {\n        // non escaped dir_start\n        if (c == Token.dir_start and (i == 0 or str[i - 1] != Token.escape))\n            result += 1;\n    }\n    return result;\n}\n\nfn showError(comptime msg: []const u8, comptime args: anytype) void {\n    @compileError(std.fmt.comptimePrint(msg, args));\n}\n\nconst State = enum {\n    literal,\n    variable,\n    computed,\n};\n\nconst Fragment = union(State) {\n    literal: []const u8,\n    variable: []const u8,\n    computed: []const u8,\n};\n\nconst Token = struct {\n    pub const dir_start = '{';\n    pub const DirEnd = '}';\n    pub const computed = '%';\n    pub const escape = '\\\\';\n};\n\npub fn Template(comptime fmt: []const u8) type {\n    const numVariables = countVariables(fmt);\n    var buildFragments: [numVariables * 2 + 1]Stmt = undefined;\n    var state: State = .literal;\n    var startIdx = 0;\n    var buildIdx = 0;\n    var numComputed = 0;\n    for (fmt) |c, i| {\n        switch (c) {\n            Token.dir_start => {\n                if (i != 0 and fmt[i - 1] == Token.escape) continue;\n                if (state == .variable or state == .computed)\n                    showError(\"Too many levels of '{c}' at position {}\", .{ Token.dir_start, i });\n                buildFragments[buildIdx] = Stmt.literal(fmt[startIdx..i]);\n                startIdx = i;\n                state = .variable;\n                buildIdx += 1;\n            },\n            Token.computed => {\n                if (i != 0 and fmt[i - 1] == Token.dir_start) {\n                    state = .computed;\n                    startIdx += 1;\n                }\n            },\n            Token.DirEnd => {\n                const isComputed = state == .computed;\n                if (i != 0 and fmt[i - 1] == Token.escape) continue;\n                if (state == .literal) {\n                    showError(\"Unmatched '{c}' at position {}\", .{ Token.DirEnd, i });\n                } else if (isComputed and fmt[i - 1] != Token.computed) {\n                    showError(\"Unmatched '{c}' at position {}\", .{ Token.computed, i });\n                } else if (!isComputed and (i > 0 and fmt[i - 1] == Token.computed) and (i > 1 and fmt[i - 2] != Token.escape)) {\n                    showError(\"Unmatched '{c}' at position {}\", .{ Token.computed, i });\n                }\n                // trim Token.dir_start, Token.DirEnd and Token.computed\n                const value = std.mem.trim(u8, fmt[startIdx + 1 .. if (isComputed) i - 1 else i], \" \");\n                buildFragments[buildIdx] = if (isComputed) try Stmt.parseComputed(value) else Stmt.ident(value);\n                startIdx = i + 1;\n                buildIdx += 1;\n                if (isComputed) numComputed += 1;\n                state = .literal;\n            },\n            else => {},\n        }\n    }\n\n    if (state == .variable or state == .computed)\n        showError(\"Unmatched '{c}' at position {}\", .{ Token.dir_start, startIdx });\n\n    buildFragments[buildIdx] = Stmt.literal(fmt[startIdx..]);\n\n    return struct {\n        pub const fragments = buildFragments;\n        pub var statements: [numComputed]Stmt = undefined;\n        pub fn bufPrint(buf: []u8, args: anytype) ![]u8 {\n            var bufi: usize = 0;\n            inline for (fragments) |frag, i| {\n                const target = switch (frag) {\n                    .expr => switch (frag.expr) {\n                        .literal => frag.expr.literal,\n                        .ident => @field(args, frag.expr.ident.name),\n                        .call => @panic(\"unimplemented\"),\n                    },\n                    .block => interpret(frag.block),\n                    .for_in => @panic(\"unimplemented\"),\n                };\n                if (bufi + target.len > buf.len) return error.BufferTooSmall;\n                std.mem.copy(u8, buf[bufi..], target);\n                bufi += target.len;\n            }\n            return buf[0..bufi];\n        }\n        pub fn allocPrint(allr: *std.mem.Allocator, args: anytype) ![]u8 {\n            const result = try allr.alloc(u8, countSize(args));\n            return bufPrint(result, args) catch |err| switch (err) {\n                error.BufferTooSmall => unreachable,\n            };\n        }\n        pub fn countSize(args: anytype) usize {\n            var size: usize = 0;\n            inline for (fragments) |frag, i| {\n                size += switch (frag) {\n                    .expr => switch (frag.expr) {\n                        .literal => frag.expr.literal,\n                        .ident => @field(args, frag.expr.ident.name),\n                        .call => @panic(\"unimplemented\"),\n                    },\n                    .block => interpret(frag.block),\n                    .for_in => @panic(\"unimplemented\"),\n                }.len;\n            }\n            return size;\n        }\n        fn interpret(text: []const u8) []const u8 {\n            return text;\n        }\n        // pub fn parseStmt(frag: []const u8) !Stmt {}\n        // pub fn parse() !void {\n        //     // std.debug.warn(\"numComputed {}\\n\", .{numComputed});\n        //     // statements = &([1]Stmt{undefined} ** numComputed);\n        //     var stmti: usize = 0;\n        //     for (fragments) |frag| {\n        //         if (frag == .block) {\n        //             statements[stmti] = try parseStmt(frag.block);\n        //         }\n        //     }\n        // }\n    };\n}\n\nfn f() void {\n    // TODO build ast\n    var computed: [numComputed][]const u8 = undefined;\n    var proci: usize = 0;\n    for (buildFragments) |frag| {\n        if (frag == .computed) {\n            computed[proci] = frag.computed;\n            // const tree = std.zig.parse(a, frag.computed) catch |e| {\n            //     std.debug.warn(\"e {}\\n\", .{e});\n            // };\n            proci += 1;\n        }\n    }\n}\n\nconst testing = std.testing;\n// var allocatorBuf: [1024 * 64]u8 = undefined;\n// var allocator = std.heap.FixedBufferAllocator.init(&allocatorBuf).allocator;\nconst allocator = testing.allocator;\n\ntest \"basic tests\" {\n    var out_buf: [1000]u8 = undefined;\n    {\n        const tmpl = Template(\"hello\");\n\n        testing.expectEqual(tmpl.fragments.len, 1);\n        testing.expect(Stmt.isLiteral(tmpl.fragments[0]));\n        testing.expectEqualSlices(u8, tmpl.fragments[0].expr.literal, \"hello\");\n\n        const out = try tmpl.bufPrint(&out_buf, .{});\n        testing.expectEqualSlices(u8, \"hello\", out);\n    }\n\n    {\n        const tmpl = Template(\"hello{0}world\");\n        testing.expectEqual(tmpl.fragments.len, 3);\n        testing.expectEqualSlices(u8, tmpl.fragments[0].expr.literal, \"hello\");\n        testing.expectEqualSlices(u8, tmpl.fragments[2].expr.literal, \"world\");\n        testing.expectEqualSlices(u8, tmpl.fragments[1].expr.ident.name, \"0\");\n\n        const out1 = try tmpl.bufPrint(&out_buf, .{\" \"});\n        testing.expectEqualSlices(u8, out1, \"hello world\");\n\n        const out2 = try tmpl.bufPrint(&out_buf, .{\"\\n\"});\n        testing.expectEqualSlices(u8, out2, \"hello\\nworld\");\n    }\n\n    {\n        const tmpl = Template(\"{hello} {world}\");\n        testing.expectEqual(tmpl.fragments.len, 5);\n        testing.expectEqualSlices(u8, tmpl.fragments[0].expr.literal, \"\");\n        testing.expectEqualSlices(u8, tmpl.fragments[2].expr.literal, \" \");\n        testing.expectEqualSlices(u8, tmpl.fragments[4].expr.literal, \"\");\n        testing.expectEqualSlices(u8, tmpl.fragments[1].expr.ident.name, \"hello\");\n        testing.expectEqualSlices(u8, tmpl.fragments[3].expr.ident.name, \"world\");\n\n        const out = try tmpl.bufPrint(&out_buf, .{ .hello = \"1\", .world = \"2\" });\n        testing.expectEqualSlices(u8, out, \"1 2\");\n    }\n}\n\ntest \"escapes\" {\n    const t = Template(\"\\\\{{\\\\%0\\\\%}\\\\}\");\n    // for (t.fragments) |frag| std.debug.warn(\"frag {}\\n\", .{frag});\n    testing.expectEqual(t.fragments.len, 3);\n    testing.expect(Stmt.isLiteral(t.fragments[0]));\n    testing.expectEqualSlices(u8, t.fragments[0].expr.literal, \"\\\\{\");\n    testing.expect(Stmt.isIdent(t.fragments[1]));\n    testing.expectEqualSlices(u8, t.fragments[1].expr.ident.name, \"\\\\%0\\\\%\");\n    testing.expect(Stmt.isLiteral(t.fragments[2]));\n    testing.expectEqualSlices(u8, t.fragments[2].expr.literal, \"\\\\}\");\n}\n\ntest \"allocPrint\" {\n    const tmpl = Template(\"hello{0}world\");\n    testing.expectEqual(tmpl.fragments.len, 3);\n    testing.expectEqualSlices(u8, tmpl.fragments[0].expr.literal, \"hello\");\n    testing.expectEqualSlices(u8, tmpl.fragments[2].expr.literal, \"world\");\n    testing.expectEqualSlices(u8, tmpl.fragments[1].expr.ident.name, \"0\");\n\n    const out1 = try tmpl.allocPrint(allocator, .{\" \"});\n    defer allocator.free(out1);\n    testing.expectEqualSlices(u8, out1, \"hello world\");\n\n    const out2 = try tmpl.allocPrint(allocator, .{\"\\n\"});\n    defer allocator.free(out2);\n    testing.expectEqualSlices(u8, out2, \"hello\\nworld\");\n}\n\ntest \"basic parse ast\" {\n    var out_buf: [1000]u8 = undefined;\n    {\n        const tmpl = Template(\"{% for x in range(16) %} {% x %} {% endfor %}\");\n\n        testing.expectEqual(tmpl.fragments.len, 7);\n        testing.expect(tmpl.fragments[1] == .block);\n        testing.expect(tmpl.fragments[3] == .block);\n        testing.expect(tmpl.fragments[5] == .block);\n\n        // try tmpl.parse();\n\n        // const out = try tmpl.bufPrint(&out_buf, .{});\n        // testing.expectEqualSlices(u8, \"hello\", out);\n    }\n}\n\n// var poolBuf: [1024]u8 = undefined;\n// var poolAllocator = @import(\"pool_allocator.zig\").PoolAllocator.init(&poolBuf);\ntest \"for loop\" {\n    const t = Template(\n        \\\\{oof}\n        \\\\<html>\n        \\\\<body>\n        \\\\<table>\n        \\\\{% for i in range(16) %}\n        \\\\<tr><td>{i}</td></tr>\n        \\\\{% endfor %}\n        \\\\</table>\n        \\\\</body>\n        \\\\</html>\n        \\\\{rab}\n    );\n\n    for (t.fragments) |l, i| {\n        // const value = switch (l) {\n        //     .literal => |s| s,\n        //     .variable => |s| s,\n        //     .computed => |s| s,\n        // };\n        if (l == .block) {\n            std.debug.print(\"{}: block.body {}\", .{ i, l.block.body });\n        } else std.debug.print(\"{}: {}\\n\", .{ i, l });\n    }\n    testing.expectEqual(t.fragments.len, 11);\n    testing.expect(Stmt.isLiteral(t.fragments[0]));\n    testing.expectEqual(t.fragments[0].expr.literal.len, 0);\n    testing.expect(Stmt.isIdent(t.fragments[1]));\n    testing.expectEqualSlices(u8, t.fragments[1].expr.ident.name, \"oof\");\n    testing.expect(t.fragments[3] == .block);\n    testing.expect(Stmt.isLiteral(t.fragments[t.fragments.len - 1]));\n    testing.expectEqual(t.fragments[t.fragments.len - 1].expr.literal.len, 0);\n}\n"
  }
}


[Trace - 06:46:47 PM] Received notification 'window/showMessage'.
Params: {
  "message": "[notice-main] zls initialized",
  "type": 3
}


[Trace - 06:46:47 PM] Received notification 'window/showMessage'.
Params: {
  "message": "[notice-main] Using offset encoding: utf16\n",
  "type": 3
}


[Trace - 06:46:47 PM] Received notification 'textDocument/publishDiagnostics'.
Params: {
  "diagnostics": [],
  "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig"
}


[Trace - 06:46:53 PM] Sending request 'textDocument/hover - (2)'.
Params: {
  "textDocument": {
    "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig"
  },
  "position": {
    "line": 0,
    "character": 0
  }
}


[Trace - 06:46:53 PM] Received response 'textDocument/hover - (2)' in 0ms.
Result: null


[Trace - 06:46:57 PM] Sending request 'textDocument/hover - (3)'.
Params: {
  "textDocument": {
    "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig"
  },
  "position": {
    "line": 0,
    "character": 0
  }
}


[Trace - 06:46:57 PM] Received response 'textDocument/hover - (3)' in 0ms.
Result: null


[Trace - 06:46:58 PM] Sending request 'textDocument/hover - (4)'.
Params: {
  "textDocument": {
    "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig"
  },
  "position": {
    "line": 0,
    "character": 0
  }
}


[Trace - 06:46:58 PM] Received response 'textDocument/hover - (4)' in 0ms.
Result: null


[Trace - 06:47:35 PM] Sending request 'textDocument/hover - (5)'.
Params: {
  "textDocument": {
    "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig"
  },
  "position": {
    "line": 7,
    "character": 24
  }
}


[Trace - 06:47:35 PM] Received response 'textDocument/hover - (5)' in 1ms.
Result: {
  "contents": {
    "value": "```zig\npub const dir_start = '{'\n```\n",
    "kind": "markdown"
  }
}


[Trace - 06:47:35 PM] Sending request 'textDocument/hover - (6)'.
Params: {
  "textDocument": {
    "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig"
  },
  "position": {
    "line": 10,
    "character": 14
  }
}


[Trace - 06:47:35 PM] Received response 'textDocument/hover - (6)' in 1ms.
Result: {
  "contents": {
    "value": "```zig\nvar result: usize = 0\n```\n",
    "kind": "markdown"
  }
}


[Trace - 06:47:41 PM] Sending request 'textDocument/definition - (7)'.
Params: {
  "textDocument": {
    "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig"
  },
  "position": {
    "line": 14,
    "character": 33
  }
}


[Trace - 06:47:41 PM] Received response 'textDocument/definition - (7)' in 5ms.
Result: {
  "range": {
    "end": {
      "character": 7,
      "line": 1183
    },
    "start": {
      "character": 7,
      "line": 1183
    }
  },
  "uri": "file:///usr/local/zig_lib/std/fmt.zig"
}


[Trace - 06:47:41 PM] Sending request 'textDocument/hover - (8)'.
Params: {
  "textDocument": {
    "uri": "file:///home/travis/Documents/Code/zig/zig-tmpl/src/tmpl.zig"
  },
  "position": {
    "line": 14,
    "character": 33
  }
}


[Trace - 06:47:41 PM] Received response 'textDocument/hover - (8)' in 1ms.
Result: {
  "contents": {
    "value": "```zig\npub fn comptimePrint(comptime fmt: []const u8, args: anytype) *const [count(fmt, args):0]u8\n```\n",
    "kind": "markdown"
  }
}

I do notice something else in the Messages buffer: lsp--workspace-print: Wrong type argument: lsp--workspace, nil

Here is the full output:

For information about GNU Emacs and the GNU system, type C-h C-a.
LSP :: Connected to [zls:12052 status:starting].
LSP :: zls:12052 initialized successfully
LSP :: [notice-main] zls initialized
LSP :: [notice-main] Using offset encoding: utf16

Mark set [3 times]
lsp--workspace-print: Wrong type argument: lsp--workspace, nil
Mark set [3 times]
Error running timer: (wrong-type-argument sequencep #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("uri" "file:///usr/local/zig_lib/std/testing.zig" "range" #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("start" #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("line" 232 "character" 7)) "end" #s(hash-table size 65 test equal rehash-size 1.5 rehash-threshold 0.8125 data ("line" 232 "character" 7)))))))
Beginning of buffer [2 times]
End of buffer

After restarting emacs and enabling toggle-debug-on-error I can't even bring up the right click context menu anymore. Instead I'm seeing this:

Debugger entered--Lisp error: (void-variable dap-ui-menu-items)
  #f(compiled-function (_) #<bytecode 0x1556ebb96ef9>)(nil)
  #f(compiled-function (menu) #<bytecode 0x1556ebb96f45>)(nil)
  x-popup-menu((mouse-3 (#<window 3 on tmpl.zig> 859 (615 . 94) 846317174 nil 859 (34 . 2) nil (3 . 22) (18 . 36))) (keymap (Go\ to\ definition menu-item "Go to definition" lsp-find-definition :enable (lsp--find-workspaces-for "textDocument/definition")) (Find\ references menu-item "Find references" lsp-find-references :enable (lsp--find-workspaces-for "textDocument/references")) (Find\ implementations menu-item "Find implementations" lsp-find-implementation :enable (lsp--find-workspaces-for "textDocument/implementation")) (Find\ declarations menu-item "Find declarations" lsp-find-declaration :enable (lsp--find-workspaces-for "textDocument/declaration")) (Go\ to\ type\ declaration menu-item "Go to type declaration" lsp-find-type-definition :enable (lsp--find-workspaces-for "textDocument/typeDefinition")) (nil menu-item "--") (Describe menu-item "Describe" lsp-describe-thing-at-point) (Code\ action menu-item "Code action" lsp-execute-code-action) (Format menu-item "Format" lsp-format-buffer) (Highlight\ references menu-item "Highlight references" lsp-document-highlight) (Rename menu-item "Rename" lsp-rename :enable (or (lsp--capability :renameProvider) (lsp--registered-capability "textDocument/rename"))) (nil-11 menu-item "--") (Session menu-item "Session" (keymap "Session" (View\ logs menu-item "View logs" lsp-workspace-show-log) (Describe menu-item "Describe" lsp-describe-session) (Shutdown menu-item "Shutdown" lsp-shutdown-workspace) (Restart menu-item "Restart" lsp-restart-workspace))) (Workspace\ Folders menu-item "Workspace Folders" (keymap "Workspace Folders" (Add menu-item "Add" lsp-workspace-folders-add) (Remove menu-item "Remove" lsp-workspace-folders-remove) (Open menu-item "Open" lsp-workspace-folders-open))) (Toggle\ features menu-item "Toggle features" (keymap "Toggle features" (Lenses menu-item "Lenses" lsp-lens-mode) (Headerline\ breadcrumb menu-item "Headerline breadcrumb" lsp-headerline-breadcrumb-mode) (Modeline\ code\ actions menu-item "Modeline code actions" lsp-modeline-code-actions-mode) (Modeline\ diagnostics menu-item "Modeline diagnostics" lsp-modeline-diagnostics-mode))) (nil-15 menu-item "---") (Debug menu-item "Debug" nil :filter #f(compiled-function (menu) #<bytecode 0x1556ebb96f45>) :enable (bound-and-true-p dap-ui-mode))))
  lsp-mouse-click((mouse-3 (#<window 3 on tmpl.zig> 859 (615 . 94) 846317174 nil 859 (34 . 2) nil (3 . 22) (18 . 36))))
  funcall-interactively(lsp-mouse-click (mouse-3 (#<window 3 on tmpl.zig> 859 (615 . 94) 846317174 nil 859 (34 . 2) nil (3 . 22) (18 . 36))))
  call-interactively(lsp-mouse-click nil nil)
  command-execute(lsp-mouse-click)

I will mark this issue as a bug for now. It seems like the dependency graph is some how mess up... in a weird way. Thanks for reporting these detail logs to us! We greatly appreciated! 馃憤

Thanks for your attention. Hope we can get to the bottom of this.

It seems like the dependency graph is some how mess up... in a weird way.

@jcs090218 I made the quick patch that's in my branch above. But I really did the fastest thing to make the error go away. lsp-mode does appear to be working from my end, but perhaps I just covered over the problem and things are still broken underneath.

Anyway, maybe you can have a look and see if this quick fix is enough. Otherwise, in the meantime, I'm using it locally.

Anyway, maybe you can have a look and see if this quick fix is enough. Otherwise, in the meantime, I'm using it locally.

Definitely! I have made a PR for this here #2276. We would just need 1 people to review and approve before I can merge this.

Thanks for the patch, and hopefully we can get to this quickly!

@shajra @travisstaloch The quick fix #2276 is merged! Let me know if there is any other issue! Thank you! :)

Thanks! Good to hear. So if i just reinstall lsp-mode from melpa will this pr be included? Or do i need to somehow install 'from source'. Sorry, I'm still pretty new to emacs. :man_shrugging:

Thanks! Good to hear. So if i just reinstall lsp-mode from melpa will this pr be included?

No worries! You can just install through melpa once melpa has updated the package status. The package status can be check here. You just to make sure the timestamp matches to the latest commit.

Thanks a lot for your help @jcs090218 and @shajra. I was able to use goto definition after installing the latest version of lsp-mode and lsp-ui. :+1: It seems to work pretty well although I've only just tested it a few times. Closing the issue for now.

Here is a minimal configuration I used:

(require 'package)
(add-to-list 'package-archives '("melpa" . "http://melpa.org/packages/"))
(package-initialize)

(require 'use-package)

(use-package lsp-mode
  :commands lsp
  :hook ((zig-mode) . lsp)
  :bind (:map lsp-mode-map
              ;; ("TAB" . completion-at-point)
          ))

(use-package lsp-ui
  :hook (lsp-mode . lsp-ui-mode)
  :config
  (setq lsp-ui-sideline-enable t)
  (setq lsp-ui-sideline-show-hover nil)
  (setq lsp-ui-doc-position 'bottom)
  (lsp-ui-doc-show))

(add-hook 'after-init-hook 'global-company-mode)

(require 'lsp)
(add-to-list 'lsp-language-id-configuration '(zig-mode . "zig"))
(lsp-register-client
  (make-lsp-client
    :new-connection (lsp-stdio-connection "/path/to/zls/zls")
    :major-modes '(zig-mode)
    :server-id 'zls))
Was this page helpful?
0 / 5 - 0 ratings