|
1 |
| -use rustc::hir::intravisit::FnKind; |
2 | 1 | use rustc::hir::def_id::DefId;
|
3 | 2 | use rustc::hir;
|
4 | 3 | use rustc::lint::*;
|
5 | 4 | use rustc::ty::{self, Ty};
|
6 |
| -use syntax::ast; |
7 | 5 | use syntax::codemap::Span;
|
8 | 6 | use utils::paths;
|
9 | 7 | use utils::{get_trait_def_id, implements_trait, in_external_macro, return_ty, same_tys, span_lint_and_then};
|
@@ -90,66 +88,67 @@ impl LintPass for NewWithoutDefault {
|
90 | 88 | }
|
91 | 89 |
|
92 | 90 | impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NewWithoutDefault {
|
93 |
| - fn check_fn( |
94 |
| - &mut self, |
95 |
| - cx: &LateContext<'a, 'tcx>, |
96 |
| - kind: FnKind<'tcx>, |
97 |
| - decl: &'tcx hir::FnDecl, |
98 |
| - _: &'tcx hir::Body, |
99 |
| - span: Span, |
100 |
| - id: ast::NodeId, |
101 |
| - ) { |
102 |
| - if in_external_macro(cx, span) { |
103 |
| - return; |
104 |
| - } |
105 |
| - |
106 |
| - if let FnKind::Method(name, sig, _, _) = kind { |
107 |
| - if sig.constness == hir::Constness::Const { |
108 |
| - // can't be implemented by default |
109 |
| - return; |
110 |
| - } |
111 |
| - if !cx.generics |
112 |
| - .expect("method must have generics") |
113 |
| - .ty_params |
114 |
| - .is_empty() |
115 |
| - { |
116 |
| - // when the result of `new()` depends on a type parameter we should not require |
117 |
| - // an |
118 |
| - // impl of `Default` |
119 |
| - return; |
120 |
| - } |
121 |
| - if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { |
122 |
| - let self_ty = cx.tcx |
123 |
| - .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); |
124 |
| - if_chain! { |
125 |
| - if same_tys(cx, self_ty, return_ty(cx, id)); |
126 |
| - if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); |
127 |
| - if !implements_trait(cx, self_ty, default_trait_id, &[]); |
128 |
| - then { |
129 |
| - if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { |
130 |
| - span_lint_and_then( |
131 |
| - cx, |
132 |
| - NEW_WITHOUT_DEFAULT_DERIVE, |
133 |
| - span, |
134 |
| - &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), |
135 |
| - |db| { |
136 |
| - db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); |
137 |
| - }); |
138 |
| - } else { |
139 |
| - span_lint_and_then( |
140 |
| - cx, |
141 |
| - NEW_WITHOUT_DEFAULT, |
142 |
| - span, |
143 |
| - &format!("you should consider adding a `Default` implementation for `{}`", self_ty), |
144 |
| - |db| { |
145 |
| - db.suggest_prepend_item( |
146 |
| - cx, |
147 |
| - span, |
148 |
| - "try this", |
149 |
| - &create_new_without_default_suggest_msg(self_ty), |
150 |
| - ); |
151 |
| - }, |
152 |
| - ); |
| 91 | + fn check_item(&mut self, cx: &LateContext<'a, 'tcx>, item: &'tcx hir::Item) { |
| 92 | + if let hir::ItemImpl(_, _, _, _, None, _, ref items) = item.node { |
| 93 | + for assoc_item in items { |
| 94 | + if let hir::AssociatedItemKind::Method { has_self: false } = assoc_item.kind { |
| 95 | + let impl_item = cx.tcx.hir.impl_item(assoc_item.id); |
| 96 | + if in_external_macro(cx, impl_item.span) { |
| 97 | + return; |
| 98 | + } |
| 99 | + if let hir::ImplItemKind::Method(ref sig, _) = impl_item.node { |
| 100 | + let name = impl_item.name; |
| 101 | + let span = impl_item.span; |
| 102 | + let id = impl_item.id; |
| 103 | + let decl = &sig.decl; |
| 104 | + if sig.constness == hir::Constness::Const { |
| 105 | + // can't be implemented by default |
| 106 | + return; |
| 107 | + } |
| 108 | + if !impl_item.generics |
| 109 | + .ty_params |
| 110 | + .is_empty() |
| 111 | + { |
| 112 | + // when the result of `new()` depends on a type parameter we should not require |
| 113 | + // an |
| 114 | + // impl of `Default` |
| 115 | + return; |
| 116 | + } |
| 117 | + if decl.inputs.is_empty() && name == "new" && cx.access_levels.is_reachable(id) { |
| 118 | + let self_ty = cx.tcx |
| 119 | + .type_of(cx.tcx.hir.local_def_id(cx.tcx.hir.get_parent(id))); |
| 120 | + if_chain! { |
| 121 | + if same_tys(cx, self_ty, return_ty(cx, id)); |
| 122 | + if let Some(default_trait_id) = get_trait_def_id(cx, &paths::DEFAULT_TRAIT); |
| 123 | + if !implements_trait(cx, self_ty, default_trait_id, &[]); |
| 124 | + then { |
| 125 | + if let Some(sp) = can_derive_default(self_ty, cx, default_trait_id) { |
| 126 | + span_lint_and_then( |
| 127 | + cx, |
| 128 | + NEW_WITHOUT_DEFAULT_DERIVE, |
| 129 | + span, |
| 130 | + &format!("you should consider deriving a `Default` implementation for `{}`", self_ty), |
| 131 | + |db| { |
| 132 | + db.suggest_item_with_attr(cx, sp, "try this", "#[derive(Default)]"); |
| 133 | + }); |
| 134 | + } else { |
| 135 | + span_lint_and_then( |
| 136 | + cx, |
| 137 | + NEW_WITHOUT_DEFAULT, |
| 138 | + span, |
| 139 | + &format!("you should consider adding a `Default` implementation for `{}`", self_ty), |
| 140 | + |db| { |
| 141 | + db.suggest_prepend_item( |
| 142 | + cx, |
| 143 | + span, |
| 144 | + "try this", |
| 145 | + &create_new_without_default_suggest_msg(self_ty), |
| 146 | + ); |
| 147 | + }, |
| 148 | + ); |
| 149 | + } |
| 150 | + } |
| 151 | + } |
153 | 152 | }
|
154 | 153 | }
|
155 | 154 | }
|
|
0 commit comments