[cfe] Implement the desugaring for NullAssertPattern

Part of https://github.com/dart-lang/sdk/issues/49749

Change-Id: I56ac79a98eb4306daabec05d95f09bb18d248825
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/268961
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Chloe Stefantsova <cstefantsova@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
index 34e4a62..3cef561 100644
--- a/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/internal_ast.dart
@@ -5417,15 +5417,56 @@
   @override
   Expression? makeCondition(VariableDeclaration matchedExpressionVariable,
       InferenceVisitorBase inferenceVisitor) {
-    return new InvalidExpression(
-        "Unimplemented NullAssertPattern.makeCondition");
+    // nullCheckCondition: `matchedExpressionVariable`!
+    Expression nullCheckExpression = inferenceVisitor.engine.forest
+        .createNullCheck(
+            fileOffset,
+            inferenceVisitor.engine.forest
+                .createVariableGet(fileOffset, matchedExpressionVariable));
+
+    DartType typeWithoutNullabilityMarkers =
+        matchedExpressionVariable.type.toNonNull();
+
+    // intermediateVariable: `typeWithoutNullabilityMarkers` VAR =
+    //     `nullCheckExpression`;
+    //   ==> `typeWithoutNullabilityMarkers` VAR = `matchedExpressionVariable`!;
+    VariableDeclaration intermediateVariable = inferenceVisitor.engine.forest
+        .createVariableDeclarationForValue(nullCheckExpression,
+            type: typeWithoutNullabilityMarkers);
+
+    Expression? patternCondition =
+        pattern.makeCondition(intermediateVariable, inferenceVisitor);
+    if (patternCondition == null) {
+      // TODO(cstefantsova): As an optimization of the generated code size and
+      // the number of runtime checks, the null check in this case can be
+      // removed if any variable is initialized via this pattern, and therefore
+      // will have the cast in its initializer expression.
+
+      // return: let `intermediateVariable` in true
+      //   ==> let `typeWithoutNullabilityMarkers` VAR =
+      //       `matchedExpressionVariable`! in
+      //           true
+      return inferenceVisitor.engine.forest.createLet(intermediateVariable,
+          inferenceVisitor.engine.forest.createBoolLiteral(fileOffset, true));
+    } else {
+      // return: let `intermediateVariable` in `patternCondition`
+      //   ==> let `typeWithoutNullabilityMarkers` VAR =
+      //       `matchedExpressionVariable`! in
+      //           `patternCondition`
+      return inferenceVisitor.engine.forest
+          .createLet(intermediateVariable, patternCondition);
+    }
   }
 
   @override
   void createDeclaredVariableInitializers(Expression matchedExpression,
       DartType matchedType, InferenceVisitorBase inferenceVisitor) {
+    DartType matchedTypeWithoutNullabilityMarkers = matchedType.toNonNull();
     pattern.createDeclaredVariableInitializers(
-        matchedExpression, matchedType, inferenceVisitor);
+        inferenceVisitor.engine.forest
+            .createNullCheck(fileOffset, matchedExpression),
+        matchedTypeWithoutNullabilityMarkers,
+        inferenceVisitor);
   }
 
   @override
diff --git a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.strong.expect b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.strong.expect
index 897435b..758e485 100644
--- a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.strong.expect
+++ b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.strong.expect
@@ -3,8 +3,8 @@
 
 static method test(dynamic x) → dynamic {
   final dynamic #t1 = x;
-  if(invalid-expression "Unimplemented NullAssertPattern.makeCondition") {
-    dynamic y = #t1;
+  if(let final dynamic #t2 = #t1! in true) {
+    dynamic y = #t1!;
     {}
   }
 }
diff --git a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.strong.transformed.expect b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.strong.transformed.expect
index 897435b..758e485 100644
--- a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.strong.transformed.expect
@@ -3,8 +3,8 @@
 
 static method test(dynamic x) → dynamic {
   final dynamic #t1 = x;
-  if(invalid-expression "Unimplemented NullAssertPattern.makeCondition") {
-    dynamic y = #t1;
+  if(let final dynamic #t2 = #t1! in true) {
+    dynamic y = #t1!;
     {}
   }
 }
diff --git a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.expect b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.expect
index 897435b..758e485 100644
--- a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.expect
+++ b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.expect
@@ -3,8 +3,8 @@
 
 static method test(dynamic x) → dynamic {
   final dynamic #t1 = x;
-  if(invalid-expression "Unimplemented NullAssertPattern.makeCondition") {
-    dynamic y = #t1;
+  if(let final dynamic #t2 = #t1! in true) {
+    dynamic y = #t1!;
     {}
   }
 }
diff --git a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.modular.expect b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.modular.expect
index 897435b..758e485 100644
--- a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.modular.expect
@@ -3,8 +3,8 @@
 
 static method test(dynamic x) → dynamic {
   final dynamic #t1 = x;
-  if(invalid-expression "Unimplemented NullAssertPattern.makeCondition") {
-    dynamic y = #t1;
+  if(let final dynamic #t2 = #t1! in true) {
+    dynamic y = #t1!;
     {}
   }
 }
diff --git a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.transformed.expect b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.transformed.expect
index 897435b..758e485 100644
--- a/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.transformed.expect
+++ b/pkg/front_end/testcases/patterns/null_assert_inside_if_case.dart.weak.transformed.expect
@@ -3,8 +3,8 @@
 
 static method test(dynamic x) → dynamic {
   final dynamic #t1 = x;
-  if(invalid-expression "Unimplemented NullAssertPattern.makeCondition") {
-    dynamic y = #t1;
+  if(let final dynamic #t2 = #t1! in true) {
+    dynamic y = #t1!;
     {}
   }
 }