api-macro: lower a whole bunch of errors
to be non fatal for better error messages, this way the user will see the compile error, but we still generate all the code & schema variables so that one error isn't accompanied by all the ones resulting from not having the generated code there at all. Eg. error: description not allowed on external type --> src/api2/access/user.rs:472:22 | 472 | description: "Get API token metadata (with config digest).", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Was previously also accompanied by error[E0425]: cannot find value `API_METHOD_READ_TOKEN` in this scope --> src/api2/access/user.rs:774:11 | 699 | pub fn delete_token( | ------ similarly named constant `API_METHOD_DELETE_TOKEN` defined here ... 774 | .get(&API_METHOD_READ_TOKEN) | ^^^^^^^^^^^^^^^^^^^^^ help: a constant with a similar name exists: `API_METHOD_DELETE_TOKEN` The second error was "wrong" and came much later, needlessly filling the screen if this happened on multiple functions. Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
parent
273ce60242
commit
0ad74b431e
@ -21,8 +21,8 @@ pub fn handle_enum(
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(fmt) = attribs.get("format") {
|
||||
bail!(fmt.span(), "illegal key 'format', will be autogenerated");
|
||||
if let Some(fmt) = attribs.remove("format") {
|
||||
error!(fmt.span(), "illegal key 'format', will be autogenerated");
|
||||
}
|
||||
|
||||
let schema = {
|
||||
@ -47,9 +47,10 @@ pub fn handle_enum(
|
||||
_ => bail!(variant => "api macro does not support enums with fields"),
|
||||
}
|
||||
|
||||
let (comment, _doc_span) = util::get_doc_comments(&variant.attrs)?;
|
||||
let (mut comment, _doc_span) = util::get_doc_comments(&variant.attrs)?;
|
||||
if comment.is_empty() {
|
||||
bail!(variant => "enum variant needs a description");
|
||||
error!(&variant => "enum variant needs a description");
|
||||
comment = "<missing description>".to_string();
|
||||
}
|
||||
|
||||
let attrs = serde::SerdeAttrib::try_from(&variant.attrs[..])?;
|
||||
|
@ -68,7 +68,7 @@ pub fn handle_method(mut attribs: JSONObject, mut func: syn::ItemFn) -> Result<T
|
||||
.unwrap_or(false);
|
||||
|
||||
if !attribs.is_empty() {
|
||||
bail!(
|
||||
error!(
|
||||
attribs.span(),
|
||||
"unexpected api elements: {}",
|
||||
util::join_debug(", ", attribs.elements.keys()),
|
||||
@ -171,7 +171,7 @@ enum ParameterType<'a> {
|
||||
Other(&'a syn::Type, bool, &'a Schema),
|
||||
}
|
||||
|
||||
fn check_input_type(input: &syn::FnArg) -> Result<(&syn::PatType, &syn::PatIdent), Error> {
|
||||
fn check_input_type(input: &syn::FnArg) -> Result<(&syn::PatType, &syn::PatIdent), syn::Error> {
|
||||
// `self` types are not supported:
|
||||
let pat_type = match input {
|
||||
syn::FnArg::Receiver(r) => bail!(r => "methods taking a 'self' are not supported"),
|
||||
@ -204,7 +204,13 @@ fn handle_function_signature(
|
||||
let mut param_list = Vec::<(FieldName, ParameterType)>::new();
|
||||
|
||||
for input in sig.inputs.iter() {
|
||||
let (pat_type, pat) = check_input_type(input)?;
|
||||
let (pat_type, pat) = match check_input_type(input) {
|
||||
Ok(input) => input,
|
||||
Err(err) => {
|
||||
crate::add_error(err);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
// For any named type which exists on the function signature...
|
||||
if let Some((_ident, optional, ref mut schema)) =
|
||||
@ -214,10 +220,10 @@ fn handle_function_signature(
|
||||
let is_option = util::infer_type(schema, &*pat_type.ty)?;
|
||||
let has_default = schema.find_schema_property("default").is_some();
|
||||
if !is_option && *optional && !has_default {
|
||||
bail!(pat_type => "optional types need a default or be an Option<T>");
|
||||
error!(pat_type => "optional types need a default or be an Option<T>");
|
||||
}
|
||||
if has_default && !*optional {
|
||||
bail!(pat_type => "non-optional parameter cannot have a default");
|
||||
error!(pat_type => "non-optional parameter cannot have a default");
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
@ -225,7 +231,10 @@ fn handle_function_signature(
|
||||
}
|
||||
|
||||
for input in sig.inputs.iter() {
|
||||
let (pat_type, pat) = check_input_type(input)?;
|
||||
let (pat_type, pat) = match check_input_type(input) {
|
||||
Ok(input) => input,
|
||||
Err(_err) => continue, // we already produced errors above,
|
||||
};
|
||||
|
||||
// Here's the deal: we need to distinguish between parameters we need to extract before
|
||||
// calling the function, a general "Value" parameter covering all the remaining json
|
||||
@ -265,24 +274,28 @@ fn handle_function_signature(
|
||||
ParameterType::Other(&pat_type.ty, *optional, schema)
|
||||
} else if is_api_method_type(&pat_type.ty) {
|
||||
if api_method_param.is_some() {
|
||||
bail!(pat_type => "multiple ApiMethod parameters found");
|
||||
error!(pat_type => "multiple ApiMethod parameters found");
|
||||
continue;
|
||||
}
|
||||
api_method_param = Some(param_list.len());
|
||||
ParameterType::ApiMethod
|
||||
} else if is_rpc_env_type(&pat_type.ty) {
|
||||
if rpc_env_param.is_some() {
|
||||
bail!(pat_type => "multiple RpcEnvironment parameters found");
|
||||
error!(pat_type => "multiple RpcEnvironment parameters found");
|
||||
continue;
|
||||
}
|
||||
rpc_env_param = Some(param_list.len());
|
||||
ParameterType::RpcEnv
|
||||
} else if is_value_type(&pat_type.ty) {
|
||||
if value_param.is_some() {
|
||||
bail!(pat_type => "multiple additional Value parameters found");
|
||||
error!(pat_type => "multiple additional Value parameters found");
|
||||
continue;
|
||||
}
|
||||
value_param = Some(param_list.len());
|
||||
ParameterType::Value
|
||||
} else {
|
||||
bail!(&pat_ident => "unexpected parameter {:?}", pat_ident.to_string());
|
||||
error!(&pat_ident => "unexpected parameter {:?}", pat_ident.to_string());
|
||||
continue;
|
||||
};
|
||||
|
||||
param_list.push((param_name, param_type));
|
||||
@ -437,7 +450,13 @@ fn create_wrapper_function(
|
||||
});
|
||||
}
|
||||
} else if optional && no_option_type {
|
||||
bail!(ty => "Optional parameter without Option<T> requires a default");
|
||||
// FIXME: we should not be able to reach this without having produced another
|
||||
// error above already anyway?
|
||||
error!(ty => "Optional parameter without Option<T> requires a default");
|
||||
// we produced an error so just write something that will compile
|
||||
body.extend(quote_spanned! { span =>
|
||||
.unwrap_or_else(|| unreachable!())
|
||||
});
|
||||
}
|
||||
body.extend(quote_spanned! { span => ; });
|
||||
args.extend(quote_spanned! { span => #arg_name, });
|
||||
|
@ -135,7 +135,7 @@ fn handle_regular_struct(attribs: JSONObject, stru: syn::ItemStruct) -> Result<T
|
||||
schema_fields.insert(field.0.as_str().to_string(), field);
|
||||
}
|
||||
} else {
|
||||
bail!(schema.span, "structs need an object schema");
|
||||
error!(schema.span, "structs need an object schema");
|
||||
}
|
||||
|
||||
let mut new_fields: Vec<(FieldName, bool, Schema)> = Vec::new();
|
||||
@ -182,7 +182,7 @@ fn handle_regular_struct(attribs: JSONObject, stru: syn::ItemStruct) -> Result<T
|
||||
// now error out about all the fields not found in the struct:
|
||||
if !schema_fields.is_empty() {
|
||||
let bad_fields = util::join(", ", schema_fields.keys());
|
||||
bail!(
|
||||
error!(
|
||||
schema.span,
|
||||
"struct does not contain the following fields: {}",
|
||||
bad_fields
|
||||
@ -220,7 +220,7 @@ fn handle_regular_field(
|
||||
if derived {
|
||||
field_def.1 = true;
|
||||
} else if !field_def.1 {
|
||||
bail!(&field.ty => "non-optional Option type?");
|
||||
error!(&field.ty => "non-optional Option type?");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -143,7 +143,7 @@ impl TryFrom<&[syn::Attribute]> for ContainerAttrib {
|
||||
if var.path.is_ident("rename_all") {
|
||||
let rename_all = RenameAll::try_from(&var.lit)?;
|
||||
if this.rename_all.is_some() && this.rename_all != Some(rename_all) {
|
||||
bail!(var.lit => "multiple conflicting 'rename_all' attributes");
|
||||
error!(var.lit => "multiple conflicting 'rename_all' attributes");
|
||||
}
|
||||
this.rename_all = Some(rename_all);
|
||||
}
|
||||
@ -180,11 +180,11 @@ impl TryFrom<&[syn::Attribute]> for SerdeAttrib {
|
||||
syn::Lit::Str(lit) => {
|
||||
let rename = FieldName::from(&lit);
|
||||
if this.rename.is_some() && this.rename.as_ref() != Some(&rename) {
|
||||
bail!(lit => "multiple conflicting 'rename' attributes");
|
||||
error!(lit => "multiple conflicting 'rename' attributes");
|
||||
}
|
||||
this.rename = Some(rename);
|
||||
}
|
||||
_ => bail!(var.lit => "'rename' value must be a string literal"),
|
||||
_ => error!(var.lit => "'rename' value must be a string literal"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user