Add support for &&, || and ?? operators

Change-Id: Ibb6269b349b3d0ffcf1068442c70ef46a6f521eb
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/106948
Reviewed-by: Dan Rubel <danrubel@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/nnbd_migration/lib/src/graph_builder.dart b/pkg/nnbd_migration/lib/src/graph_builder.dart
index fa47018..863d161 100644
--- a/pkg/nnbd_migration/lib/src/graph_builder.dart
+++ b/pkg/nnbd_migration/lib/src/graph_builder.dart
@@ -214,6 +214,12 @@
             : conditionInfo.not(node);
       }
       return _nonNullableBoolType;
+    } else if (operatorType == TokenType.AMPERSAND_AMPERSAND ||
+        operatorType == TokenType.BAR_BAR ||
+        operatorType == TokenType.QUESTION_QUESTION) {
+      _handleAssignment(_notNullType, node.leftOperand);
+      node.rightOperand.accept(this);
+      return _nonNullableBoolType;
     } else if (operatorType.isUserDefinableOperator) {
       _handleAssignment(_notNullType, node.leftOperand);
       var callee = node.staticElement;
@@ -228,6 +234,8 @@
       return calleeType.returnType;
     } else {
       // TODO(paulberry)
+      node.leftOperand.accept(this);
+      node.rightOperand.accept(this);
       _unimplemented(
           node, 'Binary expression with operator ${node.operator.lexeme}');
     }
diff --git a/pkg/nnbd_migration/test/graph_builder_test.dart b/pkg/nnbd_migration/test/graph_builder_test.dart
index f3a938e..d48ce18 100644
--- a/pkg/nnbd_migration/test/graph_builder_test.dart
+++ b/pkg/nnbd_migration/test/graph_builder_test.dart
@@ -294,6 +294,14 @@
     assertNoUpstreamNullability(decoratedTypeAnnotation('int f').node);
   }
 
+  test_binaryExpression_ampersandAmpersand() async {
+    await analyze('''
+bool f(bool i, bool j) => i && j;
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('bool i').node);
+  }
+
   test_binaryExpression_bar_result_not_null() async {
     await analyze('''
 int f(int i, int j) => i | j;
@@ -302,6 +310,14 @@
     assertNoUpstreamNullability(decoratedTypeAnnotation('int f').node);
   }
 
+  test_binaryExpression_barBar() async {
+    await analyze('''
+bool f(bool i, bool j) => i || j;
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('bool i').node);
+  }
+
   test_binaryExpression_caret_result_not_null() async {
     await analyze('''
 int f(int i, int j) => i ^ j;
@@ -458,6 +474,14 @@
             hard: true));
   }
 
+  test_binaryExpression_questionQuestion() async {
+    await analyze('''
+int f(int i, int j) => i ?? j;
+''');
+
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int i').node);
+  }
+
   test_binaryExpression_slash_result_not_null() async {
     await analyze('''
 double f(int i, int j) => i / j;