@@ -13,6 +13,7 @@ module Development.IDE.Core.Actions
13
13
, lookupMod
14
14
) where
15
15
16
+ import Control.Monad.Extra (mapMaybeM )
16
17
import Control.Monad.Reader
17
18
import Control.Monad.Trans.Maybe
18
19
import qualified Data.HashMap.Strict as HM
@@ -31,7 +32,9 @@ import Development.IDE.Types.HscEnvEq (hscEnv)
31
32
import Development.IDE.Types.Location
32
33
import qualified HieDb
33
34
import Language.LSP.Protocol.Types (DocumentHighlight (.. ),
34
- SymbolInformation (.. ))
35
+ SymbolInformation (.. ),
36
+ normalizedFilePathToUri ,
37
+ uriToNormalizedFilePath )
35
38
36
39
37
40
-- | Eventually this will lookup/generate URIs for files in dependencies, but not in the
@@ -66,10 +69,36 @@ getAtPoint file pos = runMaybeT $ do
66
69
! pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
67
70
MaybeT $ pure $ first (toCurrentRange mapping =<< ) <$> AtPoint. atPoint opts hf dkMap env pos'
68
71
69
- toCurrentLocations :: PositionMapping -> [Location ] -> [Location ]
70
- toCurrentLocations mapping = mapMaybe go
72
+ -- | For each Loacation, determine if we have the PositionMapping
73
+ -- for the correct file. If not, get the correct position mapping
74
+ -- and then apply the position mapping to the location.
75
+ toCurrentLocations
76
+ :: PositionMapping
77
+ -> NormalizedFilePath
78
+ -> [Location ]
79
+ -> IdeAction [Location ]
80
+ toCurrentLocations mapping file = mapMaybeM go
71
81
where
72
- go (Location uri range) = Location uri <$> toCurrentRange mapping range
82
+ go :: Location -> IdeAction (Maybe Location )
83
+ go (Location uri range) =
84
+ -- The Location we are going to might be in a different
85
+ -- file than the one we are calling gotoDefinition from.
86
+ -- So we check that the location file matches the file
87
+ -- we are in.
88
+ if nUri == normalizedFilePathToUri file
89
+ -- The Location matches the file, so use the PositionMapping
90
+ -- we have.
91
+ then pure $ Location uri <$> toCurrentRange mapping range
92
+ -- The Location does not match the file, so get the correct
93
+ -- PositionMapping and use that instead.
94
+ else do
95
+ otherLocationMapping <- fmap (fmap snd ) $ runMaybeT $ do
96
+ otherLocationFile <- MaybeT $ pure $ uriToNormalizedFilePath nUri
97
+ useE GetHieAst otherLocationFile
98
+ pure $ Location uri <$> (flip toCurrentRange range =<< otherLocationMapping)
99
+ where
100
+ nUri :: NormalizedUri
101
+ nUri = toNormalizedUri uri
73
102
74
103
-- | useE is useful to implement functions that aren’t rules but need shortcircuiting
75
104
-- e.g. getDefinition.
@@ -90,15 +119,17 @@ getDefinition file pos = runMaybeT $ do
90
119
(HAR _ hf _ _ _, mapping) <- useE GetHieAst file
91
120
(ImportMap imports, _) <- useE GetImportMap file
92
121
! pos' <- MaybeT (pure $ fromCurrentPosition mapping pos)
93
- toCurrentLocations mapping <$> AtPoint. gotoDefinition withHieDb (lookupMod hiedbWriter) opts imports hf pos'
122
+ locations <- AtPoint. gotoDefinition withHieDb (lookupMod hiedbWriter) opts imports hf pos'
123
+ MaybeT $ Just <$> toCurrentLocations mapping file locations
94
124
95
125
getTypeDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Location ])
96
126
getTypeDefinition file pos = runMaybeT $ do
97
127
ide@ ShakeExtras { withHieDb, hiedbWriter } <- ask
98
128
opts <- liftIO $ getIdeOptionsIO ide
99
129
(hf, mapping) <- useE GetHieAst file
100
130
! pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
101
- toCurrentLocations mapping <$> AtPoint. gotoTypeDefinition withHieDb (lookupMod hiedbWriter) opts hf pos'
131
+ locations <- AtPoint. gotoTypeDefinition withHieDb (lookupMod hiedbWriter) opts hf pos'
132
+ MaybeT $ Just <$> toCurrentLocations mapping file locations
102
133
103
134
highlightAtPoint :: NormalizedFilePath -> Position -> IdeAction (Maybe [DocumentHighlight ])
104
135
highlightAtPoint file pos = runMaybeT $ do
0 commit comments