@@ -37,10 +37,28 @@ const BLACK_LISTED_LINTS: [&str; 3] = ["lint_author", "deep_code_inspection", "i
3737/// These groups will be ignored by the lint group matcher. This is useful for collections like
3838/// `clippy::all`
3939const IGNORED_LINT_GROUPS : [ & str ; 1 ] = [ "clippy::all" ] ;
40- /// Lints within this group will be excluded from the collection
41- const EXCLUDED_LINT_GROUPS : [ & str ; 1 ] = [ "clippy::internal" ] ;
40+ /// Lints within this group will be excluded from the collection. These groups
41+ /// have to be defined without the `clippy::` prefix.
42+ const EXCLUDED_LINT_GROUPS : [ & str ; 1 ] = [ "internal" ] ;
4243/// Collected deprecated lint will be assigned to this group in the JSON output
43- const DEPRECATED_LINT_GROUP_STR : & str = "DEPRECATED" ;
44+ const DEPRECATED_LINT_GROUP_STR : & str = "deprecated" ;
45+ /// This is the lint level for deprecated lints that will be displayed in the lint list
46+ const DEPRECATED_LINT_LEVEL : & str = "none" ;
47+ /// This array holds Clippy's lint groups with their corresponding default lint level. The
48+ /// lint level for deprecated lints is set in `DEPRECATED_LINT_LEVEL`.
49+ const DEFAULT_LINT_LEVELS : [ ( & str , & str ) ; 8 ] = [
50+ ( "correctness" , "deny" ) ,
51+ ( "restriction" , "allow" ) ,
52+ ( "style" , "warn" ) ,
53+ ( "pedantic" , "allow" ) ,
54+ ( "complexity" , "warn" ) ,
55+ ( "perf" , "warn" ) ,
56+ ( "cargo" , "allow" ) ,
57+ ( "nursery" , "allow" ) ,
58+ ] ;
59+ /// This prefix is in front of the lint groups in the lint store. The prefix will be trimmed
60+ /// to only keep the actual lint group in the output.
61+ const CLIPPY_LINT_GROUP_PREFIX : & str = "clippy::" ;
4462
4563/// This template will be used to format the configuration section in the lint documentation.
4664/// The `configurations` parameter will be replaced with one or multiple formatted
@@ -188,18 +206,20 @@ struct LintMetadata {
188206 id : String ,
189207 id_span : SerializableSpan ,
190208 group : String ,
209+ level : & ' static str ,
191210 docs : String ,
192211 /// This field is only used in the output and will only be
193212 /// mapped shortly before the actual output.
194213 applicability : Option < ApplicabilityInfo > ,
195214}
196215
197216impl LintMetadata {
198- fn new ( id : String , id_span : SerializableSpan , group : String , docs : String ) -> Self {
217+ fn new ( id : String , id_span : SerializableSpan , group : String , level : & ' static str , docs : String ) -> Self {
199218 Self {
200219 id,
201220 id_span,
202221 group,
222+ level,
203223 docs,
204224 applicability : None ,
205225 }
@@ -368,7 +388,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
368388 let lint_name = sym_to_string( item. ident. name) . to_ascii_lowercase( ) ;
369389 if !BLACK_LISTED_LINTS . contains( & lint_name. as_str( ) ) ;
370390 // metadata extraction
371- if let Some ( group) = get_lint_group_or_lint ( cx, & lint_name, item) ;
391+ if let Some ( ( group, level ) ) = get_lint_group_and_level_or_lint ( cx, & lint_name, item) ;
372392 if let Some ( mut docs) = extract_attr_docs_or_lint( cx, item) ;
373393 then {
374394 if let Some ( configuration_section) = self . get_lint_configs( & lint_name) {
@@ -379,6 +399,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
379399 lint_name,
380400 SerializableSpan :: from_item( cx, item) ,
381401 group,
402+ level,
382403 docs,
383404 ) ) ;
384405 }
@@ -396,6 +417,7 @@ impl<'hir> LateLintPass<'hir> for MetadataCollector {
396417 lint_name,
397418 SerializableSpan :: from_item( cx, item) ,
398419 DEPRECATED_LINT_GROUP_STR . to_string( ) ,
420+ DEPRECATED_LINT_LEVEL ,
399421 docs,
400422 ) ) ;
401423 }
@@ -475,15 +497,32 @@ fn extract_attr_docs(cx: &LateContext<'_>, item: &Item<'_>) -> Option<String> {
475497 } )
476498}
477499
478- fn get_lint_group_or_lint ( cx : & LateContext < ' _ > , lint_name : & str , item : & ' hir Item < ' _ > ) -> Option < String > {
500+ fn get_lint_group_and_level_or_lint (
501+ cx : & LateContext < ' _ > ,
502+ lint_name : & str ,
503+ item : & ' hir Item < ' _ > ,
504+ ) -> Option < ( String , & ' static str ) > {
479505 let result = cx. lint_store . check_lint_name ( lint_name, Some ( sym:: clippy) ) ;
480506 if let CheckLintNameResult :: Tool ( Ok ( lint_lst) ) = result {
481- get_lint_group ( cx, lint_lst[ 0 ] )
482- . or_else ( || {
483- lint_collection_error_item ( cx, item, "Unable to determine lint group" ) ;
507+ if let Some ( group) = get_lint_group ( cx, lint_lst[ 0 ] ) {
508+ if EXCLUDED_LINT_GROUPS . contains ( & group. as_str ( ) ) {
509+ return None ;
510+ }
511+
512+ if let Some ( level) = get_lint_level_from_group ( & group) {
513+ Some ( ( group, level) )
514+ } else {
515+ lint_collection_error_item (
516+ cx,
517+ item,
518+ & format ! ( "Unable to determine lint level for found group `{}`" , group) ,
519+ ) ;
484520 None
485- } )
486- . filter ( |group| !EXCLUDED_LINT_GROUPS . contains ( & group. as_str ( ) ) )
521+ }
522+ } else {
523+ lint_collection_error_item ( cx, item, "Unable to determine lint group" ) ;
524+ None
525+ }
487526 } else {
488527 lint_collection_error_item ( cx, item, "Unable to find lint in lint_store" ) ;
489528 None
@@ -496,14 +535,21 @@ fn get_lint_group(cx: &LateContext<'_>, lint_id: LintId) -> Option<String> {
496535 continue ;
497536 }
498537
499- if lints. iter ( ) . any ( |x| * x == lint_id) {
500- return Some ( ( * group_name) . to_string ( ) ) ;
538+ if lints. iter ( ) . any ( |group_lint| * group_lint == lint_id) {
539+ let group = group_name. strip_prefix ( CLIPPY_LINT_GROUP_PREFIX ) . unwrap_or ( group_name) ;
540+ return Some ( ( * group) . to_string ( ) ) ;
501541 }
502542 }
503543
504544 None
505545}
506546
547+ fn get_lint_level_from_group ( lint_group : & str ) -> Option < & ' static str > {
548+ DEFAULT_LINT_LEVELS
549+ . iter ( )
550+ . find_map ( |( group_name, group_level) | ( * group_name == lint_group) . then ( || * group_level) )
551+ }
552+
507553fn is_deprecated_lint ( cx : & LateContext < ' _ > , ty : & hir:: Ty < ' _ > ) -> bool {
508554 if let hir:: TyKind :: Path ( ref path) = ty. kind {
509555 if let hir:: def:: Res :: Def ( DefKind :: Struct , def_id) = cx. qpath_res ( path, ty. hir_id ) {
0 commit comments