Skip to content

Instantly share code, notes, and snippets.

@farcaller
Last active August 29, 2015 14:04
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save farcaller/d0d353c1d63191f5ab34 to your computer and use it in GitHub Desktop.
Save farcaller/d0d353c1d63191f5ab34 to your computer and use it in GitHub Desktop.
#[cfg(test)]
mod test {
use hamcrest::{assert_that, is, equal_to};
describe!(
before_each {
let value = true;
}
it "includes all the statements from before_each scope" {
assert_that(value, is(equal_to(true)));
}
it "can have multiple blocks" {
assert!(true);
}
)
}
// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![crate_name="shiny"]
#![crate_type="dylib"]
#![feature(plugin_registrar, quote, managed_boxes)]
extern crate rustc;
extern crate serialize;
extern crate syntax;
use rustc::plugin::Registry;
use std::gc::{Gc, GC};
use syntax::ast;
use syntax::codemap::DUMMY_SP;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacResult};
use syntax::ext::build::AstBuilder;
use syntax::util::small_vector::SmallVector;
use syntax::parse::tts_to_parser;
use syntax::parse::token;
use syntax::abi;
use syntax::ast_util::empty_generics;
#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
reg.register_macro("describe", macro_describe);
}
pub fn macro_describe(cx: &mut ExtCtxt, _: Span, tts: &[ast::TokenTree])
-> Box<MacResult> {
let sess = cx.parse_sess();
let ttsvec = tts.iter().map(|x| (*x).clone()).collect();
let mut parser = tts_to_parser(sess, ttsvec, cx.cfg());
let mut before_block = None;
let mut test_blocks = vec!();
loop {
if parser.token == token::EOF {
break;
}
let ident = parser.parse_ident();
match ident.as_str() {
"before_each" => {
if before_block.is_some() {
fail!("only one before_each block is allowed");
}
before_block = Some(parser.parse_block());
},
"it" => {
let (name, _) = parser.parse_str();
let block = parser.parse_block();
test_blocks.push((name.get().to_string(), block));
}
_ => fail!(),
}
}
let mut funcs = vec!();
for &(ref name, block) in test_blocks.iter() {
let body = if before_block.is_none() {
block
} else {
let before = before_block.unwrap();
box(GC) ast::Block {
view_items: before.view_items + block.view_items,
stmts: before.stmts + block.stmts,
..block.deref().clone()
}
};
let attr_test = cx.attribute(DUMMY_SP, cx.meta_word(
DUMMY_SP, token::InternedString::new("test")));
let attrs = vec!(attr_test);
let func = box(GC) ast::Item {
ident: cx.ident_of(name.replace(" ", "_").as_slice()),
attrs: attrs,
id: ast::DUMMY_NODE_ID,
node: ast::ItemFn(
cx.fn_decl(Vec::new(), cx.ty_nil()),
ast::NormalFn,
abi::Rust,
empty_generics(),
body),
vis: ast::Inherited,
span: DUMMY_SP,
};
funcs.push(func);
}
MacItems::new(funcs)
}
pub struct MacItems {
items: Vec<Gc<ast::Item>>
}
impl MacItems {
pub fn new(items: Vec<Gc<ast::Item>>) -> Box<MacResult> {
box MacItems { items: items } as Box<MacResult>
}
}
impl MacResult for MacItems {
fn make_items(&self) -> Option<SmallVector<Gc<ast::Item>>> {
Some(SmallVector::many(self.items.clone()))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment