emacs-lsp / lsp-mode

Emacs client/library for the Language Server Protocol
https://emacs-lsp.github.io/lsp-mode
GNU General Public License v3.0
4.8k stars 891 forks source link

(error "Marker does not point anywhere") on post-completion #2475

Closed thomasheartman closed 3 years ago

thomasheartman commented 3 years ago

Hi,

I've got an issue with Rust Analyzer's post-completion functions. I previously reported this to Company mode, but was told to take it here.

Describe the bug

When using Rust Analyzer's post-completion functionality, I came across an issue where it seemingly doesn't work unless the previous action removed text from the buffer or there is text following the items to be expanded.

More specifically, given this scenario (inside a function and where | is the cursor):

true.if|

I can trigger company-complete to get the list of completion candidates (which contains a single item). If I try to company-complete-selection, I get an error message saying

company-call-backend-raw: Company: backend company-capf error "Marker does not point anywhere" with args (post-completion if)

However, if I add a character and then delete it, say true.if -> true.ifh -> true.if, expanding the snippet works just fine, expanding to

if true {

}

The same happens if what I delete is elsewhere in the buffer too (such as on a different line) and it doesn't seem to matter what character it is (whitespace or otherwise).

Also, it turns out that as long as I enter any characters after if (e.g. true.ifh) and move the cursor back to before the extra characters, expansions works as expected and removes the remaining characters: true.if|h -> company-complete-selection becomes

if true {

}

If a string follows the if, then it remains intact for some reason. true.if"string" becomes:

if true {

}"string"

To Reproduce

Sample project: https://github.com/thomasheartman/lsp-rust-analyzer-post-completion-issue

The sample project is a fresh rust project (as created by cargo new). In src/main.rs, line 6 is true.if. Expanding this snippet may or may not work based on previous action. It seems to always work if I delete characters before expanding. It never works if I try and expand it just after typing it out.

Expected behavior

I expect the post-completion to work regardless of what my previous action in the buffer was, and especially if I have just typed out the necessary letters for expansion to take place. I expect it to not throw any errors.

Which Language Server did you use Rust Analyzer (as of 2020-11-09).

OS NixOS 20.09

Error callstack

