use rustc_ast::attr;
use rustc_ast::ptr::P;
use rustc_ast_pretty::pprust;
+use rustc_errors::Applicability;
use rustc_expand::base::*;
use rustc_session::Session;
use rustc_span::symbol::{sym, Ident, Symbol};
}
};
- if let ast::ItemKind::MacCall(_) = item.kind {
- cx.sess.parse_sess.span_diagnostic.span_warn(
- item.span,
- "`#[test]` attribute should not be used on macros. Use `#[cfg(test)]` instead.",
- );
+ // Note: non-associated fn items are already handled by `expand_test_or_bench`
+ if !matches!(item.kind, ast::ItemKind::Fn(_)) {
+ cx.sess
+ .parse_sess
+ .span_diagnostic
+ .struct_span_err(
+ attr_sp,
+ "the `#[test]` attribute may only be used on a non-associated function",
+ )
+ .note("the `#[test]` macro causes a a function to be run on a test and has no effect on non-functions")
+ .span_label(item.span, format!("expected a non-associated function, found {} {}", item.kind.article(), item.kind.descr()))
+ .span_suggestion(attr_sp, "replace with conditional compilation to make the item only exist when tests are being run", String::from("#[cfg(test)]"), Applicability::MaybeIncorrect)
+ .emit();
+
return vec![Annotatable::Item(item)];
}
"ignore",
cx.expr_bool(sp, should_ignore(&cx.sess, &item)),
),
+ // ignore_message: Some("...") | None
+ field(
+ "ignore_message",
+ if let Some(msg) = should_ignore_message(cx, &item) {
+ cx.expr_some(sp, cx.expr_str(sp, msg))
+ } else {
+ cx.expr_none(sp)
+ },
+ ),
// compile_fail: true | false
field("compile_fail", cx.expr_bool(sp, false)),
// no_run: true | false
sess.contains_name(&i.attrs, sym::ignore)
}
+fn should_ignore_message(cx: &ExtCtxt<'_>, i: &ast::Item) -> Option<Symbol> {
+ match cx.sess.find_by_name(&i.attrs, sym::ignore) {
+ Some(attr) => {
+ match attr.meta_item_list() {
+ // Handle #[ignore(bar = "foo")]
+ Some(_) => None,
+ // Handle #[ignore] and #[ignore = "message"]
+ None => attr.value_str(),
+ }
+ }
+ None => None,
+ }
+}
+
fn should_panic(cx: &ExtCtxt<'_>, i: &ast::Item) -> ShouldPanic {
match cx.sess.find_by_name(&i.attrs, sym::should_panic) {
Some(attr) => {
(false, _) => true,
}
} else {
- sd.span_err(i.span, "only functions may be used as tests");
+ // should be unreachable because `is_test_fn_item` should catch all non-fn items
false
}
}