Skip to content

Commit 9ce5a94

Browse files
saihajdotansimha
andauthored
feat: No Fragment Cycle Rule (#8)
Co-authored-by: Dotan Simha <[email protected]>
1 parent 4428d43 commit 9ce5a94

File tree

6 files changed

+490
-15
lines changed

6 files changed

+490
-15
lines changed

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ cargo add graphql-tools
5555
- [x] KnownFragmentNames
5656
- [x] NoUnusedFragments
5757
- [ ] PossibleFragmentSpreads
58-
- [ ] NoFragmentCycles
58+
- [x] NoFragmentCycles
5959
- [ ] UniqueVariableNames
6060
- [ ] NoUndefinedVariables
6161
- [ ] NoUnusedVariables

src/ast/ext.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::static_graphql::query::{self};
1+
use crate::static_graphql::query::{self, FragmentSpread};
22
use crate::static_graphql::schema::{
33
self, Field, InterfaceType, ObjectType, TypeDefinition, UnionType,
44
};
@@ -237,3 +237,37 @@ impl AstNodeWithName for query::FragmentDefinition {
237237
Some(self.name.clone())
238238
}
239239
}
240+
241+
impl AstNodeWithName for query::FragmentSpread {
242+
fn node_name(&self) -> Option<String> {
243+
Some(self.fragment_name.clone())
244+
}
245+
}
246+
247+
pub trait FragmentSpreadExtraction {
248+
fn get_recursive_fragment_spreads(&self) -> Vec<FragmentSpread>;
249+
fn get_fragment_spreads(&self) -> Vec<FragmentSpread>;
250+
}
251+
252+
impl FragmentSpreadExtraction for query::SelectionSet {
253+
fn get_recursive_fragment_spreads(&self) -> Vec<FragmentSpread> {
254+
self.items
255+
.iter()
256+
.flat_map(|v| match v {
257+
query::Selection::FragmentSpread(f) => vec![f.clone()],
258+
query::Selection::Field(f) => f.selection_set.get_fragment_spreads(),
259+
query::Selection::InlineFragment(f) => f.selection_set.get_fragment_spreads(),
260+
})
261+
.collect()
262+
}
263+
264+
fn get_fragment_spreads(&self) -> Vec<FragmentSpread> {
265+
self.items
266+
.iter()
267+
.flat_map(|v| match v {
268+
query::Selection::FragmentSpread(f) => vec![f.clone()],
269+
_ => vec![],
270+
})
271+
.collect()
272+
}
273+
}

src/lib.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
pub mod ast;
99

1010
pub mod static_graphql {
11-
macro_rules! static_graphql {
11+
macro_rules! static_graphql {
1212
($m:ident, $m2:ident, {$($n:ident,)*}) => {
1313
pub mod $m {
1414
use graphql_parser::$m2 as $m;
@@ -20,16 +20,16 @@ pub mod static_graphql {
2020
};
2121
}
2222

23-
static_graphql!(query, query, {
24-
Document, Value, OperationDefinition, InlineFragment, TypeCondition,
25-
FragmentSpread, Field, Selection, SelectionSet, FragmentDefinition,
26-
Directive, VariableDefinition, Type, Query, Definition, Subscription, Mutation,
27-
});
28-
static_graphql!(schema, schema, {
29-
Field, Directive, InterfaceType, ObjectType, Value, TypeDefinition,
30-
EnumType, Type, Document, ScalarType, InputValue, DirectiveDefinition,
31-
UnionType, InputObjectType, EnumValue, SchemaDefinition,
32-
});
23+
static_graphql!(query, query, {
24+
Document, Value, OperationDefinition, InlineFragment, TypeCondition,
25+
FragmentSpread, Field, Selection, SelectionSet, FragmentDefinition,
26+
Directive, VariableDefinition, Type, Query, Definition, Subscription, Mutation,
27+
});
28+
static_graphql!(schema, schema, {
29+
Field, Directive, InterfaceType, ObjectType, Value, TypeDefinition,
30+
EnumType, Type, Document, ScalarType, InputValue, DirectiveDefinition,
31+
UnionType, InputObjectType, EnumValue, SchemaDefinition,
32+
});
3333
}
3434

3535
pub mod validation;

src/validation/rules/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ pub mod known_fragment_names;
55
pub mod known_type_names;
66
pub mod leaf_field_selections;
77
pub mod lone_anonymous_operation;
8+
pub mod no_fragments_cycle;
89
pub mod no_unused_fragments;
910
pub mod overlapping_fields_can_be_merged;
1011
/// Utilities validating GraphQL documents/operations
@@ -21,6 +22,7 @@ pub use self::known_fragment_names::*;
2122
pub use self::known_type_names::*;
2223
pub use self::leaf_field_selections::*;
2324
pub use self::lone_anonymous_operation::*;
25+
pub use self::no_fragments_cycle::*;
2426
pub use self::no_unused_fragments::*;
2527
pub use self::overlapping_fields_can_be_merged::*;
2628
pub use self::rule::*;

0 commit comments

Comments
 (0)