From 32c66ec4b714905fd781aca502560c90cc2bae1d Mon Sep 17 00:00:00 2001 From: Brent Westbrook <36778786+ntBre@users.noreply.github.com> Date: Tue, 4 Mar 2025 12:20:10 -0500 Subject: [PATCH] [syntax-errors] `type` alias statements before Python 3.12 (#16478) Summary -- Another simple one, just detect standalone `type` statements. I limited the diagnostic to `type` itself like [pyright]. That probably makes the most sense for more complicated examples. Test Plan -- Inline tests. [pyright]: https://pyright-play.net/?pythonVersion=3.8&strict=true&code=C4TwDgpgBAHlC8UCWA7YQ --- .../resources/inline/err/type_stmt_py311.py | 2 + .../resources/inline/ok/type_stmt_py312.py | 2 + crates/ruff_python_parser/src/error.rs | 3 ++ .../src/parser/statement.rs | 14 +++++++ .../invalid_syntax@type_stmt_py311.py.snap | 42 +++++++++++++++++++ .../valid_syntax@type_stmt_py312.py.snap | 35 ++++++++++++++++ 6 files changed, 98 insertions(+) create mode 100644 crates/ruff_python_parser/resources/inline/err/type_stmt_py311.py create mode 100644 crates/ruff_python_parser/resources/inline/ok/type_stmt_py312.py create mode 100644 crates/ruff_python_parser/tests/snapshots/invalid_syntax@type_stmt_py311.py.snap create mode 100644 crates/ruff_python_parser/tests/snapshots/valid_syntax@type_stmt_py312.py.snap diff --git a/crates/ruff_python_parser/resources/inline/err/type_stmt_py311.py b/crates/ruff_python_parser/resources/inline/err/type_stmt_py311.py new file mode 100644 index 0000000000..37a11f0899 --- /dev/null +++ b/crates/ruff_python_parser/resources/inline/err/type_stmt_py311.py @@ -0,0 +1,2 @@ +# parse_options: {"target-version": "3.11"} +type x = int diff --git a/crates/ruff_python_parser/resources/inline/ok/type_stmt_py312.py b/crates/ruff_python_parser/resources/inline/ok/type_stmt_py312.py new file mode 100644 index 0000000000..f2e3aee5d7 --- /dev/null +++ b/crates/ruff_python_parser/resources/inline/ok/type_stmt_py312.py @@ -0,0 +1,2 @@ +# parse_options: {"target-version": "3.12"} +type x = int diff --git a/crates/ruff_python_parser/src/error.rs b/crates/ruff_python_parser/src/error.rs index bc58dccd44..97af7a20a8 100644 --- a/crates/ruff_python_parser/src/error.rs +++ b/crates/ruff_python_parser/src/error.rs @@ -449,6 +449,7 @@ pub enum UnsupportedSyntaxErrorKind { Match, Walrus, ExceptStar, + TypeAliasStatement, TypeParamDefault, } @@ -458,6 +459,7 @@ impl Display for UnsupportedSyntaxError { UnsupportedSyntaxErrorKind::Match => "Cannot use `match` statement", UnsupportedSyntaxErrorKind::Walrus => "Cannot use named assignment expression (`:=`)", UnsupportedSyntaxErrorKind::ExceptStar => "Cannot use `except*`", + UnsupportedSyntaxErrorKind::TypeAliasStatement => "Cannot use `type` alias statement", UnsupportedSyntaxErrorKind::TypeParamDefault => { "Cannot set default type for a type parameter" } @@ -478,6 +480,7 @@ impl UnsupportedSyntaxErrorKind { UnsupportedSyntaxErrorKind::Match => PythonVersion::PY310, UnsupportedSyntaxErrorKind::Walrus => PythonVersion::PY38, UnsupportedSyntaxErrorKind::ExceptStar => PythonVersion::PY311, + UnsupportedSyntaxErrorKind::TypeAliasStatement => PythonVersion::PY312, UnsupportedSyntaxErrorKind::TypeParamDefault => PythonVersion::PY313, } } diff --git a/crates/ruff_python_parser/src/parser/statement.rs b/crates/ruff_python_parser/src/parser/statement.rs index 62aebfe4bb..deabb8fe1e 100644 --- a/crates/ruff_python_parser/src/parser/statement.rs +++ b/crates/ruff_python_parser/src/parser/statement.rs @@ -888,8 +888,22 @@ impl<'src> Parser<'src> { /// See: fn parse_type_alias_statement(&mut self) -> ast::StmtTypeAlias { let start = self.node_start(); + let type_range = self.current_token_range(); self.bump(TokenKind::Type); + // test_ok type_stmt_py312 + // # parse_options: {"target-version": "3.12"} + // type x = int + + // test_err type_stmt_py311 + // # parse_options: {"target-version": "3.11"} + // type x = int + + self.add_unsupported_syntax_error( + UnsupportedSyntaxErrorKind::TypeAliasStatement, + type_range, + ); + let mut name = Expr::Name(self.parse_name()); helpers::set_expr_ctx(&mut name, ExprContext::Store); diff --git a/crates/ruff_python_parser/tests/snapshots/invalid_syntax@type_stmt_py311.py.snap b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@type_stmt_py311.py.snap new file mode 100644 index 0000000000..dfb7a15121 --- /dev/null +++ b/crates/ruff_python_parser/tests/snapshots/invalid_syntax@type_stmt_py311.py.snap @@ -0,0 +1,42 @@ +--- +source: crates/ruff_python_parser/tests/fixtures.rs +input_file: crates/ruff_python_parser/resources/inline/err/type_stmt_py311.py +--- +## AST + +``` +Module( + ModModule { + range: 0..57, + body: [ + TypeAlias( + StmtTypeAlias { + range: 44..56, + name: Name( + ExprName { + range: 49..50, + id: Name("x"), + ctx: Store, + }, + ), + type_params: None, + value: Name( + ExprName { + range: 53..56, + id: Name("int"), + ctx: Load, + }, + ), + }, + ), + ], + }, +) +``` +## Unsupported Syntax Errors + + | +1 | # parse_options: {"target-version": "3.11"} +2 | type x = int + | ^^^^ Syntax Error: Cannot use `type` alias statement on Python 3.11 (syntax was added in Python 3.12) + | diff --git a/crates/ruff_python_parser/tests/snapshots/valid_syntax@type_stmt_py312.py.snap b/crates/ruff_python_parser/tests/snapshots/valid_syntax@type_stmt_py312.py.snap new file mode 100644 index 0000000000..62eeead56c --- /dev/null +++ b/crates/ruff_python_parser/tests/snapshots/valid_syntax@type_stmt_py312.py.snap @@ -0,0 +1,35 @@ +--- +source: crates/ruff_python_parser/tests/fixtures.rs +input_file: crates/ruff_python_parser/resources/inline/ok/type_stmt_py312.py +--- +## AST + +``` +Module( + ModModule { + range: 0..57, + body: [ + TypeAlias( + StmtTypeAlias { + range: 44..56, + name: Name( + ExprName { + range: 49..50, + id: Name("x"), + ctx: Store, + }, + ), + type_params: None, + value: Name( + ExprName { + range: 53..56, + id: Name("int"), + ctx: Load, + }, + ), + }, + ), + ], + }, +) +```