@@ -49,7 +49,7 @@ parseModule ::
49 Either (SrcSpan, String) ParseResult
49 Either (SrcSpan, String) ParseResult
51parseModule Config {..} path input' = liftIO $ do
51parseModule Config {..} path input' = liftIO $ do
52− let (input, extraComments) = stripLinePragmas path input'
52+ let (input, extraComments) = extractCommentsFromLines path input'
53 -- NOTE It's important that 'setDefaultExts' is done before
53 -- NOTE It's important that 'setDefaultExts' is done before
54 -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
54 -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
55 -- extension that was explicitly disabled in the file.
55 -- extension that was explicitly disabled in the file.
@@ -73,12 +73,13 @@ parseModule Config {..} path input' = liftIO $ do
73 GHC.PFailed _ ss m ->
73 GHC.PFailed _ ss m ->
74 Left (ss, GHC.showSDoc dynFlags m)
74 Left (ss, GHC.showSDoc dynFlags m)
75 GHC.POk pstate pmod ->
75 GHC.POk pstate pmod ->
76− let (comments, exts) = mkCommentStream extraComments pstate
76+ let (comments, exts, shebangs) = mkCommentStream extraComments pstate
77 in Right ParseResult
77 in Right ParseResult
78 { prParsedSource = pmod,
78 { prParsedSource = pmod,
79 prAnns = mkAnns pstate,
79 prAnns = mkAnns pstate,
80 prCommentStream = comments,
80 prCommentStream = comments,
81− prExtensions = exts
81+ prExtensions = exts,
82+ prShebangs = shebangs
83 return (warnings, r)
84 return (warnings, r)
@@ -127,18 +128,31 @@ runParser parser flags filename input = GHC.unP parser parseState
127 buffer = GHC.stringToStringBuffer input
128 buffer = GHC.stringToStringBuffer input
128 parseState = GHC.mkPState flags buffer location
129 parseState = GHC.mkPState flags buffer location
130−-- | Remove GHC style line pragams (@{-# LINE .. #-}@) and convert them into
131+-- | Transform given lines possibly returning comments extracted from them.
131−-- comments.
132+-- This handles LINE pragmas and shebangs.
133+extractCommentsFromLines ::
134+ -- | File name, just to use in the spans
136+ -- | List of lines from that file
138+ -- | Adjusted lines together with comments extracted from them
132−stripLinePragmas :: FilePath -> String -> (String, [Located String])
139+ (String, [Located String])
140+extractCommentsFromLines path =
133−stripLinePragmas path = unlines' . unzip . findLines path . lines
141+ unlines' . unzip . zipWith (extractCommentFromLine path) [1 ..] . lines
135 unlines' (a, b) = (unlines a, catMaybes b)
143 unlines' (a, b) = (unlines a, catMaybes b)
137−findLines :: FilePath -> [String] -> [(String, Maybe (Located String))]
145+-- | Transform a given line possibly returning a comment extracted from it.
138−findLines path = zipWith (checkLine path) [1 ..]
146+extractCommentFromLine ::
139−
147+ -- | File name, just to use in the spans
149+ -- | Line number of this line
151+ -- | The actual line
153+ -- | Adjusted line and possibly a comment extracted from it
140−checkLine :: FilePath -> Int -> String -> (String, Maybe (Located String))
154+ (String, Maybe (Located String))
141−checkLine path line s
155+extractCommentFromLine path line s
142 | "{-# LINE" `isPrefixOf` s =
156 | "{-# LINE" `isPrefixOf` s =
143 let (pragma, res) = getPragma s
157 let (pragma, res) = getPragma s
144 size = length pragma
158 size = length pragma
@@ -151,7 +165,13 @@ checkLine path line s
152 mkSrcLoc' = mkSrcLoc (GHC.mkFastString path) line
166 mkSrcLoc' = mkSrcLoc (GHC.mkFastString path) line
168+-- | Take a line pragma and output its replacement (where line pragma is
169+-- replaced with spaces) and the contents of the pragma itself.
171+ -- | Pragma line to analyze
173+ -- | Contents of the pragma and its replacement line
154−getPragma :: String -> (String, String)
174+ (String, String)
155getPragma [] = error "Ormolu.Parser.getPragma: input must not be empty"
175getPragma [] = error "Ormolu.Parser.getPragma: input must not be empty"
156getPragma s@(x : xs)
176getPragma s@(x : xs)
157 | "#-}" `isPrefixOf` s = ("#-}", " " ++ drop 3 s)
177 | "#-}" `isPrefixOf` s = ("#-}", " " ++ drop 3 s)