Skip to content

Commit 19d5517

Browse files
committed
refactor line filters; minor metadata updates
- moved clang-format advice filtering by lines into `run_clang_format()` - abstracted line ranges selection into `FileObj::get_ranges()` (& added tests) - update README link to Apache 2.0 License - update git-ignored cache folder name - update dev-dependency version of tempfile crate - adjust RestApiClient function signatures for posting feedback, now that line filtering is done beforehand - also fix a typo in the cfg attr filter (about openssl-vendored feature)
1 parent ff4a735 commit 19d5517

File tree

9 files changed

+119
-78
lines changed

9 files changed

+119
-78
lines changed

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,5 +195,5 @@ Cargo.lock
195195

196196

197197
# ignore generated files
198-
.cpp_linter_cache/
198+
.cpp-linter_cache/
199199
cpp-linter-py/docs/cli_args.rst

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,4 +49,4 @@ The python binding uses
4949
- [pyo3](https://crates.io/crates/pyo3): Dual-licensed under [Apache 2.0][Apache2] or [MIT][MIT].
5050

5151
[MIT]: https://choosealicense.com/licenses/mit
52-
[Apache2]: https://github.com/clap-rs/clap/blob/HEAD/LICENSE-APACHE
52+
[Apache2]: https://choosealicense.com/licenses/apache-2.0/

cpp-linter-lib/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ serde_json = "1.0.108"
2323
which = "5.0.0"
2424

2525
[dev-dependencies]
26-
tempfile = "3.8.1"
26+
tempfile = "3.9.0"
2727

2828
[features]
2929
openssl-vendored = ["dep:openssl", "dep:openssl-probe"]

cpp-linter-lib/src/clang_tools/clang_format.rs

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ pub struct Replacement {
4545
pub cols: Option<usize>,
4646
}
4747

48+
impl Clone for Replacement {
49+
fn clone(&self) -> Self {
50+
Replacement {
51+
offset: self.offset,
52+
length: self.length,
53+
value: self.value.clone(),
54+
line: self.line,
55+
cols: self.cols,
56+
}
57+
}
58+
}
59+
4860
/// Run clang-tidy for a specific `file`, then parse and return it's XML output.
4961
pub fn run_clang_format(
5062
cmd: &mut Command,
@@ -53,15 +65,9 @@ pub fn run_clang_format(
5365
lines_changed_only: u8,
5466
) -> FormatAdvice {
5567
cmd.args(["--style", style, "--output-replacements-xml"]);
56-
if lines_changed_only > 0 {
57-
let ranges = if lines_changed_only == 2 {
58-
&file.diff_chunks
59-
} else {
60-
&file.added_ranges
61-
};
62-
for range in ranges {
63-
cmd.arg(format!("--lines={}:{}", range.start(), range.end()));
64-
}
68+
let ranges = file.get_ranges(lines_changed_only);
69+
for range in &ranges {
70+
cmd.arg(format!("--lines={}:{}", range.start(), range.end()));
6571
}
6672
cmd.arg(file.name.to_string_lossy().as_ref());
6773
log::info!(
@@ -103,11 +109,23 @@ pub fn run_clang_format(
103109
replacements: vec![],
104110
});
105111
if !format_advice.replacements.is_empty() {
112+
let mut filtered_replacements = Vec::new();
106113
for replacement in &mut format_advice.replacements {
107114
let (line_number, columns) = get_line_cols_from_offset(&file.name, replacement.offset);
108115
replacement.line = Some(line_number);
109116
replacement.cols = Some(columns);
117+
for range in &ranges {
118+
if range.contains(&line_number.try_into().unwrap_or(0)) {
119+
filtered_replacements.push(replacement.clone());
120+
break;
121+
}
122+
}
123+
if ranges.is_empty() {
124+
// lines_changed_only is disabled
125+
filtered_replacements.push(replacement.clone());
126+
}
110127
}
128+
format_advice.replacements = filtered_replacements;
111129
}
112130
format_advice
113131
}

cpp-linter-lib/src/clang_tools/clang_tidy.rs

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -144,30 +144,6 @@ fn parse_tidy_output(
144144
result
145145
}
146146

147-
#[cfg(test)]
148-
mod test {
149-
#[test]
150-
fn test_capture() {
151-
let src = "tests/demo/demo.hpp:11:11: warning: use a trailing return type for this function [modernize-use-trailing-return-type]";
152-
let pat =
153-
regex::Regex::new(r"^(.+):(\d+):(\d+):\s(\w+):(.*)\[([a-zA-Z\d\-\.]+)\]$").unwrap();
154-
let cap = pat.captures(src).unwrap();
155-
assert_eq!(
156-
cap.get(0).unwrap().as_str(),
157-
format!(
158-
"{}:{}:{}: {}:{}[{}]",
159-
cap.get(1).unwrap().as_str(),
160-
cap.get(2).unwrap().as_str(),
161-
cap.get(3).unwrap().as_str(),
162-
cap.get(4).unwrap().as_str(),
163-
cap.get(5).unwrap().as_str(),
164-
cap.get(6).unwrap().as_str()
165-
)
166-
.as_str()
167-
)
168-
}
169-
}
170-
171147
/// Run clang-tidy, then parse and return it's output.
172148
pub fn run_clang_tidy(
173149
cmd: &mut Command,
@@ -190,11 +166,7 @@ pub fn run_clang_tidy(
190166
}
191167
}
192168
if lines_changed_only > 0 {
193-
let ranges = if lines_changed_only == 2 {
194-
&file.diff_chunks
195-
} else {
196-
&file.added_ranges
197-
};
169+
let ranges = file.get_ranges(lines_changed_only);
198170
let filter = format!(
199171
"[{{\"name\":{:?},\"lines\":{:?}}}]",
200172
&file
@@ -230,3 +202,27 @@ pub fn run_clang_tidy(
230202
}
231203
parse_tidy_output(&output.stdout, database_json)
232204
}
205+
206+
#[cfg(test)]
207+
mod test {
208+
#[test]
209+
fn test_capture() {
210+
let src = "tests/demo/demo.hpp:11:11: warning: use a trailing return type for this function [modernize-use-trailing-return-type]";
211+
let pat =
212+
regex::Regex::new(r"^(.+):(\d+):(\d+):\s(\w+):(.*)\[([a-zA-Z\d\-\.]+)\]$").unwrap();
213+
let cap = pat.captures(src).unwrap();
214+
assert_eq!(
215+
cap.get(0).unwrap().as_str(),
216+
format!(
217+
"{}:{}:{}: {}:{}[{}]",
218+
cap.get(1).unwrap().as_str(),
219+
cap.get(2).unwrap().as_str(),
220+
cap.get(3).unwrap().as_str(),
221+
cap.get(4).unwrap().as_str(),
222+
cap.get(5).unwrap().as_str(),
223+
cap.get(6).unwrap().as_str()
224+
)
225+
.as_str()
226+
)
227+
}
228+
}

cpp-linter-lib/src/common_fs.rs

Lines changed: 56 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,16 @@ impl FileObj {
6868
}
6969
ranges
7070
}
71+
72+
pub fn get_ranges(&self, lines_changed_only: u8) -> Vec<RangeInclusive<u32>> {
73+
if lines_changed_only == 2 {
74+
self.diff_chunks.to_vec()
75+
} else if lines_changed_only == 1 {
76+
self.added_ranges.to_vec()
77+
} else {
78+
Vec::new()
79+
}
80+
}
7181
}
7282

7383
/// Describes if a specified `file_name` is contained within the given `set` of paths.
@@ -234,12 +244,16 @@ pub fn normalize_path(path: &Path) -> PathBuf {
234244

235245
#[cfg(test)]
236246
mod test {
237-
238-
// *********************** tests for normalized paths
239-
use super::{list_source_files, normalize_path};
240247
use std::env::current_dir;
248+
use std::env::set_current_dir;
241249
use std::path::PathBuf;
242250

251+
use super::{get_line_cols_from_offset, list_source_files, normalize_path, FileObj};
252+
use crate::cli::{get_arg_parser, parse_ignore};
253+
use crate::common_fs::is_file_in_list;
254+
255+
// *********************** tests for normalized paths
256+
243257
#[test]
244258
fn normalize_redirects() {
245259
let mut src = current_dir().unwrap();
@@ -274,9 +288,6 @@ mod test {
274288
}
275289

276290
// ************* tests for ignored paths
277-
use crate::cli::{get_arg_parser, parse_ignore};
278-
use crate::common_fs::is_file_in_list;
279-
use std::env::set_current_dir;
280291

281292
fn setup_ignore(input: &str) -> (Vec<String>, Vec<String>) {
282293
let arg_parser = get_arg_parser();
@@ -359,6 +370,8 @@ mod test {
359370
));
360371
}
361372

373+
// *********************** tests for recursive path search
374+
362375
#[test]
363376
fn walk_dir_recursively() {
364377
let (ignored, not_ignored) = setup_ignore("target");
@@ -378,12 +391,48 @@ mod test {
378391
}
379392
}
380393

381-
use super::get_line_cols_from_offset;
394+
// *********************** tests for translating byte offset into line/column
395+
382396
#[test]
383397
fn translate_byte_offset() {
384398
let (lines, cols) = get_line_cols_from_offset(&PathBuf::from("tests/demo/demo.cpp"), 144);
385399
println!("lines: {lines}, cols: {cols}");
386400
assert_eq!(lines, 13);
387401
assert_eq!(cols, 5);
388402
}
403+
404+
// *********************** tests for FileObj::get_ranges()
405+
406+
#[test]
407+
fn get_ranges_0() {
408+
let file_obj = FileObj::new(PathBuf::from("tests/demo/demo.cpp"));
409+
let ranges = file_obj.get_ranges(0);
410+
assert!(ranges.is_empty());
411+
}
412+
413+
#[test]
414+
fn get_ranges_2() {
415+
let diff_chunks = vec![1..=10];
416+
let added_lines = vec![4, 5, 9];
417+
let file_obj = FileObj::from(
418+
PathBuf::from("tests/demo/demo.cpp"),
419+
added_lines,
420+
diff_chunks.clone(),
421+
);
422+
let ranges = file_obj.get_ranges(2);
423+
assert_eq!(ranges, diff_chunks);
424+
}
425+
426+
#[test]
427+
fn get_ranges_1() {
428+
let diff_chunks = vec![1..=10];
429+
let added_lines = vec![4, 5, 9];
430+
let file_obj = FileObj::from(
431+
PathBuf::from("tests/demo/demo.cpp"),
432+
added_lines,
433+
diff_chunks,
434+
);
435+
let ranges = file_obj.get_ranges(1);
436+
assert_eq!(ranges, vec![4..=5, 9..=9]);
437+
}
389438
}

cpp-linter-lib/src/rest_api/github_api.rs

Lines changed: 5 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,6 @@ impl RestApiClient for GithubApiClient {
193193
step_summary: bool,
194194
file_annotations: bool,
195195
style: &str,
196-
lines_changed_only: u8,
197196
) {
198197
let (comment, format_checks_failed, tidy_checks_failed) =
199198
self.make_comment(files, format_advice, tidy_advice);
@@ -248,7 +247,7 @@ impl RestApiClient for GithubApiClient {
248247
}
249248
}
250249
if file_annotations {
251-
self.post_annotations(files, format_advice, tidy_advice, style, lines_changed_only);
250+
self.post_annotations(files, format_advice, tidy_advice, style);
252251
}
253252
if step_summary {
254253
self.post_step_summary(&comment);
@@ -280,7 +279,6 @@ impl GithubApiClient {
280279
format_advice: &[FormatAdvice],
281280
tidy_advice: &[Vec<TidyNotification>],
282281
style: &str,
283-
lines_changed_only: u8,
284282
) {
285283
if !format_advice.is_empty() {
286284
// formalize the style guide name
@@ -298,36 +296,18 @@ impl GithubApiClient {
298296
String::from("Custom")
299297
};
300298

301-
// iterate over clang-format and post applicable annotations (according to line filtering)
299+
// iterate over clang-format advice and post annotations
302300
for (index, advice) in format_advice.iter().enumerate() {
303-
// get the ranges of lines for the corresponding file
304-
let ranges = if lines_changed_only == 0 {
305-
None
306-
} else if lines_changed_only == 1 {
307-
Some(&files[index].added_ranges)
308-
} else {
309-
Some(&files[index].diff_chunks)
310-
};
311-
312-
// assemble a list of line numbers (as strings)
301+
// assemble a list of line numbers
313302
let mut lines: Vec<usize> = Vec::new();
314303
for replacement in &advice.replacements {
315304
if let Some(line_int) = replacement.line {
316305
if !lines.contains(&line_int) {
317-
if let Some(line_ranges) = ranges {
318-
for line_range in line_ranges {
319-
if line_range.contains(&line_int.try_into().unwrap()) {
320-
lines.push(line_int);
321-
break;
322-
}
323-
}
324-
} else {
325-
lines.push(line_int);
326-
}
306+
lines.push(line_int);
327307
}
328308
}
329309
}
330-
// post annotation if any applicable lines were format
310+
// post annotation if any applicable lines were formatted
331311
if !lines.is_empty() {
332312
println!(
333313
"::notice file={name},title=Run clang-format on {name}::File {name} does not conform to {style_guide} style guidelines. (lines {line_set})",

cpp-linter-lib/src/rest_api/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,5 @@ pub trait RestApiClient {
133133
step_summary: bool,
134134
file_annotations: bool,
135135
style: &str,
136-
lines_changed_only: u8,
137136
);
138137
}

cpp-linter-lib/src/run.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::path::{Path, PathBuf};
88

99
// non-std crates
1010
use log::{set_max_level, LevelFilter};
11-
#[cfg(features = "openssl-vendored")]
11+
#[cfg(feature = "openssl-vendored")]
1212
use openssl_probe;
1313

1414
// project specific modules/crates
@@ -19,12 +19,12 @@ use crate::github_api::GithubApiClient;
1919
use crate::logger::{self, end_log_group, start_log_group};
2020
use crate::rest_api::RestApiClient;
2121

22-
#[cfg(features = "openssl-vendored")]
22+
#[cfg(feature = "openssl-vendored")]
2323
fn probe_ssl_certs() {
2424
openssl_probe::init_ssl_cert_env_vars();
2525
}
2626

27-
#[cfg(not(openssl_probe))]
27+
#[cfg(not(feature = "openssl-vendored"))]
2828
fn probe_ssl_certs() {}
2929

3030
/// This is the backend entry point for console applications.
@@ -139,7 +139,6 @@ pub fn run_main(args: Vec<String>) -> i32 {
139139
step_summary,
140140
file_annotations,
141141
style,
142-
lines_changed_only,
143142
);
144143
end_log_group();
145144
0

0 commit comments

Comments
 (0)