Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SchemaVisitor and QueryVisitor traits and functions #26

Closed
wants to merge 4 commits into from

Conversation

davidpdrsn
Copy link
Contributor

Fixes #25

Implementation is based upon the description here https://github.com/rust-unofficial/patterns/blob/master/patterns/visitor.md

@tomhoule
Copy link
Member

It looks good to me on the whole! It's unsollicited, but if nobody else has the time, I could do a more in-depth review.

@davidpdrsn
Copy link
Contributor Author

@tomhoule that would be great 😊

Copy link
Member

@tomhoule tomhoule left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not the maintainer of this crate, but as far as I'm concerned it looks good :)


fn walk_fragment_definition<'ast, V: QueryVisitor<'ast>>(visitor: &mut V, node: &'ast FragmentDefinition) {
visitor.visit_fragment_definition(node);
}
Copy link
Member

@tomhoule tomhoule Sep 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to further walk down the fragment's selection?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in db9310e 👍


fn walk_inline_fragment<'ast, V: QueryVisitor<'ast>>(visitor: &mut V, node: &'ast InlineFragment) {
visitor.visit_inline_fragment(node);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as for fragments, would it make sense to visit the selection set?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in cb71a7e 👍

Copy link
Member

@LegNeato LegNeato left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me.

@LegNeato
Copy link
Member

@tailhook will leave it to you to look at and land.

Copy link
Collaborator

@tailhook tailhook left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there are multiple mistakes with visiting recursively. I'm not sure how to structure code or how to test it well to eliminate these bugs.

(sorry that it took so long...)

Comment on lines +202 to +203
visitor.visit_field(inner);
walk_field(visitor, inner);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this pattern. You first do visit_field and then walk_field which calls visit_field again. Same with fragments. Am I misunderstanding something?

Copy link

@vladinator1000 vladinator1000 Jul 6, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a similar question. It seems that every walk function calls visit_node and then then calls a walk_node function that calls the same visit_node. For example walk_subscription calls visitor.visit_selection_set and then calls walk_selection_set which in turn calls visitor.visit_selection_set a second time.

Is that how it's supposed to work? I thought you only need to visit once.

//!
//! walk_document(&mut number_of_type, &doc);
//!
//! assert_eq!(number_of_type.count, 2);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. There are four fields if visiting recursively: query, id, country, id and single one if not (users). Currently it looks like you just counting users twice.

@tailhook
Copy link
Collaborator

tailhook commented Apr 1, 2020

It looks like there are multiple mistakes with visiting recursively.

Or was non-recursive visitor intentional?

This was referenced Apr 1, 2020
//! }
//!
//! fn main() {
//! let mut number_of_type = FieldsCounter::new();
Copy link

@spawnia spawnia Apr 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
//! let mut number_of_type = FieldsCounter::new();
//! let mut fields_counter = FieldsCounter::new();

number_of_type seems to indicate this is supposed to count types, not fields, which does not really make sense when walking over a query.

@vladinator1000
Copy link

Hi y'all, I'm gonna try another experimental flavor of an implementation for this, following the graphql-js interface. Here is my reasoning for this:

  1. enter would let you manipulate a node of the AST tree before entering its subtree
  2. leave would let you manipulate a node of the AST tree after its subtree has been visited
  3. It would pave the way for schema-aware visitors using a TypeInfo struct. Here's some example usage.

The biggest use-case of a system like this in my case is doing custom validation of a query based on a schema, this API lets you do that.

@dotansimha
Copy link

We implemented a visitor (with type info) for both schema and queries in https://github.com/dotansimha/graphql-tools-rs , also a (almost) spec-compliant validation phase.

Thanks for this PR, it was a great inspiration!

@davidpdrsn
Copy link
Contributor Author

@dotansimha why did you post this in 3 different places? 😅

@dotansimha
Copy link

dotansimha commented Jan 13, 2022

@dotansimha why did you post this in 3 different places? 😅

I saw these PRs are duplicated anyway, so I hope it would help someone :)
I'll delete if that's a problem ;) didn't plan to annoy anyone with notifications :x

@davidpdrsn
Copy link
Contributor Author

I'll close this for now. Its been a long time and I no longer have bandwidth to follow this through.

@davidpdrsn davidpdrsn closed this Mar 20, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Visitor trait?
7 participants