about summary refs log tree commit diff
path: root/src/libsyntax/ext
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-09-05 07:30:19 +0000
committerbors <bors@rust-lang.org>2018-09-05 07:30:19 +0000
commit3f13b27c2b6a1f83ee08a87c6134c86526edffc0 (patch)
tree851bd551452a99115a72773b871f0d0f1433fcc4 /src/libsyntax/ext
parent0be2c303692cab31390e52701007cfa87867bf74 (diff)
parent0593dc7e3c9783f1c0bbbc8f017f9e914114e057 (diff)
downloadrust-3f13b27c2b6a1f83ee08a87c6134c86526edffc0.tar.gz
rust-3f13b27c2b6a1f83ee08a87c6134c86526edffc0.zip
Auto merge of #53410 - djrenren:custom-test-frameworks, r=alexcrichton
Introduce Custom Test Frameworks

Introduces `#[test_case]` and `#[test_runner]` and re-implements `#[test]` and `#[bench]` in terms of them.

Details found here: https://blog.jrenner.net/rust/testing/2018/08/06/custom-test-framework-prop.html
Diffstat (limited to 'src/libsyntax/ext')
-rw-r--r--src/libsyntax/ext/base.rs3
-rw-r--r--src/libsyntax/ext/expand.rs80
2 files changed, 9 insertions, 74 deletions
diff --git a/src/libsyntax/ext/base.rs b/src/libsyntax/ext/base.rs
index e8a68b6d767..0e059bc4a6c 100644
--- a/src/libsyntax/ext/base.rs
+++ b/src/libsyntax/ext/base.rs
@@ -721,6 +721,7 @@ pub trait Resolver {
     fn visit_ast_fragment_with_placeholders(&mut self, mark: Mark, fragment: &AstFragment,
                                             derives: &[Mark]);
     fn add_builtin(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
+    fn add_unshadowable_attr(&mut self, ident: ast::Ident, ext: Lrc<SyntaxExtension>);
 
     fn resolve_imports(&mut self);
     // Resolves attribute and derive legacy macros from `#![plugin(..)]`.
@@ -729,6 +730,7 @@ pub trait Resolver {
 
     fn resolve_macro_invocation(&mut self, invoc: &Invocation, scope: Mark, force: bool)
                                 -> Result<Option<Lrc<SyntaxExtension>>, Determinacy>;
+
     fn resolve_macro_path(&mut self, path: &ast::Path, kind: MacroKind, scope: Mark,
                           derives_in_scope: &[ast::Path], force: bool)
                           -> Result<Lrc<SyntaxExtension>, Determinacy>;
@@ -759,6 +761,7 @@ impl Resolver for DummyResolver {
     fn visit_ast_fragment_with_placeholders(&mut self, _invoc: Mark, _fragment: &AstFragment,
                                             _derives: &[Mark]) {}
     fn add_builtin(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
+    fn add_unshadowable_attr(&mut self, _ident: ast::Ident, _ext: Lrc<SyntaxExtension>) {}
 
     fn resolve_imports(&mut self) {}
     fn find_legacy_attr_invoc(&mut self, _attrs: &mut Vec<Attribute>, _allow_derive: bool)
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index 6e38f820586..3bb19121ee3 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -12,10 +12,9 @@ use ast::{self, Block, Ident, NodeId, PatKind, Path};
 use ast::{MacStmtStyle, StmtKind, ItemKind};
 use attr::{self, HasAttrs};
 use source_map::{ExpnInfo, MacroBang, MacroAttribute, dummy_spanned, respan};
-use config::{is_test_or_bench, StripUnconfigured};
+use config::StripUnconfigured;
 use errors::{Applicability, FatalError};
 use ext::base::*;
-use ext::build::AstBuilder;
 use ext::derive::{add_derived_markers, collect_derives};
 use ext::hygiene::{self, Mark, SyntaxContext};
 use ext::placeholders::{placeholder, PlaceholderExpander};
@@ -37,7 +36,6 @@ use visit::{self, Visitor};
 use rustc_data_structures::fx::FxHashMap;
 use std::fs::File;
 use std::io::Read;
-use std::iter::FromIterator;
 use std::{iter, mem};
 use std::rc::Rc;
 use std::path::PathBuf;
@@ -452,14 +450,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
         let (fragment_with_placeholders, invocations) = {
             let mut collector = InvocationCollector {
                 cfg: StripUnconfigured {
-                    should_test: self.cx.ecfg.should_test,
                     sess: self.cx.parse_sess,
                     features: self.cx.ecfg.features,
                 },
                 cx: self.cx,
                 invocations: Vec::new(),
                 monotonic: self.monotonic,
-                tests_nameable: true,
             };
             (fragment.fold_with(&mut collector), collector.invocations)
         };
@@ -477,7 +473,6 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
 
     fn fully_configure(&mut self, item: Annotatable) -> Annotatable {
         let mut cfg = StripUnconfigured {
-            should_test: self.cx.ecfg.should_test,
             sess: self.cx.parse_sess,
             features: self.cx.ecfg.features,
         };
@@ -1049,11 +1044,6 @@ struct InvocationCollector<'a, 'b: 'a> {
     cfg: StripUnconfigured<'a>,
     invocations: Vec<Invocation>,
     monotonic: bool,
-
-    /// Test functions need to be nameable. Tests inside functions or in other
-    /// unnameable locations need to be ignored. `tests_nameable` tracks whether
-    /// any test functions found in the current context would be nameable.
-    tests_nameable: bool,
 }
 
 impl<'a, 'b> InvocationCollector<'a, 'b> {
@@ -1071,20 +1061,6 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         placeholder(fragment_kind, NodeId::placeholder_from_mark(mark))
     }
 
-    /// Folds the item allowing tests to be expanded because they are still nameable.
-    /// This should probably only be called with module items
-    fn fold_nameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
-        fold::noop_fold_item(item, self)
-    }
-
-    /// Folds the item but doesn't allow tests to occur within it
-    fn fold_unnameable(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
-        let was_nameable = mem::replace(&mut self.tests_nameable, false);
-        let items = fold::noop_fold_item(item, self);
-        self.tests_nameable = was_nameable;
-        items
-    }
-
     fn collect_bang(&mut self, mac: ast::Mac, span: Span, kind: AstFragmentKind) -> AstFragment {
         self.collect(kind, InvocationKind::Bang { mac: mac, ident: None, span: span })
     }
@@ -1299,7 +1275,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
     fn fold_item(&mut self, item: P<ast::Item>) -> OneVector<P<ast::Item>> {
         let item = configure!(self, item);
 
-        let (attr, traits, mut item) = self.classify_item(item);
+        let (attr, traits, item) = self.classify_item(item);
         if attr.is_some() || !traits.is_empty() {
             let item = Annotatable::Item(item);
             return self.collect_attr(attr, traits, item, AstFragmentKind::Items).make_items();
@@ -1321,7 +1297,7 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
             }
             ast::ItemKind::Mod(ast::Mod { inner, .. }) => {
                 if item.ident == keywords::Invalid.ident() {
-                    return self.fold_nameable(item);
+                    return noop_fold_item(item, self);
                 }
 
                 let orig_directory_ownership = self.cx.current_expansion.directory_ownership;
@@ -1361,58 +1337,13 @@ impl<'a, 'b> Folder for InvocationCollector<'a, 'b> {
 
                 let orig_module =
                     mem::replace(&mut self.cx.current_expansion.module, Rc::new(module));
-                let result = self.fold_nameable(item);
+                let result = noop_fold_item(item, self);
                 self.cx.current_expansion.module = orig_module;
                 self.cx.current_expansion.directory_ownership = orig_directory_ownership;
                 result
             }
-            // Ensure that test functions are accessible from the test harness.
-            // #[test] fn foo() {}
-            // becomes:
-            // #[test] pub fn foo_gensym(){}
-            // #[allow(unused)]
-            // use foo_gensym as foo;
-            ast::ItemKind::Fn(..) if self.cx.ecfg.should_test => {
-                if self.tests_nameable && item.attrs.iter().any(|attr| is_test_or_bench(attr)) {
-                    let orig_ident = item.ident;
-                    let orig_vis   = item.vis.clone();
-
-                    // Publicize the item under gensymed name to avoid pollution
-                    item = item.map(|mut item| {
-                        item.vis = respan(item.vis.span, ast::VisibilityKind::Public);
-                        item.ident = item.ident.gensym();
-                        item
-                    });
-
-                    // Use the gensymed name under the item's original visibility
-                    let mut use_item = self.cx.item_use_simple_(
-                        item.ident.span,
-                        orig_vis,
-                        Some(orig_ident),
-                        self.cx.path(item.ident.span,
-                            vec![keywords::SelfValue.ident(), item.ident]));
-
-                    // #[allow(unused)] because the test function probably isn't being referenced
-                    use_item = use_item.map(|mut ui| {
-                        ui.attrs.push(
-                            self.cx.attribute(DUMMY_SP, attr::mk_list_item(DUMMY_SP,
-                                Ident::from_str("allow"), vec![
-                                    attr::mk_nested_word_item(Ident::from_str("unused"))
-                                ]
-                            ))
-                        );
-
-                        ui
-                    });
 
-                    OneVector::from_iter(
-                        self.fold_unnameable(item).into_iter()
-                            .chain(self.fold_unnameable(use_item)))
-                } else {
-                    self.fold_unnameable(item)
-                }
-            }
-            _ => self.fold_unnameable(item),
+            _ => noop_fold_item(item, self),
         }
     }
 
@@ -1637,6 +1568,7 @@ impl<'feat> ExpansionConfig<'feat> {
     feature_tests! {
         fn enable_quotes = quote,
         fn enable_asm = asm,
+        fn enable_custom_test_frameworks = custom_test_frameworks,
         fn enable_global_asm = global_asm,
         fn enable_log_syntax = log_syntax,
         fn enable_concat_idents = concat_idents,