helix-editor / helix

A post-modern modal text editor.
https://helix-editor.com
Mozilla Public License 2.0
31.15k stars 2.3k forks source link

Completion replace not fully replacing when in macro string literal #11010

Closed RoloEdits closed 1 week ago

RoloEdits commented 1 week ago

Summary

When trying to add the with attribute for serde, the completion menu popped up, but when selected, the replacement was off by 1 character; the first remained.

Not sure if its related but #10689 also seems to be an off-by-one, with that pointing to #10279 that was a fix for an off-by-one.

Reproduction Steps

![helix_auto_complete_in_string](https://github.com/helix-editor/helix/assets/12489689/a5c9f52e-4bea-48d5-9c4f-f839e428e0de) ```toml completion-replace = true ``` ```toml [dependencies] serde = { version = "1", features = ["derive"]} chrono ={ version = "0.4", features = ["serde"]} ``` ```rust use chrono::serde::ts_milliseconds; use chrono::{DateTime, Utc}; use serde::Deserialize; #[derive(Deserialize)] struct A { #[serde(with = "tts_milliseconds")] time: DateTime, } fn main() { println!("Hello, world!"); } ``` ### Helix log
~/.cache/helix/helix.log ```log 2024-06-21T15:55:44.186 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","id":11,"result":[]} 2024-06-21T15:55:44.186 helix_lsp::transport [INFO] rust-analyzer <- [] 2024-06-21T15:55:44.186 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 0 2024-06-21T15:55:44.452 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 0 2024-06-21T15:55:44.516 helix_term::application [DEBUG] received editor event: IdleTimer 2024-06-21T15:55:44.610 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"completionItem/resolve","params":{"additionalTextEdits":[],"deprecated":false,"documentation":{"kind":"markdown","value":"Ser/de to/from timestamps in milliseconds\n\nIntended for use with `serde`s `with` attribute.\n\n# Example\n\n```rust\nuse chrono::serde::ts_milliseconds;\n#[derive(Deserialize, Serialize)]\nstruct S {\n #[serde(with = \"ts_milliseconds\")]\n time: DateTime,\n}\n\nlet time = NaiveDate::from_ymd_opt(2018, 5, 17)\n .unwrap()\n .and_hms_milli_opt(02, 04, 59, 918)\n .unwrap()\n .and_utc();\nlet my_s = S { time: time.clone() };\n\nlet as_string = serde_json::to_string(&my_s)?;\nassert_eq!(as_string, r#\"{\"time\":1526522699918}\"#);\nlet my_s: S = serde_json::from_str(&as_string)?;\nassert_eq!(my_s.time, time);\n```"},"filterText":"ts_milliseconds","kind":9,"label":"ts_milliseconds","sortText":"ffffffef","textEdit":{"insert":{"end":{"character":21,"line":6},"start":{"character":21,"line":6}},"newText":"ts_milliseconds","replace":{"end":{"character":21,"line":6},"start":{"character":21,"line":6}}}},"id":12} 2024-06-21T15:55:44.611 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","id":12,"result":{"label":"ts_milliseconds","kind":9,"documentation":{"kind":"markdown","value":"Ser/de to/from timestamps in milliseconds\n\nIntended for use with `serde`s `with` attribute.\n\n# Example\n\n```rust\nuse chrono::serde::ts_milliseconds;\n#[derive(Deserialize, Serialize)]\nstruct S {\n #[serde(with = \"ts_milliseconds\")]\n time: DateTime,\n}\n\nlet time = NaiveDate::from_ymd_opt(2018, 5, 17)\n .unwrap()\n .and_hms_milli_opt(02, 04, 59, 918)\n .unwrap()\n .and_utc();\nlet my_s = S { time: time.clone() };\n\nlet as_string = serde_json::to_string(&my_s)?;\nassert_eq!(as_string, r#\"{\"time\":1526522699918}\"#);\nlet my_s: S = serde_json::from_str(&as_string)?;\nassert_eq!(my_s.time, time);\n```"},"deprecated":false,"sortText":"ffffffef","filterText":"ts_milliseconds","textEdit":{"newText":"ts_milliseconds","insert":{"start":{"line":6,"character":21},"end":{"line":6,"character":21}},"replace":{"start":{"line":6,"character":21},"end":{"line":6,"character":21}}},"additionalTextEdits":[]}} 2024-06-21T15:55:44.611 helix_lsp::transport [INFO] rust-analyzer <- {"additionalTextEdits":[],"deprecated":false,"documentation":{"kind":"markdown","value":"Ser/de to/from timestamps in milliseconds\n\nIntended for use with `serde`s `with` attribute.\n\n# Example\n\n```rust\nuse chrono::serde::ts_milliseconds;\n#[derive(Deserialize, Serialize)]\nstruct S {\n #[serde(with = \"ts_milliseconds\")]\n time: DateTime,\n}\n\nlet time = NaiveDate::from_ymd_opt(2018, 5, 17)\n .unwrap()\n .and_hms_milli_opt(02, 04, 59, 918)\n .unwrap()\n .and_utc();\nlet my_s = S { time: time.clone() };\n\nlet as_string = serde_json::to_string(&my_s)?;\nassert_eq!(as_string, r#\"{\"time\":1526522699918}\"#);\nlet my_s: S = serde_json::from_str(&as_string)?;\nassert_eq!(my_s.time, time);\n```"},"filterText":"ts_milliseconds","kind":9,"label":"ts_milliseconds","sortText":"ffffffef","textEdit":{"insert":{"end":{"character":21,"line":6},"start":{"character":21,"line":6}},"newText":"ts_milliseconds","replace":{"end":{"character":21,"line":6},"start":{"character":21,"line":6}}}} 2024-06-21T15:55:44.611 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 0 2024-06-21T15:55:44.764 helix_lsp::transport [INFO] typos-language-server -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"use chrono::serde::ts_milliseconds;\nuse chrono::{DateTime, Utc};\nuse serde::Deserialize;\n\n#[derive(Deserialize)]\nstruct A {\n #[serde(with = \"t\")]\n time: DateTime,\n}\n\nfn main() {\n println!(\"Hello, world!\");\n}\n"}],"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs","version":3}}} 2024-06-21T15:55:44.764 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"range":{"end":{"character":22,"line":6},"start":{"character":21,"line":6}},"text":""}],"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs","version":3}}} 2024-06-21T15:55:44.764 helix_lsp::transport [INFO] typos-language-server -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"text":"use chrono::serde::ts_milliseconds;\nuse chrono::{DateTime, Utc};\nuse serde::Deserialize;\n\n#[derive(Deserialize)]\nstruct A {\n #[serde(with = \"tts_milliseconds\")]\n time: DateTime,\n}\n\nfn main() {\n println!(\"Hello, world!\");\n}\n"}],"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs","version":4}}} 2024-06-21T15:55:44.764 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"textDocument/didChange","params":{"contentChanges":[{"range":{"end":{"character":21,"line":6},"start":{"character":21,"line":6}},"text":"ts_milliseconds"}],"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs","version":4}}} 2024-06-21T15:55:44.764 helix_lsp::transport [INFO] typos-language-server <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///D:/temp/helix-completion-replace/src/main.rs","version":3}} 2024-06-21T15:55:44.764 helix_lsp::transport [INFO] typos-language-server <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"diagnostics":[],"uri":"file:///D:/temp/helix-completion-replace/src/main.rs","version":4}} 2024-06-21T15:55:44.765 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 1 2024-06-21T15:55:44.765 helix_term::application [DEBUG] received editor event: LanguageServerMessage((LanguageServerId(1v1), Notification(Notification { jsonrpc: Some(V2), method: "textDocument/publishDiagnostics", params: Map({"diagnostics": Array [], "uri": String("file:///D:/temp/helix-completion-replace/src/main.rs"), "version": Number(3)}) }))) 2024-06-21T15:55:44.766 helix_term::application [INFO] Version (3) is out of date for "D:\\temp\\helix-completion-replace\\src\\main.rs" (expected (4), dropping PublishDiagnostic notification 2024-06-21T15:55:44.766 helix_term::application [DEBUG] received editor event: LanguageServerMessage((LanguageServerId(1v1), Notification(Notification { jsonrpc: Some(V2), method: "textDocument/publishDiagnostics", params: Map({"diagnostics": Array [], "uri": String("file:///D:/temp/helix-completion-replace/src/main.rs"), "version": Number(4)}) }))) 2024-06-21T15:55:44.801 helix_term::application [DEBUG] received editor event: Redraw 2024-06-21T15:55:44.801 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 1 2024-06-21T15:55:44.816 helix_term::application [DEBUG] received editor event: IdleTimer 2024-06-21T15:55:44.816 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"textDocument/inlayHint","params":{"range":{"end":{"character":0,"line":13},"start":{"character":0,"line":0}},"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs"}},"id":13} 2024-06-21T15:55:44.816 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","id":13,"result":[]} 2024-06-21T15:55:44.816 helix_lsp::transport [INFO] rust-analyzer <- [] 2024-06-21T15:55:44.817 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 1 2024-06-21T15:55:44.895 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"textDocument/signatureHelp","params":{"position":{"character":36,"line":6},"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs"}},"id":14} 2024-06-21T15:55:44.895 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","id":14,"result":{"signatures":[{"label":"struct __DeserializeWith { value: DateTime, phantom: PhantomData, lifetime: PhantomData<&()> }","parameters":[{"label":[27,47]},{"label":[49,72]},{"label":[74,100]}],"activeParameter":0}],"activeSignature":0,"activeParameter":0}} 2024-06-21T15:55:44.895 helix_lsp::transport [INFO] rust-analyzer <- {"activeParameter":0,"activeSignature":0,"signatures":[{"activeParameter":0,"label":"struct __DeserializeWith { value: DateTime, phantom: PhantomData, lifetime: PhantomData<&()> }","parameters":[{"label":[27,47]},{"label":[49,72]},{"label":[74,100]}]}]} 2024-06-21T15:55:44.896 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 1 2024-06-21T15:55:44.896 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 1 2024-06-21T15:55:45.713 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 2 2024-06-21T15:55:45.777 helix_term::application [DEBUG] received editor event: IdleTimer 2024-06-21T15:55:46.234 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 2 2024-06-21T15:55:46.295 helix_term::application [DEBUG] received editor event: IdleTimer 2024-06-21T15:55:46.376 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 2 2024-06-21T15:55:46.460 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 2 2024-06-21T15:55:46.460 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"textDocument/formatting","params":{"options":{"insertSpaces":true,"tabSize":4},"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs"}},"id":15} 2024-06-21T15:55:46.515 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","id":15,"result":null} 2024-06-21T15:55:46.515 helix_lsp::transport [INFO] rust-analyzer <- null 2024-06-21T15:55:46.515 helix_view::document [DEBUG] submitting save of doc 'Some("D:\\temp\\helix-completion-replace\\src\\main.rs")' 2024-06-21T15:55:46.516 helix_view::document [DEBUG] id 2 modified - last saved: 0, current: 2 2024-06-21T15:55:46.517 helix_view::document [ERROR] Failed to copy metadata on write: The operation completed successfully. (os error 0) 2024-06-21T15:55:46.518 helix_term::application [DEBUG] received editor event: DocumentSaved(Ok(DocumentSavedEvent { revision: 2, doc_id: DocumentId(2), path: "D:\\temp\\helix-completion-replace\\src\\main.rs", text: ["use chrono::serde::ts_milliseconds;\nuse chrono::{DateTime, Utc};\nuse serde::Deserialize;\n\n#[derive(Deserialize)]\nstruct A {\n #[serde(with = \"tts_milliseconds\")]\n time: DateTime,\n}\n\nfn main() {\n println!(\"Hello, world!\");\n}\n"] })) 2024-06-21T15:55:46.518 helix_term::application [DEBUG] document Some("D:\\temp\\helix-completion-replace\\src\\main.rs") saved with revision 2 2024-06-21T15:55:46.518 helix_view::document [DEBUG] doc 2 revision updated 0 -> 2 2024-06-21T15:55:46.518 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"textDocument/didSave","params":{"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs"}}} 2024-06-21T15:55:46.518 helix_lsp::transport [INFO] typos-language-server -> {"jsonrpc":"2.0","method":"textDocument/didSave","params":{"textDocument":{"uri":"file:///D:/temp/helix-completion-replace/src/main.rs"}}} 2024-06-21T15:55:46.518 helix_lsp::file_event [DEBUG] Received file event for "D:\\temp\\helix-completion-replace\\src\\main.rs" 2024-06-21T15:55:46.518 helix_lsp::file_event [DEBUG] Sending didChangeWatchedFiles notification to client 'rust-analyzer' 2024-06-21T15:55:46.518 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"workspace/didChangeWatchedFiles","params":{"changes":[{"type":2,"uri":"file:///D:/temp/helix-completion-replace/src/main.rs"}]}} 2024-06-21T15:55:46.518 helix_view::editor [DEBUG] editor status: 'src\main.rs' written, 14L 237B 2024-06-21T15:55:46.519 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:46.626 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","id":23,"method":"window/workDoneProgress/create","params":{"token":"rust-analyzer/flycheck/0"}} 2024-06-21T15:55:46.626 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","method":"$/progress","params":{"token":"rust-analyzer/flycheck/0","value":{"kind":"begin","title":"cargo clippy","cancellable":true}}} 2024-06-21T15:55:46.626 helix_term::application [DEBUG] received editor event: LanguageServerMessage((LanguageServerId(2v1), MethodCall(MethodCall { jsonrpc: Some(V2), method: "window/workDoneProgress/create", params: Map({"token": String("rust-analyzer/flycheck/0")}), id: Num(23) }))) 2024-06-21T15:55:46.626 helix_term::application [DEBUG] received editor event: LanguageServerMessage((LanguageServerId(2v1), Notification(Notification { jsonrpc: Some(V2), method: "$/progress", params: Map({"token": String("rust-analyzer/flycheck/0"), "value": Object {"cancellable": Bool(true), "kind": String("begin"), "title": String("cargo clippy")}}) }))) 2024-06-21T15:55:46.626 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","result":null,"id":23} 2024-06-21T15:55:46.626 helix_view::editor [DEBUG] editor status: [rust-analyzer/flycheck/0] cargo clippy 2024-06-21T15:55:46.673 helix_term::application [DEBUG] received editor event: Redraw 2024-06-21T15:55:46.674 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:46.744 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///d:/temp/helix-completion-replace/src/main.rs","diagnostics":[{"range":{"start":{"line":0,"character":4},"end":{"line":0,"character":34}},"severity":2,"code":"unused_imports","source":"rustc","message":"unused import: `chrono::serde::ts_milliseconds`\n`#[warn(unused_imports)]` on by default","relatedInformation":[{"location":{"uri":"file:///d:/temp/helix-completion-replace/src/main.rs","range":{"start":{"line":0,"character":0},"end":{"line":1,"character":0}}},"message":"remove the whole `use` item"}],"tags":[1],"data":{"rendered":"warning: unused import: `chrono::serde::ts_milliseconds`\n --> src/main.rs:1:5\n |\n1 | use chrono::serde::ts_milliseconds;\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = note: `#[warn(unused_imports)]` on by default\n\n"}},{"range":{"start":{"line":0,"character":0},"end":{"line":1,"character":0}},"severity":4,"code":"unused_imports","source":"rustc","message":"remove the whole `use` item","relatedInformation":[{"location":{"uri":"file:///d:/temp/helix-completion-replace/src/main.rs","range":{"start":{"line":0,"character":4},"end":{"line":0,"character":34}}},"message":"original diagnostic"}]}],"version":4}} 2024-06-21T15:55:46.744 helix_term::application [DEBUG] received editor event: LanguageServerMessage((LanguageServerId(2v1), Notification(Notification { jsonrpc: Some(V2), method: "textDocument/publishDiagnostics", params: Map({"diagnostics": Array [Object {"code": String("unused_imports"), "data": Object {"rendered": String("warning: unused import: `chrono::serde::ts_milliseconds`\n --> src/main.rs:1:5\n |\n1 | use chrono::serde::ts_milliseconds;\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = note: `#[warn(unused_imports)]` on by default\n\n")}, "message": String("unused import: `chrono::serde::ts_milliseconds`\n`#[warn(unused_imports)]` on by default"), "range": Object {"end": Object {"character": Number(34), "line": Number(0)}, "start": Object {"character": Number(4), "line": Number(0)}}, "relatedInformation": Array [Object {"location": Object {"range": Object {"end": Object {"character": Number(0), "line": Number(1)}, "start": Object {"character": Number(0), "line": Number(0)}}, "uri": String("file:///d:/temp/helix-completion-replace/src/main.rs")}, "message": String("remove the whole `use` item")}], "severity": Number(2), "source": String("rustc"), "tags": Array [Number(1)]}, Object {"code": String("unused_imports"), "message": String("remove the whole `use` item"), "range": Object {"end": Object {"character": Number(0), "line": Number(1)}, "start": Object {"character": Number(0), "line": Number(0)}}, "relatedInformation": Array [Object {"location": Object {"range": Object {"end": Object {"character": Number(34), "line": Number(0)}, "start": Object {"character": Number(4), "line": Number(0)}}, "uri": String("file:///d:/temp/helix-completion-replace/src/main.rs")}, "message": String("original diagnostic")}], "severity": Number(4), "source": String("rustc")}], "uri": String("file:///d:/temp/helix-completion-replace/src/main.rs"), "version": Number(4)}) }))) 2024-06-21T15:55:46.754 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","method":"textDocument/publishDiagnostics","params":{"uri":"file:///d:/temp/helix-completion-replace/src/main.rs","diagnostics":[{"range":{"start":{"line":0,"character":4},"end":{"line":0,"character":34}},"severity":2,"code":"unused_imports","source":"rustc","message":"unused import: `chrono::serde::ts_milliseconds`\n`#[warn(unused_imports)]` on by default","relatedInformation":[{"location":{"uri":"file:///d:/temp/helix-completion-replace/src/main.rs","range":{"start":{"line":0,"character":0},"end":{"line":1,"character":0}}},"message":"remove the whole `use` item"}],"tags":[1],"data":{"rendered":"warning: unused import: `chrono::serde::ts_milliseconds`\n --> src/main.rs:1:5\n |\n1 | use chrono::serde::ts_milliseconds;\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = note: `#[warn(unused_imports)]` on by default\n\n"}},{"range":{"start":{"line":0,"character":0},"end":{"line":1,"character":0}},"severity":4,"code":"unused_imports","source":"rustc","message":"remove the whole `use` item","relatedInformation":[{"location":{"uri":"file:///d:/temp/helix-completion-replace/src/main.rs","range":{"start":{"line":0,"character":4},"end":{"line":0,"character":34}}},"message":"original diagnostic"}]},{"range":{"start":{"line":6,"character":19},"end":{"line":6,"character":37}},"severity":1,"code":"E0433","codeDescription":{"href":"https://doc.rust-lang.org/error-index.html#E0433"},"source":"rustc","message":"failed to resolve: use of undeclared crate or module `tts_milliseconds`\nuse of undeclared crate or module `tts_milliseconds`","data":{"rendered":"error[E0433]: failed to resolve: use of undeclared crate or module `tts_milliseconds`\n --> src/main.rs:7:20\n |\n7 | #[serde(with = \"tts_milliseconds\")]\n | ^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `tts_milliseconds`\n\n"}}],"version":4}} 2024-06-21T15:55:46.754 helix_term::application [DEBUG] received editor event: LanguageServerMessage((LanguageServerId(2v1), Notification(Notification { jsonrpc: Some(V2), method: "textDocument/publishDiagnostics", params: Map({"diagnostics": Array [Object {"code": String("unused_imports"), "data": Object {"rendered": String("warning: unused import: `chrono::serde::ts_milliseconds`\n --> src/main.rs:1:5\n |\n1 | use chrono::serde::ts_milliseconds;\n | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n |\n = note: `#[warn(unused_imports)]` on by default\n\n")}, "message": String("unused import: `chrono::serde::ts_milliseconds`\n`#[warn(unused_imports)]` on by default"), "range": Object {"end": Object {"character": Number(34), "line": Number(0)}, "start": Object {"character": Number(4), "line": Number(0)}}, "relatedInformation": Array [Object {"location": Object {"range": Object {"end": Object {"character": Number(0), "line": Number(1)}, "start": Object {"character": Number(0), "line": Number(0)}}, "uri": String("file:///d:/temp/helix-completion-replace/src/main.rs")}, "message": String("remove the whole `use` item")}], "severity": Number(2), "source": String("rustc"), "tags": Array [Number(1)]}, Object {"code": String("unused_imports"), "message": String("remove the whole `use` item"), "range": Object {"end": Object {"character": Number(0), "line": Number(1)}, "start": Object {"character": Number(0), "line": Number(0)}}, "relatedInformation": Array [Object {"location": Object {"range": Object {"end": Object {"character": Number(34), "line": Number(0)}, "start": Object {"character": Number(4), "line": Number(0)}}, "uri": String("file:///d:/temp/helix-completion-replace/src/main.rs")}, "message": String("original diagnostic")}], "severity": Number(4), "source": String("rustc")}, Object {"code": String("E0433"), "codeDescription": Object {"href": String("https://doc.rust-lang.org/error-index.html#E0433")}, "data": Object {"rendered": String("error[E0433]: failed to resolve: use of undeclared crate or module `tts_milliseconds`\n --> src/main.rs:7:20\n |\n7 | #[serde(with = \"tts_milliseconds\")]\n | ^^^^^^^^^^^^^^^^^^ use of undeclared crate or module `tts_milliseconds`\n\n")}, "message": String("failed to resolve: use of undeclared crate or module `tts_milliseconds`\nuse of undeclared crate or module `tts_milliseconds`"), "range": Object {"end": Object {"character": Number(37), "line": Number(6)}, "start": Object {"character": Number(19), "line": Number(6)}}, "severity": Number(1), "source": String("rustc")}], "uri": String("file:///d:/temp/helix-completion-replace/src/main.rs"), "version": Number(4)}) }))) 2024-06-21T15:55:46.781 helix_term::application [DEBUG] received editor event: Redraw 2024-06-21T15:55:46.781 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","method":"$/progress","params":{"token":"rust-analyzer/flycheck/0","value":{"kind":"end"}}} 2024-06-21T15:55:46.782 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:46.782 helix_term::application [DEBUG] received editor event: LanguageServerMessage((LanguageServerId(2v1), Notification(Notification { jsonrpc: Some(V2), method: "$/progress", params: Map({"token": String("rust-analyzer/flycheck/0"), "value": Object {"kind": String("end")}}) }))) 2024-06-21T15:55:46.830 helix_term::application [DEBUG] received editor event: Redraw 2024-06-21T15:55:46.830 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:47.986 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:49.506 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:49.764 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:49.816 helix_term::application [DEBUG] received editor event: IdleTimer 2024-06-21T15:55:50.164 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:50.227 helix_term::application [DEBUG] received editor event: IdleTimer 2024-06-21T15:55:50.346 helix_term::commands::typed [DEBUG] quitting... 2024-06-21T15:55:50.347 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:50.439 helix_term::commands::typed [DEBUG] quitting... 2024-06-21T15:55:50.439 helix_view::document [DEBUG] id 2 modified - last saved: 2, current: 2 2024-06-21T15:55:50.439 helix_term::job [DEBUG] waiting on jobs... 2024-06-21T15:55:50.439 helix_term::job [DEBUG] waiting on jobs... 2024-06-21T15:55:50.439 helix_lsp::file_event [DEBUG] Removing LSP client: 1v1 2024-06-21T15:55:50.439 helix_lsp::transport [INFO] typos-language-server -> {"jsonrpc":"2.0","method":"shutdown","id":1} 2024-06-21T15:55:50.439 helix_lsp::file_event [DEBUG] Removing LSP client: 2v1 2024-06-21T15:55:50.439 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"shutdown","id":16} 2024-06-21T15:55:50.440 helix_lsp::transport [INFO] typos-language-server <- {"jsonrpc":"2.0","result":null,"id":1} 2024-06-21T15:55:50.440 helix_lsp::transport [INFO] rust-analyzer <- {"jsonrpc":"2.0","id":16,"result":null} 2024-06-21T15:55:50.440 helix_lsp::transport [INFO] typos-language-server <- null 2024-06-21T15:55:50.440 helix_lsp::transport [INFO] rust-analyzer <- null 2024-06-21T15:55:50.440 helix_lsp::transport [INFO] typos-language-server -> {"jsonrpc":"2.0","method":"exit"} 2024-06-21T15:55:50.440 helix_lsp::transport [INFO] rust-analyzer -> {"jsonrpc":"2.0","method":"exit"} ```
### Platform WIndows ### Terminal Emulator Alacritty ### Installation Method source ### Helix Version 24.03-218-g9b7dffbd
pascalkuthe commented 1 week ago

this loooks like a rust-analyzer bug. Lsp has two modes of returning completion edits: One simple mode where the lsp has to figure out what text to replace and an explicit mode where the lsp specifies the range.

RA always uses the explicit mode and all the setting does is switch between the two edits. In this case the edit RA provides is simply off by one so it's an off by one bug in rust-analyzer not in helix. Particularly these completions inside derive macros are new so I am not too surprised. It may also be a RA limitation since sered uses string literals.

A better case is you start with a file where the word is partially already written out and enter insertmode (so entirely new completion).

use chrono::serde::ts_milliseconds;
use chrono::{DateTime, Utc};
use serde::Deserialize;

#[derive(Deserialize)]
struct A {
    #[serde(with = "ts_mill")]
    time: DateTime<Utc>,
}

fn main() {
    println!("Hello, world!");
}

it completes ts_milliseconds and you endup with ts_millts_milliseconds. This has nothing to do with complteon replace btw. Completion replace is about the remainedr of the word (to the right) not about keeping prefixes around (that would be stupid). Both the insert and replace completion text edit returned by RA are identical and don't replace any text.