-
Notifications
You must be signed in to change notification settings - Fork 426
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
Ensure Specification(June 2018) Compliance #631
Conversation
- Removed proc-macro-error -> not required -> use syn::Error - Everything below lib.rs uses proc_macro2::TokenStream instead of proc_macro::TokenStream - Replaced error handling in attribute parsers
Before I continue, I would like to get some feedback for the implemented error handling (@LegNeato). I wonder if the current design is acceptable or are there any problems? Why?A change is preferable because panics messages are not precise. Instead
Since there are errors shared between the different implementations, there are shortcuts for shared errors (including no duplicates, not empty, etc.). Errors which are unique are also propagated through the error framework. To let the error generator know what kind of macro is used, all macros must provide a context at the beginning. This context is used to generate prefixes like |
This is perfect and very close to what I was planning on doing when I got some time. Thank you! I wonder if instead of referring to the derive we refer to "GraphQL" in general as most of these aren't requirement of the derive but instead a spec requirement. So error: #[derive(GraphQLObject)] does not allow multiple fields/variants with the same name. There is at least one other field with the same name `test`
--> $DIR/derive_fields_unique.rs:4:5 Becomes error: GraphQL objects must not contain multiple fields/variants with the same name. There is at least one other field with the same name `test`
--> $DIR/derive_fields_unique.rs:4:5
| What do you think? |
And maybe an optional link to the spec section? |
Thanks for the response. That is a good idea. I wonder if we should use https://docs.rs/proc-macro-error/1.0.2/proc_macro_error/struct.Diagnostic.html for errors. This allows to specify |
That sounds like a good plan, we already were thinking about it: |
The proc-macro-error crate is nice to use. With your previous feedback, an error looks like the following.
As you can see there are errors located in the benchmark module which tries to implement empty objects. What should be done here? Remove the non-compiling snippets? The current implementation wraps all parsed attributes into a |
I think benches is just an oversight. We can use For |
|
@LegNeato maybe you can resolve this question. Resolver functions for objects, e.g.,
Edit: Looks like there are more functions than the ~10 functions, I previously found. I assume that all four functions should be accepted?! |
Oh weird! AFAIK we should have tests for this. The two middle should compile, the first and last should not. &self is required and context is optional (as is the executor) but if it is there it needs to be a reference. |
Ah, what I remember seeing is for the resolve function: It looks like we don't require I think it makes sense to always require |
Having the requirement for An obvious downside is the breaking change which may result in changing a lot of functions. However, currently I tend to introduce the breaking but I am not fully convinced. |
This release is already breaking a ton so let's just do it. |
- removed support for Scalar within a string ("DefaultScalarValue") - removed unraw function and replaced it with the built-in one - added error messages and return types for all functions within utils - added more constraints to fulfill the GraphQL spec
This PR is getting a little bit larger. I had to refactor the GraphQLInputObject which allows applying my error scheme. Now the GraphQLInputObject has a similar form like GraphQLObject and the others. Since GraphQLInputObject was the last construct which used a different argument parse, it now does not allow using string scalars like "DefaultScalarValue". I mentioned this breaking change in the changelog. One last thing, since GraphQLInputObject is missing the async trait, some of the tests fail with a different error message. So there are two possibilities:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like rustfmt
is failing:
Diff in /home/vsts/work/1/s/integration_tests/juniper_tests/src/codegen/derive_object.rs at line 387:
f((type_info, fields));
}
-
Happy to either disable those tests and do a followup or have you do the async change here...whatever is easier for you!
Thanks for your review. Additionally, I added a marker trait to detect non-object within the context of unions. Now it is not possible to use non-objects as values for unions. Besides your recommendations, I added the Finally there is support to rename an argument inside an object impl block. This was required to test the |
I notice that interface testing is not possible at the moment, since it is still a declarative macro. Enforcing the requirements of the specification seems not possible. I disabled the test. After the macro is replaced the test should be re-enabled. Maybe you can take a close look at the GraphQLTypeAsync impl for input objects. The input object now implements the async type. No functions are required to implement for the async trait since input objects are constructed by the other two traits (ToInputValue, FromInputValue)?! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking awesome! Thank you again for your hard work.
We're having issues with the panic message tests, as the note is included on nightly but not on stable...so the tests pass on nightly but fail on stable even though everything is ok. That is kinda annoying.
We have a way to run crates in CI only on nightly (see the rocket integration, it is basically dropping a cargo-make
file in the crate) so perhaps we should pull these out into their own crate under https://github.com/graphql-rust/juniper/tree/master/integration_tests and have it only run on nightly? Is there any way we can switch between expected output automatically based on what toolchain is running the tests?
Nightly and stable produce different outputs, thus only test nightly.
The only way to switch the expected output is to have two crates with different expected output. But testing only on nightly should be fine. This way we notice possible changes since. Stable does not implement most of the features, thus the output should not change at all (until the |
Excellent! I think we just need to record the output again and we're good to merge! |
Implementing the constraints that arguments have the property $crate::__juniper_impl_trait!(
impl<$($scalar)* $(, $lifetimes)* > GraphQLType for $name {
fn mark() {
$(
<$return_ty as $crate::marker::IsOutputType<$($scalar)*>::mark();
)*
}
}
); The reason why this does not compile is because of the nested |
Yeah, the plan is to remove all macros and replace them with proc macros in this release for just that reason. We just did so a couple weeks ago with The declarative macros were from way back from when proc macros were not available on stable. If you want to skip that check in this PR so we can land it I'm totally fine with that. Also, I'd love to add you as a maintainer for Juniper, let me know if you would be interested. You're doing a ton of high-quality work. |
Thanks again! |
Motivation
Juniper currently produces code which is not allowed by the GraphQL specification. To ensure that these errors are fixed, a test suite is required. The test suite ensures that configurations which are not compliant to the specification, can not successfully compile.
Implementation
Each GraphQL type has a
Type Validation
chapter. Therefore, each of the constraints must be checked. An isolated Rust source snippet is created for each of these constraints. An external library compiles these snippets. The library ensures that the output of the compilation process is equal to an expected output. With the process it is ensured that these problems can not reoccur silently in the future.Goals (Progress)
Related