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