Skip to content

Commit 55ea094

Browse files
authored
[red-knot] Allow any Ranged argument for report_lint and report_diagnostic (#16252)
1 parent 3032867 commit 55ea094

File tree

6 files changed

+235
-220
lines changed

6 files changed

+235
-220
lines changed

crates/red_knot_python_semantic/src/types.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -2264,11 +2264,7 @@ impl<'db> InvalidTypeExpressionError<'db> {
22642264
invalid_expressions,
22652265
} = self;
22662266
for error in invalid_expressions {
2267-
context.report_lint(
2268-
&INVALID_TYPE_FORM,
2269-
node.into(),
2270-
format_args!("{}", error.reason()),
2271-
);
2267+
context.report_lint(&INVALID_TYPE_FORM, node, format_args!("{}", error.reason()));
22722268
}
22732269
fallback_type
22742270
}

crates/red_knot_python_semantic/src/types/context.rs

+45-30
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ use ruff_db::{
55
diagnostic::{DiagnosticId, SecondaryDiagnosticMessage, Severity},
66
files::File,
77
};
8-
use ruff_python_ast::AnyNodeRef;
9-
use ruff_text_size::Ranged;
8+
use ruff_text_size::{Ranged, TextRange};
109

1110
use super::{binding_type, KnownFunction, TypeCheckDiagnostic, TypeCheckDiagnostics};
1211

@@ -67,46 +66,60 @@ impl<'db> InferContext<'db> {
6766
self.diagnostics.get_mut().extend(other.diagnostics());
6867
}
6968

