use std::fmt;
#[derive(Default, Debug)]
pub struct Diagnostics(Vec<Diagnostic>);
impl Diagnostics {
pub fn any_fatal(&self) -> bool {
self.0.iter().any(|diagnostic| diagnostic.severity.is_error())
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = &Diagnostic> {
self.0.iter()
}
pub fn iter_warnings(&self) -> impl Iterator<Item = &str> {
self.0
.iter()
.filter(|diagnostic| diagnostic.severity.is_warning())
.map(|diagnostic| diagnostic.message.as_str())
}
pub fn iter_errors(&self) -> impl Iterator<Item = &str> {
self.0
.iter()
.filter(|diagnostic| diagnostic.severity.is_error())
.map(|diagnostic| diagnostic.message.as_str())
}
pub(crate) fn clone_all_from(&mut self, other: &Diagnostics) {
self.0.extend(other.0.iter().cloned())
}
pub fn iter_messages(&self) -> impl Iterator<Item = &str> {
self.0.iter().map(|diagnostic| diagnostic.message.as_str())
}
pub(crate) fn push_composite_schemas_source_schema_validation_error(
&mut self,
source_schema_name: &str,
message: impl fmt::Display,
error_code: CompositeSchemasSourceSchemaValidationErrorCode,
) {
self.0.push(Diagnostic {
message: format!("[{source_schema_name}] {message}"),
severity: error_code.severity(),
error_code: Some(error_code.into()),
});
}
pub(crate) fn push_composite_schemas_pre_merge_validation_error(
&mut self,
message: String,
error_code: CompositeSchemasPreMergeValidationErrorCode,
) {
self.0.push(Diagnostic {
message,
severity: error_code.severity(),
error_code: Some(error_code.into()),
});
}
pub(crate) fn push_composite_schemas_post_merge_validation_error(
&mut self,
message: String,
error_code: CompositeSchemasPostMergeValidationErrorCode,
) {
self.0.push(Diagnostic {
message,
severity: error_code.severity(),
error_code: Some(error_code.into()),
});
}
pub(crate) fn push_fatal(&mut self, message: String) {
self.0.push(Diagnostic {
message,
severity: Severity::Error,
error_code: None,
});
}
pub(crate) fn push_warning(&mut self, message: String) {
self.0.push(Diagnostic {
message,
severity: Severity::Warning,
error_code: None,
});
}
}
#[derive(Debug, Clone)]
pub struct Diagnostic {
message: String,
severity: Severity,
error_code: Option<CompositeSchemasErrorCode>,
}
impl Diagnostic {
pub fn message(&self) -> &str {
&self.message
}
pub fn severity(&self) -> Severity {
self.severity
}
pub fn composite_schemas_error_code(&self) -> Option<CompositeSchemasErrorCode> {
self.error_code
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum Severity {
Error,
Warning,
}
impl Severity {
#[must_use]
pub fn is_error(&self) -> bool {
matches!(self, Self::Error)
}
#[must_use]
pub fn is_warning(&self) -> bool {
matches!(self, Self::Warning)
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum CompositeSchemasErrorCode {
SourceSchema(CompositeSchemasSourceSchemaValidationErrorCode),
PreMerge(CompositeSchemasPreMergeValidationErrorCode),
PostMerge(CompositeSchemasPostMergeValidationErrorCode),
}
impl From<CompositeSchemasPostMergeValidationErrorCode> for CompositeSchemasErrorCode {
fn from(v: CompositeSchemasPostMergeValidationErrorCode) -> Self {
Self::PostMerge(v)
}
}
impl From<CompositeSchemasSourceSchemaValidationErrorCode> for CompositeSchemasErrorCode {
fn from(v: CompositeSchemasSourceSchemaValidationErrorCode) -> Self {
Self::SourceSchema(v)
}
}
impl From<CompositeSchemasPreMergeValidationErrorCode> for CompositeSchemasErrorCode {
fn from(v: CompositeSchemasPreMergeValidationErrorCode) -> Self {
Self::PreMerge(v)
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
#[non_exhaustive]
pub enum CompositeSchemasSourceSchemaValidationErrorCode {
QueryRootTypeInaccessible,
LookupReturnsNonNullableType,
OverrideFromSelf,
ProvidesDirectiveInFieldsArgument,
}
impl CompositeSchemasSourceSchemaValidationErrorCode {
fn severity(&self) -> Severity {
use CompositeSchemasSourceSchemaValidationErrorCode::*;
match self {
QueryRootTypeInaccessible | OverrideFromSelf | ProvidesDirectiveInFieldsArgument => Severity::Error,
LookupReturnsNonNullableType => Severity::Warning,
}
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum CompositeSchemasPreMergeValidationErrorCode {
TypeKindMismatch,
OverrideSourceHasOverride,
}
impl CompositeSchemasPreMergeValidationErrorCode {
fn severity(&self) -> Severity {
use CompositeSchemasPreMergeValidationErrorCode::*;
match self {
TypeKindMismatch | OverrideSourceHasOverride => Severity::Error,
}
}
}
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
pub enum CompositeSchemasPostMergeValidationErrorCode {
InvalidFieldSharing,
}
impl CompositeSchemasPostMergeValidationErrorCode {
fn severity(&self) -> Severity {
use CompositeSchemasPostMergeValidationErrorCode::*;
match self {
InvalidFieldSharing => Severity::Error,
}
}
}