#![allow(clippy::needless_return)]
use crate::{
parser::grammar::{description, directive, document::is_definition, field, name, ty},
Parser, SyntaxKind, TokenKind, S, T,
};
pub(crate) fn object_type_definition(p: &mut Parser) {
let _g = p.start_node(SyntaxKind::OBJECT_TYPE_DEFINITION);
if let Some(TokenKind::StringValue) = p.peek() {
description::description(p);
}
if let Some("type") = p.peek_data().as_deref() {
p.bump(SyntaxKind::type_KW);
}
match p.peek() {
Some(TokenKind::Name) => name::name(p),
_ => p.err("expected a name"),
}
if let Some(TokenKind::Name) = p.peek() {
if p.peek_data().unwrap() == "implements" {
implements_interfaces(p);
} else {
p.err("unexpected Name");
}
}
if let Some(T![@]) = p.peek() {
directive::directives(p);
}
if let Some(T!['{']) = p.peek() {
field::fields_definition(p);
}
}
pub(crate) fn object_type_extension(p: &mut Parser) {
let _g = p.start_node(SyntaxKind::OBJECT_TYPE_EXTENSION);
p.bump(SyntaxKind::extend_KW);
p.bump(SyntaxKind::type_KW);
let mut meets_requirements = false;
match p.peek() {
Some(TokenKind::Name) => name::name(p),
_ => p.err("expected a Name"),
}
if let Some("implements") = p.peek_data().as_deref() {
meets_requirements = true;
implements_interfaces(p);
}
if let Some(T![@]) = p.peek() {
meets_requirements = true;
directive::directives(p)
}
if let Some(T!['{']) = p.peek() {
meets_requirements = true;
field::fields_definition(p)
}
if !meets_requirements {
p.err("expected an Implements Interface, Directives or a Fields Definition");
}
}
pub(crate) fn implements_interfaces(p: &mut Parser) {
let _g = p.start_node(SyntaxKind::IMPLEMENTS_INTERFACES);
p.bump(SyntaxKind::implements_KW);
implements_interface(p, false);
}
fn implements_interface(p: &mut Parser, is_interfaces: bool) {
match p.peek() {
Some(T![&]) => {
p.bump(S![&]);
implements_interface(p, is_interfaces)
}
Some(TokenKind::Name) => {
ty::named_type(p);
if let Some(node) = p.peek_data() {
if !is_definition(node) {
implements_interface(p, true);
}
return;
}
}
_ => {
if !is_interfaces {
p.err("expected an Object Type Definition");
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::ast;
#[test]
fn object_type_definition() {
let input = "
type Business implements NamedEntity & ValuedEntity & CatEntity {
name: String
}";
let parser = Parser::new(input);
let ast = parser.parse();
assert_eq!(0, ast.errors().len());
let doc = ast.document();
for def in doc.definitions() {
if let ast::Definition::ObjectTypeDefinition(interface_type) = def {
assert_eq!(interface_type.name().unwrap().text(), "Business");
for implements_interfaces in interface_type
.implements_interfaces()
.unwrap()
.named_types()
{
println!("{}", implements_interfaces.name().unwrap().text());
}
}
}
}
}