Augment. Use the scope of the container - library or augmentation.

This fixes resolution of metadata in library augmentations, and brings
us a step closer to supporting JsonSerializable.

Change-Id: I8874540cb020a40f551d72b842f1e75f2d3ad118
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/347424
Reviewed-by: Phil Quitslund <pquitslund@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 97f089a..d83a096 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -796,7 +796,7 @@
 
     unit.accept(ScopeResolverVisitor(
         _libraryElement, source, _typeProvider, errorListener,
-        nameScope: _libraryElement.scope));
+        nameScope: unitElement.enclosingElement.scope));
 
     // Nothing for RESOLVED_UNIT8?
     // Nothing for RESOLVED_UNIT9?
diff --git a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
index 3705301..20d1784 100644
--- a/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/metadata_resolver.dart
@@ -13,17 +13,18 @@
 
 class MetadataResolver extends ThrowingAstVisitor<void> {
   final Linker _linker;
-  final Scope _libraryScope;
+  final Scope _containerScope;
   final LibraryBuilder _libraryBuilder;
   final CompilationUnitElementImpl _unitElement;
-  Scope _scope;
+  late Scope _scope;
 
   MetadataResolver(
     this._linker,
     this._unitElement,
     this._libraryBuilder,
-  )   : _libraryScope = _libraryBuilder.element.scope,
-        _scope = _libraryBuilder.element.scope;
+  ) : _containerScope = _unitElement.enclosingElement.scope {
+    _scope = _containerScope;
+  }
 
   @override
   void visitAnnotation(covariant AnnotationImpl node) {
@@ -52,7 +53,7 @@
     try {
       node.members.accept(this);
     } finally {
-      _scope = _libraryScope;
+      _scope = _containerScope;
     }
   }
 
@@ -94,7 +95,7 @@
       node.constants.accept(this);
       node.members.accept(this);
     } finally {
-      _scope = _libraryScope;
+      _scope = _containerScope;
     }
   }
 
@@ -116,7 +117,7 @@
     try {
       node.members.accept(this);
     } finally {
-      _scope = _libraryScope;
+      _scope = _containerScope;
     }
   }
 
@@ -130,7 +131,7 @@
     try {
       node.members.accept(this);
     } finally {
-      _scope = _libraryScope;
+      _scope = _containerScope;
     }
   }
 
@@ -224,7 +225,7 @@
     try {
       node.members.accept(this);
     } finally {
-      _scope = _libraryScope;
+      _scope = _containerScope;
     }
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/macro_test.dart b/pkg/analyzer/test/src/dart/resolution/macro_test.dart
index e0f60e3..165fc03 100644
--- a/pkg/analyzer/test/src/dart/resolution/macro_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/macro_test.dart
@@ -477,16 +477,32 @@
     ]);
   }
 
-  @SkippedTest(reason: r'''
-CompileTimeErrorCode.FINAL_NOT_INITIALIZED [141, 3, "The final variable 'age' must be initialized.", "Try initializing the variable."]
-CompileTimeErrorCode.FINAL_NOT_INITIALIZED [161, 4, "The final variable 'name' must be initialized.", "Try initializing the variable."]
+  @FailingTest(reason: r'''
+ResolvedLibraryResult #0
+  element: package:test/test.dart
+  units
+    ResolvedUnitResult #1
+      path: /home/test/lib/test.dart
+      uri: package:test/test.dart
+      flags: exists isLibrary
+      errors
+        169 +3 FINAL_NOT_INITIALIZED
+        189 +4 FINAL_NOT_INITIALIZED
+    ResolvedUnitResult #2
+      path: /home/test/lib/test.macro.dart
+      uri: package:test/test.macro.dart
+      flags: exists isAugmentation isMacroAugmentation
+      errors
+        317 +13 DUPLICATE_CONSTRUCTOR
+        164 +4 FINAL_NOT_INITIALIZED_CONSTRUCTOR
 ''')
   test_example_jsonSerializable() async {
-    await assertNoErrorsInCode(r'''
+    newFile(testFile.path, r'''
 import 'json_serializable.dart';
 
 void f(Map<String, Object?> json) {
-  User.fromJson(json);
+  var user = User.fromJson(json);
+  user.toJson();
 }
 
 @JsonSerializable()
@@ -495,6 +511,23 @@
   final String name;
 }
 ''');
+
+    final session = contextFor(testFile).currentSession;
+    final result = await session.getResolvedLibrary(testFile.path);
+
+    assertResolvedLibraryResultText(result, r'''
+ResolvedLibraryResult #0
+  element: package:test/test.dart
+  units
+    ResolvedUnitResult #1
+      path: /home/test/lib/test.dart
+      uri: package:test/test.dart
+      flags: exists isLibrary
+    ResolvedUnitResult #2
+      path: /home/test/lib/test.macro.dart
+      uri: package:test/test.macro.dart
+      flags: exists isAugmentation isMacroAugmentation
+''');
   }
 
   test_getResolvedLibrary_macroAugmentation_hasErrors() async {
diff --git a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
index e1c2ca9..f93b07d 100644
--- a/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/metadata_test.dart
@@ -204,6 +204,63 @@
     // No checks, as long as it does not crash.
   }
 
