@@ -69,11 +69,13 @@ use rustc_hir::def::{DefKind, Res};
69
69
use rustc_hir:: def_id:: DefId ;
70
70
use rustc_hir:: hir_id:: { HirIdMap , HirIdSet } ;
71
71
use rustc_hir:: intravisit:: { self , walk_expr, ErasedMap , FnKind , NestedVisitorMap , Visitor } ;
72
+ use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
72
73
use rustc_hir:: LangItem :: { OptionNone , ResultErr , ResultOk } ;
73
74
use rustc_hir:: {
74
- def, Arm , BindingAnnotation , Block , Body , Constness , Destination , Expr , ExprKind , FnDecl , GenericArgs , HirId , Impl ,
75
- ImplItem , ImplItemKind , IsAsync , Item , ItemKind , LangItem , Local , MatchSource , Mutability , Node , Param , Pat ,
76
- PatKind , Path , PathSegment , PrimTy , QPath , Stmt , StmtKind , TraitItem , TraitItemKind , TraitRef , TyKind , UnOp ,
75
+ def, Arm , BindingAnnotation , Block , Body , Constness , Destination , Expr , ExprKind , FnDecl , ForeignItem , GenericArgs ,
76
+ HirId , Impl , ImplItem , ImplItemKind , IsAsync , Item , ItemKind , LangItem , Local , MatchSource , Mutability , Node ,
77
+ Param , Pat , PatKind , Path , PathSegment , PrimTy , QPath , Stmt , StmtKind , TraitItem , TraitItemKind , TraitRef , TyKind ,
78
+ UnOp ,
77
79
} ;
78
80
use rustc_lint:: { LateContext , Level , Lint , LintContext } ;
79
81
use rustc_middle:: hir:: exports:: Export ;
@@ -2064,16 +2066,72 @@ pub fn is_hir_ty_cfg_dependant(cx: &LateContext<'_>, ty: &hir::Ty<'_>) -> bool {
2064
2066
false
2065
2067
}
2066
2068
2067
- /// Checks whether item either has `test` attribute applied, or
2068
- /// is a module with `test` in its name.
2069
- pub fn is_test_module_or_function ( tcx : TyCtxt < ' _ > , item : & Item < ' _ > ) -> bool {
2070
- if let Some ( def_id) = tcx. hir ( ) . opt_local_def_id ( item. hir_id ( ) ) {
2071
- if tcx. has_attr ( def_id. to_def_id ( ) , sym:: test) {
2072
- return true ;
2069
+ struct VisitConstTestStruct < ' tcx > {
2070
+ tcx : TyCtxt < ' tcx > ,
2071
+ names : Vec < Symbol > ,
2072
+ found : bool ,
2073
+ }
2074
+ impl < ' hir > ItemLikeVisitor < ' hir > for VisitConstTestStruct < ' hir > {
2075
+ fn visit_item ( & mut self , item : & Item < ' _ > ) {
2076
+ if let ItemKind :: Const ( ty, _body) = item. kind {
2077
+ if let TyKind :: Path ( QPath :: Resolved ( _, path) ) = ty. kind {
2078
+ // We could also check for the type name `test::TestDescAndFn`
2079
+ // and the `#[rustc_test_marker]` attribute?
2080
+ if let Res :: Def ( DefKind :: Struct , _) = path. res {
2081
+ let has_test_marker = self
2082
+ . tcx
2083
+ . hir ( )
2084
+ . attrs ( item. hir_id ( ) )
2085
+ . iter ( )
2086
+ . any ( |a| a. has_name ( sym:: rustc_test_marker) ) ;
2087
+ if has_test_marker && self . names . contains ( & item. ident . name ) {
2088
+ self . found = true ;
2089
+ }
2090
+ }
2091
+ }
2073
2092
}
2074
2093
}
2094
+ fn visit_trait_item ( & mut self , _: & TraitItem < ' _ > ) { }
2095
+ fn visit_impl_item ( & mut self , _: & ImplItem < ' _ > ) { }
2096
+ fn visit_foreign_item ( & mut self , _: & ForeignItem < ' _ > ) { }
2097
+ }
2075
2098
2076
- matches ! ( item. kind, ItemKind :: Mod ( ..) ) && item. ident . name . as_str ( ) . split ( '_' ) . any ( |a| a == "test" || a == "tests" )
2099
+ /// Checks if the function containing the given `HirId` is a `#[test]` function
2100
+ ///
2101
+ /// Note: If you use this function, please add a `#[test]` case in `tests/ui_test`.
2102
+ pub fn is_in_test_function ( tcx : TyCtxt < ' _ > , id : hir:: HirId ) -> bool {
2103
+ let names: Vec < _ > = tcx
2104
+ . hir ( )
2105
+ . parent_iter ( id)
2106
+ // Since you can nest functions we need to collect all until we leave
2107
+ // function scope
2108
+ . filter_map ( |( _id, node) | {
2109
+ if let Node :: Item ( item) = node {
2110
+ if let ItemKind :: Fn ( _, _, _) = item. kind {
2111
+ return Some ( item. ident . name ) ;
2112
+ }
2113
+ }
2114
+ None
2115
+ } )
2116
+ . collect ( ) ;
2117
+ let parent_mod = tcx. parent_module ( id) ;
2118
+ let mut vis = VisitConstTestStruct {
2119
+ tcx,
2120
+ names,
2121
+ found : false ,
2122
+ } ;
2123
+ tcx. hir ( ) . visit_item_likes_in_module ( parent_mod, & mut vis) ;
2124
+ vis. found
2125
+ }
2126
+
2127
+ /// Checks whether item either has `test` attribute appelied, or
2128
+ /// is a module with `test` in its name.
2129
+ ///
2130
+ /// Note: If you use this function, please add a `#[test]` case in `tests/ui_test`.
2131
+ pub fn is_test_module_or_function ( tcx : TyCtxt < ' _ > , item : & Item < ' _ > ) -> bool {
2132
+ is_in_test_function ( tcx, item. hir_id ( ) )
2133
+ || matches ! ( item. kind, ItemKind :: Mod ( ..) )
2134
+ && item. ident . name . as_str ( ) . split ( '_' ) . any ( |a| a == "test" || a == "tests" )
2077
2135
}
2078
2136
2079
2137
macro_rules! op_utils {
0 commit comments