@@ -698,6 +698,260 @@ _f(bool/*?*/ x) => ((x) != (null)) && x;
698698 visitSubexpression (findNode.binary ('&&' ), 'bool' );
699699 }
700700
701+ test_postfixExpression_combined_nullable_noProblem () async {
702+ await analyze ('''
703+ abstract class _C {
704+ _D/*?*/ operator+(int/*!*/ value);
705+ }
706+ abstract class _D extends _C {}
707+ abstract class _E {
708+ _C/*!*/ get x;
709+ void set x(_C/*?*/ value);
710+ f() => x++;
711+ }
712+ ''' );
713+ visitSubexpression (findNode.postfix ('++' ), '_C' );
714+ }
715+
716+ @FailingTest (issue: 'https://github.com/dart-lang/sdk/issues/38833' )
717+ test_postfixExpression_combined_nullable_noProblem_dynamic () async {
718+ await analyze ('''
719+ abstract class _E {
720+ dynamic get x;
721+ void set x(Object/*!*/ value);
722+ f() => x++;
723+ }
724+ ''' );
725+ visitSubexpression (findNode.postfix ('++' ), 'dynamic' );
726+ }
727+
728+ test_postfixExpression_combined_nullable_problem () async {
729+ await analyze ('''
730+ abstract class _C {
731+ _D/*?*/ operator+(int/*!*/ value);
732+ }
733+ abstract class _D extends _C {}
734+ abstract class _E {
735+ _C/*!*/ get x;
736+ void set x(_C/*!*/ value);
737+ f() => x++;
738+ }
739+ ''' );
740+ var postfix = findNode.postfix ('++' );
741+ visitSubexpression (postfix, '_C' , problems: {
742+ postfix: {const CompoundAssignmentCombinedNullable ()}
743+ });
744+ }
745+
746+ test_postfixExpression_dynamic () async {
747+ await analyze ('''
748+ _f(dynamic x) => x++;
749+ ''' );
750+ visitSubexpression (findNode.postfix ('++' ), 'dynamic' );
751+ }
752+
753+ test_postfixExpression_lhs_nullable_problem () async {
754+ await analyze ('''
755+ abstract class _C {
756+ _D/*!*/ operator+(int/*!*/ value);
757+ }
758+ abstract class _D extends _C {}
759+ abstract class _E {
760+ _C/*?*/ get x;
761+ void set x(_C/*?*/ value);
762+ f() => x++;
763+ }
764+ ''' );
765+ var postfix = findNode.postfix ('++' );
766+ visitSubexpression (postfix, '_C?' , problems: {
767+ postfix: {const CompoundAssignmentReadNullable ()}
768+ });
769+ }
770+
771+ test_postfixExpression_rhs_nonNullable () async {
772+ await analyze ('''
773+ abstract class _C {
774+ _D/*!*/ operator+(int/*!*/ value);
775+ }
776+ abstract class _D extends _C {}
777+ _f(_C/*!*/ x) => x++;
778+ ''' );
779+ visitSubexpression (findNode.postfix ('++' ), '_C' );
780+ }
781+
782+ test_prefixExpression_bang_flow () async {
783+ await analyze ('''
784+ _f(int/*?*/ x) {
785+ if (!(x == null)) {
786+ x + 1;
787+ }
788+ }
789+ ''' );
790+ // No null check should be needed on `x + 1` because `!(x == null)` promotes
791+ // x's type to `int`.
792+ visitStatement (findNode.statement ('if' ));
793+ }
794+
795+ test_prefixExpression_bang_nonNullable () async {
796+ await analyze ('''
797+ _f(bool/*!*/ x) => !x;
798+ ''' );
799+ visitSubexpression (findNode.prefix ('!x' ), 'bool' );
800+ }
801+
802+ test_prefixExpression_bang_nullable () async {
803+ await analyze ('''
804+ _f(bool/*?*/ x) => !x;
805+ ''' );
806+ visitSubexpression (findNode.prefix ('!x' ), 'bool' ,
807+ nullChecked: {findNode.simple ('x;' )});
808+ }
809+
810+ test_prefixExpression_combined_nullable_noProblem () async {
811+ await analyze ('''
812+ abstract class _C {
813+ _D/*?*/ operator+(int/*!*/ value);
814+ }
815+ abstract class _D extends _C {}
816+ abstract class _E {
817+ _C/*!*/ get x;
818+ void set x(_C/*?*/ value);
819+ f() => ++x;
820+ }
821+ ''' );
822+ visitSubexpression (findNode.prefix ('++' ), '_D?' );
823+ }
824+
825+ test_prefixExpression_combined_nullable_noProblem_dynamic () async {
826+ await analyze ('''
827+ abstract class _E {
828+ dynamic get x;
829+ void set x(Object/*!*/ value);
830+ f() => ++x;
831+ }
832+ ''' );
833+ var prefix = findNode.prefix ('++' );
834+ visitSubexpression (prefix, 'dynamic' );
835+ }
836+
837+ test_prefixExpression_combined_nullable_problem () async {
838+ await analyze ('''
839+ abstract class _C {
840+ _D/*?*/ operator+(int/*!*/ value);
841+ }
842+ abstract class _D extends _C {}
843+ abstract class _E {
844+ _C/*!*/ get x;
845+ void set x(_C/*!*/ value);
846+ f() => ++x;
847+ }
848+ ''' );
849+ var prefix = findNode.prefix ('++' );
850+ visitSubexpression (prefix, '_D' , problems: {
851+ prefix: {const CompoundAssignmentCombinedNullable ()}
852+ });
853+ }
854+
855+ test_prefixExpression_intRules () async {
856+ await analyze ('''
857+ _f(int x) => ++x;
858+ ''' );
859+ visitSubexpression (findNode.prefix ('++' ), 'int' );
860+ }
861+
862+ test_prefixExpression_lhs_nullable_problem () async {
863+ await analyze ('''
864+ abstract class _C {
865+ _D/*!*/ operator+(int/*!*/ value);
866+ }
867+ abstract class _D extends _C {}
868+ abstract class _E {
869+ _C/*?*/ get x;
870+ void set x(_C/*?*/ value);
871+ f() => ++x;
872+ }
873+ ''' );
874+ var prefix = findNode.prefix ('++' );
875+ visitSubexpression (prefix, '_D' , problems: {
876+ prefix: {const CompoundAssignmentReadNullable ()}
877+ });
878+ }
879+
880+ test_prefixExpression_minus_dynamic () async {
881+ await analyze ('''
882+ _f(dynamic x) => -x;
883+ ''' );
884+ visitSubexpression (findNode.prefix ('-x' ), 'dynamic' );
885+ }
886+
887+ test_prefixExpression_minus_nonNullable () async {
888+ await analyze ('''
889+ _f(int/*!*/ x) => -x;
890+ ''' );
891+ visitSubexpression (findNode.prefix ('-x' ), 'int' );
892+ }
893+
894+ test_prefixExpression_minus_nullable () async {
895+ await analyze ('''
896+ _f(int/*?*/ x) => -x;
897+ ''' );
898+ visitSubexpression (findNode.prefix ('-x' ), 'int' ,
899+ nullChecked: {findNode.simple ('x;' )});
900+ }
901+
902+ test_prefixExpression_minus_substitution () async {
903+ await analyze ('''
904+ abstract class _C<T> {
905+ List<T> operator-();
906+ }
907+ _f(_C<int> x) => -x;
908+ ''' );
909+ visitSubexpression (findNode.prefix ('-x' ), 'List<int>' );
910+ }
911+
912+ test_prefixExpression_rhs_nonNullable () async {
913+ await analyze ('''
914+ abstract class _C {
915+ _D/*!*/ operator+(int/*!*/ value);
916+ }
917+ abstract class _D extends _C {}
918+ _f(_C/*!*/ x) => ++x;
919+ ''' );
920+ visitSubexpression (findNode.prefix ('++' ), '_D' );
921+ }
922+
923+ test_prefixExpression_tilde_dynamic () async {
924+ await analyze ('''
925+ _f(dynamic x) => ~x;
926+ ''' );
927+ visitSubexpression (findNode.prefix ('~x' ), 'dynamic' );
928+ }
929+
930+ test_prefixExpression_tilde_nonNullable () async {
931+ await analyze ('''
932+ _f(int/*!*/ x) => ~x;
933+ ''' );
934+ visitSubexpression (findNode.prefix ('~x' ), 'int' );
935+ }
936+
937+ test_prefixExpression_tilde_nullable () async {
938+ await analyze ('''
939+ _f(int/*?*/ x) => ~x;
940+ ''' );
941+ visitSubexpression (findNode.prefix ('~x' ), 'int' ,
942+ nullChecked: {findNode.simple ('x;' )});
943+ }
944+
945+ test_prefixExpression_tilde_substitution () async {
946+ await analyze ('''
947+ abstract class _C<T> {
948+ List<T> operator~();
949+ }
950+ _f(_C<int> x) => ~x;
951+ ''' );
952+ visitSubexpression (findNode.prefix ('~x' ), 'List<int>' );
953+ }
954+
701955 test_simpleIdentifier_className () async {
702956 await analyze ('''
703957_f() => int;
0 commit comments