@@ -7,7 +7,6 @@ module Ormolu.Parser.CommentStream
7 ( CommentStream (..),
7 ( CommentStream (..),
8 Comment (..),
8 Comment (..),
9 mkCommentStream,
9 mkCommentStream,
11 isPrevHaddock,
10 isPrevHaddock,
12 isMultilineComment,
11 isMultilineComment,
13 showCommentStream,
12 showCommentStream,
@@ -16,14 +15,14 @@ where
17import Data.Char (isSpace)
16import Data.Char (isSpace)
18import Data.Data (Data)
17import Data.Data (Data)
19−import Data.Either (partitionEithers)
18+import qualified Data.List as L
20−import Data.List (dropWhileEnd, isPrefixOf, sortOn)
21import Data.List.NonEmpty (NonEmpty (..))
19import Data.List.NonEmpty (NonEmpty (..))
22import qualified Data.List.NonEmpty as NE
20import qualified Data.List.NonEmpty as NE
23import Data.Maybe (mapMaybe)
21import Data.Maybe (mapMaybe)
24import qualified GHC
22import qualified GHC
25import qualified Lexer as GHC
23import qualified Lexer as GHC
26import Ormolu.Parser.Pragma
24import Ormolu.Parser.Pragma
25+import Ormolu.Parser.Shebang
27import Ormolu.Utils (showOutputable)
26import Ormolu.Utils (showOutputable)
28import SrcLoc
27import SrcLoc
@@ -45,37 +44,38 @@ mkCommentStream ::
45 [Located String] ->
44 [Located String] ->
46 -- | Parser state to use for comment extraction
45 -- | Parser state to use for comment extraction
47 GHC.PState ->
46 GHC.PState ->
48− -- | Comment stream, a set of extracted pragmas, and extracted shebangs
47+ -- | Stack header, shebangs, pragmas, and comment stream
48+ ( Maybe (RealLocated Comment),
50+ [([RealLocated Comment], Pragma)],
49− (CommentStream, [Pragma], [Located String])
51+ CommentStream
50mkCommentStream extraComments pstate =
53mkCommentStream extraComments pstate =
51− ( CommentStream $
54+ ( mstackHeader,
52− mkComment <$> sortOn (realSrcSpanStart . getRealSrcSpan) comments,
55+ shebangs,
54− shebangs
57+ CommentStream comments
57− (comments, pragmas) = partitionEithers (partitionComments <$> rawComments)
60+ (comments, pragmas) = extractPragmas rawComments1
58− rawComments =
61+ (rawComments1, mstackHeader) = extractStackHeader rawComments0
59− mapMaybe toRealSpan $
63+ L.sortOn (realSrcSpanStart . getRealSrcSpan) . mapMaybe toRealSpan $
60 otherExtraComments
64 otherExtraComments
61 ++ mapMaybe (liftMaybe . fmap unAnnotationComment) (GHC.comment_q pstate)
65 ++ mapMaybe (liftMaybe . fmap unAnnotationComment) (GHC.comment_q pstate)
62 ++ concatMap
66 ++ concatMap
63 (mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
67 (mapMaybe (liftMaybe . fmap unAnnotationComment) . snd)
64 (GHC.annotations_comments pstate)
68 (GHC.annotations_comments pstate)
65− (shebangs, otherExtraComments) = span (isShebang . unLoc) extraComments
69+ (shebangs, otherExtraComments) = extractShebangs extraComments
67−-- | Return 'True' if given 'String' is a shebang.
68−isShebang :: String -> Bool
69−isShebang str = "#!" `isPrefixOf` str
71-- | Test whether a 'Comment' looks like a Haddock following a definition,
71-- | Test whether a 'Comment' looks like a Haddock following a definition,
72-- i.e. something starting with @-- ^@.
72-- i.e. something starting with @-- ^@.
73isPrevHaddock :: Comment -> Bool
73isPrevHaddock :: Comment -> Bool
74−isPrevHaddock (Comment (x :| _)) = "-- ^" `isPrefixOf` x
74+isPrevHaddock (Comment (x :| _)) = "-- ^" `L.isPrefixOf` x
76-- | Is this comment multiline-style?
76-- | Is this comment multiline-style?
77isMultilineComment :: Comment -> Bool
77isMultilineComment :: Comment -> Bool
78−isMultilineComment (Comment (x :| _)) = "{-" `isPrefixOf` x
78+isMultilineComment (Comment (x :| _)) = "{-" `L.isPrefixOf` x
80-- | Pretty-print a 'CommentStream'.
80-- | Pretty-print a 'CommentStream'.
81showCommentStream :: CommentStream -> String
81showCommentStream :: CommentStream -> String
@@ -94,7 +94,7 @@ showCommentStream (CommentStream xs) =
94mkComment :: RealLocated String -> RealLocated Comment
94mkComment :: RealLocated String -> RealLocated Comment
95mkComment (L l s) =
95mkComment (L l s) =
96 L l . Comment . fmap dropTrailing $
96 L l . Comment . fmap dropTrailing $
97− if "{-" `isPrefixOf` s
97+ if "{-" `L.isPrefixOf` s
98 then case NE.nonEmpty (lines s) of
98 then case NE.nonEmpty (lines s) of
99 Nothing -> s :| []
99 Nothing -> s :| []
100 Just (x :| xs) ->
100 Just (x :| xs) ->
@@ -106,7 +106,7 @@ mkComment (L l s) =
106 in x :| (drop n <$> xs)
106 in x :| (drop n <$> xs)
107 else s :| []
107 else s :| []
109− dropTrailing = dropWhileEnd isSpace
109+ dropTrailing = L.dropWhileEnd isSpace
110 startIndent = srcSpanStartCol l - 1
110 startIndent = srcSpanStartCol l - 1
112-- | Get a 'String' from 'GHC.AnnotationComment'.
112-- | Get a 'String' from 'GHC.AnnotationComment'.
@@ -129,12 +129,32 @@ toRealSpan :: Located a -> Maybe (RealLocated a)
129toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
129toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
130toRealSpan _ = Nothing
130toRealSpan _ = Nothing
132−-- | If a given comment is a pragma, return it in parsed form in 'Right'.
132+-- | Detect and extract stack header if it is present.
133−-- Otherwise return the original comment unchanged.
133+extractStackHeader ::
134−partitionComments ::
134+ [RealLocated String] ->
135+ ([RealLocated String], Maybe (RealLocated Comment))
136+extractStackHeader = \case
139+ let comment = mkComment x
140+ in if isStackHeader (unRealSrcSpan comment)
141+ then (xs, Just comment)
142+ else (x : xs, Nothing)
144+ isStackHeader (Comment (x :| _)) =
145+ "stack" `L.isPrefixOf` dropWhile isSpace (drop 2 x)
147+-- | Extract pragmas and their associated comments.
135− RealLocated String ->
149+ [RealLocated String] ->
136− Either (RealLocated String) Pragma
150+ ([RealLocated Comment], [([RealLocated Comment], Pragma)])
137−partitionComments input =
151+extractPragmas = go id id
153+ go csSoFar pragmasSoFar = \case
154+ [] -> (csSoFar [], pragmasSoFar [])
138− case parsePragma (unRealSrcSpan input) of
156+ case parsePragma (unRealSrcSpan x) of
139− Nothing -> Left input
157+ Nothing -> go (csSoFar . (mkComment x :)) pragmasSoFar xs
140− Just pragma -> Right pragma
158+ Just pragma ->
159+ let combined = (csSoFar [], pragma)
160+ in go id (pragmasSoFar . (combined :)) xs