DAS: eight-digit hex: respect x case and expected triplet separators

Cq-Include-Trybots: luci.dart.try:flutter-analyze-try,analyzer-win-release-try,pkg-win-release-try
Change-Id: Icc444c1d6ac80e6b5c6c98c1e8d64506fbec5820
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/375723
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart
index e8ba6fd..f5883c0 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/replace_with_eight_digit_hex.dart
@@ -13,6 +13,9 @@
 class ReplaceWithEightDigitHex extends ResolvedCorrectionProducer {
   static final _underscoresPattern = RegExp('_+');
 
+  static final _tripletWithUnderscoresPattern =
+      RegExp(r'^[0-9a-fA-F]{2}_[0-9a-fA-F]{2}_[0-9a-fA-F]{2}$');
+
   /// The replacement text, used as an argument to the fix message.
   String _replacement = '';
 
@@ -39,14 +42,25 @@
         // The original string should be a substring of the replacement
         // (ignoring the '0x'). If there are existing separators, preserve them.
         var originalDigits = literal.lexeme.substring('0x'.length);
-        var originalWithoutSeparators =
-            originalDigits.replaceAll(_underscoresPattern, '');
-        var numberOfDigitsToAdd =
-            replacementDigits.length - originalWithoutSeparators.length;
-        var newLeadingDigits = '0' * numberOfDigitsToAdd;
-        replacementDigits = '$newLeadingDigits$originalDigits';
+        if (_tripletWithUnderscoresPattern.hasMatch(originalDigits)) {
+          replacementDigits = '00_$originalDigits';
+        } else {
+          var originalWithoutSeparators =
+              originalDigits.replaceAll(_underscoresPattern, '');
+          var numberOfDigitsToAdd =
+              replacementDigits.length - originalWithoutSeparators.length;
+          var newLeadingDigits = '0' * numberOfDigitsToAdd;
+          replacementDigits = '$newLeadingDigits$originalDigits';
+        }
       }
-      _replacement = '0x$replacementDigits';
+      var hexIndicator = switch (literal.type) {
+        TokenType.HEXADECIMAL ||
+        TokenType.HEXADECIMAL_WITH_SEPARATORS =>
+          literal.lexeme.substring(0, '0x'.length),
+        // Defalt to lower-case.
+        _ => '0x',
+      };
+      _replacement = '$hexIndicator$replacementDigits';
       await builder.addDartFileEdit(file, (builder) {
         builder.addSimpleReplacement(range.node(node), _replacement);
       });
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_eight_digit_hex_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_eight_digit_hex_test.dart
index a4de97e..8d829a5 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_with_eight_digit_hex_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/replace_with_eight_digit_hex_test.dart
@@ -95,7 +95,49 @@
 ''');
   }
 
-  Future<void> test_sixDigitHex_withSeparators() async {
+  Future<void> test_sixDigitHex_capitalX() async {
+    await resolveTestCode('''
+library dart.ui;
+
+var c = Color(0X000001);
+
+class Color {
+  Color(int value);
+}
+''');
+    await assertHasFix('''
+library dart.ui;
+
+var c = Color(0X00000001);
+
+class Color {
+  Color(int value);
+}
+''');
+  }
+
+  Future<void> test_sixDigitHex_withIrregularSeparators() async {
+    await resolveTestCode('''
+library dart.ui;
+
+var c = Color(0x000__001);
+
+class Color {
+  Color(int value);
+}
+''');
+    await assertHasFix('''
+library dart.ui;
+
+var c = Color(0x00000__001);
+
+class Color {
+  Color(int value);
+}
+''');
+  }
+
+  Future<void> test_sixDigitHex_withTripletSeparators() async {
     await resolveTestCode('''
 library dart.ui;
 
@@ -108,7 +150,7 @@
     await assertHasFix('''
 library dart.ui;
 
-var c = Color(0x0000_00_01);
+var c = Color(0x00_00_00_01);
 
 class Color {
   Color(int value);