4
4
5
5
use lazy_static:: lazy_static;
6
6
use rustc_span:: source_map;
7
- use std :: default :: Default ;
8
- use std:: io :: Read ;
7
+ use source_map :: Span ;
8
+ use std:: path :: { Path , PathBuf } ;
9
9
use std:: sync:: Mutex ;
10
- use std:: { env, fmt, fs, io, path } ;
11
- use syntax:: ast;
10
+ use std:: { env, fmt, fs, io} ;
11
+ use syntax:: ast:: { LitKind , MetaItemKind , NestedMetaItem } ;
12
12
13
13
/// Gets the configuration file from arguments.
14
- pub fn file_from_args ( args : & [ ast :: NestedMetaItem ] ) -> Result < Option < path :: PathBuf > , ( & ' static str , source_map :: Span ) > {
15
- for arg in args. iter ( ) . filter_map ( syntax :: ast :: NestedMetaItem :: meta_item) {
14
+ pub fn file_from_args ( args : & [ NestedMetaItem ] ) -> Result < Option < PathBuf > , ( & ' static str , Span ) > {
15
+ for arg in args. iter ( ) . filter_map ( NestedMetaItem :: meta_item) {
16
16
if arg. check_name ( sym ! ( conf_file) ) {
17
17
return match arg. kind {
18
- ast:: MetaItemKind :: Word | ast:: MetaItemKind :: List ( _) => {
19
- Err ( ( "`conf_file` must be a named value" , arg. span ) )
20
- } ,
21
- ast:: MetaItemKind :: NameValue ( ref value) => {
22
- if let ast:: LitKind :: Str ( ref file, _) = value. kind {
18
+ MetaItemKind :: Word | MetaItemKind :: List ( _) => Err ( ( "`conf_file` must be a named value" , arg. span ) ) ,
19
+ MetaItemKind :: NameValue ( ref value) => {
20
+ if let LitKind :: Str ( ref file, _) = value. kind {
23
21
Ok ( Some ( file. to_string ( ) . into ( ) ) )
24
22
} else {
25
23
Err ( ( "`conf_file` value must be a string" , value. span ) )
@@ -37,15 +35,15 @@ pub fn file_from_args(args: &[ast::NestedMetaItem]) -> Result<Option<path::PathB
37
35
pub enum Error {
38
36
/// An I/O error.
39
37
Io ( io:: Error ) ,
40
- /// Not valid toml or doesn't fit the expected conf format
38
+ /// Not valid toml or doesn't fit the expected config format
41
39
Toml ( String ) ,
42
40
}
43
41
44
42
impl fmt:: Display for Error {
45
- fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> Result < ( ) , fmt:: Error > {
46
- match * self {
47
- Self :: Io ( ref err) => err. fmt ( f) ,
48
- Self :: Toml ( ref err) => err. fmt ( f) ,
43
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
44
+ match self {
45
+ Self :: Io ( err) => err. fmt ( f) ,
46
+ Self :: Toml ( err) => err. fmt ( f) ,
49
47
}
50
48
}
51
49
}
@@ -61,59 +59,61 @@ lazy_static! {
61
59
}
62
60
63
61
macro_rules! define_Conf {
64
- ( $( #[ $doc: meta] ( $rust_name: ident, $rust_name_str: expr, $default: expr => $( $ty: tt) +) , ) +) => {
65
- pub use self :: helpers:: Conf ;
62
+ ( $( #[ $doc: meta] ( $config: ident, $config_str: literal: $Ty: ty, $default: expr) , ) +) => {
66
63
mod helpers {
67
64
use serde:: Deserialize ;
68
65
/// Type used to store lint configuration.
69
66
#[ derive( Deserialize ) ]
70
- #[ serde( rename_all= "kebab-case" , deny_unknown_fields) ]
67
+ #[ serde( rename_all = "kebab-case" , deny_unknown_fields) ]
71
68
pub struct Conf {
72
- $( #[ $doc] #[ serde( default =$rust_name_str) ] #[ serde( with=$rust_name_str) ]
73
- pub $rust_name: define_Conf!( TY $( $ty) +) , ) +
69
+ $(
70
+ #[ $doc]
71
+ #[ serde( default = $config_str) ]
72
+ #[ serde( with = $config_str) ]
73
+ pub $config: $Ty,
74
+ ) +
74
75
#[ allow( dead_code) ]
75
76
#[ serde( default ) ]
76
77
third_party: Option <:: toml:: Value >,
77
78
}
79
+
78
80
$(
79
- mod $rust_name {
81
+ mod $config {
80
82
use serde:: Deserialize ;
81
- crate fn deserialize<' de, D : serde:: Deserializer <' de>>( deserializer: D )
82
- -> Result <define_Conf!( TY $( $ty) +) , D :: Error > {
83
- type T = define_Conf!( TY $( $ty) +) ;
84
- Ok ( T :: deserialize( deserializer) . unwrap_or_else( |e| {
85
- crate :: utils:: conf:: ERRORS . lock( ) . expect( "no threading here" )
86
- . push( crate :: utils:: conf:: Error :: Toml ( e. to_string( ) ) ) ;
87
- super :: $rust_name( )
88
- } ) )
83
+ crate fn deserialize<' de, D : serde:: Deserializer <' de>>( deserializer: D ) -> Result <$Ty, D :: Error > {
84
+ use super :: super :: { ERRORS , Error } ;
85
+ Ok (
86
+ <$Ty>:: deserialize( deserializer) . unwrap_or_else( |e| {
87
+ ERRORS
88
+ . lock( )
89
+ . expect( "no threading here" )
90
+ . push( Error :: Toml ( e. to_string( ) ) ) ;
91
+ super :: $config( )
92
+ } )
93
+ )
89
94
}
90
95
}
91
96
92
97
#[ must_use]
93
- fn $rust_name( ) -> define_Conf!( TY $( $ty) +) {
94
- define_Conf!( DEFAULT $( $ty) +, $default)
98
+ fn $config( ) -> $Ty {
99
+ let x = $default;
100
+ x
95
101
}
96
102
) +
97
103
}
98
104
} ;
99
-
100
- // hack to convert tts
101
- ( TY $ty: ty) => { $ty } ;
102
-
103
- // provide a nicer syntax to declare the default value of `Vec<String>` variables
104
- ( DEFAULT Vec <String >, $e: expr) => { $e. iter( ) . map( |& e| e. to_owned( ) ) . collect( ) } ;
105
- ( DEFAULT $ty: ty, $e: expr) => { $e } ;
106
105
}
107
106
107
+ pub use self :: helpers:: Conf ;
108
108
define_Conf ! {
109
109
/// Lint: BLACKLISTED_NAME. The list of blacklisted names to lint about
110
- ( blacklisted_names, "blacklisted_names" , [ "foo" , "bar" , "baz" , "quux" ] => Vec < String > ) ,
110
+ ( blacklisted_names, "blacklisted_names" : Vec < String > , [ "foo" , "bar" , "baz" , "quux" ] . iter ( ) . map ( ToString :: to_string ) . collect ( ) ) ,
111
111
/// Lint: COGNITIVE_COMPLEXITY. The maximum cognitive complexity a function can have
112
- ( cognitive_complexity_threshold, "cognitive_complexity_threshold" , 25 => u64 ) ,
112
+ ( cognitive_complexity_threshold, "cognitive_complexity_threshold" : u64 , 25 ) ,
113
113
/// DEPRECATED LINT: CYCLOMATIC_COMPLEXITY. Use the Cognitive Complexity lint instead.
114
- ( cyclomatic_complexity_threshold, "cyclomatic_complexity_threshold" , None => Option <u64 >) ,
114
+ ( cyclomatic_complexity_threshold, "cyclomatic_complexity_threshold" : Option <u64 >, None ) ,
115
115
/// Lint: DOC_MARKDOWN. The list of words this lint should not consider as identifiers needing ticks
116
- ( doc_valid_idents, "doc_valid_idents" , [
116
+ ( doc_valid_idents, "doc_valid_idents" : Vec < String > , [
117
117
"KiB" , "MiB" , "GiB" , "TiB" , "PiB" , "EiB" ,
118
118
"DirectX" ,
119
119
"ECMAScript" ,
@@ -129,31 +129,31 @@ define_Conf! {
129
129
"TeX" , "LaTeX" , "BibTeX" , "BibLaTeX" ,
130
130
"MinGW" ,
131
131
"CamelCase" ,
132
- ] => Vec < String > ) ,
132
+ ] . iter ( ) . map ( ToString :: to_string ) . collect ( ) ) ,
133
133
/// Lint: TOO_MANY_ARGUMENTS. The maximum number of argument a function or method can have
134
- ( too_many_arguments_threshold, "too_many_arguments_threshold" , 7 => u64 ) ,
134
+ ( too_many_arguments_threshold, "too_many_arguments_threshold" : u64 , 7 ) ,
135
135
/// Lint: TYPE_COMPLEXITY. The maximum complexity a type can have
136
- ( type_complexity_threshold, "type_complexity_threshold" , 250 => u64 ) ,
136
+ ( type_complexity_threshold, "type_complexity_threshold" : u64 , 250 ) ,
137
137
/// Lint: MANY_SINGLE_CHAR_NAMES. The maximum number of single char bindings a scope may have
138
- ( single_char_binding_names_threshold, "single_char_binding_names_threshold" , 5 => u64 ) ,
138
+ ( single_char_binding_names_threshold, "single_char_binding_names_threshold" : u64 , 5 ) ,
139
139
/// Lint: BOXED_LOCAL. The maximum size of objects (in bytes) that will be linted. Larger objects are ok on the heap
140
- ( too_large_for_stack, "too_large_for_stack" , 200 => u64 ) ,
140
+ ( too_large_for_stack, "too_large_for_stack" : u64 , 200 ) ,
141
141
/// Lint: ENUM_VARIANT_NAMES. The minimum number of enum variants for the lints about variant names to trigger
142
- ( enum_variant_name_threshold, "enum_variant_name_threshold" , 3 => u64 ) ,
142
+ ( enum_variant_name_threshold, "enum_variant_name_threshold" : u64 , 3 ) ,
143
143
/// Lint: LARGE_ENUM_VARIANT. The maximum size of a enum's variant to avoid box suggestion
144
- ( enum_variant_size_threshold, "enum_variant_size_threshold" , 200 => u64 ) ,
144
+ ( enum_variant_size_threshold, "enum_variant_size_threshold" : u64 , 200 ) ,
145
145
/// Lint: VERBOSE_BIT_MASK. The maximum allowed size of a bit mask before suggesting to use 'trailing_zeros'
146
- ( verbose_bit_mask_threshold, "verbose_bit_mask_threshold" , 1 => u64 ) ,
146
+ ( verbose_bit_mask_threshold, "verbose_bit_mask_threshold" : u64 , 1 ) ,
147
147
/// Lint: DECIMAL_LITERAL_REPRESENTATION. The lower bound for linting decimal literals
148
- ( literal_representation_threshold, "literal_representation_threshold" , 16384 => u64 ) ,
148
+ ( literal_representation_threshold, "literal_representation_threshold" : u64 , 16384 ) ,
149
149
/// Lint: TRIVIALLY_COPY_PASS_BY_REF. The maximum size (in bytes) to consider a `Copy` type for passing by value instead of by reference.
150
- ( trivial_copy_size_limit, "trivial_copy_size_limit" , None => Option <u64 >) ,
150
+ ( trivial_copy_size_limit, "trivial_copy_size_limit" : Option <u64 >, None ) ,
151
151
/// Lint: TOO_MANY_LINES. The maximum number of lines a function or method can have
152
- ( too_many_lines_threshold, "too_many_lines_threshold" , 100 => u64 ) ,
152
+ ( too_many_lines_threshold, "too_many_lines_threshold" : u64 , 100 ) ,
153
153
/// Lint: LARGE_STACK_ARRAYS. The maximum allowed size for arrays on the stack
154
- ( array_size_threshold, "array_size_threshold" , 512_000 => u64 ) ,
154
+ ( array_size_threshold, "array_size_threshold" : u64 , 512_000 ) ,
155
155
/// Lint: VEC_BOX. The size of the boxed type in bytes, where boxing in a `Vec` is allowed
156
- ( vec_box_size_threshold, "vec_box_size_threshold" , 4096 => u64 ) ,
156
+ ( vec_box_size_threshold, "vec_box_size_threshold" : u64 , 4096 ) ,
157
157
}
158
158
159
159
impl Default for Conf {
@@ -164,32 +164,26 @@ impl Default for Conf {
164
164
}
165
165
166
166
/// Search for the configuration file.
167
- pub fn lookup_conf_file ( ) -> io:: Result < Option < path :: PathBuf > > {
167
+ pub fn lookup_conf_file ( ) -> io:: Result < Option < PathBuf > > {
168
168
/// Possible filename to search for.
169
169
const CONFIG_FILE_NAMES : [ & str ; 2 ] = [ ".clippy.toml" , "clippy.toml" ] ;
170
170
171
171
// Start looking for a config file in CLIPPY_CONF_DIR, or failing that, CARGO_MANIFEST_DIR.
172
172
// If neither of those exist, use ".".
173
- let mut current = path:: PathBuf :: from (
174
- env:: var ( "CLIPPY_CONF_DIR" )
175
- . or_else ( |_| env:: var ( "CARGO_MANIFEST_DIR" ) )
176
- . unwrap_or_else ( |_| "." . to_string ( ) ) ,
177
- ) ;
173
+ let mut current = env:: var_os ( "CLIPPY_CONF_DIR" )
174
+ . or_else ( || env:: var_os ( "CARGO_MANIFEST_DIR" ) )
175
+ . map_or_else ( || PathBuf :: from ( "." ) , PathBuf :: from) ;
178
176
loop {
179
177
for config_file_name in & CONFIG_FILE_NAMES {
180
178
let config_file = current. join ( config_file_name) ;
181
179
match fs:: metadata ( & config_file) {
182
180
// Only return if it's a file to handle the unlikely situation of a directory named
183
181
// `clippy.toml`.
184
- Ok ( ref md) if md. is_file ( ) => return Ok ( Some ( config_file) ) ,
182
+ Ok ( ref md) if ! md. is_dir ( ) => return Ok ( Some ( config_file) ) ,
185
183
// Return the error if it's something other than `NotFound`; otherwise we didn't
186
184
// find the project file yet, and continue searching.
187
- Err ( e) => {
188
- if e. kind ( ) != io:: ErrorKind :: NotFound {
189
- return Err ( e) ;
190
- }
191
- } ,
192
- _ => ( ) ,
185
+ Err ( e) if e. kind ( ) != io:: ErrorKind :: NotFound => return Err ( e) ,
186
+ _ => { } ,
193
187
}
194
188
}
195
189
@@ -210,28 +204,14 @@ fn default(errors: Vec<Error>) -> (Conf, Vec<Error>) {
210
204
/// Read the `toml` configuration file.
211
205
///
212
206
/// In case of error, the function tries to continue as much as possible.
213
- pub fn read ( path : Option < & path:: Path > ) -> ( Conf , Vec < Error > ) {
214
- let path = if let Some ( path) = path {
215
- path
216
- } else {
217
- return default ( Vec :: new ( ) ) ;
218
- } ;
219
-
220
- let file = match fs:: File :: open ( path) {
221
- Ok ( mut file) => {
222
- let mut buf = String :: new ( ) ;
223
-
224
- if let Err ( err) = file. read_to_string ( & mut buf) {
225
- return default ( vec ! [ err. into( ) ] ) ;
226
- }
227
-
228
- buf
229
- } ,
207
+ pub fn read ( path : & Path ) -> ( Conf , Vec < Error > ) {
208
+ let content = match fs:: read_to_string ( path) {
209
+ Ok ( content) => content,
230
210
Err ( err) => return default ( vec ! [ err. into( ) ] ) ,
231
211
} ;
232
212
233
213
assert ! ( ERRORS . lock( ) . expect( "no threading -> mutex always safe" ) . is_empty( ) ) ;
234
- match toml:: from_str ( & file ) {
214
+ match toml:: from_str ( & content ) {
235
215
Ok ( toml) => {
236
216
let mut errors = ERRORS . lock ( ) . expect ( "no threading -> mutex always safe" ) . split_off ( 0 ) ;
237
217
0 commit comments