feat: enable fuzzy matching for completion

This commit is contained in:
larsk21 2022-03-10 11:59:32 +01:00 committed by Leonardo de Moura
parent ff11325fce
commit 64dba41b4c
7 changed files with 455 additions and 61 deletions

View file

@ -5,6 +5,7 @@ Authors: Leonardo de Moura
-/
import Lean.Environment
import Lean.Parser.Term
import Lean.Data.FuzzyMatching
import Lean.Data.Lsp.LanguageFeatures
import Lean.Data.Lsp.Capabilities
import Lean.Data.Lsp.Utf16
@ -17,6 +18,7 @@ namespace Lean.Server.Completion
open Lsp
open Elab
open Meta
open FuzzyMatching
builtin_initialize completionBlackListExt : TagDeclarationExtension ← mkTagDeclarationExtension `blackListCompletion
@ -61,8 +63,9 @@ private def isTypeApplicable (type : Expr) (expectedType? : Option Expr) : MetaM
catch _ =>
return false
private def sortCompletionItems (items : Array CompletionItem) : Array CompletionItem :=
items.qsort fun i1 i2 => i1.label < i2.label
private def sortCompletionItems (items : Array (CompletionItem × Float)) : Array CompletionItem :=
-- TODO fix float eq comparison
items.qsort (fun (i1, s1) (i2, s2) => if s1 == s2 then i1.label < i2.label else s1 > s2) |>.map (·.1)
private def mkCompletionItem (label : Name) (type : Expr) (docString? : Option String) (kind : CompletionItemKind) : MetaM CompletionItem := do
let doc? := docString?.map fun docString => { value := docString, kind := MarkupKind.markdown : MarkupContent }
@ -70,18 +73,18 @@ private def mkCompletionItem (label : Name) (type : Expr) (docString? : Option S
return { label := label.getString!, detail? := detail, documentation? := doc?, kind? := kind }
structure State where
itemsMain : Array CompletionItem := #[]
itemsOther : Array CompletionItem := #[]
itemsMain : Array (CompletionItem × Float) := #[]
itemsOther : Array (CompletionItem × Float) := #[]
abbrev M := OptionT $ StateRefT State MetaM
private def addCompletionItem (label : Name) (type : Expr) (expectedType? : Option Expr) (declName? : Option Name) (kind : CompletionItemKind) : M Unit := do
private def addCompletionItem (label : Name) (type : Expr) (expectedType? : Option Expr) (declName? : Option Name) (kind : CompletionItemKind) (score : Float) : M Unit := do
let docString? ← if let some declName := declName? then findDocString? (← getEnv) declName else pure none
let item ← mkCompletionItem label type docString? kind
if (← isTypeApplicable type expectedType?) then
modify fun s => { s with itemsMain := s.itemsMain.push item }
modify fun s => { s with itemsMain := s.itemsMain.push (item, score) }
else
modify fun s => { s with itemsOther := s.itemsOther.push item }
modify fun s => { s with itemsOther := s.itemsOther.push (item, score) }
private def getCompletionKindForDecl (constInfo : ConstantInfo) : M CompletionItemKind := do
let env ← getEnv
@ -101,17 +104,17 @@ private def getCompletionKindForDecl (constInfo : ConstantInfo) : M CompletionIt
else
return CompletionItemKind.constant
private def addCompletionItemForDecl (label : Name) (declName : Name) (expectedType? : Option Expr) : M Unit := do
private def addCompletionItemForDecl (label : Name) (declName : Name) (expectedType? : Option Expr) (score : Float) : M Unit := do
if let some c := (← getEnv).find? declName then
addCompletionItem label c.type expectedType? (some declName) (← getCompletionKindForDecl c)
addCompletionItem label c.type expectedType? (some declName) (← getCompletionKindForDecl c) score
private def addKeywordCompletionItem (keyword : String) : M Unit := do
let item := { label := keyword, detail? := "keyword", documentation? := none, kind? := CompletionItemKind.keyword }
modify fun s => { s with itemsMain := s.itemsMain.push item }
modify fun s => { s with itemsMain := s.itemsMain.push (item, 1) }
private def addNamespaceCompletionItem (ns : Name) : M Unit := do
private def addNamespaceCompletionItem (ns : Name) (score : Float) : M Unit := do
let item := { label := ns.toString, detail? := "namespace", documentation? := none, kind? := CompletionItemKind.module }
modify fun s => { s with itemsMain := s.itemsMain.push item }
modify fun s => { s with itemsMain := s.itemsMain.push (item, score) }
private def runM (ctx : ContextInfo) (lctx : LocalContext) (x : M Unit) : IO (Option CompletionList) :=
ctx.runMetaM lctx do
@ -120,10 +123,10 @@ private def runM (ctx : ContextInfo) (lctx : LocalContext) (x : M Unit) : IO (Op
| (some _, s) =>
return some { items := sortCompletionItems s.itemsMain ++ sortCompletionItems s.itemsOther, isIncomplete := true }
private def matchAtomic (id : Name) (declName : Name) : Bool :=
private def matchAtomic (id : Name) (declName : Name) : Option Float :=
match id, declName with
| Name.str Name.anonymous s₁ _, Name.str Name.anonymous s₂ _ => s₁.isPrefixOf s₂
| _, _ => false
| Name.str Name.anonymous s₁ _, Name.str Name.anonymous s₂ _ => fuzzyMatchScoreWithThreshold? s₁ s₂
| _, _ => none
private def normPrivateName (declName : Name) : MetaM Name := do
match privateToUserName? declName with
@ -140,7 +143,7 @@ private def normPrivateName (declName : Name) : MetaM Name := do
Remark: `danglingDot == true` when the completion point is an identifier followed by `.`.
-/
private def matchDecl? (ns : Name) (id : Name) (danglingDot : Bool) (declName : Name) : MetaM (Option Name) := do
private def matchDecl? (ns : Name) (id : Name) (danglingDot : Bool) (declName : Name) : MetaM (Option (Name × Float)) := do
-- dbg_trace "{ns}, {id}, {declName}, {danglingDot}"
let declName ← normPrivateName declName
if !ns.isPrefixOf declName then
@ -150,14 +153,14 @@ private def matchDecl? (ns : Name) (id : Name) (danglingDot : Bool) (declName :
if id.isPrefixOf declName && danglingDot then
let declName := declName.replacePrefix id Name.anonymous
if declName.isAtomic && !declName.isAnonymous then
return some declName
return some (declName, 1)
else
return none
else if !danglingDot then
match id, declName with
| Name.str p₁ s₁ _, Name.str p₂ s₂ _ =>
if p₁ == p₂ && s₁.isPrefixOf s₂ then
return some s₂
if p₁ == p₂ then
return fuzzyMatchScoreWithThreshold? s₁ s₂ |>.map (s₂, ·)
else
return none
| _, _ => return none
@ -190,34 +193,38 @@ inductive HoverInfo where
| after
| inside (delta : Nat)
def matchNamespace (ns : Name) (nsFragment : Name) (danglingDot : Bool) : Bool :=
def matchNamespace (ns : Name) (nsFragment : Name) (danglingDot : Bool) : Option Float :=
if danglingDot then
nsFragment != ns && nsFragment.isPrefixOf ns
if nsFragment != ns && nsFragment.isPrefixOf ns then
some 1
else
none
else
match ns, nsFragment with
| Name.str p₁ s₁ _, Name.str p₂ s₂ _ => p₁ == p₂ && s₂.isPrefixOf s₁
| _, _ => false
| Name.str p₁ s₁ _, Name.str p₂ s₂ _ =>
if p₁ == p₂ then fuzzyMatchScoreWithThreshold? s₂ s₁ else none
| _, _ => none
def completeNamespaces (ctx : ContextInfo) (id : Name) (danglingDot : Bool) : M Unit := do
let env ← getEnv
let add (ns : Name) (ns' : Name) : M Unit :=
let add (ns : Name) (ns' : Name) (score : Float) : M Unit :=
if danglingDot then
addNamespaceCompletionItem (ns.replacePrefix (ns' ++ id) Name.anonymous)
addNamespaceCompletionItem (ns.replacePrefix (ns' ++ id) Name.anonymous) score
else
addNamespaceCompletionItem (ns.replacePrefix ns' Name.anonymous)
addNamespaceCompletionItem (ns.replacePrefix ns' Name.anonymous) score
env.getNamespaceSet |>.forM fun ns => do
unless ns.isInternal || env.contains ns do -- Ignore internal and namespaces that are also declaration names
for openDecl in ctx.openDecls do
match openDecl with
| OpenDecl.simple ns' except =>
if matchNamespace ns (ns' ++ id) danglingDot then
add ns ns'
if let some score := matchNamespace ns (ns' ++ id) danglingDot then
add ns ns' score
return ()
| _ => pure ()
-- use current namespace
let rec visitNamespaces (ns' : Name) : M Unit := do
if matchNamespace ns (ns' ++ id) danglingDot then
add ns ns'
if let some score := matchNamespace ns (ns' ++ id) danglingDot then
add ns ns' score
else
match ns' with
| Name.str p .. => visitNamespaces p
@ -234,16 +241,16 @@ private def idCompletionCore (ctx : ContextInfo) (id : Name) (hoverInfo : HoverI
if id.isAtomic then
-- search for matches in the local context
for localDecl in (← getLCtx) do
if matchAtomic id localDecl.userName then
addCompletionItem localDecl.userName localDecl.type expectedType? none (kind := CompletionItemKind.variable)
if let some score := matchAtomic id localDecl.userName then
addCompletionItem localDecl.userName localDecl.type expectedType? none (kind := CompletionItemKind.variable) score
-- search for matches in the environment
let env ← getEnv
env.constants.forM fun declName c => do
unless (← isBlackListed declName) do
let matchUsingNamespace (ns : Name): M Bool := do
if let some label ← matchDecl? ns id danglingDot declName then
if let some (label, score) ← matchDecl? ns id danglingDot declName then
-- dbg_trace "matched with {id}, {declName}, {label}"
addCompletionItem label c.type expectedType? declName (← getCompletionKindForDecl c)
addCompletionItem label c.type expectedType? declName (← getCompletionKindForDecl c) score
return true
else
return false
@ -265,30 +272,33 @@ private def idCompletionCore (ctx : ContextInfo) (id : Name) (hoverInfo : HoverI
return ()
| _ => pure ()
-- Recall that aliases may not be atomic and include the namespace where they were created.
let matchAlias (ns : Name) (alias : Name) : Bool :=
ns.isPrefixOf alias && matchAtomic id (alias.replacePrefix ns Name.anonymous)
let matchAlias (ns : Name) (alias : Name) : Option Float :=
if ns.isPrefixOf alias then
matchAtomic id (alias.replacePrefix ns Name.anonymous)
else
none
-- Auxiliary function for `alias`
let addAlias (alias : Name) (declNames : List Name) : M Unit := do
let addAlias (alias : Name) (declNames : List Name) (score : Float) : M Unit := do
declNames.forM fun declName => do
unless (← isBlackListed declName) do
addCompletionItemForDecl alias declName expectedType?
addCompletionItemForDecl alias declName expectedType? score
-- search explicitily open `ids`
for openDecl in ctx.openDecls do
match openDecl with
| OpenDecl.explicit openedId resolvedId =>
unless (← isBlackListed resolvedId) do
if matchAtomic id openedId then
addCompletionItemForDecl openedId resolvedId expectedType?
if let some score := matchAtomic id openedId then
addCompletionItemForDecl openedId resolvedId expectedType? score
| OpenDecl.simple ns except =>
getAliasState env |>.forM fun alias declNames => do
if matchAlias ns alias then
addAlias alias declNames
if let some score := matchAlias ns alias then
addAlias alias declNames score
-- search for aliases
getAliasState env |>.forM fun alias declNames => do
-- use current namespace
let rec searchAlias (ns : Name) : M Unit := do
if matchAlias ns alias then
addAlias alias declNames
if let some score := matchAlias ns alias then
addAlias alias declNames score
else
match ns with
| Name.str p .. => searchAlias p
@ -356,7 +366,7 @@ private def dotCompletion (ctx : ContextInfo) (info : TermInfo) (hoverInfo : Hov
if nameSet.contains typeName then
unless (← isBlackListed c.name) do
if (← isDotCompletionMethod typeName c) then
addCompletionItem c.name.getString! c.type expectedType? c.name (kind := (← getCompletionKindForDecl c))
addCompletionItem c.name.getString! c.type expectedType? c.name (kind := (← getCompletionKindForDecl c)) 1
private def optionCompletion (ctx : ContextInfo) (stx : Syntax) (caps : ClientCapabilities) : IO (Option CompletionList) :=
ctx.runMetaM {} do
@ -375,7 +385,7 @@ private def optionCompletion (ctx : ContextInfo) (stx : Syntax) (caps : ClientCa
let opts ← getOptions
let mut items := #[]
for ⟨name, decl⟩ in decls do
if partialName.isPrefixOf name.toString then
if let some score := fuzzyMatchScoreWithThreshold? partialName name.toString then
let textEdit :=
if !caps.textDocument?.any (·.completion?.any (·.completionItem?.any (·.insertReplaceSupport?.any (·)))) then
none -- InsertReplaceEdit not supported by client
@ -386,20 +396,20 @@ private def optionCompletion (ctx : ContextInfo) (stx : Syntax) (caps : ClientCa
else
none
items := items.push
{ label := name.toString
detail? := s!"({opts.get name decl.defValue}), {decl.descr}"
documentation? := none,
kind? := CompletionItemKind.property -- TODO: investigate whether this is the best kind for options.
textEdit? := textEdit }
({ label := name.toString
detail? := s!"({opts.get name decl.defValue}), {decl.descr}"
documentation? := none,
kind? := CompletionItemKind.property -- TODO: investigate whether this is the best kind for options.
textEdit? := textEdit }, score)
return some { items := sortCompletionItems items, isIncomplete := true }
private def tacticCompletion (ctx : ContextInfo) : IO (Option CompletionList) :=
-- Just return the list of tactics for now.
ctx.runMetaM {} do
let table := Parser.getCategory (Parser.parserExtension.getState (← getEnv)).categories `tactic |>.get!.tables.leadingTable
let items : Array CompletionItem := table.fold (init := #[]) fun items tk parser =>
let items : Array (CompletionItem × Float) := table.fold (init := #[]) fun items tk parser =>
-- TODO pretty print tactic syntax
items.push { label := tk.toString, detail? := none, documentation? := none, kind? := CompletionItemKind.keyword }
items.push ({ label := tk.toString, detail? := none, documentation? := none, kind? := CompletionItemKind.keyword }, 1)
return some { items := sortCompletionItems items, isIncomplete := true }
partial def find? (fileMap : FileMap) (hoverPos : String.Pos) (infoTree : InfoTree) (caps : ClientCapabilities) : IO (Option CompletionList) := do

View file

@ -23,5 +23,95 @@
{"label": "Function", "kind": 9, "detail": "namespace"},
{"label": "Functor",
"kind": 7,
"detail": "(Type u → Type v) → Type (max (u + 1) v)"}],
"detail": "(Type u → Type v) → Type (max (u + 1) v)"},
{"label": "fix",
"kind": 3,
"detail": "[inst : Inhabited β] → ((α → β) → α → β) → α → β"},
{"label": "fix1",
"kind": 3,
"detail": "[inst : Inhabited β] → ((α → β) → α → β) → α → β"},
{"label": "fix2",
"kind": 3,
"detail":
"[inst : Inhabited β] → ((α₁ → α₂ → β) → α₁ → α₂ → β) → α₁ → α₂ → β"},
{"label": "fix3",
"kind": 3,
"detail":
"[inst : Inhabited β] → ((α₁ → α₂ → α₃ → β) → α₁ → α₂ → α₃ → β) → α₁ → α₂ → α₃ → β"},
{"label": "fix4",
"kind": 3,
"detail":
"[inst : Inhabited β] → ((α₁ → α₂ → α₃ → α₄ → β) → α₁ → α₂ → α₃ → α₄ → β) → α₁ → α₂ → α₃ → α₄ → β"},
{"label": "fix5",
"kind": 3,
"detail":
"[inst : Inhabited β] → ((α₁ → α₂ → α₃ → α₄ → α₅ → β) → α₁ → α₂ → α₃ → α₄ → α₅ → β) → α₁ → α₂ → α₃ → α₄ → α₅ → β"},
{"label": "fix6",
"kind": 3,
"detail":
"[inst : Inhabited β] →\n ((α₁ → α₂ → α₃ → α₄ → α₅ → α₆ → β) → α₁ → α₂ → α₃ → α₄ → α₅ → α₆ → β) → α₁ → α₂ → α₃ → α₄ → α₅ → α₆ → β"},
{"label": "fixCore",
"kind": 3,
"detail": "(α → β) → ((α → β) → α → β) → α → β"},
{"label": "fixCore1",
"kind": 3,
"detail": "(α → β) → ((α → β) → α → β) → α → β"},
{"label": "fixCore2",
"kind": 3,
"detail": "(α₁ → α₂ → β) → ((α₁ → α₂ → β) → α₁ → α₂ → β) → α₁ → α₂ → β"},
{"label": "fixCore3",
"kind": 3,
"detail":
"(α₁ → α₂ → α₃ → β) → ((α₁ → α₂ → α₃ → β) → α₁ → α₂ → α₃ → β) → α₁ → α₂ → α₃ → β"},
{"label": "fixCore4",
"kind": 3,
"detail":
"(α₁ → α₂ → α₃ → α₄ → β) → ((α₁ → α₂ → α₃ → α₄ → β) → α₁ → α₂ → α₃ → α₄ → β) → α₁ → α₂ → α₃ → α₄ → β"},
{"label": "fixCore5",
"kind": 3,
"detail":
"(α₁ → α₂ → α₃ → α₄ → α₅ → β) → ((α₁ → α₂ → α₃ → α₄ → α₅ → β) → α₁ → α₂ → α₃ → α₄ → α₅ → β) → α₁ → α₂ → α₃ → α₄ → α₅ → β"},
{"label": "fixCore6",
"kind": 3,
"detail":
"(α₁ → α₂ → α₃ → α₄ → α₅ → α₆ → β) →\n ((α₁ → α₂ → α₃ → α₄ → α₅ → α₆ → β) → α₁ → α₂ → α₃ → α₄ → α₅ → α₆ → β) → α₁ → α₂ → α₃ → α₄ → α₅ → α₆ → β"},
{"label": "failure",
"kind": 5,
"detail": "[self : Alternative f] → {α : Type u} → f α"},
{"label": "false", "kind": 4, "detail": "Bool"},
{"label": "false_and",
"kind": 3,
"detail": "∀ (p : Prop), (False ∧ p) = False"},
{"label": "false_iff", "kind": 3, "detail": "∀ (p : Prop), (False ↔ p) = ¬p"},
{"label": "false_implies",
"kind": 3,
"detail": "∀ (p : Prop), (False → p) = True"},
{"label": "false_of_ne", "kind": 3, "detail": "a ≠ a → False"},
{"label": "false_or", "kind": 3, "detail": "∀ (p : Prop), (False p) = p"},
{"label": "flip", "kind": 3, "detail": "(α → β → φ) → β → α → φ"},
{"label": "floatDecLe",
"kind": 3,
"detail": "(a b : Float) → Decidable (a ≤ b)"},
{"label": "floatDecLt",
"kind": 3,
"detail": "(a b : Float) → Decidable (a < b)"},
{"label": "floatSpec", "kind": 21, "detail": "FloatSpec"},
{"label": "forIn",
"kind": 5,
"detail":
"[self : ForIn m ρ α] → {β : Type u₁} → [inst : Monad m] → ρ → β → (α → β → m (ForInStep β)) → m β"},
{"label": "forIn'",
"kind": 5,
"detail":
"[self : ForIn' m ρ α d] → {β : Type u₁} → [inst : Monad m] → (x : ρ) → β → ((a : α) → a ∈ x → β → m (ForInStep β)) → m β"},
{"label": "forM",
"kind": 5,
"detail":
"[self : ForM m γ α] → [inst : Monad m] → γ → (α → m PUnit) → m PUnit"},
{"label": "forall_congr",
"kind": 3,
"detail": "(∀ (a : α), p a = q a) → (∀ (a : α), p a) = ∀ (a : α), q a"},
{"label": "funext",
"kind": 3,
"detail": "(∀ (x : α), f₁ x = f₂ x) → f₁ = f₂"}],
"isIncomplete": true}

