@@ -19,6 +19,7 @@ use which::{which, which_in};
19
19
use super :: common_fs:: FileObj ;
20
20
use crate :: {
21
21
cli:: LinesChangedOnly ,
22
+ common_fs:: FileFilter ,
22
23
logger:: { end_log_group, start_log_group} ,
23
24
} ;
24
25
pub mod clang_format;
@@ -77,15 +78,17 @@ pub fn get_clang_tool_exe(name: &str, version: &str) -> Result<PathBuf, &'static
77
78
}
78
79
79
80
#[ derive( Debug , Clone ) ]
80
- struct ClangParams {
81
- tidy_checks : String ,
82
- lines_changed_only : LinesChangedOnly ,
83
- database : Option < PathBuf > ,
84
- extra_args : Option < Vec < String > > ,
85
- database_json : Option < CompilationDatabase > ,
86
- style : String ,
87
- clang_tidy_command : Option < PathBuf > ,
88
- clang_format_command : Option < PathBuf > ,
81
+ pub struct ClangParams {
82
+ pub tidy_checks : String ,
83
+ pub lines_changed_only : LinesChangedOnly ,
84
+ pub database : Option < PathBuf > ,
85
+ pub extra_args : Option < Vec < String > > ,
86
+ pub database_json : Option < CompilationDatabase > ,
87
+ pub style : String ,
88
+ pub clang_tidy_command : Option < PathBuf > ,
89
+ pub clang_format_command : Option < PathBuf > ,
90
+ pub tidy_filter : FileFilter ,
91
+ pub format_filter : FileFilter ,
89
92
}
90
93
91
94
/// This creates a task to run clang-tidy and clang-format on a single file.
@@ -100,104 +103,114 @@ fn analyze_single_file(
100
103
file : & mut Arc < Mutex < FileObj > > ,
101
104
clang_params : Arc < ClangParams > ,
102
105
) -> ( PathBuf , Vec < ( log:: Level , String ) > ) {
106
+ let file_lock = file. lock ( ) . unwrap ( ) ;
107
+ let file_name = file_lock. name . clone ( ) ;
108
+ drop ( file_lock) ;
103
109
let mut logs = vec ! [ ] ;
104
110
if let Some ( tidy_cmd) = & clang_params. clang_tidy_command {
105
- let tidy_result = run_clang_tidy (
106
- & mut Command :: new ( tidy_cmd) ,
107
- file,
108
- clang_params. tidy_checks . as_str ( ) ,
109
- & clang_params. lines_changed_only ,
110
- & clang_params. database ,
111
- & clang_params. extra_args ,
112
- & clang_params. database_json ,
113
- ) ;
114
- logs. extend ( tidy_result) ;
111
+ if clang_params
112
+ . tidy_filter
113
+ . is_source_or_ignored ( file_name. as_path ( ) )
114
+ {
115
+ let tidy_result = run_clang_tidy (
116
+ & mut Command :: new ( tidy_cmd) ,
117
+ file,
118
+ clang_params. tidy_checks . as_str ( ) ,
119
+ & clang_params. lines_changed_only ,
120
+ & clang_params. database ,
121
+ & clang_params. extra_args ,
122
+ & clang_params. database_json ,
123
+ ) ;
124
+ logs. extend ( tidy_result) ;
125
+ } else {
126
+ logs. push ( (
127
+ log:: Level :: Info ,
128
+ format ! (
129
+ "{} not scanned due to `--ignore-tidy`" ,
130
+ file_name. as_os_str( ) . to_string_lossy( )
131
+ ) ,
132
+ ) )
133
+ }
115
134
}
116
135
if let Some ( format_cmd) = & clang_params. clang_format_command {
117
- let format_result = run_clang_format (
118
- & mut Command :: new ( format_cmd) ,
119
- file,
120
- clang_params. style . as_str ( ) ,
121
- & clang_params. lines_changed_only ,
122
- ) ;
123
- logs. extend ( format_result) ;
136
+ if clang_params
137
+ . format_filter
138
+ . is_source_or_ignored ( file_name. as_path ( ) )
139
+ {
140
+ let format_result = run_clang_format (
141
+ & mut Command :: new ( format_cmd) ,
142
+ file,
143
+ clang_params. style . as_str ( ) ,
144
+ & clang_params. lines_changed_only ,
145
+ ) ;
146
+ logs. extend ( format_result) ;
147
+ } else {
148
+ logs. push ( (
149
+ log:: Level :: Info ,
150
+ format ! (
151
+ "{} not scanned by clang-format due to `--ignore-format`" ,
152
+ file_name. as_os_str( ) . to_string_lossy( )
153
+ ) ,
154
+ ) ) ;
155
+ }
124
156
}
125
- let file = file. lock ( ) . unwrap ( ) ;
126
- ( file. name . clone ( ) , logs)
157
+ ( file_name, logs)
127
158
}
128
159
129
160
/// Runs clang-tidy and/or clang-format and returns the parsed output from each.
130
161
///
131
- /// The returned list of [`FormatAdvice`] is parallel to the `files` list passed in
132
- /// here. The returned 2D list of [`TidyAdvice`] is also parallel on the first
133
- /// dimension. The second dimension is a list of notes specific to a translation unit
134
- /// (each element of `files`).
135
- ///
136
162
/// If `tidy_checks` is `"-*"` then clang-tidy is not executed.
137
163
/// If `style` is a blank string (`""`), then clang-format is not executed.
138
164
pub async fn capture_clang_tools_output (
139
165
files : & mut Vec < Arc < Mutex < FileObj > > > ,
140
166
version : & str ,
141
- tidy_checks : & str ,
142
- style : & str ,
143
- lines_changed_only : & LinesChangedOnly ,
144
- database : Option < PathBuf > ,
145
- extra_args : Option < Vec < String > > ,
167
+ clang_params : & mut ClangParams ,
146
168
) {
147
169
// find the executable paths for clang-tidy and/or clang-format and show version
148
170
// info as debugging output.
149
- let clang_tidy_command = if tidy_checks != "-*" {
150
- let cmd = get_clang_tool_exe ( "clang-tidy" , version) . unwrap ( ) ;
151
- log:: debug!(
152
- "{} --version\n {}" ,
153
- & cmd. to_string_lossy( ) ,
154
- String :: from_utf8_lossy( & Command :: new( & cmd) . arg( "--version" ) . output( ) . unwrap( ) . stdout)
155
- ) ;
156
- Some ( cmd)
157
- } else {
158
- None
171
+ if clang_params. tidy_checks != "-*" {
172
+ clang_params. clang_tidy_command = {
173
+ let cmd = get_clang_tool_exe ( "clang-tidy" , version) . unwrap ( ) ;
174
+ log:: debug!(
175
+ "{} --version\n {}" ,
176
+ & cmd. to_string_lossy( ) ,
177
+ String :: from_utf8_lossy(
178
+ & Command :: new( & cmd) . arg( "--version" ) . output( ) . unwrap( ) . stdout
179
+ )
180
+ ) ;
181
+ Some ( cmd)
182
+ }
159
183
} ;
160
- let clang_format_command = if !style. is_empty ( ) {
161
- let cmd = get_clang_tool_exe ( "clang-format" , version) . unwrap ( ) ;
162
- log:: debug!(
163
- "{} --version\n {}" ,
164
- & cmd. to_string_lossy( ) ,
165
- String :: from_utf8_lossy( & Command :: new( & cmd) . arg( "--version" ) . output( ) . unwrap( ) . stdout)
166
- ) ;
167
- Some ( cmd)
168
- } else {
169
- None
184
+ if !clang_params. style . is_empty ( ) {
185
+ clang_params. clang_format_command = {
186
+ let cmd = get_clang_tool_exe ( "clang-format" , version) . unwrap ( ) ;
187
+ log:: debug!(
188
+ "{} --version\n {}" ,
189
+ & cmd. to_string_lossy( ) ,
190
+ String :: from_utf8_lossy(
191
+ & Command :: new( & cmd) . arg( "--version" ) . output( ) . unwrap( ) . stdout
192
+ )
193
+ ) ;
194
+ Some ( cmd)
195
+ }
170
196
} ;
171
197
172
198
// parse database (if provided) to match filenames when parsing clang-tidy's stdout
173
- let database_json : Option < CompilationDatabase > = if let Some ( db_path) = & database {
199
+ if let Some ( db_path) = & clang_params . database {
174
200
if let Ok ( db_str) = fs:: read ( db_path) {
175
- Some (
201
+ clang_params . database_json = Some (
176
202
serde_json:: from_str :: < CompilationDatabase > (
177
203
String :: from_utf8 ( db_str) . unwrap ( ) . as_str ( ) ,
178
204
)
179
205
. unwrap ( ) ,
180
206
)
181
- } else {
182
- None
183
207
}
184
- } else {
185
- None
186
208
} ;
209
+
187
210
let mut executors = JoinSet :: new ( ) ;
188
211
// iterate over the discovered files and run the clang tools
189
212
for file in files {
190
- let clang_params = ClangParams {
191
- tidy_checks : tidy_checks. to_string ( ) ,
192
- lines_changed_only : lines_changed_only. clone ( ) ,
193
- database : database. clone ( ) ,
194
- extra_args : extra_args. clone ( ) ,
195
- database_json : database_json. clone ( ) ,
196
- style : style. to_string ( ) ,
197
- clang_tidy_command : clang_tidy_command. clone ( ) ,
198
- clang_format_command : clang_format_command. clone ( ) ,
199
- } ;
200
- let arc_params = Arc :: new ( clang_params) ;
213
+ let arc_params = Arc :: new ( clang_params. clone ( ) ) ;
201
214
let mut arc_file = Arc :: clone ( file) ;
202
215
executors. spawn ( async move { analyze_single_file ( & mut arc_file, arc_params) } ) ;
203
216
}
0 commit comments