mirror of
https://github.com/astral-sh/ruff.git
synced 2025-07-28 15:34:19 +00:00
Start detecting version-related syntax errors in the parser (#16090)
## Summary This PR builds on the changes in #16220 to pass a target Python version to the parser. It also adds the `Parser::unsupported_syntax_errors` field, which collects version-related syntax errors while parsing. These syntax errors are then turned into `Message`s in ruff (in preview mode). This PR only detects one syntax error (`match` statement before Python 3.10), but it has been pretty quick to extend to several other simple errors (see #16308 for example). ## Test Plan The current tests are CLI tests in the linter crate, but these could be supplemented with inline parser tests after #16357. I also tested the display of these syntax errors in VS Code:   --------- Co-authored-by: Alex Waygood <alex.waygood@gmail.com>
This commit is contained in:
parent
b39a4ad01d
commit
78806361fd
14 changed files with 356 additions and 37 deletions
|
@ -1,5 +1,6 @@
|
|||
use std::fmt;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
use ruff_python_ast::PythonVersion;
|
||||
use ruff_text_size::TextRange;
|
||||
|
||||
use crate::TokenKind;
|
||||
|
@ -426,6 +427,50 @@ impl std::fmt::Display for LexicalErrorType {
|
|||
}
|
||||
}
|
||||
|
||||
/// Represents a version-related syntax error detected during parsing.
|
||||
///
|
||||
/// An example of a version-related error is the use of a `match` statement before Python 3.10, when
|
||||
/// it was first introduced. See [`UnsupportedSyntaxErrorKind`] for other kinds of errors.
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub struct UnsupportedSyntaxError {
|
||||
pub kind: UnsupportedSyntaxErrorKind,
|
||||
pub range: TextRange,
|
||||
/// The target [`PythonVersion`] for which this error was detected.
|
||||
///
|
||||
/// This is different from the version reported by the
|
||||
/// [`minimum_version`](UnsupportedSyntaxError::minimum_version) method, which is the earliest
|
||||
/// allowed version for this piece of syntax. The `target_version` is primarily used for
|
||||
/// user-facing error messages.
|
||||
pub target_version: PythonVersion,
|
||||
}
|
||||
|
||||
impl UnsupportedSyntaxError {
|
||||
/// The earliest allowed version for the syntax associated with this error.
|
||||
pub const fn minimum_version(&self) -> PythonVersion {
|
||||
match self.kind {
|
||||
UnsupportedSyntaxErrorKind::MatchBeforePy310 => PythonVersion::PY310,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for UnsupportedSyntaxError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.kind {
|
||||
UnsupportedSyntaxErrorKind::MatchBeforePy310 => write!(
|
||||
f,
|
||||
"Cannot use `match` statement on Python {} (syntax was added in Python {})",
|
||||
self.target_version,
|
||||
self.minimum_version(),
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Clone, Copy)]
|
||||
pub enum UnsupportedSyntaxErrorKind {
|
||||
MatchBeforePy310,
|
||||
}
|
||||
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
mod sizes {
|
||||
use crate::error::{LexicalError, LexicalErrorType};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue