CQ. Tweaks for InsertOnKeyword and tests.

Change-Id: I7dcdcbceb775fbf07c0bc27ab38a94bc02253086
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/394343
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/insert_on_keyword.dart b/pkg/analysis_server/lib/src/services/correction/dart/insert_on_keyword.dart
index ec31007..ed3ce8f 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/insert_on_keyword.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/insert_on_keyword.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/utilities/extensions/object.dart';
 import 'package:analysis_server_plugin/edit/dart/correction_producer.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
@@ -25,25 +26,39 @@
 
   @override
   Future<void> compute(ChangeBuilder builder) async {
-    var node = this.node;
-    if (node is! ExtensionDeclaration) {
-      if (node.parent case ExtensionDeclaration parent) {
-        node = parent;
-      } else {
-        return;
-      }
+    var extension =
+        node.ifTypeOrNull<ExtensionDeclaration>() ??
+        node.parent.ifTypeOrNull<ExtensionDeclaration>();
+    if (extension == null) {
+      return;
     }
 
-    var onClause = node.onClause;
-    if (onClause != null && onClause.onKeyword.isSynthetic) {
-      var onOffset = onClause.onKeyword.offset;
-      if (onClause.extendedType.length == 0) {
-        onOffset = node.name?.offset ?? onOffset;
-      }
-
-      await builder.addDartFileEdit(file, (builder) {
-        builder.addSimpleInsertion(onOffset, 'on ');
-      });
+    var onClause = extension.onClause;
+    if (onClause == null) {
+      return;
     }
+
+    var name = extension.name;
+    var onKeyword = onClause.onKeyword;
+    var extendedType = onClause.extendedType;
+
+    // We don't expect this.
+    if (name == null || name.isSynthetic) {
+      return;
+    }
+
+    // Otherwise this is not our error to fix.
+    if (!onKeyword.isSynthetic) {
+      return;
+    }
+
+    // `extension int {}`
+    // `extension E int {}`
+    var insertOffset =
+        extendedType.isSynthetic ? name.offset : extendedType.offset;
+
+    await builder.addDartFileEdit(file, (builder) {
+      builder.addSimpleInsertion(insertOffset, 'on ');
+    });
   }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/fix/insert_on_keyword_test.dart b/pkg/analysis_server/test/src/services/correction/fix/insert_on_keyword_test.dart
index f1609c1..d55317e 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/insert_on_keyword_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/insert_on_keyword_test.dart
@@ -19,7 +19,7 @@
 
 @reflectiveTest
 class InsertOnKeywordMultiTest extends FixInFileProcessorTest {
-  Future<void> test_expected_onKeyword_multi() async {
+  Future<void> test_hasName() async {
     await resolveTestCode('''
 extension String {}
 extension String {}
@@ -40,7 +40,7 @@
   @override
   FixKind get kind => DartFixKind.INSERT_ON_KEYWORD;
 
-  Future<void> test_expected_onKeyword() async {
+  Future<void> test_hasName() async {
     await resolveTestCode('''
 extension int {}
 ''');
@@ -54,7 +54,7 @@
     );
   }
 
-  Future<void> test_expected_onKeyword_betweenNameAndType() async {
+  Future<void> test_hasName_hasType() async {
     await resolveTestCode('''
 extension E int {}
 ''');
@@ -63,7 +63,16 @@
 ''');
   }
 
-  Future<void> test_expected_onKeyword_betweenTypeParameterAndType() async {
+  Future<void> test_hasName_hasType_withTypeArguments() async {
+    await resolveTestCode('''
+extension E List<int> {}
+''');
+    await assertHasFix('''
+extension E on List<int> {}
+''');
+  }
+
+  Future<void> test_hasName_hasTypeParameters_noType() async {
     await resolveTestCode('''
 extension E<T> int {}
 ''');
@@ -72,36 +81,7 @@
 ''');
   }
 
-  Future<void> test_expected_onKeyword_nonType() async {
-    await resolveTestCode('''
-extension UnresolvedType {}
-''');
-    await assertHasFix(
-      '''
-extension on UnresolvedType {}
-''',
-      errorFilter: (error) {
-        return error.errorCode == ParserErrorCode.EXPECTED_TOKEN;
-      },
-    );
-  }
-
-  Future<void> test_expected_onKeyword_nonTypeWithTypeArguments() async {
-    // We want to believe that the type parameter is from the undefined type.
-    await resolveTestCode('''
-extension UnresolvedType<T> {}
-''');
-    await assertHasFix(
-      '''
-extension on UnresolvedType<T> {}
-''',
-      errorFilter: (error) {
-        return error.errorCode == ParserErrorCode.EXPECTED_TOKEN;
-      },
-    );
-  }
-
-  Future<void> test_expected_onKeyword_typeWithTypeArguments() async {
+  Future<void> test_noName_hasType_withTypeArguments() async {
     await resolveTestCode('''
 extension List<int> {}
 ''');