6
6
module Development.IDE.Spans.AtPoint (
7
7
atPoint
8
8
, gotoDefinition
9
+ , gotoTypeDefinition
9
10
) where
10
11
11
12
import Development.IDE.GHC.Error
@@ -34,6 +35,16 @@ import Data.Maybe
34
35
import Data.List
35
36
import qualified Data.Text as T
36
37
38
+ gotoTypeDefinition
39
+ :: MonadIO m
40
+ => (Module -> m (Maybe (HieFile , FilePath )))
41
+ -> IdeOptions
42
+ -> [SpanInfo ]
43
+ -> Position
44
+ -> m [Location ]
45
+ gotoTypeDefinition getHieFile ideOpts srcSpans pos
46
+ = typeLocationsAtPoint getHieFile ideOpts pos srcSpans
47
+
37
48
-- | Locate the definition of the name at a given position.
38
49
gotoDefinition
39
50
:: MonadIO m
@@ -115,6 +126,26 @@ atPoint IdeOptions{..} (SpansInfo srcSpans cntsSpans) pos = do
115
126
Just name -> any (`isInfixOf` getOccString name) [" ==" , " showsPrec" ]
116
127
Nothing -> False
117
128
129
+
130
+
131
+
132
+ typeLocationsAtPoint
133
+ :: forall m
134
+ . MonadIO m
135
+ => (Module -> m (Maybe (HieFile , FilePath )))
136
+ -> IdeOptions
137
+ -> Position
138
+ -> [SpanInfo ]
139
+ -> m [Location ]
140
+ typeLocationsAtPoint getHieFile = querySpanInfoAt getTypeSpan
141
+ where getTypeSpan :: SpanInfo -> m (Maybe SrcSpan )
142
+ getTypeSpan SpanInfo { spaninfoType = Just t } =
143
+ case splitTyConApp_maybe t of
144
+ Nothing -> return Nothing
145
+ Just (getName -> name, _) ->
146
+ nameToLocation getHieFile name
147
+ getTypeSpan _ = return Nothing
148
+
118
149
locationsAtPoint
119
150
:: forall m
120
151
. MonadIO m
@@ -123,32 +154,47 @@ locationsAtPoint
123
154
-> Position
124
155
-> [SpanInfo ]
125
156
-> m [Location ]
126
- locationsAtPoint getHieFile _ideOptions pos =
127
- fmap (map srcSpanToLocation) . mapMaybeM (getSpan . spaninfoSource) . spansAtPoint pos
157
+ locationsAtPoint getHieFile = querySpanInfoAt (getSpan . spaninfoSource)
128
158
where getSpan :: SpanSource -> m (Maybe SrcSpan )
129
159
getSpan NoSource = pure Nothing
130
160
getSpan (SpanS sp) = pure $ Just sp
131
161
getSpan (Lit _) = pure Nothing
132
- getSpan (Named name) = case nameSrcSpan name of
133
- sp@ (RealSrcSpan _) -> pure $ Just sp
134
- sp@ (UnhelpfulSpan _) -> runMaybeT $ do
135
- guard (sp /= wiredInSrcSpan)
136
- -- This case usually arises when the definition is in an external package (DAML only).
137
- -- In this case the interface files contain garbage source spans
138
- -- so we instead read the .hie files to get useful source spans.
139
- mod <- MaybeT $ return $ nameModule_maybe name
140
- (hieFile, srcPath) <- MaybeT $ getHieFile mod
141
- avail <- MaybeT $ pure $ find (eqName name . snd ) $ hieExportNames hieFile
142
- -- The location will point to the source file used during compilation.
143
- -- This file might no longer exists and even if it does the path will be relative
144
- -- to the compilation directory which we don’t know.
145
- let span = setFileName srcPath $ fst avail
146
- pure span
147
- -- We ignore uniques and source spans and only compare the name and the module.
148
- eqName :: Name -> Name -> Bool
149
- eqName n n' = nameOccName n == nameOccName n' && nameModule_maybe n == nameModule_maybe n'
150
- setFileName f (RealSrcSpan span ) = RealSrcSpan (span { srcSpanFile = mkFastString f })
151
- setFileName _ span @ (UnhelpfulSpan _) = span
162
+ getSpan (Named name) = nameToLocation getHieFile name
163
+
164
+ querySpanInfoAt :: forall m
165
+ . MonadIO m
166
+ => (SpanInfo -> m (Maybe SrcSpan ))
167
+ -> IdeOptions
168
+ -> Position
169
+ -> [SpanInfo ]
170
+ -> m [Location ]
171
+ querySpanInfoAt getSpan _ideOptions pos =
172
+ fmap (map srcSpanToLocation) . mapMaybeM getSpan . spansAtPoint pos
173
+
174
+ -- | Given a 'Name' attempt to find the location where it is defined.
175
+ nameToLocation :: Monad f => (Module -> f (Maybe (HieFile , String ))) -> Name -> f (Maybe SrcSpan )
176
+ nameToLocation getHieFile name =
177
+ case nameSrcSpan name of
178
+ sp@ (RealSrcSpan _) -> pure $ Just sp
179
+ sp@ (UnhelpfulSpan _) -> runMaybeT $ do
180
+ guard (sp /= wiredInSrcSpan)
181
+ -- This case usually arises when the definition is in an external package (DAML only).
182
+ -- In this case the interface files contain garbage source spans
183
+ -- so we instead read the .hie files to get useful source spans.
184
+ mod <- MaybeT $ return $ nameModule_maybe name
185
+ (hieFile, srcPath) <- MaybeT $ getHieFile mod
186
+ avail <- MaybeT $ pure $ find (eqName name . snd ) $ hieExportNames hieFile
187
+ -- The location will point to the source file used during compilation.
188
+ -- This file might no longer exists and even if it does the path will be relative
189
+ -- to the compilation directory which we don’t know.
190
+ let span = setFileName srcPath $ fst avail
191
+ pure span
192
+ where
193
+ -- We ignore uniques and source spans and only compare the name and the module.
194
+ eqName :: Name -> Name -> Bool
195
+ eqName n n' = nameOccName n == nameOccName n' && nameModule_maybe n == nameModule_maybe n'
196
+ setFileName f (RealSrcSpan span ) = RealSrcSpan (span { srcSpanFile = mkFastString f })
197
+ setFileName _ span @ (UnhelpfulSpan _) = span
152
198
153
199
-- | Filter out spans which do not enclose a given point
154
200
spansAtPoint :: Position -> [SpanInfo ] -> [SpanInfo ]
0 commit comments