Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rename applicability levels to Safe, Unsafe, and Display #7843

Merged
merged 1 commit into from
Oct 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/ruff_cli/tests/format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ import os
},
"filename": "-",
"fix": {
"applicability": "always",
"applicability": "safe",
"edits": [
{
"content": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ exit_code: 1
},
"filename": "/path/to/F401.py",
"fix": {
"applicability": "always",
"applicability": "safe",
"edits": [
{
"content": "",
Expand Down
44 changes: 22 additions & 22 deletions crates/ruff_diagnostics/src/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ use crate::edit::Edit;
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))]
pub enum Applicability {
/// The fix is unsafe and should only be manually applied by the user.
/// The fix is unsafe and should only be displayed for manual application by the user.
/// The fix is likely to be incorrect or the resulting code may have invalid syntax.
Never,
Display,

/// The fix is unsafe and should only be applied with user opt-in.
/// The fix may be what the user intended, but it is uncertain; the resulting code will have valid syntax.
Sometimes,
Unsafe,

/// The fix is safe and can always be applied.
/// The fix is definitely what the user intended, or it maintains the exact meaning of the code.
Always,
Safe,
}

/// Indicates the level of isolation required to apply a fix.
Expand All @@ -47,62 +47,62 @@ pub struct Fix {
}

impl Fix {
/// Create a new [`Fix`] that can [always](Applicability::Always) be applied from an [`Edit`] element.
pub fn always_applies(edit: Edit) -> Self {
/// Create a new [`Fix`] that is [safe](Applicability::Safe) to apply from an [`Edit`] element.
pub fn safe_edit(edit: Edit) -> Self {
Self {
edits: vec![edit],
applicability: Applicability::Always,
applicability: Applicability::Safe,
isolation_level: IsolationLevel::default(),
}
}

/// Create a new [`Fix`] that can [always](Applicability::Always) be applied from multiple [`Edit`] elements.
pub fn always_applies_edits(edit: Edit, rest: impl IntoIterator<Item = Edit>) -> Self {
/// Create a new [`Fix`] that is [safe](Applicability::Safe) to apply from multiple [`Edit`] elements.
pub fn safe_edits(edit: Edit, rest: impl IntoIterator<Item = Edit>) -> Self {
let mut edits: Vec<Edit> = std::iter::once(edit).chain(rest).collect();
edits.sort_by_key(|edit| (edit.start(), edit.end()));
Self {
edits,
applicability: Applicability::Always,
applicability: Applicability::Safe,
isolation_level: IsolationLevel::default(),
}
}

/// Create a new [`Fix`] that can [sometimes](Applicability::Sometimes) be applied from an [`Edit`] element.
pub fn sometimes_applies(edit: Edit) -> Self {
/// Create a new [`Fix`] that is [unsafe](Applicability::Unsafe) to apply from an [`Edit`] element.
pub fn unsafe_edit(edit: Edit) -> Self {
Self {
edits: vec![edit],
applicability: Applicability::Sometimes,
applicability: Applicability::Unsafe,
isolation_level: IsolationLevel::default(),
}
}

/// Create a new [`Fix`] that can [sometimes](Applicability::Sometimes) be applied from multiple [`Edit`] elements.
pub fn sometimes_applies_edits(edit: Edit, rest: impl IntoIterator<Item = Edit>) -> Self {
/// Create a new [`Fix`] that is [unsafe](Applicability::Unsafe) to apply from multiple [`Edit`] elements.
pub fn unsafe_edits(edit: Edit, rest: impl IntoIterator<Item = Edit>) -> Self {
let mut edits: Vec<Edit> = std::iter::once(edit).chain(rest).collect();
edits.sort_by_key(|edit| (edit.start(), edit.end()));
Self {
edits,
applicability: Applicability::Sometimes,
applicability: Applicability::Unsafe,
isolation_level: IsolationLevel::default(),
}
}

/// Create a new [`Fix`] that should [never](Applicability::Never) be applied from an [`Edit`] element .
pub fn never_applies(edit: Edit) -> Self {
/// Create a new [`Fix`] that should only [display](Applicability::Display) and not apply from an [`Edit`] element .
pub fn display_edit(edit: Edit) -> Self {
Self {
edits: vec![edit],
applicability: Applicability::Never,
applicability: Applicability::Display,
isolation_level: IsolationLevel::default(),
}
}

/// Create a new [`Fix`] that should [never](Applicability::Never) be applied from multiple [`Edit`] elements.
pub fn never_applies_edits(edit: Edit, rest: impl IntoIterator<Item = Edit>) -> Self {
/// Create a new [`Fix`] that should only [display](Applicability::Display) and not apply from multiple [`Edit`] elements.
pub fn display_edits(edit: Edit, rest: impl IntoIterator<Item = Edit>) -> Self {
let mut edits: Vec<Edit> = std::iter::once(edit).chain(rest).collect();
edits.sort_by_key(|edit| (edit.start(), edit.end()));
Self {
edits,
applicability: Applicability::Never,
applicability: Applicability::Display,
isolation_level: IsolationLevel::default(),
}
}
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_linter/src/checkers/ast/analyze/bindings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub(crate) fn bindings(checker: &mut Checker) {
binding,
checker.locator,
)
.map(Fix::always_applies)
.map(Fix::safe_edit)
});
}
checker.diagnostics.push(diagnostic);
Expand Down
18 changes: 7 additions & 11 deletions crates/ruff_linter/src/checkers/noqa.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,10 +110,8 @@ pub(crate) fn check_noqa(
let mut diagnostic =
Diagnostic::new(UnusedNOQA { codes: None }, directive.range());
if settings.rules.should_fix(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::sometimes_applies(delete_noqa(
directive.range(),
locator,
)));
diagnostic
.set_fix(Fix::unsafe_edit(delete_noqa(directive.range(), locator)));
}
diagnostics.push(diagnostic);
}
Expand Down Expand Up @@ -177,17 +175,15 @@ pub(crate) fn check_noqa(
);
if settings.rules.should_fix(diagnostic.kind.rule()) {
if valid_codes.is_empty() {
diagnostic.set_fix(Fix::sometimes_applies(delete_noqa(
diagnostic.set_fix(Fix::unsafe_edit(delete_noqa(
directive.range(),
locator,
)));
} else {
diagnostic.set_fix(Fix::sometimes_applies(
Edit::range_replacement(
format!("# noqa: {}", valid_codes.join(", ")),
directive.range(),
),
));
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
format!("# noqa: {}", valid_codes.join(", ")),
directive.range(),
)));
}
}
diagnostics.push(diagnostic);
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_linter/src/fix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ mod tests {
// The choice of rule here is arbitrary.
kind: MissingNewlineAtEndOfFile.into(),
range: edit.range(),
fix: Some(Fix::always_applies(edit)),
fix: Some(Fix::safe_edit(edit)),
parent: None,
})
.collect()
Expand Down
6 changes: 3 additions & 3 deletions crates/ruff_linter/src/message/diff.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,9 @@ impl Display for Diff<'_> {

let message = match self.fix.applicability() {
// TODO(zanieb): Adjust this messaging once it's user-facing
Applicability::Always => "Fix",
Applicability::Sometimes => "Suggested fix",
Applicability::Never => "Possible fix",
Applicability::Safe => "Fix",
Applicability::Unsafe => "Suggested fix",
Applicability::Display => "Possible fix",
};
writeln!(f, "ℹ {}", message.blue())?;

Expand Down
9 changes: 5 additions & 4 deletions crates/ruff_linter/src/message/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,10 @@ def fibonacci(n):
},
TextRange::new(TextSize::from(7), TextSize::from(9)),
)
.with_fix(Fix::sometimes_applies(Edit::range_deletion(
TextRange::new(TextSize::from(0), TextSize::from(10)),
)));
.with_fix(Fix::unsafe_edit(Edit::range_deletion(TextRange::new(
TextSize::from(0),
TextSize::from(10),
))));

let fib_source = SourceFileBuilder::new("fib.py", fib).finish();

Expand All @@ -192,7 +193,7 @@ def fibonacci(n):
},
TextRange::new(TextSize::from(94), TextSize::from(95)),
)
.with_fix(Fix::sometimes_applies(Edit::deletion(
.with_fix(Fix::unsafe_edit(Edit::deletion(
TextSize::from(94),
TextSize::from(99),
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ expression: content
},
"filename": "fib.py",
"fix": {
"applicability": "sometimes",
"applicability": "unsafe",
"edits": [
{
"content": "",
Expand Down Expand Up @@ -43,7 +43,7 @@ expression: content
},
"filename": "fib.py",
"fix": {
"applicability": "sometimes",
"applicability": "unsafe",
"edits": [
{
"content": "",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
source: crates/ruff_linter/src/message/json_lines.rs
expression: content
---
{"code":"F401","end_location":{"column":10,"row":1},"filename":"fib.py","fix":{"applicability":"sometimes","edits":[{"content":"","end_location":{"column":1,"row":2},"location":{"column":1,"row":1}}],"message":"Remove unused import: `os`"},"location":{"column":8,"row":1},"message":"`os` imported but unused","noqa_row":1,"url":"https://docs.astral.sh/ruff/rules/unused-import"}
{"code":"F841","end_location":{"column":6,"row":6},"filename":"fib.py","fix":{"applicability":"sometimes","edits":[{"content":"","end_location":{"column":10,"row":6},"location":{"column":5,"row":6}}],"message":"Remove assignment to unused variable `x`"},"location":{"column":5,"row":6},"message":"Local variable `x` is assigned to but never used","noqa_row":6,"url":"https://docs.astral.sh/ruff/rules/unused-variable"}
{"code":"F401","end_location":{"column":10,"row":1},"filename":"fib.py","fix":{"applicability":"unsafe","edits":[{"content":"","end_location":{"column":1,"row":2},"location":{"column":1,"row":1}}],"message":"Remove unused import: `os`"},"location":{"column":8,"row":1},"message":"`os` imported but unused","noqa_row":1,"url":"https://docs.astral.sh/ruff/rules/unused-import"}
{"code":"F841","end_location":{"column":6,"row":6},"filename":"fib.py","fix":{"applicability":"unsafe","edits":[{"content":"","end_location":{"column":10,"row":6},"location":{"column":5,"row":6}}],"message":"Remove assignment to unused variable `x`"},"location":{"column":5,"row":6},"message":"Local variable `x` is assigned to but never used","noqa_row":6,"url":"https://docs.astral.sh/ruff/rules/unused-variable"}
{"code":"F821","end_location":{"column":5,"row":1},"filename":"undef.py","fix":null,"location":{"column":4,"row":1},"message":"Undefined name `a`","noqa_row":1,"url":"https://docs.astral.sh/ruff/rules/undefined-name"}

Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ pub(crate) fn commented_out_code(
let mut diagnostic = Diagnostic::new(CommentedOutCode, *range);

if settings.rules.should_fix(Rule::CommentedOutCode) {
diagnostic.set_fix(Fix::never_applies(Edit::range_deletion(
diagnostic.set_fix(Fix::display_edit(Edit::range_deletion(
locator.full_lines_range(*range),
)));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -703,7 +703,7 @@ pub(crate) fn definition(
function.identifier(),
);
if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::sometimes_applies(Edit::insertion(
diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion(
" -> None".to_string(),
function.parameters.range().end(),
)));
Expand All @@ -721,7 +721,7 @@ pub(crate) fn definition(
);
if checker.patch(diagnostic.kind.rule()) {
if let Some(return_type) = simple_magic_return_type(name) {
diagnostic.set_fix(Fix::sometimes_applies(Edit::insertion(
diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion(
format!(" -> {return_type}"),
function.parameters.range().end(),
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ pub(crate) fn assert_false(checker: &mut Checker, stmt: &Stmt, test: &Expr, msg:

let mut diagnostic = Diagnostic::new(AssertFalse, test.range());
if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::sometimes_applies(Edit::range_replacement(
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
checker.generator().stmt(&assertion_error(msg)),
stmt.range(),
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ fn duplicate_handler_exceptions<'a>(
expr.range(),
);
if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::always_applies(Edit::range_replacement(
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
// Single exceptions don't require parentheses, but since we're _removing_
// parentheses, insert whitespace as needed.
if let [elt] = unique_elts.as_slice() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ pub(crate) fn getattr_with_constant(

let mut diagnostic = Diagnostic::new(GetAttrWithConstant, expr.range());
if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::sometimes_applies(Edit::range_replacement(
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
pad(
if matches!(
obj,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,5 @@ fn move_initialization(
}

let initialization_edit = Edit::insertion(content, pos);
Some(Fix::never_applies_edits(
default_edit,
[initialization_edit],
))
Some(Fix::display_edits(default_edit, [initialization_edit]))
}
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub(crate) fn redundant_tuple_in_exception_handler(
// ```
// Otherwise, the output will be invalid syntax, since we're removing a set of
// parentheses.
diagnostic.set_fix(Fix::always_applies(Edit::range_replacement(
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
pad(
checker.generator().expr(elt),
type_.range(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ pub(crate) fn setattr_with_constant(
if expr == child.as_ref() {
let mut diagnostic = Diagnostic::new(SetAttrWithConstant, expr.range());
if checker.patch(diagnostic.kind.rule()) {
diagnostic.set_fix(Fix::sometimes_applies(Edit::range_replacement(
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
assignment(obj, name, value, checker.generator()),
expr.range(),
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ pub(crate) fn unreliable_callable_check(
if checker.patch(diagnostic.kind.rule()) {
if id == "hasattr" {
if checker.semantic().is_builtin("callable") {
diagnostic.set_fix(Fix::always_applies(Edit::range_replacement(
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
format!("callable({})", checker.locator().slice(obj)),
expr.range(),
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ pub(crate) fn unused_loop_control_variable(checker: &mut Checker, stmt_for: &ast
.filter(|binding| binding.start() >= expr.start())
.all(|binding| !binding.is_used())
{
diagnostic.set_fix(Fix::sometimes_applies(Edit::range_replacement(
diagnostic.set_fix(Fix::unsafe_edit(Edit::range_replacement(
rename,
expr.range(),
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -325,9 +325,7 @@ pub(crate) fn trailing_commas(
let comma = prev.spanned.unwrap();
let mut diagnostic = Diagnostic::new(ProhibitedTrailingComma, comma.1);
if settings.rules.should_fix(Rule::ProhibitedTrailingComma) {
diagnostic.set_fix(Fix::always_applies(Edit::range_deletion(
diagnostic.range(),
)));
diagnostic.set_fix(Fix::safe_edit(Edit::range_deletion(diagnostic.range())));
}
diagnostics.push(diagnostic);
}
Expand Down Expand Up @@ -367,7 +365,7 @@ pub(crate) fn trailing_commas(
// removing any brackets in the same linter pass - doing both at the same time could
// lead to a syntax error.
let contents = locator.slice(missing_comma.1);
diagnostic.set_fix(Fix::always_applies(Edit::range_replacement(
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
format!("{contents},"),
missing_comma.1,
)));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1293,7 +1293,7 @@ pub(crate) fn fix_unnecessary_comprehension_any_all(
_ => whitespace_after_arg,
};

Ok(Fix::sometimes_applies(Edit::range_replacement(
Ok(Fix::unsafe_edit(Edit::range_replacement(
tree.codegen_stylist(stylist),
expr.range(),
)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,9 +90,9 @@ pub(crate) fn unnecessary_call_around_sorted(
checker.stylist(),
)?;
if outer.id == "reversed" {
Ok(Fix::sometimes_applies(edit))
Ok(Fix::unsafe_edit(edit))
} else {
Ok(Fix::always_applies(edit))
Ok(Fix::safe_edit(edit))
}
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ pub(crate) fn unnecessary_collection_call(
);
if checker.patch(diagnostic.kind.rule()) {
diagnostic.try_set_fix(|| {
fixes::fix_unnecessary_collection_call(expr, checker).map(Fix::sometimes_applies)
fixes::fix_unnecessary_collection_call(expr, checker).map(Fix::unsafe_edit)
});
}
checker.diagnostics.push(diagnostic);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ fn add_diagnostic(checker: &mut Checker, expr: &Expr) {
if checker.patch(diagnostic.kind.rule()) {
diagnostic.try_set_fix(|| {
fixes::fix_unnecessary_comprehension(expr, checker.locator(), checker.stylist())
.map(Fix::sometimes_applies)
.map(Fix::unsafe_edit)
});
}
checker.diagnostics.push(diagnostic);
Expand Down
Loading
Loading