Smarter HsType pretty-print for promoted datacons
[ghc.git] / compiler / basicTypes / SrcLoc.hs
1 -- (c) The University of Glasgow, 1992-2006
2
3 {-# LANGUAGE DeriveDataTypeable #-}
4 {-# LANGUAGE StandaloneDeriving #-}
5 {-# LANGUAGE DeriveFunctor #-}
6 {-# LANGUAGE DeriveFoldable #-}
7 {-# LANGUAGE DeriveTraversable #-}
8 {-# LANGUAGE FlexibleInstances #-}
9 {-# LANGUAGE RecordWildCards #-}
10
11 -- | This module contains types that relate to the positions of things
12 -- in source files, and allow tagging of those things with locations
13 module SrcLoc (
14 -- * SrcLoc
15 RealSrcLoc, -- Abstract
16 SrcLoc(..),
17
18 -- ** Constructing SrcLoc
19 mkSrcLoc, mkRealSrcLoc, mkGeneralSrcLoc,
20
21 noSrcLoc, -- "I'm sorry, I haven't a clue"
22 generatedSrcLoc, -- Code generated within the compiler
23 interactiveSrcLoc, -- Code from an interactive session
24
25 advanceSrcLoc,
26
27 -- ** Unsafely deconstructing SrcLoc
28 -- These are dubious exports, because they crash on some inputs
29 srcLocFile, -- return the file name part
30 srcLocLine, -- return the line part
31 srcLocCol, -- return the column part
32
33 -- * SrcSpan
34 RealSrcSpan, -- Abstract
35 SrcSpan(..),
36
37 -- ** Constructing SrcSpan
38 mkGeneralSrcSpan, mkSrcSpan, mkRealSrcSpan,
39 noSrcSpan,
40 wiredInSrcSpan, -- Something wired into the compiler
41 interactiveSrcSpan,
42 srcLocSpan, realSrcLocSpan,
43 combineSrcSpans,
44 srcSpanFirstCharacter,
45
46 -- ** Deconstructing SrcSpan
47 srcSpanStart, srcSpanEnd,
48 realSrcSpanStart, realSrcSpanEnd,
49 srcSpanFileName_maybe,
50 pprUserRealSpan,
51
52 -- ** Unsafely deconstructing SrcSpan
53 -- These are dubious exports, because they crash on some inputs
54 srcSpanFile,
55 srcSpanStartLine, srcSpanEndLine,
56 srcSpanStartCol, srcSpanEndCol,
57
58 -- ** Predicates on SrcSpan
59 isGoodSrcSpan, isOneLineSpan,
60 containsSpan,
61
62 -- * Located
63 Located,
64 RealLocated,
65 GenLocated(..),
66
67 -- ** Constructing Located
68 noLoc,
69 mkGeneralLocated,
70
71 -- ** Deconstructing Located
72 getLoc, unLoc,
73
74 -- ** Combining and comparing Located values
75 eqLocated, cmpLocated, combineLocs, addCLoc,
76 leftmost_smallest, leftmost_largest, rightmost,
77 spans, isSubspanOf, sortLocated
78 ) where
79
80 import GhcPrelude
81
82 import Util
83 import Json
84 import Outputable
85 import FastString
86
87 import Control.DeepSeq
88 import Data.Bits
89 import Data.Data
90 import Data.List
91 import Data.Ord
92
93 {-
94 ************************************************************************
95 * *
96 \subsection[SrcLoc-SrcLocations]{Source-location information}
97 * *
98 ************************************************************************
99
100 We keep information about the {\em definition} point for each entity;
101 this is the obvious stuff:
102 -}
103
104 -- | Real Source Location
105 --
106 -- Represents a single point within a file
107 data RealSrcLoc
108 = SrcLoc FastString -- A precise location (file name)
109 {-# UNPACK #-} !Int -- line number, begins at 1
110 {-# UNPACK #-} !Int -- column number, begins at 1
111 deriving (Eq, Ord)
112
113 -- | Source Location
114 data SrcLoc
115 = RealSrcLoc {-# UNPACK #-}!RealSrcLoc
116 | UnhelpfulLoc FastString -- Just a general indication
117 deriving (Eq, Ord, Show)
118
119 {-
120 ************************************************************************
121 * *
122 \subsection[SrcLoc-access-fns]{Access functions}
123 * *
124 ************************************************************************
125 -}
126
127 mkSrcLoc :: FastString -> Int -> Int -> SrcLoc
128 mkSrcLoc x line col = RealSrcLoc (mkRealSrcLoc x line col)
129
130 mkRealSrcLoc :: FastString -> Int -> Int -> RealSrcLoc
131 mkRealSrcLoc x line col = SrcLoc x line col
132
133 -- | Built-in "bad" 'SrcLoc' values for particular locations
134 noSrcLoc, generatedSrcLoc, interactiveSrcLoc :: SrcLoc
135 noSrcLoc = UnhelpfulLoc (fsLit "<no location info>")
136 generatedSrcLoc = UnhelpfulLoc (fsLit "<compiler-generated code>")
137 interactiveSrcLoc = UnhelpfulLoc (fsLit "<interactive>")
138
139 -- | Creates a "bad" 'SrcLoc' that has no detailed information about its location
140 mkGeneralSrcLoc :: FastString -> SrcLoc
141 mkGeneralSrcLoc = UnhelpfulLoc
142
143 -- | Gives the filename of the 'RealSrcLoc'
144 srcLocFile :: RealSrcLoc -> FastString
145 srcLocFile (SrcLoc fname _ _) = fname
146
147 -- | Raises an error when used on a "bad" 'SrcLoc'
148 srcLocLine :: RealSrcLoc -> Int
149 srcLocLine (SrcLoc _ l _) = l
150
151 -- | Raises an error when used on a "bad" 'SrcLoc'
152 srcLocCol :: RealSrcLoc -> Int
153 srcLocCol (SrcLoc _ _ c) = c
154
155 -- | Move the 'SrcLoc' down by one line if the character is a newline,
156 -- to the next 8-char tabstop if it is a tab, and across by one
157 -- character in any other case
158 advanceSrcLoc :: RealSrcLoc -> Char -> RealSrcLoc
159 advanceSrcLoc (SrcLoc f l _) '\n' = SrcLoc f (l + 1) 1
160 advanceSrcLoc (SrcLoc f l c) '\t' = SrcLoc f l (((((c - 1) `shiftR` 3) + 1)
161 `shiftL` 3) + 1)
162 advanceSrcLoc (SrcLoc f l c) _ = SrcLoc f l (c + 1)
163
164 {-
165 ************************************************************************
166 * *
167 \subsection[SrcLoc-instances]{Instance declarations for various names}
168 * *
169 ************************************************************************
170 -}
171
172 sortLocated :: [Located a] -> [Located a]
173 sortLocated things = sortBy (comparing getLoc) things
174
175 instance Outputable RealSrcLoc where
176 ppr (SrcLoc src_path src_line src_col)
177 = hcat [ pprFastFilePath src_path <> colon
178 , int src_line <> colon
179 , int src_col ]
180
181 -- I don't know why there is this style-based difference
182 -- if userStyle sty || debugStyle sty then
183 -- hcat [ pprFastFilePath src_path, char ':',
184 -- int src_line,
185 -- char ':', int src_col
186 -- ]
187 -- else
188 -- hcat [text "{-# LINE ", int src_line, space,
189 -- char '\"', pprFastFilePath src_path, text " #-}"]
190
191 instance Outputable SrcLoc where
192 ppr (RealSrcLoc l) = ppr l
193 ppr (UnhelpfulLoc s) = ftext s
194
195 instance Data RealSrcSpan where
196 -- don't traverse?
197 toConstr _ = abstractConstr "RealSrcSpan"
198 gunfold _ _ = error "gunfold"
199 dataTypeOf _ = mkNoRepType "RealSrcSpan"
200
201 instance Data SrcSpan where
202 -- don't traverse?
203 toConstr _ = abstractConstr "SrcSpan"
204 gunfold _ _ = error "gunfold"
205 dataTypeOf _ = mkNoRepType "SrcSpan"
206
207 {-
208 ************************************************************************
209 * *
210 \subsection[SrcSpan]{Source Spans}
211 * *
212 ************************************************************************
213 -}
214
215 {- |
216 A 'RealSrcSpan' delimits a portion of a text file. It could be represented
217 by a pair of (line,column) coordinates, but in fact we optimise
218 slightly by using more compact representations for single-line and
219 zero-length spans, both of which are quite common.
220
221 The end position is defined to be the column /after/ the end of the
222 span. That is, a span of (1,1)-(1,2) is one character long, and a
223 span of (1,1)-(1,1) is zero characters long.
224 -}
225
226 -- | Real Source Span
227 data RealSrcSpan
228 = RealSrcSpan'
229 { srcSpanFile :: !FastString,
230 srcSpanSLine :: {-# UNPACK #-} !Int,
231 srcSpanSCol :: {-# UNPACK #-} !Int,
232 srcSpanELine :: {-# UNPACK #-} !Int,
233 srcSpanECol :: {-# UNPACK #-} !Int
234 }
235 deriving Eq
236
237 -- | Source Span
238 --
239 -- A 'SrcSpan' identifies either a specific portion of a text file
240 -- or a human-readable description of a location.
241 data SrcSpan =
242 RealSrcSpan !RealSrcSpan
243 | UnhelpfulSpan !FastString -- Just a general indication
244 -- also used to indicate an empty span
245
246 deriving (Eq, Ord, Show) -- Show is used by Lexer.x, because we
247 -- derive Show for Token
248
249 instance ToJson SrcSpan where
250 json (UnhelpfulSpan {} ) = JSNull --JSObject [( "type", "unhelpful")]
251 json (RealSrcSpan rss) = json rss
252
253 instance ToJson RealSrcSpan where
254 json (RealSrcSpan'{..}) = JSObject [ ("file", JSString (unpackFS srcSpanFile))
255 , ("startLine", JSInt srcSpanSLine)
256 , ("startCol", JSInt srcSpanSCol)
257 , ("endLine", JSInt srcSpanELine)
258 , ("endCol", JSInt srcSpanECol)
259 ]
260
261 instance NFData SrcSpan where
262 rnf x = x `seq` ()
263
264 -- | Built-in "bad" 'SrcSpan's for common sources of location uncertainty
265 noSrcSpan, wiredInSrcSpan, interactiveSrcSpan :: SrcSpan
266 noSrcSpan = UnhelpfulSpan (fsLit "<no location info>")
267 wiredInSrcSpan = UnhelpfulSpan (fsLit "<wired into compiler>")
268 interactiveSrcSpan = UnhelpfulSpan (fsLit "<interactive>")
269
270 -- | Create a "bad" 'SrcSpan' that has not location information
271 mkGeneralSrcSpan :: FastString -> SrcSpan
272 mkGeneralSrcSpan = UnhelpfulSpan
273
274 -- | Create a 'SrcSpan' corresponding to a single point
275 srcLocSpan :: SrcLoc -> SrcSpan
276 srcLocSpan (UnhelpfulLoc str) = UnhelpfulSpan str
277 srcLocSpan (RealSrcLoc l) = RealSrcSpan (realSrcLocSpan l)
278
279 realSrcLocSpan :: RealSrcLoc -> RealSrcSpan
280 realSrcLocSpan (SrcLoc file line col) = RealSrcSpan' file line col line col
281
282 -- | Create a 'SrcSpan' between two points in a file
283 mkRealSrcSpan :: RealSrcLoc -> RealSrcLoc -> RealSrcSpan
284 mkRealSrcSpan loc1 loc2 = RealSrcSpan' file line1 col1 line2 col2
285 where
286 line1 = srcLocLine loc1
287 line2 = srcLocLine loc2
288 col1 = srcLocCol loc1
289 col2 = srcLocCol loc2
290 file = srcLocFile loc1
291
292 -- | 'True' if the span is known to straddle only one line.
293 isOneLineRealSpan :: RealSrcSpan -> Bool
294 isOneLineRealSpan (RealSrcSpan' _ line1 _ line2 _)
295 = line1 == line2
296
297 -- | 'True' if the span is a single point
298 isPointRealSpan :: RealSrcSpan -> Bool
299 isPointRealSpan (RealSrcSpan' _ line1 col1 line2 col2)
300 = line1 == line2 && col1 == col2
301
302 -- | Create a 'SrcSpan' between two points in a file
303 mkSrcSpan :: SrcLoc -> SrcLoc -> SrcSpan
304 mkSrcSpan (UnhelpfulLoc str) _ = UnhelpfulSpan str
305 mkSrcSpan _ (UnhelpfulLoc str) = UnhelpfulSpan str
306 mkSrcSpan (RealSrcLoc loc1) (RealSrcLoc loc2)
307 = RealSrcSpan (mkRealSrcSpan loc1 loc2)
308
309 -- | Combines two 'SrcSpan' into one that spans at least all the characters
310 -- within both spans. Returns UnhelpfulSpan if the files differ.
311 combineSrcSpans :: SrcSpan -> SrcSpan -> SrcSpan
312 combineSrcSpans (UnhelpfulSpan _) r = r -- this seems more useful
313 combineSrcSpans l (UnhelpfulSpan _) = l
314 combineSrcSpans (RealSrcSpan span1) (RealSrcSpan span2)
315 | srcSpanFile span1 == srcSpanFile span2
316 = RealSrcSpan (combineRealSrcSpans span1 span2)
317 | otherwise = UnhelpfulSpan (fsLit "<combineSrcSpans: files differ>")
318
319 -- | Combines two 'SrcSpan' into one that spans at least all the characters
320 -- within both spans. Assumes the "file" part is the same in both inputs
321 combineRealSrcSpans :: RealSrcSpan -> RealSrcSpan -> RealSrcSpan
322 combineRealSrcSpans span1 span2
323 = RealSrcSpan' file line_start col_start line_end col_end
324 where
325 (line_start, col_start) = min (srcSpanStartLine span1, srcSpanStartCol span1)
326 (srcSpanStartLine span2, srcSpanStartCol span2)
327 (line_end, col_end) = max (srcSpanEndLine span1, srcSpanEndCol span1)
328 (srcSpanEndLine span2, srcSpanEndCol span2)
329 file = srcSpanFile span1
330
331 -- | Convert a SrcSpan into one that represents only its first character
332 srcSpanFirstCharacter :: SrcSpan -> SrcSpan
333 srcSpanFirstCharacter l@(UnhelpfulSpan {}) = l
334 srcSpanFirstCharacter (RealSrcSpan span) = RealSrcSpan $ mkRealSrcSpan loc1 loc2
335 where
336 loc1@(SrcLoc f l c) = realSrcSpanStart span
337 loc2 = SrcLoc f l (c+1)
338
339 {-
340 ************************************************************************
341 * *
342 \subsection[SrcSpan-predicates]{Predicates}
343 * *
344 ************************************************************************
345 -}
346
347 -- | Test if a 'SrcSpan' is "good", i.e. has precise location information
348 isGoodSrcSpan :: SrcSpan -> Bool
349 isGoodSrcSpan (RealSrcSpan _) = True
350 isGoodSrcSpan (UnhelpfulSpan _) = False
351
352 isOneLineSpan :: SrcSpan -> Bool
353 -- ^ True if the span is known to straddle only one line.
354 -- For "bad" 'SrcSpan', it returns False
355 isOneLineSpan (RealSrcSpan s) = srcSpanStartLine s == srcSpanEndLine s
356 isOneLineSpan (UnhelpfulSpan _) = False
357
358 -- | Tests whether the first span "contains" the other span, meaning
359 -- that it covers at least as much source code. True where spans are equal.
360 containsSpan :: RealSrcSpan -> RealSrcSpan -> Bool
361 containsSpan s1 s2
362 = (srcSpanStartLine s1, srcSpanStartCol s1)
363 <= (srcSpanStartLine s2, srcSpanStartCol s2)
364 && (srcSpanEndLine s1, srcSpanEndCol s1)
365 >= (srcSpanEndLine s2, srcSpanEndCol s2)
366 && (srcSpanFile s1 == srcSpanFile s2)
367 -- We check file equality last because it is (presumably?) least
368 -- likely to fail.
369 {-
370 %************************************************************************
371 %* *
372 \subsection[SrcSpan-unsafe-access-fns]{Unsafe access functions}
373 * *
374 ************************************************************************
375 -}
376
377 srcSpanStartLine :: RealSrcSpan -> Int
378 srcSpanEndLine :: RealSrcSpan -> Int
379 srcSpanStartCol :: RealSrcSpan -> Int
380 srcSpanEndCol :: RealSrcSpan -> Int
381
382 srcSpanStartLine RealSrcSpan'{ srcSpanSLine=l } = l
383 srcSpanEndLine RealSrcSpan'{ srcSpanELine=l } = l
384 srcSpanStartCol RealSrcSpan'{ srcSpanSCol=l } = l
385 srcSpanEndCol RealSrcSpan'{ srcSpanECol=c } = c
386
387 {-
388 ************************************************************************
389 * *
390 \subsection[SrcSpan-access-fns]{Access functions}
391 * *
392 ************************************************************************
393 -}
394
395 -- | Returns the location at the start of the 'SrcSpan' or a "bad" 'SrcSpan' if that is unavailable
396 srcSpanStart :: SrcSpan -> SrcLoc
397 srcSpanStart (UnhelpfulSpan str) = UnhelpfulLoc str
398 srcSpanStart (RealSrcSpan s) = RealSrcLoc (realSrcSpanStart s)
399
400 -- | Returns the location at the end of the 'SrcSpan' or a "bad" 'SrcSpan' if that is unavailable
401 srcSpanEnd :: SrcSpan -> SrcLoc
402 srcSpanEnd (UnhelpfulSpan str) = UnhelpfulLoc str
403 srcSpanEnd (RealSrcSpan s) = RealSrcLoc (realSrcSpanEnd s)
404
405 realSrcSpanStart :: RealSrcSpan -> RealSrcLoc
406 realSrcSpanStart s = mkRealSrcLoc (srcSpanFile s)
407 (srcSpanStartLine s)
408 (srcSpanStartCol s)
409
410 realSrcSpanEnd :: RealSrcSpan -> RealSrcLoc
411 realSrcSpanEnd s = mkRealSrcLoc (srcSpanFile s)
412 (srcSpanEndLine s)
413 (srcSpanEndCol s)
414
415 -- | Obtains the filename for a 'SrcSpan' if it is "good"
416 srcSpanFileName_maybe :: SrcSpan -> Maybe FastString
417 srcSpanFileName_maybe (RealSrcSpan s) = Just (srcSpanFile s)
418 srcSpanFileName_maybe (UnhelpfulSpan _) = Nothing
419
420 {-
421 ************************************************************************
422 * *
423 \subsection[SrcSpan-instances]{Instances}
424 * *
425 ************************************************************************
426 -}
427
428 -- We want to order RealSrcSpans first by the start point, then by the
429 -- end point.
430 instance Ord RealSrcSpan where
431 a `compare` b =
432 (realSrcSpanStart a `compare` realSrcSpanStart b) `thenCmp`
433 (realSrcSpanEnd a `compare` realSrcSpanEnd b)
434
435 instance Show RealSrcLoc where
436 show (SrcLoc filename row col)
437 = "SrcLoc " ++ show filename ++ " " ++ show row ++ " " ++ show col
438
439 -- Show is used by Lexer.x, because we derive Show for Token
440 instance Show RealSrcSpan where
441 show span@(RealSrcSpan' file sl sc el ec)
442 | isPointRealSpan span
443 = "SrcSpanPoint " ++ show file ++ " " ++ intercalate " " (map show [sl,sc])
444
445 | isOneLineRealSpan span
446 = "SrcSpanOneLine " ++ show file ++ " "
447 ++ intercalate " " (map show [sl,sc,ec])
448
449 | otherwise
450 = "SrcSpanMultiLine " ++ show file ++ " "
451 ++ intercalate " " (map show [sl,sc,el,ec])
452
453
454 instance Outputable RealSrcSpan where
455 ppr span = pprUserRealSpan True span
456
457 -- I don't know why there is this style-based difference
458 -- = getPprStyle $ \ sty ->
459 -- if userStyle sty || debugStyle sty then
460 -- text (showUserRealSpan True span)
461 -- else
462 -- hcat [text "{-# LINE ", int (srcSpanStartLine span), space,
463 -- char '\"', pprFastFilePath $ srcSpanFile span, text " #-}"]
464
465 instance Outputable SrcSpan where
466 ppr span = pprUserSpan True span
467
468 -- I don't know why there is this style-based difference
469 -- = getPprStyle $ \ sty ->
470 -- if userStyle sty || debugStyle sty then
471 -- pprUserSpan True span
472 -- else
473 -- case span of
474 -- UnhelpfulSpan _ -> panic "Outputable UnhelpfulSpan"
475 -- RealSrcSpan s -> ppr s
476
477 pprUserSpan :: Bool -> SrcSpan -> SDoc
478 pprUserSpan _ (UnhelpfulSpan s) = ftext s
479 pprUserSpan show_path (RealSrcSpan s) = pprUserRealSpan show_path s
480
481 pprUserRealSpan :: Bool -> RealSrcSpan -> SDoc
482 pprUserRealSpan show_path span@(RealSrcSpan' src_path line col _ _)
483 | isPointRealSpan span
484 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
485 , int line <> colon
486 , int col ]
487
488 pprUserRealSpan show_path span@(RealSrcSpan' src_path line scol _ ecol)
489 | isOneLineRealSpan span
490 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
491 , int line <> colon
492 , int scol
493 , ppUnless (ecol - scol <= 1) (char '-' <> int (ecol - 1)) ]
494 -- For single-character or point spans, we just
495 -- output the starting column number
496
497 pprUserRealSpan show_path (RealSrcSpan' src_path sline scol eline ecol)
498 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
499 , parens (int sline <> comma <> int scol)
500 , char '-'
501 , parens (int eline <> comma <> int ecol') ]
502 where
503 ecol' = if ecol == 0 then ecol else ecol - 1
504
505 {-
506 ************************************************************************
507 * *
508 \subsection[Located]{Attaching SrcSpans to things}
509 * *
510 ************************************************************************
511 -}
512
513 -- | We attach SrcSpans to lots of things, so let's have a datatype for it.
514 data GenLocated l e = L l e
515 deriving (Eq, Ord, Data, Functor, Foldable, Traversable)
516
517 type Located = GenLocated SrcSpan
518 type RealLocated = GenLocated RealSrcSpan
519
520 unLoc :: GenLocated l e -> e
521 unLoc (L _ e) = e
522
523 getLoc :: GenLocated l e -> l
524 getLoc (L l _) = l
525
526 noLoc :: e -> Located e
527 noLoc e = L noSrcSpan e
528
529 mkGeneralLocated :: String -> e -> Located e
530 mkGeneralLocated s e = L (mkGeneralSrcSpan (fsLit s)) e
531
532 combineLocs :: Located a -> Located b -> SrcSpan
533 combineLocs a b = combineSrcSpans (getLoc a) (getLoc b)
534
535 -- | Combine locations from two 'Located' things and add them to a third thing
536 addCLoc :: Located a -> Located b -> c -> Located c
537 addCLoc a b c = L (combineSrcSpans (getLoc a) (getLoc b)) c
538
539 -- not clear whether to add a general Eq instance, but this is useful sometimes:
540
541 -- | Tests whether the two located things are equal
542 eqLocated :: Eq a => Located a -> Located a -> Bool
543 eqLocated a b = unLoc a == unLoc b
544
545 -- not clear whether to add a general Ord instance, but this is useful sometimes:
546
547 -- | Tests the ordering of the two located things
548 cmpLocated :: Ord a => Located a -> Located a -> Ordering
549 cmpLocated a b = unLoc a `compare` unLoc b
550
551 instance (Outputable l, Outputable e) => Outputable (GenLocated l e) where
552 ppr (L l e) = -- TODO: We can't do this since Located was refactored into
553 -- GenLocated:
554 -- Print spans without the file name etc
555 -- ifPprDebug (braces (pprUserSpan False l))
556 whenPprDebug (braces (ppr l))
557 $$ ppr e
558
559 {-
560 ************************************************************************
561 * *
562 \subsection{Ordering SrcSpans for InteractiveUI}
563 * *
564 ************************************************************************
565 -}
566
567 -- | Alternative strategies for ordering 'SrcSpan's
568 leftmost_smallest, leftmost_largest, rightmost :: SrcSpan -> SrcSpan -> Ordering
569 rightmost = flip compare
570 leftmost_smallest = compare
571 leftmost_largest a b = (srcSpanStart a `compare` srcSpanStart b)
572 `thenCmp`
573 (srcSpanEnd b `compare` srcSpanEnd a)
574
575 -- | Determines whether a span encloses a given line and column index
576 spans :: SrcSpan -> (Int, Int) -> Bool
577 spans (UnhelpfulSpan _) _ = panic "spans UnhelpfulSpan"
578 spans (RealSrcSpan span) (l,c) = realSrcSpanStart span <= loc && loc <= realSrcSpanEnd span
579 where loc = mkRealSrcLoc (srcSpanFile span) l c
580
581 -- | Determines whether a span is enclosed by another one
582 isSubspanOf :: SrcSpan -- ^ The span that may be enclosed by the other
583 -> SrcSpan -- ^ The span it may be enclosed by
584 -> Bool
585 isSubspanOf src parent
586 | srcSpanFileName_maybe parent /= srcSpanFileName_maybe src = False
587 | otherwise = srcSpanStart parent <= srcSpanStart src &&
588 srcSpanEnd parent >= srcSpanEnd src