@@ -14,9 +14,8 @@ import qualified CmdLineParser as GHC
14import Control.Exception
14import Control.Exception
15import Control.Monad
15import Control.Monad
16import Control.Monad.IO.Class
16import Control.Monad.IO.Class
17−import Data.List ((\\), foldl', isPrefixOf, sortOn)
17+import qualified Data.List as L
18import qualified Data.List.NonEmpty as NE
18import qualified Data.List.NonEmpty as NE
19−import Data.Maybe (catMaybes)
20import Data.Ord (Down (Down))
19import Data.Ord (Down (Down))
21import DynFlags as GHC
20import DynFlags as GHC
22import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
21import ErrUtils (Severity (..), errMsgSeverity, errMsgSpan)
@@ -32,7 +31,7 @@ import Ormolu.Exception
32import Ormolu.Parser.Anns
31import Ormolu.Parser.Anns
33import Ormolu.Parser.CommentStream
32import Ormolu.Parser.CommentStream
34import Ormolu.Parser.Result
33import Ormolu.Parser.Result
35−import Ormolu.Parser.Shebang
34+import Ormolu.Processing.Preprocess (preprocess)
36import qualified Panic as GHC
35import qualified Panic as GHC
37import qualified Parser as GHC
36import qualified Parser as GHC
38import qualified StringBuffer as GHC
37import qualified StringBuffer as GHC
@@ -51,7 +50,7 @@ parseModule ::
51 Either (SrcSpan, String) ParseResult
50 Either (SrcSpan, String) ParseResult
53parseModule Config {..} path input' = liftIO $ do
52parseModule Config {..} path input' = liftIO $ do
54− let (input, extraComments) = extractCommentsFromLines path input'
53+ let (input, extraComments) = preprocess path input'
55 -- It's important that 'setDefaultExts' is done before
54 -- It's important that 'setDefaultExts' is done before
56 -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
55 -- 'parsePragmasIntoDynFlags', because otherwise we might enable an
57 -- extension that was explicitly disabled in the file.
56 -- extension that was explicitly disabled in the file.
@@ -78,7 +77,7 @@ parseModule Config {..} path input' = liftIO $ do
78 (pluginModNames dynFlags)
77 (pluginModNames dynFlags)
79 pStateErrors = \pstate ->
78 pStateErrors = \pstate ->
80 let errs = bagToList $ GHC.getErrorMessages pstate dynFlags
79 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
82 [] -> Nothing
81 [] -> Nothing
83 err : _ -> Just (errMsgSpan err, show err) -- Show instance returns a short error message
82 err : _ -> Just (errMsgSpan err, show err) -- Show instance returns a short error message
84 r = case runParser GHC.parseModule dynFlags path input of
83 r = case runParser GHC.parseModule dynFlags path input of
@@ -110,6 +109,14 @@ parseModule Config {..} path input' = liftIO $ do
111 return (warnings, r)
110 return (warnings, r)
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
117+ autoExts = allExts L.\\ manualExts
118+ allExts = [minBound .. maxBound]
113-- | Extensions that are not enabled automatically and should be activated
120-- | Extensions that are not enabled automatically and should be activated
114-- by user.
121-- by user.
115manualExts :: [Extension]
122manualExts :: [Extension]
@@ -136,9 +143,6 @@ manualExts =
136 -- decision of enabling this style is left to the user
143 -- decision of enabling this style is left to the user
139−----------------------------------------------------------------------------
140−-- Helpers (taken from ghc-exactprint)
142-- | Run a 'GHC.P' computation.
146-- | Run a 'GHC.P' computation.
143runParser ::
147runParser ::
144 -- | Computation to run
148 -- | Computation to run
@@ -157,67 +161,27 @@ runParser parser flags filename input = GHC.unP parser parseState
157 buffer = GHC.stringToStringBuffer input
161 buffer = GHC.stringToStringBuffer input
158 parseState = GHC.mkPState flags buffer location
162 parseState = GHC.mkPState flags buffer location
160−-- | Transform given input possibly returning comments extracted from it.
164+-- | Wrap GHC's 'Severity' to add 'Ord' instance.
161−-- This handles LINE pragmas and shebangs.
165+newtype SeverityOrd = SeverityOrd Severity
162−extractCommentsFromLines ::
163− -- | File name, just to use in the spans
165− -- | Contents of that file
167− -- | Adjusted input with comments extracted from it
168− (String, [Located String])
169−extractCommentsFromLines path =
170− unlines' . unzip . zipWith (extractCommentFromLine path) [1 ..] . lines
172− unlines' (a, b) = (unlines a, catMaybes b)
174−-- | Transform a given line possibly returning a comment extracted from it.
175−extractCommentFromLine ::
176− -- | File name, just to use in the spans
178− -- | Line number of this line
180− -- | The actual line
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)
191− let ss = mkSrcSpan (mkSrcLoc' 1) (mkSrcLoc' (length s))
192− in ("", Just $ L ss s)
193− | otherwise = (s, Nothing)
195− mkSrcLoc' = mkSrcLoc (GHC.mkFastString path) line
197−-- | Take a line pragma and output its replacement (where line pragma is
167+instance Eq SeverityOrd where
198−-- replaced with spaces) and the contents of the pragma itself.
168+ s1 == s2 = compare s1 s2 == EQ
200− -- | Pragma line to analyze
202− -- | Contents of the pragma and its replacement line
204−getPragma [] = error "Ormolu.Parser.getPragma: input must not be empty"
206− | "#-}" `isPrefixOf` s = ("#-}", " " ++ drop 3 s)
208− let (prag, remline) = getPragma xs
209− in (x : prag, ' ' : remline)
211−-- | Enable all language extensions that we think should be enabled by
170+instance Ord SeverityOrd where
212−-- default for ease of use.
171+ compare (SeverityOrd s1) (SeverityOrd s2) =
213−setDefaultExts :: DynFlags -> DynFlags
172+ compare (f s1) (f s2)
214−setDefaultExts flags = foldl' GHC.xopt_set flags autoExts
173+ where
215− where
174+ f :: Severity -> Int
216− autoExts = allExts \\ manualExts
175+ f SevOutput = 1
217− allExts = [minBound .. maxBound]
176+ f SevFatal = 2
177+ f SevInteractive = 3
219----------------------------------------------------------------------------
183----------------------------------------------------------------------------
220−-- More helpers (taken from HLint)
184+-- Helpers taken from HLint
222parsePragmasIntoDynFlags ::
186parsePragmasIntoDynFlags ::
223 -- | Pre-set 'DynFlags'
187 -- | Pre-set 'DynFlags'
@@ -246,25 +210,3 @@ parsePragmasIntoDynFlags flags extraOpts filepath str =
246 reportErr
210 reportErr
247 (GHC.handleSourceError reportErr act)
211 (GHC.handleSourceError reportErr act)
248 reportErr e = return $ Left (show e)
212 reportErr e = return $ Left (show e)
250−----------------------------------------------------------------------------
253−-- Wrap GHC's ErrUtils.Severity to add Ord instance
254−newtype SeverityOrd = SeverityOrd Severity
256−instance Eq SeverityOrd where
257− s1 == s2 = compare s1 s2 == EQ
259−instance Ord SeverityOrd where
260− compare (SeverityOrd s1) (SeverityOrd s2) =
261− compare (f s1) (f s2)
263− f :: Severity -> Int
266− f SevInteractive = 3