-
Notifications
You must be signed in to change notification settings - Fork 437
/
DeclarationRange.lean
79 lines (72 loc) · 2.88 KB
/
DeclarationRange.lean
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
/-
Copyright (c) 2021 Microsoft Corporation. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Leonardo de Moura
-/
prelude
import Lean.Log
import Lean.Parser.Command
import Lean.DeclarationRange
import Lean.Data.Lsp.Utf16
namespace Lean.Elab
def getDeclarationRange? [Monad m] [MonadFileMap m] (stx : Syntax) : m (Option DeclarationRange) := do
let some range := stx.getRange?
| return none
let fileMap ← getFileMap
--let range := fileMap.utf8RangeToLspRange
let pos := fileMap.toPosition range.start
let endPos := fileMap.toPosition range.stop
return some {
pos := pos
charUtf16 := fileMap.leanPosToLspPos pos |>.character
endPos := endPos
endCharUtf16 := fileMap.leanPosToLspPos endPos |>.character
}
/--
For most builtin declarations, the selection range is just its name, which is stored in the second position.
Example:
```
"def " >> declId >> optDeclSig >> declVal
```
If the declaration name is absent, we use the keyword instead.
This function converts the given `Syntax` into one that represents its "selection range".
-/
def getDeclarationSelectionRef (stx : Syntax) : Syntax :=
if stx.isOfKind ``Lean.Parser.Command.instance then
-- must skip `attrKind` and `optPrio` for `instance`
if !stx[3].isNone then
stx[3][0]
else
stx[1]
else
if stx[1][0].isIdent then
stx[1][0] -- `declId`
else if stx[1].isIdent then
stx[1] -- raw `ident`
else
stx[0]
/--
Derives and adds declaration ranges from given syntax trees. If `rangeStx` does not have a range,
nothing is added. If `selectionRangeStx` does not have a range, it is defaulted to that of
`rangeStx`.
-/
def addDeclarationRangesFromSyntax [Monad m] [MonadEnv m] [MonadFileMap m] (declName : Name)
(rangeStx : Syntax) (selectionRangeStx : Syntax := .missing) : m Unit := do
-- may fail on partial syntax, ignore in that case
let some range ← getDeclarationRange? rangeStx | return
let selectionRange ← (·.getD range) <$> getDeclarationRange? selectionRangeStx
Lean.addDeclarationRanges declName { range, selectionRange }
/--
Stores the `range` and `selectionRange` for `declName` where `modsStx` is the modifier part and
`cmdStx` the remaining part of the syntax tree for `declName`.
This method is for the builtin declarations only. User-defined commands should use
`Lean.Elab.addDeclarationRangesFromSyntax` or `Lean.addDeclarationRanges` to store this information
for their commands.
-/
def addDeclarationRangesForBuiltin [Monad m] [MonadEnv m] [MonadFileMap m] (declName : Name)
(modsStx : TSyntax ``Parser.Command.declModifiers) (declStx : Syntax) : m Unit := do
if declStx.getKind == ``Parser.Command.«example» then
return ()
let stx := mkNullNode #[modsStx, declStx]
addDeclarationRangesFromSyntax declName stx (getDeclarationSelectionRef declStx)
end Lean.Elab