@@ -14,9 +14,8 @@ import qualified CmdLineParser as GHC
1414import Control.Exception
1515import Control.Monad
1616import Control.Monad.IO.Class
17−import Data.List ((\\), foldl', isPrefixOf, sortOn)
17+import qualified Data.List as L
1818import qualified Data.List.NonEmpty as NE
19−import Data.Maybe (catMaybes)
2019import Data.Ord (Down (Down))
2120import DynFlags as GHC
2221import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
@@ -32,7 +31,7 @@ import Ormolu.Exception
3231import Ormolu.Parser.Anns
3332import Ormolu.Parser.CommentStream
3433import Ormolu.Parser.Result
35−import Ormolu.Parser.Shebang
34+import Ormolu.Processing.Preprocess (preprocess)
3635import qualified Panic as GHC
3736import qualified Parser as GHC
3837import qualified StringBuffer as GHC
@@ -51,7 +50,7 @@ parseModule ::
5150 Either (SrcSpan, String) ParseResult
5251 )
5352parseModule Config {..} path input' = liftIO $ do
54− let (input, extraComments) = extractCommentsFromLines path input'
53+ let (input, extraComments) = preprocess path input'
5554 -- It's important that 'setDefaultExts' is done before
5655 -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
5756 -- extension that was explicitly disabled in the file.
@@ -78,7 +77,7 @@ parseModule Config {..} path input' = liftIO $ do
7877 (pluginModNames dynFlags)
7978 pStateErrors = \pstate ->
8079 let errs = bagToList $ GHC.getErrorMessages pstate dynFlags
81− in case sortOn (Down . SeverityOrd . errMsgSeverity) errs of
80+ in case L.sortOn (Down . SeverityOrd . errMsgSeverity) errs of
8281 [] -> Nothing
8382 err : _ -> Just (errMsgSpan err, show err) -- Show instance returns a short error message
8483 r = case runParser GHC.parseModule dynFlags path input of
@@ -110,6 +109,14 @@ parseModule Config {..} path input' = liftIO $ do
110109 }
111110 return (warnings, r)
112111
112+-- | Enable all language extensions that we think should be enabled by
113+-- default for ease of use.
114+setDefaultExts :: DynFlags -> DynFlags
115+setDefaultExts flags = L.foldl' xopt_set flags autoExts
116+ where
117+ autoExts = allExts L.\\ manualExts
118+ allExts = [minBound .. maxBound]
119+
113120-- | Extensions that are not enabled automatically and should be activated
114121-- by user.
115122manualExts :: [Extension]
@@ -136,9 +143,6 @@ manualExts =
136143 -- decision of enabling this style is left to the user
137144 ]
138145
139−----------------------------------------------------------------------------
140−-- Helpers (taken from ghc-exactprint)
141−
142146-- | Run a 'GHC.P' computation.
143147runParser ::
144148 -- | Computation to run
@@ -157,67 +161,27 @@ runParser parser flags filename input = GHC.unP parser parseState
157161 buffer = GHC.stringToStringBuffer input
158162 parseState = GHC.mkPState flags buffer location
159163
160−-- | Transform given input possibly returning comments extracted from it.
161−-- This handles LINE pragmas and shebangs.
162−extractCommentsFromLines ::
163− -- | File name, just to use in the spans
164− FilePath ->
165− -- | Contents of that file
166− String ->
167− -- | Adjusted input with comments extracted from it
168− (String, [Located String])
169−extractCommentsFromLines path =
170− unlines' . unzip . zipWith (extractCommentFromLine path) [1 ..] . lines
171− where
172− unlines' (a, b) = (unlines a, catMaybes b)
173−
174−-- | Transform a given line possibly returning a comment extracted from it.
175−extractCommentFromLine ::
176− -- | File name, just to use in the spans
177− FilePath ->
178− -- | Line number of this line
179− Int ->
180− -- | The actual line
181− String ->
182− -- | Adjusted line and possibly a comment extracted from it
183− (String, Maybe (Located String))
184−extractCommentFromLine path line s
185− | "{-# LINE" `isPrefixOf` s =
186− let (pragma, res) = getPragma s
187− size = length pragma
188− ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (size + 1))
189− in (res, Just $ L ss pragma)
190− | isShebang s =
191− let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length s))
192− in ("", Just $ L ss s)
193− | otherwise = (s, Nothing)
194− where
195− mkSrcLoc' = mkSrcLoc (GHC.mkFastString path) line
164+-- | Wrap GHC's 'Severity' to add 'Ord' instance.
165+newtype SeverityOrd = SeverityOrd Severity
196166
197−-- | Take a line pragma and output its replacement (where line pragma is
198−-- replaced with spaces) and the contents of the pragma itself.
199−getPragma ::
200− -- | Pragma line to analyze
201− String ->
202− -- | Contents of the pragma and its replacement line
203− (String, String)
204−getPragma [] = error "Ormolu.Parser.getPragma: input must not be empty"
205−getPragma s@(x : xs)
206− | "#-}" `isPrefixOf` s = ("#-}", " " ++ drop 3 s)
207− | otherwise =
208− let (prag, remline) = getPragma xs
209− in (x : prag, ' ' : remline)
167+instance Eq SeverityOrd where
168+ s1 == s2 = compare s1 s2 == EQ
210169
211−-- | Enable all language extensions that we think should be enabled by
212−-- default for ease of use.
213−setDefaultExts :: DynFlags -> DynFlags
214−setDefaultExts flags = foldl' GHC.xopt_set flags autoExts
215− where
216− autoExts = allExts \\ manualExts
217− allExts = [minBound .. maxBound]
170+instance Ord SeverityOrd where
171+ compare (SeverityOrd s1) (SeverityOrd s2) =
172+ compare (f s1) (f s2)
173+ where
174+ f :: Severity -> Int
175+ f SevOutput = 1
176+ f SevFatal = 2
177+ f SevInteractive = 3
178+ f SevDump = 4
179+ f SevInfo = 5
180+ f SevWarning = 6
181+ f SevError = 7
218182
219183----------------------------------------------------------------------------
220−-- More helpers (taken from HLint)
184+-- Helpers taken from HLint
221185
222186parsePragmasIntoDynFlags ::
223187 -- | Pre-set 'DynFlags'
@@ -246,25 +210,3 @@ parsePragmasIntoDynFlags flags extraOpts filepath str =
246210 reportErr
247211 (GHC.handleSourceError reportErr act)
248212 reportErr e = return $ Left (show e)
249−
250−----------------------------------------------------------------------------
251−-- Even more helpers
252−
253−-- Wrap GHC's ErrUtils.Severity to add Ord instance
254−newtype SeverityOrd = SeverityOrd Severity
255−
256−instance Eq SeverityOrd where
257− s1 == s2 = compare s1 s2 == EQ
258−
259−instance Ord SeverityOrd where
260− compare (SeverityOrd s1) (SeverityOrd s2) =
261− compare (f s1) (f s2)
262− where
263− f :: Severity -> Int
264− f SevOutput = 1
265− f SevFatal = 2
266− f SevInteractive = 3
267− f SevDump = 4
268− f SevInfo = 5
269− f SevWarning = 6
270− f SevError = 7