Skip to content

Commit 85d0ddb

Browse files
author
kokobd
committed
expand selection range by HieAST
1 parent d81aad8 commit 85d0ddb

File tree

2 files changed

+57
-26
lines changed

2 files changed

+57
-26
lines changed

ghcide/src/Development/IDE/Core/Actions.hs

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ module Development.IDE.Core.Actions
1010
, useNoFileE
1111
, usesE
1212
, workspaceSymbols
13-
, getSelectionRanges
1413
) where
1514

1615
import Control.Monad.Reader
@@ -29,10 +28,8 @@ import Development.IDE.Graph
2928
import qualified Development.IDE.Spans.AtPoint as AtPoint
3029
import Development.IDE.Types.HscEnvEq (hscEnv)
3130
import Development.IDE.Types.Location
32-
import Development.IDE.Types.Logger
3331
import qualified HieDb
3432
import Language.LSP.Types (DocumentHighlight (..),
35-
SelectionRange,
3633
SymbolInformation (..))
3734

3835

@@ -122,10 +119,3 @@ workspaceSymbols query = runMaybeT $ do
122119
ShakeExtras{withHieDb} <- ask
123120
res <- liftIO $ withHieDb (\hieDb -> HieDb.searchDef hieDb $ T.unpack query)
124121
pure $ mapMaybe AtPoint.defRowToSymbolInfo res
125-
126-
getSelectionRanges :: NormalizedFilePath -> [Position] -> IdeAction [SelectionRange]
127-
getSelectionRanges file positions = fmap (fromMaybe []) <$> runMaybeT $ do
128-
ShakeExtras{logger} <- ask
129-
(parsedModule, _) <- useE GetParsedModuleWithComments file
130-
liftIO $ logDebug logger $ T.pack (show parsedModule)
131-
pure []
Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,38 @@
1+
{-# LANGUAGE RankNTypes #-}
12
module Development.IDE.Plugin.SelectionRange
23
( descriptor
34
) where
45

5-
import Control.Monad.IO.Class (liftIO)
6-
import Development.IDE (IdeState (shakeExtras),
7-
runIdeAction,
8-
toNormalizedFilePath',
9-
uriToFilePath')
10-
import Development.IDE.Core.Actions (getSelectionRanges)
11-
import Ide.Types (PluginDescriptor (pluginHandlers),
12-
PluginId,
13-
defaultPluginDescriptor,
14-
mkPluginHandler)
15-
import Language.LSP.Server (LspM)
16-
import Language.LSP.Types (List (List), ResponseError,
17-
SMethod (STextDocumentSelectionRange),
18-
SelectionRange,
19-
SelectionRangeParams (..),
20-
TextDocumentIdentifier (TextDocumentIdentifier))
6+
import Control.Monad.IO.Class (liftIO)
7+
import Control.Monad.Trans.Maybe (MaybeT (MaybeT), runMaybeT)
8+
import Data.Foldable (find)
9+
import qualified Data.Map.Strict as Map
10+
import Data.Maybe (fromMaybe, mapMaybe)
11+
import Development.IDE (GetHieAst (GetHieAst),
12+
HieAstResult (HAR, hieAst),
13+
IdeAction,
14+
IdeState (shakeExtras),
15+
Range (Range),
16+
fromNormalizedFilePath,
17+
realSrcSpanToRange,
18+
runIdeAction,
19+
toNormalizedFilePath',
20+
uriToFilePath')
21+
import Development.IDE.Core.Actions (useE)
22+
import Development.IDE.GHC.Compat (HieAST (Node), Span, getAsts)
23+
import Development.IDE.GHC.Compat.Util (mkFastString)
24+
import Ide.Types (PluginDescriptor (pluginHandlers),
25+
PluginId,
26+
defaultPluginDescriptor,
27+
mkPluginHandler)
28+
import Language.LSP.Server (LspM)
29+
import Language.LSP.Types (List (List),
30+
NormalizedFilePath, Position,
31+
ResponseError,
32+
SMethod (STextDocumentSelectionRange),
33+
SelectionRange (..),
34+
SelectionRangeParams (..),
35+
TextDocumentIdentifier (TextDocumentIdentifier))
2136

2237
descriptor :: PluginId -> PluginDescriptor IdeState
2338
descriptor plId = (defaultPluginDescriptor plId)
@@ -34,3 +49,29 @@ selectionRangeHandler ide _ SelectionRangeParams{..} = do
3449
let (List positions) = _positions
3550
selectionRanges <- runIdeAction "SelectionRange" (shakeExtras ide) $ getSelectionRanges filePath positions
3651
pure . Right . List $ selectionRanges
52+
53+
getSelectionRanges :: NormalizedFilePath -> [Position] -> IdeAction [SelectionRange]
54+
getSelectionRanges file positions = fmap (fromMaybe []) <$> runMaybeT $ do
55+
(HAR{hieAst}, _) <- useE GetHieAst file
56+
ast <- MaybeT . pure $ getAsts hieAst Map.!? (mkFastString . fromNormalizedFilePath) file
57+
pure $ findSelectionRangesByPositions (astPathsLeafToRoot ast) positions
58+
59+
-- |build all paths from ast leaf to root
60+
astPathsLeafToRoot :: HieAST a -> [SelectionRange]
61+
astPathsLeafToRoot = mapMaybe spansToSelectionRange . go [[]]
62+
where
63+
go acc (Node _ span []) = fmap (span:) acc
64+
go acc (Node _ span children) = concatMap (go (fmap (span:) acc)) children
65+
66+
spansToSelectionRange :: [Span] -> Maybe SelectionRange
67+
spansToSelectionRange [] = Nothing
68+
spansToSelectionRange (span:spans) = Just $
69+
SelectionRange {_range = realSrcSpanToRange span, _parent = spansToSelectionRange spans}
70+
71+
findSelectionRangesByPositions :: [SelectionRange] -> [Position] -> [SelectionRange]
72+
findSelectionRangesByPositions selectionRanges = fmap findByPosition
73+
where
74+
findByPosition p = fromMaybe SelectionRange{_range = Range p p, _parent = Nothing} $
75+
find (isPositionInSelectionRange p) selectionRanges
76+
isPositionInSelectionRange p SelectionRange{_range} =
77+
let Range sp ep = _range in sp <= p && p <= ep

0 commit comments

Comments
 (0)