Parse comments in the front of definitions

This commit is contained in:
Eugen Wissner 2020-07-09 08:11:12 +02:00
parent c9e265f72c
commit 28781586a5
3 changed files with 49 additions and 41 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to
## Fixed ## Fixed
- Location of a parse error is returned in a singleton array with key - Location of a parse error is returned in a singleton array with key
`locations`. `locations`.
- Parsing comments in the front of definitions.
## Added ## Added
- `AST` reexports `AST.Parser`. - `AST` reexports `AST.Parser`.

View File

@ -6,7 +6,7 @@ module Language.GraphQL.AST.Parser
( document ( document
) where ) where
import Control.Applicative (Alternative(..), optional) import Control.Applicative (Alternative(..), liftA2, optional)
import Control.Applicative.Combinators (sepBy1) import Control.Applicative.Combinators (sepBy1)
import qualified Control.Applicative.Combinators.NonEmpty as NonEmpty import qualified Control.Applicative.Combinators.NonEmpty as NonEmpty
import Data.List.NonEmpty (NonEmpty(..)) import Data.List.NonEmpty (NonEmpty(..))
@ -24,8 +24,8 @@ import Text.Megaparsec (lookAhead, option, try, (<?>))
-- | Parser for the GraphQL documents. -- | Parser for the GraphQL documents.
document :: Parser Document document :: Parser Document
document = unicodeBOM document = unicodeBOM
>> spaceConsumer *> spaceConsumer
>> lexeme (NonEmpty.some definition) *> lexeme (NonEmpty.some definition)
definition :: Parser Definition definition :: Parser Definition
definition = ExecutableDefinition <$> executableDefinition definition = ExecutableDefinition <$> executableDefinition
@ -40,19 +40,22 @@ executableDefinition = DefinitionOperation <$> operationDefinition
typeSystemDefinition :: Parser TypeSystemDefinition typeSystemDefinition :: Parser TypeSystemDefinition
typeSystemDefinition = schemaDefinition typeSystemDefinition = schemaDefinition
<|> TypeDefinition <$> typeDefinition <|> typeSystemDefinitionWithDescription
<|> directiveDefinition
<?> "TypeSystemDefinition" <?> "TypeSystemDefinition"
where
typeSystemDefinitionWithDescription = description
>>= liftA2 (<|>) typeDefinition' directiveDefinition
typeDefinition' description' = TypeDefinition
<$> typeDefinition description'
typeSystemExtension :: Parser TypeSystemExtension typeSystemExtension :: Parser TypeSystemExtension
typeSystemExtension = SchemaExtension <$> schemaExtension typeSystemExtension = SchemaExtension <$> schemaExtension
<|> TypeExtension <$> typeExtension <|> TypeExtension <$> typeExtension
<?> "TypeSystemExtension" <?> "TypeSystemExtension"
directiveDefinition :: Parser TypeSystemDefinition directiveDefinition :: Description -> Parser TypeSystemDefinition
directiveDefinition = DirectiveDefinition directiveDefinition description' = DirectiveDefinition description'
<$> description <$ symbol "directive"
<* symbol "directive"
<* at <* at
<*> name <*> name
<*> argumentsDefinition <*> argumentsDefinition
@ -91,13 +94,13 @@ typeSystemDirectiveLocation = Directive.Schema <$ symbol "SCHEMA"
<|> Directive.InputObject <$ symbol "INPUT_OBJECT" <|> Directive.InputObject <$ symbol "INPUT_OBJECT"
<|> Directive.InputFieldDefinition <$ symbol "INPUT_FIELD_DEFINITION" <|> Directive.InputFieldDefinition <$ symbol "INPUT_FIELD_DEFINITION"
typeDefinition :: Parser TypeDefinition typeDefinition :: Description -> Parser TypeDefinition
typeDefinition = scalarTypeDefinition typeDefinition description' = scalarTypeDefinition description'
<|> objectTypeDefinition <|> objectTypeDefinition description'
<|> interfaceTypeDefinition <|> interfaceTypeDefinition description'
<|> unionTypeDefinition <|> unionTypeDefinition description'
<|> enumTypeDefinition <|> enumTypeDefinition description'
<|> inputObjectTypeDefinition <|> inputObjectTypeDefinition description'
<?> "TypeDefinition" <?> "TypeDefinition"
typeExtension :: Parser TypeExtension typeExtension :: Parser TypeExtension
@ -109,10 +112,9 @@ typeExtension = scalarTypeExtension
<|> inputObjectTypeExtension <|> inputObjectTypeExtension
<?> "TypeExtension" <?> "TypeExtension"
scalarTypeDefinition :: Parser TypeDefinition scalarTypeDefinition :: Description -> Parser TypeDefinition
scalarTypeDefinition = ScalarTypeDefinition scalarTypeDefinition description' = ScalarTypeDefinition description'
<$> description <$ symbol "scalar"
<* symbol "scalar"
<*> name <*> name
<*> directives <*> directives
<?> "ScalarTypeDefinition" <?> "ScalarTypeDefinition"
@ -121,10 +123,9 @@ scalarTypeExtension :: Parser TypeExtension
scalarTypeExtension = extend "scalar" "ScalarTypeExtension" scalarTypeExtension = extend "scalar" "ScalarTypeExtension"
$ (ScalarTypeExtension <$> name <*> NonEmpty.some directive) :| [] $ (ScalarTypeExtension <$> name <*> NonEmpty.some directive) :| []
objectTypeDefinition :: Parser TypeDefinition objectTypeDefinition :: Description -> Parser TypeDefinition
objectTypeDefinition = ObjectTypeDefinition objectTypeDefinition description' = ObjectTypeDefinition description'
<$> description <$ symbol "type"
<* symbol "type"
<*> name <*> name
<*> option (ImplementsInterfaces []) (implementsInterfaces sepBy1) <*> option (ImplementsInterfaces []) (implementsInterfaces sepBy1)
<*> directives <*> directives
@ -153,13 +154,12 @@ objectTypeExtension = extend "type" "ObjectTypeExtension"
description :: Parser Description description :: Parser Description
description = Description description = Description
<$> optional (string <|> blockString) <$> optional (blockString <|> string)
<?> "Description" <?> "Description"
unionTypeDefinition :: Parser TypeDefinition unionTypeDefinition :: Description -> Parser TypeDefinition
unionTypeDefinition = UnionTypeDefinition unionTypeDefinition description' = UnionTypeDefinition description'
<$> description <$ symbol "union"
<* symbol "union"
<*> name <*> name
<*> directives <*> directives
<*> option (UnionMemberTypes []) (unionMemberTypes sepBy1) <*> option (UnionMemberTypes []) (unionMemberTypes sepBy1)
@ -187,10 +187,9 @@ unionMemberTypes sepBy' = UnionMemberTypes
<*> name `sepBy'` pipe <*> name `sepBy'` pipe
<?> "UnionMemberTypes" <?> "UnionMemberTypes"
interfaceTypeDefinition :: Parser TypeDefinition interfaceTypeDefinition :: Description -> Parser TypeDefinition
interfaceTypeDefinition = InterfaceTypeDefinition interfaceTypeDefinition description' = InterfaceTypeDefinition description'
<$> description <$ symbol "interface"
<* symbol "interface"
<*> name <*> name
<*> directives <*> directives
<*> braces (many fieldDefinition) <*> braces (many fieldDefinition)
@ -208,10 +207,9 @@ interfaceTypeExtension = extend "interface" "InterfaceTypeExtension"
<$> name <$> name
<*> NonEmpty.some directive <*> NonEmpty.some directive
enumTypeDefinition :: Parser TypeDefinition enumTypeDefinition :: Description -> Parser TypeDefinition
enumTypeDefinition = EnumTypeDefinition enumTypeDefinition description' = EnumTypeDefinition description'
<$> description <$ symbol "enum"
<* symbol "enum"
<*> name <*> name
<*> directives <*> directives
<*> listOptIn braces enumValueDefinition <*> listOptIn braces enumValueDefinition
@ -229,10 +227,9 @@ enumTypeExtension = extend "enum" "EnumTypeExtension"
<$> name <$> name
<*> NonEmpty.some directive <*> NonEmpty.some directive
inputObjectTypeDefinition :: Parser TypeDefinition inputObjectTypeDefinition :: Description -> Parser TypeDefinition
inputObjectTypeDefinition = InputObjectTypeDefinition inputObjectTypeDefinition description' = InputObjectTypeDefinition description'
<$> description <$ symbol "input"
<* symbol "input"
<*> name <*> name
<*> directives <*> directives
<*> listOptIn braces inputValueDefinition <*> listOptIn braces inputValueDefinition

View File

@ -149,3 +149,13 @@ spec = describe "Parser" $ do
title title
} }
|] |]
it "parses documents beginning with a comment" $
parse document "" `shouldSucceedOn` [r|
"""
Query
"""
type Query {
queryField: String
}
|]