@@ -57,9 +57,9 @@ impl Lint {
57
57
}
58
58
}
59
59
60
- /// Returns all non-deprecated lints
61
- pub fn active_lints ( lints : impl Iterator < Item =Self > ) -> impl Iterator < Item =Self > {
62
- lints. filter ( |l| l. deprecation . is_none ( ) )
60
+ /// Returns all non-deprecated lints and non-internal lints
61
+ pub fn usable_lints ( lints : impl Iterator < Item =Self > ) -> impl Iterator < Item =Self > {
62
+ lints. filter ( |l| l. deprecation . is_none ( ) && !l . group . starts_with ( "internal" ) )
63
63
}
64
64
65
65
/// Returns the lints in a HashMap, grouped by the different lint groups
@@ -101,6 +101,89 @@ fn lint_files() -> impl Iterator<Item=walkdir::DirEntry> {
101
101
. filter ( |f| f. path ( ) . extension ( ) == Some ( OsStr :: new ( "rs" ) ) )
102
102
}
103
103
104
+ /// Replace a region in a file delimited by two lines matching regexes.
105
+ ///
106
+ /// `path` is the relative path to the file on which you want to perform the replacement.
107
+ ///
108
+ /// See `replace_region_in_text` for documentation of the other options.
109
+ #[ allow( clippy:: expect_fun_call) ]
110
+ pub fn replace_region_in_file < F > ( path : & str , start : & str , end : & str , replace_start : bool , replacements : F ) where F : Fn ( ) -> Vec < String > {
111
+ let mut f = fs:: File :: open ( path) . expect ( & format ! ( "File not found: {}" , path) ) ;
112
+ let mut contents = String :: new ( ) ;
113
+ f. read_to_string ( & mut contents) . expect ( "Something went wrong reading the file" ) ;
114
+ let replaced = replace_region_in_text ( & contents, start, end, replace_start, replacements) ;
115
+
116
+ let mut f = fs:: File :: create ( path) . expect ( & format ! ( "File not found: {}" , path) ) ;
117
+ f. write_all ( replaced. as_bytes ( ) ) . expect ( "Unable to write file" ) ;
118
+ // Ensure we write the changes with a trailing newline so that
119
+ // the file has the proper line endings.
120
+ f. write_all ( b"\n " ) . expect ( "Unable to write file" ) ;
121
+ }
122
+
123
+ /// Replace a region in a text delimited by two lines matching regexes.
124
+ ///
125
+ /// * `text` is the input text on which you want to perform the replacement
126
+ /// * `start` is a `&str` that describes the delimiter line before the region you want to replace.
127
+ /// As the `&str` will be converted to a `Regex`, this can contain regex syntax, too.
128
+ /// * `end` is a `&str` that describes the delimiter line until where the replacement should
129
+ /// happen. As the `&str` will be converted to a `Regex`, this can contain regex syntax, too.
130
+ /// * If `replace_start` is true, the `start` delimiter line is replaced as well.
131
+ /// The `end` delimiter line is never replaced.
132
+ /// * `replacements` is a closure that has to return a `Vec<String>` which contains the new text.
133
+ ///
134
+ /// If you want to perform the replacement on files instead of already parsed text,
135
+ /// use `replace_region_in_file`.
136
+ ///
137
+ /// # Example
138
+ ///
139
+ /// ```
140
+ /// let the_text = "replace_start\nsome text\nthat will be replaced\nreplace_end";
141
+ /// let result = clippy_dev::replace_region_in_text(
142
+ /// the_text,
143
+ /// r#"replace_start"#,
144
+ /// r#"replace_end"#,
145
+ /// false,
146
+ /// || {
147
+ /// vec!["a different".to_string(), "text".to_string()]
148
+ /// }
149
+ /// );
150
+ /// assert_eq!("replace_start\na different\ntext\nreplace_end", result);
151
+ /// ```
152
+ pub fn replace_region_in_text < F > ( text : & str , start : & str , end : & str , replace_start : bool , replacements : F ) -> String where F : Fn ( ) -> Vec < String > {
153
+ let lines = text. lines ( ) ;
154
+ let mut in_old_region = false ;
155
+ let mut found = false ;
156
+ let mut new_lines = vec ! [ ] ;
157
+ let start = Regex :: new ( start) . unwrap ( ) ;
158
+ let end = Regex :: new ( end) . unwrap ( ) ;
159
+
160
+ for line in lines {
161
+ if in_old_region {
162
+ if end. is_match ( & line) {
163
+ in_old_region = false ;
164
+ new_lines. extend ( replacements ( ) ) ;
165
+ new_lines. push ( line. to_string ( ) ) ;
166
+ }
167
+ } else if start. is_match ( & line) {
168
+ if !replace_start {
169
+ new_lines. push ( line. to_string ( ) ) ;
170
+ }
171
+ in_old_region = true ;
172
+ found = true ;
173
+ } else {
174
+ new_lines. push ( line. to_string ( ) ) ;
175
+ }
176
+ }
177
+
178
+ if !found {
179
+ // This happens if the provided regex in `clippy_dev/src/main.rs` is not found in the
180
+ // given text or file. Most likely this is an error on the programmer's side and the Regex
181
+ // is incorrect.
182
+ println ! ( "regex {:?} not found. You may have to update it." , start) ;
183
+ }
184
+ new_lines. join ( "\n " )
185
+ }
186
+
104
187
#[ test]
105
188
fn test_parse_contents ( ) {
106
189
let result: Vec < Lint > = parse_contents (
@@ -141,15 +224,54 @@ declare_deprecated_lint! {
141
224
}
142
225
143
226
#[ test]
144
- fn test_active_lints ( ) {
227
+ fn test_replace_region ( ) {
228
+ let text = r#"
229
+ abc
230
+ 123
231
+ 789
232
+ def
233
+ ghi"# ;
234
+ let expected = r#"
235
+ abc
236
+ hello world
237
+ def
238
+ ghi"# ;
239
+ let result = replace_region_in_text ( text, r#"^\s*abc$"# , r#"^\s*def"# , false , || {
240
+ vec ! [ "hello world" . to_string( ) ]
241
+ } ) ;
242
+ assert_eq ! ( expected, result) ;
243
+ }
244
+
245
+ #[ test]
246
+ fn test_replace_region_with_start ( ) {
247
+ let text = r#"
248
+ abc
249
+ 123
250
+ 789
251
+ def
252
+ ghi"# ;
253
+ let expected = r#"
254
+ hello world
255
+ def
256
+ ghi"# ;
257
+ let result = replace_region_in_text ( text, r#"^\s*abc$"# , r#"^\s*def"# , true , || {
258
+ vec ! [ "hello world" . to_string( ) ]
259
+ } ) ;
260
+ assert_eq ! ( expected, result) ;
261
+ }
262
+
263
+ #[ test]
264
+ fn test_usable_lints ( ) {
145
265
let lints = vec ! [
146
266
Lint :: new( "should_assert_eq" , "Deprecated" , "abc" , Some ( "Reason" ) , "module_name" ) ,
147
- Lint :: new( "should_assert_eq2" , "Not Deprecated" , "abc" , None , "module_name" )
267
+ Lint :: new( "should_assert_eq2" , "Not Deprecated" , "abc" , None , "module_name" ) ,
268
+ Lint :: new( "should_assert_eq2" , "internal" , "abc" , None , "module_name" ) ,
269
+ Lint :: new( "should_assert_eq2" , "internal_style" , "abc" , None , "module_name" )
148
270
] ;
149
271
let expected = vec ! [
150
272
Lint :: new( "should_assert_eq2" , "Not Deprecated" , "abc" , None , "module_name" )
151
273
] ;
152
- assert_eq ! ( expected, Lint :: active_lints ( lints. into_iter( ) ) . collect:: <Vec <Lint >>( ) ) ;
274
+ assert_eq ! ( expected, Lint :: usable_lints ( lints. into_iter( ) ) . collect:: <Vec <Lint >>( ) ) ;
153
275
}
154
276
155
277
#[ test]
0 commit comments