Use doc comments instead of the doc attribute in the changelog examples (#273)

This commit is contained in:
Georg Semmler 2018-11-11 23:58:50 +01:00 committed by Christian Legnitto
parent 0f2a654471
commit 4ecf558066
6 changed files with 102 additions and 118 deletions

View file

@ -57,13 +57,13 @@
}
// New alternative syntax for field descriptions
#[doc = "Description"]
/// Description
field my_field() -> { ... }
// New alternative syntax for argument descriptions
field my_field(
#[doc = "The number of starfish to be returned. \
Can't be more than 100."]
/// The number of starfish to be returned.
/// Can't be more than 100.
arg: i32,
) -> {
...
@ -73,12 +73,11 @@
//
// Multiple docstrings will be collapsed into a single
// description separated by newlines.
#[doc = r#"
This is my field.
Make sure not to flitz the bitlet.
Flitzing without a bitlet has undefined behaviour.
"]
/// This is my field.
///
/// Make sure not to filtz the bitlet.
/// Flitzing without a bitlet has undefined behaviour.
///
#[doc = my_consts::ADDED_IN_VERSION_XYZ]
field my_field() -> { ... }
```

View file

@ -677,7 +677,7 @@ macro_rules! __juniper_create_arg {
$info,
)
$(.description($arg_description))*
$(.push_docstring($arg_docstring))*
.push_docstring(&[$($arg_docstring,)*])
};
(
@ -695,6 +695,6 @@ macro_rules! __juniper_create_arg {
$info,
)
$(.description($arg_description))*
$(.push_docstring($arg_docstring))*
.push_docstring(&[$($arg_docstring,)*])
};
}

View file

@ -153,7 +153,7 @@ macro_rules! graphql_interface {
info
)
$(.description($fn_description))*
$(.push_docstring($docstring))*
.push_docstring(&[$($docstring,)*])
$(.deprecated($deprecated))*
$(.argument(
__juniper_create_arg!(

View file

@ -35,8 +35,11 @@ graphql_object!(User: () |&self| {
## Documentation and descriptions
You can optionally add descriptions to the type itself, the fields, and field
arguments:
You can optionally add descriptions to the type itself, the fields,
and field arguments. For field and argument descriptions it is
possible to use normal rustdoc comments or doc
attributes. Alternatively the same syntax as for the type could be
used
```rust
# #[macro_use] extern crate juniper;
@ -45,7 +48,9 @@ struct User { id: String, name: String, group_ids: Vec<String> }
graphql_object!(User: () |&self| {
description: "A user in the database"
field id() -> &String as "The user's unique identifier" {
/// The user's unique identifier
field id() -> &String {
&self.id
}
@ -53,47 +58,11 @@ graphql_object!(User: () |&self| {
&self.name
}
#[doc = "Test if a user is member of a group"]
field member_of_group(
group_id: String as "The group id you want to test membership against"
) -> bool as "Test if a user is member of a group" {
self.group_ids.iter().any(|gid| gid == &group_id)
}
});
# fn main() { }
```
**Alternatively,** descriptions can be added with the builtin `doc` attribute.
Consecutive `#[doc = "..."]` attributes will be collapsed into a single description
where the docstrings are separated by newlines.
```rust
# #[macro_use] extern crate juniper;
struct User { id: String, name: String, group_ids: Vec<String> }
graphql_object!(User: () |&self| {
description: "A user in the database"
#[doc = "The user's unique identifier"]
field id() -> &String {
&self.id
}
#[doc = "The user's name"]
field name() -> &String {
&self.name
}
#[doc = r#"
Test if a user is member of a group.
This may return a flitzbit if the floop is twizled.
Make sure not to rumblejumble the cog-rotater.
"#]
#[doc = "Added in vX.Y.44"]
field member_of_group(
#[doc = "The group id you want to test membership against"]
group_id: String,
/// The group id you want to test membership against
/// second line
group_id: String
) -> bool {
self.group_ids.iter().any(|gid| gid == &group_id)
}
@ -275,16 +244,19 @@ A field's description and deprecation can also be set using the
builtin `doc` and `deprecated` attributes.
```text
#[doc = "Field description"]
/// Field description
field name(args...) -> Type { }
#[doc = "Field description"]
field name(args...) -> Type {}
#[deprecated] // no reason required
field name(args...) -> Type { }
#[deprecated(note = "Reason")]
field name(args...) -> Type { }
#[doc = "Field description"]
/// Field description
#[deprecated(note = "Reason")] // deprecated must come after doc
field deprecated "Reason" name(args...) -> Type { }
```
@ -326,9 +298,11 @@ arg_name = (Point { x: 1, y: 2 }): Point
arg_name = ("default".to_owned()): String
```
A description can also be provided using the builtin `doc` attribute.
A description can also be provided using normal doc comments or doc attributes.
```text
/// Argument description
arg_name: ArgType
#[doc = "Argument description"]
arg_name: ArgType
```
@ -391,7 +365,7 @@ macro_rules! graphql_object {
info
)
$(.description($fn_description))*
$(.push_docstring($docstring))*
.push_docstring(&[$($docstring,)*])
$(.deprecated($deprecated))*
$(.argument(
__juniper_create_arg!(

View file

@ -31,19 +31,18 @@ graphql_object!(Root: () |&self| {
field deprecated "Deprecation reason"
deprecated_descr() -> i32 as "Field description" { 0 }
#[doc = "Field description"]
/// Field description
field attr_description() -> i32 { 0 }
#[doc = "Field description"]
#[doc = "with `collapse_docs` behavior"] // https://doc.rust-lang.org/rustdoc/the-doc-attribute.html
/// Field description
/// with `collapse_docs` behavior
field attr_description_collapse() -> i32 { 0 }
#[doc = r#"
Get the i32 representation of 0.
- This comment is longer.
- These two lines are rendered as bullets by GraphiQL.
"#]
/// Get the i32 representation of 0.
///
/// - This comment is longer.
/// - These two lines are rendered as bullets by GraphiQL.
/// - subsection
field attr_description_long() -> i32 { 0 }
#[deprecated]
@ -52,7 +51,7 @@ graphql_object!(Root: () |&self| {
#[deprecated(note = "Deprecation reason")]
field attr_deprecated_reason() -> i32 { 0 }
#[doc = "Field description"]
/// Field description
#[deprecated(note = "Deprecation reason")]
field attr_deprecated_descr() -> i32 { 0 }
@ -76,19 +75,17 @@ graphql_interface!(Interface: () |&self| {
field deprecated "Deprecation reason"
deprecated_descr() -> i32 as "Field description" { 0 }
#[doc = "Field description"]
/// Field description
field attr_description() -> i32 { 0 }
#[doc = "Field description"]
#[doc = "with `collapse_docs` behavior"] // https://doc.rust-lang.org/rustdoc/the-doc-attribute.html
/// Field description
/// with `collapse_docs` behavior
field attr_description_collapse() -> i32 { 0 }
#[doc = r#"
Get the i32 representation of 0.
- This comment is longer.
- These two lines are rendered as bullets by GraphiQL.
"#]
/// Get the i32 representation of 0.
///
/// - This comment is longer.
/// - These two lines are rendered as bullets by GraphiQL.
field attr_description_long() -> i32 { 0 }
#[deprecated]
@ -97,7 +94,7 @@ graphql_interface!(Interface: () |&self| {
#[deprecated(note = "Deprecation reason")]
field attr_deprecated_reason() -> i32 { 0 }
#[doc = "Field description"]
/// Field description
#[deprecated(note = "Deprecation reason")]
field attr_deprecated_descr() -> i32 { 0 }
@ -384,7 +381,7 @@ fn introspect_object_field_attr_description_long() {
);
assert_eq!(
field.get_field_value("description"),
Some(&Value::scalar("Get the i32 representation of 0.\n\n- This comment is longer.\n- These two lines are rendered as bullets by GraphiQL."))
Some(&Value::scalar("Get the i32 representation of 0.\n\n- This comment is longer.\n- These two lines are rendered as bullets by GraphiQL.\n - subsection"))
);
assert_eq!(
field.get_field_value("isDeprecated"),

View file

@ -613,15 +613,16 @@ impl<'a, S> Field<'a, S> {
///
/// If the description hasn't been set, the description is set to the provided line.
/// Otherwise, the doc string is added to the current description after a newline.
pub fn push_docstring(mut self, multiline: &str) -> Field<'a, S> {
let docstring = clean_docstring(multiline);
match &mut self.description {
&mut Some(ref mut desc) => {
desc.push('\n');
desc.push_str(&docstring);
}
desc @ &mut None => {
*desc = Some(docstring.to_string());
pub fn push_docstring(mut self, multiline: &[&str]) -> Field<'a, S> {
if let Some(docstring) = clean_docstring(multiline) {
match &mut self.description {
&mut Some(ref mut desc) => {
desc.push('\n');
desc.push_str(&docstring);
}
desc @ &mut None => {
*desc = Some(docstring);
}
}
}
self
@ -679,15 +680,16 @@ impl<'a, S> Argument<'a, S> {
///
/// If the description hasn't been set, the description is set to the provided line.
/// Otherwise, the doc string is added to the current description after a newline.
pub fn push_docstring(mut self, multiline: &str) -> Argument<'a, S> {
let docstring = clean_docstring(multiline);
match &mut self.description {
&mut Some(ref mut desc) => {
desc.push('\n');
desc.push_str(&docstring);
}
desc @ &mut None => {
*desc = Some(docstring.to_string());
pub fn push_docstring(mut self, multiline: &[&str]) -> Argument<'a, S> {
if let Some(docstring) = clean_docstring(multiline) {
match &mut self.description {
&mut Some(ref mut desc) => {
desc.push('\n');
desc.push_str(&docstring);
}
desc @ &mut None => {
*desc = Some(docstring)
}
}
}
self
@ -766,26 +768,38 @@ where
<T as FromInputValue<S>>::from_input_value(v).is_some()
}
fn clean_docstring<'a>(multiline: &'a str) -> Cow<'a, str> {
let trim_start = multiline.split('\n')
.skip(1)
.filter_map(|ln| ln.chars().position(|ch| ch != ' ' && ch != '\t'))
.min();
if let Some(trim) = trim_start {
let trimmed = multiline
.split('\n')
.map(|ln| {
if !ln.starts_with(' ') && !ln.starts_with('\t') {
ln // skip trimming the first line
} else if ln.len() >= trim {
&ln[trim..]
fn clean_docstring(multiline: &[&str]) -> Option<String> {
if multiline.is_empty() {
return None;
}
let trim_start = multiline
.iter()
.filter_map(|ln| ln.chars().position(|ch| !ch.is_whitespace()))
.min()
.unwrap_or(0);
Some(
multiline
.iter()
.enumerate()
.flat_map(|(line, ln)| {
let new_ln = if !ln
.chars()
.next()
.map(|ch| ch.is_whitespace())
.unwrap_or(false)
{
ln.trim_end() // skip trimming the first line
} else if ln.len() >= trim_start {
&ln[trim_start..].trim_end()
} else {
""
}
})
.collect::<Vec<_>>();
Cow::from(trimmed.join("\n").trim_matches('\n').to_owned())
} else {
Cow::from(multiline.trim_matches('\n'))
}
};
new_ln.chars().chain(
['\n']
.iter()
.take_while(move |_| line < multiline.len() - 1)
.cloned(),
)
}).collect::<String>(),
)
}