@@ -37,8 +37,8 @@ use std::path::Path;
3737
3838use crate :: utils:: internal_lints:: is_lint_ref_type;
3939use crate :: utils:: {
40- get_enclosing_body, get_parent_expr_for_hir, last_path_segment, match_function_call, match_qpath, match_type ,
41- path_to_local_id, paths, span_lint, walk_ptrs_ty_depth, get_parent_expr
40+ get_enclosing_body, get_parent_expr , get_parent_expr_for_hir, last_path_segment, match_function_call, match_qpath,
41+ match_type , path_to_local_id, paths, span_lint, walk_ptrs_ty_depth,
4242} ;
4343
4444/// This is the output file of the lint collector.
@@ -202,39 +202,19 @@ impl<'tcx> LateLintPass<'tcx> for MetadataCollector {
202202 /// ```
203203 fn check_item ( & mut self , cx : & LateContext < ' tcx > , item : & ' tcx Item < ' _ > ) {
204204 if_chain ! {
205+ // item validation
205206 if let ItemKind :: Static ( ref ty, Mutability :: Not , body_id) = item. kind;
206207 if is_lint_ref_type( cx, ty) ;
207208 let expr = & cx. tcx. hir( ) . body( body_id) . value;
208209 if let ExprKind :: AddrOf ( _, _, ref inner_exp) = expr. kind;
209210 if let ExprKind :: Struct ( _, _, _) = inner_exp. kind;
211+ // blacklist check
212+ let lint_name = sym_to_string( item. ident. name) . to_ascii_lowercase( ) ;
213+ if !BLACK_LISTED_LINTS . contains( & lint_name. as_str( ) ) ;
214+ // metadata extraction
215+ if let Some ( group) = get_lint_group_or_lint( cx, & lint_name, item) ;
216+ if let Some ( docs) = extract_attr_docs_or_lint( cx, item) ;
210217 then {
211- let lint_name = sym_to_string( item. ident. name) . to_ascii_lowercase( ) ;
212- if BLACK_LISTED_LINTS . contains( & lint_name. as_str( ) ) {
213- return ;
214- }
215-
216- let group: String ;
217- let result = cx. lint_store. check_lint_name( lint_name. as_str( ) , Some ( sym:: clippy) ) ;
218- if let CheckLintNameResult :: Tool ( Ok ( lint_lst) ) = result {
219- if let Some ( group_some) = get_lint_group( cx, lint_lst[ 0 ] ) {
220- group = group_some;
221- } else {
222- lint_collection_error_item( cx, item, "Unable to determine lint group" ) ;
223- return ;
224- }
225- } else {
226- lint_collection_error_item( cx, item, "Unable to find lint in lint_store" ) ;
227- return ;
228- }
229-
230- let docs: String ;
231- if let Some ( docs_some) = extract_attr_docs( item) {
232- docs = docs_some;
233- } else {
234- lint_collection_error_item( cx, item, "could not collect the lint documentation" ) ;
235- return ;
236- } ;
237-
238218 self . lints. push( LintMetadata :: new(
239219 lint_name,
240220 SerializableSpan :: from_item( cx, item) ,
@@ -301,7 +281,7 @@ impl<'tcx> LateLintPass<'tcx> for MetadataCollector {
301281 let span = SerializableSpan :: from_span( cx, local. span) ;
302282 let local_str = crate :: utils:: snippet( cx, local. span, "_" ) ;
303283 log_to_file( & format!( "{} -- {}\n " , local_str, span) ) ;
304-
284+
305285 let value_hir_id = local. pat. hir_id;
306286 let mut tracker = ValueTracker :: new( cx, value_hir_id) ;
307287 if let Some ( init_expr) = local. init {
@@ -342,10 +322,21 @@ fn get_local_type<'a>(cx: &'a LateContext<'_>, local: &'a hir::Local<'_>) -> Opt
342322 None
343323}
344324
325+ // ==================================================================
326+ // Lint definition extraction
327+ // ==================================================================
328+
345329fn sym_to_string ( sym : Symbol ) -> String {
346330 sym. as_str ( ) . to_string ( )
347331}
348332
333+ fn extract_attr_docs_or_lint ( cx : & LateContext < ' _ > , item : & Item < ' _ > ) -> Option < String > {
334+ extract_attr_docs ( item) . or_else ( || {
335+ lint_collection_error_item ( cx, item, "could not collect the lint documentation" ) ;
336+ None
337+ } )
338+ }
339+
349340/// This function collects all documentation that has been added to an item using
350341/// `#[doc = r""]` attributes. Several attributes are aggravated using line breaks
351342///
@@ -367,6 +358,19 @@ fn extract_attr_docs(item: &Item<'_>) -> Option<String> {
367358 } )
368359}
369360
361+ fn get_lint_group_or_lint ( cx : & LateContext < ' _ > , lint_name : & str , item : & ' tcx Item < ' _ > ) -> Option < String > {
362+ let result = cx. lint_store . check_lint_name ( lint_name, Some ( sym:: clippy) ) ;
363+ if let CheckLintNameResult :: Tool ( Ok ( lint_lst) ) = result {
364+ get_lint_group ( cx, lint_lst[ 0 ] ) . or_else ( || {
365+ lint_collection_error_item ( cx, item, "Unable to determine lint group" ) ;
366+ None
367+ } )
368+ } else {
369+ lint_collection_error_item ( cx, item, "Unable to find lint in lint_store" ) ;
370+ None
371+ }
372+ }
373+
370374fn get_lint_group ( cx : & LateContext < ' _ > , lint_id : LintId ) -> Option < String > {
371375 for ( group_name, lints, _) in & cx. lint_store . get_lint_groups ( ) {
372376 if lints. iter ( ) . any ( |x| * x == lint_id) {
@@ -526,19 +530,8 @@ impl<'a, 'hir> ValueTracker<'a, 'hir> {
526530 }
527531 }
528532
529- fn process_borrow_expr ( & mut self , access_hir_id : hir:: HirId ) {
530- let borrower: & rustc_hir:: Expr < ' _ > ;
531- if let Some ( addr_of_expr) = get_parent_expr_for_hir ( self . cx , access_hir_id) {
532- if let Some ( borrower_expr) = get_parent_expr ( self . cx , addr_of_expr) {
533- borrower = borrower_expr
534- } else {
535- return ;
536- }
537- } else {
538- return ;
539- }
540-
541- match & borrower. kind {
533+ fn process_borrow_expr ( & mut self , borrower_expr : & ' hir rustc_hir:: Expr < ' hir > ) {
534+ match & borrower_expr. kind {
542535 hir:: ExprKind :: Call ( func_expr, ..) => {
543536 // We only deal with resolved paths as this is the usual case. Other expression kinds like closures
544537 // etc. are hard to track but might be a worthy improvement in the future
@@ -555,36 +548,45 @@ impl<'a, 'hir> ValueTracker<'a, 'hir> {
555548 hir:: ExprKind :: MethodCall ( ..) => {
556549 let msg = format ! (
557550 "Unsupported borrow in MethodCall at: {}" ,
558- SerializableSpan :: from_span( self . cx, borrower . span)
551+ SerializableSpan :: from_span( self . cx, borrower_expr . span)
559552 ) ;
560553 self . value_mutations . push ( ApplicabilityModifier :: Unknown ( msg) ) ;
561554 } ,
562555 _ => {
563556 let msg = format ! (
564557 "Unexpected borrow at: {}" ,
565- SerializableSpan :: from_span( self . cx, borrower . span)
558+ SerializableSpan :: from_span( self . cx, borrower_expr . span)
566559 ) ;
567560 self . value_mutations . push ( ApplicabilityModifier :: Unknown ( msg) ) ;
568561 } ,
569562 }
570563 }
564+
565+ fn process_consume_expr ( & mut self , consume_expr : & ' hir rustc_hir:: Expr < ' hir > ) {
566+ // We are only interested in lint emissions. Other types like assignments might be
567+ // interesting for further use or improvement but are to complex for now.
568+ if let hir:: ExprKind :: Call ( func_expr, ..) = & consume_expr. kind { }
569+ }
571570}
572571
573572impl < ' a , ' hir > Delegate < ' hir > for ValueTracker < ' a , ' hir > {
574573 fn consume ( & mut self , _place_with_id : & PlaceWithHirId < ' hir > , expr_id : hir:: HirId , _: ConsumeMode ) {
575574 if self . is_value_expr ( expr_id) {
576575 // TODO xFrednet 2021-02-17: Check if lint emission and extract lint ID
577- if let Some ( hir:: Node :: Expr ( expr) ) = self . cx . tcx . hir ( ) . find ( expr_id) {
578- let span = SerializableSpan :: from_span ( self . cx , expr. span ) ;
579- log_to_file ( & format ! ( "- consume {}\n " , span) ) ;
576+ if let Some ( expr) = get_parent_expr_for_hir ( self . cx , expr_id) {
577+ log_to_file ( & format ! ( "- consume {:?}\n " , expr) ) ;
580578 }
581579 }
582580 }
583581
584582 fn borrow ( & mut self , _place_with_id : & PlaceWithHirId < ' hir > , expr_id : hir:: HirId , bk : BorrowKind ) {
585- if self . is_value_expr ( expr_id) {
586- if let BorrowKind :: MutBorrow = bk {
587- self . process_borrow_expr ( expr_id) ;
583+ if_chain ! {
584+ if self . is_value_expr( expr_id) ;
585+ if let BorrowKind :: MutBorrow = bk;
586+ if let Some ( addr_of_expr) = get_parent_expr_for_hir( self . cx, expr_id) ;
587+ if let Some ( borrower_expr) = get_parent_expr( self . cx, addr_of_expr) ;
588+ then {
589+ self . process_borrow_expr( borrower_expr) ;
588590 }
589591 }
590592 }
0 commit comments