1 // Copyright 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.
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.
13 use intravisit::{self, Visitor, FnKind};
15 use syntax::ast::{Name, NodeId, DUMMY_NODE_ID};
16 use syntax::codemap::Span;
19 pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool
20 where F: FnMut(&Pat) -> bool
22 // FIXME(#19596) this is a workaround, but there should be a better way
23 fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool
24 where G: FnMut(&Pat) -> bool
31 PatIdent(_, _, Some(ref p)) => walk_pat_(&**p, it),
32 PatStruct(_, ref fields, _) => {
33 fields.iter().all(|field| walk_pat_(&*field.node.pat, it))
35 PatEnum(_, Some(ref s)) | PatTup(ref s) => {
36 s.iter().all(|p| walk_pat_(&**p, it))
38 PatBox(ref s) | PatRegion(ref s, _) => {
41 PatVec(ref before, ref slice, ref after) => {
42 before.iter().all(|p| walk_pat_(&**p, it)) &&
43 slice.iter().all(|p| walk_pat_(&**p, it)) &&
44 after.iter().all(|p| walk_pat_(&**p, it))
57 walk_pat_(pat, &mut it)
60 pub fn binop_to_string(op: BinOp_) -> &'static str {
83 pub fn stmt_id(s: &Stmt) -> NodeId {
85 StmtDecl(_, id) => id,
86 StmtExpr(_, id) => id,
87 StmtSemi(_, id) => id,
91 pub fn lazy_binop(b: BinOp_) -> bool {
99 pub fn is_shift_binop(b: BinOp_) -> bool {
107 pub fn is_comparison_binop(b: BinOp_) -> bool {
109 BiEq | BiLt | BiLe | BiNe | BiGt | BiGe => true,
125 /// Returns `true` if the binary operator takes its arguments by value
126 pub fn is_by_value_binop(b: BinOp_) -> bool {
127 !is_comparison_binop(b)
130 /// Returns `true` if the unary operator takes its argument by value
131 pub fn is_by_value_unop(u: UnOp) -> bool {
133 UnNeg | UnNot => true,
138 pub fn unop_to_string(op: UnOp) -> &'static str {
146 pub struct IdVisitor<'a, O: 'a> {
147 operation: &'a mut O,
149 // In general, the id visitor visits the contents of an item, but
150 // not including nested trait/impl items, nor other nested items.
151 // The base visitor itself always skips nested items, but not
152 // trait/impl items. This means in particular that if you start by
153 // visiting a trait or an impl, you should not visit the
154 // trait/impl items respectively. This is handled by setting
155 // `skip_members` to true when `visit_item` is on the stack. This
156 // way, if the user begins by calling `visit_trait_item`, we will
157 // visit the trait item, but if they begin with `visit_item`, we
158 // won't visit the (nested) trait items.
162 impl<'a, O: ast_util::IdVisitingOperation> IdVisitor<'a, O> {
163 pub fn new(operation: &'a mut O) -> IdVisitor<'a, O> {
164 IdVisitor { operation: operation, skip_members: false }
167 fn visit_generics_helper(&mut self, generics: &Generics) {
168 for type_parameter in generics.ty_params.iter() {
169 self.operation.visit_id(type_parameter.id)
171 for lifetime in &generics.lifetimes {
172 self.operation.visit_id(lifetime.lifetime.id)
177 impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
178 fn visit_mod(&mut self, module: &Mod, _: Span, node_id: NodeId) {
179 self.operation.visit_id(node_id);
180 intravisit::walk_mod(self, module)
183 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
184 self.operation.visit_id(foreign_item.id);
185 intravisit::walk_foreign_item(self, foreign_item)
188 fn visit_item(&mut self, item: &Item) {
189 assert!(!self.skip_members);
190 self.skip_members = true;
192 self.operation.visit_id(item.id);
194 ItemUse(ref view_path) => {
195 match view_path.node {
196 ViewPathSimple(_, _) |
197 ViewPathGlob(_) => {}
198 ViewPathList(_, ref paths) => {
200 self.operation.visit_id(path.node.id())
207 intravisit::walk_item(self, item);
209 self.skip_members = false;
212 fn visit_local(&mut self, local: &Local) {
213 self.operation.visit_id(local.id);
214 intravisit::walk_local(self, local)
217 fn visit_block(&mut self, block: &Block) {
218 self.operation.visit_id(block.id);
219 intravisit::walk_block(self, block)
222 fn visit_stmt(&mut self, statement: &Stmt) {
223 self.operation.visit_id(stmt_id(statement));
224 intravisit::walk_stmt(self, statement)
227 fn visit_pat(&mut self, pattern: &Pat) {
228 self.operation.visit_id(pattern.id);
229 intravisit::walk_pat(self, pattern)
232 fn visit_expr(&mut self, expression: &Expr) {
233 self.operation.visit_id(expression.id);
234 intravisit::walk_expr(self, expression)
237 fn visit_ty(&mut self, typ: &Ty) {
238 self.operation.visit_id(typ.id);
239 intravisit::walk_ty(self, typ)
242 fn visit_generics(&mut self, generics: &Generics) {
243 self.visit_generics_helper(generics);
244 intravisit::walk_generics(self, generics)
247 fn visit_fn(&mut self,
248 function_kind: FnKind<'v>,
249 function_declaration: &'v FnDecl,
253 self.operation.visit_id(node_id);
255 match function_kind {
256 FnKind::ItemFn(_, generics, _, _, _, _) => {
257 self.visit_generics_helper(generics)
259 FnKind::Method(_, sig, _) => {
260 self.visit_generics_helper(&sig.generics)
262 FnKind::Closure => {}
265 for argument in &function_declaration.inputs {
266 self.operation.visit_id(argument.id)
269 intravisit::walk_fn(self, function_kind, function_declaration, block, span);
272 fn visit_struct_field(&mut self, struct_field: &StructField) {
273 self.operation.visit_id(struct_field.node.id);
274 intravisit::walk_struct_field(self, struct_field)
277 fn visit_variant_data(&mut self,
278 struct_def: &VariantData,
283 self.operation.visit_id(struct_def.id());
284 intravisit::walk_struct_def(self, struct_def);
287 fn visit_trait_item(&mut self, ti: &hir::TraitItem) {
288 if !self.skip_members {
289 self.operation.visit_id(ti.id);
290 intravisit::walk_trait_item(self, ti);
294 fn visit_impl_item(&mut self, ii: &hir::ImplItem) {
295 if !self.skip_members {
296 self.operation.visit_id(ii.id);
297 intravisit::walk_impl_item(self, ii);
301 fn visit_lifetime(&mut self, lifetime: &Lifetime) {
302 self.operation.visit_id(lifetime.id);
305 fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
306 self.visit_lifetime(&def.lifetime);
309 fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
310 self.operation.visit_id(trait_ref.ref_id);
311 intravisit::walk_trait_ref(self, trait_ref);
315 /// Computes the id range for a single fn body, ignoring nested items.
316 pub fn compute_id_range_for_fn_body(fk: FnKind,
321 -> ast_util::IdRange {
322 let mut visitor = ast_util::IdRangeComputingVisitor { result: ast_util::IdRange::max() };
323 let mut id_visitor = IdVisitor::new(&mut visitor);
324 id_visitor.visit_fn(fk, decl, body, sp, id);
325 id_visitor.operation.result
328 pub fn is_path(e: P<Expr>) -> bool {
330 ExprPath(..) => true,
335 pub fn empty_generics() -> Generics {
337 lifetimes: HirVec::new(),
338 ty_params: HirVec::new(),
339 where_clause: WhereClause {
341 predicates: HirVec::new(),
346 // convert a span and an identifier to the corresponding
348 pub fn ident_to_path(s: Span, ident: Ident) -> Path {
352 segments: hir_vec![hir::PathSegment {
354 parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
355 lifetimes: HirVec::new(),
356 types: HirVec::new(),
357 bindings: HirVec::new(),