]>
Commit | Line | Data |
---|---|---|
54a0048b SL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | //! Walks the crate looking for items/impl-items/trait-items that have | |
12 | //! either a `rustc_symbol_name` or `rustc_item_path` attribute and | |
13 | //! generates an error giving, respectively, the symbol name or | |
14 | //! item-path. This is used for unit testing the code that generates | |
15 | //! paths etc in all kinds of annoying scenarios. | |
16 | ||
54a0048b | 17 | use rustc::hir; |
476ff2be | 18 | use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; |
cc61c64b | 19 | use rustc::ty::TyCtxt; |
54a0048b | 20 | use syntax::ast; |
54a0048b | 21 | |
54a0048b SL |
22 | use monomorphize::Instance; |
23 | ||
24 | const SYMBOL_NAME: &'static str = "rustc_symbol_name"; | |
25 | const ITEM_PATH: &'static str = "rustc_item_path"; | |
26 | ||
cc61c64b | 27 | pub fn report_symbol_names<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) { |
54a0048b SL |
28 | // if the `rustc_attrs` feature is not enabled, then the |
29 | // attributes we are interested in cannot be present anyway, so | |
30 | // skip the walk. | |
54a0048b SL |
31 | if !tcx.sess.features.borrow().rustc_attrs { |
32 | return; | |
33 | } | |
34 | ||
35 | let _ignore = tcx.dep_graph.in_ignore(); | |
cc61c64b | 36 | let mut visitor = SymbolNamesTest { tcx: tcx }; |
476ff2be | 37 | // FIXME(#37712) could use ItemLikeVisitor if trait items were item-like |
32a655c1 | 38 | tcx.hir.krate().visit_all_item_likes(&mut visitor.as_deep_visitor()); |
54a0048b SL |
39 | } |
40 | ||
41 | struct SymbolNamesTest<'a, 'tcx:'a> { | |
cc61c64b | 42 | tcx: TyCtxt<'a, 'tcx, 'tcx>, |
54a0048b SL |
43 | } |
44 | ||
45 | impl<'a, 'tcx> SymbolNamesTest<'a, 'tcx> { | |
46 | fn process_attrs(&mut self, | |
47 | node_id: ast::NodeId) { | |
cc61c64b | 48 | let tcx = self.tcx; |
32a655c1 | 49 | let def_id = tcx.hir.local_def_id(node_id); |
54a0048b SL |
50 | for attr in tcx.get_attrs(def_id).iter() { |
51 | if attr.check_name(SYMBOL_NAME) { | |
52 | // for now, can only use on monomorphic names | |
cc61c64b | 53 | let instance = Instance::mono(tcx, def_id); |
7cac9316 | 54 | let name = self.tcx.symbol_name(instance); |
54a0048b SL |
55 | tcx.sess.span_err(attr.span, &format!("symbol-name({})", name)); |
56 | } else if attr.check_name(ITEM_PATH) { | |
57 | let path = tcx.item_path_str(def_id); | |
58 | tcx.sess.span_err(attr.span, &format!("item-path({})", path)); | |
59 | } | |
60 | ||
61 | // (*) The formatting of `tag({})` is chosen so that tests can elect | |
62 | // to test the entirety of the string, if they choose, or else just | |
63 | // some subset. | |
64 | } | |
65 | } | |
66 | } | |
67 | ||
68 | impl<'a, 'tcx> Visitor<'tcx> for SymbolNamesTest<'a, 'tcx> { | |
476ff2be SL |
69 | fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { |
70 | NestedVisitorMap::None | |
71 | } | |
72 | ||
54a0048b SL |
73 | fn visit_item(&mut self, item: &'tcx hir::Item) { |
74 | self.process_attrs(item.id); | |
75 | intravisit::walk_item(self, item); | |
76 | } | |
77 | ||
78 | fn visit_trait_item(&mut self, ti: &'tcx hir::TraitItem) { | |
79 | self.process_attrs(ti.id); | |
80 | intravisit::walk_trait_item(self, ti) | |
81 | } | |
82 | ||
83 | fn visit_impl_item(&mut self, ii: &'tcx hir::ImplItem) { | |
84 | self.process_attrs(ii.id); | |
85 | intravisit::walk_impl_item(self, ii) | |
86 | } | |
87 | } |