use crate::ast;
use crate::token::GraphQLTriviaToken;
use crate::ByteSpan;
use crate::GraphQLParseError;
use crate::SourceMap;
#[derive(Debug)]
pub enum ParseResult<'src, TAst> {
Ok {
ast: TAst,
source_map: SourceMap<'src>,
},
Recovered {
ast: TAst,
errors: Vec<GraphQLParseError>,
source_map: SourceMap<'src>,
},
}
impl<'src, TAst> ParseResult<'src, TAst> {
pub fn ast(&self) -> &TAst {
match self {
Self::Ok { ast, .. } => ast,
Self::Recovered { ast, .. } => ast,
}
}
pub fn errors(&self) -> &[GraphQLParseError] {
match self {
Self::Ok { .. } => &[],
Self::Recovered { errors, .. } => errors,
}
}
pub fn formatted_errors(&self) -> String {
let source = self.source_map().source();
self.errors()
.iter()
.map(|e| e.format_detailed(source))
.collect::<Vec<_>>()
.join("\n")
}
pub fn has_errors(&self) -> bool {
matches!(self, Self::Recovered { .. })
}
pub fn into_ast(self) -> TAst {
match self {
Self::Ok { ast, .. } => ast,
Self::Recovered { ast, .. } => ast,
}
}
pub fn into_recovered(self) -> Option<(TAst, Vec<GraphQLParseError>, SourceMap<'src>)> {
match self {
Self::Ok { .. } => None,
Self::Recovered { ast, errors, source_map } => Some((ast, errors, source_map)),
}
}
pub fn into_valid(self) -> Option<(TAst, SourceMap<'src>)> {
match self {
Self::Ok { ast, source_map } => Some((ast, source_map)),
Self::Recovered { .. } => None,
}
}
pub(crate) fn new_ok(ast: TAst, source_map: SourceMap<'src>) -> Self {
Self::Ok { ast, source_map }
}
pub(crate) fn new_recovered(
ast: TAst,
errors: Vec<GraphQLParseError>,
source_map: SourceMap<'src>,
) -> Self {
debug_assert!(
!errors.is_empty(),
"ParseResult::new_recovered() called with empty errors vec; \
use ParseResult::new_ok() instead",
);
Self::Recovered { ast, errors, source_map }
}
pub fn recovered(&self) -> Option<(&TAst, &[GraphQLParseError], &SourceMap<'src>)> {
match self {
Self::Ok { .. } => None,
Self::Recovered { ast, errors, source_map } => Some((ast, errors, source_map)),
}
}
pub fn source_map(&self) -> &SourceMap<'src> {
match self {
Self::Ok { source_map, .. } => source_map,
Self::Recovered { source_map, .. } => source_map,
}
}
pub fn valid(&self) -> Option<(&TAst, &SourceMap<'src>)> {
match self {
Self::Ok { ast, source_map } => Some((ast, source_map)),
Self::Recovered { .. } => None,
}
}
}
impl<'src> ParseResult<'src, ast::Document<'src>> {
pub fn definitions(&self) -> &[ast::Definition<'src>] {
&self.ast().definitions
}
pub fn executable_definitions(&self) -> impl Iterator<Item = &ast::Definition<'src>> {
self.ast().executable_definitions()
}
pub fn schema_definitions(&self) -> impl Iterator<Item = &ast::Definition<'src>> {
self.ast().schema_definitions()
}
pub fn span(&self) -> ByteSpan {
self.ast().span
}
pub fn syntax(&self) -> &Option<Box<ast::DocumentSyntax<'src>>> {
&self.ast().syntax
}
pub fn trailing_trivia(&self) -> Option<&[GraphQLTriviaToken<'src>]> {
self.ast().trailing_trivia()
}
}
impl<'src, TAst> From<ParseResult<'src, TAst>>
for Result<(TAst, SourceMap<'src>), Vec<GraphQLParseError>> {
fn from(result: ParseResult<'src, TAst>) -> Self {
match result {
ParseResult::Ok { ast, source_map } => Ok((ast, source_map)),
ParseResult::Recovered { errors, .. } => Err(errors),
}
}
}