View file

@ -21,7 +21,11 @@
"detail": "Environment → Name → Option Name"},
{"label": "getRevAliases",
"kind": 3,
"detail": "Environment → Name → List Name"}],
"detail": "Environment → Name → List Name"},
{"label": "getConstInfoRec",
"kind": 3,
"detail":
"[inst : Monad m] → [inst : MonadEnv m] → [inst : MonadError m] → Name → m RecursorVal"}],
"isIncomplete": true}
{"textDocument": {"uri": "file://863.lean"},
"position": {"line": 7, "character": 12}}
@ -46,5 +50,9 @@
"detail": "Environment → Name → Option Name"},
{"label": "getRevAliases",
"kind": 3,
"detail": "Environment → Name → List Name"}],
"detail": "Environment → Name → List Name"},
{"label": "getConstInfoRec",
"kind": 3,
"detail":
"[inst : Monad m] → [inst : MonadEnv m] → [inst : MonadError m] → Name → m RecursorVal"}],
"isIncomplete": true}

View file

@ -3,7 +3,51 @@
{"items":
[{"label": "And", "kind": 22, "detail": "Prop → Prop → Prop"},
{"label": "AndOp", "kind": 7, "detail": "Type u → Type u"},
{"label": "AndThen", "kind": 7, "detail": "Type u → Type u"}],
{"label": "AndThen", "kind": 7, "detail": "Type u → Type u"},
{"label": "and", "kind": 3, "detail": "Bool → Bool → Bool"},
{"label": "andM",
"kind": 3,
"detail": "[inst : Monad m] → [inst : ToBool β] → m β → m β → m β"},
{"label": "and_false",
"kind": 3,
"detail": "∀ (p : Prop), (p ∧ False) = False"},
{"label": "and_self", "kind": 3, "detail": "∀ (p : Prop), (p ∧ p) = p"},
{"label": "and_true", "kind": 3, "detail": "∀ (p : Prop), (p ∧ True) = p"},
{"label": "Append", "kind": 7, "detail": "Type u → Type u"},
{"label": "HAnd",
"kind": 7,
"detail": "Type u → Type v → outParam (Type w) → Type (max (max u v) w)"},
{"label": "HAndThen",
"kind": 7,
"detail": "Type u → Type v → outParam (Type w) → Type (max (max u v) w)"},
{"label": "false_and",
"kind": 3,
"detail": "∀ (p : Prop), (False ∧ p) = False"},
{"label": "instAndOpUInt16", "kind": 21, "detail": "AndOp UInt16"},
{"label": "instAndOpUInt32", "kind": 21, "detail": "AndOp UInt32"},
{"label": "instAndOpUInt64", "kind": 21, "detail": "AndOp UInt64"},
{"label": "instAndOpUInt8", "kind": 21, "detail": "AndOp UInt8"},
{"label": "instAndOpUSize", "kind": 21, "detail": "AndOp USize"},
{"label": "strictAnd", "kind": 3, "detail": "Bool → Bool → Bool"},
{"label": "true_and", "kind": 3, "detail": "∀ (p : Prop), (True ∧ p) = p"},
{"label": "instDecidableAnd",
"kind": 3,
"detail": "[dp : Decidable p] → [dq : Decidable q] → Decidable (p ∧ q)"},
{"label": "instHAnd", "kind": 3, "detail": "[inst : AndOp α] → HAnd α α α"},
{"label": "instHAndThen",
"kind": 3,
"detail": "[inst : AndThen α] → HAndThen α α α"},
{"label": "compareOfLessAndEq",
"kind": 3,
"detail":
"(x y : α) → [inst : LT α] → [inst : Decidable (x < y)] → [inst : DecidableEq α] → Ordering"},
{"label": "iff_iff_implies_and_implies",
"kind": 3,
"detail": "∀ (a b : Prop), (a ↔ b) ↔ (a → b) ∧ (b → a)"},
{"label": "HAppend",
"kind": 7,
"detail": "Type u → Type v → outParam (Type w) → Type (max (max u v) w)"},
{"label": "instAppendSubarray", "kind": 3, "detail": "Append (Subarray α)"}],
"isIncomplete": true}
{"textDocument": {"uri": "file://completion7.lean"},
"position": {"line": 2, "character": 11}}

