@@ -673,6 +673,23 @@ impl SourceOrderVisitor<'_> for SemanticTokenVisitor<'_> {
673673 self . visit_body ( & class. body ) ;
674674 self . in_class_scope = prev_in_class;
675675 }
676+ ast:: Stmt :: TypeAlias ( type_alias) => {
677+ // Type alias name
678+ self . add_token (
679+ type_alias. name . range ( ) ,
680+ SemanticTokenType :: Class ,
681+ SemanticTokenModifier :: DEFINITION ,
682+ ) ;
683+
684+ // Type parameters (Python 3.12+ syntax)
685+ if let Some ( type_params) = & type_alias. type_params {
686+ for type_param in & type_params. type_params {
687+ self . visit_type_param ( type_param) ;
688+ }
689+ }
690+
691+ self . visit_expr ( & type_alias. value ) ;
692+ }
676693 ast:: Stmt :: Import ( import) => {
677694 for alias in & import. names {
678695 if let Some ( asname) = & alias. asname {
@@ -747,6 +764,49 @@ impl SourceOrderVisitor<'_> for SemanticTokenVisitor<'_> {
747764 self . visit_expr ( value) ;
748765 }
749766 }
767+ ast:: Stmt :: For ( for_stmt) => {
768+ self . in_target_creating_definition = true ;
769+ self . visit_expr ( & for_stmt. target ) ;
770+ self . in_target_creating_definition = false ;
771+
772+ self . visit_expr ( & for_stmt. iter ) ;
773+ self . visit_body ( & for_stmt. body ) ;
774+ self . visit_body ( & for_stmt. orelse ) ;
775+ }
776+ ast:: Stmt :: With ( with_stmt) => {
777+ for item in & with_stmt. items {
778+ self . visit_expr ( & item. context_expr ) ;
779+ if let Some ( expr) = & item. optional_vars {
780+ self . in_target_creating_definition = true ;
781+ self . visit_expr ( expr) ;
782+ self . in_target_creating_definition = false ;
783+ }
784+ }
785+
786+ self . visit_body ( & with_stmt. body ) ;
787+ }
788+ ast:: Stmt :: Try ( try_stmt) => {
789+ self . visit_body ( & try_stmt. body ) ;
790+ for handler in & try_stmt. handlers {
791+ match handler {
792+ ast:: ExceptHandler :: ExceptHandler ( except_handler) => {
793+ if let Some ( expr) = & except_handler. type_ {
794+ self . visit_expr ( expr) ;
795+ }
796+ if let Some ( name) = & except_handler. name {
797+ self . add_token (
798+ name. range ( ) ,
799+ SemanticTokenType :: Variable ,
800+ SemanticTokenModifier :: DEFINITION ,
801+ ) ;
802+ }
803+ self . visit_body ( & except_handler. body ) ;
804+ }
805+ }
806+ }
807+ self . visit_body ( & try_stmt. orelse ) ;
808+ self . visit_body ( & try_stmt. finalbody ) ;
809+ }
750810
751811 _ => {
752812 // For all other statement types, let the default visitor handle them
@@ -1304,7 +1364,7 @@ result = check(None)
13041364 ) ;
13051365
13061366 assert_snapshot ! ( test. to_snapshot( & test. highlight_file( ) ) , @r#"
1307- "U" @ 6..7: TypeParameter
1367+ "U" @ 6..7: Class [definition]
13081368 "str" @ 10..13: Class
13091369 "int" @ 16..19: Class
13101370 "Test" @ 27..31: Class [definition]
@@ -2405,16 +2465,16 @@ finally:
24052465 "1" @ 14..15: Number
24062466 "0" @ 18..19: Number
24072467 "ValueError" @ 27..37: Class
2408- "ve" @ 41..43: Variable
2468+ "ve" @ 41..43: Variable [definition]
24092469 "print" @ 49..54: Function
24102470 "ve" @ 55..57: Variable
24112471 "TypeError" @ 67..76: Class
24122472 "RuntimeError" @ 78..90: Class
2413- "re" @ 95..97: Variable
2473+ "re" @ 95..97: Variable [definition]
24142474 "print" @ 103..108: Function
24152475 "re" @ 109..111: Variable
24162476 "Exception" @ 120..129: Class
2417- "e" @ 133..134: Variable
2477+ "e" @ 133..134: Variable [definition]
24182478 "print" @ 140..145: Function
24192479 "e" @ 146..147: Variable
24202480 "# ) ;
@@ -2460,6 +2520,81 @@ class C:
24602520 "# ) ;
24612521 }
24622522
2523+ #[ test]
2524+ fn test_augmented_assignment ( ) {
2525+ let test = SemanticTokenTest :: new (
2526+ r#"
2527+ x = 0
2528+ x += 1
2529+ "# ,
2530+ ) ;
2531+
2532+ let tokens = test. highlight_file ( ) ;
2533+
2534+ assert_snapshot ! ( test. to_snapshot( & tokens) , @r#"
2535+ "x" @ 1..2: Variable [definition]
2536+ "0" @ 5..6: Number
2537+ "x" @ 7..8: Variable
2538+ "1" @ 12..13: Number
2539+ "# ) ;
2540+ }
2541+
2542+ #[ test]
2543+ fn test_type_alias ( ) {
2544+ let test = SemanticTokenTest :: new ( "type MyList[T] = list[T]" ) ;
2545+
2546+ let tokens = test. highlight_file ( ) ;
2547+
2548+ assert_snapshot ! ( test. to_snapshot( & tokens) , @r#"
2549+ "MyList" @ 5..11: Class [definition]
2550+ "T" @ 12..13: TypeParameter [definition]
2551+ "list" @ 17..21: Class
2552+ "T" @ 22..23: TypeParameter
2553+ "# ) ;
2554+ }
2555+
2556+ #[ test]
2557+ fn test_for_stmt ( ) {
2558+ let test = SemanticTokenTest :: new (
2559+ r#"
2560+ for item in []:
2561+ print(item)
2562+ else:
2563+ print(0)
2564+ "# ,
2565+ ) ;
2566+
2567+ let tokens = test. highlight_file ( ) ;
2568+
2569+ assert_snapshot ! ( test. to_snapshot( & tokens) , @r#"
2570+ "item" @ 5..9: Variable [definition]
2571+ "print" @ 21..26: Function
2572+ "item" @ 27..31: Variable
2573+ "print" @ 43..48: Function
2574+ "0" @ 49..50: Number
2575+ "# ) ;
2576+ }
2577+
2578+ #[ test]
2579+ fn test_with_stmt ( ) {
2580+ let test = SemanticTokenTest :: new (
2581+ r#"
2582+ with open("file.txt") as f:
2583+ f.read()
2584+ "# ,
2585+ ) ;
2586+
2587+ let tokens = test. highlight_file ( ) ;
2588+
2589+ assert_snapshot ! ( test. to_snapshot( & tokens) , @r#"
2590+ "open" @ 6..10: Function
2591+ "\"file.txt\"" @ 11..21: String
2592+ "f" @ 26..27: Variable [definition]
2593+ "f" @ 33..34: Variable
2594+ "read" @ 35..39: Method
2595+ "# ) ;
2596+ }
2597+
24632598 /// Regression test for <https://github.com/astral-sh/ty/issues/1406>
24642599 #[ test]
24652600 fn test_invalid_kwargs ( ) {
0 commit comments