70-
/// Reports a lint located at `node`.
71-
pub(super) fn report_lint(
69+
/// Reports a lint located at `ranged`.
70+
pub(super) fn report_lint<T>(
7271
&self,
7372
lint: &'static LintMetadata,
74-
node: AnyNodeRef,
73+
ranged: T,
7574
message: fmt::Arguments,
76-
) {
77-
self.report_lint_with_secondary_messages(lint, node, message, vec![]);
75+
) where
76+
T: Ranged,
77+
{
78+
self.report_lint_with_secondary_messages(lint, ranged, message, vec![]);
7879
}
7980

80-
/// Reports a lint located at `node`.
81-
pub(super) fn report_lint_with_secondary_messages(
81+
/// Reports a lint located at `ranged`.
82+
pub(super) fn report_lint_with_secondary_messages<T>(
8283
&self,
8384
lint: &'static LintMetadata,
84-
node: AnyNodeRef,
85+
ranged: T,
8586
message: fmt::Arguments,
8687
secondary_messages: Vec<SecondaryDiagnosticMessage>,
87-
) {
88-
if !self.db.is_file_open(self.file) {
89-
return;
90-
}
88+
) where
89+
T: Ranged,
90+
{
91+
fn lint_severity(
92+
context: &InferContext,
93+
lint: &'static LintMetadata,
94+
range: TextRange,
95+
) -> Option<Severity> {
96+
if !context.db.is_file_open(context.file) {
97+
return None;
98+
}
9199

92-
// Skip over diagnostics if the rule is disabled.
93-
let Some(severity) = self.db.rule_selection().severity(LintId::of(lint)) else {
94-
return;
95-
};
100+
// Skip over diagnostics if the rule is disabled.
101+
let severity = context.db.rule_selection().severity(LintId::of(lint))?;
96102

97-
if self.is_in_no_type_check() {
98-
return;
99-
}
103+
if context.is_in_no_type_check() {
104+
return None;
105+
}
100106

101-
let suppressions = suppressions(self.db, self.file);
107+
let suppressions = suppressions(context.db, context.file);
102108

103-
if let Some(suppression) = suppressions.find_suppression(node.range(), LintId::of(lint)) {
104-
self.diagnostics.borrow_mut().mark_used(suppression.id());
105-
return;
109+
if let Some(suppression) = suppressions.find_suppression(range, LintId::of(lint)) {
110+
context.diagnostics.borrow_mut().mark_used(suppression.id());
111+
return None;
112+
}
113+
114+
Some(severity)
106115
}
107116

117+
let Some(severity) = lint_severity(self, lint, ranged.range()) else {
118+
return;
119+
};
120+
108121
self.report_diagnostic(
109-
node,
122+
ranged,
110123
DiagnosticId::Lint(lint.name()),
111124
severity,
112125
message,
@@ -117,14 +130,16 @@ impl<'db> InferContext<'db> {
117130
/// Adds a new diagnostic.
118131
///
119132
/// The diagnostic does not get added if the rule isn't enabled for this file.
120-
pub(super) fn report_diagnostic(
133+
pub(super) fn report_diagnostic<T>(
121134
&self,
122-
node: AnyNodeRef,
135+
ranged: T,
123136
id: DiagnosticId,
124137
severity: Severity,
125138
message: fmt::Arguments,
126139
secondary_messages: Vec<SecondaryDiagnosticMessage>,
127-
) {
140+
) where
141+
T: Ranged,
142+
{
128143
if !self.db.is_file_open(self.file) {
129144
return;
130145
}
@@ -139,7 +154,7 @@ impl<'db> InferContext<'db> {
139154
file: self.file,
140155
id,
141156
message: message.to_string(),
142-
range: node.range(),
157+
range: ranged.range(),
143158
severity,
144159
secondary_messages,
145160
});

crates/red_knot_python_semantic/src/types/diagnostic.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ pub(super) fn report_possibly_unresolved_reference(
10471047

10481048
context.report_lint(
10491049
&POSSIBLY_UNRESOLVED_REFERENCE,
1050-
expr_name_node.into(),
1050+
expr_name_node,
10511051
format_args!("Name `{id}` used when possibly not defined"),
10521052
);
10531053
}
@@ -1057,15 +1057,15 @@ pub(super) fn report_unresolved_reference(context: &InferContext, expr_name_node
10571057

10581058
context.report_lint(
10591059
&UNRESOLVED_REFERENCE,
1060-
expr_name_node.into(),
1060+
expr_name_node,
10611061
format_args!("Name `{id}` used when not defined"),
10621062
);
10631063
}
10641064

10651065
pub(super) fn report_invalid_exception_caught(context: &InferContext, node: &ast::Expr, ty: Type) {
10661066
context.report_lint(
10671067
&INVALID_EXCEPTION_CAUGHT,
1068-
node.into(),
1068+
node,
10691069
format_args!(
10701070
"Cannot catch object of type `{}` in an exception handler \
10711071
(must be a `BaseException` subclass or a tuple of `BaseException` subclasses)",
@@ -1077,7 +1077,7 @@ pub(super) fn report_invalid_exception_caught(context: &InferContext, node: &ast
10771077
pub(crate) fn report_invalid_exception_raised(context: &InferContext, node: &ast::Expr, ty: Type) {
10781078
context.report_lint(
10791079
&INVALID_RAISE,
1080-
node.into(),
1080+
node,
10811081
format_args!(
10821082
"Cannot raise object of type `{}` (must be a `BaseException` subclass or instance)",
10831083
ty.display(context.db())
@@ -1088,7 +1088,7 @@ pub(crate) fn report_invalid_exception_raised(context: &InferContext, node: &ast
10881088
pub(crate) fn report_invalid_exception_cause(context: &InferContext, node: &ast::Expr, ty: Type) {
10891089
context.report_lint(
10901090
&INVALID_RAISE,
1091-
node.into(),
1091+
node,
10921092
format_args!(
10931093
"Cannot use object of type `{}` as exception cause \
10941094
(must be a `BaseException` subclass or instance or `None`)",
@@ -1100,7 +1100,7 @@ pub(crate) fn report_invalid_exception_cause(context: &InferContext, node: &ast:
11001100
pub(crate) fn report_base_with_incompatible_slots(context: &InferContext, node: &ast::Expr) {
11011101
context.report_lint(
11021102
&INCOMPATIBLE_SLOTS,
1103-
node.into(),
1103+
node,
11041104
format_args!("Class base has incompatible `__slots__`"),
11051105
);
11061106
}
@@ -1112,7 +1112,7 @@ pub(crate) fn report_invalid_arguments_to_annotated<'db>(
11121112
) {
11131113
context.report_lint(
11141114
&INVALID_TYPE_FORM,
1115-
subscript.into(),
1115+
subscript,
11161116
format_args!(
11171117
"Special form `{}` expected at least 2 arguments (one type and at least one metadata element)",
11181118
KnownInstanceType::Annotated.repr(db)

0 commit comments

Comments
 (0)