@@ -1,24 +1,32 @@
1+{-# LANGUAGE BangPatterns #-}
12{-# LANGUAGE DeriveDataTypeable #-}
23{-# LANGUAGE GeneralizedNewtypeDeriving #-}
34{-# LANGUAGE LambdaCase #-}
5+{-# LANGUAGE TupleSections #-}
46
57-- | Functions for working with comment stream.
68
7−module Ormolu.CommentStream
9+module Ormolu.Parser.CommentStream
810 ( CommentStream (..)
911 , Comment (..)
1012 , mkCommentStream
1113 , isPrevHaddock
14+ , showCommentStream
1215 )
1316where
1417
1518import Data.Char (isSpace)
1619import Data.Data (Data)
20+import Data.Either (partitionEithers)
1721import Data.List (isPrefixOf, sortOn)
1822import Data.List.NonEmpty (NonEmpty (..))
1923import Data.Maybe (mapMaybe)
24+import Data.Set (Set)
25+import Ormolu.Parser.LanguagePragma
26+import Ormolu.Utils (showOutputable)
2027import SrcLoc
2128import qualified Data.List.NonEmpty as NE
29+import qualified Data.Set as S
2230import qualified GHC
2331import qualified Lexer as GHC
2432
@@ -34,28 +42,31 @@ newtype CommentStream = CommentStream [RealLocated Comment]
3442newtype Comment = Comment (NonEmpty String)
3543 deriving (Eq, Show, Data)
3644
37−-- | Create 'CommentStream' from 'GHC.PState'.
45+-- | Create 'CommentStream' from 'GHC.PState'. We also create a 'Set' of
46+-- extensions here, which is not sorted in any way. The pragma comment are
47+-- removed from the 'CommentStream'.
3848
3949mkCommentStream
4050 :: [Located String] -- ^ Extra comments to include
4151 -> GHC.PState -- ^ Parser state to use for comment extraction
42− -> CommentStream
43−mkCommentStream extraComments pstate
44− = CommentStream
45− -- NOTE It's easier to normalize pragmas right when we construct comment
46− -- streams. Because this way we need to do it only once and when we
47− -- perform checking later they'll automatically match.
48− . fmap (mkComment . (fmap normalizePragma))
49− . sortOn startOfSpan
50− . mapMaybe toRealSpan $
52+ -> (CommentStream, Set String)
53+ -- ^ Comment stream and a set of extensions enabled
54+mkCommentStream extraComments pstate =
55+ ( CommentStream $
56+ -- NOTE It's easier to normalize pragmas right when we construct comment
57+ -- streams. Because this way we need to do it only once and when we
58+ -- perform checking later they'll automatically match.
59+ mkComment . fmap normalizePragma
60+ <$> sortOn (realSrcSpanStart . getLoc) comments
61+ , S.unions exts
62+ )
63+ where
64+ (comments, exts) = partitionEithers (partitionComments <$> rawComments)
65+ rawComments = mapMaybe toRealSpan $
5166 extraComments ++
5267 (fmap unAnnotationComment <$> GHC.comment_q pstate) ++
5368 concatMap (fmap (fmap unAnnotationComment) . snd)
5469 (GHC.annotations_comments pstate)
55− where
56− startOfSpan (L l _) = realSrcSpanStart l
57− toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
58− toRealSpan _ = Nothing
5970
6071-- | Test whether a 'Comment' looks like a Haddock following a definition,
6172-- i.e. something starting with @-- ^@.
@@ -63,6 +74,14 @@ mkCommentStream extraComments pstate
6374isPrevHaddock :: Comment -> Bool
6475isPrevHaddock (Comment (x :| _)) = "-- ^" `isPrefixOf` x
6576
77+-- | Pretty-print a 'CommentStream'.
78+
79+showCommentStream :: CommentStream -> String
80+showCommentStream (CommentStream xs) = unlines $
81+ showComment <$> xs
82+ where
83+ showComment (GHC.L l str) = showOutputable l ++ " " ++ show str
84+
6685----------------------------------------------------------------------------
6786-- Helpers
6887
@@ -105,3 +124,18 @@ unAnnotationComment = \case
105124 GHC.AnnDocOptions s -> s
106125 GHC.AnnLineComment s -> s
107126 GHC.AnnBlockComment s -> s
127+
128+toRealSpan :: Located a -> Maybe (RealLocated a)
129+toRealSpan (L (RealSrcSpan l) a) = Just (L l a)
130+toRealSpan _ = Nothing
131+
132+-- | If a given comment is a LANGUAGE pragma, return the set of extensions
133+-- it enables in 'Right'. Otherwise return the original comment unchanged.
134+
135+partitionComments
136+ :: RealLocated String
137+ -> Either (RealLocated String) (Set String)
138+partitionComments input =
139+ case parseLanguagePragma (unLoc input) of
140+ Nothing -> Left input
141+ Just exts -> Right exts