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
|
|
|
}
|
|
|
|
}
|