@@ -13,6 +13,7 @@ module Development.IDE.Core.Actions
1313, lookupMod
1414) where
1515
16+ import Control.Monad.Extra (mapMaybeM )
1617import Control.Monad.Reader
1718import Control.Monad.Trans.Maybe
1819import qualified Data.HashMap.Strict as HM
@@ -31,7 +32,9 @@ import Development.IDE.Types.HscEnvEq (hscEnv)
3132import Development.IDE.Types.Location
3233import qualified HieDb
3334import Language.LSP.Protocol.Types (DocumentHighlight (.. ),
34- SymbolInformation (.. ))
35+ SymbolInformation (.. ),
36+ normalizedFilePathToUri ,
37+ uriToNormalizedFilePath )
3538
3639
3740-- | Eventually this will lookup/generate URIs for files in dependencies, but not in the
@@ -66,10 +69,36 @@ getAtPoint file pos = runMaybeT $ do
6669 ! pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
6770 MaybeT $ pure $ first (toCurrentRange mapping =<< ) <$> AtPoint. atPoint opts hf dkMap env pos'
6871
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
7181 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
73102
74103-- | useE is useful to implement functions that aren’t rules but need shortcircuiting
75104-- e.g. getDefinition.
@@ -90,15 +119,17 @@ getDefinition file pos = runMaybeT $ do
90119 (HAR _ hf _ _ _, mapping) <- useE GetHieAst file
91120 (ImportMap imports, _) <- useE GetImportMap file
92121 ! 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
94124
95125getTypeDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Location ])
96126getTypeDefinition file pos = runMaybeT $ do
97127 ide@ ShakeExtras { withHieDb, hiedbWriter } <- ask
98128 opts <- liftIO $ getIdeOptionsIO ide
99129 (hf, mapping) <- useE GetHieAst file
100130 ! 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
102133
103134highlightAtPoint :: NormalizedFilePath -> Position -> IdeAction (Maybe [DocumentHighlight ])
104135highlightAtPoint file pos = runMaybeT $ do
0 commit comments