on master help sign in
Refactor hover and go-to-definition searching (#260)

The process of searching for definitions is similar to the process of searching for hover information. In the original code (much of which was written out twice with occasional stylistic differences) the signal to noise ratio seemed pretty poor. Here is a refactoring which aims to make it easier to see the similarities and differences between these two related functionalities.

commit7e18f84f81e1d82031007777a567a1d445acea82 authorJacek Generowicz <jacg@my-post-office.net> dateWed 18 Dec 2019, 09:50 (7 years ago) parent6cf1d60
6 files changed+63−96
ghcide.cabal+1−2 src/Development/IDE/Core/Rules.hs+2−2 src/Development/IDE/LSP/Definition.hs−43 src/Development/IDE/LSP/Hover.hs−47 src/Development/IDE/LSP/HoverDefinition.hs+59 src/Development/IDE/LSP/LanguageServer.hs+1−2
ghcide.cabal+1−2
@@ -123,8 +123,7 @@ library
123123 Development.IDE.GHC.Warnings
124124 Development.IDE.Import.FindImports
125125 Development.IDE.LSP.CodeAction
126− Development.IDE.LSP.Definition
127− Development.IDE.LSP.Hover
126+ Development.IDE.LSP.HoverDefinition
128127 Development.IDE.LSP.Notifications
129128 Development.IDE.Spans.AtPoint
130129 Development.IDE.Spans.Calculate
src/Development/IDE/Core/Rules.hs+2−2
@@ -102,17 +102,17 @@ getDependencies file = fmap transitiveModuleDeps <$> use GetDependencies file
102102getAtPoint :: NormalizedFilePath -> Position -> Action (Maybe (Maybe Range, [T.Text]))
103103getAtPoint file pos = fmap join $ runMaybeT $ do
104104 opts <- lift getIdeOptions
105+ spans <- useE GetSpanInfo file
105106 files <- transitiveModuleDeps <$> useE GetDependencies file
106107 tms <- usesE TypeCheck (file : files)
107− spans <- useE GetSpanInfo file
108108 return $ AtPoint.atPoint opts (map tmrModule tms) spans pos
109109
110110-- | Goto Definition.
111111getDefinition :: NormalizedFilePath -> Position -> Action (Maybe Location)
112112getDefinition file pos = fmap join $ runMaybeT $ do
113+ opts <- lift getIdeOptions
113114 spans <- useE GetSpanInfo file
114115 pkgState <- hscEnv <$> useE GhcSession file
115− opts <- lift getIdeOptions
116116 let getHieFile x = useNoFile (GetHieFile x)
117117 lift $ AtPoint.gotoDefinition getHieFile opts pkgState spans pos
118118
src/Development/IDE/LSP/Definition.hsdeleted−43
@@ -1,43 +0,0 @@
1−-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2−-- SPDX-License-Identifier: Apache-2.0
3−
4−
5−-- | Go to the definition of a variable.
6−module Development.IDE.LSP.Definition
7− ( setHandlersDefinition
8− ) where
9−
10−import Language.Haskell.LSP.Types
11−import Development.IDE.Types.Location
12−
13−import Development.IDE.Types.Logger
14−import Development.IDE.Core.Rules
15−import Development.IDE.Core.Service
16−import Development.IDE.LSP.Server
17−import qualified Language.Haskell.LSP.Core as LSP
18−import Language.Haskell.LSP.Messages
19−
20−import qualified Data.Text as T
21−
22−-- | Go to the definition of a variable.
23−gotoDefinition
24− :: IdeState
25− -> TextDocumentPositionParams
26− -> IO LocationResponseParams
27−gotoDefinition ide (TextDocumentPositionParams (TextDocumentIdentifier uri) pos _) = do
28− mbResult <- case uriToFilePath' uri of
29− Just path -> do
30− logInfo (ideLogger ide) $
31− "Definition request at position " <> T.pack (showPosition pos) <>
32− " in file: " <> T.pack path
33− runAction ide $ getDefinition (toNormalizedFilePath path) pos
34− Nothing -> pure Nothing
35− pure $ case mbResult of
36− Nothing -> MultiLoc []
37− Just loc -> SingleLoc loc
38−
39−
40−setHandlersDefinition :: PartialHandlers
41−setHandlersDefinition = PartialHandlers $ \WithMessage{..} x -> return x{
42− LSP.definitionHandler = withResponse RspDefinition $ const gotoDefinition
43− }
src/Development/IDE/LSP/Hover.hsdeleted−47
@@ -1,47 +0,0 @@
1−-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2−-- SPDX-License-Identifier: Apache-2.0
3−
4−
5−-- | Display information on hover.
6−module Development.IDE.LSP.Hover
7− ( setHandlersHover
8− ) where
9−
10−import Language.Haskell.LSP.Types
11−import Development.IDE.Types.Location
12−import Development.IDE.Core.Service
13−import Development.IDE.LSP.Server
14−import Development.IDE.Types.Logger
15−import qualified Language.Haskell.LSP.Core as LSP
16−import Language.Haskell.LSP.Messages
17−
18−import qualified Data.Text as T
19−
20−import Development.IDE.Core.Rules
21−
22−-- | Display information on hover.
23−onHover
24− :: IdeState
25− -> TextDocumentPositionParams
26− -> IO (Maybe Hover)
27−onHover ide (TextDocumentPositionParams (TextDocumentIdentifier uri) pos _) = do
28− mbResult <- case uriToFilePath' uri of
29− Just (toNormalizedFilePath -> filePath) -> do
30− logInfo (ideLogger ide) $
31− "Hover request at position " <> T.pack (showPosition pos) <>
32− " in file: " <> T.pack (fromNormalizedFilePath filePath)
33− runAction ide $ getAtPoint filePath pos
34− Nothing -> pure Nothing
35−
36− case mbResult of
37− Just (mbRange, contents) ->
38− pure $ Just $ Hover
39− (HoverContents $ MarkupContent MkMarkdown $ T.intercalate sectionSeparator contents)
40− mbRange
41−
42− Nothing -> pure Nothing
43−
44−setHandlersHover :: PartialHandlers
45−setHandlersHover = PartialHandlers $ \WithMessage{..} x -> return x{
46− LSP.hoverHandler = withResponse RspHover $ const onHover
47− }
src/Development/IDE/LSP/HoverDefinition.hsnew file+59
@@ -0,0 +1,59 @@
1+-- Copyright (c) 2019 The DAML Authors. All rights reserved.
2+-- SPDX-License-Identifier: Apache-2.0
3+
4+
5+-- | Display information on hover.
6+module Development.IDE.LSP.HoverDefinition
7+ ( setHandlersHover
8+ , setHandlersDefinition
9+ ) where
10+
11+import Development.IDE.Core.Rules
12+import Development.IDE.Core.Service
13+import Development.IDE.LSP.Server
14+import Development.IDE.Types.Location
15+import Development.IDE.Types.Logger
16+import Development.Shake
17+import qualified Language.Haskell.LSP.Core as LSP
18+import Language.Haskell.LSP.Messages
19+import Language.Haskell.LSP.Types
20+
21+import qualified Data.Text as T
22+
23+gotoDefinition :: IdeState -> TextDocumentPositionParams -> IO LocationResponseParams
24+hover :: IdeState -> TextDocumentPositionParams -> IO (Maybe Hover)
25+gotoDefinition = request "Definition" getDefinition (MultiLoc []) SingleLoc
26+hover = request "Hover" getAtPoint Nothing foundHover
27+
28+foundHover :: (Maybe Range, [T.Text]) -> Maybe Hover
29+foundHover (mbRange, contents) =
30+ Just $ Hover (HoverContents $ MarkupContent MkMarkdown $ T.intercalate sectionSeparator contents) mbRange
31+
32+setHandlersDefinition, setHandlersHover :: PartialHandlers
33+setHandlersDefinition = PartialHandlers $ \WithMessage{..} x ->
34+ return x{LSP.definitionHandler = withResponse RspDefinition $ const gotoDefinition}
35+setHandlersHover = PartialHandlers $ \WithMessage{..} x ->
36+ return x{LSP.hoverHandler = withResponse RspHover $ const hover}
37+
38+-- | Respond to and log a hover or go-to-definition request
39+request
40+ :: T.Text
41+ -> (NormalizedFilePath -> Position -> Action (Maybe a))
42+ -> b
43+ -> (a -> b)
44+ -> IdeState
45+ -> TextDocumentPositionParams
46+ -> IO b
47+request label getResults notFound found ide (TextDocumentPositionParams (TextDocumentIdentifier uri) pos _) = do
48+ mbResult <- case uriToFilePath' uri of
49+ Just path -> logAndRunRequest label getResults ide pos path
50+ Nothing -> pure Nothing
51+ pure $ maybe notFound found mbResult
52+
53+logAndRunRequest :: T.Text -> (NormalizedFilePath -> Position -> Action b) -> IdeState -> Position -> String -> IO b
54+logAndRunRequest label getResults ide pos path = do
55+ let filePath = toNormalizedFilePath path
56+ logInfo (ideLogger ide) $
57+ label <> " request at position " <> T.pack (showPosition pos) <>
58+ " in file: " <> T.pack path
59+ runAction ide $ getResults filePath pos
src/Development/IDE/LSP/LanguageServer.hs+1−2
@@ -28,8 +28,7 @@ import GHC.IO.Handle (hDuplicate)
2828import System.IO
2929import Control.Monad.Extra
3030
31−import Development.IDE.LSP.Definition
32−import Development.IDE.LSP.Hover
31+import Development.IDE.LSP.HoverDefinition
3332import Development.IDE.LSP.CodeAction
3433import Development.IDE.LSP.Notifications
3534import Development.IDE.Core.Service