about summary refs log tree commit diff
path: root/src/libsyntax_ext/test.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/libsyntax_ext/test.rs')
-rw-r--r--src/libsyntax_ext/test.rs33
1 files changed, 33 insertions, 0 deletions
diff --git a/src/libsyntax_ext/test.rs b/src/libsyntax_ext/test.rs
index d381c42f9ce..a2d93d01cec 100644
--- a/src/libsyntax_ext/test.rs
+++ b/src/libsyntax_ext/test.rs
@@ -7,11 +7,44 @@ use syntax::ext::base::*;
 use syntax::ext::build::AstBuilder;
 use syntax::ext::hygiene::SyntaxContext;
 use syntax::print::pprust;
+use syntax::source_map::respan;
 use syntax::symbol::{Symbol, sym};
 use syntax_pos::Span;
 
 use std::iter;
 
+// #[test_case] is used by custom test authors to mark tests
+// When building for test, it needs to make the item public and gensym the name
+// Otherwise, we'll omit the item. This behavior means that any item annotated
+// with #[test_case] is never addressable.
+//
+// We mark item with an inert attribute "rustc_test_marker" which the test generation
+// logic will pick up on.
+pub fn expand_test_case(
+    ecx: &mut ExtCtxt<'_>,
+    attr_sp: Span,
+    meta_item: &ast::MetaItem,
+    anno_item: Annotatable
+) -> Vec<Annotatable> {
+    check_builtin_macro_attribute(ecx, meta_item, sym::test_case);
+
+    if !ecx.ecfg.should_test { return vec![]; }
+
+    let sp = attr_sp.with_ctxt(SyntaxContext::empty().apply_mark(ecx.current_expansion.id));
+    let mut item = anno_item.expect_item();
+    item = item.map(|mut item| {
+        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
+        item.ident = item.ident.gensym();
+        item.attrs.push(
+            ecx.attribute(sp,
+                ecx.meta_word(sp, sym::rustc_test_marker))
+        );
+        item
+    });
+
+    return vec![Annotatable::Item(item)]
+}
+
 pub fn expand_test(
     cx: &mut ExtCtxt<'_>,
     attr_sp: Span,