1
1
use super :: DUPLICATED_ATTRIBUTES ;
2
2
use clippy_utils:: diagnostics:: span_lint_and_then;
3
- use rustc_ast:: { Attribute , MetaItem } ;
3
+ use rustc_ast:: { MetaItem , MetaItemInner } ;
4
4
use rustc_data_structures:: fx:: FxHashMap ;
5
+ use rustc_hir:: Attribute ;
5
6
use rustc_lint:: LateContext ;
6
- use rustc_span:: { Span , sym} ;
7
+ use rustc_span:: symbol:: Ident ;
8
+ use rustc_span:: { Span , Symbol , sym} ;
7
9
use std:: collections:: hash_map:: Entry ;
10
+ use thin_vec:: ThinVec ;
8
11
9
12
fn emit_if_duplicated (
10
13
cx : & LateContext < ' _ > ,
11
- attr : & MetaItem ,
14
+ span : Span ,
12
15
attr_paths : & mut FxHashMap < String , Span > ,
13
16
complete_path : String ,
14
17
) {
15
18
match attr_paths. entry ( complete_path) {
16
19
Entry :: Vacant ( v) => {
17
- v. insert ( attr . span ) ;
20
+ v. insert ( span) ;
18
21
} ,
19
22
Entry :: Occupied ( o) => {
20
- span_lint_and_then ( cx, DUPLICATED_ATTRIBUTES , attr . span , "duplicated attribute" , |diag| {
23
+ span_lint_and_then ( cx, DUPLICATED_ATTRIBUTES , span, "duplicated attribute" , |diag| {
21
24
diag. span_note ( * o. get ( ) , "first defined here" ) ;
22
- diag. span_help ( attr . span , "remove this attribute" ) ;
25
+ diag. span_help ( span, "remove this attribute" ) ;
23
26
} ) ;
24
27
} ,
25
28
}
26
29
}
27
30
31
+ trait AttrOrMetaItem {
32
+ fn ident ( & self ) -> Option < Ident > ;
33
+ fn span ( & self ) -> Span ;
34
+ fn meta_item_list ( & self ) -> Option < ThinVec < MetaItemInner > > ;
35
+ fn value_str ( & self ) -> Option < Symbol > ;
36
+ }
37
+
38
+ impl AttrOrMetaItem for Attribute {
39
+ fn ident ( & self ) -> Option < Ident > {
40
+ rustc_ast:: attr:: AttributeExt :: ident ( self )
41
+ }
42
+
43
+ fn span ( & self ) -> Span {
44
+ rustc_ast:: attr:: AttributeExt :: span ( self )
45
+ }
46
+
47
+ fn meta_item_list ( & self ) -> Option < ThinVec < MetaItemInner > > {
48
+ rustc_ast:: attr:: AttributeExt :: meta_item_list ( self )
49
+ }
50
+
51
+ fn value_str ( & self ) -> Option < Symbol > {
52
+ rustc_ast:: attr:: AttributeExt :: value_str ( self )
53
+ }
54
+ }
55
+
56
+ impl AttrOrMetaItem for MetaItem {
57
+ fn ident ( & self ) -> Option < Ident > {
58
+ MetaItem :: ident ( self )
59
+ }
60
+
61
+ fn span ( & self ) -> Span {
62
+ self . span
63
+ }
64
+
65
+ fn meta_item_list ( & self ) -> Option < ThinVec < MetaItemInner > > {
66
+ MetaItem :: meta_item_list ( self ) . map ( |i| i. iter ( ) . cloned ( ) . collect ( ) )
67
+ }
68
+
69
+ fn value_str ( & self ) -> Option < Symbol > {
70
+ MetaItem :: value_str ( self )
71
+ }
72
+ }
73
+
28
74
fn check_duplicated_attr (
29
75
cx : & LateContext < ' _ > ,
30
- attr : & MetaItem ,
76
+ attr : & impl AttrOrMetaItem ,
31
77
attr_paths : & mut FxHashMap < String , Span > ,
32
78
parent : & mut Vec < String > ,
33
79
) {
34
- if attr. span . from_expansion ( ) {
80
+ if attr. span ( ) . from_expansion ( ) {
35
81
return ;
36
82
}
37
83
let Some ( ident) = attr. ident ( ) else { return } ;
@@ -51,7 +97,12 @@ fn check_duplicated_attr(
51
97
return ;
52
98
}
53
99
if let Some ( value) = attr. value_str ( ) {
54
- emit_if_duplicated ( cx, attr, attr_paths, format ! ( "{}:{name}={value}" , parent. join( ":" ) ) ) ;
100
+ emit_if_duplicated (
101
+ cx,
102
+ attr. span ( ) ,
103
+ attr_paths,
104
+ format ! ( "{}:{name}={value}" , parent. join( ":" ) ) ,
105
+ ) ;
55
106
} else if let Some ( sub_attrs) = attr. meta_item_list ( ) {
56
107
parent. push ( name. as_str ( ) . to_string ( ) ) ;
57
108
for sub_attr in sub_attrs {
@@ -61,16 +112,16 @@ fn check_duplicated_attr(
61
112
}
62
113
parent. pop ( ) ;
63
114
} else {
64
- emit_if_duplicated ( cx, attr, attr_paths, format ! ( "{}:{name}" , parent. join( ":" ) ) ) ;
115
+ emit_if_duplicated ( cx, attr. span ( ) , attr_paths, format ! ( "{}:{name}" , parent. join( ":" ) ) ) ;
65
116
}
66
117
}
67
118
68
119
pub fn check ( cx : & LateContext < ' _ > , attrs : & [ Attribute ] ) {
69
120
let mut attr_paths = FxHashMap :: default ( ) ;
70
121
71
122
for attr in attrs {
72
- if let Some ( meta ) = attr. meta ( ) {
73
- check_duplicated_attr ( cx, & meta , & mut attr_paths, & mut Vec :: new ( ) ) ;
123
+ if !rustc_ast :: attr:: AttributeExt :: is_doc_comment ( attr ) {
124
+ check_duplicated_attr ( cx, attr , & mut attr_paths, & mut Vec :: new ( ) ) ;
74
125
}
75
126
}
76
127
}
0 commit comments