diff --git a/crates/ruff_db/src/parsed.rs b/crates/ruff_db/src/parsed.rs index fcc10b5844..9fcfe1d5b7 100644 --- a/crates/ruff_db/src/parsed.rs +++ b/crates/ruff_db/src/parsed.rs @@ -102,7 +102,7 @@ mod tests { let parsed = parsed_module(&db, file); - assert!(parsed.is_valid()); + assert!(parsed.has_valid_syntax()); Ok(()) } @@ -118,7 +118,7 @@ mod tests { let parsed = parsed_module(&db, file); - assert!(parsed.is_valid()); + assert!(parsed.has_valid_syntax()); Ok(()) } @@ -134,7 +134,7 @@ mod tests { let parsed = parsed_module(&db, virtual_file.file()); - assert!(parsed.is_valid()); + assert!(parsed.has_valid_syntax()); Ok(()) } @@ -150,7 +150,7 @@ mod tests { let parsed = parsed_module(&db, virtual_file.file()); - assert!(parsed.is_valid()); + assert!(parsed.has_valid_syntax()); Ok(()) } @@ -181,6 +181,6 @@ else: let parsed = parsed_module(&db, file); - assert!(parsed.is_valid()); + assert!(parsed.has_valid_syntax()); } } diff --git a/crates/ruff_linter/src/linter.rs b/crates/ruff_linter/src/linter.rs index 51dfec63b5..e5bc700ab9 100644 --- a/crates/ruff_linter/src/linter.rs +++ b/crates/ruff_linter/src/linter.rs @@ -42,6 +42,8 @@ pub struct LinterResult { pub messages: Vec, /// 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. + /// + /// This includes both [`ParseError`]s and [`UnsupportedSyntaxError`]s. pub has_syntax_error: bool, } @@ -133,7 +135,7 @@ pub fn check_path( } // Run the AST-based rules only if there are no syntax errors. - if parsed.is_valid() { + if parsed.has_valid_syntax() { let use_ast = settings .rules .iter_enabled() @@ -283,7 +285,7 @@ pub fn check_path( locator, comment_ranges, &directives.noqa_line_for, - parsed.is_valid(), + parsed.has_valid_syntax(), &per_file_ignores, settings, ); @@ -294,7 +296,7 @@ pub fn check_path( } } - if parsed.is_valid() { + if parsed.has_valid_syntax() { // Remove fixes for any rules marked as unfixable. for diagnostic in &mut diagnostics { if !settings.rules.should_fix(diagnostic.kind.rule()) { @@ -445,7 +447,7 @@ pub fn lint_only( &locator, &directives, ), - has_syntax_error: !parsed.is_valid() || !parsed.unsupported_syntax_errors().is_empty(), + has_syntax_error: parsed.has_syntax_errors(), } } @@ -546,7 +548,7 @@ pub fn lint_fix<'a>( ); if iterations == 0 { - is_valid_syntax = parsed.is_valid() && parsed.unsupported_syntax_errors().is_empty(); + is_valid_syntax = parsed.has_no_syntax_errors(); } 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 diff --git a/crates/ruff_linter/src/test.rs b/crates/ruff_linter/src/test.rs index d15f49ed20..627257dea8 100644 --- a/crates/ruff_linter/src/test.rs +++ b/crates/ruff_linter/src/test.rs @@ -141,7 +141,7 @@ pub(crate) fn test_contents<'a>( target_version, ); - let source_has_errors = !parsed.is_valid(); + let source_has_errors = parsed.has_invalid_syntax(); // Detect fixes that don't converge after multiple iterations. let mut iterations = 0; @@ -207,7 +207,7 @@ pub(crate) fn test_contents<'a>( target_version, ); - if !parsed.is_valid() && !source_has_errors { + if parsed.has_invalid_syntax() && !source_has_errors { // Previous fix introduced a syntax error, abort let fixes = print_diagnostics(diagnostics, path, source_kind); let syntax_errors = diff --git a/crates/ruff_python_parser/src/lib.rs b/crates/ruff_python_parser/src/lib.rs index c2c21adec8..260375ece2 100644 --- a/crates/ruff_python_parser/src/lib.rs +++ b/crates/ruff_python_parser/src/lib.rs @@ -342,21 +342,47 @@ impl Parsed { self.errors } - /// Returns `true` if the parsed source code is valid i.e., it has no 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 - /// [`unsupported_syntax_errors`](Parsed::unsupported_syntax_errors). - pub fn is_valid(&self) -> bool { + /// Note that this does not include version-related [`UnsupportedSyntaxError`]s. + /// + /// See [`Parsed::has_no_syntax_errors`] for a version that takes these into account. + pub fn has_valid_syntax(&self) -> bool { self.errors.is_empty() } + /// 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 [`Parsed::has_no_syntax_errors`] for a version that takes these into account. + pub fn has_invalid_syntax(&self) -> bool { + !self.has_valid_syntax() + } + + /// Returns `true` if the parsed source code does not contain any [`ParseError`]s *or* + /// [`UnsupportedSyntaxError`]s. + /// + /// See [`Parsed::has_valid_syntax`] for a version specific to [`ParseError`]s. + pub fn has_no_syntax_errors(&self) -> bool { + self.has_valid_syntax() && self.unsupported_syntax_errors.is_empty() + } + + /// Returns `true` if the parsed source code contains any [`ParseError`]s *or* + /// [`UnsupportedSyntaxError`]s. + /// + /// See [`Parsed::has_invalid_syntax`] for a version specific to [`ParseError`]s. + pub fn has_syntax_errors(&self) -> bool { + !self.has_no_syntax_errors() + } + /// Returns the [`Parsed`] output as a [`Result`], returning [`Ok`] if it has no syntax errors, /// or [`Err`] containing the first [`ParseError`] encountered. /// /// Note that any [`unsupported_syntax_errors`](Parsed::unsupported_syntax_errors) will not /// cause [`Err`] to be returned. pub fn as_result(&self) -> Result<&Parsed, &[ParseError]> { - if self.is_valid() { + if self.has_valid_syntax() { Ok(self) } else { Err(&self.errors) @@ -369,7 +395,7 @@ impl Parsed { /// Note that any [`unsupported_syntax_errors`](Parsed::unsupported_syntax_errors) will not /// cause [`Err`] to be returned. pub(crate) fn into_result(self) -> Result, ParseError> { - if self.is_valid() { + if self.has_valid_syntax() { Ok(self) } else { Err(self.into_errors().into_iter().next().unwrap()) diff --git a/crates/ruff_python_parser/tests/fixtures.rs b/crates/ruff_python_parser/tests/fixtures.rs index 219729a196..5ce0f741db 100644 --- a/crates/ruff_python_parser/tests/fixtures.rs +++ b/crates/ruff_python_parser/tests/fixtures.rs @@ -39,9 +39,7 @@ fn test_valid_syntax(input_path: &Path) { }); let parsed = parse_unchecked(&source, options); - let is_valid = parsed.is_valid() && parsed.unsupported_syntax_errors().is_empty(); - - if !is_valid { + if parsed.has_syntax_errors() { let line_index = LineIndex::from_source_text(&source); let source_code = SourceCode::new(&source, &line_index); @@ -101,10 +99,8 @@ fn test_invalid_syntax(input_path: &Path) { }); let parsed = parse_unchecked(&source, options); - let is_valid = parsed.is_valid() && parsed.unsupported_syntax_errors().is_empty(); - assert!( - !is_valid, + parsed.has_syntax_errors(), "{input_path:?}: Expected parser to generate at least one syntax error for a program containing syntax errors." ); @@ -224,7 +220,7 @@ f'{foo!r' println!("AST:\n----\n{:#?}", parsed.syntax()); println!("Tokens:\n-------\n{:#?}", parsed.tokens()); - if !parsed.is_valid() { + if parsed.has_invalid_syntax() { println!("Errors:\n-------"); let line_index = LineIndex::from_source_text(source); diff --git a/fuzz/fuzz_targets/red_knot_check_invalid_syntax.rs b/fuzz/fuzz_targets/red_knot_check_invalid_syntax.rs index 61151c10c5..b98aeb0bb2 100644 --- a/fuzz/fuzz_targets/red_knot_check_invalid_syntax.rs +++ b/fuzz/fuzz_targets/red_knot_check_invalid_syntax.rs @@ -135,7 +135,7 @@ fn do_fuzz(case: &[u8]) -> Corpus { }; let parsed = parse_unchecked(code, ParseOptions::from(Mode::Module)); - if parsed.is_valid() { + if parsed.has_valid_syntax() { return Corpus::Reject; }