{-# LANGUAGE CPP #-}
module HIndent.Pragma
( extractPragmasFromCode
, extractPragmaNameAndElement
, pragmaExists
, isPragma
) where
import Data.Bifunctor
import Data.Char
import Data.Generics
import Data.List
import Data.List.Split
import Data.Maybe
import GHC.Hs
import GHC.Parser.Lexer
import HIndent.GhcLibParserWrapper.GHC.Hs
import HIndent.Parse
import Text.Regex.TDFA hiding (empty)
extractPragmasFromCode :: String -> [(String, String)]
=
(String -> Maybe (String, String))
-> [String] -> [(String, String)]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe String -> Maybe (String, String)
extractPragmaNameAndElement ([String] -> [(String, String)])
-> (String -> [String]) -> String -> [(String, String)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Token -> Maybe String) -> [Token] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe Token -> Maybe String
extractBlockComment ([Token] -> [String]) -> (String -> [Token]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HasCallStack => String -> [Token]
String -> [Token]
lexCode
where
extractBlockComment :: Token -> Maybe String
extractBlockComment (ITblockComment String
c PsSpan
_) = String -> Maybe String
forall a. a -> Maybe a
Just String
c
extractBlockComment Token
_ = Maybe String
forall a. Maybe a
Nothing
extractPragmaNameAndElement :: String -> Maybe (String, String)
extractPragmaNameAndElement :: String -> Maybe (String, String)
extractPragmaNameAndElement String
l
| (String
_, String
_, String
_, [String
name, String
element]) <-
Regex -> String -> (String, String, String, [String])
forall regex source target.
RegexContext regex source target =>
regex -> source -> target
match Regex
pragmaRegex String
l :: (String, String, String, [String]) =
(String, String) -> Maybe (String, String)
forall a. a -> Maybe a
Just (String
name, String
element)
extractPragmaNameAndElement String
_ = Maybe (String, String)
forall a. Maybe a
Nothing
isPragma :: EpaCommentTok -> Bool
isPragma :: EpaCommentTok -> Bool
isPragma (EpaBlockComment String
c) = Regex -> String -> Bool
forall regex source target.
RegexContext regex source target =>
regex -> source -> target
match Regex
pragmaRegex String
c
isPragma EpaCommentTok
_ = Bool
False
pragmaRegex :: Regex
pragmaRegex :: Regex
pragmaRegex =
CompOption -> ExecOption -> String -> Regex
forall regex compOpt execOpt source.
RegexMaker regex compOpt execOpt source =>
compOpt -> execOpt -> source -> regex
makeRegexOpts
CompOption
compOption
ExecOption
execOption
String
"^{-#[[:space:]]*([^[:space:]]+)[[:space:]]+([^#]+)#-}"
execOption :: ExecOption
execOption :: ExecOption
execOption = ExecOption {captureGroups :: Bool
captureGroups = Bool
True}
compOption :: CompOption
compOption :: CompOption
compOption =
CompOption
{ caseSensitive :: Bool
caseSensitive = Bool
True
, multiline :: Bool
multiline = Bool
False
, rightAssoc :: Bool
rightAssoc = Bool
True
, newSyntax :: Bool
newSyntax = Bool
True
, lastStarGreedy :: Bool
lastStarGreedy = Bool
True
}
pragmaExists :: HsModule' -> Bool
pragmaExists :: HsModule' -> Bool
pragmaExists = Bool -> Bool
not (Bool -> Bool) -> (HsModule' -> Bool) -> HsModule' -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([String] -> Bool) -> (HsModule' -> [String]) -> HsModule' -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HsModule' -> [String]
collectPragmas
collectPragmas :: HsModule' -> [String]
collectPragmas :: HsModule' -> [String]
collectPragmas =
((String, [String]) -> String) -> [(String, [String])] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((String -> [String] -> String) -> (String, [String]) -> String
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry String -> [String] -> String
constructPragma)
([(String, [String])] -> [String])
-> (HsModule' -> [(String, [String])]) -> HsModule' -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (EpaCommentTok -> Maybe (String, [String]))
-> [EpaCommentTok] -> [(String, [String])]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe EpaCommentTok -> Maybe (String, [String])
extractPragma
([EpaCommentTok] -> [(String, [String])])
-> (HsModule' -> [EpaCommentTok])
-> HsModule'
-> [(String, [String])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (EpaCommentTok -> Bool) -> GenericQ [EpaCommentTok]
forall r. Typeable r => (r -> Bool) -> GenericQ [r]
listify EpaCommentTok -> Bool
isBlockComment
(EpAnn AnnsModule -> [EpaCommentTok])
-> (HsModule' -> EpAnn AnnsModule) -> HsModule' -> [EpaCommentTok]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HsModule' -> EpAnn AnnsModule
getModuleAnn
extractPragma :: EpaCommentTok -> Maybe (String, [String])
(EpaBlockComment String
c) =
(String -> [String]) -> (String, String) -> (String, [String])
forall b c a. (b -> c) -> (a, b) -> (a, c)
forall (p :: * -> * -> *) b c a.
Bifunctor p =>
(b -> c) -> p a b -> p a c
second ((String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> String
strip ([String] -> [String])
-> (String -> [String]) -> String -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String -> [String]
forall a. Eq a => [a] -> [a] -> [[a]]
splitOn String
",") ((String, String) -> (String, [String]))
-> Maybe (String, String) -> Maybe (String, [String])
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> Maybe (String, String)
extractPragmaNameAndElement String
c
where
strip :: String -> String
strip = String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
forall a. [a] -> [a]
reverse (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Char -> Bool) -> String -> String
forall a. (a -> Bool) -> [a] -> [a]
dropWhile Char -> Bool
isSpace
extractPragma EpaCommentTok
_ = Maybe (String, [String])
forall a. Maybe a
Nothing
constructPragma :: String -> [String] -> String
constructPragma :: String -> [String] -> String
constructPragma String
optionOrPragma [String]
xs =
String
"{-# " String -> String -> String
forall a. [a] -> [a] -> [a]
++ (Char -> Char) -> String -> String
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Char -> Char
toUpper String
optionOrPragma String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String -> [String] -> String
forall a. [a] -> [[a]] -> [a]
intercalate String
", " [String]
xs String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
" #-}"
isBlockComment :: EpaCommentTok -> Bool
EpaBlockComment {} = Bool
True
isBlockComment EpaCommentTok
_ = Bool
False