Try all extension parsers

This commit is contained in:
Eugen Wissner 2020-01-28 11:08:28 +01:00
parent a6bd2370b6
commit e8b82122c6
6 changed files with 48 additions and 37 deletions

View File

@ -267,7 +267,7 @@ data OperationTypeDefinition
data SchemaExtension data SchemaExtension
= SchemaOperationExtension [Directive] (NonEmpty OperationTypeDefinition) = SchemaOperationExtension [Directive] (NonEmpty OperationTypeDefinition)
| SchemaDirectiveExtension (NonEmpty Directive) | SchemaDirectivesExtension (NonEmpty Directive)
deriving (Eq, Show) deriving (Eq, Show)
-- ** Descriptions -- ** Descriptions

View File

@ -33,9 +33,12 @@ import Control.Applicative (Alternative(..), liftA2)
import Data.Char (chr, digitToInt, isAsciiLower, isAsciiUpper, ord) import Data.Char (chr, digitToInt, isAsciiLower, isAsciiUpper, ord)
import Data.Foldable (foldl') import Data.Foldable (foldl')
import Data.List (dropWhileEnd) import Data.List (dropWhileEnd)
import qualified Data.List.NonEmpty as NonEmpty
import Data.List.NonEmpty (NonEmpty(..))
import Data.Proxy (Proxy(..)) import Data.Proxy (Proxy(..))
import Data.Void (Void) import Data.Void (Void)
import Text.Megaparsec ( Parsec import Text.Megaparsec ( Parsec
, (<?>)
, between , between
, chunk , chunk
, chunkToTokens , chunkToTokens
@ -220,5 +223,14 @@ unicodeBOM :: Parser ()
unicodeBOM = optional (char '\xfeff') >> pure () unicodeBOM = optional (char '\xfeff') >> pure ()
-- | Parses "extend" followed by a 'symbol'. It is used by schema extensions. -- | Parses "extend" followed by a 'symbol'. It is used by schema extensions.
extend :: Text -> Parser () extend :: forall a. Text -> String -> NonEmpty (Parser a) -> Parser a
extend token = symbol "extend" *> symbol token >> pure () extend token extensionLabel parsers
= foldr combine headParser (NonEmpty.tail parsers)
<?> extensionLabel
where
headParser = tryExtension $ NonEmpty.head parsers
combine current accumulated = accumulated <|> tryExtension current
tryExtension extensionParser = try
$ symbol "extend"
*> symbol token
*> extensionParser

View File

@ -9,7 +9,7 @@ module Language.GraphQL.AST.Parser
import Control.Applicative (Alternative(..), optional) import Control.Applicative (Alternative(..), 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(..))
import Data.Text (Text) import Data.Text (Text)
import qualified Language.GraphQL.AST.DirectiveLocation as Directive import qualified Language.GraphQL.AST.DirectiveLocation as Directive
import Language.GraphQL.AST.DirectiveLocation import Language.GraphQL.AST.DirectiveLocation
@ -118,11 +118,8 @@ scalarTypeDefinition = ScalarTypeDefinition
<?> "ScalarTypeDefinition" <?> "ScalarTypeDefinition"
scalarTypeExtension :: Parser TypeExtension scalarTypeExtension :: Parser TypeExtension
scalarTypeExtension = ScalarTypeExtension scalarTypeExtension = extend "scalar" "ScalarTypeExtension"
<$ extend "scalar" $ (ScalarTypeExtension <$> name <*> NonEmpty.some directive) :| []
<*> name
<*> NonEmpty.some directive
<?> "ScalarTypeExtension"
objectTypeDefinition :: Parser TypeDefinition objectTypeDefinition :: Parser TypeDefinition
objectTypeDefinition = ObjectTypeDefinition objectTypeDefinition = ObjectTypeDefinition
@ -135,11 +132,11 @@ objectTypeDefinition = ObjectTypeDefinition
<?> "ObjectTypeDefinition" <?> "ObjectTypeDefinition"
objectTypeExtension :: Parser TypeExtension objectTypeExtension :: Parser TypeExtension
objectTypeExtension = extend "type" objectTypeExtension = extend "type" "ObjectTypeExtension"
>> try fieldsDefinitionExtension $ fieldsDefinitionExtension :|
<|> try directivesExtension [ directivesExtension
<|> implementsInterfacesExtension , implementsInterfacesExtension
<?> "ObjectTypeExtension" ]
where where
fieldsDefinitionExtension = ObjectTypeFieldsDefinitionExtension fieldsDefinitionExtension = ObjectTypeFieldsDefinitionExtension
<$> name <$> name
@ -169,10 +166,8 @@ unionTypeDefinition = UnionTypeDefinition
<?> "UnionTypeDefinition" <?> "UnionTypeDefinition"
unionTypeExtension :: Parser TypeExtension unionTypeExtension :: Parser TypeExtension
unionTypeExtension = extend "union" unionTypeExtension = extend "union" "UnionTypeExtension"
>> try unionMemberTypesExtension $ unionMemberTypesExtension :| [directivesExtension]
<|> directivesExtension
<?> "UnionTypeExtension"
where where
unionMemberTypesExtension = UnionTypeUnionMemberTypesExtension unionMemberTypesExtension = UnionTypeUnionMemberTypesExtension
<$> name <$> name
@ -202,10 +197,8 @@ interfaceTypeDefinition = InterfaceTypeDefinition
<?> "InterfaceTypeDefinition" <?> "InterfaceTypeDefinition"
interfaceTypeExtension :: Parser TypeExtension interfaceTypeExtension :: Parser TypeExtension
interfaceTypeExtension = extend "interface" interfaceTypeExtension = extend "interface" "InterfaceTypeExtension"
>> try fieldsDefinitionExtension $ fieldsDefinitionExtension :| [directivesExtension]
<|> directivesExtension
<?> "InterfaceTypeExtension"
where where
fieldsDefinitionExtension = InterfaceTypeFieldsDefinitionExtension fieldsDefinitionExtension = InterfaceTypeFieldsDefinitionExtension
<$> name <$> name
@ -225,10 +218,8 @@ enumTypeDefinition = EnumTypeDefinition
<?> "EnumTypeDefinition" <?> "EnumTypeDefinition"
enumTypeExtension :: Parser TypeExtension enumTypeExtension :: Parser TypeExtension
enumTypeExtension = extend "enum" enumTypeExtension = extend "enum" "EnumTypeExtension"
>> try enumValuesDefinitionExtension $ enumValuesDefinitionExtension :| [directivesExtension]
<|> directivesExtension
<?> "EnumTypeExtension"
where where
enumValuesDefinitionExtension = EnumTypeEnumValuesDefinitionExtension enumValuesDefinitionExtension = EnumTypeEnumValuesDefinitionExtension
<$> name <$> name
@ -248,10 +239,8 @@ inputObjectTypeDefinition = InputObjectTypeDefinition
<?> "InputObjectTypeDefinition" <?> "InputObjectTypeDefinition"
inputObjectTypeExtension :: Parser TypeExtension inputObjectTypeExtension :: Parser TypeExtension
inputObjectTypeExtension = extend "input" inputObjectTypeExtension = extend "input" "InputObjectTypeExtension"
>> try inputFieldsDefinitionExtension $ inputFieldsDefinitionExtension :| [directivesExtension]
<|> directivesExtension
<?> "InputObjectTypeExtension"
where where
inputFieldsDefinitionExtension = InputObjectTypeInputFieldsDefinitionExtension inputFieldsDefinitionExtension = InputObjectTypeInputFieldsDefinitionExtension
<$> name <$> name
@ -314,11 +303,11 @@ operationTypeDefinitions :: Parser (NonEmpty OperationTypeDefinition)
operationTypeDefinitions = braces $ NonEmpty.some operationTypeDefinition operationTypeDefinitions = braces $ NonEmpty.some operationTypeDefinition
schemaExtension :: Parser SchemaExtension schemaExtension :: Parser SchemaExtension
schemaExtension = extend "schema" schemaExtension = extend "schema" "SchemaExtension"
>> try schemaOperationExtension $ schemaOperationExtension :| [directivesExtension]
<|> SchemaDirectiveExtension <$> NonEmpty.some directive
<?> "SchemaExtension"
where where
directivesExtension = SchemaDirectivesExtension
<$> NonEmpty.some directive
schemaOperationExtension = SchemaOperationExtension schemaOperationExtension = SchemaOperationExtension
<$> directives <$> directives
<*> operationTypeDefinitions <*> operationTypeDefinitions

View File

@ -1,4 +1,4 @@
resolver: lts-14.21 resolver: lts-14.22
packages: packages:
- . - .

View File

@ -88,9 +88,12 @@ spec = describe "Lexer" $ do
it "lexes ampersand" $ it "lexes ampersand" $
parse amp "" "&" `shouldParse` "&" parse amp "" "&" `shouldParse` "&"
it "lexes schema extensions" $ it "lexes schema extensions" $
parse (extend "schema") "" `shouldSucceedOn` "extend schema" parseExtend "schema" `shouldSucceedOn` "extend schema"
it "fails if the given token doesn't match" $ it "fails if the given token doesn't match" $
parse (extend "schema") "" `shouldFailOn` "extend shema" parseExtend "schema" `shouldFailOn` "extend shema"
parseExtend :: Text -> (Text -> Either (ParseErrorBundle Text Void) ())
parseExtend extension = parse (extend extension "" $ pure $ pure ()) ""
runBetween :: (Parser () -> Parser ()) -> Text -> Either (ParseErrorBundle Text Void) () runBetween :: (Parser () -> Parser ()) -> Text -> Either (ParseErrorBundle Text Void) ()
runBetween parser = parse (parser $ pure ()) "" runBetween parser = parse (parser $ pure ()) ""

View File

@ -135,3 +135,10 @@ spec = describe "Parser" $ do
$ OperationTypeDefinition Query "Query" :| [] $ OperationTypeDefinition Query "Query" :| []
query = [r|extend schema @newDirective { query: Query }|] query = [r|extend schema @newDirective { query: Query }|]
in parse document "" query `shouldParse` (testSchemaExtension :| []) in parse document "" query `shouldParse` (testSchemaExtension :| [])
it "parses an object extension" $
parse document "" `shouldSucceedOn` [r|
extend type Story {
isHiddenLocally: Boolean
}
|]