use crate::ast::ast_node::append_span_source_slice;
use crate::ast::AstNode;
use crate::ast::Definition;
use crate::ByteSpan;
use crate::SourceMap;
use crate::SourceSpan;
use crate::token::GraphQLTriviaToken;
use inherent::inherent;
#[derive(Clone, Debug, PartialEq)]
pub struct Document<'src> {
pub definitions: Vec<Definition<'src>>,
pub span: ByteSpan,
pub syntax: Option<Box<DocumentSyntax<'src>>>,
}
impl<'src> Document<'src> {
pub fn executable_definitions(
&self,
) -> impl Iterator<Item = &Definition<'src>> {
self.definitions.iter().filter(|d| {
matches!(
d,
Definition::FragmentDefinition(_)
| Definition::OperationDefinition(_)
)
})
}
pub fn schema_definitions(
&self,
) -> impl Iterator<Item = &Definition<'src>> {
self.definitions.iter().filter(|d| {
matches!(
d,
Definition::DirectiveDefinition(_)
| Definition::SchemaDefinition(_)
| Definition::SchemaExtension(_)
| Definition::TypeDefinition(_)
| Definition::TypeExtension(_)
)
})
}
pub fn trailing_trivia(&self) -> Option<&[GraphQLTriviaToken<'src>]> {
self.syntax.as_ref().map(|s| s.trailing_trivia.as_slice())
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct DocumentSyntax<'src> {
pub trailing_trivia:
Vec<GraphQLTriviaToken<'src>>,
}
#[inherent]
impl AstNode for Document<'_> {
pub fn append_source(
&self,
sink: &mut String,
source: Option<&str>,
) {
if let Some(src) = source {
append_span_source_slice(
self.span, sink, src,
);
if let Some(syntax) = &self.syntax {
for trivia in &syntax.trailing_trivia {
let trivia_span = match trivia {
GraphQLTriviaToken::Comment { span, .. }
| GraphQLTriviaToken::Comma { span, .. }
| GraphQLTriviaToken::Whitespace {
span, ..
} => span,
};
append_span_source_slice(
*trivia_span, sink, src,
);
}
}
}
}
#[inline]
pub fn byte_span(&self) -> ByteSpan {
self.span
}
#[inline]
pub fn source_span(
&self,
source_map: &SourceMap,
) -> Option<SourceSpan> {
self.byte_span().resolve(source_map)
}
}