@@ -2597,6 +2597,72 @@ public void except_group() {
25972597 .hasMessage ("Parse error at line 2: except* clause must specify the type of the expected exception." );
25982598 }
25992599
2600+ /**
2601+ * except* body cannot contain continue, break or return instruction
2602+ */
2603+ @ Test
2604+ public void except_group_invalid_instruction () {
2605+ String code1 = "try:pass\n " +
2606+ "except* OSError:\n " +
2607+ " continue" ;
2608+ assertThatThrownBy (() -> parse (code1 , treeMaker ::fileInput ))
2609+ .isInstanceOf (RecognitionException .class )
2610+ .hasMessage ("Parse error at line 3: continue statement cannot appear in except* block." );
2611+
2612+ String code2 = "try:pass\n " +
2613+ "except* OSError:\n " +
2614+ " break" ;
2615+ assertThatThrownBy (() -> parse (code2 , treeMaker ::fileInput ))
2616+ .isInstanceOf (RecognitionException .class )
2617+ .hasMessage ("Parse error at line 3: break statement cannot appear in except* block." );
2618+
2619+ String code3 = "try:pass\n " +
2620+ "except* OSError:\n " +
2621+ " return" ;
2622+ assertThatThrownBy (() -> parse (code3 , treeMaker ::fileInput ))
2623+ .isInstanceOf (RecognitionException .class )
2624+ .hasMessage ("Parse error at line 3: return statement cannot appear in except* block." );
2625+
2626+ // should not return parse error if continue/break is in a loop
2627+ String code4 = "try:pass\n " +
2628+ "except* OSError:\n " +
2629+ " while true:break" ;
2630+ FileInput tree = parse (code4 , treeMaker ::fileInput );
2631+ TryStatement tryStatement = (TryStatement ) tree .statements ().statements ().get (0 );
2632+ assertThat (tryStatement .exceptClauses ().get (0 ).getKind ()).isEqualTo (Kind .EXCEPT_GROUP_CLAUSE );
2633+
2634+ String code5 = "try:pass\n " +
2635+ "except* OSError:\n " +
2636+ " for x in \" bob\" :continue" ;
2637+ tree = parse (code5 , treeMaker ::fileInput );
2638+ tryStatement = (TryStatement ) tree .statements ().statements ().get (0 );
2639+ assertThat (tryStatement .exceptClauses ().get (0 ).getKind ()).isEqualTo (Kind .EXCEPT_GROUP_CLAUSE );
2640+
2641+ // should not return parse error if return is in a function
2642+ String code6 = "try:pass\n " +
2643+ "except* OSError:\n " +
2644+ " def foo():return" ;
2645+ tree = parse (code6 , treeMaker ::fileInput );
2646+ tryStatement = (TryStatement ) tree .statements ().statements ().get (0 );
2647+ assertThat (tryStatement .exceptClauses ().get (0 ).getKind ()).isEqualTo (Kind .EXCEPT_GROUP_CLAUSE );
2648+
2649+ String code7 = "for x in range(42):\n " +
2650+ " try:pass\n " +
2651+ " except* OSError:\n " +
2652+ " continue" ;
2653+ assertThatThrownBy (() -> parse (code7 , treeMaker ::fileInput ))
2654+ .isInstanceOf (RecognitionException .class )
2655+ .hasMessage ("Parse error at line 4: continue statement cannot appear in except* block." );
2656+
2657+ String code8 = "def foo():\n " +
2658+ " try:pass\n " +
2659+ " except* OSError:\n " +
2660+ " continue" ;
2661+ assertThatThrownBy (() -> parse (code8 , treeMaker ::fileInput ))
2662+ .isInstanceOf (RecognitionException .class )
2663+ .hasMessage ("Parse error at line 4: continue statement cannot appear in except* block." );
2664+ }
2665+
26002666 @ Test
26012667 public void except_group_multiple () {
26022668 FileInput tree = parse ("try:pass\n except* OSError:pass\n except* ValueError:pass" , treeMaker ::fileInput );
0 commit comments