Parses a decorator list followed by a class, function or async function definition. See:
(&mut self)
| 2894 | /// |
| 2895 | /// See: <https://docs.python.org/3/reference/compound_stmts.html#grammar-token-python-grammar-decorators> |
| 2896 | fn parse_decorators(&mut self) -> Stmt { |
| 2897 | let start = self.node_start(); |
| 2898 | |
| 2899 | let mut decorators = DecoratorList::new(); |
| 2900 | let mut progress = ParserProgress::default(); |
| 2901 | |
| 2902 | // test_err decorator_missing_expression |
| 2903 | // @def foo(): ... |
| 2904 | // @ |
| 2905 | // def foo(): ... |
| 2906 | // @@ |
| 2907 | // def foo(): ... |
| 2908 | // @test |
| 2909 | // @ |
| 2910 | // class Test |
| 2911 | while self.at(TokenKind::At) { |
| 2912 | progress.assert_progressing(self); |
| 2913 | |
| 2914 | let decorator_start = self.node_start(); |
| 2915 | self.bump(TokenKind::At); |
| 2916 | |
| 2917 | let parsed_expr = if self.at(TokenKind::Def) || self.at(TokenKind::Class) { |
| 2918 | Expr::Name(self.parse_missing_name()).into() |
| 2919 | } else { |
| 2920 | self.parse_named_expression_or_higher(ExpressionContext::default()) |
| 2921 | }; |
| 2922 | |
| 2923 | if self.options.target_version < PythonVersion::PY39 { |
| 2924 | // test_ok decorator_expression_dotted_ident_py38 |
| 2925 | // # parse_options: { "target-version": "3.8" } |
| 2926 | // @buttons.clicked.connect |
| 2927 | // def spam(): ... |
| 2928 | |
| 2929 | // test_ok decorator_expression_identity_hack_py38 |
| 2930 | // # parse_options: { "target-version": "3.8" } |
| 2931 | // def _(x): return x |
| 2932 | // @_(buttons[0].clicked.connect) |
| 2933 | // def spam(): ... |
| 2934 | |
| 2935 | // test_ok decorator_expression_eval_hack_py38 |
| 2936 | // # parse_options: { "target-version": "3.8" } |
| 2937 | // @eval("buttons[0].clicked.connect") |
| 2938 | // def spam(): ... |
| 2939 | |
| 2940 | // test_ok decorator_expression_py39 |
| 2941 | // # parse_options: { "target-version": "3.9" } |
| 2942 | // @buttons[0].clicked.connect |
| 2943 | // def spam(): ... |
| 2944 | // @(x := lambda x: x)(foo) |
| 2945 | // def bar(): ... |
| 2946 | |
| 2947 | // test_err decorator_expression_py38 |
| 2948 | // # parse_options: { "target-version": "3.8" } |
| 2949 | // @buttons[0].clicked.connect |
| 2950 | // def spam(): ... |
| 2951 | |
| 2952 | // test_err decorator_named_expression_py37 |
| 2953 | // # parse_options: { "target-version": "3.7" } |
no test coverage detected