async-graphql/async-graphql-derive/src/args.rs

454 lines
17 KiB
Rust
Raw Normal View History

2020-03-03 03:48:00 +00:00
use crate::utils::parse_value;
use graphql_parser::query::Value;
2020-03-05 06:23:55 +00:00
use syn::{Attribute, AttributeArgs, Error, Meta, NestedMeta, Result};
2020-03-01 10:54:34 +00:00
#[derive(Debug)]
pub struct Object {
2020-03-02 00:24:49 +00:00
pub internal: bool,
2020-03-01 10:54:34 +00:00
pub name: Option<String>,
pub desc: Option<String>,
}
impl Object {
pub fn parse(args: AttributeArgs) -> Result<Self> {
2020-03-02 00:24:49 +00:00
let mut internal = false;
2020-03-01 10:54:34 +00:00
let mut name = None;
let mut desc = None;
for arg in args {
match arg {
2020-03-02 00:24:49 +00:00
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("internal") => {
internal = true;
}
2020-03-01 10:54:34 +00:00
NestedMeta::Meta(Meta::NameValue(nv)) => {
if nv.path.is_ident("name") {
if let syn::Lit::Str(lit) = nv.lit {
name = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'name' should be a string.",
));
}
} else if nv.path.is_ident("desc") {
if let syn::Lit::Str(lit) = nv.lit {
desc = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'desc' should be a string.",
));
}
}
}
_ => {}
}
}
2020-03-02 00:24:49 +00:00
Ok(Self {
internal,
name,
desc,
})
2020-03-01 10:54:34 +00:00
}
}
#[derive(Debug)]
pub struct Argument {
2020-03-05 06:23:55 +00:00
pub name: Option<String>,
2020-03-01 10:54:34 +00:00
pub desc: Option<String>,
2020-03-03 03:48:00 +00:00
pub default: Option<Value>,
2020-03-01 10:54:34 +00:00
}
2020-03-05 06:23:55 +00:00
impl Argument {
pub fn parse(attrs: &[Attribute]) -> Result<Self> {
2020-03-01 10:54:34 +00:00
let mut name = None;
let mut desc = None;
2020-03-05 06:23:55 +00:00
let mut default = None;
for attr in attrs {
match attr.parse_meta() {
Ok(Meta::List(ls)) if ls.path.is_ident("arg") => {
for meta in &ls.nested {
match meta {
NestedMeta::Meta(Meta::NameValue(nv)) => {
2020-03-01 10:54:34 +00:00
if nv.path.is_ident("name") {
2020-03-02 11:25:21 +00:00
if let syn::Lit::Str(lit) = &nv.lit {
2020-03-01 10:54:34 +00:00
name = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'name' should be a string.",
));
}
} else if nv.path.is_ident("desc") {
2020-03-02 11:25:21 +00:00
if let syn::Lit::Str(lit) = &nv.lit {
2020-03-01 10:54:34 +00:00
desc = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'desc' should be a string.",
));
}
2020-03-03 03:48:00 +00:00
} else if nv.path.is_ident("default") {
if let syn::Lit::Str(lit) = &nv.lit {
match parse_value(&lit.value()) {
2020-03-04 02:38:07 +00:00
Ok(Value::Variable(_)) => {
return Err(Error::new_spanned(
&nv.lit,
"The default cannot be a variable",
))
}
2020-03-03 03:48:00 +00:00
Ok(value) => default = Some(value),
Err(err) => {
return Err(Error::new_spanned(
&nv.lit,
format!("Invalid value: {}", err),
));
}
}
} else {
return Err(Error::new_spanned(
&nv.lit,
2020-03-05 06:23:55 +00:00
"Attribute 'deprecation' should be a string.",
));
}
}
}
_ => {}
}
}
}
_ => {}
}
}
Ok(Self {
name,
desc,
default,
})
}
}
#[derive(Debug)]
pub struct Field {
pub name: Option<String>,
pub desc: Option<String>,
pub deprecation: Option<String>,
}
impl Field {
pub fn parse(attrs: &[Attribute]) -> Result<Option<Self>> {
let mut is_field = false;
let mut name = None;
let mut desc = None;
let mut deprecation = None;
for attr in attrs {
match attr.parse_meta() {
Ok(Meta::Path(p)) if p.is_ident("field") => {
is_field = true;
}
Ok(Meta::List(ls)) if ls.path.is_ident("field") => {
is_field = true;
for meta in &ls.nested {
match meta {
NestedMeta::Meta(Meta::NameValue(nv)) => {
if nv.path.is_ident("name") {
if let syn::Lit::Str(lit) = &nv.lit {
name = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'name' should be a string.",
2020-03-03 03:48:00 +00:00
));
}
2020-03-05 06:23:55 +00:00
} else if nv.path.is_ident("desc") {
2020-03-02 00:24:49 +00:00
if let syn::Lit::Str(lit) = &nv.lit {
2020-03-05 06:23:55 +00:00
desc = Some(lit.value());
2020-03-02 00:24:49 +00:00
} else {
return Err(Error::new_spanned(
&nv.lit,
2020-03-05 06:23:55 +00:00
"Attribute 'desc' should be a string.",
));
}
} else if nv.path.is_ident("deprecation") {
if let syn::Lit::Str(lit) = &nv.lit {
deprecation = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'deprecation' should be a string.",
2020-03-02 00:24:49 +00:00
));
}
2020-03-01 10:54:34 +00:00
}
}
2020-03-05 06:23:55 +00:00
_ => {}
2020-03-02 11:25:21 +00:00
}
2020-03-01 10:54:34 +00:00
}
}
2020-03-02 11:25:21 +00:00
_ => {}
2020-03-01 10:54:34 +00:00
}
}
2020-03-05 06:23:55 +00:00
if is_field {
Ok(Some(Self {
name,
desc,
deprecation,
}))
} else {
Ok(None)
2020-03-01 10:54:34 +00:00
}
}
}
#[derive(Debug)]
pub struct Enum {
2020-03-02 00:24:49 +00:00
pub internal: bool,
2020-03-01 10:54:34 +00:00
pub name: Option<String>,
pub desc: Option<String>,
}
impl Enum {
pub fn parse(args: AttributeArgs) -> Result<Self> {
2020-03-02 00:24:49 +00:00
let mut internal = false;
2020-03-01 10:54:34 +00:00
let mut name = None;
let mut desc = None;
for arg in args {
match arg {
2020-03-02 00:24:49 +00:00
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("internal") => {
internal = true;
}
2020-03-01 10:54:34 +00:00
NestedMeta::Meta(Meta::NameValue(nv)) => {
if nv.path.is_ident("name") {
if let syn::Lit::Str(lit) = nv.lit {
name = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'name' should be a string.",
));
}
} else if nv.path.is_ident("desc") {
if let syn::Lit::Str(lit) = nv.lit {
desc = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'desc' should be a string.",
));
}
}
}
_ => {}
}
}
2020-03-02 00:24:49 +00:00
Ok(Self {
internal,
name,
desc,
})
2020-03-01 10:54:34 +00:00
}
}
#[derive(Debug)]
pub struct EnumItem {
pub name: Option<String>,
pub desc: Option<String>,
2020-03-03 03:48:00 +00:00
pub deprecation: Option<String>,
2020-03-01 10:54:34 +00:00
}
impl EnumItem {
pub fn parse(attrs: &[Attribute]) -> Result<Self> {
let mut name = None;
let mut desc = None;
2020-03-03 03:48:00 +00:00
let mut deprecation = None;
2020-03-01 10:54:34 +00:00
for attr in attrs {
if attr.path.is_ident("item") {
if let Ok(Meta::List(args)) = attr.parse_meta() {
for meta in args.nested {
match meta {
NestedMeta::Meta(Meta::NameValue(nv)) => {
if nv.path.is_ident("name") {
if let syn::Lit::Str(lit) = nv.lit {
name = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'name' should be a string.",
));
}
} else if nv.path.is_ident("desc") {
if let syn::Lit::Str(lit) = nv.lit {
desc = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'desc' should be a string.",
));
}
2020-03-03 03:48:00 +00:00
} else if nv.path.is_ident("deprecation") {
if let syn::Lit::Str(lit) = nv.lit {
deprecation = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'deprecation' should be a string.",
));
}
2020-03-01 10:54:34 +00:00
}
}
_ => {}
}
}
}
}
}
2020-03-03 03:48:00 +00:00
Ok(Self {
name,
desc,
deprecation,
})
2020-03-01 10:54:34 +00:00
}
}
#[derive(Debug)]
pub struct InputField {
2020-03-02 00:24:49 +00:00
pub internal: bool,
2020-03-01 10:54:34 +00:00
pub name: Option<String>,
pub desc: Option<String>,
2020-03-03 03:48:00 +00:00
pub default: Option<Value>,
2020-03-01 10:54:34 +00:00
}
impl InputField {
pub fn parse(attrs: &[Attribute]) -> Result<Self> {
2020-03-02 00:24:49 +00:00
let mut internal = false;
2020-03-01 10:54:34 +00:00
let mut name = None;
let mut desc = None;
2020-03-03 03:48:00 +00:00
let mut default = None;
2020-03-01 10:54:34 +00:00
for attr in attrs {
if attr.path.is_ident("field") {
if let Ok(Meta::List(args)) = attr.parse_meta() {
for meta in args.nested {
match meta {
2020-03-02 00:24:49 +00:00
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("internal") => {
internal = true;
}
2020-03-01 10:54:34 +00:00
NestedMeta::Meta(Meta::NameValue(nv)) => {
if nv.path.is_ident("name") {
if let syn::Lit::Str(lit) = nv.lit {
name = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'name' should be a string.",
));
}
} else if nv.path.is_ident("desc") {
if let syn::Lit::Str(lit) = nv.lit {
desc = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'desc' should be a string.",
));
}
2020-03-03 03:48:00 +00:00
} else if nv.path.is_ident("default") {
if let syn::Lit::Str(lit) = nv.lit {
match parse_value(&lit.value()) {
2020-03-04 02:38:07 +00:00
Ok(Value::Variable(_)) => {
return Err(Error::new_spanned(
&lit,
"The default cannot be a variable",
))
}
2020-03-03 03:48:00 +00:00
Ok(value) => default = Some(value),
Err(err) => {
return Err(Error::new_spanned(
&lit,
format!("Invalid value: {}", err),
));
}
}
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'default' should be a string.",
));
}
2020-03-01 10:54:34 +00:00
}
}
_ => {}
}
}
}
}
}
2020-03-03 03:48:00 +00:00
Ok(Self {
internal,
name,
desc,
default,
})
}
}
#[derive(Debug)]
pub struct InputObject {
pub internal: bool,
pub name: Option<String>,
pub desc: Option<String>,
}
impl InputObject {
pub fn parse(args: AttributeArgs) -> Result<Self> {
let mut internal = false;
let mut name = None;
let mut desc = None;
for arg in args {
match arg {
NestedMeta::Meta(Meta::Path(p)) if p.is_ident("internal") => {
internal = true;
}
NestedMeta::Meta(Meta::NameValue(nv)) => {
if nv.path.is_ident("name") {
if let syn::Lit::Str(lit) = nv.lit {
name = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'name' should be a string.",
));
}
} else if nv.path.is_ident("desc") {
if let syn::Lit::Str(lit) = nv.lit {
desc = Some(lit.value());
} else {
return Err(Error::new_spanned(
&nv.lit,
"Attribute 'desc' should be a string.",
));
}
}
}
_ => {}
}
}
2020-03-02 00:24:49 +00:00
Ok(Self {
internal,
name,
desc,
})
2020-03-01 10:54:34 +00:00
}
}