From 51e6df689cf292e10e99bc011baae6d82a1d4b71 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 5 Jan 2012 18:16:42 -0800 Subject: [PATCH] rustc: Allow the test runner to run unexported tests --- src/comp/front/test.rs | 5 +++- src/comp/middle/resolve.rs | 36 ++++++++++++++++++----- src/test/run-fail/run-unexported-tests.rs | 13 ++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 src/test/run-fail/run-unexported-tests.rs diff --git a/src/comp/front/test.rs b/src/comp/front/test.rs index 46293c80310..bb2e5426938 100644 --- a/src/comp/front/test.rs +++ b/src/comp/front/test.rs @@ -187,9 +187,12 @@ fn mk_test_module(cx: test_ctxt) -> @ast::item { let mainfn = mk_main(cx); let testmod: ast::_mod = {view_items: [], items: [mainfn, testsfn]}; let item_ = ast::item_mod(testmod); + // This attribute tells resolve to let us call unexported functions + let resolve_unexported_attr = + attr::mk_attr(attr::mk_word_item("!resolve_unexported")); let item: ast::item = {ident: "__test", - attrs: [], + attrs: [resolve_unexported_attr], id: cx.sess.next_node_id(), node: item_, span: dummy_sp()}; diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index 01be1c4409f..9aa57e182cc 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -2,8 +2,9 @@ import syntax::{ast, ast_util, codemap}; import syntax::ast::*; import ast::{ident, fn_ident, def, def_id, node_id}; -import syntax::ast_util::{local_def, def_id_of_def, is_exported}; +import syntax::ast_util::{local_def, def_id_of_def}; +import front::attr; import metadata::{csearch, cstore}; import driver::session::session; import util::common::*; @@ -143,6 +144,7 @@ fn eq(v1: key, v2: key) -> bool { mutable reported: [{ident: str, sc: scope}], mutable ignored_imports: [node_id], mutable current_tp: option::t, + mutable resolve_unexported: bool, sess: session}; @@ -170,6 +172,7 @@ fn resolve_crate(sess: session, amap: ast_map::map, crate: @ast::crate) -> mutable reported: [], mutable ignored_imports: [], mutable current_tp: none, + mutable resolve_unexported: false, sess: sess}; map_crate(e, crate); resolve_imports(*e); @@ -231,7 +234,7 @@ fn path_from_scope(sc: scopes, n: str) -> str { path } fn index_i(e: @env, i: @ast::item, sc: scopes, v: vt) { - visit_item_with_scope(i, sc, v); + visit_item_with_scope(e, i, sc, v); alt i.node { ast::item_mod(md) { e.mod_map.insert(i.id, @@ -257,7 +260,7 @@ fn index_i(e: @env, i: @ast::item, sc: scopes, v: vt) { let v_link_glob = @{visit_view_item: bind link_glob(e, _, _, _), visit_block: visit_block_with_scope, - visit_item: visit_item_with_scope + visit_item: bind visit_item_with_scope(e, _, _, _) with *visit::default_visitor::()}; visit::visit_crate(*c, cons(scope_crate, @nil), visit::mk_vt(v_link_glob)); @@ -331,7 +334,7 @@ fn resolve_names(e: @env, c: @ast::crate) { e.used_imports.track = true; let v = @{visit_native_item: visit_native_item_with_scope, - visit_item: visit_item_with_scope, + visit_item: bind visit_item_with_scope(e, _, _, _), visit_block: visit_block_with_scope, visit_decl: visit_decl_with_scope, visit_arm: visit_arm_with_scope, @@ -413,7 +416,17 @@ fn walk_pat(e: @env, pat: @ast::pat, sc: scopes, v: vt) { // Visit helper functions -fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt) { +fn visit_item_with_scope(e: @env, i: @ast::item, sc: scopes, v: vt) { + + // Some magic here. Items with the !resolve_unexported attribute + // cause us to consider every name to be exported when resolving their + // contents. This is used to allow the test runner to run unexported + // tests. + let old_resolve_unexported = e.resolve_unexported; + e.resolve_unexported |= + attr::contains_name(attr::attr_metas(i.attrs), + "!resolve_unexported"); + let sc = cons(scope_item(i), @sc); alt i.node { ast::item_impl(tps, ifce, sty, methods) { @@ -436,6 +449,8 @@ fn visit_item_with_scope(i: @ast::item, sc: scopes, v: vt) { } _ { visit::visit_item(i, sc, v); } } + + e.resolve_unexported = old_resolve_unexported; } fn visit_native_item_with_scope(ni: @ast::native_item, sc: scopes, @@ -1187,10 +1202,14 @@ fn lookup_in_local_native_mod(e: env, node_id: node_id, sp: span, id: ident, ret lookup_in_local_mod(e, node_id, sp, id, ns, inside); } +fn is_exported(e: env, i: ident, m: _mod) -> bool { + ast_util::is_exported(i, m) || e.resolve_unexported +} + fn lookup_in_local_mod(e: env, node_id: node_id, sp: span, id: ident, ns: namespace, dr: dir) -> option::t { let info = e.mod_map.get(node_id); - if dr == outside && !is_exported(id, option::get(info.m)) { + if dr == outside && !is_exported(e, id, option::get(info.m)) { // if we're in a native mod, then dr==inside, so info.m is some _mod ret none::; // name is not visible } @@ -1792,7 +1811,10 @@ fn find_impls_in_item(e: env, i: @ast::item, &impls: [@_impl], alt i.node { ast::item_impl(_, ifce, _, mthds) { if alt name { some(n) { n == i.ident } _ { true } } && - alt ck_exports { some(m) { is_exported(i.ident, m) } _ { true } } { + alt ck_exports { + some(m) { is_exported(e, i.ident, m) } + _ { true } + } { impls += [@{did: local_def(i.id), iface_did: alt ifce { some(@{node: ast::ty_path(_, id), _}) { diff --git a/src/test/run-fail/run-unexported-tests.rs b/src/test/run-fail/run-unexported-tests.rs new file mode 100644 index 00000000000..c0512a4e213 --- /dev/null +++ b/src/test/run-fail/run-unexported-tests.rs @@ -0,0 +1,13 @@ +// error-pattern:runned an unexported test +// compile-flags:--test + +use std; + +mod m { + export exported; + + fn exported() { } + + #[test] + fn unexported() { fail "runned an unexported test"; } +} -- 2.44.0