Skip to content

Fix error in code range #3229

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Sep 29, 2022
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 25 additions & 23 deletions plugins/hls-code-range-plugin/src/Ide/Plugin/CodeRange.hs
Original file line number Diff line number Diff line change
Expand Up @@ -15,21 +15,22 @@ module Ide.Plugin.CodeRange (
import Control.Monad.Except (ExceptT (ExceptT),
runExceptT)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Maybe (MaybeT (MaybeT),
maybeToExceptT)
import Data.Either.Extra (maybeToEither)
import Data.Maybe (fromMaybe)
import Data.Vector (Vector)
import qualified Data.Vector as V
import Development.IDE (IdeAction,
import Development.IDE (Action, IdeAction,
IdeState (shakeExtras),
Range (Range), Recorder,
WithPriority,
cmapWithPrio,
cmapWithPrio, runAction,
runIdeAction,
toNormalizedFilePath',
uriToFilePath')
import Development.IDE.Core.Actions (useE)
uriToFilePath', use,
useWithStaleFast)
import Development.IDE.Core.PositionMapping (PositionMapping,
fromCurrentPosition,
toCurrentRange)
Expand Down Expand Up @@ -77,19 +78,18 @@ foldingRangeHandler ide _ FoldingRangeParams{..} = do
pluginResponse $ do
filePath <- ExceptT . pure . maybeToEither "fail to convert uri to file path" $
toNormalizedFilePath' <$> uriToFilePath' uri
foldingRanges <- ExceptT . liftIO . runIdeAction "FoldingRange" (shakeExtras ide) . runExceptT $
foldingRanges <- liftIO . runAction "FoldingRange" ide $
getFoldingRanges filePath
pure . List $ foldingRanges
where
uri :: Uri
TextDocumentIdentifier uri = _textDocument

getFoldingRanges :: NormalizedFilePath -> ExceptT String IdeAction [FoldingRange]
getFoldingRanges :: NormalizedFilePath -> Action [FoldingRange]
getFoldingRanges file = do
(codeRange, _) <- maybeToExceptT "fail to get code range" $ useE GetCodeRange file

-- removing first node because it folds the entire file
pure $ drop 1 $ findFoldingRanges codeRange
codeRange <- use GetCodeRange file
-- removing the first node because it folds the entire file
pure $ maybe [] (drop 1 . findFoldingRanges) codeRange

selectionRangeHandler :: IdeState -> PluginId -> SelectionRangeParams -> LspM c (Either ResponseError (List SelectionRange))
selectionRangeHandler ide _ SelectionRangeParams{..} = do
Expand All @@ -108,19 +108,21 @@ selectionRangeHandler ide _ SelectionRangeParams{..} = do

getSelectionRanges :: NormalizedFilePath -> [Position] -> ExceptT String IdeAction [SelectionRange]
getSelectionRanges file positions = do
(codeRange, positionMapping) <- maybeToExceptT "fail to get code range" $ useE GetCodeRange file
-- 'positionMapping' should be appied to the input before using them
positions' <- maybeToExceptT "fail to apply position mapping to input positions" . MaybeT . pure $
traverse (fromCurrentPosition positionMapping) positions

let selectionRanges = flip fmap positions' $ \pos ->
-- We need a default selection range if the lookup fails, so that other positions can still have valid results.
let defaultSelectionRange = SelectionRange (Range pos pos) Nothing
in fromMaybe defaultSelectionRange . findPosition pos $ codeRange

-- 'positionMapping' should be applied to the output ranges before returning them
maybeToExceptT "fail to apply position mapping to output positions" . MaybeT . pure $
traverse (toCurrentSelectionRange positionMapping) selectionRanges
codeRangeResult <- lift $ useWithStaleFast GetCodeRange file
flip (maybe (pure [])) codeRangeResult $ \(codeRange, positionMapping) -> do
-- 'positionMapping' should be appied to the input before using them
positions' <- maybeToExceptT "fail to apply position mapping to input positions" . MaybeT . pure $
traverse (fromCurrentPosition positionMapping) positions

let selectionRanges = flip fmap positions' $ \pos ->
-- We need a default selection range if the lookup fails,
-- so that other positions can still have valid results.
let defaultSelectionRange = SelectionRange (Range pos pos) Nothing
in fromMaybe defaultSelectionRange . findPosition pos $ codeRange

-- 'positionMapping' should be applied to the output ranges before returning them
maybeToExceptT "fail to apply position mapping to output positions" . MaybeT . pure $
traverse (toCurrentSelectionRange positionMapping) selectionRanges

-- | Find 'Position' in 'CodeRange'. This can fail, if the given position is not covered by the 'CodeRange'.
findPosition :: Position -> CodeRange -> Maybe SelectionRange
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ handleError recorder action' = do
valueEither <- runExceptT action'
case valueEither of
Left msg -> do
logWith recorder Error msg
logWith recorder Warning msg
pure $ toIdeResult (Left [])
Right value -> pure $ toIdeResult (Right value)

Expand Down
9 changes: 5 additions & 4 deletions plugins/hls-code-range-plugin/test/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ main = do
defaultTestRunner $
testGroup "Code Range" [
testGroup "Integration Tests" [
makeSelectionRangeGoldenTest recorder "Import" [(4, 36), (1, 8)],
makeSelectionRangeGoldenTest recorder "Function" [(5, 19), (5, 12), (4, 4), (3, 5)],
selectionRangeGoldenTest recorder "Import" [(4, 36), (1, 8)],
selectionRangeGoldenTest recorder "Function" [(5, 19), (5, 12), (4, 4), (3, 5)],
selectionRangeGoldenTest recorder "Empty" [(1, 5)],
foldingRangeGoldenTest recorder "Function"
],
testGroup "Unit Tests" [
Expand All @@ -37,8 +38,8 @@ main = do
]
]

makeSelectionRangeGoldenTest :: Recorder (WithPriority Log) -> TestName -> [(UInt, UInt)] -> TestTree
makeSelectionRangeGoldenTest recorder testName positions = goldenGitDiff testName (testDataDir </> testName <.> "golden" <.> "txt") $ do
selectionRangeGoldenTest :: Recorder (WithPriority Log) -> TestName -> [(UInt, UInt)] -> TestTree
selectionRangeGoldenTest recorder testName positions = goldenGitDiff testName (testDataDir </> testName <.> "golden" <.> "txt") $ do
res <- runSessionWithServer (plugin recorder) testDataDir $ do
doc <- openDoc (testName <.> "hs") "haskell"
resp <- request STextDocumentSelectionRange $ SelectionRangeParams Nothing Nothing doc
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module Empty where
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ cradle:
direct:
arguments:
- "Function"
- "Empty"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
module Empty where
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ cradle:
arguments:
- "Import"
- "Function"
- "Empty"