Merge branch 'master' into rework-core-traits

This commit is contained in:
tyranron 2022-05-12 17:28:18 +03:00
commit ffc42b16a1
No known key found for this signature in database
GPG key ID: 762E144FB230A4F0
18 changed files with 227 additions and 75 deletions

View file

@ -130,6 +130,7 @@ fn expand_on_trait(
.map(|c| c.inner().clone())
.collect(),
suppress_dead_code: None,
src_intra_doc_link: format!("trait@{}", trait_ident),
};
Ok(quote! {
@ -223,8 +224,8 @@ fn expand_on_derive_input(
) -> syn::Result<TokenStream> {
let attr = Attr::from_attrs("graphql_interface", &attrs)?;
let trait_ident = &ast.ident;
let trait_span = ast.span();
let struct_ident = &ast.ident;
let struct_span = ast.span();
let data = match &mut ast.data {
syn::Data::Struct(data) => data,
@ -241,13 +242,13 @@ fn expand_on_derive_input(
.name
.clone()
.map(SpanContainer::into_inner)
.unwrap_or_else(|| trait_ident.unraw().to_string());
.unwrap_or_else(|| struct_ident.unraw().to_string());
if !attr.is_internal && name.starts_with("__") {
ERR.no_double_underscore(
attr.name
.as_ref()
.map(SpanContainer::span_ident)
.unwrap_or_else(|| trait_ident.span()),
.unwrap_or_else(|| struct_ident.span()),
);
}
@ -270,10 +271,10 @@ fn expand_on_derive_input(
proc_macro_error::abort_if_dirty();
if fields.is_empty() {
ERR.emit_custom(trait_span, "must have at least one field");
ERR.emit_custom(struct_span, "must have at least one field");
}
if !field::all_different(&fields) {
ERR.emit_custom(trait_span, "must have a different name for each field");
ERR.emit_custom(struct_span, "must have a different name for each field");
}
proc_macro_error::abort_if_dirty();
@ -293,7 +294,7 @@ fn expand_on_derive_input(
})
.unwrap_or_else(|| parse_quote! { () });
let (enum_ident, enum_alias_ident) = enum_idents(trait_ident, attr.r#enum.as_deref());
let (enum_ident, enum_alias_ident) = enum_idents(struct_ident, attr.r#enum.as_deref());
let generated_code = Definition {
generics: ast.generics.clone(),
vis: ast.vis.clone(),
@ -310,6 +311,7 @@ fn expand_on_derive_input(
.map(|c| c.inner().clone())
.collect(),
suppress_dead_code: None,
src_intra_doc_link: format!("struct@{}", struct_ident),
};
Ok(quote! {

View file

@ -103,6 +103,7 @@ pub fn expand(input: TokenStream) -> syn::Result<TokenStream> {
.map(|c| c.inner().clone())
.collect(),
suppress_dead_code: Some((ast.ident.clone(), data.fields.clone())),
src_intra_doc_link: format!("struct@{}", struct_ident),
}
.into_token_stream())
}

View file

@ -327,6 +327,12 @@ struct Definition {
///
/// [1]: https://spec.graphql.org/June2018/#sec-Interfaces
suppress_dead_code: Option<(syn::Ident, syn::Fields)>,
/// Intra-doc link to the [`syn::Item`] defining this
/// [GraphQL interface][1].
///
/// [1]: https://spec.graphql.org/June2018/#sec-Interfaces
src_intra_doc_link: String,
}
impl ToTokens for Definition {
@ -358,7 +364,6 @@ impl Definition {
let par = format_ident!("__I{}", id);
parse_quote! { #par }
});
let variants_idents = self
.implemented_for
.iter()
@ -367,7 +372,6 @@ impl Definition {
let interface_gens = &self.generics;
let (interface_impl_gens, interface_ty_gens, interface_where_clause) =
self.generics.split_for_impl();
let (interface_gens_lifetimes, interface_gens_tys) = interface_gens
.params
.clone()
@ -381,13 +385,11 @@ impl Definition {
enum_gens.params.extend(interface_gens_tys.clone());
enum_gens
};
let enum_alias_gens = {
let mut enum_alias_gens = interface_gens.clone();
enum_alias_gens.move_bounds_to_where_clause();
enum_alias_gens
};
let enum_to_alias_gens = {
interface_gens_lifetimes
.into_iter()
@ -407,26 +409,42 @@ impl Definition {
rest => quote! { #rest },
}))
};
let enum_doc = format!(
"Enum building an opaque value represented by [`{}`]({}) \
[GraphQL interface][0].\
\n\n\
[0]: https://spec.graphql.org/June2018/#sec-Interfaces",
self.name, self.src_intra_doc_link,
);
let enum_alias_doc = format!(
"Opaque value represented by [`{}`]({}) [GraphQL interface][0].\
\n\n\
[0]: https://spec.graphql.org/June2018/#sec-Interfaces",
self.name, self.src_intra_doc_link,
);
let phantom_variant = self.has_phantom_variant().then(|| {
let phantom_params = interface_gens.params.iter().filter_map(|p| {
let ty = match p {
syn::GenericParam::Type(ty) => {
let ident = &ty.ident;
quote! { #ident }
}
syn::GenericParam::Lifetime(lt) => {
let lifetime = &lt.lifetime;
quote! { &#lifetime () }
}
syn::GenericParam::Const(_) => return None,
};
Some(quote! {
::std::marker::PhantomData<::std::sync::atomic::AtomicPtr<Box<#ty>>>
})
});
quote! { __Phantom(#(#phantom_params),*) }
});
let phantom_variant = self
.has_phantom_variant()
.then(|| {
let phantom_params = interface_gens.params.iter().filter_map(|p| {
let ty = match p {
syn::GenericParam::Type(ty) => {
let ident = &ty.ident;
quote! { #ident }
}
syn::GenericParam::Lifetime(lt) => {
let lifetime = &lt.lifetime;
quote! { &#lifetime () }
}
syn::GenericParam::Const(_) => return None,
};
Some(quote! {
::std::marker::PhantomData<::std::sync::atomic::AtomicPtr<Box<#ty>>>
})
});
quote! { __Phantom(#(#phantom_params),*) }
})
.into_iter();
let from_impls = self
.implemented_for
@ -449,12 +467,14 @@ impl Definition {
quote! {
#[automatically_derived]
#[derive(Clone, Copy, Debug)]
#[doc = #enum_doc]
#vis enum #enum_ident#enum_gens {
#( #variants_idents(#variant_gens_pars), )*
#phantom_variant
#( #[doc(hidden)] #variants_idents(#variant_gens_pars), )*
#( #[doc(hidden)] #phantom_variant, )*
}
#[automatically_derived]
#[doc = #enum_alias_doc]
#vis type #alias_ident#enum_alias_gens =
#enum_ident<#( #enum_to_alias_gens ),*>;
@ -676,8 +696,8 @@ impl Definition {
&self,
info: &Self::TypeInfo,
field: &str,
args: &::juniper::Arguments<#scalar>,
executor: &::juniper::Executor<Self::Context, #scalar>,
args: &::juniper::Arguments<'_, #scalar>,
executor: &::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::ExecutionResult<#scalar> {
match field {
#( #fields_resolvers )*
@ -697,8 +717,8 @@ impl Definition {
&self,
info: &Self::TypeInfo,
type_name: &str,
_: Option<&[::juniper::Selection<#scalar>]>,
executor: &::juniper::Executor<Self::Context, #scalar>,
_: Option<&[::juniper::Selection<'_, #scalar>]>,
executor: &::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::ExecutionResult<#scalar> {
#downcast
}
@ -747,8 +767,8 @@ impl Definition {
&'b self,
info: &'b Self::TypeInfo,
field: &'b str,
args: &'b ::juniper::Arguments<#scalar>,
executor: &'b ::juniper::Executor<Self::Context, #scalar>,
args: &'b ::juniper::Arguments<'_, #scalar>,
executor: &'b ::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::BoxFuture<'b, ::juniper::ExecutionResult<#scalar>> {
match field {
#( #fields_resolvers )*
@ -942,8 +962,8 @@ impl Definition {
fn call(
&self,
info: &Self::TypeInfo,
args: &::juniper::Arguments<#scalar>,
executor: &::juniper::Executor<Self::Context, #scalar>,
args: &::juniper::Arguments<'_, #scalar>,
executor: &::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::ExecutionResult<#scalar> {
match self {
#( #ty::#implemented_for_idents(v) => {
@ -1022,8 +1042,8 @@ impl Definition {
fn call<'b>(
&'b self,
info: &'b Self::TypeInfo,
args: &'b ::juniper::Arguments<#scalar>,
executor: &'b ::juniper::Executor<Self::Context, #scalar>,
args: &'b ::juniper::Arguments<'_, #scalar>,
executor: &'b ::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::BoxFuture<'b, ::juniper::ExecutionResult<#scalar>> {
match self {
#( #ty::#implemented_for_idents(v) => {

View file

@ -679,8 +679,8 @@ impl Definition<Query> {
fn call(
&self,
info: &Self::TypeInfo,
args: &::juniper::Arguments<#scalar>,
executor: &::juniper::Executor<Self::Context, #scalar>,
args: &::juniper::Arguments<'_, #scalar>,
executor: &::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::ExecutionResult<#scalar> {
#resolve
}
@ -740,8 +740,8 @@ impl Definition<Query> {
fn call<'b>(
&'b self,
info: &'b Self::TypeInfo,
args: &'b ::juniper::Arguments<#scalar>,
executor: &'b ::juniper::Executor<Self::Context, #scalar>,
args: &'b ::juniper::Arguments<'_, #scalar>,
executor: &'b ::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::BoxFuture<'b, ::juniper::ExecutionResult<#scalar>> {
let fut = #res;
#resolving_code
@ -799,8 +799,8 @@ impl Definition<Query> {
&self,
info: &Self::TypeInfo,
field: &str,
args: &::juniper::Arguments<#scalar>,
executor: &::juniper::Executor<Self::Context, #scalar>,
args: &::juniper::Arguments<'_, #scalar>,
executor: &::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::ExecutionResult<#scalar> {
match field {
#( #fields_resolvers )*
@ -856,8 +856,8 @@ impl Definition<Query> {
&'b self,
info: &'b Self::TypeInfo,
field: &'b str,
args: &'b ::juniper::Arguments<#scalar>,
executor: &'b ::juniper::Executor<Self::Context, #scalar>,
args: &'b ::juniper::Arguments<'_, #scalar>,
executor: &'b ::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::BoxFuture<'b, ::juniper::ExecutionResult<#scalar>> {
match field {
#( #fields_resolvers )*

View file

@ -432,8 +432,8 @@ impl Definition {
fn resolve(
&self,
info: &(),
selection: Option<&[::juniper::Selection<#scalar>]>,
executor: &::juniper::Executor<Self::Context, #scalar>,
selection: Option<&[::juniper::Selection<'_, #scalar>]>,
executor: &::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::ExecutionResult<#scalar> {
#resolve
}
@ -460,8 +460,8 @@ impl Definition {
fn resolve_async<'b>(
&'b self,
info: &'b Self::TypeInfo,
selection_set: Option<&'b [::juniper::Selection<#scalar>]>,
executor: &'b ::juniper::Executor<Self::Context, #scalar>,
selection_set: Option<&'b [::juniper::Selection<'_, #scalar>]>,
executor: &'b ::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::BoxFuture<'b, ::juniper::ExecutionResult<#scalar>> {
use ::juniper::futures::future;
let v = ::juniper::GraphQLValue::resolve(self, info, selection_set, executor);

View file

@ -57,8 +57,8 @@ impl Definition<Subscription> {
&self,
_: &Self::TypeInfo,
_: &str,
_: &::juniper::Arguments<#scalar>,
_: &::juniper::Executor<Self::Context, #scalar>,
_: &::juniper::Arguments<'_, #scalar>,
_: &::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::ExecutionResult<#scalar> {
Err(::juniper::FieldError::from(
"Called `resolve_field` on subscription object",

View file

@ -554,8 +554,8 @@ impl Definition {
&self,
info: &Self::TypeInfo,
type_name: &str,
_: Option<&[::juniper::Selection<#scalar>]>,
executor: &::juniper::Executor<Self::Context, #scalar>,
_: Option<&[::juniper::Selection<'_, #scalar>]>,
executor: &::juniper::Executor<'_, '_, Self::Context, #scalar>,
) -> ::juniper::ExecutionResult<#scalar> {
let context = executor.context();
#( #variant_resolvers )*

View file

@ -11,6 +11,7 @@ All user visible changes to `juniper_rocket` crate will be documented in this fi
### BC Breaks
- Switched to 0.16 version of [`juniper` crate].
- Switched to 0.5.0-rc.2 version of [`rocket` crate].
### Added
@ -30,4 +31,5 @@ See [old CHANGELOG](/../../blob/juniper_rocket-v0.8.1/juniper_rocket/CHANGELOG.m
[`juniper` crate]: https://docs.rs/juniper
[`rocket` crate]: https://docs.rs/rocket
[Semantic Versioning 2.0.0]: https://semver.org

View file

@ -19,7 +19,7 @@ exclude = ["/examples/", "/tests/", "/release.toml"]
[dependencies]
futures = "0.3.1"
juniper = { version = "0.16.0-dev", path = "../juniper", default-features = false }
rocket = { version = "0.5.0-rc.1", default-features = false }
rocket = { version = "0.5.0-rc.2", default-features = false }
serde_json = "1.0.2"
[dev-dependencies]

View file

@ -2,12 +2,12 @@ use juniper::{
tests::fixtures::starwars::schema::{Database, Query},
EmptyMutation, EmptySubscription, RootNode,
};
use rocket::{response::content, Rocket, State};
use rocket::{response::content, State};
type Schema = RootNode<'static, Query, EmptyMutation<Database>, EmptySubscription<Database>>;
#[rocket::get("/")]
fn graphiql() -> content::Html<String> {
fn graphiql() -> content::RawHtml<String> {
juniper_rocket::graphiql_source("/graphql", None)
}
@ -31,7 +31,7 @@ fn post_graphql_handler(
#[rocket::main]
async fn main() {
Rocket::build()
let _ = rocket::build()
.manage(Database::new())
.manage(Schema::new(
Query,

View file

@ -46,8 +46,8 @@ pub struct GraphQLResponse(pub Status, pub String);
pub fn graphiql_source(
graphql_endpoint_url: &str,
subscriptions_endpoint_url: Option<&str>,
) -> content::Html<String> {
content::Html(juniper::http::graphiql::graphiql_source(
) -> content::RawHtml<String> {
content::RawHtml(juniper::http::graphiql::graphiql_source(
graphql_endpoint_url,
subscriptions_endpoint_url,
))
@ -57,8 +57,8 @@ pub fn graphiql_source(
pub fn playground_source(
graphql_endpoint_url: &str,
subscriptions_endpoint_url: Option<&str>,
) -> content::Html<String> {
content::Html(juniper::http::playground::playground_source(
) -> content::RawHtml<String> {
content::RawHtml(juniper::http::playground::playground_source(
graphql_endpoint_url,
subscriptions_endpoint_url,
))

View file

@ -65,7 +65,7 @@ fn test_derived_enum() {
);
// Ensure validity of meta info.
let mut registry: Registry = Registry::new(FnvHashMap::default());
let mut registry: Registry<'_> = Registry::new(FnvHashMap::default());
let meta = SomeEnum::meta(&(), &mut registry);
assert_eq!(meta.name(), Some("Some"));
@ -100,21 +100,21 @@ fn test_derived_enum() {
#[test]
fn test_doc_comment() {
let mut registry: Registry = Registry::new(FnvHashMap::default());
let mut registry: Registry<'_> = Registry::new(FnvHashMap::default());
let meta = DocEnum::meta(&(), &mut registry);
assert_eq!(meta.description(), Some("Enum doc."));
}
#[test]
fn test_multi_doc_comment() {
let mut registry: Registry = Registry::new(FnvHashMap::default());
let mut registry: Registry<'_> = Registry::new(FnvHashMap::default());
let meta = MultiDocEnum::meta(&(), &mut registry);
assert_eq!(meta.description(), Some("Doc 1. Doc 2.\n\nDoc 4."));
}
#[test]
fn test_doc_comment_override() {
let mut registry: Registry = Registry::new(FnvHashMap::default());
let mut registry: Registry<'_> = Registry::new(FnvHashMap::default());
let meta = OverrideDocEnum::meta(&(), &mut registry);
assert_eq!(meta.description(), Some("enum override"));
}

View file

@ -114,7 +114,7 @@ fn test_derived_input_object() {
);
// Validate meta info.
let mut registry: Registry = Registry::new(FnvHashMap::default());
let mut registry: Registry<'_> = Registry::new(FnvHashMap::default());
let meta = Input::meta(&(), &mut registry);
assert_eq!(meta.name(), Some("MyInput"));
assert_eq!(meta.description(), Some("input descr"));
@ -171,21 +171,21 @@ fn test_derived_input_object() {
#[test]
fn test_doc_comment() {
let mut registry: Registry = Registry::new(FnvHashMap::default());
let mut registry: Registry<'_> = Registry::new(FnvHashMap::default());
let meta = DocComment::meta(&(), &mut registry);
assert_eq!(meta.description(), Some("Object comment."));
}
#[test]
fn test_multi_doc_comment() {
let mut registry: Registry = Registry::new(FnvHashMap::default());
let mut registry: Registry<'_> = Registry::new(FnvHashMap::default());
let meta = MultiDocComment::meta(&(), &mut registry);
assert_eq!(meta.description(), Some("Doc 1. Doc 2.\n\nDoc 4."));
}
#[test]
fn test_doc_comment_override() {
let mut registry: Registry = Registry::new(FnvHashMap::default());
let mut registry: Registry<'_> = Registry::new(FnvHashMap::default());
let meta = OverrideDocComment::meta(&(), &mut registry);
assert_eq!(meta.description(), Some("obj override"));
}

View file

@ -2538,3 +2538,44 @@ mod nullable_argument_subtyping {
}
}
}
mod preserves_visibility {
use super::*;
#[allow(dead_code)]
type Foo = self::inner::CharacterValue;
pub(crate) mod inner {
use super::*;
#[graphql_interface(for = Human)]
pub(crate) struct Character {
id: String,
}
#[derive(GraphQLObject)]
#[graphql(impl = CharacterValue)]
pub(crate) struct Human {
id: String,
home_planet: String,
}
}
}
mod has_no_missing_docs {
#![deny(missing_docs)]
use super::*;
#[graphql_interface(for = Human)]
pub struct Character {
pub id: String,
}
#[derive(GraphQLObject)]
#[graphql(impl = CharacterValue)]
pub struct Human {
id: String,
home_planet: String,
}
}

View file

@ -3377,3 +3377,44 @@ mod nullable_argument_subtyping {
}
}
}
mod preserves_visibility {
use super::*;
#[allow(dead_code)]
type Foo = self::inner::CharacterValue;
pub(crate) mod inner {
use super::*;
#[graphql_interface(for = Human)]
pub(crate) trait Character {
fn id(&self) -> &str;
}
#[derive(GraphQLObject)]
#[graphql(impl = CharacterValue)]
pub(crate) struct Human {
id: String,
home_planet: String,
}
}
}
mod has_no_missing_docs {
#![deny(missing_docs)]
use super::*;
#[graphql_interface(for = Human)]
pub trait Character {
fn id(&self) -> &str;
}
#[derive(GraphQLObject)]
#[graphql(impl = CharacterValue)]
pub struct Human {
id: String,
home_planet: String,
}
}

View file

@ -2558,3 +2558,46 @@ mod nullable_argument_subtyping {
}
}
}
mod preserves_visibility {
use super::*;
#[allow(dead_code)]
type Foo = self::inner::CharacterValue;
pub(crate) mod inner {
use super::*;
#[derive(GraphQLInterface)]
#[graphql(for = Human)]
pub(crate) struct Character {
id: String,
}
#[derive(GraphQLObject)]
#[graphql(impl = CharacterValue)]
pub(crate) struct Human {
id: String,
home_planet: String,
}
}
}
mod has_no_missing_docs {
#![deny(missing_docs)]
use super::*;
#[derive(GraphQLInterface)]
#[graphql(for = Human)]
pub struct Character {
pub id: String,
}
#[derive(GraphQLObject)]
#[graphql(impl = CharacterValue)]
pub struct Human {
id: String,
home_planet: String,
}
}

View file

@ -31,7 +31,7 @@ impl<'de> Deserialize<'de> for MyScalarValue {
impl<'de> de::Visitor<'de> for Visitor {
type Value = MyScalarValue;
fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("a valid input value")
}

View file

@ -1,3 +1,5 @@
#![deny(rust_2018_idioms)]
#[cfg(test)]
mod arc_fields;
#[cfg(test)]