1
- {-# LANGUAGE OverloadedStrings #-}
2
- {-# LANGUAGE RecordWildCards #-}
1
+ {-# LANGUAGE OverloadedStrings #-}
2
+ {-# LANGUAGE RecordWildCards #-}
3
3
{-# LANGUAGE ScopedTypeVariables #-}
4
4
5
- module Ide.Plugin.CodeRange (
6
- descriptor
7
- , Log
5
+ module Ide.Plugin.CodeRange
6
+ ( descriptor ,
7
+ Log ,
8
8
9
9
-- * Internal
10
- , findPosition
11
- ) where
10
+ findPosition ,
11
+ )
12
+ where
12
13
13
14
import Control.Monad.Except (ExceptT (ExceptT ),
14
15
runExceptT )
15
16
import Control.Monad.IO.Class (liftIO )
16
17
import Control.Monad.Trans.Maybe (MaybeT (MaybeT ),
17
18
maybeToExceptT )
18
19
import Data.Either.Extra (maybeToEither )
19
- import Data.Maybe ( fromMaybe , catMaybes )
20
+ import Data.Maybe ( fromMaybe )
20
21
import Data.Vector (Vector )
21
22
import qualified Data.Vector as V
22
23
import Development.IDE (IdeAction ,
@@ -43,62 +44,67 @@ import Ide.Types (PluginDescriptor (pluginH
43
44
defaultPluginDescriptor ,
44
45
mkPluginHandler )
45
46
import Language.LSP.Server (LspM )
46
- import Language.LSP.Types (List (List ),
47
+ import Language.LSP.Types (FoldingRange (.. ),
48
+ FoldingRangeParams (.. ),
49
+ List (List ),
47
50
NormalizedFilePath ,
48
51
Position (.. ),
49
52
Range (_start ),
50
53
ResponseError ,
51
- SMethod (STextDocumentSelectionRange , STextDocumentFoldingRange ),
54
+ SMethod (STextDocumentFoldingRange , STextDocumentSelectionRange ),
52
55
SelectionRange (.. ),
53
56
SelectionRangeParams (.. ),
54
- FoldingRange (.. ),
55
- FoldingRangeParams (.. ),
56
57
TextDocumentIdentifier (TextDocumentIdentifier ),
57
- Uri
58
- )
58
+ Uri )
59
59
import Prelude hiding (log , span )
60
60
61
61
descriptor :: Recorder (WithPriority Log ) -> PluginId -> PluginDescriptor IdeState
62
- descriptor recorder plId = (defaultPluginDescriptor plId)
63
- { pluginHandlers = mkPluginHandler STextDocumentSelectionRange selectionRangeHandler
64
- <> mkPluginHandler STextDocumentFoldingRange foldingRangeHandler
65
- , pluginRules = codeRangeRule (cmapWithPrio LogRules recorder)
62
+ descriptor recorder plId =
63
+ (defaultPluginDescriptor plId)
64
+ { pluginHandlers =
65
+ mkPluginHandler STextDocumentSelectionRange selectionRangeHandler
66
+ <> mkPluginHandler STextDocumentFoldingRange foldingRangeHandler,
67
+ pluginRules = codeRangeRule (cmapWithPrio LogRules recorder)
66
68
}
67
69
68
70
data Log = LogRules Rules. Log
69
71
70
72
instance Pretty Log where
71
- pretty log = case log of
72
- LogRules codeRangeLog -> pretty codeRangeLog
73
+ pretty log = case log of
74
+ LogRules codeRangeLog -> pretty codeRangeLog
73
75
74
76
foldingRangeHandler :: IdeState -> PluginId -> FoldingRangeParams -> LspM c (Either ResponseError (List FoldingRange ))
75
- foldingRangeHandler ide _ FoldingRangeParams {.. } = do
76
- pluginResponse $ do
77
- filePath <- ExceptT . pure . maybeToEither " fail to convert uri to file path" $
78
- toNormalizedFilePath' <$> uriToFilePath' uri
79
- foldingRanges <- ExceptT . liftIO . runIdeAction " FoldingRange" (shakeExtras ide) . runExceptT $
80
- getFoldingRanges filePath
81
- pure . List $ foldingRanges
82
- where
83
- uri :: Uri
84
- TextDocumentIdentifier uri = _textDocument
77
+ foldingRangeHandler ide _ FoldingRangeParams {.. } = do
78
+ pluginResponse $ do
79
+ filePath <-
80
+ ExceptT . pure . maybeToEither " fail to convert uri to file path" $
81
+ toNormalizedFilePath' <$> uriToFilePath' uri
82
+ foldingRanges <-
83
+ ExceptT . liftIO . runIdeAction " FoldingRange" (shakeExtras ide) . runExceptT $
84
+ getFoldingRanges filePath
85
+ pure . List $ foldingRanges
86
+ where
87
+ uri :: Uri
88
+ TextDocumentIdentifier uri = _textDocument
85
89
86
90
getFoldingRanges :: NormalizedFilePath -> ExceptT String IdeAction [FoldingRange ]
87
91
getFoldingRanges file = do
88
- (codeRange, _) <- maybeToExceptT " fail to get code range" $ useE GetCodeRange file
92
+ (codeRange, _) <- maybeToExceptT " fail to get code range" $ useE GetCodeRange file
89
93
90
- let foldingRanges = findFoldingRanges codeRange
94
+ let foldingRanges = findFoldingRanges codeRange
91
95
92
- maybeToExceptT " Fail to generate folding range" (MaybeT . pure $ Just foldingRanges)
96
+ maybeToExceptT " Fail to generate folding range" (MaybeT . pure $ Just foldingRanges)
93
97
94
98
selectionRangeHandler :: IdeState -> PluginId -> SelectionRangeParams -> LspM c (Either ResponseError (List SelectionRange ))
95
- selectionRangeHandler ide _ SelectionRangeParams {.. } = do
96
- pluginResponse $ do
97
- filePath <- ExceptT . pure . maybeToEither " fail to convert uri to file path" $
98
- toNormalizedFilePath' <$> uriToFilePath' uri
99
- selectionRanges <- ExceptT . liftIO . runIdeAction " SelectionRange" (shakeExtras ide) . runExceptT $
100
- getSelectionRanges filePath positions
101
- pure . List $ selectionRanges
99
+ selectionRangeHandler ide _ SelectionRangeParams {.. } = do
100
+ pluginResponse $ do
101
+ filePath <-
102
+ ExceptT . pure . maybeToEither " fail to convert uri to file path" $
103
+ toNormalizedFilePath' <$> uriToFilePath' uri
104
+ selectionRanges <-
105
+ ExceptT . liftIO . runIdeAction " SelectionRange" (shakeExtras ide) . runExceptT $
106
+ getSelectionRanges filePath positions
107
+ pure . List $ selectionRanges
102
108
where
103
109
uri :: Uri
104
110
TextDocumentIdentifier uri = _textDocument
@@ -108,19 +114,20 @@ selectionRangeHandler ide _ SelectionRangeParams{..} = do
108
114
109
115
getSelectionRanges :: NormalizedFilePath -> [Position ] -> ExceptT String IdeAction [SelectionRange ]
110
116
getSelectionRanges file positions = do
111
- (codeRange, positionMapping) <- maybeToExceptT " fail to get code range" $ useE GetCodeRange file
112
- -- 'positionMapping' should be appied to the input before using them
113
- positions' <- maybeToExceptT " fail to apply position mapping to input positions" . MaybeT . pure $
114
- traverse (fromCurrentPosition positionMapping) positions
117
+ (codeRange, positionMapping) <- maybeToExceptT " fail to get code range" $ useE GetCodeRange file
118
+ -- 'positionMapping' should be appied to the input before using them
119
+ positions' <-
120
+ maybeToExceptT " fail to apply position mapping to input positions" . MaybeT . pure $
121
+ traverse (fromCurrentPosition positionMapping) positions
115
122
116
- let selectionRanges = flip fmap positions' $ \ pos ->
117
- -- We need a default selection range if the lookup fails, so that other positions can still have valid results.
118
- let defaultSelectionRange = SelectionRange (Range pos pos) Nothing
119
- in fromMaybe defaultSelectionRange . findPosition pos $ codeRange
123
+ let selectionRanges = flip fmap positions' $ \ pos ->
124
+ -- We need a default selection range if the lookup fails, so that other positions can still have valid results.
125
+ let defaultSelectionRange = SelectionRange (Range pos pos) Nothing
126
+ in fromMaybe defaultSelectionRange . findPosition pos $ codeRange
120
127
121
- -- 'positionMapping' should be applied to the output ranges before returning them
122
- maybeToExceptT " fail to apply position mapping to output positions" . MaybeT . pure $
123
- traverse (toCurrentSelectionRange positionMapping) selectionRanges
128
+ -- 'positionMapping' should be applied to the output ranges before returning them
129
+ maybeToExceptT " fail to apply position mapping to output positions" . MaybeT . pure $
130
+ traverse (toCurrentSelectionRange positionMapping) selectionRanges
124
131
125
132
-- | Find 'Position' in 'CodeRange'. This can fail, if the given position is not covered by the 'CodeRange'.
126
133
findPosition :: Position -> CodeRange -> Maybe SelectionRange
@@ -129,54 +136,56 @@ findPosition pos root = go Nothing root
129
136
-- Helper function for recursion. The range list is built top-down
130
137
go :: Maybe SelectionRange -> CodeRange -> Maybe SelectionRange
131
138
go acc node =
132
- if positionInRange pos range
139
+ if positionInRange pos range
133
140
then maybe acc' (go acc') (binarySearchPos children)
134
- -- If all children doesn't contain pos, acc' will be returned.
141
+ else -- If all children doesn't contain pos, acc' will be returned.
135
142
-- acc' will be Nothing only if we are in the root level.
136
- else Nothing
143
+ Nothing
137
144
where
138
145
range = _codeRange_range node
139
146
children = _codeRange_children node
140
147
acc' = Just $ maybe (SelectionRange range Nothing ) (SelectionRange range . Just ) acc
141
148
142
149
binarySearchPos :: Vector CodeRange -> Maybe CodeRange
143
150
binarySearchPos v
144
- | V. null v = Nothing
145
- | V. length v == 1 ,
146
- Just r <- V. headM v = if positionInRange pos (_codeRange_range r) then Just r else Nothing
147
- | otherwise = do
148
- let (left, right) = V. splitAt (V. length v `div` 2 ) v
149
- startOfRight <- _start . _codeRange_range <$> V. headM right
150
- if pos < startOfRight then binarySearchPos left else binarySearchPos right
151
+ | V. null v = Nothing
152
+ | V. length v == 1 ,
153
+ Just r <- V. headM v =
154
+ if positionInRange pos (_codeRange_range r) then Just r else Nothing
155
+ | otherwise = do
156
+ let (left, right) = V. splitAt (V. length v `div` 2 ) v
157
+ startOfRight <- _start . _codeRange_range <$> V. headM right
158
+ if pos < startOfRight then binarySearchPos left else binarySearchPos right
151
159
152
160
findFoldingRanges :: CodeRange -> [FoldingRange ]
153
161
findFoldingRanges r@ (CodeRange _ children _) =
154
162
let frRoot :: [FoldingRange ] = case createFoldingRange r of
155
- Just x -> [x]
163
+ Just x -> [x]
156
164
Nothing -> []
157
165
158
166
frChildren :: [FoldingRange ] = concat $ V. toList $ fmap findFoldingRanges children
159
167
in frRoot ++ frChildren
160
168
161
169
createFoldingRange :: CodeRange -> Maybe FoldingRange
162
170
createFoldingRange node1 = do
163
- let range = _codeRange_range node1
164
- let Range startPos endPos = range
165
- let Position lineStart _= startPos
166
- let Position lineEnd _ = endPos
167
- let codeRangeKind = _codeRange_kind node1
171
+ let range = _codeRange_range node1
172
+ let Range startPos endPos = range
173
+ let Position lineStart _ = startPos
174
+ let Position lineEnd _ = endPos
175
+ let codeRangeKind = _codeRange_kind node1
168
176
169
- let frk = crkToFrk codeRangeKind
177
+ let frk = crkToFrk codeRangeKind
170
178
171
- case frk of
172
- Just _ -> Just (FoldingRange lineStart Nothing lineEnd Nothing frk)
173
- Nothing -> Nothing
179
+ case frk of
180
+ Just _ -> Just (FoldingRange lineStart Nothing lineEnd Nothing frk)
181
+ Nothing -> Nothing
174
182
175
183
-- | Likes 'toCurrentPosition', but works on 'SelectionRange'
176
184
toCurrentSelectionRange :: PositionMapping -> SelectionRange -> Maybe SelectionRange
177
- toCurrentSelectionRange positionMapping SelectionRange {.. } = do
178
- newRange <- toCurrentRange positionMapping _range
179
- pure $ SelectionRange {
180
- _range = newRange,
185
+ toCurrentSelectionRange positionMapping SelectionRange {.. } = do
186
+ newRange <- toCurrentRange positionMapping _range
187
+ pure $
188
+ SelectionRange
189
+ { _range = newRange,
181
190
_parent = _parent >>= toCurrentSelectionRange positionMapping
182
- }
191
+ }
0 commit comments