Callstack ``` Debugger entered--Lisp error: (error "Marker does not point anywhere") delete-region(271 #) apply(delete-region (271 #)) lsp-completion--exit-fn(#("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #)) finished #f(compiled-function () #)) apply(lsp-completion--exit-fn (#("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #)) finished #f(compiled-function () #))) #f(compiled-function (&rest args-before) #)(#("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #)) finished) company--capf-post-completion(#("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) #f(compiled-function (command &optional arg &rest args) "`company-mode' backend using `completion-at-point-functions'." (interactive #f(compiled-function () #)) #)(post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) apply(#f(compiled-function (command &optional arg &rest args) "`company-mode' backend using `completion-at-point-functions'." (interactive #f(compiled-function () #)) #) (post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #)))) company-flx-company-capf-advice(#f(compiled-function (command &optional arg &rest args) "`company-mode' backend using `completion-at-point-functions'." (interactive #f(compiled-function () #)) #) post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) apply(company-flx-company-capf-advice #f(compiled-function (command &optional arg &rest args) "`company-mode' backend using `completion-at-point-functions'." (interactive #f(compiled-function () #)) #) (post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #)))) company-capf(post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) apply(company-capf (post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #)))) company-call-backend-raw(post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) apply(company-call-backend-raw (post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #)))) company--force-sync(company-call-backend-raw (post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) company-capf) company-call-backend(post-completion #("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) company-cancel(#("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) company-finish(#("if" 0 2 (face (completions-common-part) lsp-completion-prefix "if" lsp-completion-markers (271 #) lsp-completion-start-point 271 lsp-sort-text nil lsp-completion-item #))) company-complete-selection() my-company-complete-selection-or-first() funcall-interactively(my-company-complete-selection-or-first) call-interactively(my-company-complete-selection-or-first nil nil) command-execute(my-company-complete-selection-or-first) ```
`*lsp-log*` ``` Command "rls" is not present on the path. Command "/home/thomas/.emacs.d/.cache/lsp/rust/rust-analyzer" is present on the path. Command "rls" is not present on the path. Command "/home/thomas/.emacs.d/.cache/lsp/rust/rust-analyzer" is present on the path. Found the following clients for /home/thomas/projects/rust-analyzer-setup/src/main.rs: (server-id rust-analyzer, priority 1) The following clients were selected based on priority: (server-id rust-analyzer, priority 1) Command "rls" is present on the path. Command "/nix/store/99y2l9alga74r3fzd55a8y7nkzw0qzd8-rust-analyzer-unstable-2020-08-24/bin/rust-analyzer" is present on the path. Command "rls" is present on the path. Command "/nix/store/99y2l9alga74r3fzd55a8y7nkzw0qzd8-rust-analyzer-unstable-2020-08-24/bin/rust-analyzer" is present on the path. Found the following clients for /home/thomas/projects/rust-analyzer-setup/src/main.rs: (server-id rls, priority -1), (server-id rust-analyzer, priority 1) The following clients were selected based on priority: (server-id rust-analyzer, priority 1) Creating watch for /home/thomas/projects/rust-analyzer-setup Creating watch for /home/thomas/projects/rust-analyzer-setup/src Command "rls" is present on the path. Command "/nix/store/99y2l9alga74r3fzd55a8y7nkzw0qzd8-rust-analyzer-unstable-2020-08-24/bin/rust-analyzer" is present on the path. Command "rls" is present on the path. Command "/nix/store/99y2l9alga74r3fzd55a8y7nkzw0qzd8-rust-analyzer-unstable-2020-08-24/bin/rust-analyzer" is present on the path. Found the following clients for /home/thomas/projects/lsp-post-completion/src/main.rs: (server-id rls, priority -1), (server-id rust-analyzer, priority 1) The following clients were selected based on priority: (server-id rust-analyzer, priority 1) Creating watch for /home/thomas/projects/lsp-post-completion Creating watch for /home/thomas/projects/lsp-post-completion/src Cancelling textDocument/onTypeFormatting(97) in hook after-change-functions Cancelling textDocument/codeAction(145) in hook after-change-functions Cancelling textDocument/hover(159) in hook after-change-functions Cancelling textDocument/codeAction(158) in hook after-change-functions Cancelling textDocument/hover(176) in hook after-change-functions Cancelling textDocument/hover(206) in hook after-change-functions Cancelling textDocument/hover(211) in hook after-change-functions Cancelling textDocument/codeAction(210) in hook after-change-functions Cancelling textDocument/hover(218) in hook after-change-functions Cancelling textDocument/codeAction(217) in hook after-change-functions Cancelling textDocument/hover(226) in hook after-change-functions Cancelling textDocument/documentHighlight(225) in hook after-change-functions Cancelling textDocument/codeAction(224) in hook after-change-functions Cancelling textDocument/codeAction(327) in hook after-change-functions ```

The lsp-workspace-show-log output was too long to include in this comment. I'll try and put it in a separate comment.

Versions

Reproducing the issue in a clean environment:

I tried reproducing the issue in a clean environment but wasn't able to install the correct major mode. I'm not sure why or what's going on. If there is a simple solution, I'd be more than happy to try again. I've included the error message below.

Install error message ``` Debugger entered--Lisp error: (wrong-type-argument stringp nil) string-match("\\`https?:" nil nil) package--with-response-buffer-1(nil #f(compiled-function () #) :file "rust-mode-20201204.1527.el" :async nil :error-function #f(compiled-function () #) :noerror nil) package-install-from-archive(#s(package-desc :name rust-mode :version (20201204 1527) :summary "A major emacs mode for editing Rust source code" :reqs ((emacs (25 1))) :kind single :archive "melpa" :dir nil :extras ((:commit . "c5c7ed31a2e1106ab4835b135618a34570796dc7") (:authors ("Mozilla")) (:maintainer "Mozilla") (:keywords "languages") (:url . "https://github.com/rust-lang/rust-mode")) :signed nil)) mapc(package-install-from-archive (#s(package-desc :name rust-mode :version (20201204 1527) :summary "A major emacs mode for editing Rust source code" :reqs ((emacs (25 1))) :kind single :archive "melpa" :dir nil :extras ((:commit . "c5c7ed31a2e1106ab4835b135618a34570796dc7") (:authors ("Mozilla")) (:maintainer "Mozilla") (:keywords "languages") (:url . "https://github.com/rust-lang/rust-mode")) :signed nil))) package-download-transaction((#s(package-desc :name rust-mode :version (20201204 1527) :summary "A major emacs mode for editing Rust source code" :reqs ((emacs (25 1))) :kind single :archive "melpa" :dir nil :extras ((:commit . "c5c7ed31a2e1106ab4835b135618a34570796dc7") (:authors ("Mozilla")) (:maintainer "Mozilla") (:keywords "languages") (:url . "https://github.com/rust-lang/rust-mode")) :signed nil))) package-install(rust-mode nil) funcall-interactively(package-install rust-mode nil) call-interactively(package-install record nil) command-execute(package-install record) execute-extended-command(nil "package-install" "package-inst") funcall-interactively(execute-extended-command nil "package-install" "package-inst") call-interactively(execute-extended-command nil nil) command-execute(execute-extended-command) ```
thomasheartman commented 3 years ago
`lsp-show-workspace-log` ``` [Trace - 12:55:32 PM] Sending request 'initialize - (2)'. Params: { "processId": null, "rootPath": "/home/thomas/projects/lsp-post-completion", "clientInfo": { "name": "emacs", "version": "GNU Emacs 27.1 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.24.21, cairo version 1.16.0)" }, "rootUri": "file:///home/thomas/projects/lsp-post-completion", "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 }, "experimental": { "snippetTextEdit": true } }, "initializationOptions": { "diagnostics": { "enable": true, "enableExperimental": true, "disabled": [] }, "assist": { "importMergeBehaviour": "full", "importPrefix": "plain" }, "lruCapacity": null, "checkOnSave": { "enable": true, "command": "check", "extraArgs": [], "allTargets": true, "overrideCommand": [] }, "files": { "exclude": [], "watcher": true }, "cargo": { "allFeatures": false, "noDefaultFeatures": false, "features": [], "loadOutDirsFromCheck": false }, "rustfmt": { "extraArgs": [], "overrideCommand": [] }, "inlayHints": { "typeHints": false, "chainingHints": false, "parameterHints": false, "maxLength": null }, "completion": { "addCallParenthesis": true, "addCallArgumentSnippets": true, "postfix": { "enable": true } }, "callInfo": { "full": true }, "procMacro": { "enable": false } }, "workDoneToken": "1" } [Trace - 12:55:32 PM] Received response 'initialize - (2)' in 14ms. Result: { "serverInfo": { "version": "2020-11-09", "name": "rust-analyzer" }, "capabilities": { "workspaceSymbolProvider": true, "typeDefinitionProvider": true, "textDocumentSync": { "save": { }, "openClose": true, "change": 2 }, "signatureHelpProvider": { "triggerCharacters": [ "(", "," ] }, "semanticTokensProvider": { "range": true, "legend": { "tokenTypes": [ "comment", "keyword", "string", "number", "regexp", "operator", "namespace", "type", "struct", "class", "interface", "enum", "enumMember", "typeParameter", "function", "member", "property", "macro", "variable", "parameter", "attribute", "boolean", "builtinType", "escapeSequence", "formatSpecifier", "generic", "lifetime", "punctuation", "selfKeyword", "typeAlias", "union", "unresolvedReference" ], "tokenModifiers": [ "documentation", "declaration", "definition", "static", "abstract", "deprecated", "readonly", "constant", "controlFlow", "injected", "mutable", "consuming", "unsafe", "attribute", "callable" ] }, "full": { "delta": true } }, "selectionRangeProvider": true, "renameProvider": { "prepareProvider": true }, "referencesProvider": true, "implementationProvider": true, "hoverProvider": true, "foldingRangeProvider": true, "experimental": { "ssr": true, "runnables": { "kinds": [ "cargo" ] }, "parentModule": true, "onEnter": true, "joinLines": true }, "documentSymbolProvider": true, "documentOnTypeFormattingProvider": { "moreTriggerCharacter": [ ".", ">" ], "firstTriggerCharacter": "=" }, "documentHighlightProvider": true, "documentFormattingProvider": true, "definitionProvider": true, "completionProvider": { "triggerCharacters": [ ":", "." ] }, "codeLensProvider": { "resolveProvider": true }, "codeActionProvider": { "codeActionKinds": [ "", "quickfix", "refactor", "refactor.extract", "refactor.inline", "refactor.rewrite" ] }, "callHierarchyProvider": true } } [Trace - 12:55:32 PM] Sending notification 'initialized'. Params: { } [Trace - 12:55:32 PM] Sending notification 'textDocument/didOpen'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "languageId": "rust", "version": 0, "text": "fn main() {\n // trying to expand the below line seems to succeed or fail based\n // on recent actions in the current buffer. To expand it, move the\n // cursor to the end of the line and use Rust Analyzer's\n // post-completion function for `expr.if`.\n true.if\n\n println!(\"Hello, world!\");\n}\n" } } [Trace - 12:55:32 PM] Sending request 'textDocument/codeAction - (3)'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs" }, "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } }, "context": { "diagnostics": [] } } [Trace - 12:55:33 PM] Received request 'client/registerCapability - (0). Params: { "registrations": [ { "registerOptions": { "includeText": null, "documentSelector": [ { "pattern": "**/*.rs" }, { "pattern": "**/Cargo.toml" }, { "pattern": "**/Cargo.lock" } ] }, "method": "textDocument/didSave", "id": "textDocument/didSave" } ] } [Trace - 12:55:33 PM] Sending response 'client/registerCapability - (0)'. Processing request took 69ms Params: { "jsonrpc": "2.0", "id": 0, "result": null } [Trace - 12:55:33 PM] Received request 'client/registerCapability - (1). Params: { "registrations": [ { "registerOptions": { "watchers": [ { "globPattern": "/home/thomas/projects/lsp-post-completion/**/*.rs" } ] }, "method": "workspace/didChangeWatchedFiles", "id": "workspace/didChangeWatchedFiles" } ] } [Trace - 12:55:33 PM] Sending response 'client/registerCapability - (1)'. Processing request took 31ms Params: { "jsonrpc": "2.0", "id": 1, "result": null } [Trace - 12:55:33 PM] Received request 'window/workDoneProgress/create - (2). Params: { "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Sending response 'window/workDoneProgress/create - (2)'. Processing request took 0ms Params: { "jsonrpc": "2.0", "id": 2, "result": null } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "title": "roots scanned", "percentage": 0.0, "message": "0/11", "kind": "begin" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 9.090909090909092, "message": "1/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 18.181818181818183, "message": "2/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 27.27272727272727, "message": "3/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 36.36363636363637, "message": "4/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 45.45454545454545, "message": "5/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 54.54545454545454, "message": "6/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 63.63636363636363, "message": "7/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 72.72727272727273, "message": "8/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 81.81818181818183, "message": "9/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 90.9090909090909, "message": "10/11", "kind": "report" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "message": "11/11", "kind": "end" }, "token": "rustAnalyzer/roots scanned" } [Trace - 12:55:33 PM] Received request 'window/workDoneProgress/create - (3). Params: { "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Sending response 'window/workDoneProgress/create - (3)'. Processing request took 0ms Params: { "jsonrpc": "2.0", "id": 3, "result": null } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "title": "indexing", "percentage": 0.0, "kind": "begin" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 0.0, "message": "0/11 (core)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received request 'window/workDoneProgress/create - (4). Params: { "token": "rustAnalyzer/cargo check" } [Trace - 12:55:33 PM] Sending response 'window/workDoneProgress/create - (4)'. Processing request took 0ms Params: { "jsonrpc": "2.0", "id": 4, "result": null } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "title": "cargo check", "kind": "begin" }, "token": "rustAnalyzer/cargo check" } [Trace - 12:55:33 PM] Received notification 'textDocument/publishDiagnostics'. Params: { "version": 0, "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "diagnostics": [ { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" } ] } [Trace - 12:55:33 PM] Received notification 'textDocument/publishDiagnostics'. Params: { "version": 0, "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "diagnostics": [ { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" }, { "source": "rustc", "severity": 1, "relatedInformation": [ { "message": "expected one of 7 possible tokens", "location": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } } } } ], "range": { "start": { "line": 7, "character": 4 }, "end": { "line": 7, "character": 11 } }, "message": "expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `println`\nunexpected token" } ] } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "kind": "end" }, "token": "rustAnalyzer/cargo check" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 9.090909090909092, "message": "1/11 (alloc)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 18.181818181818183, "message": "2/11 (panic_abort)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 27.27272727272727, "message": "3/11 (panic_unwind)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 36.36363636363637, "message": "4/11 (profiler_builtins)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 45.45454545454545, "message": "5/11 (proc_macro)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 54.54545454545454, "message": "6/11 (term)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 63.63636363636363, "message": "7/11 (test)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 72.72727272727273, "message": "8/11 (unwind)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:33 PM] Received notification '$/progress'. Params: { "value": { "percentage": 81.81818181818183, "message": "9/11 (std)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:34 PM] Received notification '$/progress'. Params: { "value": { "percentage": 90.9090909090909, "message": "10/11 (lsp_post_completion)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:34 PM] Received notification '$/progress'. Params: { "value": { "kind": "end" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:34 PM] Received notification 'textDocument/publishDiagnostics'. Params: { "version": 0, "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "diagnostics": [ { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected field name or number" }, { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected SEMICOLON" }, { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 7, "character": 29 }, "end": { "line": 7, "character": 29 } }, "message": "Syntax Error: expected a block" }, { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" }, { "source": "rustc", "severity": 1, "relatedInformation": [ { "message": "expected one of 7 possible tokens", "location": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } } } } ], "range": { "start": { "line": 7, "character": 4 }, "end": { "line": 7, "character": 11 } }, "message": "expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `println`\nunexpected token" } ] } [Trace - 12:55:34 PM] Received response 'textDocument/codeAction - (3)' in 820ms. Result: [] [Trace - 12:55:36 PM] Sending request 'textDocument/codeAction - (4)'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs" }, "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } }, "context": { "diagnostics": [ { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected field name or number" }, { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected SEMICOLON" }, { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" } ] } } [Trace - 12:55:36 PM] Received response 'textDocument/codeAction - (4)' in 8ms. Result: [] [Trace - 12:55:36 PM] Sending request 'textDocument/codeAction - (5)'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs" }, "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } }, "context": { "diagnostics": [ { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected field name or number" }, { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected SEMICOLON" }, { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" } ] } } [Trace - 12:55:36 PM] Received response 'textDocument/codeAction - (5)' in 0ms. Result: [] [Trace - 12:55:37 PM] Sending notification 'textDocument/didChange'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "version": 1 }, "contentChanges": [ { "range": { "start": { "line": 5, "character": 10 }, "end": { "line": 5, "character": 11 } }, "rangeLength": 1, "text": "" } ] } [Trace - 12:55:37 PM] Received request 'window/workDoneProgress/create - (5). Params: { "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Sending response 'window/workDoneProgress/create - (5)'. Processing request took 0ms Params: { "jsonrpc": "2.0", "id": 5, "result": null } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "title": "indexing", "percentage": 0.0, "kind": "begin" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 0.0, "message": "0/11 (core)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 9.090909090909092, "message": "1/11 (alloc)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 45.45454545454545, "message": "5/11 (proc_macro)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 54.54545454545454, "message": "6/11 (term)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 63.63636363636363, "message": "7/11 (test)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 81.81818181818183, "message": "9/11 (std)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 90.9090909090909, "message": "10/11 (lsp_post_completion)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "kind": "end" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification 'textDocument/publishDiagnostics'. Params: { "version": 1, "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "diagnostics": [ { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 10 }, "end": { "line": 5, "character": 10 } }, "message": "Syntax Error: expected SEMICOLON" }, { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" }, { "source": "rustc", "severity": 1, "relatedInformation": [ { "message": "expected one of 7 possible tokens", "location": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } } } } ], "range": { "start": { "line": 7, "character": 4 }, "end": { "line": 7, "character": 11 } }, "message": "expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `println`\nunexpected token" } ] } [Trace - 12:55:37 PM] Sending notification 'textDocument/didChange'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "version": 2 }, "contentChanges": [ { "range": { "start": { "line": 5, "character": 10 }, "end": { "line": 5, "character": 10 } }, "rangeLength": 0, "text": "f" } ] } [Trace - 12:55:37 PM] Received request 'window/workDoneProgress/create - (6). Params: { "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Sending response 'window/workDoneProgress/create - (6)'. Processing request took 0ms Params: { "jsonrpc": "2.0", "id": 6, "result": null } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "title": "indexing", "percentage": 0.0, "kind": "begin" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 81.81818181818183, "message": "9/11 (std)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "percentage": 90.9090909090909, "message": "10/11 (lsp_post_completion)", "kind": "report" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification '$/progress'. Params: { "value": { "kind": "end" }, "token": "rustAnalyzer/indexing" } [Trace - 12:55:37 PM] Received notification 'textDocument/publishDiagnostics'. Params: { "version": 2, "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "diagnostics": [ { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected field name or number" }, { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected SEMICOLON" }, { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 7, "character": 29 }, "end": { "line": 7, "character": 29 } }, "message": "Syntax Error: expected a block" }, { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" }, { "source": "rustc", "severity": 1, "relatedInformation": [ { "message": "expected one of 7 possible tokens", "location": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs", "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } } } } ], "range": { "start": { "line": 7, "character": 4 }, "end": { "line": 7, "character": 11 } }, "message": "expected one of `(`, `.`, `::`, `;`, `?`, `}`, or an operator, found `println`\nunexpected token" } ] } [Trace - 12:55:37 PM] Sending request 'textDocument/completion - (6)'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs" }, "position": { "line": 5, "character": 11 }, "context": { "triggerKind": 1 } } [Trace - 12:55:37 PM] Received response 'textDocument/completion - (6)' in 20ms. Result: [ { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "then_some(${1:t})$0" }, "label": "then_some(…)", "kind": 2, "insertTextFormat": 2, "filterText": "then_some", "documentation": { "value": "Returns `Some(t)` if the `bool` is `true`, or `None` otherwise.\n\n# Examples\n\n```rust\n#![feature(bool_to_option)]\n\nassert_eq!(false.then_some(0), None);\nassert_eq!(true.then_some(0), Some(0));\n```", "kind": "markdown" }, "detail": "pub fn then_some(self, t: T) -> Option", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "then(${1:f})$0" }, "label": "then(…)", "kind": 2, "insertTextFormat": 2, "filterText": "then", "documentation": { "value": "Returns `Some(f())` if the `bool` is `true`, or `None` otherwise.\n\n# Examples\n\n```rust\n#![feature(bool_to_option)]\n\nassert_eq!(false.then(|| 0), None);\nassert_eq!(true.then(|| 0), Some(0));\n```", "kind": "markdown" }, "detail": "pub fn then T>(self, f: F) -> Option", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "into()$0" }, "label": "into()", "kind": 2, "insertTextFormat": 2, "filterText": "into", "documentation": { "value": "Performs the conversion.", "kind": "markdown" }, "detail": "fn into(self) -> T", "deprecated": null, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "max(${1:other})$0" }, "label": "max(…)", "kind": 2, "insertTextFormat": 2, "filterText": "max", "documentation": { "value": "Compares and returns the maximum of two values.\n\nReturns the second argument if the comparison determines them to be equal.\n\n# Examples\n\n```rust\nassert_eq!(2, 1.max(2));\nassert_eq!(2, 2.max(2));\n```", "kind": "markdown" }, "detail": "fn max(self, other: Self) -> Self\nwhere\n Self: Sized,", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "min(${1:other})$0" }, "label": "min(…)", "kind": 2, "insertTextFormat": 2, "filterText": "min", "documentation": { "value": "Compares and returns the minimum of two values.\n\nReturns the first argument if the comparison determines them to be equal.\n\n# Examples\n\n```rust\nassert_eq!(1, 1.min(2));\nassert_eq!(2, 2.min(2));\n```", "kind": "markdown" }, "detail": "fn min(self, other: Self) -> Self\nwhere\n Self: Sized,", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "clamp(${1:min}, ${2:max})$0" }, "label": "clamp(…)", "kind": 2, "insertTextFormat": 2, "filterText": "clamp", "documentation": { "value": "Restrict a value to a certain interval.\n\nReturns `max` if `self` is greater than `max`, and `min` if `self` is\nless than `min`. Otherwise this returns `self`.\n\n# Panics\n\nPanics if `min > max`.\n\n# Examples\n\n```rust\n#![feature(clamp)]\n\nassert!((-3).clamp(-2, 1) == -2);\nassert!(0.clamp(-2, 1) == 0);\nassert!(2.clamp(-2, 1) == 1);\n```", "kind": "markdown" }, "detail": "fn clamp(self, min: Self, max: Self) -> Self\nwhere\n Self: Sized,", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "eq(${1:other})$0" }, "label": "eq(…)", "kind": 2, "insertTextFormat": 2, "filterText": "eq", "documentation": { "value": "This method tests for `self` and `other` values to be equal, and is used\nby `==`.", "kind": "markdown" }, "detail": "fn eq(&self, other: &Rhs) -> bool", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "ne(${1:other})$0" }, "label": "ne(…)", "kind": 2, "insertTextFormat": 2, "filterText": "ne", "documentation": { "value": "This method tests for `!=`.", "kind": "markdown" }, "detail": "fn ne(&self, other: &Rhs) -> bool", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "partial_cmp(${1:other})$0" }, "label": "partial_cmp(…)", "kind": 2, "insertTextFormat": 2, "filterText": "partial_cmp", "documentation": { "value": "This method returns an ordering between `self` and `other` values if one exists.\n\n# Examples\n\n```rust\nuse std::cmp::Ordering;\n\nlet result = 1.0.partial_cmp(&2.0);\nassert_eq!(result, Some(Ordering::Less));\n\nlet result = 1.0.partial_cmp(&1.0);\nassert_eq!(result, Some(Ordering::Equal));\n\nlet result = 2.0.partial_cmp(&1.0);\nassert_eq!(result, Some(Ordering::Greater));\n```\n\nWhen comparison is impossible:\n\n```rust\nlet result = f64::NAN.partial_cmp(&1.0);\nassert_eq!(result, None);\n```", "kind": "markdown" }, "detail": "fn partial_cmp(&self, other: &Rhs) -> Option", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "lt(${1:other})$0" }, "label": "lt(…)", "kind": 2, "insertTextFormat": 2, "filterText": "lt", "documentation": { "value": "This method tests less than (for `self` and `other`) and is used by the `<` operator.\n\n# Examples\n\n```rust\nlet result = 1.0 < 2.0;\nassert_eq!(result, true);\n\nlet result = 2.0 < 1.0;\nassert_eq!(result, false);\n```", "kind": "markdown" }, "detail": "fn lt(&self, other: &Rhs) -> bool", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "le(${1:other})$0" }, "label": "le(…)", "kind": 2, "insertTextFormat": 2, "filterText": "le", "documentation": { "value": "This method tests less than or equal to (for `self` and `other`) and is used by the `<=`\noperator.\n\n# Examples\n\n```rust\nlet result = 1.0 <= 2.0;\nassert_eq!(result, true);\n\nlet result = 2.0 <= 2.0;\nassert_eq!(result, true);\n```", "kind": "markdown" }, "detail": "fn le(&self, other: &Rhs) -> bool", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "gt(${1:other})$0" }, "label": "gt(…)", "kind": 2, "insertTextFormat": 2, "filterText": "gt", "documentation": { "value": "This method tests greater than (for `self` and `other`) and is used by the `>` operator.\n\n# Examples\n\n```rust\nlet result = 1.0 > 2.0;\nassert_eq!(result, false);\n\nlet result = 2.0 > 2.0;\nassert_eq!(result, false);\n```", "kind": "markdown" }, "detail": "fn gt(&self, other: &Rhs) -> bool", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "ge(${1:other})$0" }, "label": "ge(…)", "kind": 2, "insertTextFormat": 2, "filterText": "ge", "documentation": { "value": "This method tests greater than or equal to (for `self` and `other`) and is used by the `>=`\noperator.\n\n# Examples\n\n```rust\nlet result = 2.0 >= 1.0;\nassert_eq!(result, true);\n\nlet result = 2.0 >= 2.0;\nassert_eq!(result, true);\n```", "kind": "markdown" }, "detail": "fn ge(&self, other: &Rhs) -> bool", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "to_owned()$0" }, "label": "to_owned()", "kind": 2, "insertTextFormat": 2, "filterText": "to_owned", "documentation": { "value": "Creates owned data from borrowed data, usually by cloning.\n\n# Examples\n\nBasic usage:\n\n```rust\nlet s: &str = \"a\";\nlet ss: String = s.to_owned();\n\nlet v: &[i32] = &[1, 2];\nlet vv: Vec = v.to_owned();\n```", "kind": "markdown" }, "detail": "fn to_owned(&self) -> Self::Owned", "deprecated": null, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "clone_into(${1:target})$0" }, "label": "clone_into(…)", "kind": 2, "insertTextFormat": 2, "filterText": "clone_into", "documentation": { "value": "Uses borrowed data to replace owned data, usually by cloning.\n\nThis is borrow-generalized version of `Clone::clone_from`.\n\n# Examples\n\nBasic usage:\n\n```rust\nlet mut s: String = String::new();\n\"hello\".clone_into(&mut s);\n\nlet mut v: Vec = Vec::new();\n[1, 2][..].clone_into(&mut v);\n```", "kind": "markdown" }, "detail": "fn clone_into(&self, target: &mut Self::Owned)", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "cmp(${1:other})$0" }, "label": "cmp(…)", "kind": 2, "insertTextFormat": 2, "filterText": "cmp", "documentation": { "value": "This method returns an [`Ordering`] between `self` and `other`.\n\nBy convention, `self.cmp(&other)` returns the ordering matching the expression\n`self other` if true.\n\n# Examples\n\n```rust\nuse std::cmp::Ordering;\n\nassert_eq!(5.cmp(&10), Ordering::Less);\nassert_eq!(10.cmp(&5), Ordering::Greater);\nassert_eq!(5.cmp(&5), Ordering::Equal);\n```", "kind": "markdown" }, "detail": "fn cmp(&self, other: &Self) -> Ordering", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "to_string()$0" }, "label": "to_string()", "kind": 2, "insertTextFormat": 2, "filterText": "to_string", "documentation": { "value": "Converts the given value to a `String`.\n\n# Examples\n\nBasic usage:\n\n```rust\nlet i = 5;\nlet five = String::from(\"5\");\n\nassert_eq!(five, i.to_string());\n```", "kind": "markdown" }, "detail": "fn to_string(&self) -> String", "deprecated": null, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "clone()$0" }, "label": "clone()", "kind": 2, "insertTextFormat": 2, "filterText": "clone", "documentation": { "value": "Returns a copy of the value.\n\n# Examples\n\n```rust\nlet hello = \"Hello\"; // &str implements Clone\n\nassert_eq!(\"Hello\", hello.clone());\n```", "kind": "markdown" }, "detail": "fn clone(&self) -> Self", "deprecated": null, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "assert_receiver_is_total_eq()$0" }, "label": "assert_receiver_is_total_eq()", "kind": 2, "insertTextFormat": 2, "filterText": "assert_receiver_is_total_eq", "detail": "fn assert_receiver_is_total_eq(&self)", "deprecated": null, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "clone_from(${1:source})$0" }, "label": "clone_from(…)", "kind": 2, "insertTextFormat": 2, "filterText": "clone_from", "documentation": { "value": "Performs copy-assignment from `source`.\n\n`a.clone_from(&b)` is equivalent to `a = b.clone()` in functionality,\nbut can be overridden to reuse the resources of `a` to avoid unnecessary\nallocations.", "kind": "markdown" }, "detail": "fn clone_from(&mut self, source: &Self)", "deprecated": null, "command": { "title": "triggerParameterHints", "command": "editor.action.triggerParameterHints" }, "additionalTextEdits": [] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "if true {\n $0\n}" }, "label": "if", "kind": 15, "insertTextFormat": 2, "filterText": "if", "detail": "if expr {}", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "while true {\n $0\n}" }, "label": "while", "kind": 15, "insertTextFormat": 2, "filterText": "while", "detail": "while expr {}", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "!true" }, "label": "not", "kind": 15, "insertTextFormat": 2, "filterText": "not", "detail": "!expr", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "&true" }, "label": "ref", "kind": 15, "insertTextFormat": 2, "filterText": "ref", "detail": "&expr", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "&mut true" }, "label": "refm", "kind": 15, "insertTextFormat": 2, "filterText": "refm", "detail": "&mut expr", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "match true {\n ${1:_} => {$0},\n}" }, "label": "match", "kind": 15, "insertTextFormat": 2, "filterText": "match", "detail": "match expr {}", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "Box::new(true)" }, "label": "box", "kind": 15, "insertTextFormat": 2, "filterText": "box", "detail": "Box::new(expr)", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "Ok(true)" }, "label": "ok", "kind": 15, "insertTextFormat": 2, "filterText": "ok", "detail": "Ok(expr)", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "dbg!(true)" }, "label": "dbg", "kind": 15, "insertTextFormat": 2, "filterText": "dbg", "detail": "dbg!(expr)", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "dbg!(&true)" }, "label": "dbgr", "kind": 15, "insertTextFormat": 2, "filterText": "dbgr", "detail": "dbg!(&expr)", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] }, { "textEdit": { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "newText": "${1}(true)" }, "label": "call", "kind": 15, "insertTextFormat": 2, "filterText": "call", "detail": "function(expr)", "deprecated": null, "additionalTextEdits": [ { "range": { "start": { "line": 5, "character": 4 }, "end": { "line": 5, "character": 9 } }, "newText": "" } ] } ] [Trace - 12:55:38 PM] Sending request 'textDocument/hover - (7)'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs" }, "position": { "line": 5, "character": 11 } } [Trace - 12:55:38 PM] Sending request 'textDocument/codeAction - (8)'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs" }, "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } }, "context": { "diagnostics": [ { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected field name or number" }, { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected SEMICOLON" }, { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" } ] } } [Trace - 12:55:38 PM] Received response 'textDocument/hover - (7)' in 169ms. Result: { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 7, "character": 29 } }, "contents": { "value": "```rust\n()\n```", "kind": "markdown" } } [Trace - 12:55:39 PM] Received response 'textDocument/codeAction - (8)' in 480ms. Result: [] [Trace - 12:55:54 PM] Sending request 'textDocument/codeAction - (9)'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs" }, "range": { "start": { "line": 5, "character": 11 }, "end": { "line": 5, "character": 11 } }, "context": { "diagnostics": [ { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected field name or number" }, { "source": "rust-analyzer", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 9 } }, "message": "Syntax Error: expected SEMICOLON" }, { "source": "rustc", "severity": 1, "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 5, "character": 11 } }, "message": "expected identifier, found keyword `if`\nexpected identifier, found keyword" } ] } } [Trace - 12:55:54 PM] Sending request 'textDocument/hover - (10)'. Params: { "textDocument": { "uri": "file:///home/thomas/projects/lsp-post-completion/src/main.rs" }, "position": { "line": 5, "character": 11 } } [Trace - 12:55:54 PM] Received response 'textDocument/codeAction - (9)' in 19ms. Result: [] [Trace - 12:55:54 PM] Received response 'textDocument/hover - (10)' in 16ms. Result: { "range": { "start": { "line": 5, "character": 9 }, "end": { "line": 7, "character": 29 } }, "contents": { "value": "```rust\n()\n```", "kind": "markdown" } } ```
kiennq commented 3 years ago

I will take a look at this

nbfalcon commented 3 years ago

I've noticed the same error with intelephense when calling ivy-completion-at-point while in company-complete and completing variables.

nbfalcon commented 3 years ago

My error is caused by lsp-completion--clear-cache, specifically the part where it deletes the markers (set-marker nil). Removing it fixes my issue, but that is just a debugging workaround. My issue does seem unrelated though.

thomasheartman commented 3 years ago

@nbfalcon Thanks for the input! I can confirm that that does indeed seem to fix the problem :D What are the implications of removing that (set-marker nil)? Will it cause anything to stop working?

But as you mention, it's not a real fix, but a temporary workaround. I wonder what's causing the issue. Why is the marker being set to nil in the first place?

nbfalcon commented 3 years ago

Nothing will stop working, but the markers won't get cleaned up, which will cause slowdowns until a GC happens. Emacs might quickly become unresponsive if you use auto-complete a lot.

nbfalcon commented 3 years ago

Actually, my issue might not be unrelated: it seems that in both cases, the marker is reused between multiple invocations of lsp-completion-at-point which go trough the cache.

@kiennq have you already started working on this? If not, you may assign this to me, since I may have a headstart in debugging.

kiennq commented 3 years ago

@nbfalcon Sure, please take it (I think you can just change the assignee by yourself).

I'm not being able to repro this on my env so there's not much actionable from me. I wrote that code before expecting we have to invalidate the cache in correct time while the marker is not used anymore. What happens here is that the marker may have been alternated by some other means so it's not become available anymore (anything that modify the buffer before lsp-mode does when apply edit). We need the marker so that the insertion by company-mode (or any other completion rendering framework) can be properly tracked. @nbfalcon @thomasheartman If you can easily (and 100%) repro this problem, can you take the calling stack for that? Evaluate something like this

  (defsubst logme (&rest args)
    "Like `message' with same ARGS but don't echo."
    (let ((inhibit-message t))
      (apply #'message args)))

  (defun log-backtrace (&optional max-depth)
    "Print out `backtrace'."
    (let ((i 5) (bt t) backtraces
          (max-depth (+ 5 (or max-depth 999))))
      (logme "%s" backtraces)
      (while (and bt (< i max-depth))
        (setq bt (backtrace-frame i))
        (setq backtraces (nconc backtraces (list bt)))
        (cl-incf i))
      (->> (mapconcat (lambda (bt) (format "%.100s" (cdr bt)))
                      backtraces
                      "\n")
           (logme "================ Backtrace ================\n%s")))))

After that insert (log-backtrace) on lsp-completion--clear-cache function and repro this problem (the minimal least step repro). The calling trace will be recorded in *Message* buffer.

kiennq commented 3 years ago

I figure out the issue, when there's only one completion item like in this case, company-mode actually cancel the completion (not even doing template expansion) thus invalidate the cache.

thomasheartman commented 3 years ago

Nice one! I checked out the PR and can confirm that this indeed seems to fix the issue I've been having. Thanks!