Skip to content

Commit 46701aa

Browse files
authored
Cleanup code, and allow to use graphql_parser_hive_fork instead of graphql_parser (#60)
1 parent a6cdb8c commit 46701aa

38 files changed

+746
-593
lines changed

.github/workflows/ci.yaml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,15 @@ jobs:
1818
uses: Swatinem/rust-cache@v1
1919

2020
- name: Test Rust
21-
run: cargo test
21+
run: |
22+
# features=graphql_parser_fork
23+
cargo test --features graphql_parser_fork --no-default-features
24+
# features=graphql_parser
25+
cargo test
2226
2327
- name: Build Rust
24-
run: cargo build --release
28+
run: |
29+
# features=graphql_parser_fork
30+
cargo build --release --features graphql_parser_fork --no-default-features
31+
# features=graphql_parser
32+
cargo build --release

Cargo.lock

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

Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,14 @@ documentation = "https://github.com/dotansimha/graphql-tools-rs"
1111
authors = ["Dotan Simha <[email protected]>"]
1212

1313
[dependencies]
14-
graphql-parser = "^0.4.0"
14+
graphql-parser = { version = "^0.4.0", optional = true }
15+
graphql-parser-hive-fork = { version = "^0.5.0", optional = true }
1516
lazy_static = "1.4.0"
1617
serde = { version = "1.0", features = ["derive"] }
1718
serde_json = "1.0"
1819
serde_with = "2.2.0"
1920

20-
[dev-dependencies]
21-
graphql-parser = "0.4.0"
21+
[features]
22+
default = ["graphql_parser"]
23+
graphql_parser_fork = ["dep:graphql-parser-hive-fork"]
24+
graphql_parser = ["dep:graphql-parser"]

README.md

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
[Documentation](https://docs.rs/graphql-tools) | [Crate](https://crates.io/crates/graphql-tools) | [GitHub](https://github.com/dotansimha/graphql-tools-rs)
44

5-
> **Note: this crate is still under development (see roadmap below)**
6-
75
The [`graphql_tools` crate](https://crates.io/crates/graphql-tools) implements tooling around GraphQL for Rust libraries. Most of the tools are based on `trait`s and `struct`s implemented in [`graphql_parser` crate](https://crates.io/crates/graphql-parser).
86

97
The goal of this library is to create a common layer of tools that has similar/improved APIs to [`graphql-js` reference implementation](https://github.com/graphql/graphql-js) and [`graphql-tools` from the JS/TS ecosystem](https://github.com/ardatan/graphql-tools).
@@ -25,23 +23,16 @@ Or, if you are using [`cargo-edit`](https://github.com/killercup/cargo-edit):
2523
cargo add graphql-tools
2624
```
2725

28-
### Roadmap and progress
29-
30-
- [ ] Better documentation
31-
- [x] AST Visitor for GraphQL schema (`graphql_parser::schema::Document`)
32-
- [x] AST Visitor for GraphQL operations (`graphql_parser::operation::Document`)
33-
- [x] AST Visitor with TypeInfo
34-
- [x] AST tools (ongoing)
35-
- [x] `struct` extensions
36-
- [x] GraphQL Validation engine
37-
- [x] Validation rules
38-
- [x] GraphQL operations transformer
26+
By default, this crate is using the [`graphql-parser`](https://github.com/graphql-rust/graphql-parser) library for parsing. If you wish to use an alternative implementation such as [`graphql-hive/graphql-parser-hive-fork`](https://github.com/graphql-hive/graphql-parser-hive-fork), use the following `features` setup:
3927

40-
> If you have an idea / missing feature, feel free to open an issue / start a GitHub discussion!
28+
```toml
29+
[dependencies]
30+
graphql-tools = { version = "...", features = "graphql_parser_fork", default-features = false }
31+
```
4132

4233
#### Validation Rules
4334

44-
> This comparison is based on `graphql-js` refernece implementation.
35+
> This comparison is based on `graphql-js` refernece implementation.
4536
4637
- [x] ExecutableDefinitions (not actually needed)
4738
- [x] UniqueOperationNames
@@ -68,4 +59,4 @@ cargo add graphql-tools
6859
- [x] ProvidedRequiredArguments
6960
- [x] VariablesInAllowedPosition
7061
- [x] OverlappingFieldsCanBeMerged
71-
- [ ] UniqueInputFieldNames (blocked by https://github.com/graphql-rust/graphql-parser/issues/59)
62+
- [ ] UniqueInputFieldNames (blocked by https://github.com/graphql-rust/graphql-parser/issues/59)

src/ast/collect_fields.rs

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn does_fragment_condition_match<'a>(
4747
return interface_type.is_implemented_by(current_selection_set_type)
4848
}
4949
TypeDefinition::Union(union_type) => {
50-
return union_type.has_sub_type(&current_selection_set_type.name())
50+
return union_type.has_sub_type(current_selection_set_type.name())
5151
}
5252
_ => return false,
5353
}
@@ -70,14 +70,14 @@ fn collect_fields_inner<'a>(
7070
) {
7171
selection_set.items.iter().for_each(|item| match item {
7272
Selection::Field(f) => {
73-
let existing = result_arr.entry(f.name.clone()).or_insert(vec![]);
73+
let existing = result_arr.entry(f.name.clone()).or_default();
7474
existing.push(f.clone());
7575
}
7676
Selection::InlineFragment(f) => {
7777
if does_fragment_condition_match(&f.type_condition, parent_type, context) {
7878
collect_fields_inner(
7979
&f.selection_set,
80-
&parent_type,
80+
parent_type,
8181
known_fragments,
8282
context,
8383
result_arr,
@@ -86,22 +86,21 @@ fn collect_fields_inner<'a>(
8686
}
8787
}
8888
Selection::FragmentSpread(f) => {
89-
if visited_fragments_names
89+
if !visited_fragments_names
9090
.iter()
91-
.find(|name| f.fragment_name.eq(*name))
92-
.is_none()
91+
.any(|name| f.fragment_name.eq(name))
9392
{
9493
visited_fragments_names.push(f.fragment_name.clone());
9594

9695
if let Some(fragment) = known_fragments.get(f.fragment_name.as_str()) {
9796
if does_fragment_condition_match(
9897
&Some(fragment.type_condition.clone()),
99-
&parent_type,
98+
parent_type,
10099
context,
101100
) {
102101
collect_fields_inner(
103102
&fragment.selection_set,
104-
&parent_type,
103+
parent_type,
105104
known_fragments,
106105
context,
107106
result_arr,

src/ast/ext.rs

Lines changed: 19 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl OperationDefinitionExtension for OperationDefinition {
5757
fn selection_set(&self) -> &SelectionSet {
5858
match self {
5959
OperationDefinition::Query(query) => &query.selection_set,
60-
OperationDefinition::SelectionSet(selection_set) => &selection_set,
60+
OperationDefinition::SelectionSet(selection_set) => selection_set,
6161
OperationDefinition::Mutation(mutation) => &mutation.selection_set,
6262
OperationDefinition::Subscription(subscription) => &subscription.selection_set,
6363
}
@@ -156,7 +156,7 @@ impl SchemaDocumentExtension for schema::Document {
156156
self.schema_definition()
157157
.subscription
158158
.as_ref()
159-
.and_then(|name| self.object_type_by_name(&name))
159+
.and_then(|name| self.object_type_by_name(name))
160160
}
161161

162162
fn object_type_by_name(&self, name: &str) -> Option<&ObjectType> {
@@ -185,7 +185,7 @@ impl SchemaDocumentExtension for schema::Document {
185185
self.type_by_name(sub_type_name),
186186
self.type_by_name(super_type_name),
187187
) {
188-
super_type.is_abstract_type() && self.is_possible_type(&super_type, &sub_type)
188+
super_type.is_abstract_type() && self.is_possible_type(super_type, sub_type)
189189
} else {
190190
false
191191
}
@@ -206,7 +206,7 @@ impl SchemaDocumentExtension for schema::Document {
206206
TypeDefinition::Interface(interface_typedef) => {
207207
let implementes_interfaces = possible_type.interfaces();
208208

209-
return implementes_interfaces.contains(&interface_typedef.name);
209+
implementes_interfaces.contains(&interface_typedef.name)
210210
}
211211
_ => false,
212212
}
@@ -248,12 +248,12 @@ impl SchemaDocumentExtension for schema::Document {
248248
// If superType type is an abstract type, check if it is super type of maybeSubType.
249249
// Otherwise, the child type is not a valid subtype of the parent type.
250250
if let (Some(sub_type), Some(super_type)) = (
251-
self.type_by_name(&sub_type.inner_type()),
252-
self.type_by_name(&super_type.inner_type()),
251+
self.type_by_name(sub_type.inner_type()),
252+
self.type_by_name(super_type.inner_type()),
253253
) {
254254
return super_type.is_abstract_type()
255255
&& (sub_type.is_interface_type() || sub_type.is_object_type())
256-
&& self.is_possible_type(&super_type, &sub_type);
256+
&& self.is_possible_type(super_type, sub_type);
257257
}
258258

259259
false
@@ -350,7 +350,7 @@ pub trait InputValueHelpers {
350350
impl InputValueHelpers for InputValue {
351351
fn is_required(&self) -> bool {
352352
if let Type::NonNullType(_inner_type) = &self.value_type {
353-
if let None = &self.default_value {
353+
if self.default_value.is_none() {
354354
return true;
355355
}
356356
}
@@ -394,22 +394,20 @@ impl ImplementingInterfaceExtension for TypeDefinition {
394394
fn has_sub_type(&self, other_type: &TypeDefinition) -> bool {
395395
match self {
396396
TypeDefinition::Interface(interface_type) => {
397-
return interface_type.is_implemented_by(other_type)
397+
interface_type.is_implemented_by(other_type)
398398
}
399399
TypeDefinition::Union(union_type) => return union_type.has_sub_type(other_type.name()),
400-
_ => return false,
400+
_ => false,
401401
}
402402
}
403403

404404
fn has_concrete_sub_type(&self, concrete_type: &ObjectType) -> bool {
405405
match self {
406406
TypeDefinition::Interface(interface_type) => {
407-
return interface_type.is_implemented_by(concrete_type)
408-
}
409-
TypeDefinition::Union(union_type) => {
410-
return union_type.has_sub_type(&concrete_type.name)
407+
interface_type.is_implemented_by(concrete_type)
411408
}
412-
_ => return false,
409+
TypeDefinition::Union(union_type) => union_type.has_sub_type(&concrete_type.name),
410+
_ => false,
413411
}
414412
}
415413
}
@@ -487,17 +485,13 @@ pub trait SubTypeExtension {
487485

488486
impl SubTypeExtension for UnionType {
489487
fn has_sub_type(&self, other_type_name: &str) -> bool {
490-
self.types.iter().find(|v| other_type_name.eq(*v)).is_some()
488+
self.types.iter().any(|v| other_type_name.eq(v))
491489
}
492490
}
493491

494492
impl AbstractTypeDefinitionExtension for InterfaceType {
495493
fn is_implemented_by(&self, other_type: &dyn ImplementingInterfaceExtension) -> bool {
496-
other_type
497-
.interfaces()
498-
.iter()
499-
.find(|v| self.name.eq(*v))
500-
.is_some()
494+
other_type.interfaces().iter().any(|v| self.name.eq(v))
501495
}
502496
}
503497

@@ -627,31 +621,19 @@ impl TypeDefinitionExtension for schema::TypeDefinition {
627621
}
628622

629623
fn is_object_type(&self) -> bool {
630-
match self {
631-
schema::TypeDefinition::Object(_o) => true,
632-
_ => false,
633-
}
624+
matches!(self, schema::TypeDefinition::Object(_o))
634625
}
635626

636627
fn is_union_type(&self) -> bool {
637-
match self {
638-
schema::TypeDefinition::Union(_o) => true,
639-
_ => false,
640-
}
628+
matches!(self, schema::TypeDefinition::Union(_o))
641629
}
642630

643631
fn is_enum_type(&self) -> bool {
644-
match self {
645-
schema::TypeDefinition::Enum(_o) => true,
646-
_ => false,
647-
}
632+
matches!(self, schema::TypeDefinition::Enum(_o))
648633
}
649634

650635
fn is_scalar_type(&self) -> bool {
651-
match self {
652-
schema::TypeDefinition::Scalar(_o) => true,
653-
_ => false,
654-
}
636+
matches!(self, schema::TypeDefinition::Scalar(_o))
655637
}
656638
}
657639

0 commit comments

Comments
 (0)