+  test_location_libraryAugmentation_class() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+class A {
+  final int a;
+  const A(this.a);
+}
+''');
+
+    var b = newFile('$testPackageLibPath/b.dart', r'''
+library augment 'test.dart';
+import 'a.dart' as prefix;
+
+@prefix.A(42)
+class B {}
+''');
+
+    newFile('$testPackageLibPath/test.dart', r'''
+import augment 'b.dart';
+''');
+
+    await resolveFile2(b);
+
+    var annotation = findNode.annotation('@prefix.A(42)');
+    assertResolvedNodeText(annotation, '''
+Annotation
+  atSign: @
+  name: PrefixedIdentifier
+    prefix: SimpleIdentifier
+      token: prefix
+      staticElement: self::@augmentation::package:test/b.dart::@prefix::prefix
+      staticType: null
+    period: .
+    identifier: SimpleIdentifier
+      token: A
+      staticElement: package:test/a.dart::@class::A
+      staticType: null
+    staticElement: package:test/a.dart::@class::A
+    staticType: null
+  arguments: ArgumentList
+    leftParenthesis: (
+    arguments
+      IntegerLiteral
+        literal: 42
+        parameter: package:test/a.dart::@class::A::@constructor::new::@parameter::a
+        staticType: int
+    rightParenthesis: )
+  element: package:test/a.dart::@class::A::@constructor::new
+''');
+
+    final localVariable = findElement.class_('B');
+    final annotationOnElement = localVariable.metadata.single;
+    _assertElementAnnotationValueText(annotationOnElement, '''
+A
+  a: int 42
+''');
+  }
+
   test_location_libraryAugmentationDirective() async {
     newFile('$testPackageLibPath/test.dart', r'''
 import augment 'a.dart';
diff --git a/pkg/analyzer/test/src/summary/elements_test.dart b/pkg/analyzer/test/src/summary/elements_test.dart
index 10a3a35..f69e885 100644
--- a/pkg/analyzer/test/src/summary/elements_test.dart
+++ b/pkg/analyzer/test/src/summary/elements_test.dart
@@ -4217,7 +4217,59 @@
 ''');
   }
 
-  test_augmentation_importScope_prefixed() async {
+  test_augmentation_importScope_prefixed_metadata() async {
+    newFile('$testPackageLibPath/a.dart', r'''
+class A {
+  const A();
+}
+''');
+
+    newFile('$testPackageLibPath/b.dart', r'''
+library augment 'test.dart';
+import 'a.dart' as prefix;
+
+@prefix.A()
+void f() {}
+''');
+
+    final library = await buildLibrary(r'''
+import augment 'b.dart';
+''');
+
+    checkElementText(library, r'''
+library
+  definingUnit
+  augmentationImports
+    package:test/b.dart
+      imports
+        package:test/a.dart as prefix @48
+      definingUnit
+        functions
+          f @74
+            metadata
+              Annotation
+                atSign: @ @57
+                name: PrefixedIdentifier
+                  prefix: SimpleIdentifier
+                    token: prefix @58
+                    staticElement: self::@augmentation::package:test/b.dart::@prefix::prefix
+                    staticType: null
+                  period: . @64
+                  identifier: SimpleIdentifier
+                    token: A @65
+                    staticElement: package:test/a.dart::@class::A
+                    staticType: null
+                  staticElement: package:test/a.dart::@class::A
+                  staticType: null
+                arguments: ArgumentList
+                  leftParenthesis: ( @66
+                  rightParenthesis: ) @67
+                element: package:test/a.dart::@class::A::@constructor::new
+            returnType: void
+''');
+  }
+
+  test_augmentation_importScope_prefixed_typeAnnotation() async {
     newFile('$testPackageLibPath/a.dart', r'''
 class A {}
 ''');
diff --git a/pkg/analyzer/test/src/summary/macro_test.dart b/pkg/analyzer/test/src/summary/macro_test.dart
index 64186a9..0f0364d 100644
--- a/pkg/analyzer/test/src/summary/macro_test.dart
+++ b/pkg/analyzer/test/src/summary/macro_test.dart
@@ -2372,19 +2372,19 @@
                 name: PrefixedIdentifier
                   prefix: SimpleIdentifier
                     token: prefix0 @73
-                    staticElement: <null>
+                    staticElement: self::@augmentation::package:test/test.macro.dart::@prefix::prefix0
                     staticType: null
                   period: . @80
                   identifier: SimpleIdentifier
                     token: AddMethodFoo @81
-                    staticElement: <null>
+                    staticElement: package:test/a.dart::@class::AddMethodFoo
                     staticType: null
-                  staticElement: <null>
+                  staticElement: package:test/a.dart::@class::AddMethodFoo
                   staticType: null
                 arguments: ArgumentList
                   leftParenthesis: ( @93
                   rightParenthesis: ) @94
-                element: <null>
+                element: package:test/a.dart::@class::AddMethodFoo::@constructor::new
             augmentation: self::@augmentation::package:test/test.macro.dart::@classAugmentation::B
             augmented
               methods