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 PatKind
::Ident(_
, _
, Some(ref p
)) => walk_pat_(&p
, it
),
32 PatKind
::Struct(_
, ref fields
, _
) => {
33 fields
.iter().all(|field
| walk_pat_(&field
.node
.pat
, it
))
35 PatKind
::TupleStruct(_
, Some(ref s
)) | PatKind
::Tup(ref s
) => {
36 s
.iter().all(|p
| walk_pat_(&p
, it
))
38 PatKind
::Box(ref s
) | PatKind
::Ref(ref s
, _
) => {
41 PatKind
::Vec(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
))
48 PatKind
::Range(_
, _
) |
49 PatKind
::Ident(_
, _
, _
) |
50 PatKind
::TupleStruct(..) |
52 PatKind
::QPath(_
, _
) => {
58 walk_pat_(pat
, &mut it
)
61 pub fn binop_to_string(op
: BinOp_
) -> &'
static str {
84 pub fn stmt_id(s
: &Stmt
) -> NodeId
{
86 StmtDecl(_
, id
) => id
,
87 StmtExpr(_
, id
) => id
,
88 StmtSemi(_
, id
) => id
,
92 pub fn lazy_binop(b
: BinOp_
) -> bool
{
100 pub fn is_shift_binop(b
: BinOp_
) -> bool
{
108 pub fn is_comparison_binop(b
: BinOp_
) -> bool
{
110 BiEq
| BiLt
| BiLe
| BiNe
| BiGt
| BiGe
=> true,
126 /// Returns `true` if the binary operator takes its arguments by value
127 pub fn is_by_value_binop(b
: BinOp_
) -> bool
{
128 !is_comparison_binop(b
)
131 /// Returns `true` if the unary operator takes its argument by value
132 pub fn is_by_value_unop(u
: UnOp
) -> bool
{
134 UnNeg
| UnNot
=> true,
139 pub fn unop_to_string(op
: UnOp
) -> &'
static str {
147 pub struct IdVisitor
<'a
, O
: 'a
> {
148 operation
: &'a
mut O
,
150 // In general, the id visitor visits the contents of an item, but
151 // not including nested trait/impl items, nor other nested items.
152 // The base visitor itself always skips nested items, but not
153 // trait/impl items. This means in particular that if you start by
154 // visiting a trait or an impl, you should not visit the
155 // trait/impl items respectively. This is handled by setting
156 // `skip_members` to true when `visit_item` is on the stack. This
157 // way, if the user begins by calling `visit_trait_item`, we will
158 // visit the trait item, but if they begin with `visit_item`, we
159 // won't visit the (nested) trait items.
163 impl<'a
, O
: ast_util
::IdVisitingOperation
> IdVisitor
<'a
, O
> {
164 pub fn new(operation
: &'a
mut O
) -> IdVisitor
<'a
, O
> {
165 IdVisitor { operation: operation, skip_members: false }
168 fn visit_generics_helper(&mut self, generics
: &Generics
) {
169 for type_parameter
in generics
.ty_params
.iter() {
170 self.operation
.visit_id(type_parameter
.id
)
172 for lifetime
in &generics
.lifetimes
{
173 self.operation
.visit_id(lifetime
.lifetime
.id
)
178 impl<'a
, 'v
, O
: ast_util
::IdVisitingOperation
> Visitor
<'v
> for IdVisitor
<'a
, O
> {
179 fn visit_mod(&mut self, module
: &Mod
, _
: Span
, node_id
: NodeId
) {
180 self.operation
.visit_id(node_id
);
181 intravisit
::walk_mod(self, module
)
184 fn visit_foreign_item(&mut self, foreign_item
: &ForeignItem
) {
185 self.operation
.visit_id(foreign_item
.id
);
186 intravisit
::walk_foreign_item(self, foreign_item
)
189 fn visit_item(&mut self, item
: &Item
) {
190 assert
!(!self.skip_members
);
191 self.skip_members
= true;
193 self.operation
.visit_id(item
.id
);
195 ItemUse(ref view_path
) => {
196 match view_path
.node
{
197 ViewPathSimple(_
, _
) |
198 ViewPathGlob(_
) => {}
199 ViewPathList(_
, ref paths
) => {
201 self.operation
.visit_id(path
.node
.id())
208 intravisit
::walk_item(self, item
);
210 self.skip_members
= false;
213 fn visit_local(&mut self, local
: &Local
) {
214 self.operation
.visit_id(local
.id
);
215 intravisit
::walk_local(self, local
)
218 fn visit_block(&mut self, block
: &Block
) {
219 self.operation
.visit_id(block
.id
);
220 intravisit
::walk_block(self, block
)
223 fn visit_stmt(&mut self, statement
: &Stmt
) {
224 self.operation
.visit_id(stmt_id(statement
));
225 intravisit
::walk_stmt(self, statement
)
228 fn visit_pat(&mut self, pattern
: &Pat
) {
229 self.operation
.visit_id(pattern
.id
);
230 intravisit
::walk_pat(self, pattern
)
233 fn visit_expr(&mut self, expression
: &Expr
) {
234 self.operation
.visit_id(expression
.id
);
235 intravisit
::walk_expr(self, expression
)
238 fn visit_ty(&mut self, typ
: &Ty
) {
239 self.operation
.visit_id(typ
.id
);
240 intravisit
::walk_ty(self, typ
)
243 fn visit_generics(&mut self, generics
: &Generics
) {
244 self.visit_generics_helper(generics
);
245 intravisit
::walk_generics(self, generics
)
248 fn visit_fn(&mut self,
249 function_kind
: FnKind
<'v
>,
250 function_declaration
: &'v FnDecl
,
254 self.operation
.visit_id(node_id
);
256 match function_kind
{
257 FnKind
::ItemFn(_
, generics
, _
, _
, _
, _
) => {
258 self.visit_generics_helper(generics
)
260 FnKind
::Method(_
, sig
, _
) => {
261 self.visit_generics_helper(&sig
.generics
)
263 FnKind
::Closure
=> {}
266 for argument
in &function_declaration
.inputs
{
267 self.operation
.visit_id(argument
.id
)
270 intravisit
::walk_fn(self, function_kind
, function_declaration
, block
, span
);
273 fn visit_struct_field(&mut self, struct_field
: &StructField
) {
274 self.operation
.visit_id(struct_field
.node
.id
);
275 intravisit
::walk_struct_field(self, struct_field
)
278 fn visit_variant_data(&mut self,
279 struct_def
: &VariantData
,
284 self.operation
.visit_id(struct_def
.id());
285 intravisit
::walk_struct_def(self, struct_def
);
288 fn visit_trait_item(&mut self, ti
: &hir
::TraitItem
) {
289 if !self.skip_members
{
290 self.operation
.visit_id(ti
.id
);
291 intravisit
::walk_trait_item(self, ti
);
295 fn visit_impl_item(&mut self, ii
: &hir
::ImplItem
) {
296 if !self.skip_members
{
297 self.operation
.visit_id(ii
.id
);
298 intravisit
::walk_impl_item(self, ii
);
302 fn visit_lifetime(&mut self, lifetime
: &Lifetime
) {
303 self.operation
.visit_id(lifetime
.id
);
306 fn visit_lifetime_def(&mut self, def
: &LifetimeDef
) {
307 self.visit_lifetime(&def
.lifetime
);
310 fn visit_trait_ref(&mut self, trait_ref
: &TraitRef
) {
311 self.operation
.visit_id(trait_ref
.ref_id
);
312 intravisit
::walk_trait_ref(self, trait_ref
);
316 /// Computes the id range for a single fn body, ignoring nested items.
317 pub fn compute_id_range_for_fn_body(fk
: FnKind
,
322 -> ast_util
::IdRange
{
323 let mut visitor
= ast_util
::IdRangeComputingVisitor { result: ast_util::IdRange::max() }
;
324 let mut id_visitor
= IdVisitor
::new(&mut visitor
);
325 id_visitor
.visit_fn(fk
, decl
, body
, sp
, id
);
326 id_visitor
.operation
.result
329 pub fn is_path(e
: P
<Expr
>) -> bool
{
331 ExprPath(..) => true,
336 pub fn empty_generics() -> Generics
{
338 lifetimes
: HirVec
::new(),
339 ty_params
: HirVec
::new(),
340 where_clause
: WhereClause
{
342 predicates
: HirVec
::new(),
347 // convert a span and an identifier to the corresponding
349 pub fn ident_to_path(s
: Span
, ident
: Ident
) -> Path
{
353 segments
: hir_vec
![hir
::PathSegment
{
355 parameters
: hir
::AngleBracketedParameters(hir
::AngleBracketedParameterData
{
356 lifetimes
: HirVec
::new(),
357 types
: HirVec
::new(),
358 bindings
: HirVec
::new(),