Skip to content

Commit 3ffe78b

Browse files
authored
Some updates from py codebase (#5)
* encapsulate user inputs to post_feedback() * encapsulate `TidyNotification`s in a `TidyAdvice` struct * change data type returned on REST API calls * re-order feedback based on fallibility * use an enum to statically type `--lines-changed-only`
1 parent 03f3de5 commit 3ffe78b

File tree

10 files changed

+152
-104
lines changed

10 files changed

+152
-104
lines changed

.pre-commit-config.yaml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
repos:
22
- repo: https://github.com/pre-commit/pre-commit-hooks
3-
rev: v4.5.0
3+
rev: v4.6.0
44
hooks:
55
- id: trailing-whitespace
66
exclude: cpp-linter-lib/tests/capture_tools_output/cpp-linter/cpp-linter/test_git_lib.patch
@@ -14,7 +14,7 @@ repos:
1414
- id: mixed-line-ending
1515
args: ["--fix=lf"]
1616
- repo: https://github.com/astral-sh/ruff-pre-commit
17-
rev: v0.1.8
17+
rev: v0.5.2
1818
hooks:
1919
# Run the python linter.
2020
- id: ruff

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

+5-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use serde::Deserialize;
88
use serde_xml_rs::de::Deserializer;
99

1010
// project-specific crates/modules
11-
use crate::common_fs::{get_line_cols_from_offset, FileObj};
11+
use crate::{
12+
cli::LinesChangedOnly,
13+
common_fs::{get_line_cols_from_offset, FileObj},
14+
};
1215

1316
/// A Structure used to deserialize clang-format's XML output.
1417
#[derive(Debug, Deserialize, PartialEq)]
@@ -62,7 +65,7 @@ pub fn run_clang_format(
6265
cmd: &mut Command,
6366
file: &FileObj,
6467
style: &str,
65-
lines_changed_only: u8,
68+
lines_changed_only: &LinesChangedOnly,
6669
) -> FormatAdvice {
6770
cmd.args(["--style", style, "--output-replacements-xml"]);
6871
let ranges = file.get_ranges(lines_changed_only);

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

+29-6
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@ use regex::Regex;
1212
use serde::Deserialize;
1313

1414
// project-specific modules/crates
15-
use crate::common_fs::{normalize_path, FileObj};
15+
use crate::{
16+
cli::LinesChangedOnly,
17+
common_fs::{normalize_path, FileObj},
18+
};
1619

1720
/// Used to deserialize a JSON compilation database
1821
#[derive(Deserialize, Debug)]
@@ -68,14 +71,34 @@ pub struct TidyNotification {
6871
pub suggestion: Vec<String>,
6972
}
7073

74+
impl TidyNotification {
75+
pub fn diagnostic_link(&self) -> String {
76+
let ret_val = if let Some((category, name)) = self.diagnostic.split_once('-') {
77+
format!(
78+
"[{}](https://clang.llvm.org/extra/clang-tidy/checks/{category}/{name}).html",
79+
self.diagnostic
80+
)
81+
} else {
82+
self.diagnostic.clone()
83+
};
84+
ret_val
85+
}
86+
}
87+
88+
/// A struct to hold notification from clang-tidy about a single file
89+
pub struct TidyAdvice {
90+
/// A list of notifications parsed from clang-tidy stdout.
91+
pub notes: Vec<TidyNotification>,
92+
}
93+
7194
/// Parses clang-tidy stdout.
7295
///
7396
/// Here it helps to have the JSON database deserialized for normalizing paths present
7497
/// in the notifications.
7598
fn parse_tidy_output(
7699
tidy_stdout: &[u8],
77100
database_json: &Option<CompilationDatabase>,
78-
) -> Vec<TidyNotification> {
101+
) -> TidyAdvice {
79102
let note_header = Regex::new(r"^(.+):(\d+):(\d+):\s(\w+):(.*)\[([a-zA-Z\d\-\.]+)\]$").unwrap();
80103
let mut notification = None;
81104
let mut result = Vec::new();
@@ -141,19 +164,19 @@ fn parse_tidy_output(
141164
if let Some(note) = notification {
142165
result.push(note);
143166
}
144-
result
167+
TidyAdvice { notes: result }
145168
}
146169

147170
/// Run clang-tidy, then parse and return it's output.
148171
pub fn run_clang_tidy(
149172
cmd: &mut Command,
150173
file: &FileObj,
151174
checks: &str,
152-
lines_changed_only: u8,
175+
lines_changed_only: &LinesChangedOnly,
153176
database: &Option<PathBuf>,
154177
extra_args: &Option<Vec<&str>>,
155178
database_json: &Option<CompilationDatabase>,
156-
) -> Vec<TidyNotification> {
179+
) -> TidyAdvice {
157180
if !checks.is_empty() {
158181
cmd.args(["-checks", checks]);
159182
}
@@ -165,7 +188,7 @@ pub fn run_clang_tidy(
165188
cmd.args(["--extra-arg", format!("\"{}\"", arg).as_str()]);
166189
}
167190
}
168-
if lines_changed_only > 0 {
191+
if *lines_changed_only != LinesChangedOnly::Off {
169192
let ranges = file.get_ranges(lines_changed_only);
170193
let filter = format!(
171194
"[{{\"name\":{:?},\"lines\":{:?}}}]",

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

+10-8
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,14 @@ use which::{which, which_in};
1010

1111
// project-specific modules/crates
1212
use super::common_fs::FileObj;
13-
use crate::logger::{end_log_group, start_log_group};
13+
use crate::{
14+
cli::LinesChangedOnly,
15+
logger::{end_log_group, start_log_group},
16+
};
1417
pub mod clang_format;
1518
use clang_format::{run_clang_format, FormatAdvice};
1619
pub mod clang_tidy;
17-
use clang_tidy::{run_clang_tidy, CompilationDatabase, TidyNotification};
20+
use clang_tidy::{run_clang_tidy, CompilationDatabase, TidyAdvice};
1821

1922
/// Fetch the path to a clang tool by `name` (ie `"clang-tidy"` or `"clang-format"`) and
2023
/// `version`.
@@ -69,7 +72,7 @@ pub fn get_clang_tool_exe(name: &str, version: &str) -> Result<PathBuf, &'static
6972
/// Runs clang-tidy and/or clang-format and returns the parsed output from each.
7073
///
7174
/// The returned list of [`FormatAdvice`] is parallel to the `files` list passed in
72-
/// here. The returned 2D list of [`TidyNotification`] is also parallel on the first
75+
/// here. The returned 2D list of [`TidyAdvice`] is also parallel on the first
7376
/// dimension. The second dimension is a list of notes specific to a translation unit
7477
/// (each element of `files`).
7578
///
@@ -80,10 +83,10 @@ pub fn capture_clang_tools_output(
8083
version: &str,
8184
tidy_checks: &str,
8285
style: &str,
83-
lines_changed_only: u8,
86+
lines_changed_only: &LinesChangedOnly,
8487
database: Option<PathBuf>,
8588
extra_args: Option<Vec<&str>>,
86-
) -> (Vec<FormatAdvice>, Vec<Vec<TidyNotification>>) {
89+
) -> (Vec<FormatAdvice>, Vec<TidyAdvice>) {
8790
// find the executable paths for clang-tidy and/or clang-format and show version
8891
// info as debugging output.
8992
let clang_tidy_command = if tidy_checks != "-*" {
@@ -126,9 +129,8 @@ pub fn capture_clang_tools_output(
126129
};
127130

128131
// iterate over the discovered files and run the clang tools
129-
let mut all_format_advice: Vec<clang_format::FormatAdvice> = Vec::with_capacity(files.len());
130-
let mut all_tidy_advice: Vec<Vec<clang_tidy::TidyNotification>> =
131-
Vec::with_capacity(files.len());
132+
let mut all_format_advice: Vec<FormatAdvice> = Vec::with_capacity(files.len());
133+
let mut all_tidy_advice: Vec<TidyAdvice> = Vec::with_capacity(files.len());
132134
for file in files {
133135
start_log_group(format!("Analyzing {}", file.name.to_string_lossy()));
134136
if let Some(tidy_cmd) = &clang_tidy_command {

cpp-linter-lib/src/cli.rs

+11
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ use std::fs;
66
use clap::builder::FalseyValueParser;
77
use clap::{Arg, ArgAction, ArgMatches, Command};
88

9+
/// An enum to describe `--lines-changed-only` CLI option's behavior.
10+
#[derive(PartialEq)]
11+
pub enum LinesChangedOnly {
12+
/// All lines are scanned
13+
Off,
14+
/// Only lines in the diff are scanned
15+
Diff,
16+
/// Only lines in the diff with additions are scanned.
17+
On,
18+
}
19+
920
/// Builds and returns the Command Line Interface's argument parsing object.
1021
pub fn get_arg_parser() -> Command {
1122
Command::new("cpp-linter")

cpp-linter-lib/src/common_fs.rs

+12-11
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ use std::path::{Component, Path};
55
use std::{fs, io};
66
use std::{ops::RangeInclusive, path::PathBuf};
77

8+
use crate::cli::LinesChangedOnly;
9+
810
/// A structure to represent a file's path and line changes.
911
#[derive(Debug)]
1012
pub struct FileObj {
@@ -52,7 +54,7 @@ impl FileObj {
5254
/// A helper function to consolidate a [Vec<u32>] of line numbers into a
5355
/// [Vec<RangeInclusive<u32>>] in which each range describes the beginning and
5456
/// ending of a group of consecutive line numbers.
55-
fn consolidate_numbers_to_ranges(lines: &Vec<u32>) -> Vec<RangeInclusive<u32>> {
57+
fn consolidate_numbers_to_ranges(lines: &[u32]) -> Vec<RangeInclusive<u32>> {
5658
let mut range_start = None;
5759
let mut ranges: Vec<RangeInclusive<u32>> = Vec::new();
5860
for (index, number) in lines.iter().enumerate() {
@@ -69,13 +71,11 @@ impl FileObj {
6971
ranges
7072
}
7173

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()
74+
pub fn get_ranges(&self, lines_changed_only: &LinesChangedOnly) -> Vec<RangeInclusive<u32>> {
75+
match lines_changed_only {
76+
LinesChangedOnly::Diff => self.diff_chunks.to_vec(),
77+
LinesChangedOnly::On => self.added_ranges.to_vec(),
78+
_ => Vec::new(),
7979
}
8080
}
8181
}
@@ -249,6 +249,7 @@ mod test {
249249
use std::path::PathBuf;
250250

251251
use super::{get_line_cols_from_offset, list_source_files, normalize_path, FileObj};
252+
use crate::cli::LinesChangedOnly;
252253
use crate::cli::{get_arg_parser, parse_ignore};
253254
use crate::common_fs::is_file_in_list;
254255

@@ -406,7 +407,7 @@ mod test {
406407
#[test]
407408
fn get_ranges_0() {
408409
let file_obj = FileObj::new(PathBuf::from("tests/demo/demo.cpp"));
409-
let ranges = file_obj.get_ranges(0);
410+
let ranges = file_obj.get_ranges(&LinesChangedOnly::Off);
410411
assert!(ranges.is_empty());
411412
}
412413

@@ -419,7 +420,7 @@ mod test {
419420
added_lines,
420421
diff_chunks.clone(),
421422
);
422-
let ranges = file_obj.get_ranges(2);
423+
let ranges = file_obj.get_ranges(&LinesChangedOnly::Diff);
423424
assert_eq!(ranges, diff_chunks);
424425
}
425426

@@ -432,7 +433,7 @@ mod test {
432433
added_lines,
433434
diff_chunks,
434435
);
435-
let ranges = file_obj.get_ranges(1);
436+
let ranges = file_obj.get_ranges(&LinesChangedOnly::On);
436437
assert_eq!(ranges, vec![4..=5, 9..=9]);
437438
}
438439
}

0 commit comments

Comments
 (0)