Update Hadrian
[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. Assumes the "file" part is the same in both inputs
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 = RealSrcSpan (combineRealSrcSpans span1 span2)
316
317 -- | Combines two 'SrcSpan' into one that spans at least all the characters
318 -- within both spans. Assumes the "file" part is the same in both inputs
319 combineRealSrcSpans :: RealSrcSpan -> RealSrcSpan -> RealSrcSpan
320 combineRealSrcSpans span1 span2
321 = RealSrcSpan' file line_start col_start line_end col_end
322 where
323 (line_start, col_start) = min (srcSpanStartLine span1, srcSpanStartCol span1)
324 (srcSpanStartLine span2, srcSpanStartCol span2)
325 (line_end, col_end) = max (srcSpanEndLine span1, srcSpanEndCol span1)
326 (srcSpanEndLine span2, srcSpanEndCol span2)
327 file = srcSpanFile span1
328
329 -- | Convert a SrcSpan into one that represents only its first character
330 srcSpanFirstCharacter :: SrcSpan -> SrcSpan
331 srcSpanFirstCharacter l@(UnhelpfulSpan {}) = l
332 srcSpanFirstCharacter (RealSrcSpan span) = RealSrcSpan $ mkRealSrcSpan loc1 loc2
333 where
334 loc1@(SrcLoc f l c) = realSrcSpanStart span
335 loc2 = SrcLoc f l (c+1)
336 {-
337 ************************************************************************
338 * *
339 \subsection[SrcSpan-predicates]{Predicates}
340 * *
341 ************************************************************************
342 -}
343
344 -- | Test if a 'SrcSpan' is "good", i.e. has precise location information
345 isGoodSrcSpan :: SrcSpan -> Bool
346 isGoodSrcSpan (RealSrcSpan _) = True
347 isGoodSrcSpan (UnhelpfulSpan _) = False
348
349 isOneLineSpan :: SrcSpan -> Bool
350 -- ^ True if the span is known to straddle only one line.
351 -- For "bad" 'SrcSpan', it returns False
352 isOneLineSpan (RealSrcSpan s) = srcSpanStartLine s == srcSpanEndLine s
353 isOneLineSpan (UnhelpfulSpan _) = False
354
355 -- | Tests whether the first span "contains" the other span, meaning
356 -- that it covers at least as much source code. True where spans are equal.
357 containsSpan :: RealSrcSpan -> RealSrcSpan -> Bool
358 containsSpan s1 s2
359 = (srcSpanStartLine s1, srcSpanStartCol s1)
360 <= (srcSpanStartLine s2, srcSpanStartCol s2)
361 && (srcSpanEndLine s1, srcSpanEndCol s1)
362 >= (srcSpanEndLine s2, srcSpanEndCol s2)
363 && (srcSpanFile s1 == srcSpanFile s2)
364 -- We check file equality last because it is (presumably?) least
365 -- likely to fail.
366 {-
367 %************************************************************************
368 %* *
369 \subsection[SrcSpan-unsafe-access-fns]{Unsafe access functions}
370 * *
371 ************************************************************************
372 -}
373
374 srcSpanStartLine :: RealSrcSpan -> Int
375 srcSpanEndLine :: RealSrcSpan -> Int
376 srcSpanStartCol :: RealSrcSpan -> Int
377 srcSpanEndCol :: RealSrcSpan -> Int
378
379 srcSpanStartLine RealSrcSpan'{ srcSpanSLine=l } = l
380 srcSpanEndLine RealSrcSpan'{ srcSpanELine=l } = l
381 srcSpanStartCol RealSrcSpan'{ srcSpanSCol=l } = l
382 srcSpanEndCol RealSrcSpan'{ srcSpanECol=c } = c
383
384 {-
385 ************************************************************************
386 * *
387 \subsection[SrcSpan-access-fns]{Access functions}
388 * *
389 ************************************************************************
390 -}
391
392 -- | Returns the location at the start of the 'SrcSpan' or a "bad" 'SrcSpan' if that is unavailable
393 srcSpanStart :: SrcSpan -> SrcLoc
394 srcSpanStart (UnhelpfulSpan str) = UnhelpfulLoc str
395 srcSpanStart (RealSrcSpan s) = RealSrcLoc (realSrcSpanStart s)
396
397 -- | Returns the location at the end of the 'SrcSpan' or a "bad" 'SrcSpan' if that is unavailable
398 srcSpanEnd :: SrcSpan -> SrcLoc
399 srcSpanEnd (UnhelpfulSpan str) = UnhelpfulLoc str
400 srcSpanEnd (RealSrcSpan s) = RealSrcLoc (realSrcSpanEnd s)
401
402 realSrcSpanStart :: RealSrcSpan -> RealSrcLoc
403 realSrcSpanStart s = mkRealSrcLoc (srcSpanFile s)
404 (srcSpanStartLine s)
405 (srcSpanStartCol s)
406
407 realSrcSpanEnd :: RealSrcSpan -> RealSrcLoc
408 realSrcSpanEnd s = mkRealSrcLoc (srcSpanFile s)
409 (srcSpanEndLine s)
410 (srcSpanEndCol s)
411
412 -- | Obtains the filename for a 'SrcSpan' if it is "good"
413 srcSpanFileName_maybe :: SrcSpan -> Maybe FastString
414 srcSpanFileName_maybe (RealSrcSpan s) = Just (srcSpanFile s)
415 srcSpanFileName_maybe (UnhelpfulSpan _) = Nothing
416
417 {-
418 ************************************************************************
419 * *
420 \subsection[SrcSpan-instances]{Instances}
421 * *
422 ************************************************************************
423 -}
424
425 -- We want to order RealSrcSpans first by the start point, then by the
426 -- end point.
427 instance Ord RealSrcSpan where
428 a `compare` b =
429 (realSrcSpanStart a `compare` realSrcSpanStart b) `thenCmp`
430 (realSrcSpanEnd a `compare` realSrcSpanEnd b)
431
432 instance Show RealSrcLoc where
433 show (SrcLoc filename row col)
434 = "SrcLoc " ++ show filename ++ " " ++ show row ++ " " ++ show col
435
436 -- Show is used by Lexer.x, because we derive Show for Token
437 instance Show RealSrcSpan where
438 show span@(RealSrcSpan' file sl sc el ec)
439 | isPointRealSpan span
440 = "SrcSpanPoint " ++ show file ++ " " ++ intercalate " " (map show [sl,sc])
441
442 | isOneLineRealSpan span
443 = "SrcSpanOneLine " ++ show file ++ " "
444 ++ intercalate " " (map show [sl,sc,ec])
445
446 | otherwise
447 = "SrcSpanMultiLine " ++ show file ++ " "
448 ++ intercalate " " (map show [sl,sc,el,ec])
449
450
451 instance Outputable RealSrcSpan where
452 ppr span = pprUserRealSpan True span
453
454 -- I don't know why there is this style-based difference
455 -- = getPprStyle $ \ sty ->
456 -- if userStyle sty || debugStyle sty then
457 -- text (showUserRealSpan True span)
458 -- else
459 -- hcat [text "{-# LINE ", int (srcSpanStartLine span), space,
460 -- char '\"', pprFastFilePath $ srcSpanFile span, text " #-}"]
461
462 instance Outputable SrcSpan where
463 ppr span = pprUserSpan True span
464
465 -- I don't know why there is this style-based difference
466 -- = getPprStyle $ \ sty ->
467 -- if userStyle sty || debugStyle sty then
468 -- pprUserSpan True span
469 -- else
470 -- case span of
471 -- UnhelpfulSpan _ -> panic "Outputable UnhelpfulSpan"
472 -- RealSrcSpan s -> ppr s
473
474 pprUserSpan :: Bool -> SrcSpan -> SDoc
475 pprUserSpan _ (UnhelpfulSpan s) = ftext s
476 pprUserSpan show_path (RealSrcSpan s) = pprUserRealSpan show_path s
477
478 pprUserRealSpan :: Bool -> RealSrcSpan -> SDoc
479 pprUserRealSpan show_path span@(RealSrcSpan' src_path line col _ _)
480 | isPointRealSpan span
481 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
482 , int line <> colon
483 , int col ]
484
485 pprUserRealSpan show_path span@(RealSrcSpan' src_path line scol _ ecol)
486 | isOneLineRealSpan span
487 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
488 , int line <> colon
489 , int scol
490 , ppUnless (ecol - scol <= 1) (char '-' <> int (ecol - 1)) ]
491 -- For single-character or point spans, we just
492 -- output the starting column number
493
494 pprUserRealSpan show_path (RealSrcSpan' src_path sline scol eline ecol)
495 = hcat [ ppWhen show_path (pprFastFilePath src_path <> colon)
496 , parens (int sline <> comma <> int scol)
497 , char '-'
498 , parens (int eline <> comma <> int ecol') ]
499 where
500 ecol' = if ecol == 0 then ecol else ecol - 1
501
502 {-
503 ************************************************************************
504 * *
505 \subsection[Located]{Attaching SrcSpans to things}
506 * *
507 ************************************************************************
508 -}
509
510 -- | We attach SrcSpans to lots of things, so let's have a datatype for it.
511 data GenLocated l e = L l e
512 deriving (Eq, Ord, Data, Functor, Foldable, Traversable)
513
514 type Located e = GenLocated SrcSpan e
515 type RealLocated e = GenLocated RealSrcSpan e
516
517 unLoc :: GenLocated l e -> e
518 unLoc (L _ e) = e
519
520 getLoc :: GenLocated l e -> l
521 getLoc (L l _) = l
522
523 noLoc :: e -> Located e
524 noLoc e = L noSrcSpan e
525
526 mkGeneralLocated :: String -> e -> Located e
527 mkGeneralLocated s e = L (mkGeneralSrcSpan (fsLit s)) e
528
529 combineLocs :: Located a -> Located b -> SrcSpan
530 combineLocs a b = combineSrcSpans (getLoc a) (getLoc b)
531
532 -- | Combine locations from two 'Located' things and add them to a third thing
533 addCLoc :: Located a -> Located b -> c -> Located c
534 addCLoc a b c = L (combineSrcSpans (getLoc a) (getLoc b)) c
535
536 -- not clear whether to add a general Eq instance, but this is useful sometimes:
537
538 -- | Tests whether the two located things are equal
539 eqLocated :: Eq a => Located a -> Located a -> Bool
540 eqLocated a b = unLoc a == unLoc b
541
542 -- not clear whether to add a general Ord instance, but this is useful sometimes:
543
544 -- | Tests the ordering of the two located things
545 cmpLocated :: Ord a => Located a -> Located a -> Ordering
546 cmpLocated a b = unLoc a `compare` unLoc b
547
548 instance (Outputable l, Outputable e) => Outputable (GenLocated l e) where
549 ppr (L l e) = -- TODO: We can't do this since Located was refactored into
550 -- GenLocated:
551 -- Print spans without the file name etc
552 -- ifPprDebug (braces (pprUserSpan False l))
553 whenPprDebug (braces (ppr l))
554 $$ ppr e
555
556 {-
557 ************************************************************************
558 * *
559 \subsection{Ordering SrcSpans for InteractiveUI}
560 * *
561 ************************************************************************
562 -}
563
564 -- | Alternative strategies for ordering 'SrcSpan's
565 leftmost_smallest, leftmost_largest, rightmost :: SrcSpan -> SrcSpan -> Ordering
566 rightmost = flip compare
567 leftmost_smallest = compare
568 leftmost_largest a b = (srcSpanStart a `compare` srcSpanStart b)
569 `thenCmp`
570 (srcSpanEnd b `compare` srcSpanEnd a)
571
572 -- | Determines whether a span encloses a given line and column index
573 spans :: SrcSpan -> (Int, Int) -> Bool
574 spans (UnhelpfulSpan _) _ = panic "spans UnhelpfulSpan"
575 spans (RealSrcSpan span) (l,c) = realSrcSpanStart span <= loc && loc <= realSrcSpanEnd span
576 where loc = mkRealSrcLoc (srcSpanFile span) l c
577
578 -- | Determines whether a span is enclosed by another one
579 isSubspanOf :: SrcSpan -- ^ The span that may be enclosed by the other
580 -> SrcSpan -- ^ The span it may be enclosed by
581 -> Bool
582 isSubspanOf src parent
583 | srcSpanFileName_maybe parent /= srcSpanFileName_maybe src = False
584 | otherwise = srcSpanStart parent <= srcSpanStart src &&
585 srcSpanEnd parent >= srcSpanEnd src