Skip to content

Commit 007475b

Browse files
javabstermeta-codesync[bot]
authored andcommitted
Phase 4: Multi-tool suppression parsing
Summary: Phase 4 of the typestats migration plan (D96957977). **What changed:** - Replaced the hardcoded regex-based suppression parser (which only matched `# pyrefly: ignore[…]`) with the multi-tool parser from `pyrefly_python::ignore::Ignore`. - The report now recognises suppression comments from seven tools: `# type: ignore`, `# pyrefly: ignore`, `# pyright: ignore`, `# mypy: type: ignore`, `# pyre-fixme`, `# ty: ignore`, and `# zuban: ignore`. - Renamed the struct from `Suppression` to `ReportSuppression` for clarity. - The `kind` field now contains the originating tool name (e.g. `"pyrefly"`, `"type"`, `"mypy"`) instead of the previous hardcoded `"ignore"`. - Removed the `regex` crate dependency from this module. **Files changed:** - `report.rs`: rewrote `parse_suppressions`, renamed struct, updated imports. - `suppressions.expected.json`: updated `kind` from `"ignore"` to `"pyrefly"`. Reviewed By: yangdanny97 Differential Revision: D98536947 fbshipit-source-id: 91b6af70394608a646d47a854a47594ccb21de5b
1 parent 234dc5d commit 007475b

2 files changed

Lines changed: 33 additions & 37 deletions

File tree

pyrefly/lib/commands/report.rs

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ use clap::Parser;
1414
use pyrefly_build::handle::Handle;
1515
use pyrefly_config::args::ConfigOverrideArgs;
1616
use pyrefly_config::finder::ConfigFinder;
17+
use pyrefly_python::ignore::Ignore;
18+
use pyrefly_python::ignore::Tool;
1719
use pyrefly_python::module::Module;
1820
use pyrefly_python::module_name::ModuleName;
1921
use pyrefly_python::nesting_context::NestingContext;
@@ -23,7 +25,6 @@ use pyrefly_types::types::Type;
2325
use pyrefly_util::forgetter::Forgetter;
2426
use pyrefly_util::includes::Includes;
2527
use pyrefly_util::thread_pool::ThreadCount;
26-
use regex::Regex;
2728
use ruff_python_ast::Parameters;
2829
use ruff_python_ast::name::Name;
2930
use ruff_text_size::Ranged;
@@ -70,10 +71,11 @@ struct Parameter {
7071
location: Location,
7172
}
7273

73-
/// Suppression information
74+
/// Renamed from `Suppression` to avoid collision with `pyrefly_python::ignore::Suppression`.
7475
#[derive(Debug, Serialize)]
75-
struct Suppression {
76-
kind: String,
76+
struct ReportSuppression {
77+
/// The suppression tool (e.g. pyrefly, mypy, pyre).
78+
kind: Tool,
7779
codes: Vec<String>,
7880
location: Location,
7981
}
@@ -122,7 +124,7 @@ struct FileReport {
122124
line_count: usize,
123125
functions: Vec<Function>,
124126
classes: Vec<ReportClass>,
125-
suppressions: Vec<Suppression>,
127+
suppressions: Vec<ReportSuppression>,
126128
/// Percentage of functions that are fully annotated (0.0 to 100.0).
127129
/// A function is fully annotated if it has return and parameter annotations present.
128130
annotation_completeness: f64,
@@ -212,40 +214,34 @@ impl ReportArgs {
212214
}
213215
}
214216

215-
/// Helper to parse suppression comments from source code
216-
fn parse_suppressions(module: &Module) -> Vec<Suppression> {
217-
let regex = Regex::new(r"#\s*pyrefly:\s*ignore\s*\[([^\]]*)\]").unwrap();
217+
/// Parse type-ignore suppressions from source using the multi-tool parser from `ignore.rs`.
218+
fn parse_suppressions(module: &Module) -> Vec<ReportSuppression> {
218219
let source = module.lined_buffer().contents();
220+
let ignore = Ignore::new(source);
221+
219222
let lines: Vec<&str> = source.lines().collect();
220223
let mut suppressions = Vec::new();
221224

222-
for (line_idx, line) in lines.iter().enumerate() {
223-
if let Some(caps) = regex.captures(line) {
224-
let codes: Vec<String> = caps
225-
.get(1)
226-
.map(|m| {
227-
m.as_str()
228-
.split(',')
229-
.map(|s| s.trim().to_owned())
230-
.filter(|s| !s.is_empty())
231-
.collect()
232-
})
233-
.unwrap_or_default();
234-
235-
// Find the position of the comment in the line
236-
if let Some(comment_start) = line.find('#') {
237-
let line_number = line_idx + 1; // 1-indexed
238-
let start_col = comment_start + 1; // 1-indexed column
239-
240-
suppressions.push(Suppression {
241-
kind: "ignore".to_owned(),
242-
codes,
243-
location: Location {
244-
line: line_number,
245-
column: start_col,
246-
},
247-
});
248-
}
225+
for (_line_number, supps) in ignore.iter() {
226+
for supp in supps {
227+
let comment_line_num = supp.comment_line().get() as usize;
228+
let column = comment_line_num
229+
.checked_sub(1)
230+
.and_then(|idx| lines.get(idx))
231+
.and_then(|line| line.find('#'))
232+
.map(|c| c + 1);
233+
let Some(column) = column else {
234+
continue;
235+
};
236+
237+
suppressions.push(ReportSuppression {
238+
kind: supp.tool(),
239+
codes: supp.error_codes().to_vec(),
240+
location: Location {
241+
line: comment_line_num,
242+
column,
243+
},
244+
});
249245
}
250246
}
251247

pyrefly/lib/test/report/test_files/suppressions.expected.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@
3030
"classes": [],
3131
"suppressions": [
3232
{
33-
"kind": "ignore",
33+
"kind": "pyrefly",
3434
"codes": [
3535
"error-code"
3636
],
@@ -40,7 +40,7 @@
4040
}
4141
},
4242
{
43-
"kind": "ignore",
43+
"kind": "pyrefly",
4444
"codes": [
4545
"code1",
4646
"code2"

0 commit comments

Comments
 (0)