From 7ba0ae1f72492629f25c111822be88847a3213f9 Mon Sep 17 00:00:00 2001 From: Marc Huisinga Date: Fri, 5 Sep 2025 10:55:49 +0200 Subject: [PATCH] feat: improve auto-completion performance (#10249) This PR speeds up auto-completion by a factor of ~3.5x through various performance improvements in the language server. On one machine, with `import Mathlib`, completing `i` used to take 3200ms and now instead yields a result in 920ms. Specifically, the following improvements are made: - The watchdog process no longer de-serializes and re-serializes most messages from the file worker before passing them on to the user - a fast partial de-serialization procedure is now used to determine whether the message needs to be de-serialized in full or not. - `escapePart` is optimized to perform better on ASCII strings that do not need escaping. - `Json.compress` is optimized to allocate fewer objects. - A faster JSON compression specifically for completion responses is implemented that skips allocating `Json` altogether. - The JSON compression has been moved to the task where we convert a request response to `Json` so that converting to a string won't block the output task of the FileWorker and so the `Json` value is not marked as multi-threaded when we compress is, which drastically increases the cost of reference-counting. - The JSON representation of the `data?` field of each completion item is optimized. - Both the completion kind and the set of completion tags for each imported completion item is now cached. - The filtering of duplicate completion items is optimized. Other adjustments: - `LT UInt8` and `LE UInt8` are moved to Prelude so that they can be used in `Init.Meta` for the name part escaping fast path. - `Array.usize` is exposed since it was marked as `@[simp]`. --- src/Init/Data/Array/Basic.lean | 4 +- src/Init/Data/ByteArray/Basic.lean | 1 - src/Init/Data/UInt/Basic.lean | 45 - src/Init/Meta.lean | 42 +- src/Init/Prelude.lean | 46 + src/Init/Util.lean | 1 - src/Lean/Data/Json/Printer.lean | 140 ++- src/Lean/Data/Json/Stream.lean | 5 + src/Lean/Data/JsonRpc.lean | 99 ++ src/Lean/Data/Lsp/Communication.lean | 17 +- src/Lean/Data/Lsp/LanguageFeatures.lean | 111 ++ src/Lean/Server/CodeActions/Basic.lean | 6 +- src/Lean/Server/Completion.lean | 42 +- .../Completion/CompletionCollectors.lean | 149 ++- .../Completion/CompletionItemCompression.lean | 128 ++ .../Server/Completion/CompletionItemData.lean | 43 - .../Completion/CompletionResolution.lean | 22 +- .../Completion/EligibleHeaderDecls.lean | 89 +- .../Server/Completion/ImportCompletion.lean | 24 +- src/Lean/Server/FileSource.lean | 61 +- src/Lean/Server/FileWorker.lean | 105 +- .../Server/FileWorker/RequestHandling.lean | 14 +- src/Lean/Server/Requests.lean | 97 +- src/Lean/Server/Watchdog.lean | 229 ++-- tests/lean/interactive/1265.lean.expected.out | 190 +-- tests/lean/interactive/1659.lean.expected.out | 152 ++- tests/lean/interactive/533.lean.expected.out | 18 +- tests/lean/interactive/863.lean.expected.out | 37 +- .../interactive/compHeader.lean.expected.out | 23 +- .../compNamespace.lean.expected.out | 30 +- .../interactive/completion.lean.expected.out | 28 +- .../interactive/completion2.lean.expected.out | 133 +- .../interactive/completion3.lean.expected.out | 100 +- .../interactive/completion4.lean.expected.out | 100 +- .../interactive/completion5.lean.expected.out | 25 +- .../interactive/completion6.lean.expected.out | 93 +- .../interactive/completion7.lean.expected.out | 34 +- .../completionAtPrint.lean.expected.out | 7 +- .../completionCheck.lean.expected.out | 20 +- .../completionDeprecation.lean.expected.out | 104 +- .../completionEOF.lean.expected.out | 7 +- .../completionFallback.lean.expected.out | 84 +- ...mpletionFromExpectedType.lean.expected.out | 10 +- .../completionIStr.lean.expected.out | 25 +- ...completionOpenNamespaces.lean.expected.out | 12 +- .../completionOption.lean.expected.out | 588 ++++----- .../completionPrefixIssue.lean.expected.out | 17 +- .../completionPrivateTypes.lean.expected.out | 13 +- .../completionPrv.lean.expected.out | 64 +- ...pletionStructureInstance.lean.expected.out | 528 +++----- .../completionTactics.lean.expected.out | 1080 ++++------------- .../dotIdCompletion.lean.expected.out | 18 +- .../dottedIdentNotation.lean.expected.out | 42 +- .../editCompletion.lean.expected.out | 7 +- ...orExplanationInteractive.lean.expected.out | 168 +-- .../inWordCompletion.lean.expected.out | 53 +- .../internalNamesIssue.lean.expected.out | 12 +- .../keywordCompletion.lean.expected.out | 65 +- .../lean/interactive/match.lean.expected.out | 42 +- .../matchStxCompletion.lean.expected.out | 25 +- .../travellingCompletions.lean.expected.out | 60 +- 61 files changed, 2249 insertions(+), 3285 deletions(-) create mode 100644 src/Lean/Server/Completion/CompletionItemCompression.lean delete mode 100644 src/Lean/Server/Completion/CompletionItemData.lean diff --git a/src/Init/Data/Array/Basic.lean b/src/Init/Data/Array/Basic.lean index 805768ff9d..77083dab2c 100644 --- a/src/Init/Data/Array/Basic.lean +++ b/src/Init/Data/Array/Basic.lean @@ -10,8 +10,6 @@ public import Init.WFTactics public import Init.Data.Nat.Basic public import Init.Data.Fin.Basic public import Init.Data.UInt.BasicAux -public import Init.Data.Repr -public import Init.Data.ToString.Basic public import Init.GetElem public import Init.Data.List.ToArrayImpl import all Init.Data.List.ToArrayImpl @@ -164,7 +162,7 @@ This is a low-level version of `Array.size` that directly queries the runtime sy representation of arrays. While this is not provable, `Array.usize` always returns the exact size of the array since the implementation only supports arrays of size less than `USize.size`. -/ -@[extern "lean_array_size", simp] +@[extern "lean_array_size", simp, expose] def usize (xs : @& Array α) : USize := xs.size.toUSize /-- diff --git a/src/Init/Data/ByteArray/Basic.lean b/src/Init/Data/ByteArray/Basic.lean index d74037e5e9..963268a14e 100644 --- a/src/Init/Data/ByteArray/Basic.lean +++ b/src/Init/Data/ByteArray/Basic.lean @@ -6,7 +6,6 @@ Author: Leonardo de Moura module prelude -public import Init.Data.Array.Basic public import Init.Data.Array.DecidableEq public import Init.Data.UInt.Basic public import Init.Data.UInt.BasicAux diff --git a/src/Init/Data/UInt/Basic.lean b/src/Init/Data/UInt/Basic.lean index d37a80c158..d510749bf7 100644 --- a/src/Init/Data/UInt/Basic.lean +++ b/src/Init/Data/UInt/Basic.lean @@ -139,16 +139,6 @@ This function is overridden at runtime with an efficient implementation. -/ @[extern "lean_uint8_shift_right"] protected def UInt8.shiftRight (a b : UInt8) : UInt8 := ⟨a.toBitVec >>> (UInt8.mod b 8).toBitVec⟩ -/-- -Strict inequality of 8-bit unsigned integers, defined as inequality of the corresponding -natural numbers. Usually accessed via the `<` operator. --/ -protected def UInt8.lt (a b : UInt8) : Prop := a.toBitVec < b.toBitVec -/-- -Non-strict inequality of 8-bit unsigned integers, defined as inequality of the corresponding -natural numbers. Usually accessed via the `≤` operator. --/ -protected def UInt8.le (a b : UInt8) : Prop := a.toBitVec ≤ b.toBitVec instance : Add UInt8 := ⟨UInt8.add⟩ instance : Sub UInt8 := ⟨UInt8.sub⟩ @@ -160,8 +150,6 @@ set_option linter.deprecated false in instance : HMod UInt8 Nat UInt8 := ⟨UInt8.modn⟩ instance : Div UInt8 := ⟨UInt8.div⟩ -instance : LT UInt8 := ⟨UInt8.lt⟩ -instance : LE UInt8 := ⟨UInt8.le⟩ /-- Bitwise complement, also known as bitwise negation, for 8-bit unsigned integers. Usually accessed @@ -197,39 +185,6 @@ Converts `true` to `1` and `false` to `0`. @[extern "lean_bool_to_uint8"] def Bool.toUInt8 (b : Bool) : UInt8 := if b then 1 else 0 -/-- -Decides whether one 8-bit unsigned integer is strictly less than another. Usually accessed via the -`DecidableLT UInt8` instance. - -This function is overridden at runtime with an efficient implementation. - -Examples: - * `(if (6 : UInt8) < 7 then "yes" else "no") = "yes"` - * `(if (5 : UInt8) < 5 then "yes" else "no") = "no"` - * `show ¬((7 : UInt8) < 7) by decide` --/ -@[extern "lean_uint8_dec_lt"] -def UInt8.decLt (a b : UInt8) : Decidable (a < b) := - inferInstanceAs (Decidable (a.toBitVec < b.toBitVec)) - -/-- -Decides whether one 8-bit unsigned integer is less than or equal to another. Usually accessed via the -`DecidableLE UInt8` instance. - -This function is overridden at runtime with an efficient implementation. - -Examples: - * `(if (15 : UInt8) ≤ 15 then "yes" else "no") = "yes"` - * `(if (15 : UInt8) ≤ 5 then "yes" else "no") = "no"` - * `(if (5 : UInt8) ≤ 15 then "yes" else "no") = "yes"` - * `show (7 : UInt8) ≤ 7 by decide` --/ -@[extern "lean_uint8_dec_le"] -def UInt8.decLe (a b : UInt8) : Decidable (a ≤ b) := - inferInstanceAs (Decidable (a.toBitVec ≤ b.toBitVec)) - -attribute [instance] UInt8.decLt UInt8.decLe - instance : Max UInt8 := maxOfLe instance : Min UInt8 := minOfLe diff --git a/src/Init/Meta.lean b/src/Init/Meta.lean index fa42a35901..fd08dc77a2 100644 --- a/src/Init/Meta.lean +++ b/src/Init/Meta.lean @@ -109,9 +109,22 @@ def isSubScriptAlnum (c : Char) : Bool := @[inline] def isIdFirst (c : Char) : Bool := c.isAlpha || c = '_' || isLetterLike c +@[inline] private def isAlphaAscii (c : UInt8) : Bool := + 'a'.toUInt8 ≤ c && c ≤ 'z'.toUInt8 + || 'A'.toUInt8 ≤ c && c ≤ 'Z'.toUInt8 + +@[inline] private def isIdFirstAscii (c : UInt8) : Bool := + isAlphaAscii c || c = '_'.toUInt8 + +@[inline] private def isAlphanumAscii (c : UInt8) : Bool := + isAlphaAscii c || '0'.toUInt8 ≤ c && c ≤ '9'.toUInt8 + @[inline] def isIdRest (c : Char) : Bool := c.isAlphanum || c = '_' || c = '\'' || c == '!' || c == '?' || isLetterLike c || isSubScriptAlnum c +@[inline] private def isIdRestAscii (c : UInt8) : Bool := + isAlphanumAscii c || c = '_'.toUInt8 || c = '\''.toUInt8 || c == '!'.toUInt8 || c == '?'.toUInt8 + def idBeginEscape := '«' def idEndEscape := '»' @[inline] def isIdBeginEscape (c : Char) : Bool := c = idBeginEscape @@ -137,6 +150,23 @@ def isInaccessibleUserName : Name → Bool @[extern "lean_string_get_byte_fast"] private opaque getUtf8Byte' (s : @& String) (n : Nat) (h : n < s.utf8ByteSize) : UInt8 +private partial def needsNoEscapeAsciiRest (s : String) (i : Nat) : Bool := + if h : i < s.utf8ByteSize then + let c := getUtf8Byte' s i h + isIdRestAscii c && needsNoEscapeAsciiRest s (i + 1) + else + true + +@[inline] private def needsNoEscapeAscii (s : String) (h : s.utf8ByteSize > 0) : Bool := + let c := getUtf8Byte' s 0 h + isIdFirstAscii c && needsNoEscapeAsciiRest s 1 + +@[inline] private def needsNoEscape (s : String) (h : s.utf8ByteSize > 0) : Bool := + needsNoEscapeAscii s h || isIdFirst (s.get 0) && (s.toSubstring.drop 1).all isIdRest + +@[inline] private def escape (s : String) : String := + idBeginEscape.toString ++ s ++ idEndEscape.toString + /-- Creates a round-trippable string name component if possible, otherwise returns `none`. Names that are valid identifiers are not escaped, and otherwise, if they do not contain `»`, they are escaped. @@ -144,9 +174,15 @@ Names that are valid identifiers are not escaped, and otherwise, if they do not -/ @[inline] def escapePart (s : String) (force : Bool := false) : Option String := - if s.length > 0 && !force && isIdFirst (s.get 0) && (s.toSubstring.drop 1).all isIdRest then some s - else if s.any isIdEndEscape then none - else some <| idBeginEscape.toString ++ s ++ idEndEscape.toString + if h : s.utf8ByteSize > 0 then + if !force && needsNoEscape s h then + some s + else if s.any isIdEndEscape then + none + else + some <| escape s + else + some <| escape s variable (sep : String) (escape : Bool) in /-- diff --git a/src/Init/Prelude.lean b/src/Init/Prelude.lean index 6104636cff..5ea203ebe9 100644 --- a/src/Init/Prelude.lean +++ b/src/Init/Prelude.lean @@ -2199,6 +2199,52 @@ instance : DecidableEq UInt8 := UInt8.decEq instance : Inhabited UInt8 where default := UInt8.ofNatLT 0 (of_decide_eq_true rfl) +/-- +Strict inequality of 8-bit unsigned integers, defined as inequality of the corresponding +natural numbers. Usually accessed via the `<` operator. +-/ +protected def UInt8.lt (a b : UInt8) : Prop := LT.lt a.toBitVec b.toBitVec +/-- +Non-strict inequality of 8-bit unsigned integers, defined as inequality of the corresponding +natural numbers. Usually accessed via the `≤` operator. +-/ +protected def UInt8.le (a b : UInt8) : Prop := LE.le a.toBitVec b.toBitVec +instance : LT UInt8 := ⟨UInt8.lt⟩ +instance : LE UInt8 := ⟨UInt8.le⟩ + +/-- +Decides whether one 8-bit unsigned integer is strictly less than another. Usually accessed via the +`DecidableLT UInt8` instance. + +This function is overridden at runtime with an efficient implementation. + +Examples: + * `(if (6 : UInt8) < 7 then "yes" else "no") = "yes"` + * `(if (5 : UInt8) < 5 then "yes" else "no") = "no"` + * `show ¬((7 : UInt8) < 7) by decide` +-/ +@[extern "lean_uint8_dec_lt"] +def UInt8.decLt (a b : UInt8) : Decidable (LT.lt a b) := + inferInstanceAs (Decidable (LT.lt a.toBitVec b.toBitVec)) + +/-- +Decides whether one 8-bit unsigned integer is less than or equal to another. Usually accessed via the +`DecidableLE UInt8` instance. + +This function is overridden at runtime with an efficient implementation. + +Examples: + * `(if (15 : UInt8) ≤ 15 then "yes" else "no") = "yes"` + * `(if (15 : UInt8) ≤ 5 then "yes" else "no") = "no"` + * `(if (5 : UInt8) ≤ 15 then "yes" else "no") = "yes"` + * `show (7 : UInt8) ≤ 7 by decide` +-/ +@[extern "lean_uint8_dec_le"] +def UInt8.decLe (a b : UInt8) : Decidable (LE.le a b) := + inferInstanceAs (Decidable (LE.le a.toBitVec b.toBitVec)) + +attribute [instance] UInt8.decLt UInt8.decLe + /-- The number of distinct values representable by `UInt16`, that is, `2^16 = 65536`. -/ abbrev UInt16.size : Nat := 65536 diff --git a/src/Init/Util.lean b/src/Init/Util.lean index 2e2b867356..2e10097439 100644 --- a/src/Init/Util.lean +++ b/src/Init/Util.lean @@ -6,7 +6,6 @@ Authors: Leonardo de Moura module prelude -public import Init.Data.String.Basic public import Init.Data.ToString.Basic public section diff --git a/src/Lean/Data/Json/Printer.lean b/src/Lean/Data/Json/Printer.lean index d2038eb155..adf498758c 100644 --- a/src/Lean/Data/Json/Printer.lean +++ b/src/Lean/Data/Json/Printer.lean @@ -22,7 +22,7 @@ This table contains for each UTF-8 byte whether we need to escape a string that private def escapeTable : { xs : ByteArray // xs.size = 256 } := ⟨ByteArray.mk #[ 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, + 0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, @@ -74,6 +74,7 @@ where else false +@[inline] def escape (s : String) (acc : String := "") : String := -- If we don't have any characters that need to be escaped we can just append right away. if needEscape s then @@ -81,6 +82,7 @@ def escape (s : String) (acc : String := "") : String := else acc ++ s +@[inline] def renderString (s : String) (acc : String := "") : String := let acc := acc ++ "\"" let acc := escape s acc @@ -107,35 +109,123 @@ end def pretty (j : Json) (lineWidth := 80) : String := Format.pretty (render j) lineWidth -protected inductive CompressWorkItem - | json (j : Json) - | arrayElem (j : Json) +private inductive CompressWorkItemKind where + | json + | arrayElem | arrayEnd - | objectField (k : String) (j : Json) + | objectField | objectEnd | comma -open Json.CompressWorkItem in +private structure CompressWorkItemQueue where + kinds : Array CompressWorkItemKind + values : Array Json + objectFieldKeys : Array String + +@[inline] +private def CompressWorkItemQueue.pushKind (q : CompressWorkItemQueue) (kind : CompressWorkItemKind) : + CompressWorkItemQueue := { + q with kinds := q.kinds.push kind +} + +@[inline] +private def CompressWorkItemQueue.pushValue (q : CompressWorkItemQueue) (value : Json) : + CompressWorkItemQueue := { + q with values := q.values.push value +} + +@[inline] +private def CompressWorkItemQueue.pushObjectFieldKey (q : CompressWorkItemQueue) (objectFieldKey : String) : + CompressWorkItemQueue := { + q with objectFieldKeys := q.objectFieldKeys.push objectFieldKey +} + +@[inline] +private def CompressWorkItemQueue.popKind (q : CompressWorkItemQueue) (h : q.kinds.size ≠ 0) : + CompressWorkItemKind × CompressWorkItemQueue := + let kind := q.kinds[q.kinds.size - 1] + let q := { q with kinds := q.kinds.pop } + (kind, q) + +@[inline] +private def CompressWorkItemQueue.popValue! (q : CompressWorkItemQueue) : + Json × CompressWorkItemQueue := + let value := q.values[q.values.size - 1]! + let q := { q with values := q.values.pop } + (value, q) + +@[inline] +private def CompressWorkItemQueue.popObjectFieldKey! (q : CompressWorkItemQueue) : + String × CompressWorkItemQueue := + let objectFieldKey := q.objectFieldKeys[q.objectFieldKeys.size - 1]! + let q := { q with objectFieldKeys := q.objectFieldKeys.pop } + (objectFieldKey, q) + partial def compress (j : Json) : String := - go "" [json j] -where go (acc : String) : List Json.CompressWorkItem → String - | [] => acc - | json j :: is => - match j with - | null => go (acc ++ "null") is - | bool true => go (acc ++ "true") is - | bool false => go (acc ++ "false") is - | num s => go (acc ++ s.toString) is - | str s => go (renderString s acc) is - | arr elems => go (acc ++ "[") ((elems.map arrayElem).toListAppend (arrayEnd :: is)) - | obj kvs => go (acc ++ "{") (kvs.foldl (init := []) (fun acc k j => objectField k j :: acc) ++ [objectEnd] ++ is) - | arrayElem j :: arrayEnd :: is => go acc (json j :: arrayEnd :: is) - | arrayElem j :: is => go acc (json j :: comma :: is) - | arrayEnd :: is => go (acc ++ "]") is - | objectField k j :: objectEnd :: is => go (renderString k acc ++ ":") (json j :: objectEnd :: is) - | objectField k j :: is => go (renderString k acc ++ ":") (json j :: comma :: is) - | objectEnd :: is => go (acc ++ "}") is - | comma :: is => go (acc ++ ",") is + go "" { + kinds := #[.json] + values := #[j] + objectFieldKeys := #[] + } +where + go (acc : String) (q : CompressWorkItemQueue) : String := + if h : q.kinds.size = 0 then + acc + else + let (kind, q) := q.popKind h + match kind with + | .json => + let (j, q) := q.popValue! + match j with + | null => + go (acc ++ "null") q + | bool b => + go (acc ++ toString b) q + | num n => + go (acc ++ toString n) q + | str s => + go (renderString s acc) q + | arr elems => + let q := q.pushKind .arrayEnd + go (acc ++ "[") (elems.foldr (init := q) fun e acc => acc.pushKind .arrayElem |>.pushValue e) + | obj kvs => + let q := q.pushKind .objectEnd + go (acc ++ "{") (kvs.foldr (init := q) fun k j acc => acc.pushKind .objectField |>.pushObjectFieldKey k |>.pushValue j) + | .arrayElem => + let (j, q) := q.popValue! + if h : q.kinds.size = 0 then + go acc { + kinds := #[.comma, .json] + values := #[j] + objectFieldKeys := #[] + } + else + let kind := q.kinds[q.kinds.size - 1] + if kind matches .arrayEnd then + go acc (q.pushKind .json |>.pushValue j) + else + go acc (q.pushKind .comma |>.pushKind .json |>.pushValue j) + | .arrayEnd => + go (acc ++ "]") q + | .objectField => + let (k, q) := q.popObjectFieldKey! + let (j, q) := q.popValue! + if h : q.kinds.size = 0 then + go (renderString k acc ++ ":") { + kinds := #[.comma, .json] + values := #[j] + objectFieldKeys := #[] + } + else + let kind := q.kinds[q.kinds.size - 1] + if kind matches .objectEnd then + go (renderString k acc ++ ":") (q.pushKind .json |>.pushValue j) + else + go (renderString k acc ++ ":") (q.pushKind .comma |>.pushKind .json |>.pushValue j) + | .objectEnd => + go (acc ++ "}") q + | .comma => + go (acc ++ ",") q instance : ToFormat Json := ⟨render⟩ instance : ToString Json := ⟨pretty⟩ diff --git a/src/Lean/Data/Json/Stream.lean b/src/Lean/Data/Json/Stream.lean index e8fa2f96ba..95cc444b69 100644 --- a/src/Lean/Data/Json/Stream.lean +++ b/src/Lean/Data/Json/Stream.lean @@ -18,6 +18,11 @@ namespace IO.FS.Stream open Lean open IO +def readUTF8 (h : FS.Stream) (nBytes : Nat) : IO String := do + let bytes ← h.read (USize.ofNat nBytes) + let some s := String.fromUTF8? bytes | throw (IO.userError "invalid UTF-8") + return s + /-- Consumes `nBytes` bytes from the stream, interprets the bytes as a utf-8 string and the string as a valid JSON object. -/ def readJson (h : FS.Stream) (nBytes : Nat) : IO Json := do let bytes ← h.read (USize.ofNat nBytes) diff --git a/src/Lean/Data/JsonRpc.lean b/src/Lean/Data/JsonRpc.lean index 41d99e7ddf..b824ffe49c 100644 --- a/src/Lean/Data/JsonRpc.lean +++ b/src/Lean/Data/JsonRpc.lean @@ -296,6 +296,105 @@ instance [FromJson α] : FromJson (Notification α) where pure $ ⟨method, param⟩ else throw "not a notification" +/-- +A variant of `Message` that has been parsed *partially*, without the payload. +This is useful when we want to process the metadata of a `Message` without parsing and converting +the whole thing. +-/ +inductive MessageMetaData where + | request (id : RequestID) (method : String) + | notification (method : String) + | response (id : RequestID) + | responseError (id : RequestID) (code : ErrorCode) (message : String) (data? : Option Json) + deriving Inhabited + +def MessageMetaData.toMessage : MessageMetaData → Message + | .request id method => .request id method none + | .notification method => .notification method none + | .response id => .response id .null + | .responseError id code message data? => .responseError id code message data? + +open Std.Internal.Parsec in +open Std.Internal.Parsec.String in +open Json.Parser in +private def messageMetaDataParser (input : String) : Parser MessageMetaData := do + skip + let k ← parseStr + skip + match k with + | "id" => + -- Request or response + let id ← parseRequestID + skip + -- Skip `jsonrpc` field + let _ ← parseStr + skip + let _ ← parseStr + skip + let k' ← parseStr + match k' with + | "method" => + skip + let method ← parseStr + return .request id method + | "result" => + -- Response + return .response id + | _ => + fail "expected `method` or `result` field" + | "jsonrpc" => + -- Notification + -- Skip `jsonrpc` version + let _ ← parseStr + skip + -- Skip `method` field name + let _ ← parseStr + skip + let method ← parseStr + return .notification method + | "error" => + -- Response error + -- Response errors are usually small, so we just parse them normally. + match Json.parse input with + | .ok parsed => + match fromJson? parsed with + | .ok (.responseError id code message data? : Message) => + return .responseError id code message data? + | .ok _ => + fail "expected response error message kind" + | .error err => + fail err + | .error err => + fail err + | _ => + fail "expected `id`, `jsonrpc` or `error` field" +where + parseStr : Parser String := do + let c ← peek! + if c != '"' then + fail "expected \"" + skip + str + parseRequestID : Parser RequestID := do + (do + let num ← Parser.num + return .num num) <|> + (do + let str ← parseStr + return .str str) <|> + (do + skipString "null" + return .null) + +/-- +Danger: For performance reasons, this function makes a number of fragile assumptions about `input`. +Namely: +- `input` is the output of `(toJson (v : Message)).compress` +- `compress` yields a lexicographic ordering of JSON object keys +-/ +def parseMessageMetaData (input : String) : Except String MessageMetaData := + messageMetaDataParser input |>.run input + end Lean.JsonRpc namespace IO.FS.Stream diff --git a/src/Lean/Data/Lsp/Communication.lean b/src/Lean/Data/Lsp/Communication.lean index 535835c007..33f8bfd7fd 100644 --- a/src/Lean/Data/Lsp/Communication.lean +++ b/src/Lean/Data/Lsp/Communication.lean @@ -75,6 +75,13 @@ section catch e => throw $ userError s!"Cannot read LSP message: {e}" + def readLspMessageAsString (h : FS.Stream) : IO String := do + try + let nBytes ← readLspHeader h + h.readUTF8 nBytes + catch e => + throw $ userError s!"Cannot read LSP message: {e}" + def readLspRequestAs (h : FS.Stream) (expectedMethod : String) (α) [FromJson α] : IO (Request α) := do try let nBytes ← readLspHeader h @@ -100,14 +107,16 @@ end section variable [ToJson α] - def writeLspMessage (h : FS.Stream) (msg : Message) : IO Unit := do + def writeSerializedLspMessage (h : FS.Stream) (msg : String) : IO Unit := do + let header := s!"Content-Length: {toString msg.utf8ByteSize}\r\n\r\n" -- inlined implementation instead of using jsonrpc's writeMessage -- to maintain the atomicity of putStr - let j := (toJson msg).compress - let header := s!"Content-Length: {toString j.utf8ByteSize}\r\n\r\n" - h.putStr (header ++ j) + h.putStr (header ++ msg) h.flush + def writeLspMessage (h : FS.Stream) (msg : Message) : IO Unit := do + h.writeSerializedLspMessage (toJson msg).compress + def writeLspRequest (h : FS.Stream) (r : Request α) : IO Unit := h.writeLspMessage r diff --git a/src/Lean/Data/Lsp/LanguageFeatures.lean b/src/Lean/Data/Lsp/LanguageFeatures.lean index ed7105ac83..c1c8ab57be 100644 --- a/src/Lean/Data/Lsp/LanguageFeatures.lean +++ b/src/Lean/Data/Lsp/LanguageFeatures.lean @@ -10,6 +10,7 @@ prelude public import Lean.Data.Json.FromToJson.Basic public import Lean.Data.Lsp.Basic meta import Lean.Data.Json +public import Lean.Expr public section @@ -59,6 +60,10 @@ instance : FromJson CompletionItemTag where return CompletionItemTag.ofNat (i-1) structure CompletionItem where + -- When adjusting this type, make sure to adjust `ResolvableCompletionList.compressFast` + -- as well, which is our `(toJson l).compress` fast path. + -- (Completion downstream of Mathlib can output gigantic JSON, + -- so we want to avoid all redundant allocs) label : String detail? : Option String := none documentation? : Option MarkupContent := none @@ -85,6 +90,112 @@ structure CompletionList where items : Array CompletionItem deriving FromJson, ToJson +/-- +Identifier that is sent from the server to the client as part of the `CompletionItem.data?` field. +Needed to resolve the `CompletionItem` when the client sends a `completionItem/resolve` request +for that item, again containing the `data?` field provided by the server. +-/ +inductive CompletionIdentifier where + | const (declName : Name) + | fvar (id : Lean.FVarId) + deriving BEq, Hashable + +instance : ToJson CompletionIdentifier where + toJson + | .const declName => + .str s!"c{toString declName}" + | .fvar id => + .str s!"f{toString id.name}" + +instance : FromJson CompletionIdentifier where + fromJson? + | .str s => + let c := s.get 0 + if c == 'c' then + let declName := s.extract ⟨1⟩ s.endPos |>.toName + .ok <| .const declName + else if c == 'f' then + let id := ⟨s.extract ⟨1⟩ s.endPos |>.toName⟩ + .ok <| .fvar id + else + .error "Expected string with prefix `c` or `f` in `FromJson` instance of `CompletionIdentifier`." + | _ => .error "Expected string in `FromJson` instance of `CompletionIdentifier`." + +structure ResolvableCompletionItemData where + mod : Name + pos : Position + /-- Position of the completion info that this completion item was created from. -/ + cPos? : Option Nat := none + id? : Option CompletionIdentifier := none + deriving BEq, Hashable + +instance : ToJson ResolvableCompletionItemData where + toJson d := Id.run do + let mut arr : Array Json := #[ + toJson d.mod, + d.pos.line, + d.pos.character, + ] + if let some cPos := d.cPos? then + arr := arr.push <| toJson cPos + if let some id := d.id? then + arr := arr.push <| toJson id + Json.arr arr + +instance : FromJson ResolvableCompletionItemData where + fromJson? + | .arr elems => do + if elems.size < 3 then + .error "Expected array of size 3 in `FromJson` instance of `ResolvableCompletionItemData" + let mod : Name ← fromJson? elems[0]! + let line : Nat ← fromJson? elems[1]! + let character : Nat ← fromJson? elems[2]! + let mut cPos? : Option Nat := none + let mut id? : Option CompletionIdentifier := none + if let .ok (some cPos) := elems[3]?.mapM fromJson? then + cPos? := some cPos + if let .ok (some id) := elems[3]?.mapM fromJson? then + id? := some id + if let .ok (some cPos) := elems[4]?.mapM fromJson? then + cPos? := some cPos + if let .ok (some id) := elems[4]?.mapM fromJson? then + id? := some id + let pos := { line, character } + return { + mod + pos + cPos? + id? + } + | _ => .error "Expected array in `FromJson` instance of `ResolvableCompletionItemData`" + +structure ResolvableCompletionItem where + label : String + detail? : Option String := none + documentation? : Option MarkupContent := none + kind? : Option CompletionItemKind := none + textEdit? : Option InsertReplaceEdit := none + sortText? : Option String := none + data? : Option ResolvableCompletionItemData := none + tags? : Option (Array CompletionItemTag) := none + /- + deprecated? : boolean + preselect? : boolean + filterText? : string + insertText? : string + insertTextFormat? : InsertTextFormat + insertTextMode? : InsertTextMode + additionalTextEdits? : TextEdit[] + commitCharacters? : string[] + command? : Command + -/ + deriving FromJson, ToJson, Inhabited, BEq, Hashable + +structure ResolvableCompletionList where + isIncomplete : Bool + items : Array ResolvableCompletionItem + deriving FromJson, ToJson + structure CompletionParams extends TextDocumentPositionParams where -- context? : CompletionContext deriving FromJson, ToJson diff --git a/src/Lean/Server/CodeActions/Basic.lean b/src/Lean/Server/CodeActions/Basic.lean index b19579bfbd..2c6f1d7625 100644 --- a/src/Lean/Server/CodeActions/Basic.lean +++ b/src/Lean/Server/CodeActions/Basic.lean @@ -37,12 +37,12 @@ structure CodeActionResolveData where providerResultIndex : Nat deriving ToJson, FromJson -def CodeAction.getFileSource! (ca : CodeAction) : DocumentUri := - let r : Except String DocumentUri := do +def CodeAction.getFileSource! (ca : CodeAction) : FileIdent := + let r : Except String FileIdent := do let some data := ca.data? | throw s!"no data param on code action {ca.title}" let data : CodeActionResolveData ← fromJson? data - return data.params.textDocument.uri + return .uri data.params.textDocument.uri match r with | Except.ok uri => uri | Except.error e => panic! e diff --git a/src/Lean/Server/Completion.lean b/src/Lean/Server/Completion.lean index 31059ef272..279b973a7f 100644 --- a/src/Lean/Server/Completion.lean +++ b/src/Lean/Server/Completion.lean @@ -17,27 +17,27 @@ open Lsp open Elab private def filterDuplicateCompletionItems - (items : Array CompletionItem) - : Array CompletionItem := - let duplicationGroups := items.groupByKey fun i => ( - i.label, - i.textEdit?, - i.detail?, - i.kind?, - i.tags?, - i.documentation?, - ) - duplicationGroups.map (fun _ duplicateItems => duplicateItems[0]!) - |>.valuesArray + (items : Array ResolvableCompletionItem) + : Array ResolvableCompletionItem := Id.run do + let mut r : Array ResolvableCompletionItem := #[] + let mut index : Std.HashSet (String × Option InsertReplaceEdit) := ∅ + for i in items do + let key := (i.label, i.textEdit?) + let (isDup, index') := index.containsThenInsert key + index := index' + if ! isDup then + r := r.push i + return r partial def find? - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (fileMap : FileMap) (hoverPos : String.Pos) (cmdStx : Syntax) (infoTree : InfoTree) (caps : ClientCapabilities) - : CancellableM CompletionList := do + : CancellableM ResolvableCompletionList := do let (prioritizedPartitions, isComplete) := findPrioritizedCompletionPartitionsAt fileMap hoverPos cmdStx infoTree let mut allCompletions := #[] for partition in prioritizedPartitions do @@ -46,19 +46,19 @@ partial def find? let completions : Array ScoredCompletionItem ← match i.info with | .id stx id danglingDot lctx .. => - idCompletion params completionInfoPos i.ctx lctx stx id i.hoverInfo danglingDot + idCompletion mod pos completionInfoPos i.ctx lctx stx id i.hoverInfo danglingDot | .dot info .. => - dotCompletion params completionInfoPos i.ctx info + dotCompletion mod pos completionInfoPos i.ctx info | .dotId _ id lctx expectedType? => - dotIdCompletion params completionInfoPos i.ctx lctx id expectedType? + dotIdCompletion mod pos completionInfoPos i.ctx lctx id expectedType? | .fieldId _ id lctx structName => - fieldIdCompletion params completionInfoPos i.ctx lctx id structName + fieldIdCompletion mod pos completionInfoPos i.ctx lctx id structName | .option stx => - optionCompletion params completionInfoPos i.ctx stx caps + optionCompletion mod pos completionInfoPos i.ctx stx caps | .errorName _ partialId => - errorNameCompletion params completionInfoPos i.ctx partialId caps + errorNameCompletion mod pos completionInfoPos i.ctx partialId caps | .tactic .. => - tacticCompletion params completionInfoPos i.ctx + tacticCompletion mod pos completionInfoPos i.ctx | _ => pure #[] allCompletions := allCompletions ++ completions diff --git a/src/Lean/Server/Completion/CompletionCollectors.lean b/src/Lean/Server/Completion/CompletionCollectors.lean index cd0f51df82..41058a0f56 100644 --- a/src/Lean/Server/Completion/CompletionCollectors.lean +++ b/src/Lean/Server/Completion/CompletionCollectors.lean @@ -24,14 +24,15 @@ open FuzzyMatching section Infrastructure private structure Context where - params : CompletionParams + mod : Name + pos : Lsp.Position completionInfoPos : Nat /-- Intermediate state while completions are being computed. -/ private structure State where /-- All completion items and their fuzzy match scores so far. -/ - items : Array CompletionItem := #[] + items : Array ResolvableCompletionItem := #[] /-- Monad used for completion computation that allows modifying a completion `State` and reading @@ -46,12 +47,13 @@ section Infrastructure : M Unit := do let ctx ← read let data := { - params := ctx.params, - cPos := ctx.completionInfoPos, + mod := ctx.mod, + pos := ctx.pos, + cPos? := ctx.completionInfoPos, id? : ResolvableCompletionItemData } - let item := { item with data? := toJson data } + let item := { item with data? := data } modify fun s => { s with items := s.items.push item } /-- @@ -62,42 +64,16 @@ section Infrastructure (label : Name) (id : CompletionIdentifier) (kind : CompletionItemKind) + (tags : Array CompletionItemTag) : M Unit := do - let env ← getEnv - let tags? := do - let .const declName := id - | none - guard <| Linter.isDeprecated env declName - some #[CompletionItemTag.deprecated] - let item := { label := label.toString, kind? := kind, tags? } + let item := { label := label.toString, kind? := kind, tags? := tags } addItem item id - private def getCompletionKindForDecl (constInfo : ConstantInfo) : M CompletionItemKind := do - let env ← getEnv - if constInfo.isCtor then - return CompletionItemKind.constructor - else if constInfo.isInductive then - if isClass env constInfo.name then - return CompletionItemKind.class - else if (← isEnumType constInfo.name) then - return CompletionItemKind.enum - else - return CompletionItemKind.struct - else if wasOriginallyTheorem env constInfo.name then - return CompletionItemKind.event - else if (← isProjectionFn constInfo.name) then - return CompletionItemKind.field - else - let isFunction : Bool ← withTheReader Core.Context ({ · with maxHeartbeats := 0 }) do - return (← whnf constInfo.type).isForall - if isFunction then - return CompletionItemKind.function - else - return CompletionItemKind.constant - private def addUnresolvedCompletionItemForDecl (label : Name) (declName : Name) : M Unit := do if let some c := (← getEnv).find? declName then - addUnresolvedCompletionItem label (.const declName) (← getCompletionKindForDecl c) + addUnresolvedCompletionItem label (.const declName) + (← getCompletionKindForDecl c) + (← getCompletionTagsForDecl declName) private def addKeywordCompletionItem (keyword : String) : M Unit := do let item := { label := keyword, detail? := "keyword", documentation? := none, kind? := CompletionItemKind.keyword } @@ -108,15 +84,16 @@ section Infrastructure addItem item private def runM - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (completionInfoPos : Nat) (ctx : ContextInfo) (lctx : LocalContext) (x : M Unit) - : CancellableM (Array CompletionItem) := do + : CancellableM (Array ResolvableCompletionItem) := do let tk ← read let r ← ctx.runMetaM lctx do - x.run ⟨params, completionInfoPos⟩ |>.run {} |>.run tk + x.run ⟨mod, pos, completionInfoPos⟩ |>.run {} |>.run tk match r with | .error _ => throw .requestCancelled | .ok (_, s) => return s.items @@ -169,9 +146,8 @@ section Utils return none return none - private def forEligibleDeclsWithCancellationM [Monad m] [MonadEnv m] - [MonadLiftT (ST IO.RealWorld) m] [MonadCancellable m] [MonadLiftT IO m] - (f : Name → ConstantInfo → m PUnit) : m PUnit := do + private def forEligibleDeclsWithCancellationM [Monad m] [MonadEnv m] [MonadLiftT MetaM m] + [MonadCancellable m] (f : Name → EligibleDecl → m PUnit) : m PUnit := do let _ ← StateT.run (s := 0) <| forEligibleDeclsM fun decl ci => do modify (· + 1) if (← get) >= 10000 then @@ -372,13 +348,14 @@ private def idCompletionCore -- search for matches in the local context for localDecl in (← getLCtx) do if matchAtomic id localDecl.userName danglingDot then - addUnresolvedCompletionItem localDecl.userName (.fvar localDecl.fvarId) (kind := CompletionItemKind.variable) + addUnresolvedCompletionItem localDecl.userName (.fvar localDecl.fvarId) + (kind := CompletionItemKind.variable) (tags := #[]) -- search for matches in the environment let env ← getEnv - forEligibleDeclsWithCancellationM fun declName c => do + forEligibleDeclsWithCancellationM fun declName decl => do let bestMatch? ← bestLabelForDecl? ctx declName id danglingDot if let some bestLabel := bestMatch? then - addUnresolvedCompletionItem bestLabel (.const declName) (← getCompletionKindForDecl c) + addUnresolvedCompletionItem bestLabel (.const declName) (← decl.kind) (← decl.tags) RequestCancellation.check let matchAlias (ns : Name) (alias : Name) : Bool := -- Recall that aliases may not be atomic and include the namespace where they were created. @@ -425,7 +402,8 @@ private def idCompletionCore completeNamespaces ctx id danglingDot def idCompletion - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (completionInfoPos : Nat) (ctx : ContextInfo) (lctx : LocalContext) @@ -433,17 +411,18 @@ def idCompletion (id : Name) (hoverInfo : HoverInfo) (danglingDot : Bool) - : CancellableM (Array CompletionItem) := - runM params completionInfoPos ctx lctx do + : CancellableM (Array ResolvableCompletionItem) := + runM mod pos completionInfoPos ctx lctx do idCompletionCore ctx stx id hoverInfo danglingDot def dotCompletion - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (completionInfoPos : Nat) (ctx : ContextInfo) (info : TermInfo) - : CancellableM (Array CompletionItem) := - runM params completionInfoPos ctx info.lctx do + : CancellableM (Array ResolvableCompletionItem) := + runM mod pos completionInfoPos ctx info.lctx do let nameSet ← try getDotCompletionTypeNameSet (← instantiateMVars (← inferType info.expr)) catch _ => @@ -451,27 +430,29 @@ def dotCompletion if nameSet.isEmpty then return - forEligibleDeclsWithCancellationM fun declName c => do + forEligibleDeclsWithCancellationM fun declName decl => do let unnormedTypeName := declName.getPrefix if ! nameSet.contains unnormedTypeName then return let some declName ← normPrivateName? declName | return + let c := decl.info let typeName := declName.getPrefix if ! (← isDotCompletionMethod typeName c) then return - let completionKind ← getCompletionKindForDecl c - addUnresolvedCompletionItem (.mkSimple c.name.getString!) (.const c.name) (kind := completionKind) + addUnresolvedCompletionItem (.mkSimple c.name.getString!) (.const c.name) + (← decl.kind) (← decl.tags) def dotIdCompletion - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (completionInfoPos : Nat) (ctx : ContextInfo) (lctx : LocalContext) (id : Name) (expectedType? : Option Expr) - : CancellableM (Array CompletionItem) := - runM params completionInfoPos ctx lctx do + : CancellableM (Array ResolvableCompletionItem) := + runM mod pos completionInfoPos ctx lctx do let some expectedType := expectedType? | return () @@ -481,7 +462,7 @@ def dotIdCompletion let nameSet := NameSetModPrivate.ofArray typeNames - forEligibleDeclsWithCancellationM fun declName c => do + forEligibleDeclsWithCancellationM fun declName decl => do let unnormedTypeName := declName.getPrefix if ! nameSet.contains unnormedTypeName then return @@ -489,27 +470,30 @@ def dotIdCompletion let some declName ← normPrivateName? declName | return + let c := decl.info if ! (← isDotIdCompletionMethod nameSet c) then return - let completionKind ← getCompletionKindForDecl c + let kind ← decl.kind + let tags ← decl.tags if id.isAnonymous then -- We're completing a lone dot => offer all decls of the type - addUnresolvedCompletionItem (.mkSimple c.name.getString!) (.const c.name) completionKind + addUnresolvedCompletionItem (.mkSimple c.name.getString!) (.const c.name) kind tags return let some label ← matchDecl? declName.getPrefix id (danglingDot := false) declName | pure () - addUnresolvedCompletionItem label (.const c.name) completionKind + addUnresolvedCompletionItem label (.const c.name) kind tags def fieldIdCompletion - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (completionInfoPos : Nat) (ctx : ContextInfo) (lctx : LocalContext) (id : Option Name) (structName : Name) - : CancellableM (Array CompletionItem) := - runM params completionInfoPos ctx lctx do + : CancellableM (Array ResolvableCompletionItem) := + runM mod pos completionInfoPos ctx lctx do let idStr := id.map (·.toString) |>.getD "" let fieldNames := getStructureFieldsFlattened (← getEnv) structName (includeSubobjectFields := false) for fieldName in fieldNames do @@ -526,8 +510,8 @@ affect the set of eligible completion candidates. -/ private def trailingDotCompletion [ForIn Id Coll (Name × α)] (entries : Coll) (stx : Syntax) (caps : ClientCapabilities) (ctx : ContextInfo) - (mkItem : Name → α → Option InsertReplaceEdit → CompletionItem) : - Array CompletionItem := Id.run do + (mkItem : Name → α → Option InsertReplaceEdit → ResolvableCompletionItem) : + Array ResolvableCompletionItem := Id.run do let (partialName, trailingDot) := match stx.getSubstring? (withLeading := false) (withTrailing := false) with | none => ("", false) -- the `ident` is `missing`, list all options @@ -553,12 +537,13 @@ private def trailingDotCompletion [ForIn Id Coll (Name × α)] return items def optionCompletion - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (completionInfoPos : Nat) (ctx : ContextInfo) (stx : Syntax) (caps : ClientCapabilities) - : IO (Array CompletionItem) := + : IO (Array ResolvableCompletionItem) := ctx.runMetaM {} do -- HACK(WN): unfold the type so ForIn works let (decls : Std.TreeMap _ _ _) ← getOptionDecls @@ -570,20 +555,22 @@ def optionCompletion documentation? := none, kind? := CompletionItemKind.property -- TODO: investigate whether this is the best kind for options. textEdit? - data? := toJson { - params - cPos := completionInfoPos + data? := { + mod + pos + cPos? := completionInfoPos id? := none : ResolvableCompletionItemData } } def errorNameCompletion - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (completionInfoPos : Nat) (ctx : ContextInfo) (partialId : Syntax) (caps : ClientCapabilities) - : IO (Array CompletionItem) := + : IO (Array ResolvableCompletionItem) := ctx.runMetaM {} do let explanations := getErrorExplanationsRaw (← getEnv) return trailingDotCompletion explanations partialId caps ctx fun name explan textEdit? => { @@ -597,26 +584,28 @@ def errorNameCompletion kind? := CompletionItemKind.property textEdit? tags? := explan.metadata.removedVersion?.map fun _ => #[CompletionItemTag.deprecated] - data? := toJson { - params - cPos := completionInfoPos + data? := { + mod + pos + cPos? := completionInfoPos id? := none : ResolvableCompletionItemData } } def tacticCompletion - (params : CompletionParams) + (mod : Name) + (pos : Lsp.Position) (completionInfoPos : Nat) (ctx : ContextInfo) - : IO (Array CompletionItem) := ctx.runMetaM .empty do + : IO (Array ResolvableCompletionItem) := ctx.runMetaM .empty do let allTacticDocs ← Tactic.Doc.allTacticDocs - let items : Array CompletionItem := allTacticDocs.map fun tacticDoc => { + let items : Array ResolvableCompletionItem := allTacticDocs.map fun tacticDoc => { label := tacticDoc.userName detail? := none documentation? := tacticDoc.docString.map fun docString => { value := docString, kind := MarkupKind.markdown : MarkupContent } kind? := CompletionItemKind.keyword - data? := toJson { params, cPos := completionInfoPos, id? := none : ResolvableCompletionItemData } + data? := { mod, pos, cPos? := completionInfoPos, id? := none : ResolvableCompletionItemData } } return items diff --git a/src/Lean/Server/Completion/CompletionItemCompression.lean b/src/Lean/Server/Completion/CompletionItemCompression.lean new file mode 100644 index 0000000000..30c8b70d03 --- /dev/null +++ b/src/Lean/Server/Completion/CompletionItemCompression.lean @@ -0,0 +1,128 @@ +/- +Copyright (c) 2025 Lean FRO, LLC. All rights reserved. +Released under Apache 2.0 license as described in the file LICENSE. +Authors: Marc Huisinga +-/ +module + +prelude +public import Lean.Data.Lsp.LanguageFeatures + +namespace Lean.Lsp.ResolvableCompletionList + +@[inline] +def compressItemDataFast (acc : String) (data : ResolvableCompletionItemData) : + String := Id.run do + let mut acc := acc ++ "[" + acc := Json.renderString data.mod.toString acc + acc := acc ++ "," ++ data.pos.line.repr + acc := acc ++ "," ++ data.pos.character.repr + if let some cPos := data.cPos? then + acc := acc ++ "," ++ cPos.repr + if let some id := data.id? then + acc := acc ++ "," + match id with + | .const declName => + acc := acc ++ "\"c" + acc := Json.escape declName.toString acc ++ "\"" + | .fvar id => + acc := acc ++ "\"f" + acc := Json.escape id.name.toString acc ++ "\"" + acc ++ "]" + +@[inline] +def compressMarkupContentFast (acc : String) (c : MarkupContent) : String := + let kind := match c.kind with + | .plaintext => "plaintext" + | .markdown => "markdown" + let acc := acc ++ "{\"kind\":\"" ++ kind ++ "\",\"value\":" + let acc := Json.renderString c.value acc + acc ++ "}" + +@[inline] +def compressPositionFast (acc : String) (p : Position) : String := + acc ++ "{\"character\":" ++ p.character.repr ++ ",\"line\":" ++ p.line.repr ++ "}" + +@[inline] +def compressRangeFast (acc : String) (range : Range) : String := + let acc := acc ++ "{\"end\":" + let acc := compressPositionFast acc range.end + let acc := acc ++ ",\"start\":" + let acc := compressPositionFast acc range.start + acc ++ "}" + +@[inline] +def compressEditFast (acc : String) (edit : InsertReplaceEdit) : String := + let acc := acc ++ "{\"insert\":" + let acc := compressRangeFast acc edit.insert + let acc := acc ++ ",\"newText\":\"" ++ edit.newText ++ "\"" + let acc := acc ++ ",\"replace\":" + let acc := compressRangeFast acc edit.replace + acc ++ "}" + +def compressCompletionTagsFast (acc : String) (tags : Array CompletionItemTag) (i : Nat) : + String := + if h : i < tags.size then + let acc := acc ++ (tags[i].ctorIdx + 1).repr + let acc := + if i < tags.size - 1 then + acc ++ "," + else + acc + compressCompletionTagsFast acc tags (i + 1) + else + acc + +@[inline] +def compressItemFast (acc : String) (item : ResolvableCompletionItem) : String := Id.run do + let mut acc := acc ++ "{\"label\":" + acc := Json.renderString item.label acc + if let some detail := item.detail? then + acc := acc ++ ",\"detail\":" + acc := Json.renderString detail acc + if let some documentation := item.documentation? then + acc := acc ++ ",\"documentation\":" + acc := compressMarkupContentFast acc documentation + if let some kind := item.kind? then + acc := acc ++ ",\"kind\":" ++ (kind.ctorIdx + 1).repr + if let some textEdit := item.textEdit? then + acc := acc ++ ",\"edit\":" + acc := compressEditFast acc textEdit + if let some sortText := item.sortText? then + acc := acc ++ ",\"sortText\":" + acc := Json.renderString sortText acc + if let some data := item.data? then + acc := acc ++ ",\"data\":" + acc := compressItemDataFast acc data + if let some tags := item.tags? then + if h : tags.size > 0 then + acc := acc ++ ",\"tags\":[" + if tags.size == 1 then + acc := acc ++ (tags[0].ctorIdx + 1).repr + else + acc := compressCompletionTagsFast acc tags 0 + acc := acc ++ "]" + return acc ++ "}" + +def compressItemsFast + (acc : String) (items : Array ResolvableCompletionItem) (i : Nat) : + String := + if h : i < items.size then + let acc := compressItemFast acc items[i] + let acc := + if i < items.size - 1 then + acc ++ "," + else + acc + compressItemsFast acc items (i + 1) + else + acc + +/-- +Fast path for `(toJson l).compress` that skips the intermediate `Json` object. +Used in place of `(toJson l).compress` in the language server. +-/ +public def compressFast (l : ResolvableCompletionList) : String := + let acc := "{\"isIncomplete\":" ++ toString l.isIncomplete ++ ",\"items\":[" + let acc := compressItemsFast acc l.items 0 + acc ++ "]}" diff --git a/src/Lean/Server/Completion/CompletionItemData.lean b/src/Lean/Server/Completion/CompletionItemData.lean deleted file mode 100644 index ffddeed5e4..0000000000 --- a/src/Lean/Server/Completion/CompletionItemData.lean +++ /dev/null @@ -1,43 +0,0 @@ -/- -Copyright (c) 2024 Lean FRO, LLC. All rights reserved. -Released under Apache 2.0 license as described in the file LICENSE. -Authors: Marc Huisinga --/ -module - -prelude -public import Lean.Server.FileSource - -public section - -namespace Lean.Lsp - -/-- Used in `CompletionItem.data?`. -/ -structure CompletionItemData where - params : CompletionParams - deriving FromJson, ToJson - -/-- -Yields the file source of `item` by attempting to parse `item.data?` to `CompletionItemData` and -obtaining the original file source from its `params` fields. Panics if `item.data?` is not present -or cannot be parsed to `CompletionItemData`. -Used when `completionItem/resolve` requests pass the watchdog to decide which file worker to forward -the request to. -Since this function can panic and clients typically send `completionItem/resolve` requests for every -selected completion item, all completion items returned by the server in `textDocument/completion` -requests must have a `data?` field that can be parsed to `CompletionItemData`. --/ -def CompletionItem.getFileSource! (item : CompletionItem) : DocumentUri := - let r : Except String DocumentUri := do - let some data := item.data? - | throw s!"no data param on completion item {item.label}" - let data : CompletionItemData ← fromJson? data - return data.params.textDocument.uri - match r with - | Except.ok uri => uri - | Except.error e => panic! e - -instance : FileSource CompletionItem where - fileSource := CompletionItem.getFileSource! - -end Lean.Lsp diff --git a/src/Lean/Server/Completion/CompletionResolution.lean b/src/Lean/Server/Completion/CompletionResolution.lean index 1c8e6ce322..cc0f6179e2 100644 --- a/src/Lean/Server/Completion/CompletionResolution.lean +++ b/src/Lean/Server/Completion/CompletionResolution.lean @@ -6,7 +6,7 @@ Authors: Leonardo de Moura, Marc Huisinga module prelude -public import Lean.Server.Completion.CompletionItemData +public import Lean.Data.Lsp public import Lean.Server.Completion.CompletionInfoSelection public import Lean.Linter.Deprecated @@ -14,26 +14,6 @@ public section namespace Lean.Lsp -/-- -Identifier that is sent from the server to the client as part of the `CompletionItem.data?` field. -Needed to resolve the `CompletionItem` when the client sends a `completionItem/resolve` request -for that item, again containing the `data?` field provided by the server. --/ -inductive CompletionIdentifier where - | const (declName : Name) - | fvar (id : FVarId) - deriving FromJson, ToJson - -/-- -`CompletionItemData` that contains additional information to identify the item -in order to resolve it. --/ -structure ResolvableCompletionItemData extends CompletionItemData where - /-- Position of the completion info that this completion item was created from. -/ - cPos : Nat - id? : Option CompletionIdentifier - deriving FromJson, ToJson - private partial def consumeImplicitPrefix (e : Expr) (k : Expr → MetaM α) : MetaM α := do match e with | Expr.forallE n d b c => diff --git a/src/Lean/Server/Completion/EligibleHeaderDecls.lean b/src/Lean/Server/Completion/EligibleHeaderDecls.lean index e07fd259a8..f90b6a5116 100644 --- a/src/Lean/Server/Completion/EligibleHeaderDecls.lean +++ b/src/Lean/Server/Completion/EligibleHeaderDecls.lean @@ -7,46 +7,95 @@ module prelude public import Lean.Meta.CompletionName - +public import Lean.Data.Lsp.LanguageFeatures +public import Lean.AddDecl +public import Lean.ProjFns +public import Std.Sync.Mutex +import Lean.Linter.Deprecated public section namespace Lean.Server.Completion open Meta -abbrev EligibleHeaderDecls := Std.HashMap Name ConstantInfo +structure EligibleDecl where + info : ConstantInfo + kind : MetaM Lsp.CompletionItemKind + tags : MetaM (Array Lsp.CompletionItemTag) + +abbrev EligibleHeaderDecls := Std.HashMap Name EligibleDecl /-- Cached header declarations for which `allowCompletion headerEnv decl` is true. -/ -builtin_initialize eligibleHeaderDeclsRef : IO.Ref (Option EligibleHeaderDecls) ← - IO.mkRef none +builtin_initialize eligibleHeaderDeclsMutex : Std.Mutex (Option EligibleHeaderDecls) ← + Std.Mutex.new none + +def getCompletionKindForDecl (constInfo : ConstantInfo) + : MetaM Lsp.CompletionItemKind := do + let env ← getEnv + if constInfo.isCtor then + return .constructor + else if constInfo.isInductive then + if isClass env constInfo.name then + return .class + else if (← isEnumType constInfo.name) then + return .enum + else + return .struct + else if wasOriginallyTheorem env constInfo.name then + return .event + else if (← isProjectionFn constInfo.name) then + return .field + else + let isFunction : Bool ← withTheReader Core.Context ({ · with maxHeartbeats := 0 }) do + return (← whnf constInfo.type).isForall + if isFunction then + return .function + else + return .constant + +def getCompletionTagsForDecl (declName : Name) : MetaM (Array Lsp.CompletionItemTag) := do + if Linter.isDeprecated (← getEnv) declName then + return #[.deprecated] + else + return #[] /-- Returns the declarations in the header for which `allowCompletion env decl` is true, caching them if not already cached. -/ -def getEligibleHeaderDecls (env : Environment) : IO EligibleHeaderDecls := do - eligibleHeaderDeclsRef.modifyGet fun - | some eligibleHeaderDecls => (eligibleHeaderDecls, some eligibleHeaderDecls) +def getEligibleHeaderDecls (env : Environment) : MetaM EligibleHeaderDecls := do + eligibleHeaderDeclsMutex.atomically do + match ← get with + | some eligibleHeaderDecls => + return eligibleHeaderDecls | none => - let (_, eligibleHeaderDecls) := Id.run <| - StateT.run (s := {}) do - -- `map₁` are the header decls - env.constants.map₁.forM fun declName c => do - modify fun eligibleHeaderDecls => - if allowCompletion env declName then - eligibleHeaderDecls.insert declName c - else - eligibleHeaderDecls - (eligibleHeaderDecls, some eligibleHeaderDecls) + let mut eligibleHeaderDecls : EligibleHeaderDecls := {} + -- map₁ are the header decls + for (declName, c) in env.constants.map₁ do + if allowCompletion env declName then + let kind ← getCompletionKindForDecl c + let tags ← getCompletionTagsForDecl declName + eligibleHeaderDecls := eligibleHeaderDecls.insert declName { + info := c + kind := pure kind + tags := pure tags + } + set <| some eligibleHeaderDecls + return eligibleHeaderDecls /-- Iterate over all declarations that are allowed in completion results. -/ -def forEligibleDeclsM [Monad m] [MonadEnv m] [MonadLiftT (ST IO.RealWorld) m] - [MonadLiftT IO m] (f : Name → ConstantInfo → m PUnit) : m PUnit := do +def forEligibleDeclsM [Monad m] [MonadEnv m] [MonadLiftT MetaM m] + (f : Name → EligibleDecl → m PUnit) : m PUnit := do let env ← getEnv (← getEligibleHeaderDecls env).forM f -- map₂ are exactly the local decls env.constants.map₂.forM fun name c => do if allowCompletion env name then - f name c + f name { + info := c + -- Lazily compute the kind and the tags when needed. + kind := getCompletionKindForDecl c + tags := getCompletionTagsForDecl name + } /-- Checks whether this declaration can appear in completion results. -/ def allowCompletion (eligibleHeaderDecls : EligibleHeaderDecls) (env : Environment) diff --git a/src/Lean/Server/Completion/ImportCompletion.lean b/src/Lean/Server/Completion/ImportCompletion.lean index 57fde5c23e..a137af1525 100644 --- a/src/Lean/Server/Completion/ImportCompletion.lean +++ b/src/Lean/Server/Completion/ImportCompletion.lean @@ -8,14 +8,12 @@ module prelude public import Lean.Data.NameTrie public import Lean.Util.LakePath -public import Lean.Server.Completion.CompletionItemData +public import Lean.Data.Lsp public import Lean.Parser.Module meta import Lean.Parser.Module public section -public section - namespace ImportCompletion open Lean Lsp @@ -130,30 +128,30 @@ Sets the `data?` field of every `CompletionItem` in `completionList` using `para `completionItem/resolve` requests can be routed to the correct file worker even for `CompletionItem`s produced by the import completion. -/ -def addCompletionItemData (completionList : CompletionList) (params : CompletionParams) +def addCompletionItemData (mod : Name) (pos : Lsp.Position) (completionList : CompletionList) : CompletionList := - let data := { params : Lean.Lsp.CompletionItemData } + let data := { mod, pos : Lean.Lsp.ResolvableCompletionItemData } { completionList with items := completionList.items.map fun item => { item with data? := some <| toJson data } } -def find (text : FileMap) (headerStx : TSyntax ``Parser.Module.header) (params : CompletionParams) (availableImports : AvailableImports) : CompletionList := +def find (mod : Name) (pos : Lsp.Position) (text : FileMap) (headerStx : TSyntax ``Parser.Module.header) (availableImports : AvailableImports) : CompletionList := let availableImports := availableImports.toImportTrie - let completionPos := text.lspPosToUtf8Pos params.position + let completionPos := text.lspPosToUtf8Pos pos if isImportNameCompletionRequest headerStx completionPos then let allAvailableImportNameCompletions := availableImports.toArray.map ({ label := toString · }) - addCompletionItemData { isIncomplete := false, items := allAvailableImportNameCompletions } params + addCompletionItemData mod pos { isIncomplete := false, items := allAvailableImportNameCompletions } else if isImportCmdCompletionRequest headerStx completionPos then let allAvailableFullImportCompletions := availableImports.toArray.map ({ label := s!"import {·}" }) - addCompletionItemData { isIncomplete := false, items := allAvailableFullImportCompletions } params + addCompletionItemData mod pos { isIncomplete := false, items := allAvailableFullImportCompletions } else let completionNames : Array Name := computePartialImportCompletions headerStx completionPos availableImports let completions : Array CompletionItem := completionNames.map ({ label := toString · }) - addCompletionItemData { isIncomplete := false, items := completions } params + addCompletionItemData mod pos { isIncomplete := false, items := completions } -def computeCompletions (text : FileMap) (headerStx : TSyntax ``Parser.Module.header) (params : CompletionParams) +def computeCompletions (mod : Name) (pos : Lsp.Position) (text : FileMap) (headerStx : TSyntax ``Parser.Module.header) : IO CompletionList := do let availableImports ← collectAvailableImports - let completionList := find text headerStx params availableImports - return addCompletionItemData completionList params + let completionList := find mod pos text headerStx availableImports + return addCompletionItemData mod pos completionList end ImportCompletion diff --git a/src/Lean/Server/FileSource.lean b/src/Lean/Server/FileSource.lean index d0193ddfe3..b31c3228b6 100644 --- a/src/Lean/Server/FileSource.lean +++ b/src/Lean/Server/FileSource.lean @@ -13,24 +13,34 @@ public section namespace Lean.Lsp +inductive FileIdent where + | uri (uri : DocumentUri) + | mod (mod : Name) + deriving Inhabited + +instance : ToString FileIdent where + toString + | .uri uri => toString uri + | .mod mod => toString mod + class FileSource (α : Type) where - fileSource : α → DocumentUri + fileSource : α → FileIdent export FileSource (fileSource) instance : FileSource Location := - ⟨fun l => l.uri⟩ + ⟨fun l => .uri l.uri⟩ instance : FileSource TextDocumentIdentifier := - ⟨fun i => i.uri⟩ + ⟨fun i => .uri i.uri⟩ instance : FileSource VersionedTextDocumentIdentifier := - ⟨fun i => i.uri⟩ + ⟨fun i => .uri i.uri⟩ instance : FileSource TextDocumentEdit := ⟨fun e => fileSource e.textDocument⟩ instance : FileSource TextDocumentItem := - ⟨fun i => i.uri⟩ + ⟨fun i => .uri i.uri⟩ instance : FileSource TextDocumentPositionParams := ⟨fun p => fileSource p.textDocument⟩ @@ -66,7 +76,7 @@ instance : FileSource ReferenceParams := ⟨fun h => fileSource h.toTextDocumentPositionParams⟩ instance : FileSource WaitForDiagnosticsParams := - ⟨fun p => p.uri⟩ + ⟨fun p => .uri p.uri⟩ instance : FileSource DocumentHighlightParams := ⟨fun h => fileSource h.toTextDocumentPositionParams⟩ @@ -90,16 +100,16 @@ instance : FileSource PlainTermGoalParams where fileSource p := fileSource p.textDocument instance : FileSource RpcConnectParams where - fileSource p := p.uri + fileSource p := .uri p.uri instance : FileSource RpcCallParams where fileSource p := fileSource p.textDocument instance : FileSource RpcReleaseParams where - fileSource p := p.uri + fileSource p := .uri p.uri instance : FileSource RpcKeepAliveParams where - fileSource p := p.uri + fileSource p := .uri p.uri instance : FileSource CodeActionParams where fileSource p := fileSource p.textDocument @@ -110,4 +120,37 @@ instance : FileSource InlayHintParams where instance : FileSource SignatureHelpParams where fileSource p := fileSource p.textDocument +/-- +Yields the file source of `item` by attempting to obtain `mod : Name` from `item.data?`. \ +Panics if `item.data?` is not present or does not contain a `mod` field and the first element of a +`data?` array cannot be parsed to `Name`. +Used when `completionItem/resolve` requests pass the watchdog to decide which file worker to forward +the request to. +Since this function can panic and clients typically send `completionItem/resolve` requests for every +selected completion item, all completion items returned by the server in `textDocument/completion` +requests must have a `data?` field that has a `mod` field. +-/ +def CompletionItem.getFileSource! (item : CompletionItem) : FileIdent := + let r : Except String FileIdent := do + let some data := item.data? + | throw s!"no data param on completion item {item.label}" + match data with + | .obj _ => + -- In the language server, `data` is always an array, + -- but we also support having `mod` as an object field for + -- `chainLspRequestHandler` consumers. + let mod ← data.getObjValAs? Name "mod" + return .mod mod + | .arr _ => + let mod ← fromJson? <| ← data.getArrVal? 0 + return .mod mod + | _ => + throw s!"unexpected completion item data: {data}" + match r with + | Except.ok id => id + | Except.error e => panic! e + +instance : FileSource CompletionItem where + fileSource := CompletionItem.getFileSource! + end Lean.Lsp diff --git a/src/Lean/Server/FileWorker.lean b/src/Lean/Server/FileWorker.lean index 811a50d2f8..2d5aa388ee 100644 --- a/src/Lean/Server/FileWorker.lean +++ b/src/Lean/Server/FileWorker.lean @@ -72,12 +72,25 @@ structure PartialHandlerInfo where pendingRefreshInfo? : Option RefreshInfo deriving Inhabited +structure OutputMessage where + msg? : Option JsonRpc.Message + serialized : String + deriving Inhabited + +def OutputMessage.ofLspResponse (id : RequestID) (r : SerializedLspResponse) : OutputMessage where + msg? := r.response?.map (.response id ·) + serialized := r.toSerializedMessage id + +def OutputMessage.ofMsg (msg : JsonRpc.Message) : OutputMessage where + msg? := msg + serialized := toJson msg |>.compress + open Widget in structure WorkerContext where /-- Synchronized output channel for LSP messages. Notifications for outdated versions are discarded on read. -/ - chanOut : Std.Channel JsonRpc.Message + chanOut : Std.Channel OutputMessage /-- Latest document version received by the client, used for filtering out notifications from previous versions. @@ -213,7 +226,7 @@ This option can only be set on the command line, not in the lakefile or via `set stickyInteractiveDiagnostics ++ docInteractiveDiagnostics |>.map (·.toDiagnostic) let notification := mkPublishDiagnosticsNotification doc.meta diagnostics - ctx.chanOut.sync.send notification + ctx.chanOut.sync.send <| .ofMsg notification open Language in /-- @@ -238,14 +251,14 @@ This option can only be set on the command line, not in the lakefile or via `set return () -- callback at the end of reporting if st.hasFatal then - ctx.chanOut.send <| mkFileProgressAtPosNotification doc.meta 0 .fatalError + ctx.chanOut.send <| .ofMsg <| mkFileProgressAtPosNotification doc.meta 0 .fatalError else - ctx.chanOut.send <| mkFileProgressDoneNotification doc.meta + ctx.chanOut.send <| .ofMsg <| mkFileProgressDoneNotification doc.meta unless st.hasBlocked do -- "Debouncing 4." publishDiagnostics ctx doc -- This will overwrite existing ilean info for the file, in case something -- went wrong during the incremental updates. - ctx.chanOut.sync.send (← mkIleanInfoFinalNotification doc.meta st.allInfoTrees) + ctx.chanOut.sync.send <| .ofMsg <| ← mkIleanInfoFinalNotification doc.meta st.allInfoTrees return () where /-- @@ -322,7 +335,7 @@ This option can only be set on the command line, not in the lakefile or via `set if let some itree := node.element.infoTree? then let mut newInfoTrees := (← get).newInfoTrees.push itree if (← get).hasBlocked then - ctx.chanOut.sync.send (← mkIleanInfoUpdateNotification doc.meta newInfoTrees) + ctx.chanOut.sync.send <| .ofMsg <| ← mkIleanInfoUpdateNotification doc.meta newInfoTrees newInfoTrees := #[] modify fun st => { st with newInfoTrees, allInfoTrees := st.allInfoTrees.push itree } @@ -341,7 +354,7 @@ This option can only be set on the command line, not in the lakefile or via `set | none => rs.push r let ranges := ranges.map (·.toLspRange doc.meta.text) let notifs := ranges.map ({ range := ·, kind := .processing }) - ctx.chanOut.sync.send <| mkFileProgressNotification doc.meta notifs + ctx.chanOut.sync.send <| .ofMsg <| mkFileProgressNotification doc.meta notifs end Elab @@ -379,7 +392,7 @@ Lake for processing imports. def setupImports (doc : DocumentMeta) (cmdlineOpts : Options) - (chanOut : Std.Channel JsonRpc.Message) + (chanOut : Std.Channel OutputMessage) (stx : Elab.HeaderSyntax) : Language.ProcessingT IO (Except Language.Lean.HeaderProcessedSnapshot SetupImportsResult) := do let importsAlreadyLoaded ← importsLoadedRef.modifyGet ((·, true)) @@ -393,7 +406,7 @@ def setupImports return .error { diagnostics := .empty, result? := none, metaSnap := default } let header := stx.toModuleHeader - chanOut.sync.send <| mkInitialIleanInfoUpdateNotification doc <| collectImports stx + chanOut.sync.send <| .ofMsg <| mkInitialIleanInfoUpdateNotification doc <| collectImports stx let fileSetupResult ← setupFile doc header fun stderrLine => do let progressDiagnostic := { range := ⟨⟨0, 0⟩, ⟨1, 0⟩⟩ @@ -402,9 +415,9 @@ def setupImports severity? := DiagnosticSeverity.information message := stderrLine } - chanOut.sync.send <| mkPublishDiagnosticsNotification doc #[progressDiagnostic] + chanOut.sync.send <| .ofMsg <| mkPublishDiagnosticsNotification doc #[progressDiagnostic] -- clear progress notifications in the end - chanOut.sync.send <| mkPublishDiagnosticsNotification doc #[] + chanOut.sync.send <| .ofMsg <| mkPublishDiagnosticsNotification doc #[] match fileSetupResult.kind with | .importsOutOfDate => return .error { @@ -466,7 +479,7 @@ section Initialization let _ ← ServerTask.IO.asTask do let importClosure ← IO.lazyPure fun _ => getImportClosure? initSnap let importClosure ← importClosure.filterMapM (documentUriFromModule? ·) - chanOut.send <| mkImportClosureNotification importClosure + chanOut.send <| .ofMsg <| mkImportClosureNotification importClosure let ctx := { chanOut hLog := e @@ -498,20 +511,21 @@ section Initialization the output FS stream after discarding outdated notifications. This is the only component of the worker with access to the output stream, so we can synchronize messages from parallel elaboration tasks here. -/ - mkLspOutputChannel maxDocVersion : IO (Std.Channel JsonRpc.Message) := do + mkLspOutputChannel maxDocVersion : IO (Std.Channel OutputMessage) := do let chanOut ← Std.Channel.new - let _ ← chanOut.forAsync (prio := .dedicated) fun msg => do + let _ ← chanOut.forAsync (prio := .dedicated) fun ⟨msg?, serialized⟩ => do -- discard outdated notifications; note that in contrast to responses, notifications can -- always be silently discarded - let version? : Option Int := do match msg with - | .notification "textDocument/publishDiagnostics" (some params) => + let version? : Option Int := do + match msg? with + | some (.notification "textDocument/publishDiagnostics" (some params)) => let params : PublishDiagnosticsParams ← fromJson? (toJson params) |>.toOption params.version? - | .notification "$/lean/fileProgress" (some params) => + | some (.notification "$/lean/fileProgress" (some params)) => let params : LeanFileProgressParams ← fromJson? (toJson params) |>.toOption params.textDocument.version? - | .notification "$/lean/ileanInfoUpdate" (some params) - | .notification "$/lean/ileanInfoFinal" (some params) => + | some (.notification "$/lean/ileanInfoUpdate" (some params)) + | some (.notification "$/lean/ileanInfoFinal" (some params)) => let params : LeanIleanInfoParams ← fromJson? (toJson params) |>.toOption some params.version | _ => none @@ -521,7 +535,7 @@ section Initialization -- note that because of `server.reportDelayMs`, we cannot simply set `maxDocVersion` here -- as that would allow outdated messages to be reported until the delay is over - o.writeLspMessage msg |>.catchExceptions (fun _ => pure ()) + o.writeSerializedLspMessage serialized |>.catchExceptions (fun _ => pure ()) return chanOut getImportClosure? (snap : Language.Lean.InitialSnapshot) : Array Name := Id.run do @@ -545,7 +559,7 @@ section ServerRequests (freshRequestId, freshRequestId + 1) let responseTask ← ctx.initPendingServerRequest responseType freshRequestId let r : JsonRpc.Request paramType := ⟨freshRequestId, method, param⟩ - ctx.chanOut.sync.send r + ctx.chanOut.sync.send <| .ofMsg r return responseTask def sendUntypedServerRequest @@ -692,14 +706,15 @@ section MessageHandling : WorkerM (ServerTask (Except Error AvailableImportsCache)) := do let ctx ← read let st ← get + let mod := st.doc.meta.mod let text := st.doc.meta.text match st.importCachingTask? with | none => ServerTask.IO.asTask do let availableImports ← ImportCompletion.collectAvailableImports let lastRequestTimestampMs ← IO.monoMsNow - let completions := ImportCompletion.find text ⟨st.doc.initSnap.stx⟩ params availableImports - ctx.chanOut.sync.send <| .response id (toJson completions) + let completions := ImportCompletion.find mod params.position text ⟨st.doc.initSnap.stx⟩ availableImports + ctx.chanOut.sync.send <| .ofMsg <| .response id (toJson completions) pure { availableImports, lastRequestTimestampMs : AvailableImportsCache } | some task => ServerTask.IO.mapTaskCostly (t := task) fun (result : Except Error AvailableImportsCache) => do @@ -708,8 +723,8 @@ section MessageHandling if timestampNowMs - lastRequestTimestampMs >= 10000 then availableImports ← ImportCompletion.collectAvailableImports lastRequestTimestampMs := timestampNowMs - let completions := ImportCompletion.find text ⟨st.doc.initSnap.stx⟩ params availableImports - ctx.chanOut.sync.send <| .response id (toJson completions) + let completions := ImportCompletion.find mod params.position text ⟨st.doc.initSnap.stx⟩ availableImports + ctx.chanOut.sync.send <| .ofMsg <| .response id (toJson completions) pure { availableImports, lastRequestTimestampMs : AvailableImportsCache } def handleStatefulPreRequestSpecialCases (id : RequestID) (method : String) (params : Json) : WorkerM Bool := do @@ -721,7 +736,7 @@ section MessageHandling | "$/lean/rpc/connect" => let ps ← parseParams RpcConnectParams params let resp ← handleRpcConnect ps - ctx.chanOut.sync.send <| .response id (toJson resp) + ctx.chanOut.sync.send <| .ofMsg <| .response id (toJson resp) return true | "textDocument/completion" => let params ← parseParams CompletionParams params @@ -734,7 +749,7 @@ section MessageHandling | _ => return false catch e => - ctx.chanOut.sync.send <| .responseError id .internalError (toString e) none + ctx.chanOut.sync.send <| .ofMsg <| .responseError id .internalError (toString e) none return true open Widget RequestM Language in @@ -766,7 +781,7 @@ section MessageHandling def handlePreRequestSpecialCases? (ctx : WorkerContext) (st : WorkerState) (id : RequestID) (method : String) (params : Json) - : RequestM (Option (RequestTask (LspResponse Json))) := do + : RequestM (Option (RequestTask SerializedLspResponse)) := do match method with | "$/lean/rpc/call" => let params ← RequestM.parseRequestParams Lsp.RpcCallParams params @@ -778,7 +793,7 @@ section MessageHandling let resp ← handleGetInteractiveDiagnosticsRequest ctx params let resp ← seshRef.modifyGet fun st => rpcEncode resp st.objects |>.map (·) ({st with objects := ·}) - return some <| .pure { response := resp, isComplete := true } + return some <| .pure { response? := resp, serialized := resp.compress, isComplete := true } | "codeAction/resolve" => let params ← RequestM.parseRequestParams CodeAction params let some data := params.data? @@ -789,36 +804,41 @@ section MessageHandling return some <| ← RequestM.asTask do let unknownIdentifierRanges ← waitAllUnknownIdentifierRanges st.doc if unknownIdentifierRanges.isEmpty then - return { response := toJson params, isComplete := true } + let p := toJson params + return { response? := p, serialized := p.compress, isComplete := true } let action? ← handleResolveImportAllUnknownIdentifiersCodeAction? id params unknownIdentifierRanges let action := action?.getD params - return { response := toJson action, isComplete := true } + let action := toJson action + return { response? := action, serialized := action.compress, isComplete := true } | _ => return none def handlePostRequestSpecialCases (id : RequestID) (method : String) (params : Json) - (task : RequestTask (LspResponse Json)) : RequestM (RequestTask (LspResponse Json)) := do + (task : RequestTask SerializedLspResponse) : RequestM (RequestTask SerializedLspResponse) := do let doc ← RequestM.readDoc match method with | "textDocument/codeAction" => let .ok (params : CodeActionParams) := fromJson? params | return task RequestM.mapRequestTaskCostly task fun r => do + let some response := r.response? + | return r let isSourceAction := params.context.only?.any fun only => only.contains "source" || only.contains "source.organizeImports" if isSourceAction then let unknownIdentifierRanges ← waitAllUnknownIdentifierRanges doc if unknownIdentifierRanges.isEmpty then return r - let .ok (codeActions : Array CodeAction) := fromJson? r.response + let .ok (codeActions : Array CodeAction) := fromJson? response | return r - return { r with response := toJson <| codeActions.push <| importAllUnknownIdentifiersCodeAction params "source.organizeImports" } + let response := toJson <| codeActions.push <| importAllUnknownIdentifiersCodeAction params "source.organizeImports" + return { r with response? := response, serialized := response.compress } else let requestedRange := doc.meta.text.lspRangeToUtf8Range params.range let unknownIdentifierRanges ← waitUnknownIdentifierRanges doc requestedRange if unknownIdentifierRanges.isEmpty then return r - let .ok (codeActions : Array CodeAction) := fromJson? r.response + let .ok (codeActions : Array CodeAction) := fromJson? response | return r RequestM.checkCancelled -- Since computing the unknown identifier code actions is *really* expensive, @@ -826,12 +846,13 @@ section MessageHandling IO.sleep 1000 RequestM.checkCancelled let unknownIdentifierCodeActions ← handleUnknownIdentifierCodeAction id params requestedRange - return { r with response := toJson <| codeActions ++ unknownIdentifierCodeActions } + let response := toJson <| codeActions ++ unknownIdentifierCodeActions + return { r with response? := response, serialized := response.compress } | _ => return task def emitRequestResponse - (requestTask? : Except RequestError (RequestTask (LspResponse Json))) + (requestTask? : Except RequestError (RequestTask SerializedLspResponse)) (cancelTk : RequestCancellationToken) (id : RequestID) (method : String) @@ -839,7 +860,7 @@ section MessageHandling let ctx ← read match requestTask? with | Except.error e => - emitResponse ctx (isComplete := false) <| e.toLspResponseError id + emitResponse ctx (isComplete := false) <| .ofMsg <| e.toLspResponseError id return ServerTask.pure <| .ok () | Except.ok requestTask => ServerTask.IO.mapTaskCheap (t := requestTask) fun @@ -848,13 +869,13 @@ section MessageHandling -- Try not to emit a partial response if this request was cancelled. -- Clients usually discard responses for requests that they cancelled anyways, -- but it's still good to send less over the wire in this case. - emitResponse ctx (isComplete := false) <| RequestError.requestCancelled.toLspResponseError id + emitResponse ctx (isComplete := false) <| .ofMsg <| RequestError.requestCancelled.toLspResponseError id return - emitResponse ctx (isComplete := r.isComplete) <| .response id (toJson r.response) + emitResponse ctx (isComplete := r.isComplete) <| .ofLspResponse id r | Except.error e => - emitResponse ctx (isComplete := false) <| e.toLspResponseError id + emitResponse ctx (isComplete := false) <| .ofMsg <| e.toLspResponseError id where - emitResponse (ctx : WorkerContext) (m : JsonRpc.Message) (isComplete : Bool) : IO Unit := do + emitResponse (ctx : WorkerContext) (m : OutputMessage) (isComplete : Bool) : IO Unit := do ctx.chanOut.sync.send m let timestamp ← IO.monoMsNow ctx.modifyPartialHandler method fun h => { h with diff --git a/src/Lean/Server/FileWorker/RequestHandling.lean b/src/Lean/Server/FileWorker/RequestHandling.lean index bfcb106c0f..a079a494d6 100644 --- a/src/Lean/Server/FileWorker/RequestHandling.lean +++ b/src/Lean/Server/FileWorker/RequestHandling.lean @@ -13,6 +13,7 @@ public import Lean.Server.FileWorker.SemanticHighlighting public import Lean.Server.FileWorker.SignatureHelp public import Lean.Server.Completion public import Lean.Server.References +public import Lean.Server.Completion.CompletionItemCompression meta import Lean.Parser.Module public import Lean.Widget.Diff @@ -40,7 +41,7 @@ def findCompletionCmdDataAtPos findCmdDataAtPos doc pos (includeStop := true) def handleCompletion (p : CompletionParams) - : RequestM (RequestTask CompletionList) := do + : RequestM (RequestTask ResolvableCompletionList) := do let doc ← readDoc let text := doc.meta.text let pos := text.lspPosToUtf8Pos p.position @@ -48,7 +49,7 @@ def handleCompletion (p : CompletionParams) mapTaskCostly (findCompletionCmdDataAtPos doc pos) fun cmdData? => do let some (cmdStx, infoTree) := cmdData? | return { items := #[], isIncomplete := true } - Completion.find? p doc.meta.text pos cmdStx infoTree caps + Completion.find? doc.meta.mod p.position doc.meta.text pos cmdStx infoTree caps /-- Handles `completionItem/resolve` requests that are sent by the client after the user selects @@ -65,11 +66,13 @@ def handleCompletionItemResolve (item : CompletionItem) | return .pure item let some id := data.id? | return .pure item - let pos := text.lspPosToUtf8Pos data.params.position + let some cPos := data.cPos? + | return .pure item + let pos := text.lspPosToUtf8Pos data.pos mapTaskCostly (findCompletionCmdDataAtPos doc pos) fun cmdData? => do let some (cmdStx, infoTree) := cmdData? | return item - Completion.resolveCompletionItem? text pos cmdStx infoTree item id data.cPos + Completion.resolveCompletionItem? text pos cmdStx infoTree item id cPos open Elab in def handleHover (p : HoverParams) @@ -485,8 +488,9 @@ builtin_initialize registerLspRequestHandler "textDocument/completion" CompletionParams - CompletionList + ResolvableCompletionList handleCompletion + (serialize? := some (·.compressFast)) registerLspRequestHandler "completionItem/resolve" CompletionItem diff --git a/src/Lean/Server/Requests.lean b/src/Lean/Server/Requests.lean index 5a59590322..7fc0dcc822 100644 --- a/src/Lean/Server/Requests.lean +++ b/src/Lean/Server/Requests.lean @@ -451,9 +451,28 @@ For details of how to register one, see `registerLspRequestHandler`. -/ section HandlerTable open Lsp +structure LspResponse (α : Type) where + response : α + isComplete : Bool + +structure SerializedLspResponse where + response? : Option Json + serialized : String + isComplete : Bool + +-- Custom serialization that uses `r.serialized` in place of `response`. +-- Identical to `Json.compress` for the JSON of `JsonRpc.Message.response ..`. +def SerializedLspResponse.toSerializedMessage + (id : JsonRpc.RequestID) (r : SerializedLspResponse) : String := + "{" ++ + s!"\"id\":{toJson id |>.compress}," ++ + s!"\"jsonrpc\":\"2.0\"," ++ + s!"\"result\":{r.serialized}" + ++ "}" + structure RequestHandler where - fileSource : Json → Except RequestError Lsp.DocumentUri - handle : Json → RequestM (RequestTask Json) + fileSource : Json → Except RequestError FileIdent + handle : Json → RequestM (RequestTask SerializedLspResponse) builtin_initialize requestHandlers : IO.Ref (PersistentHashMap String RequestHandler) ← IO.mkRef {} @@ -466,6 +485,8 @@ A registration consists of: - a type of JSON-serializable response data `respType` - an actual `handler` which runs in the `RequestM` monad and is expected to produce an asynchronous `RequestTask` which does any waiting/computation +- an optional `serialize` function which can be used to serialize `respType` directly to a string + for performance reasons, skipping `Json` A handler task may be cancelled at any time, so it should check the cancellation token when possible to handle this cooperatively. Any exceptions thrown in a request handler will be reported to the client @@ -473,7 +494,9 @@ as LSP error responses. -/ def registerLspRequestHandler (method : String) paramType [FromJson paramType] [FileSource paramType] respType [ToJson respType] - (handler : paramType → RequestM (RequestTask respType)) : IO Unit := do + (handler : paramType → RequestM (RequestTask respType)) + (serialize? : Option (respType → String) := none) : + IO Unit := do if !(← Lean.initializing) then throw <| IO.userError s!"Failed to register LSP request handler for '{method}': only possible during initialization" if (← requestHandlers.get).contains method then @@ -483,7 +506,20 @@ def registerLspRequestHandler (method : String) let handle := fun j => do let params ← RequestM.parseRequestParams paramType j let t ← handler params - pure <| t.mapCheap <| Except.map ToJson.toJson + pure <| t.mapCheap <| Except.map fun r => + if let some serialize := serialize? then + { + response? := none + serialized := serialize r + isComplete := true + } + else + let j := toJson r + { + response? := some j + serialized := j.compress + isComplete := true + } requestHandlers.modify fun rhs => rhs.insert method { fileSource, handle } @@ -506,11 +542,26 @@ def chainLspRequestHandler (method : String) if let some oldHandler ← lookupLspRequestHandler method then let handle := fun j => do let t ← oldHandler.handle j - let t := t.mapCheap fun x => x.bind fun j => FromJson.fromJson? j |>.mapError fun e => - .internalError s!"Failed to parse original LSP response for `{method}` when chaining: {e}" + let t := t.mapCheap fun x => + x.bind fun j => do + let response ← + match j.response? with + | none => + Json.parse j.serialized |>.mapError fun e => + .internalError s!"Failed to parse original LSP response JSON for `{method}` when chaining: {e}" + | some response => + pure response + FromJson.fromJson? response |>.mapError fun e => + .internalError s!"Failed to parse original LSP response for `{method}` when chaining: {e}" let params ← RequestM.parseRequestParams paramType j let t ← handler params t - pure <| t.mapCheap <| Except.map ToJson.toJson + pure <| t.mapCheap <| Except.map fun r => + let j := toJson r + { + response? := some j + serialized := j.compress + isComplete := true + } requestHandlers.modify fun rhs => rhs.insert method {oldHandler with handle} else @@ -531,18 +582,14 @@ inductive RequestHandlerCompleteness where -/ | «partial» (refreshMethod : String) (refreshIntervalMs : Nat) -structure LspResponse (α : Type) where - response : α - isComplete : Bool - structure StatefulRequestHandler where - fileSource : Json → Except RequestError Lsp.DocumentUri + fileSource : Json → Except RequestError FileIdent /-- `handle` with explicit state management for chaining request handlers. This function is pure w.r.t. `lastTaskMutex` and `stateRef`, but not `RequestM`. -/ - pureHandle : Json → Dynamic → RequestM (LspResponse Json × Dynamic) - handle : Json → RequestM (RequestTask (LspResponse Json)) + pureHandle : Json → Dynamic → RequestM (SerializedLspResponse × Dynamic) + handle : Json → RequestM (RequestTask SerializedLspResponse) /-- `onDidChange` with explicit state management for chaining request handlers. This function is pure w.r.t. `lastTaskMutex` and `stateRef`, but not `RequestM`. @@ -588,13 +635,14 @@ private def overrideStatefulLspRequestHandler let initState := Dynamic.mk initState let stateRef ← IO.mkRef initState - let pureHandle : Json → Dynamic → RequestM (LspResponse Json × Dynamic) := fun param state => do + let pureHandle : Json → Dynamic → RequestM (SerializedLspResponse × Dynamic) := fun param state => do let param ← RequestM.parseRequestParams paramType param let state ← getState! method state stateType let (r, state') ← handler param state - return ({ r with response := toJson r.response }, Dynamic.mk state') + let response := toJson r.response + return ({ r with response? := some response, serialized := response.compress }, Dynamic.mk state') - let handle : Json → RequestM (RequestTask (LspResponse Json)) := fun param => lastTaskMutex.atomically do + let handle : Json → RequestM (RequestTask SerializedLspResponse) := fun param => lastTaskMutex.atomically do let lastTask ← get let requestTask ← RequestM.mapTaskCostly lastTask fun () => do let state ← stateRef.get @@ -691,7 +739,12 @@ def chainStatefulLspRequestHandler (method : String) let initState ← getIOState! method oldHandler.initState stateType let handle (p : paramType) (s : stateType) : RequestM (LspResponse respType × stateType) := do let (r, s) ← oldHandle (toJson p) (Dynamic.mk s) - let .ok response := fromJson? r.response + let .ok response := + match r.response? with + | none => Json.parse r.serialized + | some response => .ok response + | throw <| RequestError.internalError "Failed to parse response of previous request handler when chaining stateful LSP request handlers" + let .ok response := fromJson? response | throw <| RequestError.internalError "Failed to convert response of previous request handler when chaining stateful LSP request handlers" let r := { r with response := response } let s ← getState! method s stateType @@ -709,7 +762,7 @@ def handleOnDidChange (p : DidChangeTextDocumentParams) : RequestM Unit := do (← statefulRequestHandlers.get).forM fun _ handler => do handler.onDidChange p -def handleLspRequest (method : String) (params : Json) : RequestM (RequestTask (LspResponse Json)) := do +def handleLspRequest (method : String) (params : Json) : RequestM (RequestTask SerializedLspResponse) := do if ← isStatefulLspRequestMethod method then match ← lookupStatefulLspRequestHandler method with | none => @@ -721,11 +774,9 @@ def handleLspRequest (method : String) (params : Json) : RequestM (RequestTask ( | none => throw <| .internalError s!"request '{method}' routed through watchdog but unknown in worker; are both using the same plugins?" - | some rh => - let t ← rh.handle params - return t.mapCheap fun r => r.map ({response := ·, isComplete := true }) + | some rh => rh.handle params -def routeLspRequest (method : String) (params : Json) : IO (Except RequestError DocumentUri) := do +def routeLspRequest (method : String) (params : Json) : IO (Except RequestError FileIdent) := do if ← isStatefulLspRequestMethod method then match ← lookupStatefulLspRequestHandler method with | none => return Except.error <| RequestError.methodNotFound method diff --git a/src/Lean/Server/Watchdog.lean b/src/Lean/Server/Watchdog.lean index c7eeb1caad..570cf10e0b 100644 --- a/src/Lean/Server/Watchdog.lean +++ b/src/Lean/Server/Watchdog.lean @@ -269,7 +269,31 @@ section FileWorker end FileWorker section ServerM - abbrev FileWorkerMap := Std.TreeMap DocumentUri FileWorker + structure FileWorkerMap where + fileWorkers : Std.TreeMap DocumentUri FileWorker := {} + uriByMod : Std.TreeMap Name DocumentUri Name.quickCmp := {} + + def FileWorkerMap.getUri? (m : FileWorkerMap) (id : FileIdent) : Option DocumentUri := + match id with + | .uri uri => uri + | .mod mod => m.uriByMod.get? mod + + def FileWorkerMap.insert (m : FileWorkerMap) (uri : DocumentUri) (fw : FileWorker) : + FileWorkerMap where + fileWorkers := m.fileWorkers.insert uri fw + uriByMod := m.uriByMod.insert fw.doc.mod uri + + def FileWorkerMap.erase (m : FileWorkerMap) (uri : DocumentUri) : FileWorkerMap := Id.run do + let some fw := m.fileWorkers.get? uri + | return m + return { + fileWorkers := m.fileWorkers.erase uri + uriByMod := m.uriByMod.erase fw.doc.mod + } + + def FileWorkerMap.get? (m : FileWorkerMap) (uri : DocumentUri) : Option FileWorker := do + m.fileWorkers.get? uri + abbrev ImportMap := Std.TreeMap DocumentUri (Std.TreeSet DocumentUri) /-- Global import data for all open files managed by this watchdog. -/ @@ -416,9 +440,17 @@ section ServerM let rd ← rd.modifyReferencesM (m := IO) f set rd + def getFileWorkerUri? (id : FileIdent) : ServerM (Option DocumentUri) := + return (← (← read).fileWorkersRef.get).getUri? id + def getFileWorker? (uri : DocumentUri) : ServerM (Option FileWorker) := return (← (←read).fileWorkersRef.get).get? uri + def fileWorkerExists (id : FileIdent) : ServerM Bool := do + let some uri ← getFileWorkerUri? id + | return false + return (← getFileWorker? uri).isSome + def getFileWorkerMod? (uri : DocumentUri) : ServerM (Option Name) := do return (← getFileWorker? uri).map (·.doc.mod) @@ -654,40 +686,72 @@ section ServerM definitions := definitions.push definitionLocation return definitions - def handleResponseSpecialCases (req : JsonRpc.Request Json) (resp : JsonRpc.Response Json) : - ServerM (JsonRpc.Response Json) := do + def parseRequestParams? (α : Type) [FromJson α] (request : String) : Except String α := do + let j ← Json.parse request + let msg : JsonRpc.Message ← fromJson? j + match msg with + | .request _ _ params => + fromJson? (toJson params) + | _ => + Except.error "Got message that isn't a request in `parseRequestParams?`." + + def parseNotificationParams? (α : Type) [FromJson α] (notification : String) : Except String α := do + let j ← Json.parse notification + let msg : JsonRpc.Message ← fromJson? j + match msg with + | .notification _ params => + fromJson? (toJson params) + | _ => + Except.error "Got message that isn't a notification in `parseNotificationParams?`." + + def parseResponseResult? (α : Type) [FromJson α] (response : String) : Except String α := do + let j ← Json.parse response + let msg : JsonRpc.Message ← fromJson? j + match msg with + | .response _ result => + fromJson? result + | _ => + Except.error "Got message that isn't a response in `parseResponseResult?`." + + def bendLocationLinks (req : JsonRpc.Request Json) (r : Array LeanLocationLink) : + ServerM Json := do + let refs ← getReferences + let r : Array LeanLocationLink := r.filterMap fun ll => Id.run do + let some ident := ll.ident? + | return ll + let ident : RefIdent := .const ident.module.toString ident.decl.toString + let some definitionInfo := refs.definitionOf? ident + | return ll + let newTargetRange := definitionInfo.location.range + return some { + ll with toLocationLink := { + originSelectionRange? := ll.originSelectionRange? + targetUri := definitionInfo.location.uri + targetRange := newTargetRange + targetSelectionRange := newTargetRange + } + } + if r.all (·.isDefault) then + -- The file worker produced fallback location links. + -- Let's see if we can obtain better ones using the .ileans, just to be safe. + let params' ← parseParams TextDocumentPositionParams req.param + let definitions ← findDefinitions params' + if ! definitions.isEmpty then + return toJson definitions + return toJson <| r.map (·.toLocationLink) + + def handleResponseSpecialCases (req : JsonRpc.Request Json) (resp : String) : + ServerM String := do match req.method with | "textDocument/definition" | "textDocument/declaration" | "textDocument/typeDefinition" => - let r : Array LeanLocationLink := - match fromJson? resp.result with - | .ok r => r - | .error e => panic! s!"Expected `LeanLocationLink` in file worker response to definition request. Error: {e}. Got: {resp.result.compress}." - let refs ← getReferences - let r : Array LeanLocationLink := r.filterMap fun ll => Id.run do - let some ident := ll.ident? - | return ll - let ident : RefIdent := .const ident.module.toString ident.decl.toString - let some definitionInfo := refs.definitionOf? ident - | return ll - let newTargetRange := definitionInfo.location.range - return some { - ll with toLocationLink := { - originSelectionRange? := ll.originSelectionRange? - targetUri := definitionInfo.location.uri - targetRange := newTargetRange - targetSelectionRange := newTargetRange - } - } - if r.all (·.isDefault) then - -- The file worker produced fallback location links. - -- Let's see if we can obtain better ones using the .ileans, just to be safe. - let params' ← parseParams TextDocumentPositionParams req.param - let definitions ← findDefinitions params' - if ! definitions.isEmpty then - return { resp with result := toJson definitions } - return { resp with result := toJson <| r.map (·.toLocationLink) } + match parseResponseResult? (Array LeanLocationLink) resp with + | .ok r => + let result ← bendLocationLinks req r + return JsonRpc.Message.response req.id result |> toJson |>.compress + | .error _ => + return resp | _ => return resp @@ -704,7 +768,7 @@ section ServerM while true do let msg ← try - fw.stdout.readLspMessage + fw.stdout.readLspMessageAsString catch _ => let exitCode ← fw.waitForProc -- Remove surviving descendant processes, if any, such as from nested builds. @@ -715,18 +779,21 @@ section ServerM | 0 => return .terminated | 2 => return .importsChanged | _ => return .crashed exitCode + let .ok metaData := parseMessageMetaData msg + | continue let (_, pendingWorkerToWatchdogRequests') ← - StateT.run (s := pendingWorkerToWatchdogRequests) <| handleMessage msg + StateT.run (s := pendingWorkerToWatchdogRequests) <| handleMessage msg metaData pendingWorkerToWatchdogRequests := ∅ for (id, task, cancelTk) in pendingWorkerToWatchdogRequests' do if ← task.hasFinished then continue pendingWorkerToWatchdogRequests := pendingWorkerToWatchdogRequests.insert id (task, cancelTk) + return .terminated - handleMessage (msg : JsonRpc.Message) + handleMessage (msg : String) (metaData : MessageMetaData) : StateT (Std.TreeMap RequestID (ServerTask Unit × CancelToken)) ServerM Unit := -- When the file worker is terminated by the main thread, the client can immediately launch -- another file worker using `didOpen`. In this case, even when this task and the old file @@ -740,8 +807,8 @@ section ServerM return -- Re. `o.writeLspMessage msg`: -- Writes to Lean I/O channels are atomic, so these won't trample on each other. - match msg with - | Message.response id result => do + match metaData with + | .response id => do let req? ← eraseGetPendingRequest uri id -- In the rare scenario that we detect a file worker crash on the main thread and this task -- still has a response to process, it could theoretically happen that we restart the file @@ -749,44 +816,40 @@ section ServerM -- This ensures that this scenario can't occur, and we only emit responses for requests -- that were still pending. if let some req := req? then - let resp ← handleResponseSpecialCases req { id, result } - o.writeLspMessage resp - | Message.responseError id code _ _ => do + let resp ← handleResponseSpecialCases req msg + o.writeSerializedLspMessage resp + | .responseError id code _ _ => do let wasPending ← erasePendingRequest uri id if code matches .requestCancelled then let pendingWorkerToWatchdogRequests ← getThe (Std.TreeMap RequestID (ServerTask Unit × CancelToken)) if let some (_, cancelTk) := pendingWorkerToWatchdogRequests.get? id then cancelTk.set if wasPending then - o.writeLspMessage msg - | Message.request id method params? => + o.writeSerializedLspMessage msg + | .request id method => if method == "$/lean/queryModule" then - if let some params := params? then - if let .ok (params : LeanQueryModuleParams) := fromJson? <| toJson params then - let (task, cancelTk) ← handleQueryModule fw id params - modifyThe (Std.TreeMap RequestID (ServerTask Unit × CancelToken)) (·.insert params.sourceRequestID (task, cancelTk)) + if let .ok params := parseRequestParams? LeanQueryModuleParams msg then + let (task, cancelTk) ← handleQueryModule fw id params + modifyThe (Std.TreeMap RequestID (ServerTask Unit × CancelToken)) (·.insert params.sourceRequestID (task, cancelTk)) else - let globalID ← (← read).serverRequestData.modifyGet - (·.trackOutboundRequest fw.doc.uri id) - o.writeLspMessage (Message.request globalID method params?) - | Message.notification "$/lean/ileanHeaderInfo" params => - if let some params := params then - if let Except.ok params := FromJson.fromJson? <| ToJson.toJson params then - handleILeanHeaderInfo fw params - | Message.notification "$/lean/ileanInfoUpdate" params => - if let some params := params then - if let Except.ok params := FromJson.fromJson? <| ToJson.toJson params then - handleIleanInfoUpdate fw params - | Message.notification "$/lean/ileanInfoFinal" params => - if let some params := params then - if let Except.ok params := FromJson.fromJson? <| ToJson.toJson params then - handleIleanInfoFinal fw params - | Message.notification "$/lean/importClosure" params => - if let some params := params then - if let Except.ok params := FromJson.fromJson? <| ToJson.toJson params then - handleImportClosure fw params + if let .ok params? := parseRequestParams? (Option Json.Structured) msg then + let globalID ← (← read).serverRequestData.modifyGet + (·.trackOutboundRequest fw.doc.uri id) + o.writeLspMessage (Message.request globalID method params?) + | .notification "$/lean/ileanHeaderInfo" => + if let .ok params := parseNotificationParams? LeanILeanHeaderInfoParams msg then + handleILeanHeaderInfo fw params + | .notification "$/lean/ileanInfoUpdate" => + if let .ok params := parseNotificationParams? LeanIleanInfoParams msg then + handleIleanInfoUpdate fw params + | .notification "$/lean/ileanInfoFinal" => + if let .ok params := parseNotificationParams? LeanIleanInfoParams msg then + handleIleanInfoFinal fw params + | .notification "$/lean/importClosure" => + if let .ok params := parseNotificationParams? LeanImportClosureParams msg then + handleImportClosure fw params | _ => - o.writeLspMessage msg + o.writeSerializedLspMessage msg def startFileWorker (m : DocumentMeta) : ServerM Unit := do let st ← read @@ -861,9 +924,11 @@ section ServerM pure () def tryWriteMessage - (uri : DocumentUri) + (id : FileIdent) (msg : JsonRpc.Message) : ServerM Unit := do + let some uri ← getFileWorkerUri? id + | return let some fw ← getFileWorker? uri | return if let some req := JsonRpc.Request.ofMessage? msg then @@ -896,7 +961,7 @@ section ServerM staleDependency := staleDependency : LeanStaleDependencyParams } - tryWriteMessage uri notification + tryWriteMessage (.uri uri) notification end ServerM section RequestHandling @@ -1202,7 +1267,7 @@ section NotificationHandling } updateFileWorkers { fw with doc := newDoc } let notification := Notification.mk "textDocument/didChange" p - tryWriteMessage doc.uri notification + tryWriteMessage (.uri doc.uri) notification /-- When a file is saved, notifies all file workers for files that depend on this file that this @@ -1211,11 +1276,11 @@ section NotificationHandling -/ def handleDidSave (p : DidSaveTextDocumentParams) : ServerM Unit := do let s ← read - let fileWorkers ← s.fileWorkersRef.get + let fws ← s.fileWorkersRef.get let importData ← s.importData.get let dependents := importData.importedBy.getD p.textDocument.uri ∅ - for ⟨uri, _⟩ in fileWorkers do + for ⟨uri, _⟩ in fws.fileWorkers do if ! dependents.contains uri then continue notifyAboutStaleDependency uri p.textDocument.uri @@ -1257,7 +1322,7 @@ section NotificationHandling let ctx ← read let some uri ← ctx.requestData.getUri? p.id | return - tryWriteMessage uri (Notification.mk "$/cancelRequest" p) + tryWriteMessage (.uri uri) (Notification.mk "$/cancelRequest" p) def forwardNotification {α : Type} [ToJson α] [FileSource α] (method : String) (params : α) : ServerM Unit := @@ -1266,7 +1331,7 @@ end NotificationHandling section MessageHandling def forwardRequestToWorker (id : RequestID) (method : String) (params : Json) : ServerM Unit := do - let uri: DocumentUri ← + let fileId : FileIdent ← if method == "$/lean/rpc/connect" then let ps ← parseParams Lsp.RpcConnectParams params pure <| fileSource ps @@ -1276,7 +1341,7 @@ section MessageHandling (←read).hOut.writeLspResponseError <| e.toLspResponseError id return | Except.ok uri => pure uri - if (← getFileWorker? uri).isNone then + if ! (← fileWorkerExists fileId) then /- Clients may send requests to closed files, which we respond to with an error. For example, VSCode sometimes sends requests just after closing a file, and RPC clients may also do so, e.g. due to remaining timers. -/ @@ -1285,16 +1350,16 @@ section MessageHandling /- Some clients (VSCode) also send requests *before* opening a file. We reply with `contentModified` as that does not display a "request failed" popup. -/ code := ErrorCode.contentModified - message := s!"Cannot process request to closed file '{uri}'" } + message := s!"Cannot process request to closed file '{toString fileId}'" } return let r := Request.mk id method params - tryWriteMessage uri r + tryWriteMessage fileId r def handleReferenceRequest α β [FromJson α] [ToJson β] (id : RequestID) (params : Json) (handler : α → ReaderT ReferenceRequestContext IO β) : ServerM Unit := do let ctx ← read let hOut := ctx.hOut - let fileWorkerMods := (← ctx.fileWorkersRef.get).map fun _ fw => fw.doc.mod + let fileWorkerMods := (← ctx.fileWorkersRef.get).fileWorkers.map fun _ fw => fw.doc.mod let references ← getReferences let _ ← ServerTask.IO.asTask do try @@ -1396,7 +1461,7 @@ section MessageHandling def handleResponse (id : RequestID) (result : Json) : ServerM Unit := do let some translation ← (← read).serverRequestData.modifyGet (·.translateInboundResponse id) | return - tryWriteMessage translation.sourceUri (Response.mk translation.localID result) + tryWriteMessage (.uri translation.sourceUri) (Response.mk translation.localID result) def handleResponseError (id : RequestID) @@ -1406,15 +1471,15 @@ section MessageHandling : ServerM Unit := do let some translation ← (← read).serverRequestData.modifyGet (·.translateInboundResponse id) | return - tryWriteMessage translation.sourceUri (ResponseError.mk translation.localID code message data?) + tryWriteMessage (.uri translation.sourceUri) (ResponseError.mk translation.localID code message data?) end MessageHandling section MainLoop def shutdown : ServerM Unit := do let fileWorkers ← (←read).fileWorkersRef.get - for ⟨uri, _⟩ in fileWorkers do + for ⟨uri, _⟩ in fileWorkers.fileWorkers do try terminateFileWorker uri catch _ => pure () - for ⟨_, fw⟩ in fileWorkers do + for ⟨_, fw⟩ in fileWorkers.fileWorkers do -- TODO: Wait for process group to finish instead try let _ ← fw.killProcAndWait catch _ => pure () @@ -1438,7 +1503,7 @@ section MainLoop let st ← read let workers ← st.fileWorkersRef.get let mut workerTasks := #[] - for (_, fw) in workers do + for (_, fw) in workers.fileWorkers do if !((← getWorkerState fw) matches WorkerState.crashed) then workerTasks := workerTasks.push <| fw.commTask.mapCheap (ServerEvent.workerEvent fw) @@ -1626,7 +1691,7 @@ def initAndRunWatchdog (args : List String) (i o e : FS.Stream) : IO Unit := do pendingWaitForILeanRequests := #[] } startLoadingReferences referenceData - let fileWorkersRef ← IO.mkRef (Std.TreeMap.empty : FileWorkerMap) + let fileWorkersRef ← IO.mkRef ({} : FileWorkerMap) let serverRequestData ← IO.mkRef { pendingServerRequests := Std.TreeMap.empty freshServerRequestID := 0 diff --git a/tests/lean/interactive/1265.lean.expected.out b/tests/lean/interactive/1265.lean.expected.out index e33e6f10dc..aa0bedc5aa 100644 --- a/tests/lean/interactive/1265.lean.expected.out +++ b/tests/lean/interactive/1265.lean.expected.out @@ -1,168 +1,86 @@ {"textDocument": {"uri": "file:///1265.lean"}, "position": {"line": 0, "character": 51}} {"items": - [{"label": "getDocString", + [{"label": "getScientific", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.getDocString"}}, - "cPos": 1}}, - {"label": "expandInterpolatedStr", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.expandInterpolatedStr"}}, - "cPos": 1}}, - {"label": "getHygieneInfo", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.getHygieneInfo"}}, - "cPos": 1}}, + ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.getScientific"]}, {"label": "getString", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.getString"}}, - "cPos": 1}}, - {"label": "getName", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.getName"}}, - "cPos": 1}}, - {"label": "getChar", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.getChar"}}, - "cPos": 1}}, + ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.getString"]}, {"label": "getNat", "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.getNat"}}, - "cPos": 1}}, - {"label": "getScientific", + "data": ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.getNat"]}, + {"label": "getName", "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.getScientific"}}, - "cPos": 1}}, + "data": ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.getName"]}, + {"label": "getChar", + "kind": 3, + "data": ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.getChar"]}, {"label": "raw", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.raw"}}, - "cPos": 1}}, - {"label": "getId", + "data": ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.raw"]}, + {"label": "getDocString", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 0, "character": 51}}, - "id": {"const": {"declName": "Lean.TSyntax.getId"}}, - "cPos": 1}}], + ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.getDocString"]}, + {"label": "expandInterpolatedStr", + "kind": 3, + "data": + ["«external:file:///1265.lean»", + 0, + 51, + 1, + "cLean.TSyntax.expandInterpolatedStr"]}, + {"label": "getHygieneInfo", + "kind": 3, + "data": + ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.getHygieneInfo"]}, + {"label": "getId", + "kind": 3, + "data": ["«external:file:///1265.lean»", 0, 51, 1, "cLean.TSyntax.getId"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///1265.lean"}, "position": {"line": 2, "character": 53}} {"items": - [{"label": "getDocString", + [{"label": "getScientific", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.getDocString"}}, - "cPos": 1}}, - {"label": "expandInterpolatedStr", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.expandInterpolatedStr"}}, - "cPos": 1}}, - {"label": "getHygieneInfo", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.getHygieneInfo"}}, - "cPos": 1}}, + ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.getScientific"]}, {"label": "getString", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.getString"}}, - "cPos": 1}}, - {"label": "getName", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.getName"}}, - "cPos": 1}}, - {"label": "getChar", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.getChar"}}, - "cPos": 1}}, + ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.getString"]}, {"label": "getNat", "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.getNat"}}, - "cPos": 1}}, - {"label": "getScientific", + "data": ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.getNat"]}, + {"label": "getName", "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.getScientific"}}, - "cPos": 1}}, + "data": ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.getName"]}, + {"label": "getChar", + "kind": 3, + "data": ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.getChar"]}, {"label": "raw", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.raw"}}, - "cPos": 1}}, - {"label": "getId", + "data": ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.raw"]}, + {"label": "getDocString", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///1265.lean"}, - "position": {"line": 2, "character": 53}}, - "id": {"const": {"declName": "Lean.TSyntax.getId"}}, - "cPos": 1}}], + ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.getDocString"]}, + {"label": "expandInterpolatedStr", + "kind": 3, + "data": + ["«external:file:///1265.lean»", + 2, + 53, + 1, + "cLean.TSyntax.expandInterpolatedStr"]}, + {"label": "getHygieneInfo", + "kind": 3, + "data": + ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.getHygieneInfo"]}, + {"label": "getId", + "kind": 3, + "data": ["«external:file:///1265.lean»", 2, 53, 1, "cLean.TSyntax.getId"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/1659.lean.expected.out b/tests/lean/interactive/1659.lean.expected.out index d5c919cdff..18f44329e7 100644 --- a/tests/lean/interactive/1659.lean.expected.out +++ b/tests/lean/interactive/1659.lean.expected.out @@ -1,42 +1,42 @@ {"textDocument": {"uri": "file:///1659.lean"}, "position": {"line": 9, "character": 23}} {"items": - [{"label": "Lean.Elab.Tactic.elabTermEnsuringType", + [{"label": "Lean.Elab.Term.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 9, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Tactic.elabTermEnsuringType"}}, - "cPos": 0}}, - {"label": "Lean.Elab.Term.elabTermEnsuringType", + ["«external:file:///1659.lean»", + 9, + 23, + 0, + "cLean.Elab.Term.elabTermEnsuringType"]}, + {"label": "Lean.Elab.Tactic.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 9, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Term.elabTermEnsuringType"}}, - "cPos": 0}}], + ["«external:file:///1659.lean»", + 9, + 23, + 0, + "cLean.Elab.Tactic.elabTermEnsuringType"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///1659.lean"}, "position": {"line": 15, "character": 23}} {"items": - [{"label": "Tactic.elabTermEnsuringType", + [{"label": "Term.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 15, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Tactic.elabTermEnsuringType"}}, - "cPos": 0}}, - {"label": "Term.elabTermEnsuringType", + ["«external:file:///1659.lean»", + 15, + 23, + 0, + "cLean.Elab.Term.elabTermEnsuringType"]}, + {"label": "Tactic.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 15, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Term.elabTermEnsuringType"}}, - "cPos": 0}}], + ["«external:file:///1659.lean»", + 15, + 23, + 0, + "cLean.Elab.Tactic.elabTermEnsuringType"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///1659.lean"}, "position": {"line": 21, "character": 23}} @@ -44,81 +44,73 @@ [{"label": "elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 21, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Term.elabTermEnsuringType"}}, - "cPos": 0}}, + ["«external:file:///1659.lean»", + 21, + 23, + 0, + "cLean.Elab.Term.elabTermEnsuringType"]}, {"label": "Lean.Elab.Tactic.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 21, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Tactic.elabTermEnsuringType"}}, - "cPos": 0}}], + ["«external:file:///1659.lean»", + 21, + 23, + 0, + "cLean.Elab.Tactic.elabTermEnsuringType"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///1659.lean"}, "position": {"line": 27, "character": 23}} {"items": - [{"label": "elabTermEnsuringType", + [{"label": "Lean.Elab.Term.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 27, "character": 23}}, - "id": {"const": {"declName": "elabTermEnsuringType"}}, - "cPos": 0}}, + ["«external:file:///1659.lean»", + 27, + 23, + 0, + "cLean.Elab.Term.elabTermEnsuringType"]}, + {"label": "elabTermEnsuringType", + "kind": 21, + "data": + ["«external:file:///1659.lean»", 27, 23, 0, "celabTermEnsuringType"]}, {"label": "Lean.Elab.Tactic.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 27, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Tactic.elabTermEnsuringType"}}, - "cPos": 0}}, - {"label": "Lean.Elab.Term.elabTermEnsuringType", - "kind": 21, - "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 27, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Term.elabTermEnsuringType"}}, - "cPos": 0}}], + ["«external:file:///1659.lean»", + 27, + 23, + 0, + "cLean.Elab.Tactic.elabTermEnsuringType"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///1659.lean"}, "position": {"line": 33, "character": 23}} {"items": - [{"label": "elabTermEnsuringType", + [{"label": "Lean.Elab.Term.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 33, "character": 23}}, - "id": {"const": {"declName": "elabTermEnsuringType"}}, - "cPos": 0}}, - {"label": "Lean.Elab.Tactic.elabTermEnsuringType", - "kind": 21, - "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 33, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Tactic.elabTermEnsuringType"}}, - "cPos": 0}}, - {"label": "Lean.Elab.Term.elabTermEnsuringType", - "kind": 21, - "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 33, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.Term.elabTermEnsuringType"}}, - "cPos": 0}}, + ["«external:file:///1659.lean»", + 33, + 23, + 0, + "cLean.Elab.Term.elabTermEnsuringType"]}, {"label": "Lean.Elab.elabTermEnsuringType", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///1659.lean"}, - "position": {"line": 33, "character": 23}}, - "id": {"const": {"declName": "Lean.Elab.elabTermEnsuringType"}}, - "cPos": 0}}], + ["«external:file:///1659.lean»", + 33, + 23, + 0, + "cLean.Elab.elabTermEnsuringType"]}, + {"label": "elabTermEnsuringType", + "kind": 21, + "data": + ["«external:file:///1659.lean»", 33, 23, 0, "celabTermEnsuringType"]}, + {"label": "Lean.Elab.Tactic.elabTermEnsuringType", + "kind": 21, + "data": + ["«external:file:///1659.lean»", + 33, + 23, + 0, + "cLean.Elab.Tactic.elabTermEnsuringType"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/533.lean.expected.out b/tests/lean/interactive/533.lean.expected.out index f10235600e..c928cf8072 100644 --- a/tests/lean/interactive/533.lean.expected.out +++ b/tests/lean/interactive/533.lean.expected.out @@ -1,20 +1,10 @@ {"textDocument": {"uri": "file:///533.lean"}, "position": {"line": 4, "character": 10}} {"items": - [{"label": "F", + [{"label": "Foo", "kind": 6, - "data": - {"params": - {"textDocument": {"uri": "file:///533.lean"}, - "position": {"line": 4, "character": 10}}, - "id": {"fvar": {"id": "_uniq.7"}}, - "cPos": 0}}, - {"label": "Foo", + "data": ["«external:file:///533.lean»", 4, 10, 0, "f_uniq.3"]}, + {"label": "F", "kind": 6, - "data": - {"params": - {"textDocument": {"uri": "file:///533.lean"}, - "position": {"line": 4, "character": 10}}, - "id": {"fvar": {"id": "_uniq.3"}}, - "cPos": 0}}], + "data": ["«external:file:///533.lean»", 4, 10, 0, "f_uniq.7"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/863.lean.expected.out b/tests/lean/interactive/863.lean.expected.out index e4c93d06cd..3bd1911055 100644 --- a/tests/lean/interactive/863.lean.expected.out +++ b/tests/lean/interactive/863.lean.expected.out @@ -1,40 +1,21 @@ {"textDocument": {"uri": "file:///863.lean"}, "position": {"line": 9, "character": 12}} {"items": - [{"label": "getRef", + [{"label": "MonadRef.getRef", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///863.lean"}, - "position": {"line": 9, "character": 12}}, - "id": {"const": {"declName": "Lean.MonadRef.getRef"}}, - "cPos": 0}}, - {"label": "MonadRef.getRef", + "data": ["«external:file:///863.lean»", 9, 12, 0, "cLean.MonadRef.getRef"]}, + {"label": "getRef", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///863.lean"}, - "position": {"line": 9, "character": 12}}, - "id": {"const": {"declName": "Lean.MonadRef.getRef"}}, - "cPos": 0}}], + "data": ["«external:file:///863.lean»", 9, 12, 0, "cLean.MonadRef.getRef"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///863.lean"}, "position": {"line": 13, "character": 12}} {"items": - [{"label": "getRef", + [{"label": "MonadRef.getRef", + "kind": 5, + "data": ["«external:file:///863.lean»", 13, 12, 0, "cLean.MonadRef.getRef"]}, + {"label": "getRef", "kind": 5, "data": - {"params": - {"textDocument": {"uri": "file:///863.lean"}, - "position": {"line": 13, "character": 12}}, - "id": {"const": {"declName": "Lean.MonadRef.getRef"}}, - "cPos": 0}}, - {"label": "MonadRef.getRef", - "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///863.lean"}, - "position": {"line": 13, "character": 12}}, - "id": {"const": {"declName": "Lean.MonadRef.getRef"}}, - "cPos": 0}}], + ["«external:file:///863.lean»", 13, 12, 0, "cLean.MonadRef.getRef"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/compHeader.lean.expected.out b/tests/lean/interactive/compHeader.lean.expected.out index d205e1b4cf..5a87d69eea 100644 --- a/tests/lean/interactive/compHeader.lean.expected.out +++ b/tests/lean/interactive/compHeader.lean.expected.out @@ -1,20 +1,15 @@ {"textDocument": {"uri": "file:///compHeader.lean"}, "position": {"line": 2, "character": 22}} {"items": - [{"label": "veryLongNameForCompletion", + [{"label": "veryLongNam", + "kind": 6, + "data": ["«external:file:///compHeader.lean»", 2, 22, 0, "f_uniq.7"]}, + {"label": "veryLongNameForCompletion", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///compHeader.lean"}, - "position": {"line": 2, "character": 22}}, - "id": {"const": {"declName": "veryLongNameForCompletion"}}, - "cPos": 0}}, - {"label": "veryLongNam", - "kind": 6, - "data": - {"params": - {"textDocument": {"uri": "file:///compHeader.lean"}, - "position": {"line": 2, "character": 22}}, - "id": {"fvar": {"id": "_uniq.7"}}, - "cPos": 0}}], + ["«external:file:///compHeader.lean»", + 2, + 22, + 0, + "cveryLongNameForCompletion"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/compNamespace.lean.expected.out b/tests/lean/interactive/compNamespace.lean.expected.out index de9325d198..f927455ccb 100644 --- a/tests/lean/interactive/compNamespace.lean.expected.out +++ b/tests/lean/interactive/compNamespace.lean.expected.out @@ -4,11 +4,7 @@ [{"label": "LongNamespaceExample", "kind": 9, "detail": "namespace", - "data": - {"params": - {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 5, "character": 14}}, - "cPos": 0}}], + "data": ["«external:file:///compNamespace.lean»", 5, 14, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///compNamespace.lean"}, "position": {"line": 9, "character": 14}} @@ -16,11 +12,7 @@ [{"label": "LongNamespaceExample", "kind": 9, "detail": "namespace", - "data": - {"params": - {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 9, "character": 14}}, - "cPos": 0}}], + "data": ["«external:file:///compNamespace.lean»", 9, 14, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///compNamespace.lean"}, "position": {"line": 13, "character": 11}} @@ -28,11 +20,7 @@ [{"label": "LongNamespaceExample", "kind": 9, "detail": "namespace", - "data": - {"params": - {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 13, "character": 11}}, - "cPos": 0}}], + "data": ["«external:file:///compNamespace.lean»", 13, 11, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///compNamespace.lean"}, "position": {"line": 16, "character": 16}} @@ -40,11 +28,7 @@ [{"label": "LongNamespaceExample", "kind": 9, "detail": "namespace", - "data": - {"params": - {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 16, "character": 16}}, - "cPos": 0}}], + "data": ["«external:file:///compNamespace.lean»", 16, 16, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///compNamespace.lean"}, "position": {"line": 20, "character": 14}} @@ -52,9 +36,5 @@ [{"label": "LongNamespaceExample", "kind": 9, "detail": "namespace", - "data": - {"params": - {"textDocument": {"uri": "file:///compNamespace.lean"}, - "position": {"line": 20, "character": 14}}, - "cPos": 0}}], + "data": ["«external:file:///compNamespace.lean»", 20, 14, 0]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completion.lean.expected.out b/tests/lean/interactive/completion.lean.expected.out index 227bcd3f01..adbf403098 100644 --- a/tests/lean/interactive/completion.lean.expected.out +++ b/tests/lean/interactive/completion.lean.expected.out @@ -3,46 +3,26 @@ {"items": [{"label": "foo", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion.lean"}, - "position": {"line": 3, "character": 22}}, - "id": {"const": {"declName": "Foo.foo"}}, - "cPos": 1}}], + "data": ["«external:file:///completion.lean»", 3, 22, 1, "cFoo.foo"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion.lean"}, "position": {"line": 5, "character": 23}} {"items": [{"label": "foo", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion.lean"}, - "position": {"line": 5, "character": 23}}, - "id": {"const": {"declName": "Foo.foo"}}, - "cPos": 1}}], + "data": ["«external:file:///completion.lean»", 5, 23, 1, "cFoo.foo"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion.lean"}, "position": {"line": 7, "character": 28}} {"items": [{"label": "foo", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion.lean"}, - "position": {"line": 7, "character": 28}}, - "id": {"const": {"declName": "Foo.foo"}}, - "cPos": 0}}], + "data": ["«external:file:///completion.lean»", 7, 28, 0, "cFoo.foo"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion.lean"}, "position": {"line": 9, "character": 29}} {"items": [{"label": "foo", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion.lean"}, - "position": {"line": 9, "character": 29}}, - "id": {"const": {"declName": "Foo.foo"}}, - "cPos": 0}}], + "data": ["«external:file:///completion.lean»", 9, 29, 0, "cFoo.foo"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completion2.lean.expected.out b/tests/lean/interactive/completion2.lean.expected.out index d1fa9cc25c..f6c0ba991c 100644 --- a/tests/lean/interactive/completion2.lean.expected.out +++ b/tests/lean/interactive/completion2.lean.expected.out @@ -1,136 +1,61 @@ {"textDocument": {"uri": "file:///completion2.lean"}, "position": {"line": 19, "character": 10}} {"items": - [{"label": "ex3", + [{"label": "ex2", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 19, "character": 10}}, - "id": {"const": {"declName": "Foo.Bla.ex3"}}, - "cPos": 0}}, - {"label": "ex2", + "data": ["«external:file:///completion2.lean»", 19, 10, 0, "cFoo.Bla.ex2"]}, + {"label": "ex3", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 19, "character": 10}}, - "id": {"const": {"declName": "Foo.Bla.ex2"}}, - "cPos": 0}}, - {"label": "ax1", - "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 19, "character": 10}}, - "id": {"const": {"declName": "Foo.Bla.ax1"}}, - "cPos": 0}}, + "data": ["«external:file:///completion2.lean»", 19, 10, 0, "cFoo.Bla.ex3"]}, {"label": "ex1", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 19, "character": 10}}, - "id": {"const": {"declName": "Foo.Bla.ex1"}}, - "cPos": 0}}], + "data": ["«external:file:///completion2.lean»", 19, 10, 0, "cFoo.Bla.ex1"]}, + {"label": "ax1", + "kind": 23, + "data": ["«external:file:///completion2.lean»", 19, 10, 0, "cFoo.Bla.ax1"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion2.lean"}, "position": {"line": 25, "character": 6}} {"items": - [{"label": "ex3", + [{"label": "ex2", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 25, "character": 6}}, - "id": {"const": {"declName": "Foo.Bla.ex3"}}, - "cPos": 0}}, - {"label": "ex2", + "data": ["«external:file:///completion2.lean»", 25, 6, 0, "cFoo.Bla.ex2"]}, + {"label": "ex3", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 25, "character": 6}}, - "id": {"const": {"declName": "Foo.Bla.ex2"}}, - "cPos": 0}}, - {"label": "ax1", - "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 25, "character": 6}}, - "id": {"const": {"declName": "Foo.Bla.ax1"}}, - "cPos": 0}}, + "data": ["«external:file:///completion2.lean»", 25, 6, 0, "cFoo.Bla.ex3"]}, {"label": "ex1", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 25, "character": 6}}, - "id": {"const": {"declName": "Foo.Bla.ex1"}}, - "cPos": 0}}], + "data": ["«external:file:///completion2.lean»", 25, 6, 0, "cFoo.Bla.ex1"]}, + {"label": "ax1", + "kind": 23, + "data": ["«external:file:///completion2.lean»", 25, 6, 0, "cFoo.Bla.ax1"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion2.lean"}, "position": {"line": 30, "character": 21}} {"items": - [{"label": "ex3", + [{"label": "ex2", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 30, "character": 21}}, - "id": {"const": {"declName": "Foo.Bla.ex3"}}, - "cPos": 0}}, - {"label": "ex2", + "data": ["«external:file:///completion2.lean»", 30, 21, 0, "cFoo.Bla.ex2"]}, + {"label": "ex3", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 30, "character": 21}}, - "id": {"const": {"declName": "Foo.Bla.ex2"}}, - "cPos": 0}}, - {"label": "ax1", - "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 30, "character": 21}}, - "id": {"const": {"declName": "Foo.Bla.ax1"}}, - "cPos": 0}}, + "data": ["«external:file:///completion2.lean»", 30, 21, 0, "cFoo.Bla.ex3"]}, {"label": "ex1", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 30, "character": 21}}, - "id": {"const": {"declName": "Foo.Bla.ex1"}}, - "cPos": 0}}], + "data": ["«external:file:///completion2.lean»", 30, 21, 0, "cFoo.Bla.ex1"]}, + {"label": "ax1", + "kind": 23, + "data": ["«external:file:///completion2.lean»", 30, 21, 0, "cFoo.Bla.ax1"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion2.lean"}, "position": {"line": 37, "character": 22}} {"items": - [{"label": "ex3", + [{"label": "ex2", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 37, "character": 22}}, - "id": {"const": {"declName": "Foo.Bla.ex3"}}, - "cPos": 0}}, - {"label": "ex2", + "data": ["«external:file:///completion2.lean»", 37, 22, 0, "cFoo.Bla.ex2"]}, + {"label": "ex3", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 37, "character": 22}}, - "id": {"const": {"declName": "Foo.Bla.ex2"}}, - "cPos": 0}}, + "data": ["«external:file:///completion2.lean»", 37, 22, 0, "cFoo.Bla.ex3"]}, {"label": "ex1", "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completion2.lean"}, - "position": {"line": 37, "character": 22}}, - "id": {"const": {"declName": "Foo.Bla.ex1"}}, - "cPos": 0}}], + "data": ["«external:file:///completion2.lean»", 37, 22, 0, "cFoo.Bla.ex1"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completion3.lean.expected.out b/tests/lean/interactive/completion3.lean.expected.out index 2883d8d9a7..7283d36c0e 100644 --- a/tests/lean/interactive/completion3.lean.expected.out +++ b/tests/lean/interactive/completion3.lean.expected.out @@ -3,110 +3,50 @@ {"items": [{"label": "x", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 7, "character": 9}}, - "id": {"const": {"declName": "S.x"}}, - "cPos": 1}}, - {"label": "y", - "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 7, "character": 9}}, - "id": {"const": {"declName": "S.y"}}, - "cPos": 1}}, + "data": ["«external:file:///completion3.lean»", 7, 9, 1, "cS.x"]}, {"label": "b", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 7, "character": 9}}, - "id": {"const": {"declName": "S.b"}}, - "cPos": 1}}], + "data": ["«external:file:///completion3.lean»", 7, 9, 1, "cS.b"]}, + {"label": "y", + "kind": 5, + "data": ["«external:file:///completion3.lean»", 7, 9, 1, "cS.y"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion3.lean"}, "position": {"line": 12, "character": 5}} {"items": [{"label": "x", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 12, "character": 5}}, - "id": {"const": {"declName": "S.x"}}, - "cPos": 1}}, - {"label": "y", - "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 12, "character": 5}}, - "id": {"const": {"declName": "S.y"}}, - "cPos": 1}}, + "data": ["«external:file:///completion3.lean»", 12, 5, 1, "cS.x"]}, {"label": "b", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 12, "character": 5}}, - "id": {"const": {"declName": "S.b"}}, - "cPos": 1}}], + "data": ["«external:file:///completion3.lean»", 12, 5, 1, "cS.b"]}, + {"label": "y", + "kind": 5, + "data": ["«external:file:///completion3.lean»", 12, 5, 1, "cS.y"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion3.lean"}, "position": {"line": 16, "character": 5}} {"items": [{"label": "x", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 16, "character": 5}}, - "id": {"const": {"declName": "S.x"}}, - "cPos": 1}}, - {"label": "y", - "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 16, "character": 5}}, - "id": {"const": {"declName": "S.y"}}, - "cPos": 1}}, + "data": ["«external:file:///completion3.lean»", 16, 5, 1, "cS.x"]}, {"label": "b", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 16, "character": 5}}, - "id": {"const": {"declName": "S.b"}}, - "cPos": 1}}], + "data": ["«external:file:///completion3.lean»", 16, 5, 1, "cS.b"]}, + {"label": "y", + "kind": 5, + "data": ["«external:file:///completion3.lean»", 16, 5, 1, "cS.y"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion3.lean"}, "position": {"line": 20, "character": 5}} {"items": [{"label": "x", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 20, "character": 5}}, - "id": {"const": {"declName": "S.x"}}, - "cPos": 1}}, - {"label": "y", - "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 20, "character": 5}}, - "id": {"const": {"declName": "S.y"}}, - "cPos": 1}}, + "data": ["«external:file:///completion3.lean»", 20, 5, 1, "cS.x"]}, {"label": "b", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion3.lean"}, - "position": {"line": 20, "character": 5}}, - "id": {"const": {"declName": "S.b"}}, - "cPos": 1}}], + "data": ["«external:file:///completion3.lean»", 20, 5, 1, "cS.b"]}, + {"label": "y", + "kind": 5, + "data": ["«external:file:///completion3.lean»", 20, 5, 1, "cS.y"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completion4.lean.expected.out b/tests/lean/interactive/completion4.lean.expected.out index a5a90093be..4c5c2836ff 100644 --- a/tests/lean/interactive/completion4.lean.expected.out +++ b/tests/lean/interactive/completion4.lean.expected.out @@ -1,112 +1,52 @@ {"textDocument": {"uri": "file:///completion4.lean"}, "position": {"line": 7, "character": 4}} {"items": - [{"label": "pred", + [{"label": "fn2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 7, "character": 4}}, - "id": {"const": {"declName": "S.pred"}}, - "cPos": 1}}, + "data": ["«external:file:///completion4.lean»", 7, 4, 1, "cS.fn2"]}, {"label": "fn1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 7, "character": 4}}, - "id": {"const": {"declName": "S.fn1"}}, - "cPos": 1}}, - {"label": "fn2", + "data": ["«external:file:///completion4.lean»", 7, 4, 1, "cS.fn1"]}, + {"label": "pred", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 7, "character": 4}}, - "id": {"const": {"declName": "S.fn2"}}, - "cPos": 1}}], + "data": ["«external:file:///completion4.lean»", 7, 4, 1, "cS.pred"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion4.lean"}, "position": {"line": 11, "character": 10}} {"items": - [{"label": "pred", + [{"label": "fn2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 11, "character": 10}}, - "id": {"const": {"declName": "S.pred"}}, - "cPos": 1}}, + "data": ["«external:file:///completion4.lean»", 11, 10, 1, "cS.fn2"]}, {"label": "fn1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 11, "character": 10}}, - "id": {"const": {"declName": "S.fn1"}}, - "cPos": 1}}, - {"label": "fn2", + "data": ["«external:file:///completion4.lean»", 11, 10, 1, "cS.fn1"]}, + {"label": "pred", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 11, "character": 10}}, - "id": {"const": {"declName": "S.fn2"}}, - "cPos": 1}}], + "data": ["«external:file:///completion4.lean»", 11, 10, 1, "cS.pred"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion4.lean"}, "position": {"line": 16, "character": 11}} {"items": - [{"label": "pred", + [{"label": "fn2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 16, "character": 11}}, - "id": {"const": {"declName": "S.pred"}}, - "cPos": 1}}, + "data": ["«external:file:///completion4.lean»", 16, 11, 1, "cS.fn2"]}, {"label": "fn1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 16, "character": 11}}, - "id": {"const": {"declName": "S.fn1"}}, - "cPos": 1}}, - {"label": "fn2", + "data": ["«external:file:///completion4.lean»", 16, 11, 1, "cS.fn1"]}, + {"label": "pred", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 16, "character": 11}}, - "id": {"const": {"declName": "S.fn2"}}, - "cPos": 1}}], + "data": ["«external:file:///completion4.lean»", 16, 11, 1, "cS.pred"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion4.lean"}, "position": {"line": 20, "character": 21}} {"items": - [{"label": "pred", + [{"label": "fn2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 20, "character": 21}}, - "id": {"const": {"declName": "S.pred"}}, - "cPos": 1}}, + "data": ["«external:file:///completion4.lean»", 20, 21, 1, "cS.fn2"]}, {"label": "fn1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 20, "character": 21}}, - "id": {"const": {"declName": "S.fn1"}}, - "cPos": 1}}, - {"label": "fn2", + "data": ["«external:file:///completion4.lean»", 20, 21, 1, "cS.fn1"]}, + {"label": "pred", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion4.lean"}, - "position": {"line": 20, "character": 21}}, - "id": {"const": {"declName": "S.fn2"}}, - "cPos": 1}}], + "data": ["«external:file:///completion4.lean»", 20, 21, 1, "cS.pred"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completion5.lean.expected.out b/tests/lean/interactive/completion5.lean.expected.out index fa814d4161..777ef69fcf 100644 --- a/tests/lean/interactive/completion5.lean.expected.out +++ b/tests/lean/interactive/completion5.lean.expected.out @@ -1,28 +1,13 @@ {"textDocument": {"uri": "file:///completion5.lean"}, "position": {"line": 9, "character": 15}} {"items": - [{"label": "f2", + [{"label": "f1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion5.lean"}, - "position": {"line": 9, "character": 15}}, - "id": {"const": {"declName": "C.f2"}}, - "cPos": 1}}, + "data": ["«external:file:///completion5.lean»", 9, 15, 1, "cC.f1"]}, {"label": "b1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion5.lean"}, - "position": {"line": 9, "character": 15}}, - "id": {"const": {"declName": "C.b1"}}, - "cPos": 1}}, - {"label": "f1", + "data": ["«external:file:///completion5.lean»", 9, 15, 1, "cC.b1"]}, + {"label": "f2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion5.lean"}, - "position": {"line": 9, "character": 15}}, - "id": {"const": {"declName": "C.f1"}}, - "cPos": 1}}], + "data": ["«external:file:///completion5.lean»", 9, 15, 1, "cC.f2"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completion6.lean.expected.out b/tests/lean/interactive/completion6.lean.expected.out index fe3e985640..be4e48f05a 100644 --- a/tests/lean/interactive/completion6.lean.expected.out +++ b/tests/lean/interactive/completion6.lean.expected.out @@ -1,96 +1,41 @@ {"textDocument": {"uri": "file:///completion6.lean"}, "position": {"line": 12, "character": 15}} {"items": - [{"label": "f3", + [{"label": "f1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 12, "character": 15}}, - "id": {"const": {"declName": "D.f3"}}, - "cPos": 1}}, - {"label": "f2", + "data": ["«external:file:///completion6.lean»", 12, 15, 1, "cC.f1"]}, + {"label": "f3", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 12, "character": 15}}, - "id": {"const": {"declName": "C.f2"}}, - "cPos": 1}}, + "data": ["«external:file:///completion6.lean»", 12, 15, 1, "cD.f3"]}, {"label": "toC", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 12, "character": 15}}, - "id": {"const": {"declName": "D.toC"}}, - "cPos": 1}}, + "data": ["«external:file:///completion6.lean»", 12, 15, 1, "cD.toC"]}, {"label": "b1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 12, "character": 15}}, - "id": {"const": {"declName": "C.b1"}}, - "cPos": 1}}, - {"label": "f1", + "data": ["«external:file:///completion6.lean»", 12, 15, 1, "cC.b1"]}, + {"label": "f2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 12, "character": 15}}, - "id": {"const": {"declName": "C.f1"}}, - "cPos": 1}}], + "data": ["«external:file:///completion6.lean»", 12, 15, 1, "cC.f2"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion6.lean"}, "position": {"line": 21, "character": 4}} {"items": - [{"label": "f3", + [{"label": "f1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 21, "character": 4}}, - "id": {"const": {"declName": "D.f3"}}, - "cPos": 1}}, - {"label": "f2", + "data": ["«external:file:///completion6.lean»", 21, 4, 1, "cC.f1"]}, + {"label": "f3", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 21, "character": 4}}, - "id": {"const": {"declName": "C.f2"}}, - "cPos": 1}}, - {"label": "doubleF1", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 21, "character": 4}}, - "id": {"const": {"declName": "E.doubleF1"}}, - "cPos": 1}}, + "data": ["«external:file:///completion6.lean»", 21, 4, 1, "cD.f3"]}, {"label": "toC", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 21, "character": 4}}, - "id": {"const": {"declName": "D.toC"}}, - "cPos": 1}}, + "data": ["«external:file:///completion6.lean»", 21, 4, 1, "cD.toC"]}, {"label": "b1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 21, "character": 4}}, - "id": {"const": {"declName": "C.b1"}}, - "cPos": 1}}, - {"label": "f1", + "data": ["«external:file:///completion6.lean»", 21, 4, 1, "cC.b1"]}, + {"label": "doubleF1", + "kind": 3, + "data": ["«external:file:///completion6.lean»", 21, 4, 1, "cE.doubleF1"]}, + {"label": "f2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion6.lean"}, - "position": {"line": 21, "character": 4}}, - "id": {"const": {"declName": "C.f1"}}, - "cPos": 1}}], + "data": ["«external:file:///completion6.lean»", 21, 4, 1, "cC.f2"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completion7.lean.expected.out b/tests/lean/interactive/completion7.lean.expected.out index bb56197851..dac64dfca5 100644 --- a/tests/lean/interactive/completion7.lean.expected.out +++ b/tests/lean/interactive/completion7.lean.expected.out @@ -3,38 +3,18 @@ {"items": [{"label": "And", "kind": 22, - "data": - {"params": - {"textDocument": {"uri": "file:///completion7.lean"}, - "position": {"line": 6, "character": 10}}, - "id": {"const": {"declName": "And"}}, - "cPos": 0}}], + "data": ["«external:file:///completion7.lean»", 6, 10, 0, "cAnd"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completion7.lean"}, "position": {"line": 8, "character": 11}} {"items": - [{"label": "mk", - "kind": 4, - "data": - {"params": - {"textDocument": {"uri": "file:///completion7.lean"}, - "position": {"line": 8, "character": 11}}, - "id": {"const": {"declName": "And.mk"}}, - "cPos": 0}}, - {"label": "left", + [{"label": "left", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion7.lean"}, - "position": {"line": 8, "character": 11}}, - "id": {"const": {"declName": "And.left"}}, - "cPos": 0}}, + "data": ["«external:file:///completion7.lean»", 8, 11, 0, "cAnd.left"]}, {"label": "right", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completion7.lean"}, - "position": {"line": 8, "character": 11}}, - "id": {"const": {"declName": "And.right"}}, - "cPos": 0}}], + "data": ["«external:file:///completion7.lean»", 8, 11, 0, "cAnd.right"]}, + {"label": "mk", + "kind": 4, + "data": ["«external:file:///completion7.lean»", 8, 11, 0, "cAnd.mk"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionAtPrint.lean.expected.out b/tests/lean/interactive/completionAtPrint.lean.expected.out index 910ba92594..0b429b2372 100644 --- a/tests/lean/interactive/completionAtPrint.lean.expected.out +++ b/tests/lean/interactive/completionAtPrint.lean.expected.out @@ -3,10 +3,5 @@ {"items": [{"label": "gg", "kind": 21, - "data": - {"params": - {"textDocument": {"uri": "file:///completionAtPrint.lean"}, - "position": {"line": 2, "character": 10}}, - "id": {"const": {"declName": "f.gg"}}, - "cPos": 0}}], + "data": ["«external:file:///completionAtPrint.lean»", 2, 10, 0, "cf.gg"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionCheck.lean.expected.out b/tests/lean/interactive/completionCheck.lean.expected.out index a81bd54908..6606b60873 100644 --- a/tests/lean/interactive/completionCheck.lean.expected.out +++ b/tests/lean/interactive/completionCheck.lean.expected.out @@ -4,17 +4,17 @@ [{"label": "AVerySpecificStructureName2", "kind": 22, "data": - {"params": - {"textDocument": {"uri": "file:///completionCheck.lean"}, - "position": {"line": 6, "character": 33}}, - "id": {"const": {"declName": "AVerySpecificStructureName2"}}, - "cPos": 0}}, + ["«external:file:///completionCheck.lean»", + 6, + 33, + 0, + "cAVerySpecificStructureName2"]}, {"label": "AVerySpecificStructureName", "kind": 22, "data": - {"params": - {"textDocument": {"uri": "file:///completionCheck.lean"}, - "position": {"line": 6, "character": 33}}, - "id": {"const": {"declName": "AVerySpecificStructureName"}}, - "cPos": 0}}], + ["«external:file:///completionCheck.lean»", + 6, + 33, + 0, + "cAVerySpecificStructureName"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionDeprecation.lean.expected.out b/tests/lean/interactive/completionDeprecation.lean.expected.out index 4a25881f43..f451f232b8 100644 --- a/tests/lean/interactive/completionDeprecation.lean.expected.out +++ b/tests/lean/interactive/completionDeprecation.lean.expected.out @@ -2,73 +2,73 @@ "position": {"line": 25, "character": 28}} {"items": [{"tags": [1], + "label": "foo4", + "kind": 3, + "data": + ["«external:file:///completionDeprecation.lean»", + 25, + 28, + 0, + "cSomeStructure.foo4"]}, + {"tags": [1], "label": "foo8", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///completionDeprecation.lean"}, - "position": {"line": 25, "character": 28}}, - "id": {"const": {"declName": "SomeStructure.foo8"}}, - "cPos": 0}}, + ["«external:file:///completionDeprecation.lean»", + 25, + 28, + 0, + "cSomeStructure.foo8"]}, {"tags": [1], "label": "foo5", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///completionDeprecation.lean"}, - "position": {"line": 25, "character": 28}}, - "id": {"const": {"declName": "SomeStructure.foo5"}}, - "cPos": 0}}, - {"tags": [1], - "label": "foo4", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///completionDeprecation.lean"}, - "position": {"line": 25, "character": 28}}, - "id": {"const": {"declName": "SomeStructure.foo4"}}, - "cPos": 0}}, - {"tags": [1], - "label": "foo3", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///completionDeprecation.lean"}, - "position": {"line": 25, "character": 28}}, - "id": {"const": {"declName": "SomeStructure.foo3"}}, - "cPos": 0}}, - {"label": "foo2", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///completionDeprecation.lean"}, - "position": {"line": 25, "character": 28}}, - "id": {"const": {"declName": "SomeStructure.foo2"}}, - "cPos": 0}}, + ["«external:file:///completionDeprecation.lean»", + 25, + 28, + 0, + "cSomeStructure.foo5"]}, {"tags": [1], "label": "foo7", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///completionDeprecation.lean"}, - "position": {"line": 25, "character": 28}}, - "id": {"const": {"declName": "SomeStructure.foo7"}}, - "cPos": 0}}, + ["«external:file:///completionDeprecation.lean»", + 25, + 28, + 0, + "cSomeStructure.foo7"]}, + {"label": "foo1", + "kind": 3, + "data": + ["«external:file:///completionDeprecation.lean»", + 25, + 28, + 0, + "cSomeStructure.foo1"]}, {"tags": [1], "label": "foo6", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///completionDeprecation.lean"}, - "position": {"line": 25, "character": 28}}, - "id": {"const": {"declName": "SomeStructure.foo6"}}, - "cPos": 0}}, - {"label": "foo1", + ["«external:file:///completionDeprecation.lean»", + 25, + 28, + 0, + "cSomeStructure.foo6"]}, + {"tags": [1], + "label": "foo3", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///completionDeprecation.lean"}, - "position": {"line": 25, "character": 28}}, - "id": {"const": {"declName": "SomeStructure.foo1"}}, - "cPos": 0}}], + ["«external:file:///completionDeprecation.lean»", + 25, + 28, + 0, + "cSomeStructure.foo3"]}, + {"label": "foo2", + "kind": 3, + "data": + ["«external:file:///completionDeprecation.lean»", + 25, + 28, + 0, + "cSomeStructure.foo2"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionEOF.lean.expected.out b/tests/lean/interactive/completionEOF.lean.expected.out index 7b299e7be1..3320c94727 100644 --- a/tests/lean/interactive/completionEOF.lean.expected.out +++ b/tests/lean/interactive/completionEOF.lean.expected.out @@ -3,10 +3,5 @@ {"items": [{"label": "And", "kind": 21, - "data": - {"params": - {"textDocument": {"uri": "file:///completionEOF.lean"}, - "position": {"line": 8, "character": 9}}, - "id": {"const": {"declName": "And"}}, - "cPos": 0}}], + "data": ["«external:file:///completionEOF.lean»", 8, 9, 0, "cAnd"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionFallback.lean.expected.out b/tests/lean/interactive/completionFallback.lean.expected.out index b68235a10b..dc91570f5c 100644 --- a/tests/lean/interactive/completionFallback.lean.expected.out +++ b/tests/lean/interactive/completionFallback.lean.expected.out @@ -1,46 +1,42 @@ {"textDocument": {"uri": "file:///completionFallback.lean"}, "position": {"line": 14, "character": 14}} {"items": - [{"label": "noConfusionType", + [{"label": "up", + "kind": 4, + "data": + ["«external:file:///completionFallback.lean»", 14, 14, 0, "cDirection.up"]}, + {"label": "noConfusionType", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///completionFallback.lean"}, - "position": {"line": 14, "character": 14}}, - "id": {"const": {"declName": "Direction.noConfusionType"}}, - "cPos": 0}}, + ["«external:file:///completionFallback.lean»", + 14, + 14, + 0, + "cDirection.noConfusionType"]}, {"label": "left", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///completionFallback.lean"}, - "position": {"line": 14, "character": 14}}, - "id": {"const": {"declName": "Direction.left"}}, - "cPos": 0}}, - {"label": "right", - "kind": 4, - "data": - {"params": - {"textDocument": {"uri": "file:///completionFallback.lean"}, - "position": {"line": 14, "character": 14}}, - "id": {"const": {"declName": "Direction.right"}}, - "cPos": 0}}, - {"label": "up", - "kind": 4, - "data": - {"params": - {"textDocument": {"uri": "file:///completionFallback.lean"}, - "position": {"line": 14, "character": 14}}, - "id": {"const": {"declName": "Direction.up"}}, - "cPos": 0}}, + ["«external:file:///completionFallback.lean»", + 14, + 14, + 0, + "cDirection.left"]}, {"label": "down", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///completionFallback.lean"}, - "position": {"line": 14, "character": 14}}, - "id": {"const": {"declName": "Direction.down"}}, - "cPos": 0}}], + ["«external:file:///completionFallback.lean»", + 14, + 14, + 0, + "cDirection.down"]}, + {"label": "right", + "kind": 4, + "data": + ["«external:file:///completionFallback.lean»", + 14, + 14, + 0, + "cDirection.right"]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionFallback.lean"}, "position": {"line": 28, "character": 30}} @@ -48,25 +44,13 @@ [{"label": "mk", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///completionFallback.lean"}, - "position": {"line": 28, "character": 30}}, - "id": {"const": {"declName": "CustomAnd.mk"}}, - "cPos": 0}}, - {"label": "hb", - "kind": 23, - "data": - {"params": - {"textDocument": {"uri": "file:///completionFallback.lean"}, - "position": {"line": 28, "character": 30}}, - "id": {"const": {"declName": "CustomAnd.hb"}}, - "cPos": 0}}, + ["«external:file:///completionFallback.lean»", 28, 30, 0, "cCustomAnd.mk"]}, {"label": "ha", "kind": 23, "data": - {"params": - {"textDocument": {"uri": "file:///completionFallback.lean"}, - "position": {"line": 28, "character": 30}}, - "id": {"const": {"declName": "CustomAnd.ha"}}, - "cPos": 0}}], + ["«external:file:///completionFallback.lean»", 28, 30, 0, "cCustomAnd.ha"]}, + {"label": "hb", + "kind": 23, + "data": + ["«external:file:///completionFallback.lean»", 28, 30, 0, "cCustomAnd.hb"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionFromExpectedType.lean.expected.out b/tests/lean/interactive/completionFromExpectedType.lean.expected.out index ca464bf6c3..655a9b6c9c 100644 --- a/tests/lean/interactive/completionFromExpectedType.lean.expected.out +++ b/tests/lean/interactive/completionFromExpectedType.lean.expected.out @@ -4,9 +4,9 @@ [{"label": "mk", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///completionFromExpectedType.lean"}, - "position": {"line": 3, "character": 18}}, - "id": {"const": {"declName": "Foo.mk"}}, - "cPos": 0}}], + ["«external:file:///completionFromExpectedType.lean»", + 3, + 18, + 0, + "cFoo.mk"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionIStr.lean.expected.out b/tests/lean/interactive/completionIStr.lean.expected.out index f067812bea..ee26d0758f 100644 --- a/tests/lean/interactive/completionIStr.lean.expected.out +++ b/tests/lean/interactive/completionIStr.lean.expected.out @@ -1,28 +1,13 @@ {"textDocument": {"uri": "file:///completionIStr.lean"}, "position": {"line": 5, "character": 34}} {"items": - [{"label": "f2", + [{"label": "f1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completionIStr.lean"}, - "position": {"line": 5, "character": 34}}, - "id": {"const": {"declName": "C.f2"}}, - "cPos": 1}}, + "data": ["«external:file:///completionIStr.lean»", 5, 34, 1, "cC.f1"]}, {"label": "b1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completionIStr.lean"}, - "position": {"line": 5, "character": 34}}, - "id": {"const": {"declName": "C.b1"}}, - "cPos": 1}}, - {"label": "f1", + "data": ["«external:file:///completionIStr.lean»", 5, 34, 1, "cC.b1"]}, + {"label": "f2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completionIStr.lean"}, - "position": {"line": 5, "character": 34}}, - "id": {"const": {"declName": "C.f1"}}, - "cPos": 1}}], + "data": ["«external:file:///completionIStr.lean»", 5, 34, 1, "cC.f2"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionOpenNamespaces.lean.expected.out b/tests/lean/interactive/completionOpenNamespaces.lean.expected.out index b3c0313e5c..7bbe34bc36 100644 --- a/tests/lean/interactive/completionOpenNamespaces.lean.expected.out +++ b/tests/lean/interactive/completionOpenNamespaces.lean.expected.out @@ -4,11 +4,9 @@ [{"label": "verySpecificDefinitionNameOfCompletionOpenNamespaces", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///completionOpenNamespaces.lean"}, - "position": {"line": 4, "character": 68}}, - "id": - {"const": - {"declName": "A.B1.verySpecificDefinitionNameOfCompletionOpenNamespaces"}}, - "cPos": 0}}], + ["«external:file:///completionOpenNamespaces.lean»", + 4, + 68, + 0, + "cA.B1.verySpecificDefinitionNameOfCompletionOpenNamespaces"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionOption.lean.expected.out b/tests/lean/interactive/completionOption.lean.expected.out index 67acea2750..6c923d6a03 100644 --- a/tests/lean/interactive/completionOption.lean.expected.out +++ b/tests/lean/interactive/completionOption.lean.expected.out @@ -1,89 +1,9 @@ {"textDocument": {"uri": "file:///completionOption.lean"}, "position": {"line": 1, "character": 17}} {"items": - [{"textEdit": - {"replace": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}, - "newText": "trace.PrettyPrinter.format", - "insert": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}}, - "label": "trace.PrettyPrinter.format", + [{"label": "format.unicode", "kind": 10, - "detail": - "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 1, "character": 17}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}, - "newText": "trace.PrettyPrinter.format.input", - "insert": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}}, - "label": "trace.PrettyPrinter.format.input", - "kind": 10, - "detail": - "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 1, "character": 17}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}, - "newText": "format.inputWidth", - "insert": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}}, - "label": "format.inputWidth", - "kind": 10, - "detail": "(100), ideal input width", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 1, "character": 17}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}, - "newText": "format.width", - "insert": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}}, - "label": "format.width", - "kind": 10, - "detail": "(120), indentation", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 1, "character": 17}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}, - "newText": "format.indent", - "insert": - {"start": {"line": 1, "character": 11}, - "end": {"line": 1, "character": 17}}}, - "label": "format.indent", - "kind": 10, - "detail": "(2), indentation", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 1, "character": 17}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 1, "character": 11}, "end": {"line": 1, "character": 17}}, @@ -91,15 +11,73 @@ "insert": {"start": {"line": 1, "character": 11}, "end": {"line": 1, "character": 17}}}, - "label": "format.unicode", - "kind": 10, "detail": "(true), unicode characters", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 1, "character": 17}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 1, 17, 0]}, + {"label": "format.width", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}, + "newText": "format.width", + "insert": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}}, + "detail": "(120), indentation", + "data": ["«external:file:///completionOption.lean»", 1, 17, 0]}, + {"label": "format.inputWidth", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}, + "newText": "format.inputWidth", + "insert": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}}, + "detail": "(100), ideal input width", + "data": ["«external:file:///completionOption.lean»", 1, 17, 0]}, + {"label": "trace.PrettyPrinter.format.input", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}, + "newText": "trace.PrettyPrinter.format.input", + "insert": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}}, + "detail": + "(false), enable/disable tracing for the given module and submodules", + "data": ["«external:file:///completionOption.lean»", 1, 17, 0]}, + {"label": "trace.PrettyPrinter.format", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}, + "newText": "trace.PrettyPrinter.format", + "insert": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}}, + "detail": + "(false), enable/disable tracing for the given module and submodules", + "data": ["«external:file:///completionOption.lean»", 1, 17, 0]}, + {"label": "format.indent", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}, + "newText": "format.indent", + "insert": + {"start": {"line": 1, "character": 11}, + "end": {"line": 1, "character": 17}}}, + "detail": "(2), indentation", + "data": ["«external:file:///completionOption.lean»", 1, 17, 0]}, + {"label": "trace.PrettyPrinter.format.backtrack", + "kind": 10, + "edit": {"replace": {"start": {"line": 1, "character": 11}, "end": {"line": 1, "character": 17}}, @@ -107,20 +85,16 @@ "insert": {"start": {"line": 1, "character": 11}, "end": {"line": 1, "character": 17}}}, - "label": "trace.PrettyPrinter.format.backtrack", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 1, "character": 17}}, - "cPos": 0}}], + "data": ["«external:file:///completionOption.lean»", 1, 17, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionOption.lean"}, "position": {"line": 4, "character": 20}} {"items": - [{"textEdit": + [{"label": "format.inputWidth", + "kind": 10, + "edit": {"replace": {"start": {"line": 4, "character": 11}, "end": {"line": 4, "character": 20}}, @@ -128,15 +102,11 @@ "insert": {"start": {"line": 4, "character": 11}, "end": {"line": 4, "character": 20}}}, - "label": "format.inputWidth", - "kind": 10, "detail": "(100), ideal input width", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 4, "character": 20}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 4, 20, 0]}, + {"label": "trace.PrettyPrinter.format.input", + "kind": 10, + "edit": {"replace": {"start": {"line": 4, "character": 11}, "end": {"line": 4, "character": 20}}, @@ -144,16 +114,12 @@ "insert": {"start": {"line": 4, "character": 11}, "end": {"line": 4, "character": 20}}}, - "label": "trace.PrettyPrinter.format.input", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 4, "character": 20}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 4, 20, 0]}, + {"label": "format.indent", + "kind": 10, + "edit": {"replace": {"start": {"line": 4, "character": 11}, "end": {"line": 4, "character": 20}}, @@ -161,19 +127,15 @@ "insert": {"start": {"line": 4, "character": 11}, "end": {"line": 4, "character": 20}}}, - "label": "format.indent", - "kind": 10, "detail": "(2), indentation", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 4, "character": 20}}, - "cPos": 0}}], + "data": ["«external:file:///completionOption.lean»", 4, 20, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionOption.lean"}, "position": {"line": 7, "character": 23}} {"items": - [{"textEdit": + [{"label": "trace.Compiler.specialize.candidate", + "kind": 10, + "edit": {"replace": {"start": {"line": 7, "character": 11}, "end": {"line": 7, "character": 23}}, @@ -181,50 +143,12 @@ "insert": {"start": {"line": 7, "character": 11}, "end": {"line": 7, "character": 23}}}, - "label": "trace.Compiler.specialize.candidate", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 7, "character": 23}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 7, "character": 11}, - "end": {"line": 7, "character": 23}}, - "newText": "trace.pp.analyze", - "insert": - {"start": {"line": 7, "character": 11}, - "end": {"line": 7, "character": 23}}}, - "label": "trace.pp.analyze", + "data": ["«external:file:///completionOption.lean»", 7, 23, 0]}, + {"label": "trace.pp.analyze.error", "kind": 10, - "detail": - "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 7, "character": 23}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 7, "character": 11}, - "end": {"line": 7, "character": 23}}, - "newText": "trace.pp.analyze.tryUnify", - "insert": - {"start": {"line": 7, "character": 11}, - "end": {"line": 7, "character": 23}}}, - "label": "trace.pp.analyze.tryUnify", - "kind": 10, - "detail": - "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 7, "character": 23}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 7, "character": 11}, "end": {"line": 7, "character": 23}}, @@ -232,16 +156,38 @@ "insert": {"start": {"line": 7, "character": 11}, "end": {"line": 7, "character": 23}}}, - "label": "trace.pp.analyze.error", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 7, "character": 23}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 7, 23, 0]}, + {"label": "trace.pp.analyze", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 7, "character": 11}, + "end": {"line": 7, "character": 23}}, + "newText": "trace.pp.analyze", + "insert": + {"start": {"line": 7, "character": 11}, + "end": {"line": 7, "character": 23}}}, + "detail": + "(false), enable/disable tracing for the given module and submodules", + "data": ["«external:file:///completionOption.lean»", 7, 23, 0]}, + {"label": "trace.pp.analyze.tryUnify", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 7, "character": 11}, + "end": {"line": 7, "character": 23}}, + "newText": "trace.pp.analyze.tryUnify", + "insert": + {"start": {"line": 7, "character": 11}, + "end": {"line": 7, "character": 23}}}, + "detail": + "(false), enable/disable tracing for the given module and submodules", + "data": ["«external:file:///completionOption.lean»", 7, 23, 0]}, + {"label": "trace.pp.analyze.annotate", + "kind": 10, + "edit": {"replace": {"start": {"line": 7, "character": 11}, "end": {"line": 7, "character": 23}}, @@ -249,37 +195,16 @@ "insert": {"start": {"line": 7, "character": 11}, "end": {"line": 7, "character": 23}}}, - "label": "trace.pp.analyze.annotate", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 7, "character": 23}}, - "cPos": 0}}], + "data": ["«external:file:///completionOption.lean»", 7, 23, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionOption.lean"}, "position": {"line": 10, "character": 27}} {"items": - [{"textEdit": - {"replace": - {"start": {"line": 10, "character": 11}, - "end": {"line": 10, "character": 27}}, - "newText": "trace.pp.analyze.tryUnify", - "insert": - {"start": {"line": 10, "character": 11}, - "end": {"line": 10, "character": 27}}}, - "label": "trace.pp.analyze.tryUnify", + [{"label": "trace.pp.analyze.error", "kind": 10, - "detail": - "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 10, "character": 27}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 10, "character": 11}, "end": {"line": 10, "character": 27}}, @@ -287,16 +212,12 @@ "insert": {"start": {"line": 10, "character": 11}, "end": {"line": 10, "character": 27}}}, - "label": "trace.pp.analyze.error", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 10, "character": 27}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 10, 27, 0]}, + {"label": "trace.pp.analyze", + "kind": 10, + "edit": {"replace": {"start": {"line": 10, "character": 11}, "end": {"line": 10, "character": 27}}, @@ -304,16 +225,25 @@ "insert": {"start": {"line": 10, "character": 11}, "end": {"line": 10, "character": 27}}}, - "label": "trace.pp.analyze", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 10, "character": 27}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 10, 27, 0]}, + {"label": "trace.pp.analyze.tryUnify", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 10, "character": 11}, + "end": {"line": 10, "character": 27}}, + "newText": "trace.pp.analyze.tryUnify", + "insert": + {"start": {"line": 10, "character": 11}, + "end": {"line": 10, "character": 27}}}, + "detail": + "(false), enable/disable tracing for the given module and submodules", + "data": ["«external:file:///completionOption.lean»", 10, 27, 0]}, + {"label": "trace.pp.analyze.annotate", + "kind": 10, + "edit": {"replace": {"start": {"line": 10, "character": 11}, "end": {"line": 10, "character": 27}}, @@ -321,36 +251,28 @@ "insert": {"start": {"line": 10, "character": 11}, "end": {"line": 10, "character": 27}}}, - "label": "trace.pp.analyze.annotate", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 10, "character": 27}}, - "cPos": 0}}], + "data": ["«external:file:///completionOption.lean»", 10, 27, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionOption.lean"}, "position": {"line": 13, "character": 17}} {"items": - [{"textEdit": + [{"label": "format.unicode", + "kind": 10, + "edit": {"replace": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}, - "newText": "format.indent", + "newText": "format.unicode", "insert": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}}, - "label": "format.indent", + "detail": "(true), unicode characters", + "data": ["«external:file:///completionOption.lean»", 13, 17, 0]}, + {"label": "format.width", "kind": 10, - "detail": "(2), indentation", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 13, "character": 17}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}, @@ -358,49 +280,11 @@ "insert": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}}, - "label": "format.width", - "kind": 10, "detail": "(120), indentation", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 13, "character": 17}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 13, "character": 11}, - "end": {"line": 13, "character": 17}}, - "newText": "trace.PrettyPrinter.format.input", - "insert": - {"start": {"line": 13, "character": 11}, - "end": {"line": 13, "character": 17}}}, - "label": "trace.PrettyPrinter.format.input", + "data": ["«external:file:///completionOption.lean»", 13, 17, 0]}, + {"label": "format.inputWidth", "kind": 10, - "detail": - "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 13, "character": 17}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 13, "character": 11}, - "end": {"line": 13, "character": 17}}, - "newText": "trace.PrettyPrinter.format.backtrack", - "insert": - {"start": {"line": 13, "character": 11}, - "end": {"line": 13, "character": 17}}}, - "label": "trace.PrettyPrinter.format.backtrack", - "kind": 10, - "detail": - "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 13, "character": 17}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}, @@ -408,15 +292,24 @@ "insert": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}}, - "label": "format.inputWidth", - "kind": 10, "detail": "(100), ideal input width", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 13, "character": 17}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 13, 17, 0]}, + {"label": "trace.PrettyPrinter.format.input", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 13, "character": 11}, + "end": {"line": 13, "character": 17}}, + "newText": "trace.PrettyPrinter.format.input", + "insert": + {"start": {"line": 13, "character": 11}, + "end": {"line": 13, "character": 17}}}, + "detail": + "(false), enable/disable tracing for the given module and submodules", + "data": ["«external:file:///completionOption.lean»", 13, 17, 0]}, + {"label": "trace.PrettyPrinter.format", + "kind": 10, + "edit": {"replace": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}, @@ -424,36 +317,41 @@ "insert": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}}, - "label": "trace.PrettyPrinter.format", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 13, "character": 17}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 13, 17, 0]}, + {"label": "format.indent", + "kind": 10, + "edit": {"replace": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}, - "newText": "format.unicode", + "newText": "format.indent", "insert": {"start": {"line": 13, "character": 11}, "end": {"line": 13, "character": 17}}}, - "label": "format.unicode", + "detail": "(2), indentation", + "data": ["«external:file:///completionOption.lean»", 13, 17, 0]}, + {"label": "trace.PrettyPrinter.format.backtrack", "kind": 10, - "detail": "(true), unicode characters", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 13, "character": 17}}, - "cPos": 0}}], + "edit": + {"replace": + {"start": {"line": 13, "character": 11}, + "end": {"line": 13, "character": 17}}, + "newText": "trace.PrettyPrinter.format.backtrack", + "insert": + {"start": {"line": 13, "character": 11}, + "end": {"line": 13, "character": 17}}}, + "detail": + "(false), enable/disable tracing for the given module and submodules", + "data": ["«external:file:///completionOption.lean»", 13, 17, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionOption.lean"}, "position": {"line": 16, "character": 18}} {"items": - [{"textEdit": + [{"label": "format.unicode", + "kind": 10, + "edit": {"replace": {"start": {"line": 16, "character": 11}, "end": {"line": 16, "character": 18}}, @@ -461,31 +359,11 @@ "insert": {"start": {"line": 16, "character": 11}, "end": {"line": 16, "character": 18}}}, - "label": "format.unicode", - "kind": 10, "detail": "(true), unicode characters", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 16, "character": 18}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 16, "character": 11}, - "end": {"line": 16, "character": 18}}, - "newText": "format.inputWidth", - "insert": - {"start": {"line": 16, "character": 11}, - "end": {"line": 16, "character": 18}}}, - "label": "format.inputWidth", + "data": ["«external:file:///completionOption.lean»", 16, 18, 0]}, + {"label": "format.width", "kind": 10, - "detail": "(100), ideal input width", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 16, "character": 18}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 16, "character": 11}, "end": {"line": 16, "character": 18}}, @@ -493,48 +371,23 @@ "insert": {"start": {"line": 16, "character": 11}, "end": {"line": 16, "character": 18}}}, - "label": "format.width", - "kind": 10, "detail": "(120), indentation", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 16, "character": 18}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///completionOption.lean»", 16, 18, 0]}, + {"label": "format.inputWidth", + "kind": 10, + "edit": {"replace": {"start": {"line": 16, "character": 11}, "end": {"line": 16, "character": 18}}, - "newText": "format.indent", + "newText": "format.inputWidth", "insert": {"start": {"line": 16, "character": 11}, "end": {"line": 16, "character": 18}}}, - "label": "format.indent", + "detail": "(100), ideal input width", + "data": ["«external:file:///completionOption.lean»", 16, 18, 0]}, + {"label": "trace.PrettyPrinter.format.input", "kind": 10, - "detail": "(2), indentation", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 16, "character": 18}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 16, "character": 11}, - "end": {"line": 16, "character": 18}}, - "newText": "trace.PrettyPrinter.format.backtrack", - "insert": - {"start": {"line": 16, "character": 11}, - "end": {"line": 16, "character": 18}}}, - "label": "trace.PrettyPrinter.format.backtrack", - "kind": 10, - "detail": - "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 16, "character": 18}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 16, "character": 11}, "end": {"line": 16, "character": 18}}, @@ -542,13 +395,32 @@ "insert": {"start": {"line": 16, "character": 11}, "end": {"line": 16, "character": 18}}}, - "label": "trace.PrettyPrinter.format.input", - "kind": 10, "detail": "(false), enable/disable tracing for the given module and submodules", - "data": - {"params": - {"textDocument": {"uri": "file:///completionOption.lean"}, - "position": {"line": 16, "character": 18}}, - "cPos": 0}}], + "data": ["«external:file:///completionOption.lean»", 16, 18, 0]}, + {"label": "format.indent", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 16, "character": 11}, + "end": {"line": 16, "character": 18}}, + "newText": "format.indent", + "insert": + {"start": {"line": 16, "character": 11}, + "end": {"line": 16, "character": 18}}}, + "detail": "(2), indentation", + "data": ["«external:file:///completionOption.lean»", 16, 18, 0]}, + {"label": "trace.PrettyPrinter.format.backtrack", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 16, "character": 11}, + "end": {"line": 16, "character": 18}}, + "newText": "trace.PrettyPrinter.format.backtrack", + "insert": + {"start": {"line": 16, "character": 11}, + "end": {"line": 16, "character": 18}}}, + "detail": + "(false), enable/disable tracing for the given module and submodules", + "data": ["«external:file:///completionOption.lean»", 16, 18, 0]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionPrefixIssue.lean.expected.out b/tests/lean/interactive/completionPrefixIssue.lean.expected.out index 9f04a318b1..dc4fc6f27c 100644 --- a/tests/lean/interactive/completionPrefixIssue.lean.expected.out +++ b/tests/lean/interactive/completionPrefixIssue.lean.expected.out @@ -4,18 +4,13 @@ [{"label": "veryLongDefinitionName", "kind": 6, "data": - {"params": - {"textDocument": {"uri": "file:///completionPrefixIssue.lean"}, - "position": {"line": 1, "character": 64}}, - "id": {"fvar": {"id": "_uniq.35"}}, - "cPos": 0}}, + ["«external:file:///completionPrefixIssue.lean»", 1, 64, 0, "f_uniq.35"]}, {"label": "veryLongDefinitionNameVeryLongDefinitionName", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///completionPrefixIssue.lean"}, - "position": {"line": 1, "character": 64}}, - "id": - {"const": {"declName": "veryLongDefinitionNameVeryLongDefinitionName"}}, - "cPos": 0}}], + ["«external:file:///completionPrefixIssue.lean»", + 1, + 64, + 0, + "cveryLongDefinitionNameVeryLongDefinitionName"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionPrivateTypes.lean.expected.out b/tests/lean/interactive/completionPrivateTypes.lean.expected.out index 33c567a476..c35550ca62 100644 --- a/tests/lean/interactive/completionPrivateTypes.lean.expected.out +++ b/tests/lean/interactive/completionPrivateTypes.lean.expected.out @@ -4,12 +4,9 @@ [{"label": "x", "kind": 5, "data": - {"params": - {"textDocument": {"uri": "file:///completionPrivateTypes.lean"}, - "position": {"line": 3, "character": 26}}, - "id": - {"const": - {"declName": - "_private.«external:file:///completionPrivateTypes.lean».0.Foo.x"}}, - "cPos": 1}}], + ["«external:file:///completionPrivateTypes.lean»", + 3, + 26, + 1, + "c_private.«external:file:///completionPrivateTypes.lean».0.Foo.x"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionPrv.lean.expected.out b/tests/lean/interactive/completionPrv.lean.expected.out index aceb56499d..b579f34e0c 100644 --- a/tests/lean/interactive/completionPrv.lean.expected.out +++ b/tests/lean/interactive/completionPrv.lean.expected.out @@ -4,14 +4,11 @@ [{"label": "longAndHopefullyUniqueBlaBlaBoo", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///completionPrv.lean"}, - "position": {"line": 2, "character": 33}}, - "id": - {"const": - {"declName": - "_private.«external:file:///completionPrv.lean».0.longAndHopefullyUniqueBlaBlaBoo"}}, - "cPos": 0}}], + ["«external:file:///completionPrv.lean»", + 2, + 33, + 0, + "c_private.«external:file:///completionPrv.lean».0.longAndHopefullyUniqueBlaBlaBoo"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionPrv.lean"}, "position": {"line": 9, "character": 33}} @@ -19,14 +16,11 @@ [{"label": "longAndHopefullyUniqueBooBoo", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///completionPrv.lean"}, - "position": {"line": 9, "character": 33}}, - "id": - {"const": - {"declName": - "_private.«external:file:///completionPrv.lean».0.Foo.longAndHopefullyUniqueBooBoo"}}, - "cPos": 0}}], + ["«external:file:///completionPrv.lean»", + 9, + 33, + 0, + "c_private.«external:file:///completionPrv.lean».0.Foo.longAndHopefullyUniqueBooBoo"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionPrv.lean"}, "position": {"line": 21, "character": 5}} @@ -34,21 +28,14 @@ [{"label": "getInc", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///completionPrv.lean"}, - "position": {"line": 21, "character": 5}}, - "id": - {"const": - {"declName": "_private.«external:file:///completionPrv.lean».0.S.getInc"}}, - "cPos": 1}}, + ["«external:file:///completionPrv.lean»", + 21, + 5, + 1, + "c_private.«external:file:///completionPrv.lean».0.S.getInc"]}, {"label": "field1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completionPrv.lean"}, - "position": {"line": 21, "character": 5}}, - "id": {"const": {"declName": "S.field1"}}, - "cPos": 1}}], + "data": ["«external:file:///completionPrv.lean»", 21, 5, 1, "cS.field1"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionPrv.lean"}, "position": {"line": 25, "character": 4}} @@ -56,19 +43,12 @@ [{"label": "getInc", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///completionPrv.lean"}, - "position": {"line": 25, "character": 4}}, - "id": - {"const": - {"declName": "_private.«external:file:///completionPrv.lean».0.S.getInc"}}, - "cPos": 1}}, + ["«external:file:///completionPrv.lean»", + 25, + 4, + 1, + "c_private.«external:file:///completionPrv.lean».0.S.getInc"]}, {"label": "field1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///completionPrv.lean"}, - "position": {"line": 25, "character": 4}}, - "id": {"const": {"declName": "S.field1"}}, - "cPos": 1}}], + "data": ["«external:file:///completionPrv.lean»", 25, 4, 1, "cS.field1"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionStructureInstance.lean.expected.out b/tests/lean/interactive/completionStructureInstance.lean.expected.out index 0e965ca5d5..c9a2df2b85 100644 --- a/tests/lean/interactive/completionStructureInstance.lean.expected.out +++ b/tests/lean/interactive/completionStructureInstance.lean.expected.out @@ -1,166 +1,94 @@ {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 10, "character": 17}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 10, "character": 17}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 10, "character": 17}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 10, 17, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 10, "character": 17}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 10, 17, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 10, "character": 17}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 10, 17, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 10, 17, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 13, "character": 18}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 13, "character": 18}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 13, "character": 18}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 13, 18, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 13, "character": 18}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 13, 18, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 13, "character": 18}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 13, 18, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 13, 18, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 17, "character": 2}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 17, "character": 2}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 17, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 17, 2, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 17, "character": 2}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 17, 2, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 17, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 17, 2, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 17, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 21, "character": 3}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 21, "character": 3}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 21, 3, 0]}, {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 21, "character": 3}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 21, 3, 0]}, + {"label": "barfoo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 21, "character": 3}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 21, 3, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 25, "character": 5}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 25, "character": 5}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 25, 5, 0]}, {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 25, "character": 5}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 25, 5, 0]}, + {"label": "barfoo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 25, "character": 5}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 25, 5, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 29, "character": 9}} @@ -171,202 +99,114 @@ {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 39, "character": 2}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 39, "character": 2}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 39, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 39, 2, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 39, "character": 2}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 39, 2, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 39, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 39, 2, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 39, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 43, "character": 12}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 43, "character": 12}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 43, "character": 12}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 43, 12, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 43, "character": 12}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 43, 12, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 43, "character": 12}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 43, 12, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 43, 12, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 46, "character": 17}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 46, "character": 17}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 46, "character": 17}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 46, 17, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 46, "character": 17}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 46, 17, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 46, "character": 17}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 46, 17, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 46, 17, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 50, "character": 2}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 50, "character": 2}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 50, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 50, 2, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 50, "character": 2}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 50, 2, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 50, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 50, 2, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 50, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 55, "character": 3}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 55, "character": 3}}, - "cPos": 1}}, + "data": ["«external:file:///completionStructureInstance.lean»", 55, 3, 1]}, {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 55, "character": 3}}, - "cPos": 1}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 55, 3, 1]}, + {"label": "barfoo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 55, "character": 3}}, - "cPos": 1}}], + "data": ["«external:file:///completionStructureInstance.lean»", 55, 3, 1]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 60, "character": 5}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 60, "character": 5}}, - "cPos": 1}}, + "data": ["«external:file:///completionStructureInstance.lean»", 60, 5, 1]}, {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 60, "character": 5}}, - "cPos": 1}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 60, 5, 1]}, + {"label": "barfoo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 60, "character": 5}}, - "cPos": 1}}], + "data": ["«external:file:///completionStructureInstance.lean»", 60, 5, 1]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 66, "character": 4}} @@ -374,210 +214,118 @@ {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 72, "character": 2}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 72, "character": 2}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 72, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 72, 2, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 72, "character": 2}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 72, 2, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 72, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 72, 2, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 72, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 78, "character": 4}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 78, "character": 4}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 78, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 78, 4, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 78, "character": 4}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 78, 4, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 78, "character": 4}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 78, 4, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 78, 4, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 82, "character": 27}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 82, "character": 27}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 82, "character": 27}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 82, 27, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 82, "character": 27}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 82, 27, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 82, "character": 27}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 82, 27, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 82, 27, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 85, "character": 32}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 85, "character": 32}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 85, "character": 32}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 85, 32, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 85, "character": 32}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 85, 32, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 85, "character": 32}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 85, 32, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 85, 32, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 88, "character": 32}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 88, "character": 32}}, - "cPos": 0}}, - {"label": "foobar", - "kind": 5, - "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 88, "character": 32}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 88, 32, 0]}, {"label": "bar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 88, "character": 32}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 88, 32, 0]}, + {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 88, "character": 32}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 88, 32, 0]}, + {"label": "barfoo", + "kind": 5, + "detail": "field", + "data": ["«external:file:///completionStructureInstance.lean»", 88, 32, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 91, "character": 33}} {"items": - [{"label": "barfoo", + [{"label": "foo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 91, "character": 33}}, - "cPos": 0}}, + "data": ["«external:file:///completionStructureInstance.lean»", 91, 33, 0]}, {"label": "foobar", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 91, "character": 33}}, - "cPos": 0}}, - {"label": "foo", + "data": ["«external:file:///completionStructureInstance.lean»", 91, 33, 0]}, + {"label": "barfoo", "kind": 5, "detail": "field", - "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 91, "character": 33}}, - "cPos": 0}}], + "data": ["«external:file:///completionStructureInstance.lean»", 91, 33, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, "position": {"line": 96, "character": 52}} @@ -585,9 +333,9 @@ [{"label": "aLongUniqueIdentifier", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///completionStructureInstance.lean"}, - "position": {"line": 96, "character": 52}}, - "id": {"const": {"declName": "aLongUniqueIdentifier"}}, - "cPos": 0}}], + ["«external:file:///completionStructureInstance.lean»", + 96, + 52, + 0, + "caLongUniqueIdentifier"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/completionTactics.lean.expected.out b/tests/lean/interactive/completionTactics.lean.expected.out index 20f76299b3..d002ac55d8 100644 --- a/tests/lean/interactive/completionTactics.lean.expected.out +++ b/tests/lean/interactive/completionTactics.lean.expected.out @@ -10,74 +10,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 23, "character": 21}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 23, "character": 21}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 23, 21, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 23, "character": 21}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 23, "character": 21}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 23, 21, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 23, "character": 21}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 23, 21, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 23, 21, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 23, "character": 21}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 23, 21, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 23, "character": 21}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 23, 21, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 23, 21, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 23, "character": 21}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 23, 21, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 26, "character": 24}} @@ -88,74 +56,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 26, "character": 24}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 26, "character": 24}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 26, 24, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 26, "character": 24}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 26, "character": 24}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 26, 24, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 26, "character": 24}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 26, 24, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 26, 24, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 26, "character": 24}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 26, 24, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 26, "character": 24}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 26, 24, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 26, 24, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 26, "character": 24}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 26, 24, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 29, "character": 25}} @@ -169,74 +105,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 32, "character": 26}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 32, "character": 26}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 32, 26, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 32, "character": 26}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 32, "character": 26}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 32, 26, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 32, "character": 26}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 32, 26, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 32, 26, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 32, "character": 26}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 32, 26, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 32, "character": 26}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 32, 26, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 32, 26, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 32, "character": 26}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 32, 26, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 35, "character": 27}} @@ -247,74 +151,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 35, "character": 27}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 35, "character": 27}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 35, 27, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 35, "character": 27}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 35, "character": 27}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 35, 27, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 35, "character": 27}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 35, 27, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 35, 27, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 35, "character": 27}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 35, 27, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 35, "character": 27}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 35, 27, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 35, 27, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 35, "character": 27}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 35, 27, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 40, "character": 7}} @@ -325,74 +197,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 40, "character": 7}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 40, "character": 7}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 40, 7, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 40, "character": 7}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 40, "character": 7}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 40, 7, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 40, "character": 7}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 40, 7, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 40, 7, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 40, "character": 7}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 40, 7, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 40, "character": 7}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 40, 7, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 40, 7, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 40, "character": 7}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 40, 7, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 44, "character": 2}} @@ -403,74 +243,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 44, "character": 2}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 44, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 44, 2, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 44, "character": 2}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 44, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 44, 2, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 44, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 44, 2, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 44, 2, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 44, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 44, 2, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 44, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 44, 2, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 44, 2, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 44, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 44, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 49, "character": 2}} @@ -481,74 +289,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 49, "character": 2}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 49, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 49, 2, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 49, "character": 2}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 49, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 49, 2, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 49, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 49, 2, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 49, 2, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 49, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 49, 2, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 49, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 49, 2, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 49, 2, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 49, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 49, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 53, "character": 2}} @@ -559,74 +335,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 53, "character": 2}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 53, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 53, 2, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 53, "character": 2}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 53, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 53, 2, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 53, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 53, 2, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 53, 2, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 53, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 53, 2, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 53, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 53, 2, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 53, 2, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 53, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 53, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 59, "character": 4}} @@ -637,74 +381,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 59, "character": 4}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 59, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 59, 4, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 59, "character": 4}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 59, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 59, 4, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 59, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 59, 4, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 59, 4, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 59, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 59, 4, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 59, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 59, 4, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 59, 4, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 59, "character": 4}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 59, 4, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 64, "character": 2}} @@ -715,74 +427,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 64, "character": 2}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 64, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 64, 2, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 64, "character": 2}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 64, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 64, 2, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 64, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 64, 2, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 64, 2, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 64, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 64, 2, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 64, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 64, 2, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 64, 2, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 64, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 64, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 70, "character": 4}} @@ -793,74 +473,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 70, "character": 4}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 70, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 70, 4, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 70, "character": 4}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 70, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 70, 4, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 70, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 70, 4, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 70, 4, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 70, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 70, 4, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 70, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 70, 4, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 70, 4, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 70, "character": 4}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 70, 4, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 76, "character": 2}} @@ -871,74 +519,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 76, "character": 2}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 76, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 76, 2, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 76, "character": 2}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 76, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 76, 2, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 76, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 76, 2, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 76, 2, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 76, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 76, 2, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 76, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 76, 2, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 76, 2, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 76, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 76, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 81, "character": 4}} @@ -952,74 +568,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 86, "character": 2}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 86, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 86, 2, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 86, "character": 2}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 86, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 86, 2, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 86, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 86, 2, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 86, 2, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 86, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 86, 2, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 86, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 86, 2, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 86, 2, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 86, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 86, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 91, "character": 4}} @@ -1030,74 +614,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 91, "character": 4}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 91, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 91, 4, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 91, "character": 4}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 91, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 91, 4, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 91, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 91, 4, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 91, 4, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 91, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 91, 4, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 91, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 91, 4, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 91, 4, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 91, "character": 4}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 91, 4, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 96, "character": 2}} @@ -1108,74 +660,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 96, "character": 2}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 96, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 96, 2, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 96, "character": 2}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 96, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 96, 2, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 96, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 96, 2, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 96, 2, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 96, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 96, 2, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 96, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 96, 2, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 96, 2, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 96, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 96, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 102, "character": 4}} @@ -1186,74 +706,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 102, "character": 4}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 102, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 102, 4, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 102, "character": 4}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 102, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 102, 4, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 102, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 102, 4, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 102, 4, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 102, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 102, 4, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 102, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 102, 4, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 102, 4, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 102, "character": 4}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 102, 4, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 108, "character": 2}} @@ -1267,74 +755,42 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 112, "character": 2}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 112, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 112, 2, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 112, "character": 2}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 112, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 112, 2, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 112, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 112, 2, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 112, 2, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 112, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 112, 2, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 112, "character": 2}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 112, 2, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 112, 2, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 112, "character": 2}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 112, 2, 0]}], "isIncomplete": true} {"textDocument": {"uri": "file:///completionTactics.lean"}, "position": {"line": 118, "character": 4}} @@ -1345,72 +801,40 @@ {"value": "`open Foo in tacs` (the tactic) acts like `open Foo` at command level,\nbut it opens a namespace only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 118, "character": 4}}, - "cPos": 0}}, - {"label": "skip", - "kind": 14, - "documentation": {"value": "A docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 118, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 118, 4, 0]}, {"label": "Lean.Parser.Tactic.match", "kind": 14, "documentation": {"value": "`match` performs case analysis on one or more expressions.\nSee [Induction and Recursion][tpil4].\nThe syntax for the `match` tactic is the same as term-mode `match`, except that\nthe match arms are tactics instead of expressions.\n```\nexample (n : Nat) : n = n := by\n match n with\n | 0 => rfl\n | i+1 => simp\n```\n\n[tpil4]: https://lean-lang.org/theorem_proving_in_lean4/induction_and_recursion.html\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 118, "character": 4}}, - "cPos": 0}}, - {"label": "exact", - "kind": 14, - "documentation": {"value": "Another docstring ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 118, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 118, 4, 0]}, {"label": "Lean.Parser.Tactic.set_option", "kind": 14, "documentation": {"value": "`set_option opt val in tacs` (the tactic) acts like `set_option opt val` at the command level,\nbut it sets the option only within the tactics `tacs`. ", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 118, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 118, 4, 0]}, + {"label": "skip", + "kind": 14, + "documentation": {"value": "A docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 118, 4, 0]}, {"label": "Lean.Parser.Tactic.nestedTactic", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 118, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 118, 4, 0]}, {"label": "Lean.Parser.Tactic.unknown", "kind": 14, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 118, "character": 4}}, - "cPos": 0}}, + "data": ["«external:file:///completionTactics.lean»", 118, 4, 0]}, + {"label": "exact", + "kind": 14, + "documentation": {"value": "Another docstring ", "kind": "markdown"}, + "data": ["«external:file:///completionTactics.lean»", 118, 4, 0]}, {"label": "Lean.Parser.Tactic.introMatch", "kind": 14, "documentation": {"value": "The tactic\n```\nintro\n| pat1 => tac1\n| pat2 => tac2\n```\nis the same as:\n```\nintro x\nmatch x with\n| pat1 => tac1\n| pat2 => tac2\n```\nThat is, `intro` can be followed by match arms and it introduces the values while\ndoing a pattern match. This is equivalent to `fun` with match arms in term mode.\n", "kind": "markdown"}, - "data": - {"params": - {"textDocument": {"uri": "file:///completionTactics.lean"}, - "position": {"line": 118, "character": 4}}, - "cPos": 0}}], + "data": ["«external:file:///completionTactics.lean»", 118, 4, 0]}], "isIncomplete": true} diff --git a/tests/lean/interactive/dotIdCompletion.lean.expected.out b/tests/lean/interactive/dotIdCompletion.lean.expected.out index 5f1104d36a..ca1f1fc84b 100644 --- a/tests/lean/interactive/dotIdCompletion.lean.expected.out +++ b/tests/lean/interactive/dotIdCompletion.lean.expected.out @@ -1,20 +1,10 @@ {"textDocument": {"uri": "file:///dotIdCompletion.lean"}, "position": {"line": 4, "character": 5}} {"items": - [{"label": "truth", + [{"label": "true", "kind": 4, - "data": - {"params": - {"textDocument": {"uri": "file:///dotIdCompletion.lean"}, - "position": {"line": 4, "character": 5}}, - "id": {"const": {"declName": "Boo.truth"}}, - "cPos": 0}}, - {"label": "true", + "data": ["«external:file:///dotIdCompletion.lean»", 4, 5, 0, "cBoo.true"]}, + {"label": "truth", "kind": 4, - "data": - {"params": - {"textDocument": {"uri": "file:///dotIdCompletion.lean"}, - "position": {"line": 4, "character": 5}}, - "id": {"const": {"declName": "Boo.true"}}, - "cPos": 0}}], + "data": ["«external:file:///dotIdCompletion.lean»", 4, 5, 0, "cBoo.truth"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/dottedIdentNotation.lean.expected.out b/tests/lean/interactive/dottedIdentNotation.lean.expected.out index 7e7ff3cb12..49fd1c8302 100644 --- a/tests/lean/interactive/dottedIdentNotation.lean.expected.out +++ b/tests/lean/interactive/dottedIdentNotation.lean.expected.out @@ -4,11 +4,7 @@ [{"label": "zero", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, - "position": {"line": 11, "character": 22}}, - "id": {"const": {"declName": "MyNat.zero"}}, - "cPos": 0}}], + ["«external:file:///dottedIdentNotation.lean»", 11, 22, 0, "cMyNat.zero"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, "position": {"line": 14, "character": 30}} @@ -16,11 +12,7 @@ [{"label": "succ", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, - "position": {"line": 14, "character": 30}}, - "id": {"const": {"declName": "MyNat.succ"}}, - "cPos": 0}}], + ["«external:file:///dottedIdentNotation.lean»", 14, 30, 0, "cMyNat.succ"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, "position": {"line": 23, "character": 23}} @@ -28,11 +20,7 @@ [{"label": "zero", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, - "position": {"line": 23, "character": 23}}, - "id": {"const": {"declName": "MyNat.zero"}}, - "cPos": 0}}], + ["«external:file:///dottedIdentNotation.lean»", 23, 23, 0, "cMyNat.zero"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, "position": {"line": 26, "character": 32}} @@ -40,11 +28,7 @@ [{"label": "succ", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, - "position": {"line": 26, "character": 32}}, - "id": {"const": {"declName": "MyNat.succ"}}, - "cPos": 0}}], + ["«external:file:///dottedIdentNotation.lean»", 26, 32, 0, "cMyNat.succ"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, "position": {"line": 33, "character": 31}} @@ -52,11 +36,7 @@ [{"label": "zero", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, - "position": {"line": 33, "character": 31}}, - "id": {"const": {"declName": "MyNat.zero"}}, - "cPos": 0}}], + ["«external:file:///dottedIdentNotation.lean»", 33, 31, 0, "cMyNat.zero"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, "position": {"line": 38, "character": 31}} @@ -67,11 +47,7 @@ [{"label": "zero", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, - "position": {"line": 51, "character": 24}}, - "id": {"const": {"declName": "MyNat.zero"}}, - "cPos": 0}}], + ["«external:file:///dottedIdentNotation.lean»", 51, 24, 0, "cMyNat.zero"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, "position": {"line": 64, "character": 32}} @@ -79,9 +55,5 @@ [{"label": "succ", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///dottedIdentNotation.lean"}, - "position": {"line": 64, "character": 32}}, - "id": {"const": {"declName": "MyNat.succ"}}, - "cPos": 0}}], + ["«external:file:///dottedIdentNotation.lean»", 64, 32, 0, "cMyNat.succ"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/editCompletion.lean.expected.out b/tests/lean/interactive/editCompletion.lean.expected.out index 18fc6eb42d..d0d60daa63 100644 --- a/tests/lean/interactive/editCompletion.lean.expected.out +++ b/tests/lean/interactive/editCompletion.lean.expected.out @@ -3,10 +3,5 @@ {"items": [{"label": "foo", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///editCompletion.lean"}, - "position": {"line": 3, "character": 22}}, - "id": {"const": {"declName": "Foo.foo"}}, - "cPos": 1}}], + "data": ["«external:file:///editCompletion.lean»", 3, 22, 1, "cFoo.foo"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/errorExplanationInteractive.lean.expected.out b/tests/lean/interactive/errorExplanationInteractive.lean.expected.out index 4974f8bb5d..829355edb3 100644 --- a/tests/lean/interactive/errorExplanationInteractive.lean.expected.out +++ b/tests/lean/interactive/errorExplanationInteractive.lean.expected.out @@ -1,24 +1,9 @@ {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, "position": {"line": 28, "character": 30}} {"items": - [{"textEdit": - {"replace": - {"start": {"line": 28, "character": 23}, - "end": {"line": 28, "character": 30}}, - "newText": "testPkg.bar", - "insert": - {"start": {"line": 28, "character": 23}, - "end": {"line": 28, "character": 30}}}, - "label": "testPkg.bar", + [{"label": "testPkg.foo2", "kind": 10, - "documentation": {"value": "(error) Error 0", "kind": "markdown"}, - "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 28, "character": 30}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 28, "character": 23}, "end": {"line": 28, "character": 30}}, @@ -26,16 +11,25 @@ "insert": {"start": {"line": 28, "character": 23}, "end": {"line": 28, "character": 30}}}, - "label": "testPkg.foo2", - "kind": 10, "documentation": {"value": "(error) Error 2", "kind": "markdown"}, "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 28, "character": 30}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///errorExplanationInteractive.lean»", 28, 30, 0]}, + {"label": "testPkg.bar", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 28, "character": 23}, + "end": {"line": 28, "character": 30}}, + "newText": "testPkg.bar", + "insert": + {"start": {"line": 28, "character": 23}, + "end": {"line": 28, "character": 30}}}, + "documentation": {"value": "(error) Error 0", "kind": "markdown"}, + "detail": "error name", + "data": ["«external:file:///errorExplanationInteractive.lean»", 28, 30, 0]}, + {"label": "testPkg.foo1", + "kind": 10, + "edit": {"replace": {"start": {"line": 28, "character": 23}, "end": {"line": 28, "character": 30}}, @@ -43,20 +37,29 @@ "insert": {"start": {"line": 28, "character": 23}, "end": {"line": 28, "character": 30}}}, - "label": "testPkg.foo1", - "kind": 10, "documentation": {"value": "(error) Error 1", "kind": "markdown"}, "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 28, "character": 30}}, - "cPos": 0}}], + "data": ["«external:file:///errorExplanationInteractive.lean»", 28, 30, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, "position": {"line": 30, "character": 31}} {"items": - [{"textEdit": + [{"label": "testPkg.foo2", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 30, "character": 23}, + "end": {"line": 30, "character": 31}}, + "newText": "testPkg.foo2", + "insert": + {"start": {"line": 30, "character": 23}, + "end": {"line": 30, "character": 31}}}, + "documentation": {"value": "(error) Error 2", "kind": "markdown"}, + "detail": "error name", + "data": ["«external:file:///errorExplanationInteractive.lean»", 30, 31, 0]}, + {"label": "testPkg.bar", + "kind": 10, + "edit": {"replace": {"start": {"line": 30, "character": 23}, "end": {"line": 30, "character": 31}}, @@ -64,33 +67,12 @@ "insert": {"start": {"line": 30, "character": 23}, "end": {"line": 30, "character": 31}}}, - "label": "testPkg.bar", - "kind": 10, "documentation": {"value": "(error) Error 0", "kind": "markdown"}, "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 30, "character": 31}}, - "cPos": 0}}, - {"textEdit": - {"replace": - {"start": {"line": 30, "character": 23}, - "end": {"line": 30, "character": 31}}, - "newText": "testPkg.foo2", - "insert": - {"start": {"line": 30, "character": 23}, - "end": {"line": 30, "character": 31}}}, - "label": "testPkg.foo2", + "data": ["«external:file:///errorExplanationInteractive.lean»", 30, 31, 0]}, + {"label": "testPkg.foo1", "kind": 10, - "documentation": {"value": "(error) Error 2", "kind": "markdown"}, - "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 30, "character": 31}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 30, "character": 23}, "end": {"line": 30, "character": 31}}, @@ -98,20 +80,16 @@ "insert": {"start": {"line": 30, "character": 23}, "end": {"line": 30, "character": 31}}}, - "label": "testPkg.foo1", - "kind": 10, "documentation": {"value": "(error) Error 1", "kind": "markdown"}, "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 30, "character": 31}}, - "cPos": 0}}], + "data": ["«external:file:///errorExplanationInteractive.lean»", 30, 31, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, "position": {"line": 32, "character": 32}} {"items": - [{"textEdit": + [{"label": "testPkg.foo2", + "kind": 10, + "edit": {"replace": {"start": {"line": 32, "character": 23}, "end": {"line": 32, "character": 32}}, @@ -119,16 +97,12 @@ "insert": {"start": {"line": 32, "character": 23}, "end": {"line": 32, "character": 32}}}, - "label": "testPkg.foo2", - "kind": 10, "documentation": {"value": "(error) Error 2", "kind": "markdown"}, "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 32, "character": 32}}, - "cPos": 0}}, - {"textEdit": + "data": ["«external:file:///errorExplanationInteractive.lean»", 32, 32, 0]}, + {"label": "testPkg.foo1", + "kind": 10, + "edit": {"replace": {"start": {"line": 32, "character": 23}, "end": {"line": 32, "character": 32}}, @@ -136,37 +110,16 @@ "insert": {"start": {"line": 32, "character": 23}, "end": {"line": 32, "character": 32}}}, - "label": "testPkg.foo1", - "kind": 10, "documentation": {"value": "(error) Error 1", "kind": "markdown"}, "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 32, "character": 32}}, - "cPos": 0}}], + "data": ["«external:file:///errorExplanationInteractive.lean»", 32, 32, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, "position": {"line": 34, "character": 32}} {"items": - [{"textEdit": - {"replace": - {"start": {"line": 34, "character": 23}, - "end": {"line": 34, "character": 32}}, - "newText": "testPkg.foo1", - "insert": - {"start": {"line": 34, "character": 23}, - "end": {"line": 34, "character": 32}}}, - "label": "testPkg.foo1", + [{"label": "testPkg.foo2", "kind": 10, - "documentation": {"value": "(error) Error 1", "kind": "markdown"}, - "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 34, "character": 32}}, - "cPos": 0}}, - {"textEdit": + "edit": {"replace": {"start": {"line": 34, "character": 23}, "end": {"line": 34, "character": 32}}, @@ -174,15 +127,22 @@ "insert": {"start": {"line": 34, "character": 23}, "end": {"line": 34, "character": 32}}}, - "label": "testPkg.foo2", - "kind": 10, "documentation": {"value": "(error) Error 2", "kind": "markdown"}, "detail": "error name", - "data": - {"params": - {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, - "position": {"line": 34, "character": 32}}, - "cPos": 0}}], + "data": ["«external:file:///errorExplanationInteractive.lean»", 34, 32, 0]}, + {"label": "testPkg.foo1", + "kind": 10, + "edit": + {"replace": + {"start": {"line": 34, "character": 23}, + "end": {"line": 34, "character": 32}}, + "newText": "testPkg.foo1", + "insert": + {"start": {"line": 34, "character": 23}, + "end": {"line": 34, "character": 32}}}, + "documentation": {"value": "(error) Error 1", "kind": "markdown"}, + "detail": "error name", + "data": ["«external:file:///errorExplanationInteractive.lean»", 34, 32, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///errorExplanationInteractive.lean"}, "position": {"line": 37, "character": 31}} diff --git a/tests/lean/interactive/inWordCompletion.lean.expected.out b/tests/lean/interactive/inWordCompletion.lean.expected.out index e59eb2a418..4009834c97 100644 --- a/tests/lean/interactive/inWordCompletion.lean.expected.out +++ b/tests/lean/interactive/inWordCompletion.lean.expected.out @@ -1,56 +1,29 @@ {"textDocument": {"uri": "file:///inWordCompletion.lean"}, "position": {"line": 6, "character": 11}} {"items": - [{"label": "gfxacc", + [{"label": "gfxadc", "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///inWordCompletion.lean"}, - "position": {"line": 6, "character": 11}}, - "id": {"const": {"declName": "gfxacc"}}, - "cPos": 0}}, + "data": ["«external:file:///inWordCompletion.lean»", 6, 11, 0, "cgfxadc"]}, + {"label": "gfxacc", + "kind": 3, + "data": ["«external:file:///inWordCompletion.lean»", 6, 11, 0, "cgfxacc"]}, {"label": "gfxabc", "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///inWordCompletion.lean"}, - "position": {"line": 6, "character": 11}}, - "id": {"const": {"declName": "gfxabc"}}, - "cPos": 0}}, - {"label": "gfxadc", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///inWordCompletion.lean"}, - "position": {"line": 6, "character": 11}}, - "id": {"const": {"declName": "gfxadc"}}, - "cPos": 0}}], + "data": ["«external:file:///inWordCompletion.lean»", 6, 11, 0, "cgfxabc"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///inWordCompletion.lean"}, "position": {"line": 14, "character": 15}} {"items": - [{"label": "gfxacc", + [{"label": "gfxabc", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///inWordCompletion.lean"}, - "position": {"line": 14, "character": 15}}, - "id": {"const": {"declName": "Boo.gfxacc"}}, - "cPos": 0}}, - {"label": "gfxabc", - "kind": 3, - "data": - {"params": - {"textDocument": {"uri": "file:///inWordCompletion.lean"}, - "position": {"line": 14, "character": 15}}, - "id": {"const": {"declName": "Boo.gfxabc"}}, - "cPos": 0}}, + ["«external:file:///inWordCompletion.lean»", 14, 15, 0, "cBoo.gfxabc"]}, {"label": "gfxadc", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///inWordCompletion.lean"}, - "position": {"line": 14, "character": 15}}, - "id": {"const": {"declName": "Boo.gfxadc"}}, - "cPos": 0}}], + ["«external:file:///inWordCompletion.lean»", 14, 15, 0, "cBoo.gfxadc"]}, + {"label": "gfxacc", + "kind": 3, + "data": + ["«external:file:///inWordCompletion.lean»", 14, 15, 0, "cBoo.gfxacc"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/internalNamesIssue.lean.expected.out b/tests/lean/interactive/internalNamesIssue.lean.expected.out index 4293049ee2..688ccd76a3 100644 --- a/tests/lean/interactive/internalNamesIssue.lean.expected.out +++ b/tests/lean/interactive/internalNamesIssue.lean.expected.out @@ -4,17 +4,9 @@ [{"label": "foo", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///internalNamesIssue.lean"}, - "position": {"line": 9, "character": 11}}, - "id": {"const": {"declName": "Foo.foo"}}, - "cPos": 0}}, + ["«external:file:///internalNamesIssue.lean»", 9, 11, 0, "cFoo.foo"]}, {"label": "bla", "kind": 3, "data": - {"params": - {"textDocument": {"uri": "file:///internalNamesIssue.lean"}, - "position": {"line": 9, "character": 11}}, - "id": {"const": {"declName": "Foo.bla"}}, - "cPos": 0}}], + ["«external:file:///internalNamesIssue.lean»", 9, 11, 0, "cFoo.bla"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/keywordCompletion.lean.expected.out b/tests/lean/interactive/keywordCompletion.lean.expected.out index 7d9b907e96..017c28e645 100644 --- a/tests/lean/interactive/keywordCompletion.lean.expected.out +++ b/tests/lean/interactive/keywordCompletion.lean.expected.out @@ -1,54 +1,29 @@ {"textDocument": {"uri": "file:///keywordCompletion.lean"}, "position": {"line": 4, "character": 10}} {"items": - [{"label": "binop_lazy%", - "kind": 14, - "detail": "keyword", - "data": - {"params": - {"textDocument": {"uri": "file:///keywordCompletion.lean"}, - "position": {"line": 4, "character": 10}}, - "cPos": 0}}, - {"label": "bin", + [{"label": "bin", "kind": 21, - "data": - {"params": - {"textDocument": {"uri": "file:///keywordCompletion.lean"}, - "position": {"line": 4, "character": 10}}, - "id": {"const": {"declName": "bin"}}, - "cPos": 0}}, - {"label": "binrel_no_prop%", + "data": ["«external:file:///keywordCompletion.lean»", 4, 10, 0, "cbin"]}, + {"label": "binop_lazy%", "kind": 14, "detail": "keyword", - "data": - {"params": - {"textDocument": {"uri": "file:///keywordCompletion.lean"}, - "position": {"line": 4, "character": 10}}, - "cPos": 0}}, - {"label": "binrel%", - "kind": 14, - "detail": "keyword", - "data": - {"params": - {"textDocument": {"uri": "file:///keywordCompletion.lean"}, - "position": {"line": 4, "character": 10}}, - "cPos": 0}}, - {"label": "binder_predicate", - "kind": 14, - "detail": "keyword", - "data": - {"params": - {"textDocument": {"uri": "file:///keywordCompletion.lean"}, - "position": {"line": 4, "character": 10}}, - "cPos": 0}}, + "data": ["«external:file:///keywordCompletion.lean»", 4, 10, 0]}, {"label": "binop%", "kind": 14, "detail": "keyword", - "data": - {"params": - {"textDocument": {"uri": "file:///keywordCompletion.lean"}, - "position": {"line": 4, "character": 10}}, - "cPos": 0}}], + "data": ["«external:file:///keywordCompletion.lean»", 4, 10, 0]}, + {"label": "binrel_no_prop%", + "kind": 14, + "detail": "keyword", + "data": ["«external:file:///keywordCompletion.lean»", 4, 10, 0]}, + {"label": "binrel%", + "kind": 14, + "detail": "keyword", + "data": ["«external:file:///keywordCompletion.lean»", 4, 10, 0]}, + {"label": "binder_predicate", + "kind": 14, + "detail": "keyword", + "data": ["«external:file:///keywordCompletion.lean»", 4, 10, 0]}], "isIncomplete": false} {"textDocument": {"uri": "file:///keywordCompletion.lean"}, "position": {"line": 4, "character": 13}} @@ -56,9 +31,5 @@ [{"label": "binop_lazy%", "kind": 14, "detail": "keyword", - "data": - {"params": - {"textDocument": {"uri": "file:///keywordCompletion.lean"}, - "position": {"line": 4, "character": 13}}, - "cPos": 0}}], + "data": ["«external:file:///keywordCompletion.lean»", 4, 13, 0]}], "isIncomplete": false} diff --git a/tests/lean/interactive/match.lean.expected.out b/tests/lean/interactive/match.lean.expected.out index e7e1df26cc..62ddd051a0 100644 --- a/tests/lean/interactive/match.lean.expected.out +++ b/tests/lean/interactive/match.lean.expected.out @@ -3,56 +3,26 @@ {"items": [{"label": "value", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///match.lean"}, - "position": {"line": 6, "character": 11}}, - "id": {"const": {"declName": "S.value"}}, - "cPos": 1}}, + "data": ["«external:file:///match.lean»", 6, 11, 1, "cS.value"]}, {"label": "fn1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///match.lean"}, - "position": {"line": 6, "character": 11}}, - "id": {"const": {"declName": "S.fn1"}}, - "cPos": 1}}, + "data": ["«external:file:///match.lean»", 6, 11, 1, "cS.fn1"]}, {"label": "name", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///match.lean"}, - "position": {"line": 6, "character": 11}}, - "id": {"const": {"declName": "S.name"}}, - "cPos": 1}}], + "data": ["«external:file:///match.lean»", 6, 11, 1, "cS.name"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///match.lean"}, "position": {"line": 10, "character": 10}} {"items": [{"label": "value", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///match.lean"}, - "position": {"line": 10, "character": 10}}, - "id": {"const": {"declName": "S.value"}}, - "cPos": 1}}, + "data": ["«external:file:///match.lean»", 10, 10, 1, "cS.value"]}, {"label": "fn1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///match.lean"}, - "position": {"line": 10, "character": 10}}, - "id": {"const": {"declName": "S.fn1"}}, - "cPos": 1}}, + "data": ["«external:file:///match.lean»", 10, 10, 1, "cS.fn1"]}, {"label": "name", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///match.lean"}, - "position": {"line": 10, "character": 10}}, - "id": {"const": {"declName": "S.name"}}, - "cPos": 1}}], + "data": ["«external:file:///match.lean»", 10, 10, 1, "cS.name"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///match.lean"}, "position": {"line": 14, "character": 2}} diff --git a/tests/lean/interactive/matchStxCompletion.lean.expected.out b/tests/lean/interactive/matchStxCompletion.lean.expected.out index 6c667b4820..c1753fb07c 100644 --- a/tests/lean/interactive/matchStxCompletion.lean.expected.out +++ b/tests/lean/interactive/matchStxCompletion.lean.expected.out @@ -1,28 +1,13 @@ {"textDocument": {"uri": "file:///matchStxCompletion.lean"}, "position": {"line": 8, "character": 9}} {"items": - [{"label": "f2", + [{"label": "f1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///matchStxCompletion.lean"}, - "position": {"line": 8, "character": 9}}, - "id": {"const": {"declName": "C.f2"}}, - "cPos": 1}}, + "data": ["«external:file:///matchStxCompletion.lean»", 8, 9, 1, "cC.f1"]}, {"label": "b1", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///matchStxCompletion.lean"}, - "position": {"line": 8, "character": 9}}, - "id": {"const": {"declName": "C.b1"}}, - "cPos": 1}}, - {"label": "f1", + "data": ["«external:file:///matchStxCompletion.lean»", 8, 9, 1, "cC.b1"]}, + {"label": "f2", "kind": 5, - "data": - {"params": - {"textDocument": {"uri": "file:///matchStxCompletion.lean"}, - "position": {"line": 8, "character": 9}}, - "id": {"const": {"declName": "C.f1"}}, - "cPos": 1}}], + "data": ["«external:file:///matchStxCompletion.lean»", 8, 9, 1, "cC.f2"]}], "isIncomplete": false} diff --git a/tests/lean/interactive/travellingCompletions.lean.expected.out b/tests/lean/interactive/travellingCompletions.lean.expected.out index 9e34b4b9de..f796f14a80 100644 --- a/tests/lean/interactive/travellingCompletions.lean.expected.out +++ b/tests/lean/interactive/travellingCompletions.lean.expected.out @@ -4,11 +4,11 @@ [{"label": "aaaaaaaa", "kind": 21, "data": - {"params": - {"textDocument": {"uri": "file:///travellingCompletions.lean"}, - "position": {"line": 7, "character": 37}}, - "id": {"const": {"declName": "Foo.aaaaaaaa"}}, - "cPos": 0}}], + ["«external:file:///travellingCompletions.lean»", + 7, + 37, + 0, + "cFoo.aaaaaaaa"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///travellingCompletions.lean"}, "position": {"line": 20, "character": 20}} @@ -16,11 +16,11 @@ [{"label": "foobar", "kind": 5, "data": - {"params": - {"textDocument": {"uri": "file:///travellingCompletions.lean"}, - "position": {"line": 20, "character": 20}}, - "id": {"const": {"declName": "Bar.foobar"}}, - "cPos": 2}}], + ["«external:file:///travellingCompletions.lean»", + 20, + 20, + 2, + "cBar.foobar"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///travellingCompletions.lean"}, "position": {"line": 24, "character": 16}} @@ -28,11 +28,11 @@ [{"label": "foobar", "kind": 5, "data": - {"params": - {"textDocument": {"uri": "file:///travellingCompletions.lean"}, - "position": {"line": 24, "character": 16}}, - "id": {"const": {"declName": "Bar.foobar"}}, - "cPos": 2}}], + ["«external:file:///travellingCompletions.lean»", + 24, + 16, + 2, + "cBar.foobar"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///travellingCompletions.lean"}, "position": {"line": 38, "character": 45}} @@ -40,19 +40,19 @@ [{"label": "continuousSMul", "kind": 23, "data": - {"params": - {"textDocument": {"uri": "file:///travellingCompletions.lean"}, - "position": {"line": 38, "character": 45}}, - "id": {"const": {"declName": "Prod.continuousSMul"}}, - "cPos": 1}}, + ["«external:file:///travellingCompletions.lean»", + 38, + 45, + 1, + "cProd.continuousSMul"]}, {"label": "continuousAdd", "kind": 23, "data": - {"params": - {"textDocument": {"uri": "file:///travellingCompletions.lean"}, - "position": {"line": 38, "character": 45}}, - "id": {"const": {"declName": "Prod.continuousAdd"}}, - "cPos": 1}}], + ["«external:file:///travellingCompletions.lean»", + 38, + 45, + 1, + "cProd.continuousAdd"]}], "isIncomplete": false} {"textDocument": {"uri": "file:///travellingCompletions.lean"}, "position": {"line": 42, "character": 25}} @@ -60,9 +60,9 @@ [{"label": "intro", "kind": 4, "data": - {"params": - {"textDocument": {"uri": "file:///travellingCompletions.lean"}, - "position": {"line": 42, "character": 25}}, - "id": {"const": {"declName": "True.intro"}}, - "cPos": 1}}], + ["«external:file:///travellingCompletions.lean»", + 42, + 25, + 1, + "cTrue.intro"]}], "isIncomplete": false}