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 visit::{self, Visitor, FnKind};
15 use syntax::ast::{Ident, NodeId, DUMMY_NODE_ID};
16 use syntax::codemap::Span;
18 use syntax::owned_slice::OwnedSlice;
20 pub fn walk_pat<F>(pat: &Pat, mut it: F) -> bool where F: FnMut(&Pat) -> bool {
21 // FIXME(#19596) this is a workaround, but there should be a better way
22 fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool where G: FnMut(&Pat) -> bool {
28 PatIdent(_, _, Some(ref p)) => walk_pat_(&**p, it),
29 PatStruct(_, ref fields, _) => {
30 fields.iter().all(|field| walk_pat_(&*field.node.pat, it))
32 PatEnum(_, Some(ref s)) | PatTup(ref s) => {
33 s.iter().all(|p| walk_pat_(&**p, it))
35 PatBox(ref s) | PatRegion(ref s, _) => {
38 PatVec(ref before, ref slice, ref after) => {
39 before.iter().all(|p| walk_pat_(&**p, it)) &&
40 slice.iter().all(|p| walk_pat_(&**p, it)) &&
41 after.iter().all(|p| walk_pat_(&**p, it))
43 PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
44 PatEnum(_, _) | PatQPath(_, _) => {
50 walk_pat_(pat, &mut it)
53 pub fn binop_to_string(op: BinOp_) -> &'static str {
76 /// Returns true if the given struct def is tuple-like; i.e. that its fields
78 pub fn struct_def_is_tuple_like(struct_def: &hir::StructDef) -> bool {
79 struct_def.ctor_id.is_some()
82 pub fn stmt_id(s: &Stmt) -> NodeId {
84 StmtDecl(_, id) => id,
85 StmtExpr(_, id) => id,
86 StmtSemi(_, id) => id,
90 pub fn lazy_binop(b: BinOp_) -> bool {
98 pub fn is_shift_binop(b: BinOp_) -> bool {
106 pub fn is_comparison_binop(b: BinOp_) -> bool {
108 BiEq | BiLt | BiLe | BiNe | BiGt | BiGe =>
110 BiAnd | BiOr | BiAdd | BiSub | BiMul | BiDiv | BiRem |
111 BiBitXor | BiBitAnd | BiBitOr | BiShl | BiShr =>
116 /// Returns `true` if the binary operator takes its arguments by value
117 pub fn is_by_value_binop(b: BinOp_) -> bool {
118 !is_comparison_binop(b)
121 /// Returns `true` if the unary operator takes its argument by value
122 pub fn is_by_value_unop(u: UnOp) -> bool {
124 UnNeg | UnNot => true,
129 pub fn unop_to_string(op: UnOp) -> &'static str {
138 pub struct IdVisitor<'a, O:'a> {
139 pub operation: &'a mut O,
140 pub pass_through_items: bool,
141 pub visited_outermost: bool,
144 impl<'a, O: ast_util::IdVisitingOperation> IdVisitor<'a, O> {
145 fn visit_generics_helper(&mut self, generics: &Generics) {
146 for type_parameter in generics.ty_params.iter() {
147 self.operation.visit_id(type_parameter.id)
149 for lifetime in &generics.lifetimes {
150 self.operation.visit_id(lifetime.lifetime.id)
155 impl<'a, 'v, O: ast_util::IdVisitingOperation> Visitor<'v> for IdVisitor<'a, O> {
156 fn visit_mod(&mut self,
160 self.operation.visit_id(node_id);
161 visit::walk_mod(self, module)
164 fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
165 self.operation.visit_id(foreign_item.id);
166 visit::walk_foreign_item(self, foreign_item)
169 fn visit_item(&mut self, item: &Item) {
170 if !self.pass_through_items {
171 if self.visited_outermost {
174 self.visited_outermost = true
178 self.operation.visit_id(item.id);
180 ItemUse(ref view_path) => {
181 match view_path.node {
182 ViewPathSimple(_, _) |
183 ViewPathGlob(_) => {}
184 ViewPathList(_, ref paths) => {
186 self.operation.visit_id(path.node.id())
191 ItemEnum(ref enum_definition, _) => {
192 for variant in &enum_definition.variants {
193 self.operation.visit_id(variant.node.id)
199 visit::walk_item(self, item);
201 self.visited_outermost = false
204 fn visit_local(&mut self, local: &Local) {
205 self.operation.visit_id(local.id);
206 visit::walk_local(self, local)
209 fn visit_block(&mut self, block: &Block) {
210 self.operation.visit_id(block.id);
211 visit::walk_block(self, block)
214 fn visit_stmt(&mut self, statement: &Stmt) {
215 self.operation.visit_id(stmt_id(statement));
216 visit::walk_stmt(self, statement)
219 fn visit_pat(&mut self, pattern: &Pat) {
220 self.operation.visit_id(pattern.id);
221 visit::walk_pat(self, pattern)
224 fn visit_expr(&mut self, expression: &Expr) {
225 self.operation.visit_id(expression.id);
226 visit::walk_expr(self, expression)
229 fn visit_ty(&mut self, typ: &Ty) {
230 self.operation.visit_id(typ.id);
231 visit::walk_ty(self, typ)
234 fn visit_generics(&mut self, generics: &Generics) {
235 self.visit_generics_helper(generics);
236 visit::walk_generics(self, generics)
239 fn visit_fn(&mut self,
240 function_kind: FnKind<'v>,
241 function_declaration: &'v FnDecl,
245 if !self.pass_through_items {
246 match function_kind {
247 FnKind::Method(..) if self.visited_outermost => return,
248 FnKind::Method(..) => self.visited_outermost = true,
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)
271 function_declaration,
275 if !self.pass_through_items {
276 if let FnKind::Method(..) = function_kind {
277 self.visited_outermost = false;
282 fn visit_struct_field(&mut self, struct_field: &StructField) {
283 self.operation.visit_id(struct_field.node.id);
284 visit::walk_struct_field(self, struct_field)
287 fn visit_struct_def(&mut self,
288 struct_def: &StructDef,
292 self.operation.visit_id(id);
293 struct_def.ctor_id.map(|ctor_id| self.operation.visit_id(ctor_id));
294 visit::walk_struct_def(self, struct_def);
297 fn visit_trait_item(&mut self, ti: &hir::TraitItem) {
298 self.operation.visit_id(ti.id);
299 visit::walk_trait_item(self, ti);
302 fn visit_impl_item(&mut self, ii: &hir::ImplItem) {
303 self.operation.visit_id(ii.id);
304 visit::walk_impl_item(self, ii);
307 fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
308 self.operation.visit_id(lifetime.id);
311 fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
312 self.visit_lifetime_ref(&def.lifetime);
315 fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
316 self.operation.visit_id(trait_ref.ref_id);
317 visit::walk_trait_ref(self, trait_ref);
321 /// Computes the id range for a single fn body, ignoring nested items.
322 pub fn compute_id_range_for_fn_body(fk: FnKind,
329 let mut visitor = ast_util::IdRangeComputingVisitor {
330 result: ast_util::IdRange::max()
332 let mut id_visitor = IdVisitor {
333 operation: &mut visitor,
334 pass_through_items: false,
335 visited_outermost: false,
337 id_visitor.visit_fn(fk, decl, body, sp, id);
338 id_visitor.operation.result
341 /// Returns true if this literal is a string and false otherwise.
342 pub fn lit_is_str(lit: &Lit) -> bool {
349 pub fn is_path(e: P<Expr>) -> bool {
350 match e.node { ExprPath(..) => true, _ => false }
353 /// Get a string representation of a signed int type, with its value.
354 /// We want to avoid "45int" and "-3int" in favor of "45" and "-3"
355 pub fn int_ty_to_string(t: IntTy, val: Option<i64>) -> String {
365 // cast to a u64 so we can correctly print INT64_MIN. All integral types
366 // are parsed as u64, so we wouldn't want to print an extra negative
368 Some(n) => format!("{}{}", n as u64, s),
369 None => s.to_string()
374 /// Get a string representation of an unsigned int type, with its value.
375 /// We want to avoid "42u" in favor of "42us". "42uint" is right out.
376 pub fn uint_ty_to_string(t: UintTy, val: Option<u64>) -> String {
386 Some(n) => format!("{}{}", n, s),
387 None => s.to_string()
391 pub fn float_ty_to_string(t: FloatTy) -> String {
393 TyF32 => "f32".to_string(),
394 TyF64 => "f64".to_string(),
399 pub fn empty_generics() -> Generics {
401 lifetimes: Vec::new(),
402 ty_params: OwnedSlice::empty(),
403 where_clause: WhereClause {
405 predicates: Vec::new(),
410 // convert a span and an identifier to the corresponding
412 pub fn ident_to_path(s: Span, identifier: Ident) -> Path {
418 identifier: identifier,
419 parameters: hir::AngleBracketedParameters(hir::AngleBracketedParameterData {
420 lifetimes: Vec::new(),
421 types: OwnedSlice::empty(),
422 bindings: OwnedSlice::empty(),