diff options
Diffstat (limited to 'src/Language/GraphQL/AST')
| -rw-r--r-- | src/Language/GraphQL/AST/DirectiveLocation.hs | 2 | ||||
| -rw-r--r-- | src/Language/GraphQL/AST/Document.hs | 8 | ||||
| -rw-r--r-- | src/Language/GraphQL/AST/Encoder.hs | 5 | ||||
| -rw-r--r-- | src/Language/GraphQL/AST/Lexer.hs | 80 | ||||
| -rw-r--r-- | src/Language/GraphQL/AST/Parser.hs | 4 |
5 files changed, 54 insertions, 45 deletions
diff --git a/src/Language/GraphQL/AST/DirectiveLocation.hs b/src/Language/GraphQL/AST/DirectiveLocation.hs index d109666..600f931 100644 --- a/src/Language/GraphQL/AST/DirectiveLocation.hs +++ b/src/Language/GraphQL/AST/DirectiveLocation.hs @@ -1,6 +1,6 @@ {-# LANGUAGE Safe #-} --- | Various parts of a GraphQL document can be annotated with directives. +-- | Various parts of a GraphQL document can be annotated with directives. -- This module describes locations in a document where directives can appear. module Language.GraphQL.AST.DirectiveLocation ( DirectiveLocation(..) diff --git a/src/Language/GraphQL/AST/Document.hs b/src/Language/GraphQL/AST/Document.hs index 66fc246..101cf78 100644 --- a/src/Language/GraphQL/AST/Document.hs +++ b/src/Language/GraphQL/AST/Document.hs @@ -380,7 +380,11 @@ instance Show NonNullType where -- -- Directives begin with "@", can accept arguments, and can be applied to the -- most GraphQL elements, providing additional information. -data Directive = Directive Name [Argument] Location deriving (Eq, Show) +data Directive = Directive + { name :: Name + , arguments :: [Argument] + , location :: Location + } deriving (Eq, Show) -- * Type System @@ -405,7 +409,7 @@ data TypeSystemDefinition = SchemaDefinition [Directive] (NonEmpty OperationTypeDefinition) | TypeDefinition TypeDefinition | DirectiveDefinition - Description Name ArgumentsDefinition (NonEmpty DirectiveLocation) + Description Name ArgumentsDefinition Bool (NonEmpty DirectiveLocation) deriving (Eq, Show) -- ** Type System Extensions diff --git a/src/Language/GraphQL/AST/Encoder.hs b/src/Language/GraphQL/AST/Encoder.hs index 120fb64..a1076e4 100644 --- a/src/Language/GraphQL/AST/Encoder.hs +++ b/src/Language/GraphQL/AST/Encoder.hs @@ -159,11 +159,12 @@ typeSystemDefinition formatter = \case <> optempty (directives formatter) operationDirectives <> bracesList formatter (operationTypeDefinition formatter) (NonEmpty.toList operationTypeDefinitions') Full.TypeDefinition typeDefinition' -> typeDefinition formatter typeDefinition' - Full.DirectiveDefinition description' name' arguments' locations + Full.DirectiveDefinition description' name' arguments' repeatable locations -> description formatter description' <> "@" <> Lazy.Text.fromStrict name' <> argumentsDefinition formatter arguments' + <> (if repeatable then " repeatable" else mempty) <> " on" <> pipeList formatter (directiveLocation <$> locations) @@ -276,7 +277,7 @@ pipeList :: Foldable t => Formatter -> t Lazy.Text -> Lazy.Text pipeList Minified = (" " <>) . Lazy.Text.intercalate " | " . toList pipeList (Pretty _) = Lazy.Text.concat . fmap (("\n" <> indentSymbol <> "| ") <>) - . toList + . toList enumValueDefinition :: Formatter -> Full.EnumValueDefinition -> Lazy.Text enumValueDefinition (Pretty _) enumValue = diff --git a/src/Language/GraphQL/AST/Lexer.hs b/src/Language/GraphQL/AST/Lexer.hs index ab1f36f..62cf4d2 100644 --- a/src/Language/GraphQL/AST/Lexer.hs +++ b/src/Language/GraphQL/AST/Lexer.hs @@ -29,7 +29,8 @@ module Language.GraphQL.AST.Lexer , unicodeBOM ) where -import Control.Applicative (Alternative(..), liftA2) +import Control.Applicative (Alternative(..)) +import qualified Control.Applicative.Combinators.NonEmpty as NonEmpty import Data.Char (chr, digitToInt, isAsciiLower, isAsciiUpper, ord) import Data.Foldable (foldl') import Data.List (dropWhileEnd) @@ -37,22 +38,22 @@ import qualified Data.List.NonEmpty as NonEmpty import Data.List.NonEmpty (NonEmpty(..)) import Data.Proxy (Proxy(..)) import Data.Void (Void) -import Text.Megaparsec ( Parsec - , (<?>) - , between - , chunk - , chunkToTokens - , notFollowedBy - , oneOf - , option - , optional - , satisfy - , sepBy - , skipSome - , takeP - , takeWhile1P - , try - ) +import Text.Megaparsec + ( Parsec + , (<?>) + , between + , chunk + , chunkToTokens + , notFollowedBy + , oneOf + , option + , optional + , satisfy + , skipSome + , takeP + , takeWhile1P + , try + ) import Text.Megaparsec.Char (char, digitChar, space1) import qualified Text.Megaparsec.Char.Lexer as Lexer import Data.Text (Text) @@ -142,12 +143,13 @@ blockString :: Parser T.Text blockString = between "\"\"\"" "\"\"\"" stringValue <* spaceConsumer where stringValue = do - byLine <- sepBy (many blockStringCharacter) lineTerminator - let indentSize = foldr countIndent 0 $ tail byLine - withoutIndent = head byLine : (removeIndent indentSize <$> tail byLine) + byLine <- NonEmpty.sepBy1 (many blockStringCharacter) lineTerminator + let indentSize = foldr countIndent 0 $ NonEmpty.tail byLine + withoutIndent = NonEmpty.head byLine + : (removeIndent indentSize <$> NonEmpty.tail byLine) withoutEmptyLines = liftA2 (.) dropWhile dropWhileEnd removeEmptyLine withoutIndent - return $ T.intercalate "\n" $ T.concat <$> withoutEmptyLines + pure $ T.intercalate "\n" $ T.concat <$> withoutEmptyLines removeEmptyLine [] = True removeEmptyLine [x] = T.null x || isWhiteSpace (T.head x) removeEmptyLine _ = False @@ -180,10 +182,10 @@ name :: Parser T.Text name = do firstLetter <- nameFirstLetter rest <- many $ nameFirstLetter <|> digitChar - _ <- spaceConsumer - return $ TL.toStrict $ TL.cons firstLetter $ TL.pack rest - where - nameFirstLetter = satisfy isAsciiUpper <|> satisfy isAsciiLower <|> char '_' + void spaceConsumer + pure $ TL.toStrict $ TL.cons firstLetter $ TL.pack rest + where + nameFirstLetter = satisfy isAsciiUpper <|> satisfy isAsciiLower <|> char '_' isChunkDelimiter :: Char -> Bool isChunkDelimiter = flip notElem ['"', '\\', '\n', '\r'] @@ -197,25 +199,25 @@ lineTerminator = chunk "\r\n" <|> chunk "\n" <|> chunk "\r" isSourceCharacter :: Char -> Bool isSourceCharacter = isSourceCharacter' . ord where - isSourceCharacter' code = code >= 0x0020 - || code == 0x0009 - || code == 0x000a - || code == 0x000d + isSourceCharacter' code + = code >= 0x0020 + || elem code [0x0009, 0x000a, 0x000d] escapeSequence :: Parser Char escapeSequence = do - _ <- char '\\' + void $ char '\\' escaped <- oneOf ['"', '\\', '/', 'b', 'f', 'n', 'r', 't', 'u'] case escaped of - 'b' -> return '\b' - 'f' -> return '\f' - 'n' -> return '\n' - 'r' -> return '\r' - 't' -> return '\t' - 'u' -> chr . foldl' step 0 - . chunkToTokens (Proxy :: Proxy T.Text) - <$> takeP Nothing 4 - _ -> return escaped + 'b' -> pure '\b' + 'f' -> pure '\f' + 'n' -> pure '\n' + 'r' -> pure '\r' + 't' -> pure '\t' + 'u' -> chr + . foldl' step 0 + . chunkToTokens (Proxy :: Proxy T.Text) + <$> takeP Nothing 4 + _ -> pure escaped where step accumulator = (accumulator * 16 +) . digitToInt diff --git a/src/Language/GraphQL/AST/Parser.hs b/src/Language/GraphQL/AST/Parser.hs index e19823c..f325ee7 100644 --- a/src/Language/GraphQL/AST/Parser.hs +++ b/src/Language/GraphQL/AST/Parser.hs @@ -8,7 +8,7 @@ module Language.GraphQL.AST.Parser ( document ) where -import Control.Applicative (Alternative(..), liftA2, optional) +import Control.Applicative (Alternative(..), optional) import Control.Applicative.Combinators (sepBy1) import qualified Control.Applicative.Combinators.NonEmpty as NonEmpty import Data.List.NonEmpty (NonEmpty(..)) @@ -27,6 +27,7 @@ import Text.Megaparsec , unPos , (<?>) ) +import Data.Maybe (isJust) -- | Parser for the GraphQL documents. document :: Parser Full.Document @@ -82,6 +83,7 @@ directiveDefinition description' = Full.DirectiveDefinition description' <* at <*> name <*> argumentsDefinition + <*> (isJust <$> optional (symbol "repeatable")) <* symbol "on" <*> directiveLocations <?> "DirectiveDefinition" |
