Augment. Fix semantic highlighting for functions / getters / setters.

Change-Id: I2f42d10e0d4b6a994e11ef40120a7e7fac91a15b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/355506
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index 58b8a4e..9095ac9 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -1008,9 +1008,8 @@
 
   @override
   void visitFunctionDeclaration(FunctionDeclaration node) {
-    // TODO(brianwilkerson): Update the interface to expose the token.
-    // computer._addRegion_token(
-    //     node.augmentKeyword, HighlightRegionType.BUILT_IN);
+    computer._addRegion_token(
+        node.augmentKeyword, HighlightRegionType.BUILT_IN);
     computer._addRegion_token(
         node.externalKeyword, HighlightRegionType.BUILT_IN);
     computer._addRegion_token(
@@ -1542,10 +1541,8 @@
 
   @override
   void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    // TODO(brianwilkerson): Uncomment the following lines when the token is
-    //  supported.
-    // computer._addRegion_token(
-    //     node.augmentKeyword, HighlightRegionType.BUILT_IN);
+    computer._addRegion_token(
+        node.augmentKeyword, HighlightRegionType.BUILT_IN);
     computer._addRegion_token(
         node.externalKeyword, HighlightRegionType.BUILT_IN);
 
diff --git a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
index 8ba5537..b29d57e 100644
--- a/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_highlights2_test.dart
@@ -228,7 +228,6 @@
     assertHasRegion(HighlightRegionType.BUILT_IN, 'augment');
   }
 
-  @SkippedTest(reason: 'The token is not supported')
   Future<void> test_BUILT_IN_augment_onTopLevelFunction() async {
     addTestFile('''
 augment int f(int x) => 0;
@@ -237,7 +236,6 @@
     assertHasRegion(HighlightRegionType.BUILT_IN, 'augment');
   }
 
-  @SkippedTest(reason: 'The token is not supported')
   Future<void> test_BUILT_IN_augment_onTopLevelGetter() async {
     addTestFile('''
 augment int get g => 0;
@@ -246,7 +244,6 @@
     assertHasRegion(HighlightRegionType.BUILT_IN, 'augment');
   }
 
-  @SkippedTest(reason: 'The token is not supported')
   Future<void> test_BUILT_IN_augment_onTopLevelSetter() async {
     addTestFile('''
 augment set s(int x) {}
@@ -255,7 +252,6 @@
     assertHasRegion(HighlightRegionType.BUILT_IN, 'augment');
   }
 
-  @SkippedTest(reason: 'The token is not supported')
   Future<void> test_BUILT_IN_augment_onTopLevelVariable() async {
     addTestFile('''
 augment int v = 0;
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 9317c72..d28e02e 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -8235,6 +8235,10 @@
 ///    functionSignature ::=
 ///        [Type]? ('get' | 'set')? name [FormalParameterList]
 abstract final class FunctionDeclaration implements NamedCompilationUnitMember {
+  /// The 'augment' keyword.
+  @experimental
+  Token? get augmentKeyword;
+
   @override
   ExecutableElement? get declaredElement;
 
@@ -8273,8 +8277,7 @@
 ///        [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList]
 final class FunctionDeclarationImpl extends NamedCompilationUnitMemberImpl
     implements FunctionDeclaration {
-  /// The token representing the 'augment' keyword, or `null` if this is not an
-  /// function augmentation.
+  @override
   final Token? augmentKeyword;
 
   /// The token representing the 'external' keyword, or `null` if this is not an
diff --git a/pkg/analyzer/test/src/dart/parser/test_all.dart b/pkg/analyzer/test/src/dart/parser/test_all.dart
index decd91c..1762cff 100644
--- a/pkg/analyzer/test/src/dart/parser/test_all.dart
+++ b/pkg/analyzer/test/src/dart/parser/test_all.dart
@@ -8,6 +8,7 @@
 import 'doc_comment_test.dart' as doc_comment;
 import 'extension_type_test.dart' as extension_type;
 import 'mixin_test.dart' as mixin_;
+import 'top_level_function_test.dart' as top_level_function;
 import 'top_level_variable_test.dart' as top_level_variable;
 
 /// Utility for manually running all tests.
@@ -17,6 +18,7 @@
     doc_comment.main();
     extension_type.main();
     mixin_.main();
+    top_level_function.main();
     top_level_variable.main();
   }, name: 'parser');
 }
diff --git a/pkg/analyzer/test/src/dart/parser/top_level_function_test.dart b/pkg/analyzer/test/src/dart/parser/top_level_function_test.dart
new file mode 100644
index 0000000..cb088ff
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/parser/top_level_function_test.dart
@@ -0,0 +1,93 @@
+// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../diagnostics/parser_diagnostics.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TopLevelFunctionParserTest);
+  });
+}
+
+@reflectiveTest
+class TopLevelFunctionParserTest extends ParserDiagnosticsTest {
+  test_function_augment() {
+    final parseResult = parseStringWithErrors(r'''
+library augment 'a.dart';
+augment void foo() {}
+''');
+    parseResult.assertNoErrors();
+
+    final node = parseResult.findNode.singleFunctionDeclaration;
+    assertParsedNodeText(node, r'''
+FunctionDeclaration
+  augmentKeyword: augment
+  returnType: NamedType
+    name: void
+  name: foo
+  functionExpression: FunctionExpression
+    parameters: FormalParameterList
+      leftParenthesis: (
+      rightParenthesis: )
+    body: BlockFunctionBody
+      block: Block
+        leftBracket: {
+        rightBracket: }
+''');
+  }
+
+  test_getter_augment() {
+    final parseResult = parseStringWithErrors(r'''
+library augment 'a.dart';
+augment int get foo => 0;
+''');
+    parseResult.assertNoErrors();
+
+    final node = parseResult.findNode.singleFunctionDeclaration;
+    assertParsedNodeText(node, r'''
+FunctionDeclaration
+  augmentKeyword: augment
+  returnType: NamedType
+    name: int
+  propertyKeyword: get
+  name: foo
+  functionExpression: FunctionExpression
+    body: ExpressionFunctionBody
+      functionDefinition: =>
+      expression: IntegerLiteral
+        literal: 0
+      semicolon: ;
+''');
+  }
+
+  test_setter_augment() {
+    final parseResult = parseStringWithErrors(r'''
+library augment 'a.dart';
+augment set foo(int _) {}
+''');
+    parseResult.assertNoErrors();
+
+    final node = parseResult.findNode.singleFunctionDeclaration;
+    assertParsedNodeText(node, r'''
+FunctionDeclaration
+  augmentKeyword: augment
+  propertyKeyword: set
+  name: foo
+  functionExpression: FunctionExpression
+    parameters: FormalParameterList
+      leftParenthesis: (
+      parameter: SimpleFormalParameter
+        type: NamedType
+          name: int
+        name: _
+      rightParenthesis: )
+    body: BlockFunctionBody
+      block: Block
+        leftBracket: {
+        rightBracket: }
+''');
+  }
+}