Fix an exception in sort_constructors_first

Change-Id: I08f4f626e948240e4a6e6faba190714f3c22d155
Fixes: https://github.com/dart-lang/sdk/issues/48966
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/245622
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
Auto-Submit: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/sort_constructor_first.dart b/pkg/analysis_server/lib/src/services/correction/dart/sort_constructor_first.dart
index f0a7e65..26c80f4 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/sort_constructor_first.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/sort_constructor_first.dart
@@ -4,6 +4,7 @@
 
 import 'package:analysis_server/src/services/correction/dart/abstract_producer.dart';
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/utilities/extensions/ast.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
@@ -32,7 +33,7 @@
 
     await builder.addDartFileEdit(file, (builder) {
       var deletionRange = range.endEnd(
-        constructor.beginToken.previous!,
+        constructor.firstNonCommentToken.previous!,
         constructor.endToken,
       );
 
diff --git a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
index b92d957..84e8908 100644
--- a/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
+++ b/pkg/analysis_server/lib/src/utilities/extensions/ast.dart
@@ -7,6 +7,17 @@
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 
+extension AnnotatedNodeExtensions on AnnotatedNode {
+  /// Return the first token in this node that is not a comment.
+  Token get firstNonCommentToken {
+    final metadata = this.metadata;
+    if (metadata.isEmpty) {
+      return firstTokenAfterCommentAndMetadata;
+    }
+    return metadata.beginToken!;
+  }
+}
+
 extension AstNodeExtensions on AstNode {
   /// Return the [IfStatement] associated with `this`.
   IfStatement? get enclosingIfStatement {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/sort_constructor_first_test.dart b/pkg/analysis_server/test/src/services/correction/fix/sort_constructor_first_test.dart
index c6a9dc9..db02f56 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/sort_constructor_first_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/sort_constructor_first_test.dart
@@ -80,10 +80,6 @@
   @override
   String get lintCode => LintNames.sort_constructors_first;
 
-  @FailingTest(
-    reason: 'The beginToken is the comment, which has no previous token.',
-    issue: 'https://github.com/dart-lang/sdk/issues/48966',
-  )
   Future<void> test_hasComment() async {
     await resolveTestCode('''
 class A {
@@ -101,10 +97,6 @@
 ''');
   }
 
-  @FailingTest(
-    reason: 'The beginToken is the comment, which has no previous token.',
-    issue: 'https://github.com/dart-lang/sdk/issues/48966',
-  )
   Future<void> test_hasComment_hasMetadata_afterComment() async {
     await resolveTestCode('''
 const a = 0;