diff --git a/src/Lean/Server/Utils.lean b/src/Lean/Server/Utils.lean index c980497d0442..01104108baf3 100644 --- a/src/Lean/Server/Utils.lean +++ b/src/Lean/Server/Utils.lean @@ -75,7 +75,10 @@ structure DocumentMeta where uri : Lsp.DocumentUri /-- Version number of the document. Incremented whenever the document is edited. -/ version : Nat - /-- Current text of the document. -/ + /-- + Current text of the document. + It is maintained such that it is normalized using `String.crlfToLf`, which preserves logical line/column numbers. + (Note: we assume that edit operations never split or merge `\r\n` line endings.) -/ text : FileMap /-- Controls when dependencies of the document are built on `textDocument/didOpen` notifications. @@ -98,6 +101,10 @@ def replaceLspRange (text : FileMap) (r : Lsp.Range) (newText : String) : FileMa let «end» := text.lspPosToUtf8Pos r.«end» let pre := text.source.extract 0 start let post := text.source.extract «end» text.source.endPos + -- `pre` and `post` already have normalized line endings, so only `newText` needs its endings normalized. + -- Note: this assumes that editing never separates a `\r\n`. + -- If `pre` ends with `\r` and `newText` begins with `\n`, the result is potentially inaccurate. + -- If this is ever a problem, we could store a second unnormalized FileMap, edit it, and normalize it here. (pre ++ newText.crlfToLf ++ post).toFileMap open IO