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