]>
Commit | Line | Data |
---|---|---|
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 | use super::{Item, ImplItem, TraitItem}; | |
12 | use super::intravisit::Visitor; | |
13 | ||
14 | /// The "item-like visitor" visitor defines only the top-level methods | |
15 | /// that can be invoked by `Crate::visit_all_item_likes()`. Whether | |
16 | /// this trait is the right one to implement will depend on the | |
17 | /// overall pattern you need. Here are the three available patterns, | |
18 | /// in roughly the order of desirability: | |
19 | /// | |
20 | /// 1. **Shallow visit**: Get a simple callback for every item (or item-like thing) in the HIR. | |
21 | /// - Example: find all items with a `#[foo]` attribute on them. | |
22 | /// - How: Implement `ItemLikeVisitor` and call `tcx.hir.krate().visit_all_item_likes()`. | |
23 | /// - Pro: Efficient; just walks the lists of item-like things, not the nodes themselves. | |
24 | /// - Con: Don't get information about nesting | |
25 | /// - Con: Don't have methods for specific bits of HIR, like "on | |
26 | /// every expr, do this". | |
27 | /// 2. **Deep visit**: Want to scan for specific kinds of HIR nodes within | |
28 | /// an item, but don't care about how item-like things are nested | |
29 | /// within one another. | |
30 | /// - Example: Examine each expression to look for its type and do some check or other. | |
31 | /// - How: Implement `intravisit::Visitor` and use | |
32 | /// `tcx.hir.krate().visit_all_item_likes(visitor.as_deep_visitor())`. Within | |
33 | /// your `intravisit::Visitor` impl, implement methods like | |
34 | /// `visit_expr()`; don't forget to invoke | |
35 | /// `intravisit::walk_visit_expr()` to keep walking the subparts. | |
36 | /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. | |
37 | /// - Pro: Integrates well into dependency tracking. | |
38 | /// - Con: Don't get information about nesting between items | |
39 | /// 3. **Nested visit**: Want to visit the whole HIR and you care about the nesting between | |
40 | /// item-like things. | |
41 | /// - Example: Lifetime resolution, which wants to bring lifetimes declared on the | |
42 | /// impl into scope while visiting the impl-items, and then back out again. | |
43 | /// - How: Implement `intravisit::Visitor` and override the | |
44 | /// `nested_visit_map()` methods to return | |
45 | /// `NestedVisitorMap::All`. Walk your crate with | |
46 | /// `intravisit::walk_crate()` invoked on `tcx.hir.krate()`. | |
47 | /// - Pro: Visitor methods for any kind of HIR node, not just item-like things. | |
48 | /// - Pro: Preserves nesting information | |
49 | /// - Con: Does not integrate well into dependency tracking. | |
50 | /// | |
51 | /// Note: the methods of `ItemLikeVisitor` intentionally have no | |
52 | /// defaults, so that as we expand the list of item-like things, we | |
53 | /// revisit the various visitors to see if they need to change. This | |
54 | /// is harder to do with `intravisit::Visitor`, so when you add a new | |
55 | /// `visit_nested_foo()` method, it is recommended that you search for | |
56 | /// existing `fn visit_nested` methods to see where changes are | |
57 | /// needed. | |
58 | pub trait ItemLikeVisitor<'hir> { | |
59 | fn visit_item(&mut self, item: &'hir Item); | |
60 | fn visit_trait_item(&mut self, trait_item: &'hir TraitItem); | |
61 | fn visit_impl_item(&mut self, impl_item: &'hir ImplItem); | |
62 | } | |
63 | ||
64 | pub struct DeepVisitor<'v, V: 'v> { | |
65 | visitor: &'v mut V, | |
66 | } | |
67 | ||
68 | impl<'v, 'hir, V> DeepVisitor<'v, V> | |
69 | where V: Visitor<'hir> + 'v | |
70 | { | |
71 | pub fn new(base: &'v mut V) -> Self { | |
72 | DeepVisitor { visitor: base } | |
73 | } | |
74 | } | |
75 | ||
76 | impl<'v, 'hir, V> ItemLikeVisitor<'hir> for DeepVisitor<'v, V> | |
77 | where V: Visitor<'hir> | |
78 | { | |
79 | fn visit_item(&mut self, item: &'hir Item) { | |
80 | self.visitor.visit_item(item); | |
81 | } | |
82 | ||
83 | fn visit_trait_item(&mut self, trait_item: &'hir TraitItem) { | |
84 | self.visitor.visit_trait_item(trait_item); | |
85 | } | |
86 | ||
87 | fn visit_impl_item(&mut self, impl_item: &'hir ImplItem) { | |
88 | self.visitor.visit_impl_item(impl_item); | |
89 | } | |
90 | } |