@@ -17,6 +17,7 @@ use crate::state::lsp::LocalRefactorCodeAction;
1717use crate :: state:: require:: Require ;
1818use crate :: state:: state:: State ;
1919use crate :: test:: util:: get_batched_lsp_operations_report_allow_error;
20+ use crate :: test:: util:: mk_multi_file_state;
2021use crate :: test:: util:: mk_multi_file_state_assert_no_errors;
2122
2223fn apply_patch ( info : & ModuleInfo , range : TextRange , patch : String ) -> ( String , String ) {
@@ -215,6 +216,36 @@ fn assert_no_invert_boolean_action(code: &str, selection: TextRange) {
215216 ) ;
216217}
217218
219+ fn compute_invert_boolean_actions_allow_errors (
220+ code : & str ,
221+ selection : TextRange ,
222+ ) -> (
223+ ModuleInfo ,
224+ Vec < Vec < ( Module , TextRange , String ) > > ,
225+ Vec < String > ,
226+ ) {
227+ let ( handles, state) = mk_multi_file_state ( & [ ( "main" , code) ] , Require :: Everything , false ) ;
228+ let handle = handles. get ( "main" ) . unwrap ( ) ;
229+ let transaction = state. transaction ( ) ;
230+ let module_info = transaction. get_module_info ( handle) . unwrap ( ) ;
231+ let actions = transaction
232+ . invert_boolean_code_actions ( handle, selection)
233+ . unwrap_or_default ( ) ;
234+ let edit_sets: Vec < Vec < ( Module , TextRange , String ) > > =
235+ actions. iter ( ) . map ( |action| action. edits . clone ( ) ) . collect ( ) ;
236+ let titles = actions. iter ( ) . map ( |action| action. title . clone ( ) ) . collect ( ) ;
237+ ( module_info, edit_sets, titles)
238+ }
239+
240+ fn assert_no_invert_boolean_action_allow_errors ( code : & str , selection : TextRange ) {
241+ let ( _, actions, _) = compute_invert_boolean_actions_allow_errors ( code, selection) ;
242+ assert ! (
243+ actions. is_empty( ) ,
244+ "expected no invert-boolean actions, found {}" ,
245+ actions. len( )
246+ ) ;
247+ }
248+
218249fn assert_no_extract_variable_action ( code : & str ) {
219250 let ( _, actions, _) = compute_extract_variable_actions ( code) ;
220251 assert ! (
@@ -915,6 +946,94 @@ def foo():
915946 assert_no_invert_boolean_action ( code, selection) ;
916947}
917948
949+ #[ test]
950+ fn invert_boolean_annotated_assignment ( ) {
951+ let code = r#"
952+ def foo():
953+ abc: bool = True
954+ return abc
955+ "# ;
956+ let selection = find_nth_range ( code, "abc" , 2 ) ;
957+ let updated =
958+ apply_first_invert_boolean_action ( code, selection) . expect ( "expected invert-boolean action" ) ;
959+ let expected = r#"
960+ def foo():
961+ abc: bool = False
962+ return (not abc)
963+ "# ;
964+ assert_eq ! ( expected. trim( ) , updated. trim( ) ) ;
965+ }
966+
967+ #[ test]
968+ fn invert_boolean_rejects_deleted_variable ( ) {
969+ let code = r#"
970+ def foo():
971+ abc = True
972+ del abc
973+ return abc
974+ "# ;
975+ let selection = find_nth_range ( code, "abc" , 3 ) ;
976+ assert_no_invert_boolean_action_allow_errors ( code, selection) ;
977+ }
978+
979+ #[ test]
980+ fn invert_boolean_multiple_assignments ( ) {
981+ let code = r#"
982+ def foo():
983+ abc = True
984+ abc = False
985+ return abc
986+ "# ;
987+ let selection = find_nth_range ( code, "abc" , 3 ) ;
988+ let updated =
989+ apply_first_invert_boolean_action ( code, selection) . expect ( "expected invert-boolean action" ) ;
990+ let expected = r#"
991+ def foo():
992+ abc = True
993+ abc = True
994+ return (not abc)
995+ "# ;
996+ assert_eq ! ( expected. trim( ) , updated. trim( ) ) ;
997+ }
998+
999+ #[ test]
1000+ fn invert_boolean_nested_expression_keeps_outer_not ( ) {
1001+ let code = r#"
1002+ def foo():
1003+ abc = True
1004+ other = True
1005+ return not (abc and other)
1006+ "# ;
1007+ let selection = find_nth_range ( code, "abc" , 2 ) ;
1008+ let updated =
1009+ apply_first_invert_boolean_action ( code, selection) . expect ( "expected invert-boolean action" ) ;
1010+ let expected = r#"
1011+ def foo():
1012+ abc = False
1013+ other = True
1014+ return not ((not abc) and other)
1015+ "# ;
1016+ assert_eq ! ( expected. trim( ) , updated. trim( ) ) ;
1017+ }
1018+
1019+ #[ test]
1020+ fn invert_boolean_inverts_unary_not_assignment_value ( ) {
1021+ let code = r#"
1022+ def foo(other_var):
1023+ abc = not other_var
1024+ return abc
1025+ "# ;
1026+ let selection = find_nth_range ( code, "abc" , 2 ) ;
1027+ let updated =
1028+ apply_first_invert_boolean_action ( code, selection) . expect ( "expected invert-boolean action" ) ;
1029+ let expected = r#"
1030+ def foo(other_var):
1031+ abc = other_var
1032+ return (not abc)
1033+ "# ;
1034+ assert_eq ! ( expected. trim( ) , updated. trim( ) ) ;
1035+ }
1036+
9181037#[ test]
9191038fn pull_member_up_basic ( ) {
9201039 let code = r#"
0 commit comments