@@ -49,7 +49,7 @@ use ruff_python_ast::{helpers, str, visitor, PySourceType};
49
49
use ruff_python_codegen:: { Generator , Stylist } ;
50
50
use ruff_python_index:: Indexer ;
51
51
use ruff_python_parser:: typing:: { parse_type_annotation, AnnotationKind , ParsedAnnotation } ;
52
- use ruff_python_parser:: { Parsed , Tokens } ;
52
+ use ruff_python_parser:: { ParseError , Parsed , Tokens } ;
53
53
use ruff_python_semantic:: all:: { DunderAllDefinition , DunderAllFlags } ;
54
54
use ruff_python_semantic:: analyze:: { imports, typing} ;
55
55
use ruff_python_semantic:: {
@@ -234,7 +234,7 @@ impl<'a> Checker<'a> {
234
234
#[ allow( clippy:: too_many_arguments) ]
235
235
pub ( crate ) fn new (
236
236
parsed : & ' a Parsed < ModModule > ,
237
- parsed_annotations_arena : & ' a typed_arena:: Arena < ParsedAnnotation > ,
237
+ parsed_annotations_arena : & ' a typed_arena:: Arena < Result < ParsedAnnotation , ParseError > > ,
238
238
settings : & ' a LinterSettings ,
239
239
noqa_line_for : & ' a NoqaMapping ,
240
240
noqa : flags:: Noqa ,
@@ -425,7 +425,7 @@ impl<'a> Checker<'a> {
425
425
pub ( crate ) fn parse_type_annotation (
426
426
& self ,
427
427
annotation : & ast:: ExprStringLiteral ,
428
- ) -> Option < & ' a ParsedAnnotation > {
428
+ ) -> Result < & ' a ParsedAnnotation , & ' a ParseError > {
429
429
self . parsed_annotations_cache
430
430
. lookup_or_parse ( annotation, self . locator . contents ( ) )
431
431
}
@@ -441,7 +441,7 @@ impl<'a> Checker<'a> {
441
441
match_fn : impl FnOnce ( & ast:: Expr ) -> bool ,
442
442
) -> bool {
443
443
if let ast:: Expr :: StringLiteral ( string_annotation) = expr {
444
- let Some ( parsed_annotation) = self . parse_type_annotation ( string_annotation) else {
444
+ let Some ( parsed_annotation) = self . parse_type_annotation ( string_annotation) . ok ( ) else {
445
445
return false ;
446
446
} ;
447
447
match_fn ( parsed_annotation. expression ( ) )
@@ -2318,58 +2318,66 @@ impl<'a> Checker<'a> {
2318
2318
while !self . visit . string_type_definitions . is_empty ( ) {
2319
2319
let type_definitions = std:: mem:: take ( & mut self . visit . string_type_definitions ) ;
2320
2320
for ( string_expr, snapshot) in type_definitions {
2321
- let annotation_parse_result = self . parse_type_annotation ( string_expr) ;
2322
- if let Some ( parsed_annotation) = annotation_parse_result {
2323
- self . parsed_type_annotation = Some ( parsed_annotation) ;
2321
+ match self . parse_type_annotation ( string_expr) {
2322
+ Ok ( parsed_annotation) => {
2323
+ self . parsed_type_annotation = Some ( parsed_annotation) ;
2324
2324
2325
- let annotation = string_expr. value . to_str ( ) ;
2326
- let range = string_expr. range ( ) ;
2325
+ let annotation = string_expr. value . to_str ( ) ;
2326
+ let range = string_expr. range ( ) ;
2327
2327
2328
- self . semantic . restore ( snapshot) ;
2328
+ self . semantic . restore ( snapshot) ;
2329
2329
2330
- if self . semantic . in_annotation ( ) && self . semantic . in_typing_only_annotation ( ) {
2331
- if self . enabled ( Rule :: QuotedAnnotation ) {
2332
- pyupgrade:: rules:: quoted_annotation ( self , annotation, range) ;
2330
+ if self . semantic . in_annotation ( )
2331
+ && self . semantic . in_typing_only_annotation ( )
2332
+ {
2333
+ if self . enabled ( Rule :: QuotedAnnotation ) {
2334
+ pyupgrade:: rules:: quoted_annotation ( self , annotation, range) ;
2335
+ }
2333
2336
}
2334
- }
2335
- if self . source_type . is_stub ( ) {
2336
- if self . enabled ( Rule :: QuotedAnnotationInStub ) {
2337
- flake8_pyi:: rules:: quoted_annotation_in_stub ( self , annotation, range) ;
2337
+ if self . source_type . is_stub ( ) {
2338
+ if self . enabled ( Rule :: QuotedAnnotationInStub ) {
2339
+ flake8_pyi:: rules:: quoted_annotation_in_stub (
2340
+ self , annotation, range,
2341
+ ) ;
2342
+ }
2338
2343
}
2339
- }
2340
2344
2341
- let type_definition_flag = match parsed_annotation. kind ( ) {
2342
- AnnotationKind :: Simple => SemanticModelFlags :: SIMPLE_STRING_TYPE_DEFINITION ,
2343
- AnnotationKind :: Complex => {
2344
- SemanticModelFlags :: COMPLEX_STRING_TYPE_DEFINITION
2345
- }
2346
- } ;
2347
-
2348
- self . semantic . flags |=
2349
- SemanticModelFlags :: TYPE_DEFINITION | type_definition_flag;
2350
- let parsed_expr = parsed_annotation. expression ( ) ;
2351
- self . visit_expr ( parsed_expr) ;
2352
- if self . semantic . in_type_alias_value ( ) {
2353
- // stub files are covered by PYI020
2354
- if !self . source_type . is_stub ( ) && self . enabled ( Rule :: QuotedTypeAlias ) {
2355
- flake8_type_checking:: rules:: quoted_type_alias (
2356
- self ,
2357
- parsed_expr,
2358
- string_expr,
2359
- ) ;
2345
+ let type_definition_flag = match parsed_annotation. kind ( ) {
2346
+ AnnotationKind :: Simple => {
2347
+ SemanticModelFlags :: SIMPLE_STRING_TYPE_DEFINITION
2348
+ }
2349
+ AnnotationKind :: Complex => {
2350
+ SemanticModelFlags :: COMPLEX_STRING_TYPE_DEFINITION
2351
+ }
2352
+ } ;
2353
+
2354
+ self . semantic . flags |=
2355
+ SemanticModelFlags :: TYPE_DEFINITION | type_definition_flag;
2356
+ let parsed_expr = parsed_annotation. expression ( ) ;
2357
+ self . visit_expr ( parsed_expr) ;
2358
+ if self . semantic . in_type_alias_value ( ) {
2359
+ // stub files are covered by PYI020
2360
+ if !self . source_type . is_stub ( ) && self . enabled ( Rule :: QuotedTypeAlias ) {
2361
+ flake8_type_checking:: rules:: quoted_type_alias (
2362
+ self ,
2363
+ parsed_expr,
2364
+ string_expr,
2365
+ ) ;
2366
+ }
2360
2367
}
2368
+ self . parsed_type_annotation = None ;
2361
2369
}
2362
- self . parsed_type_annotation = None ;
2363
- } else {
2364
- self . semantic . restore ( snapshot ) ;
2365
-
2366
- if self . enabled ( Rule :: ForwardAnnotationSyntaxError ) {
2367
- self . push_type_diagnostic ( Diagnostic :: new (
2368
- pyflakes :: rules :: ForwardAnnotationSyntaxError {
2369
- body : string_expr . value . to_string ( ) ,
2370
- } ,
2371
- string_expr . range ( ) ,
2372
- ) ) ;
2370
+ Err ( parse_error ) => {
2371
+ self . semantic . restore ( snapshot ) ;
2372
+
2373
+ if self . enabled ( Rule :: ForwardAnnotationSyntaxError ) {
2374
+ self . push_type_diagnostic ( Diagnostic :: new (
2375
+ pyflakes :: rules :: ForwardAnnotationSyntaxError {
2376
+ parse_error : parse_error . error . to_string ( ) ,
2377
+ } ,
2378
+ string_expr . range ( ) ,
2379
+ ) ) ;
2380
+ }
2373
2381
}
2374
2382
}
2375
2383
}
@@ -2541,12 +2549,12 @@ impl<'a> Checker<'a> {
2541
2549
}
2542
2550
2543
2551
struct ParsedAnnotationsCache < ' a > {
2544
- arena : & ' a typed_arena:: Arena < ParsedAnnotation > ,
2545
- by_offset : RefCell < FxHashMap < TextSize , Option < & ' a ParsedAnnotation > > > ,
2552
+ arena : & ' a typed_arena:: Arena < Result < ParsedAnnotation , ParseError > > ,
2553
+ by_offset : RefCell < FxHashMap < TextSize , Result < & ' a ParsedAnnotation , & ' a ParseError > > > ,
2546
2554
}
2547
2555
2548
2556
impl < ' a > ParsedAnnotationsCache < ' a > {
2549
- fn new ( arena : & ' a typed_arena:: Arena < ParsedAnnotation > ) -> Self {
2557
+ fn new ( arena : & ' a typed_arena:: Arena < Result < ParsedAnnotation , ParseError > > ) -> Self {
2550
2558
Self {
2551
2559
arena,
2552
2560
by_offset : RefCell :: default ( ) ,
@@ -2557,17 +2565,15 @@ impl<'a> ParsedAnnotationsCache<'a> {
2557
2565
& self ,
2558
2566
annotation : & ast:: ExprStringLiteral ,
2559
2567
source : & str ,
2560
- ) -> Option < & ' a ParsedAnnotation > {
2568
+ ) -> Result < & ' a ParsedAnnotation , & ' a ParseError > {
2561
2569
* self
2562
2570
. by_offset
2563
2571
. borrow_mut ( )
2564
2572
. entry ( annotation. start ( ) )
2565
2573
. or_insert_with ( || {
2566
- if let Ok ( annotation) = parse_type_annotation ( annotation, source) {
2567
- Some ( self . arena . alloc ( annotation) )
2568
- } else {
2569
- None
2570
- }
2574
+ self . arena
2575
+ . alloc ( parse_type_annotation ( annotation, source) )
2576
+ . as_ref ( )
2571
2577
} )
2572
2578
}
2573
2579
0 commit comments