mirror of
https://github.com/astral-sh/ruff.git
synced 2025-08-19 01:51:30 +00:00
Server: Allow FixAll
action in presence of version-specific syntax errors (#16848)
The single flag `has_syntax_error` on `LinterResult` is replaced with two (private) flags: `has_valid_syntax` and `has_no_unsupported_syntax_errors`, which record whether there are `ParseError`s or `UnsupportedSyntaxError`s, respectively. Only the former is used to prevent a `FixAll` action. An attempt has been made to make consistent the usage of the phrases "valid syntax" (which seems to be used to refer only to _parser_ errors) and "syntax error" (which refers to both _parser_ errors and version-specific syntax errors). Closes #16841
This commit is contained in:
parent
999fd4f885
commit
74f64d3f96
5 changed files with 111 additions and 73 deletions
|
@ -40,11 +40,48 @@ use crate::{directives, fs, Locator};
|
|||
pub struct LinterResult {
|
||||
/// A collection of diagnostic messages generated by the linter.
|
||||
pub messages: Vec<Message>,
|
||||
/// A flag indicating the presence of syntax errors in the source file.
|
||||
/// If `true`, at least one syntax error was detected in the source file.
|
||||
/// Flag indicating that the parsed source code does not contain any
|
||||
/// [`ParseError`]s
|
||||
has_valid_syntax: bool,
|
||||
/// Flag indicating that the parsed source code does not contain any
|
||||
/// [`UnsupportedSyntaxError`]s
|
||||
has_no_unsupported_syntax_errors: bool,
|
||||
}
|
||||
|
||||
impl LinterResult {
|
||||
/// Returns `true` if the parsed source code contains any [`ParseError`]s *or*
|
||||
/// [`UnsupportedSyntaxError`]s.
|
||||
///
|
||||
/// This includes both [`ParseError`]s and [`UnsupportedSyntaxError`]s.
|
||||
pub has_syntax_error: bool,
|
||||
/// See [`LinterResult::has_invalid_syntax`] for a version specific to [`ParseError`]s.
|
||||
pub fn has_syntax_errors(&self) -> bool {
|
||||
!self.has_no_syntax_errors()
|
||||
}
|
||||
|
||||
/// Returns `true` if the parsed source code does not contain any [`ParseError`]s *or*
|
||||
/// [`UnsupportedSyntaxError`]s.
|
||||
///
|
||||
/// See [`LinterResult::has_valid_syntax`] for a version specific to [`ParseError`]s.
|
||||
pub fn has_no_syntax_errors(&self) -> bool {
|
||||
self.has_valid_syntax() && self.has_no_unsupported_syntax_errors
|
||||
}
|
||||
|
||||
/// Returns `true` if the parsed source code is valid i.e., it has no [`ParseError`]s.
|
||||
///
|
||||
/// Note that this does not include version-related [`UnsupportedSyntaxError`]s.
|
||||
///
|
||||
/// See [`LinterResult::has_no_syntax_errors`] for a version that takes these into account.
|
||||
pub fn has_valid_syntax(&self) -> bool {
|
||||
self.has_valid_syntax
|
||||
}
|
||||
|
||||
/// Returns `true` if the parsed source code is invalid i.e., it has [`ParseError`]s.
|
||||
///
|
||||
/// Note that this does not include version-related [`UnsupportedSyntaxError`]s.
|
||||
///
|
||||
/// See [`LinterResult::has_no_syntax_errors`] for a version that takes these into account.
|
||||
pub fn has_invalid_syntax(&self) -> bool {
|
||||
!self.has_valid_syntax()
|
||||
}
|
||||
}
|
||||
|
||||
pub type FixTable = FxHashMap<Rule, usize>;
|
||||
|
@ -446,7 +483,8 @@ pub fn lint_only(
|
|||
|
||||
LinterResult {
|
||||
messages,
|
||||
has_syntax_error: parsed.has_syntax_errors(),
|
||||
has_valid_syntax: parsed.has_valid_syntax(),
|
||||
has_no_unsupported_syntax_errors: parsed.unsupported_syntax_errors().is_empty(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -503,8 +541,11 @@ pub fn lint_fix<'a>(
|
|||
// As an escape hatch, bail after 100 iterations.
|
||||
let mut iterations = 0;
|
||||
|
||||
// Track whether the _initial_ source code is valid syntax.
|
||||
let mut is_valid_syntax = false;
|
||||
// Track whether the _initial_ source code has valid syntax.
|
||||
let mut has_valid_syntax = false;
|
||||
|
||||
// Track whether the _initial_ source code has no unsupported syntax errors.
|
||||
let mut has_no_unsupported_syntax_errors = false;
|
||||
|
||||
let target_version = settings.resolve_target_version(path);
|
||||
|
||||
|
@ -547,12 +588,13 @@ pub fn lint_fix<'a>(
|
|||
);
|
||||
|
||||
if iterations == 0 {
|
||||
is_valid_syntax = parsed.has_no_syntax_errors();
|
||||
has_valid_syntax = parsed.has_valid_syntax();
|
||||
has_no_unsupported_syntax_errors = parsed.unsupported_syntax_errors().is_empty();
|
||||
} else {
|
||||
// If the source code was parseable on the first pass, but is no
|
||||
// longer parseable on a subsequent pass, then we've introduced a
|
||||
// If the source code had no syntax errors on the first pass, but
|
||||
// does on a subsequent pass, then we've introduced a
|
||||
// syntax error. Return the original code.
|
||||
if is_valid_syntax {
|
||||
if has_valid_syntax && has_no_unsupported_syntax_errors {
|
||||
if let Some(error) = parsed.errors().first() {
|
||||
report_fix_syntax_error(
|
||||
path,
|
||||
|
@ -593,7 +635,8 @@ pub fn lint_fix<'a>(
|
|||
return Ok(FixerResult {
|
||||
result: LinterResult {
|
||||
messages,
|
||||
has_syntax_error: !is_valid_syntax,
|
||||
has_valid_syntax,
|
||||
has_no_unsupported_syntax_errors,
|
||||
},
|
||||
transformed,
|
||||
fixed,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue