Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macros: improve error massages #1420

Merged
merged 2 commits into from
Aug 9, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 27 additions & 28 deletions tokio-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@
extern crate proc_macro;

use proc_macro::TokenStream;
use quote::{quote, quote_spanned};
use syn::spanned::Spanned;
use quote::quote;

/// Marks async function to be executed by selected runtime.
///
Expand Down Expand Up @@ -56,17 +55,15 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
let attrs = &input.attrs;

if input.asyncness.is_none() {
let tokens = quote_spanned! { input.span() =>
compile_error!("the async keyword is missing from the function declaration");
};

return TokenStream::from(tokens);
let msg = "the async keyword is missing from the function declaration";
return syn::Error::new_spanned(input.decl.fn_token, msg)
Copy link
Member Author

@taiki-e taiki-e Aug 9, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no change (perhaps the clearest is to highlight fn.).

error: the async keyword is missing from the function declaration
  --> tokio\examples\echo.rs:34:1
   |
34 | fn main() -> Result<(), Box<dyn Error>> {
   | ^^

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that the original version highlights the entire function when procmacro2_semver_exempt is active.

.to_compile_error()
.into();
} else if !input.decl.inputs.is_empty() {
let tokens = quote_spanned! { input.span() =>
compile_error!("the main function cannot accept arguments");
};

return TokenStream::from(tokens);
let msg = "the main function cannot accept arguments";
return syn::Error::new_spanned(&input.decl.inputs, msg)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before:

error: the main function cannot accept arguments
  --> tokio\examples\echo.rs:34:1
   |
34 | async fn main(foo: Foo) -> Result<(), Box<dyn Error>> {
   | ^^^^^

After:

error: the main function cannot accept arguments
  --> tokio\examples\echo.rs:34:15
   |
34 | async fn main(foo: Foo) -> Result<(), Box<dyn Error>> {
   |               ^^^^^^^^

.to_compile_error()
.into();
}

let mut runtime = RuntimeType::Multi;
Expand All @@ -76,7 +73,12 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
match ident.to_string().to_lowercase().as_str() {
"multi_thread" => runtime = RuntimeType::Multi,
"single_thread" => runtime = RuntimeType::Single,
name => panic!("Unknown attribute {} is specified", name),
name => {
let msg = format!("Unknown attribute {} is specified", name);
return syn::Error::new_spanned(ident, msg)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before

error: custom attribute panicked
  --> tokio\examples\echo.rs:33:1
   |
33 | #[tokio::main(foo)]
   | ^^^^^^^^^^^^^^^^^^^
   |
   = help: message: Unknown attribute foo is specified

After:

error: Unknown attribute foo is specified
  --> tokio\examples\echo.rs:33:15
   |
33 | #[tokio::main(foo)]
   |               ^^^

.to_compile_error()
.into();
}
}
}
}
Expand Down Expand Up @@ -126,26 +128,23 @@ pub fn test(_attr: TokenStream, item: TokenStream) -> TokenStream {

for attr in attrs {
if attr.path.is_ident("test") {
let tokens = quote_spanned! { input.span() =>
compile_error!("second test attribute is supplied");
};

return TokenStream::from(tokens);
let msg = "second test attribute is supplied";
return syn::Error::new_spanned(&attr, msg)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no change (this should be fine.).

error: second test attribute is supplied
  --> tokio\tests\buffered.rs:14:1
   |
14 | #[test]
   | ^^^^^^^

.to_compile_error()
.into();
}
}

if input.asyncness.is_none() {
let tokens = quote_spanned! { input.span() =>
compile_error!("the async keyword is missing from the function declaration");
};

return TokenStream::from(tokens);
let msg = "the async keyword is missing from the function declaration";
return syn::Error::new_spanned(&input, msg)
.to_compile_error()
.into();
} else if !input.decl.inputs.is_empty() {
let tokens = quote_spanned! { input.span() =>
compile_error!("the test function cannot accept arguments");
};

return TokenStream::from(tokens);
let msg = "the test function cannot accept arguments";
return syn::Error::new_spanned(&input.decl.inputs, msg)
.to_compile_error()
.into();
}

let result = quote! {
Expand Down