1use crate::ast;
52use crate::collections::IndexMap;
53use crate::coordinate::FieldArgumentCoordinate;
54use crate::coordinate::TypeAttributeCoordinate;
55use crate::parser::Parser;
56use crate::parser::SourceMap;
57use crate::parser::SourceSpan;
58use crate::schema;
59use crate::validation::DiagnosticList;
60use crate::validation::Valid;
61use crate::validation::WithErrors;
62use crate::Node;
63use crate::Schema;
64use indexmap::map::Entry;
65use std::fmt;
66use std::path::Path;
67use std::sync::Arc;
68
69pub(crate) mod from_ast;
70mod serialize;
71pub(crate) mod validation;
72
73pub use crate::ast::Argument;
74use crate::ast::ArgumentByNameError;
75pub use crate::ast::Directive;
76pub use crate::ast::DirectiveList;
77pub use crate::ast::NamedType;
78pub use crate::ast::OperationType;
79pub use crate::ast::Type;
80pub use crate::ast::Value;
81pub use crate::ast::VariableDefinition;
82use crate::collections::HashSet;
83use crate::request::RequestError;
84pub use crate::Name;
85
86#[derive(Debug, Clone, Default)]
88pub struct ExecutableDocument {
89 pub sources: SourceMap,
94
95 pub operations: OperationMap,
96 pub fragments: FragmentMap,
97}
98
99#[derive(Debug, Clone, Default, PartialEq)]
101pub struct OperationMap {
102 pub anonymous: Option<Node<Operation>>,
103 pub named: IndexMap<Name, Node<Operation>>,
104}
105
106pub type FragmentMap = IndexMap<Name, Node<Fragment>>;
108
109#[derive(Debug, Clone)]
112pub struct FieldSet {
113 pub sources: SourceMap,
118
119 pub selection_set: SelectionSet,
120}
121
122#[derive(Debug, Clone, PartialEq, Eq)]
125pub struct Operation {
126 pub operation_type: OperationType,
127 pub name: Option<Name>,
128 pub variables: Vec<Node<VariableDefinition>>,
129 pub directives: DirectiveList,
130 pub selection_set: SelectionSet,
131}
132
133#[derive(Debug, Clone, PartialEq, Eq)]
136pub struct Fragment {
137 pub name: Name,
138 pub directives: DirectiveList,
139 pub selection_set: SelectionSet,
140}
141
142#[derive(Debug, Clone, PartialEq, Eq, Hash)]
145pub struct SelectionSet {
146 pub ty: NamedType,
147 pub selections: Vec<Selection>,
148}
149
150#[derive(Debug, Clone, PartialEq, Eq, Hash)]
153pub enum Selection {
154 Field(Node<Field>),
155 FragmentSpread(Node<FragmentSpread>),
156 InlineFragment(Node<InlineFragment>),
157}
158
159#[derive(Debug, Clone, PartialEq, Eq, Hash)]
162pub struct Field {
163 pub definition: Node<schema::FieldDefinition>,
165 pub alias: Option<Name>,
166 pub name: Name,
167 pub arguments: Vec<Node<Argument>>,
168 pub directives: DirectiveList,
169 pub selection_set: SelectionSet,
170}
171
172#[derive(Debug, Clone, PartialEq, Eq, Hash)]
175pub struct FragmentSpread {
176 pub fragment_name: Name,
177 pub directives: DirectiveList,
178}
179
180#[derive(Debug, Clone, PartialEq, Eq, Hash)]
183pub struct InlineFragment {
184 pub type_condition: Option<NamedType>,
185 pub directives: DirectiveList,
186 pub selection_set: SelectionSet,
187}
188
189#[derive(thiserror::Error, Debug, Clone)]
192pub(crate) enum BuildError {
193 #[error("an executable document must not contain {describe}")]
194 TypeSystemDefinition {
195 name: Option<Name>,
196 describe: &'static str,
197 },
198
199 #[error("anonymous operation cannot be selected when the document contains other operations")]
200 AmbiguousAnonymousOperation,
201
202 #[error(
203 "the operation `{name_at_previous_location}` is defined multiple times in the document"
204 )]
205 OperationNameCollision { name_at_previous_location: Name },
206
207 #[error(
208 "the fragment `{name_at_previous_location}` is defined multiple times in the document"
209 )]
210 FragmentNameCollision { name_at_previous_location: Name },
211
212 #[error("`{operation_type}` root operation type is not defined")]
213 UndefinedRootOperation { operation_type: &'static str },
214
215 #[error(
216 "type condition `{type_name}` of fragment `{fragment_name}` \
217 is not a type defined in the schema"
218 )]
219 UndefinedTypeInNamedFragmentTypeCondition {
220 type_name: NamedType,
221 fragment_name: Name,
222 },
223
224 #[error("type condition `{type_name}` of inline fragment is not a type defined in the schema")]
225 UndefinedTypeInInlineFragmentTypeCondition {
226 type_name: NamedType,
227 path: SelectionPath,
228 },
229
230 #[error("field selection of scalar type `{type_name}` must not have subselections")]
231 SubselectionOnScalarType {
232 type_name: NamedType,
233 path: SelectionPath,
234 },
235
236 #[error("field selection of enum type `{type_name}` must not have subselections")]
237 SubselectionOnEnumType {
238 type_name: NamedType,
239 path: SelectionPath,
240 },
241
242 #[error("type `{type_name}` does not have a field `{field_name}`")]
243 UndefinedField {
244 type_name: NamedType,
245 field_name: Name,
246 path: SelectionPath,
247 },
248
249 #[error(
251 "{} can only have one root field",
252 subscription_name_or_anonymous(name)
253 )]
254 SubscriptionUsesMultipleFields {
255 name: Option<Name>,
256 fields: Vec<Name>,
257 },
258
259 #[error(
260 "{} can not have an introspection field as a root field",
261 subscription_name_or_anonymous(name)
262 )]
263 SubscriptionUsesIntrospection {
264 name: Option<Name>,
266 field: Name,
268 },
269 #[error(
270 "{} can not specify @skip or @include on root fields",
271 subscription_name_or_anonymous(name)
272 )]
273 SubscriptionUsesConditionalSelection {
274 name: Option<Name>,
276 },
277
278 #[error("{0}")]
279 ConflictingFieldType(Box<ConflictingFieldType>),
280 #[error("{0}")]
281 ConflictingFieldArgument(Box<ConflictingFieldArgument>),
282 #[error("{0}")]
283 ConflictingFieldName(Box<ConflictingFieldName>),
284}
285
286#[derive(thiserror::Error, Debug, Clone)]
287#[error("operation must not select different types using the same name `{alias}`")]
288pub(crate) struct ConflictingFieldType {
289 pub(crate) alias: Name,
291 pub(crate) original_location: Option<SourceSpan>,
292 pub(crate) original_coordinate: TypeAttributeCoordinate,
293 pub(crate) original_type: Type,
294 pub(crate) conflicting_location: Option<SourceSpan>,
295 pub(crate) conflicting_coordinate: TypeAttributeCoordinate,
296 pub(crate) conflicting_type: Type,
297}
298
299#[derive(thiserror::Error, Debug, Clone)]
300#[error("operation must not provide conflicting field arguments for the same name `{alias}`")]
301pub(crate) struct ConflictingFieldArgument {
302 pub(crate) alias: Name,
304 pub(crate) original_location: Option<SourceSpan>,
305 pub(crate) original_coordinate: FieldArgumentCoordinate,
306 pub(crate) original_value: Option<Value>,
307 pub(crate) conflicting_location: Option<SourceSpan>,
308 pub(crate) conflicting_coordinate: FieldArgumentCoordinate,
309 pub(crate) conflicting_value: Option<Value>,
310}
311
312#[derive(thiserror::Error, Debug, Clone)]
313#[error("cannot select different fields into the same alias `{alias}`")]
314pub(crate) struct ConflictingFieldName {
315 pub(crate) alias: Name,
317 pub(crate) original_location: Option<SourceSpan>,
318 pub(crate) original_selection: TypeAttributeCoordinate,
319 pub(crate) conflicting_location: Option<SourceSpan>,
320 pub(crate) conflicting_selection: TypeAttributeCoordinate,
321}
322
323fn subscription_name_or_anonymous(name: &Option<Name>) -> impl std::fmt::Display + '_ {
324 crate::validation::diagnostics::NameOrAnon {
325 name: name.as_ref(),
326 if_some_prefix: "subscription",
327 if_none: "anonymous subscription",
328 }
329}
330
331#[derive(Debug, Clone, PartialEq, Eq)]
332pub(crate) struct SelectionPath {
333 pub(crate) root: ExecutableDefinitionName,
334 pub(crate) nested_fields: Vec<Name>,
335}
336
337#[derive(Debug, Clone, PartialEq, Eq)]
339pub(crate) enum ExecutableDefinitionName {
340 AnonymousOperation(ast::OperationType),
341 NamedOperation(ast::OperationType, Name),
342 Fragment(Name),
343}
344
345impl ExecutableDocument {
346 pub fn new() -> Self {
348 Self::default()
349 }
350
351 #[allow(clippy::result_large_err)] pub fn parse(
359 schema: &Valid<Schema>,
360 source_text: impl Into<String>,
361 path: impl AsRef<Path>,
362 ) -> Result<Self, WithErrors<Self>> {
363 Parser::new().parse_executable(schema, source_text, path)
364 }
365
366 #[allow(clippy::result_large_err)] pub fn parse_and_validate(
370 schema: &Valid<Schema>,
371 source_text: impl Into<String>,
372 path: impl AsRef<Path>,
373 ) -> Result<Valid<Self>, WithErrors<Self>> {
374 let (doc, mut errors) = Parser::new().parse_executable_inner(schema, source_text, path);
375 Arc::make_mut(&mut errors.sources)
376 .extend(schema.sources.iter().map(|(k, v)| (*k, v.clone())));
377 validation::validate_executable_document(&mut errors, schema, &doc);
378 errors.into_valid_result(doc)
379 }
380
381 #[allow(clippy::result_large_err)] pub fn validate(self, schema: &Valid<Schema>) -> Result<Valid<Self>, WithErrors<Self>> {
383 let mut sources = IndexMap::clone(&schema.sources);
384 sources.extend(self.sources.iter().map(|(k, v)| (*k, v.clone())));
385 let mut errors = DiagnosticList::new(Arc::new(sources));
386 validation::validate_executable_document(&mut errors, schema, &self);
387 errors.into_valid_result(self)
388 }
389
390 serialize_method!();
391}
392
393impl Eq for ExecutableDocument {}
394
395impl PartialEq for ExecutableDocument {
397 fn eq(&self, other: &Self) -> bool {
398 let Self {
399 sources: _,
400 operations,
401 fragments,
402 } = self;
403 *operations == other.operations && *fragments == other.fragments
404 }
405}
406
407impl OperationMap {
408 pub fn from_one(operation: impl Into<Node<Operation>>) -> Self {
410 let mut map = Self::default();
411 map.insert(operation);
412 map
413 }
414
415 pub fn is_empty(&self) -> bool {
416 self.anonymous.is_none() && self.named.is_empty()
417 }
418
419 pub fn len(&self) -> usize {
420 self.anonymous.is_some() as usize + self.named.len()
421 }
422
423 pub fn iter(&self) -> impl Iterator<Item = &'_ Node<Operation>> {
425 self.anonymous
426 .as_ref()
427 .into_iter()
428 .chain(self.named.values())
429 }
430
431 pub fn get(&self, name_request: Option<&str>) -> Result<&Node<Operation>, RequestError> {
442 if let Some(name) = name_request {
443 self.named
445 .get(name)
446 .ok_or_else(|| format!("No operation named '{name}'"))
447 } else {
448 if let Some(op) = &self.anonymous {
450 self.named.is_empty().then_some(op)
452 } else {
453 self.named
455 .values()
456 .next()
457 .and_then(|op| (self.named.len() == 1).then_some(op))
458 }
459 .ok_or_else(|| {
460 "Ambiguous request: multiple operations but no specified `operationName`".to_owned()
461 })
462 }
463 .map_err(|message| RequestError {
464 message,
465 location: None,
466 is_suspected_validation_bug: false,
467 })
468 }
469
470 pub fn get_mut(&mut self, name_request: Option<&str>) -> Result<&mut Operation, RequestError> {
472 if let Some(name) = name_request {
473 self.named
475 .get_mut(name)
476 .ok_or_else(|| format!("No operation named '{name}'"))
477 } else {
478 if let Some(op) = &mut self.anonymous {
480 self.named.is_empty().then_some(op)
482 } else {
483 let len = self.named.len();
485 self.named
486 .values_mut()
487 .next()
488 .and_then(|op| (len == 1).then_some(op))
489 }
490 .ok_or_else(|| {
491 "Ambiguous request: multiple operations but no specified `operationName`".to_owned()
492 })
493 }
494 .map(Node::make_mut)
495 .map_err(|message| RequestError {
496 message,
497 location: None,
498 is_suspected_validation_bug: false,
499 })
500 }
501
502 pub fn insert(&mut self, operation: impl Into<Node<Operation>>) -> Option<Node<Operation>> {
505 let operation = operation.into();
506 if let Some(name) = &operation.name {
507 self.named.insert(name.clone(), operation)
508 } else {
509 self.anonymous.replace(operation)
510 }
511 }
512}
513
514impl Operation {
515 pub fn object_type(&self) -> &NamedType {
517 &self.selection_set.ty
518 }
519
520 pub fn is_query(&self) -> bool {
522 self.operation_type == OperationType::Query
523 }
524
525 pub fn is_mutation(&self) -> bool {
527 self.operation_type == OperationType::Mutation
528 }
529
530 pub fn is_subscription(&self) -> bool {
532 self.operation_type == OperationType::Subscription
533 }
534
535 pub fn is_introspection(&self, document: &ExecutableDocument) -> bool {
538 self.is_query()
539 && self
540 .root_fields(document)
541 .all(|field| matches!(field.name.as_str(), "__type" | "__schema" | "__typename"))
542 }
543
544 pub fn root_fields<'doc>(
559 &'doc self,
560 document: &'doc ExecutableDocument,
561 ) -> impl Iterator<Item = &'doc Node<Field>> {
562 self.selection_set.root_fields(document)
563 }
564
565 pub fn all_fields<'doc>(
578 &'doc self,
579 document: &'doc ExecutableDocument,
580 ) -> impl Iterator<Item = &'doc Node<Field>> {
581 self.selection_set.all_fields(document)
582 }
583
584 serialize_method!();
585}
586
587impl Fragment {
588 pub fn type_condition(&self) -> &NamedType {
589 &self.selection_set.ty
590 }
591
592 serialize_method!();
593}
594
595impl SelectionSet {
596 pub fn new(ty: NamedType) -> Self {
598 Self {
599 ty,
600 selections: Vec::new(),
601 }
602 }
603
604 pub fn is_empty(&self) -> bool {
605 self.selections.is_empty()
606 }
607
608 pub fn push(&mut self, selection: impl Into<Selection>) {
609 self.selections.push(selection.into())
610 }
611
612 pub fn extend(&mut self, selections: impl IntoIterator<Item = impl Into<Selection>>) {
613 self.selections
614 .extend(selections.into_iter().map(|sel| sel.into()))
615 }
616
617 pub fn new_field<'schema>(
622 &self,
623 schema: &'schema Schema,
624 name: Name,
625 ) -> Result<Field, schema::FieldLookupError<'schema>> {
626 let definition = schema.type_field(&self.ty, &name)?.node.clone();
627 Ok(Field::new(name, definition))
628 }
629
630 pub fn new_inline_fragment(&self, opt_type_condition: Option<NamedType>) -> InlineFragment {
632 if let Some(type_condition) = opt_type_condition {
633 InlineFragment::with_type_condition(type_condition)
634 } else {
635 InlineFragment::without_type_condition(self.ty.clone())
636 }
637 }
638
639 pub fn new_fragment_spread(&self, fragment_name: Name) -> FragmentSpread {
641 FragmentSpread::new(fragment_name)
642 }
643
644 pub fn fields(&self) -> impl Iterator<Item = &Node<Field>> {
648 self.selections.iter().filter_map(|sel| sel.as_field())
649 }
650
651 pub fn root_fields<'doc>(
666 &'doc self,
667 document: &'doc ExecutableDocument,
668 ) -> impl Iterator<Item = &'doc Node<Field>> {
669 let mut stack = vec![self.selections.iter()];
670 let mut fragments_seen = HashSet::default();
671 std::iter::from_fn(move || {
672 while let Some(selection_set_iter) = stack.last_mut() {
673 match selection_set_iter.next() {
674 Some(Selection::Field(field)) => {
675 return Some(field);
678 }
679 Some(Selection::InlineFragment(inline)) => {
680 stack.push(inline.selection_set.selections.iter())
681 }
682 Some(Selection::FragmentSpread(spread)) => {
683 if let Some(def) = document.fragments.get(&spread.fragment_name) {
684 let new = fragments_seen.insert(&spread.fragment_name);
685 if new {
686 stack.push(def.selection_set.selections.iter())
687 }
688 } else {
689 }
692 }
693 None => {
694 stack.pop();
697 }
698 }
699 }
700 None
701 })
702 }
703
704 pub fn all_fields<'doc>(
717 &'doc self,
718 document: &'doc ExecutableDocument,
719 ) -> impl Iterator<Item = &'doc Node<Field>> {
720 let mut stack = vec![self.selections.iter()];
721 let mut fragments_seen = HashSet::default();
722 std::iter::from_fn(move || {
723 while let Some(selection_set_iter) = stack.last_mut() {
724 match selection_set_iter.next() {
725 Some(Selection::Field(field)) => {
726 if !field.selection_set.is_empty() {
727 stack.push(field.selection_set.selections.iter())
729 }
730 return Some(field);
732 }
733 Some(Selection::InlineFragment(inline)) => {
734 stack.push(inline.selection_set.selections.iter())
735 }
736 Some(Selection::FragmentSpread(spread)) => {
737 if let Some(def) = document.fragments.get(&spread.fragment_name) {
738 let new = fragments_seen.insert(&spread.fragment_name);
739 if new {
740 stack.push(def.selection_set.selections.iter())
741 }
742 } else {
743 }
746 }
747 None => {
748 stack.pop();
751 }
752 }
753 }
754 None
755 })
756 }
757
758 serialize_method!();
759}
760
761impl Selection {
762 pub fn directives(&self) -> &DirectiveList {
763 match self {
764 Self::Field(sel) => &sel.directives,
765 Self::FragmentSpread(sel) => &sel.directives,
766 Self::InlineFragment(sel) => &sel.directives,
767 }
768 }
769
770 pub fn as_field(&self) -> Option<&Node<Field>> {
771 if let Self::Field(field) = self {
772 Some(field)
773 } else {
774 None
775 }
776 }
777
778 pub fn as_inline_fragment(&self) -> Option<&Node<InlineFragment>> {
779 if let Self::InlineFragment(inline) = self {
780 Some(inline)
781 } else {
782 None
783 }
784 }
785
786 pub fn as_fragment_spread(&self) -> Option<&Node<FragmentSpread>> {
787 if let Self::FragmentSpread(spread) = self {
788 Some(spread)
789 } else {
790 None
791 }
792 }
793
794 serialize_method!();
795}
796
797impl From<Node<Field>> for Selection {
798 fn from(node: Node<Field>) -> Self {
799 Self::Field(node)
800 }
801}
802
803impl From<Node<InlineFragment>> for Selection {
804 fn from(node: Node<InlineFragment>) -> Self {
805 Self::InlineFragment(node)
806 }
807}
808
809impl From<Node<FragmentSpread>> for Selection {
810 fn from(node: Node<FragmentSpread>) -> Self {
811 Self::FragmentSpread(node)
812 }
813}
814
815impl From<Field> for Selection {
816 fn from(value: Field) -> Self {
817 Self::Field(Node::new(value))
818 }
819}
820
821impl From<InlineFragment> for Selection {
822 fn from(value: InlineFragment) -> Self {
823 Self::InlineFragment(Node::new(value))
824 }
825}
826
827impl From<FragmentSpread> for Selection {
828 fn from(value: FragmentSpread) -> Self {
829 Self::FragmentSpread(Node::new(value))
830 }
831}
832
833impl Field {
834 pub fn new(name: Name, definition: Node<schema::FieldDefinition>) -> Self {
838 let selection_set = SelectionSet::new(definition.ty.inner_named_type().clone());
839 Field {
840 definition,
841 alias: None,
842 name,
843 arguments: Vec::new(),
844 directives: DirectiveList::new(),
845 selection_set,
846 }
847 }
848
849 pub fn with_alias(mut self, alias: Name) -> Self {
850 self.alias = Some(alias);
851 self
852 }
853
854 pub fn with_opt_alias(mut self, alias: Option<Name>) -> Self {
855 self.alias = alias;
856 self
857 }
858
859 pub fn with_directive(mut self, directive: impl Into<Node<Directive>>) -> Self {
860 self.directives.push(directive.into());
861 self
862 }
863
864 pub fn with_directives(
865 mut self,
866 directives: impl IntoIterator<Item = Node<Directive>>,
867 ) -> Self {
868 self.directives.extend(directives);
869 self
870 }
871
872 pub fn with_argument(mut self, name: Name, value: impl Into<Node<Value>>) -> Self {
873 self.arguments.push((name, value).into());
874 self
875 }
876
877 pub fn with_arguments(mut self, arguments: impl IntoIterator<Item = Node<Argument>>) -> Self {
878 self.arguments.extend(arguments);
879 self
880 }
881
882 pub fn with_selection(mut self, selection: impl Into<Selection>) -> Self {
883 self.selection_set.push(selection);
884 self
885 }
886
887 pub fn with_selections(
888 mut self,
889 selections: impl IntoIterator<Item = impl Into<Selection>>,
890 ) -> Self {
891 self.selection_set.extend(selections);
892 self
893 }
894
895 pub fn response_key(&self) -> &Name {
897 self.alias.as_ref().unwrap_or(&self.name)
898 }
899
900 pub fn ty(&self) -> &Type {
902 &self.definition.ty
903 }
904
905 pub fn inner_type_def<'a>(&self, schema: &'a Schema) -> Option<&'a schema::ExtendedType> {
909 schema.types.get(self.ty().inner_named_type())
910 }
911
912 pub fn argument_by_name(&self, name: &str) -> Result<&Node<Value>, ArgumentByNameError> {
915 Argument::argument_by_name(&self.arguments, name, || {
916 self.definition
917 .argument_by_name(name)
918 .ok_or(ArgumentByNameError::NoSuchArgument)
919 })
920 }
921
922 pub fn specified_argument_by_name(&self, name: &str) -> Option<&Node<Value>> {
929 Argument::specified_argument_by_name(&self.arguments, name)
930 }
931
932 serialize_method!();
933}
934
935impl InlineFragment {
936 pub fn with_type_condition(type_condition: NamedType) -> Self {
937 let selection_set = SelectionSet::new(type_condition.clone());
938 Self {
939 type_condition: Some(type_condition),
940 directives: DirectiveList::new(),
941 selection_set,
942 }
943 }
944
945 pub fn without_type_condition(parent_selection_set_type: NamedType) -> Self {
946 Self {
947 type_condition: None,
948 directives: DirectiveList::new(),
949 selection_set: SelectionSet::new(parent_selection_set_type),
950 }
951 }
952
953 pub fn with_directive(mut self, directive: impl Into<Node<Directive>>) -> Self {
954 self.directives.push(directive.into());
955 self
956 }
957
958 pub fn with_directives(
959 mut self,
960 directives: impl IntoIterator<Item = Node<Directive>>,
961 ) -> Self {
962 self.directives.extend(directives);
963 self
964 }
965
966 pub fn with_selection(mut self, selection: impl Into<Selection>) -> Self {
967 self.selection_set.push(selection);
968 self
969 }
970
971 pub fn with_selections(
972 mut self,
973 selections: impl IntoIterator<Item = impl Into<Selection>>,
974 ) -> Self {
975 self.selection_set.extend(selections);
976 self
977 }
978
979 serialize_method!();
980}
981
982impl FragmentSpread {
983 pub fn new(fragment_name: Name) -> Self {
984 Self {
985 fragment_name,
986 directives: DirectiveList::new(),
987 }
988 }
989
990 pub fn with_directive(mut self, directive: impl Into<Node<Directive>>) -> Self {
991 self.directives.push(directive.into());
992 self
993 }
994
995 pub fn with_directives(
996 mut self,
997 directives: impl IntoIterator<Item = Node<Directive>>,
998 ) -> Self {
999 self.directives.extend(directives);
1000 self
1001 }
1002
1003 pub fn fragment_def<'a>(&self, document: &'a ExecutableDocument) -> Option<&'a Node<Fragment>> {
1004 document.fragments.get(&self.fragment_name)
1005 }
1006
1007 serialize_method!();
1008}
1009
1010impl FieldSet {
1011 pub fn parse(
1018 schema: &Valid<Schema>,
1019 type_name: NamedType,
1020 source_text: impl Into<String>,
1021 path: impl AsRef<Path>,
1022 ) -> Result<FieldSet, WithErrors<FieldSet>> {
1023 Parser::new().parse_field_set(schema, type_name, source_text, path)
1024 }
1025
1026 pub fn parse_and_validate(
1029 schema: &Valid<Schema>,
1030 type_name: NamedType,
1031 source_text: impl Into<String>,
1032 path: impl AsRef<Path>,
1033 ) -> Result<Valid<Self>, WithErrors<Self>> {
1034 let (field_set, mut errors) =
1035 Parser::new().parse_field_set_inner(schema, type_name, source_text, path);
1036 validation::validate_field_set(&mut errors, schema, &field_set);
1037 errors.into_valid_result(field_set)
1038 }
1039
1040 pub fn validate(&self, schema: &Valid<Schema>) -> Result<(), DiagnosticList> {
1041 let mut sources = IndexMap::clone(&schema.sources);
1042 sources.extend(self.sources.iter().map(|(k, v)| (*k, v.clone())));
1043 let mut errors = DiagnosticList::new(Arc::new(sources));
1044 validation::validate_field_set(&mut errors, schema, self);
1045 errors.into_result()
1046 }
1047
1048 serialize_method!();
1049}
1050
1051impl fmt::Display for SelectionPath {
1052 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1053 match &self.root {
1054 ExecutableDefinitionName::AnonymousOperation(operation_type) => {
1055 write!(f, "{operation_type}")?
1056 }
1057 ExecutableDefinitionName::NamedOperation(operation_type, name) => {
1058 write!(f, "{operation_type} {name}")?
1059 }
1060 ExecutableDefinitionName::Fragment(name) => write!(f, "fragment {name}")?,
1061 }
1062 for name in &self.nested_fields {
1063 write!(f, " → {name}")?
1064 }
1065 Ok(())
1066 }
1067}