View file

@ -70,7 +70,19 @@
"end": {"line": 4, "character": 17}}},
"label": "format.width",
"kind": 10,
"detail": "(120), indentation"}],
"detail": "(120), indentation"},
{"textEdit":
{"replace":
{"start": {"line": 4, "character": 11},
"end": {"line": 4, "character": 17}},
"newText": "trace.PrettyPrinter.format",
"insert":
{"start": {"line": 4, "character": 11},
"end": {"line": 4, "character": 17}}},
"label": "trace.PrettyPrinter.format",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"}],
"isIncomplete": true}
{"textDocument": {"uri": "file://completionOption.lean"},
"position": {"line": 7, "character": 20}}
@ -91,6 +103,54 @@
"position": {"line": 10, "character": 18}}
{"items":
[{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.PrettyPrinter",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.PrettyPrinter",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.PrettyPrinter.delab",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.PrettyPrinter.delab",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.PrettyPrinter.format",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.PrettyPrinter.format",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.PrettyPrinter.parenthesize",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.PrettyPrinter.parenthesize",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
@ -137,6 +197,90 @@
"label": "trace.pp.analyze.tryUnify",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.Elab.postpone",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.Elab.postpone",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.Meta.IndPredBelow",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.Meta.IndPredBelow",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.Meta.IndPredBelow.match",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.Meta.IndPredBelow.match",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.Meta.synthPending",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.Meta.synthPending",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.compiler.ir.push_proj",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.compiler.ir.push_proj",
"kind": 10,
"detail":
"(false), (trace) enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.compiler.lambda_pure",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.compiler.lambda_pure",
"kind": 10,
"detail":
"(false), (trace) enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}},
"newText": "trace.Meta.isLevelDefEq.postponed",
"insert":
{"start": {"line": 10, "character": 11},
"end": {"line": 10, "character": 18}}},
"label": "trace.Meta.isLevelDefEq.postponed",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"}],
"isIncomplete": true}
{"textDocument": {"uri": "file://completionOption.lean"},
@ -189,6 +333,90 @@
"label": "trace.pp.analyze.tryUnify",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}},
"newText": "trace.PrettyPrinter",
"insert":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}}},
"label": "trace.PrettyPrinter",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}},
"newText": "trace.PrettyPrinter.delab",
"insert":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}}},
"label": "trace.PrettyPrinter.delab",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}},
"newText": "trace.PrettyPrinter.format",
"insert":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}}},
"label": "trace.PrettyPrinter.format",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}},
"newText": "trace.PrettyPrinter.parenthesize",
"insert":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}}},
"label": "trace.PrettyPrinter.parenthesize",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}},
"newText": "trace.compiler.ir.push_proj",
"insert":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}}},
"label": "trace.compiler.ir.push_proj",
"kind": 10,
"detail":
"(false), (trace) enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}},
"newText": "trace.Elab.postpone",
"insert":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}}},
"label": "trace.Elab.postpone",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"},
{"textEdit":
{"replace":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}},
"newText": "trace.Meta.isLevelDefEq.postponed",
"insert":
{"start": {"line": 13, "character": 11},
"end": {"line": 13, "character": 19}}},
"label": "trace.Meta.isLevelDefEq.postponed",
"kind": 10,
"detail":
"(false), enable/disable tracing for the given module and submodules"}],
"isIncomplete": true}
{"textDocument": {"uri": "file://completionOption.lean"},

View file

@ -4,7 +4,12 @@
"isIncomplete": true}
{"textDocument": {"uri": "file://completionPrv.lean"},
"position": {"line": 9, "character": 11}}
{"items": [{"label": "booBoo", "kind": 21, "detail": "Nat"}],
{"items":
[{"label": "booBoo", "kind": 21, "detail": "Nat"},
{"label": "instToBoolBool", "kind": 21, "detail": "ToBool Bool"},
{"label": "instLawfulBEqBoolInstBEqInstDecidableEqBool",
"kind": 21,
"detail": "LawfulBEq Bool"}],
"isIncomplete": true}
{"textDocument": {"uri": "file://completionPrv.lean"},
"position": {"line": 21, "character": 5}}

View file

@ -1,10 +1,19 @@
{"textDocument": {"uri": "file://keywordCompletion.lean"},
"position": {"line": 4, "character": 16}}
{"items": [{"label": "register_string", "kind": 14, "detail": "keyword"}],
{"items":
[{"label": "register_string", "kind": 14, "detail": "keyword"},
{"label": "termRegister_string_", "kind": 21, "detail": "Lean.ParserDescr"}],
"isIncomplete": true}
{"textDocument": {"uri": "file://keywordCompletion.lean"},
"position": {"line": 7, "character": 10}}
{"items":
[{"label": "register_string", "kind": 14, "detail": "keyword"},
{"label": "regular", "kind": 21, "detail": "Nat"}],
{"label": "regular", "kind": 21, "detail": "Nat"},
{"label": "recSubsingleton",
"kind": 3,
"detail":
"∀ [h : Decidable p] {h₁ : p → Sort u} {h₂ : ¬p → Sort u} [h₃ : ∀ (h : p), Subsingleton (h₁ h)]\n [h₄ : ∀ (h : ¬p), Subsingleton (h₂ h)], Subsingleton (Decidable.casesOn h h₂ h₁)"},
{"label": "reprArg", "kind": 3, "detail": "[inst : Repr α] → α → Std.Format"},
{"label": "termRegister_string_", "kind": 21, "detail": "Lean.ParserDescr"},
{"label": "instReprStdGen", "kind": 21, "detail": "Repr StdGen"}],
"isIncomplete": true}