diff options
Diffstat (limited to 'compiler/rustc_builtin_macros/src/test.rs')
| -rw-r--r-- | compiler/rustc_builtin_macros/src/test.rs | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index e02c7e6c01b..151afd2d458 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -8,7 +8,7 @@ use rustc_errors::Applicability; use rustc_expand::base::*; use rustc_session::Session; use rustc_span::symbol::{sym, Ident, Symbol}; -use rustc_span::Span; +use rustc_span::{FileNameDisplayPreference, Span}; use std::iter; use thin_vec::{thin_vec, ThinVec}; @@ -33,7 +33,23 @@ pub fn expand_test_case( } let sp = ecx.with_def_site_ctxt(attr_sp); - let mut item = anno_item.expect_item(); + let (mut item, is_stmt) = match anno_item { + Annotatable::Item(item) => (item, false), + Annotatable::Stmt(stmt) if let ast::StmtKind::Item(_) = stmt.kind => if let ast::StmtKind::Item(i) = stmt.into_inner().kind { + (i, true) + } else { + unreachable!() + }, + _ => { + ecx.struct_span_err( + anno_item.span(), + "`#[test_case]` attribute is only allowed on items", + ) + .emit(); + + return vec![]; + } + }; item = item.map(|mut item| { let test_path_symbol = Symbol::intern(&item_path( // skip the name of the root module @@ -50,7 +66,13 @@ pub fn expand_test_case( item }); - return vec![Annotatable::Item(item)]; + let ret = if is_stmt { + Annotatable::Stmt(P(ecx.stmt_item(item.span, item))) + } else { + Annotatable::Item(item) + }; + + vec![ret] } pub fn expand_test( @@ -231,6 +253,8 @@ pub fn expand_test_or_bench( &item.ident, )); + let location_info = get_location_info(cx, &item); + let mut test_const = cx.item( sp, Ident::new(item.ident.name, sp), @@ -280,6 +304,16 @@ pub fn expand_test_or_bench( cx.expr_none(sp) }, ), + // source_file: <relative_path_of_source_file> + field("source_file", cx.expr_str(sp, location_info.0)), + // start_line: start line of the test fn identifier. + field("start_line", cx.expr_usize(sp, location_info.1)), + // start_col: start column of the test fn identifier. + field("start_col", cx.expr_usize(sp, location_info.2)), + // end_line: end line of the test fn identifier. + field("end_line", cx.expr_usize(sp, location_info.3)), + // end_col: end column of the test fn identifier. + field("end_col", cx.expr_usize(sp, location_info.4)), // compile_fail: true | false field("compile_fail", cx.expr_bool(sp, false)), // no_run: true | false @@ -364,6 +398,19 @@ pub fn expand_test_or_bench( } } +fn get_location_info(cx: &ExtCtxt<'_>, item: &ast::Item) -> (Symbol, usize, usize, usize, usize) { + let span = item.ident.span; + let (source_file, lo_line, lo_col, hi_line, hi_col) = + cx.sess.source_map().span_to_location_info(span); + + let file_name = match source_file { + Some(sf) => sf.name.display(FileNameDisplayPreference::Remapped).to_string(), + None => "no-location".to_string(), + }; + + (Symbol::intern(&file_name), lo_line, lo_col, hi_line, hi_col) +} + fn item_path(mod_path: &[Ident], item_ident: &Ident) -> String { mod_path .iter() |
