Add gql quasi quoter

This commit is contained in:
2024-10-20 17:13:39 +02:00
parent ce5fa260f4
commit d280cd835f
4 changed files with 57 additions and 1 deletions

View File

@ -13,6 +13,7 @@ module Language.GraphQL.Class
, ToGraphQL(..)
, deriveFromGraphQL
, deriveToGraphQL
, gql
) where
import Data.Int (Int8, Int16, Int32, Int64)
@ -45,6 +46,7 @@ import Language.Haskell.TH
, Dec(..)
, Exp(..)
, Info(..)
, Lit(..)
, Quote(..)
, Name
, Q
@ -72,6 +74,7 @@ import Language.Haskell.TH
, litP
, wildP
)
import Language.Haskell.TH.Quote (QuasiQuoter(..))
import Data.Foldable (Foldable(..))
import qualified Data.HashMap.Strict as HashMap
import qualified Language.GraphQL.Type as Type
@ -438,3 +441,39 @@ deriveToGraphQL typeName = do
[ litE (stringL $ nameBase name')
, [|toGraphQL $(varE alias)|]
]
stripIndentation :: String -> String
stripIndentation code = reverse
$ dropWhile isLineBreak
$ reverse
$ unlines
$ indent spaces <$> lines' withoutLeadingNewlines
where
indent 0 xs = xs
indent count (' ' : xs) = indent (count - 1) xs
indent _ xs = xs
withoutLeadingNewlines = dropWhile isLineBreak code
spaces = length $ takeWhile (== ' ') withoutLeadingNewlines
lines' "" = []
lines' string =
let (line, rest) = break isLineBreak string
reminder =
case rest of
[] -> []
'\r' : '\n' : strippedString -> lines' strippedString
_ : strippedString -> lines' strippedString
in line : reminder
isLineBreak = flip any ['\n', '\r'] . (==)
-- | Removes leading and trailing newlines. Indentation of the first line is
-- removed from each line of the string.
gql :: QuasiQuoter
gql = QuasiQuoter
{ quoteExp = pure . LitE . StringL . stripIndentation
, quotePat = const
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a pattern)"
, quoteType = const
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a type)"
, quoteDec = const
$ fail "Illegal gql QuasiQuote (allowed as expression only, used as a declaration)"
}