mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Rewrite the unit tests in ext/expand.rs
as a compile-fail
test.
This commit is contained in:
parent
a9821e1658
commit
20b43b2323
@ -803,110 +803,3 @@ impl Folder for Marker {
|
||||
fn mark_tts(tts: &[TokenTree], m: Mark) -> Vec<TokenTree> {
|
||||
noop_fold_tts(tts, &mut Marker{mark:m, expn_id: None})
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{expand_crate, ExpansionConfig};
|
||||
use ast;
|
||||
use ext::base::{ExtCtxt, DummyResolver};
|
||||
use parse;
|
||||
use util::parser_testing::{string_to_parser};
|
||||
use visit;
|
||||
use visit::Visitor;
|
||||
|
||||
// a visitor that extracts the paths
|
||||
// from a given thingy and puts them in a mutable
|
||||
// array (passed in to the traversal)
|
||||
#[derive(Clone)]
|
||||
struct PathExprFinderContext {
|
||||
path_accumulator: Vec<ast::Path> ,
|
||||
}
|
||||
|
||||
impl Visitor for PathExprFinderContext {
|
||||
fn visit_expr(&mut self, expr: &ast::Expr) {
|
||||
if let ast::ExprKind::Path(None, ref p) = expr.node {
|
||||
self.path_accumulator.push(p.clone());
|
||||
}
|
||||
visit::walk_expr(self, expr);
|
||||
}
|
||||
}
|
||||
|
||||
// these following tests are quite fragile, in that they don't test what
|
||||
// *kind* of failure occurs.
|
||||
|
||||
fn test_ecfg() -> ExpansionConfig<'static> {
|
||||
ExpansionConfig::default("test".to_string())
|
||||
}
|
||||
|
||||
// make sure that macros can't escape fns
|
||||
#[should_panic]
|
||||
#[test] fn macros_cant_escape_fns_test () {
|
||||
let src = "fn bogus() {macro_rules! z (() => (3+4));}\
|
||||
fn inty() -> i32 { z!() }".to_string();
|
||||
let sess = parse::ParseSess::new();
|
||||
let crate_ast = parse::parse_crate_from_source_str(
|
||||
"<test>".to_string(),
|
||||
src,
|
||||
Vec::new(), &sess).unwrap();
|
||||
// should fail:
|
||||
let mut loader = DummyResolver;
|
||||
let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
|
||||
expand_crate(&mut ecx, vec![], crate_ast);
|
||||
}
|
||||
|
||||
// make sure that macros can't escape modules
|
||||
#[should_panic]
|
||||
#[test] fn macros_cant_escape_mods_test () {
|
||||
let src = "mod foo {macro_rules! z (() => (3+4));}\
|
||||
fn inty() -> i32 { z!() }".to_string();
|
||||
let sess = parse::ParseSess::new();
|
||||
let crate_ast = parse::parse_crate_from_source_str(
|
||||
"<test>".to_string(),
|
||||
src,
|
||||
Vec::new(), &sess).unwrap();
|
||||
let mut loader = DummyResolver;
|
||||
let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
|
||||
expand_crate(&mut ecx, vec![], crate_ast);
|
||||
}
|
||||
|
||||
// macro_use modules should allow macros to escape
|
||||
#[test] fn macros_can_escape_flattened_mods_test () {
|
||||
let src = "#[macro_use] mod foo {macro_rules! z (() => (3+4));}\
|
||||
fn inty() -> i32 { z!() }".to_string();
|
||||
let sess = parse::ParseSess::new();
|
||||
let crate_ast = parse::parse_crate_from_source_str(
|
||||
"<test>".to_string(),
|
||||
src,
|
||||
Vec::new(), &sess).unwrap();
|
||||
let mut loader = DummyResolver;
|
||||
let mut ecx = ExtCtxt::new(&sess, vec![], test_ecfg(), &mut loader);
|
||||
expand_crate(&mut ecx, vec![], crate_ast);
|
||||
}
|
||||
|
||||
fn expand_crate_str(crate_str: String) -> ast::Crate {
|
||||
let ps = parse::ParseSess::new();
|
||||
let crate_ast = panictry!(string_to_parser(&ps, crate_str).parse_crate_mod());
|
||||
// the cfg argument actually does matter, here...
|
||||
let mut loader = DummyResolver;
|
||||
let mut ecx = ExtCtxt::new(&ps, vec![], test_ecfg(), &mut loader);
|
||||
expand_crate(&mut ecx, vec![], crate_ast)
|
||||
}
|
||||
|
||||
#[test] fn macro_tokens_should_match(){
|
||||
expand_crate_str(
|
||||
"macro_rules! m((a)=>(13)) ;fn main(){m!(a);}".to_string());
|
||||
}
|
||||
|
||||
// should be able to use a bound identifier as a literal in a macro definition:
|
||||
#[test] fn self_macro_parsing(){
|
||||
expand_crate_str(
|
||||
"macro_rules! foo ((zz) => (287;));
|
||||
fn f(zz: i32) {foo!(zz);}".to_string()
|
||||
);
|
||||
}
|
||||
|
||||
// create a really evil test case where a $x appears inside a binding of $x
|
||||
// but *shouldn't* bind because it was inserted by a different macro....
|
||||
// can't write this test case until we have macro-generating macros.
|
||||
}
|
||||
|
46
src/test/compile-fail/macro-expansion-tests.rs
Normal file
46
src/test/compile-fail/macro-expansion-tests.rs
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
mod macros_cant_escape_fns {
|
||||
fn f() {
|
||||
macro_rules! m { () => { 3 + 4 } }
|
||||
}
|
||||
fn g() -> i32 { m!() } //~ ERROR macro undefined
|
||||
}
|
||||
|
||||
mod macros_cant_escape_mods {
|
||||
mod f {
|
||||
macro_rules! m { () => { 3 + 4 } }
|
||||
}
|
||||
fn g() -> i32 { m!() } //~ ERROR macro undefined
|
||||
}
|
||||
|
||||
mod macros_can_escape_flattened_mods_test {
|
||||
#[macro_use]
|
||||
mod f {
|
||||
macro_rules! m { () => { 3 + 4 } }
|
||||
}
|
||||
fn g() -> i32 { m!() }
|
||||
}
|
||||
|
||||
fn macro_tokens_should_match() {
|
||||
macro_rules! m { (a) => { 13 } }
|
||||
m!(a);
|
||||
}
|
||||
|
||||
// should be able to use a bound identifier as a literal in a macro definition:
|
||||
fn self_macro_parsing() {
|
||||
macro_rules! foo { (zz) => { 287; } }
|
||||
fn f(zz: i32) {
|
||||
foo!(zz);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
Loading…
Reference in New Issue
Block a user