[analyzer] change range of dead code of the RHS of binary operator

Bug: #43511
Change-Id: I1b1562c0262101900dabea3544bfc28293d5c7f6
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/260109
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_code.dart b/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_code.dart
index 8260a5b..736b1ff 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_code.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/remove_dead_code.dart
@@ -20,6 +20,23 @@
   bool get canBeAppliedToFile => false;
 
   @override
+  AstNode? get coveredNode {
+    var node = super.coveredNode;
+    if (node is BinaryExpression) {
+      var problemMessage = diagnostic?.problemMessage;
+      if (problemMessage != null) {
+        var operatorOffset = node.operator.offset;
+        var rightOperand = node.rightOperand;
+        if (problemMessage.offset == operatorOffset &&
+            problemMessage.length == rightOperand.end - operatorOffset) {
+          return rightOperand;
+        }
+      }
+    }
+    return node;
+  }
+
+  @override
   FixKind get fixKind => DartFixKind.REMOVE_DEAD_CODE;
 
   @override
diff --git a/pkg/analyzer/lib/src/error/dead_code_verifier.dart b/pkg/analyzer/lib/src/error/dead_code_verifier.dart
index 299efec..1fa83bd 100644
--- a/pkg/analyzer/lib/src/error/dead_code_verifier.dart
+++ b/pkg/analyzer/lib/src/error/dead_code_verifier.dart
@@ -160,17 +160,13 @@
         var lhsResult = _getConstantBooleanValue(lhsCondition);
         if (lhsResult != null) {
           var value = lhsResult.value?.toBoolValue();
-          if (value == true && isBarBar) {
-            // Report error on "else" block: true || !e!
-            _errorReporter.reportErrorForNode(
-                HintCode.DEAD_CODE, node.rightOperand);
-            // Only visit the LHS:
-            lhsCondition.accept(this);
-            return;
-          } else if (value == false && isAmpAmp) {
-            // Report error on "if" block: false && !e!
-            _errorReporter.reportErrorForNode(
-                HintCode.DEAD_CODE, node.rightOperand);
+          // Report error on "else" block: true || !e!
+          // or on "if" block: false && !e!
+          if (value == true && isBarBar || value == false && isAmpAmp) {
+            var offset = node.operator.offset;
+            var length = node.rightOperand.end - offset;
+            _errorReporter.reportErrorForOffset(
+                HintCode.DEAD_CODE, offset, length);
             // Only visit the LHS:
             lhsCondition.accept(this);
             return;
@@ -496,6 +492,7 @@
         // because this causes nuisance warnings for redundant `!= null`
         // asserts.
       } else {
+        var offset = firstDeadNode.offset;
         // We know that [node] is the first dead node, or contains it.
         // So, technically the code code interval ends at the end of [node].
         // But we trim it to the last statement for presentation purposes.
@@ -518,9 +515,10 @@
           if (node is SwitchMember && node.statements.isNotEmpty) {
             node = node.statements.last;
           }
+        } else if (parent is BinaryExpression && node == parent.rightOperand) {
+          offset = parent.operator.offset;
         }
 
-        var offset = firstDeadNode.offset;
         var length = node.end - offset;
         _errorReporter.reportErrorForOffset(HintCode.DEAD_CODE, offset, length);
       }
diff --git a/pkg/analyzer/test/generated/non_error_resolver_test.dart b/pkg/analyzer/test/generated/non_error_resolver_test.dart
index 65622a4..f4b49bf 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_test.dart
@@ -2582,7 +2582,7 @@
   const A.b2(bool p) : v = true || p;
 }
 ''', [
-      error(HintCode.DEAD_CODE, 170, 1),
+      error(HintCode.DEAD_CODE, 167, 4),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/const_eval_type_bool_test.dart b/pkg/analyzer/test/src/diagnostics/const_eval_type_bool_test.dart
index db0701d..54af54a 100644
--- a/pkg/analyzer/test/src/diagnostics/const_eval_type_bool_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/const_eval_type_bool_test.dart
@@ -28,7 +28,7 @@
     await assertErrorsInCode('''
 const c = (true || 0);
 ''', [
-      error(HintCode.DEAD_CODE, 19, 1),
+      error(HintCode.DEAD_CODE, 16, 4),
       error(CompileTimeErrorCode.NON_BOOL_OPERAND, 19, 1),
     ]);
   }
diff --git a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
index 633998d..23adab6 100644
--- a/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/dead_code_test.dart
@@ -494,7 +494,7 @@
   bool b = false && false;
   print(b);
 }''', [
-      error(HintCode.DEAD_CODE, 26, 5),
+      error(HintCode.DEAD_CODE, 23, 8),
     ]);
   }
 
@@ -513,7 +513,7 @@
   bool b = false && (false && false);
   print(b);
 }''', [
-      error(HintCode.DEAD_CODE, 26, 16),
+      error(HintCode.DEAD_CODE, 23, 19),
     ]);
   }
 
@@ -523,7 +523,7 @@
   bool b = true || true;
   print(b);
 }''', [
-      error(HintCode.DEAD_CODE, 25, 4),
+      error(HintCode.DEAD_CODE, 22, 7),
     ]);
   }
 
@@ -544,7 +544,7 @@
   bool b = true || (false && false);
   print(b);
 }''', [
-      error(HintCode.DEAD_CODE, 25, 16),
+      error(HintCode.DEAD_CODE, 22, 19),
     ]);
   }
 
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
index 25d9dfb..add8a1e 100644
--- a/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/use_of_nullable_value_test.dart
@@ -1514,7 +1514,7 @@
   if(x || false) {}
 }
 ''', [
-      error(HintCode.DEAD_CODE, 33, 5),
+      error(HintCode.DEAD_CODE, 30, 8),
     ]);
   }