@@ -12,6 +12,113 @@ type LintError = String;
12
12
type LintResult = Result < ( ) , LintError > ;
13
13
type LintFn = fn ( ) -> LintResult ;
14
14
15
+ struct Linter {
16
+ pub description : & ' static str ,
17
+ pub name : & ' static str ,
18
+ pub lint_fn : LintFn ,
19
+ }
20
+
21
+ fn get_linter_list ( ) -> Vec < & ' static Linter > {
22
+ vec ! [
23
+ & Linter {
24
+ description: "Check that all command line arguments are documented." ,
25
+ name: "doc" ,
26
+ lint_fn: lint_doc
27
+ } ,
28
+ & Linter {
29
+ description: "Check that no symbol from bitcoin-config.h is used without the header being included" ,
30
+ name: "includes_build_config" ,
31
+ lint_fn: lint_includes_build_config
32
+ } ,
33
+ & Linter {
34
+ description: "Check that markdown links resolve" ,
35
+ name: "markdown" ,
36
+ lint_fn: lint_markdown
37
+ } ,
38
+ & Linter {
39
+ description: "Check that std::filesystem is not used directly" ,
40
+ name: "std_filesystem" ,
41
+ lint_fn: lint_std_filesystem
42
+ } ,
43
+ & Linter {
44
+ description: "Check that subtrees are pure subtrees" ,
45
+ name: "subtree" ,
46
+ lint_fn: lint_subtree
47
+ } ,
48
+ & Linter {
49
+ description: "Check that tabs are not used as whitespace" ,
50
+ name: "tabs_whitespace" ,
51
+ lint_fn: lint_tabs_whitespace
52
+ } ,
53
+ & Linter {
54
+ description: "Check for trailing whitespace" ,
55
+ name: "trailing_whitespace" ,
56
+ lint_fn: lint_trailing_whitespace
57
+ } ,
58
+ & Linter {
59
+ description: "Run all linters of the form: test/lint/lint-*.py" ,
60
+ name: "all_python_linters" ,
61
+ lint_fn: run_all_python_linters
62
+ } ,
63
+ ]
64
+ }
65
+
66
+ fn print_help_and_exit ( ) {
67
+ print ! (
68
+ r#"
69
+ Usage: test_runner [--lint=LINTER_TO_RUN]
70
+ Runs all linters in the lint test suite, printing any errors
71
+ they detect.
72
+
73
+ If you wish to only run some particular lint tests, pass
74
+ '--lint=' with the name of the lint test you wish to run.
75
+ You can set as many '--lint=' values as you wish, e.g.:
76
+ test_runner --lint=doc --lint=subtree
77
+
78
+ The individual linters available to run are:
79
+ "#
80
+ ) ;
81
+ for linter in get_linter_list ( ) {
82
+ println ! ( "{}: \" {}\" " , linter. name, linter. description)
83
+ }
84
+
85
+ std:: process:: exit ( 1 ) ;
86
+ }
87
+
88
+ fn parse_lint_args ( args : & [ String ] ) -> Vec < & ' static Linter > {
89
+ let linter_list = get_linter_list ( ) ;
90
+ let mut lint_values = Vec :: new ( ) ;
91
+
92
+ for arg in args {
93
+ #[ allow( clippy:: if_same_then_else) ]
94
+ if arg. starts_with ( "--lint=" ) {
95
+ let lint_arg_value = arg
96
+ . trim_start_matches ( "--lint=" )
97
+ . trim_matches ( '"' )
98
+ . trim_matches ( '\'' ) ;
99
+
100
+ let try_find_linter = linter_list
101
+ . iter ( )
102
+ . find ( |linter| linter. name == lint_arg_value) ;
103
+ match try_find_linter {
104
+ Some ( linter) => {
105
+ lint_values. push ( * linter) ;
106
+ }
107
+ None => {
108
+ println ! ( "No linter {lint_arg_value} found!" ) ;
109
+ print_help_and_exit ( ) ;
110
+ }
111
+ }
112
+ } else if arg. eq ( "--help" ) || arg. eq ( "-h" ) {
113
+ print_help_and_exit ( ) ;
114
+ } else {
115
+ print_help_and_exit ( ) ;
116
+ }
117
+ }
118
+
119
+ lint_values
120
+ }
121
+
15
122
/// Return the git command
16
123
fn git ( ) -> Command {
17
124
let mut git = Command :: new ( "git" ) ;
@@ -337,7 +444,7 @@ Markdown link errors found:
337
444
}
338
445
}
339
446
340
- fn lint_all ( ) -> LintResult {
447
+ fn run_all_python_linters ( ) -> LintResult {
341
448
let mut good = true ;
342
449
let lint_dir = get_git_root ( ) . join ( "test/lint" ) ;
343
450
for entry in fs:: read_dir ( lint_dir) . unwrap ( ) {
@@ -352,7 +459,7 @@ fn lint_all() -> LintResult {
352
459
. success ( )
353
460
{
354
461
good = false ;
355
- println ! ( "^---- failure generated from {}" , entry_fn) ;
462
+ println ! ( "^---- ⚠️ Failure generated from {}" , entry_fn) ;
356
463
}
357
464
}
358
465
if good {
@@ -363,25 +470,26 @@ fn lint_all() -> LintResult {
363
470
}
364
471
365
472
fn main ( ) -> ExitCode {
366
- let test_list: Vec < ( & str , LintFn ) > = vec ! [
367
- ( "subtree check" , lint_subtree) ,
368
- ( "std::filesystem check" , lint_std_filesystem) ,
369
- ( "trailing whitespace check" , lint_trailing_whitespace) ,
370
- ( "no-tabs check" , lint_tabs_whitespace) ,
371
- ( "build config includes check" , lint_includes_build_config) ,
372
- ( "-help=1 documentation check" , lint_doc) ,
373
- ( "markdown hyperlink check" , lint_markdown) ,
374
- ( "lint-*.py scripts" , lint_all) ,
375
- ] ;
473
+ let linters_to_run: Vec < & Linter > = if env:: args ( ) . count ( ) > 1 {
474
+ let args: Vec < String > = env:: args ( ) . skip ( 1 ) . collect ( ) ;
475
+ parse_lint_args ( & args)
476
+ } else {
477
+ // If no arguments are passed, run all linters.
478
+ get_linter_list ( )
479
+ } ;
376
480
377
481
let git_root = get_git_root ( ) ;
378
482
379
483
let mut test_failed = false ;
380
- for ( lint_name , lint_fn ) in test_list {
484
+ for linter in linters_to_run {
381
485
// chdir to root before each lint test
382
486
env:: set_current_dir ( & git_root) . unwrap ( ) ;
383
- if let Err ( err) = lint_fn ( ) {
384
- println ! ( "{err}\n ^---- ⚠️ Failure generated from {lint_name}!" ) ;
487
+ if let Err ( err) = ( linter. lint_fn ) ( ) {
488
+ println ! (
489
+ "{err}\n ^---- ⚠️ Failure generated from lint check '{}'!" ,
490
+ linter. name
491
+ ) ;
492
+ println ! ( "{}" , linter. description) ;
385
493
test_failed = true ;
386
494
}
387
495
}
0 commit comments