Fixes for applying resolution to annotations.

There are still failing tests for static fields, it seems that we
don't record the class reference, as we do for prefixes. Will look next.

R=brianwilkerson@google.com, paulberry@google.com

Change-Id: Ia869031a272f7c918e465b115fa24de261f9a4ab
Reviewed-on: https://dart-review.googlesource.com/62622
Reviewed-by: Paul Berry <paulberry@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/fasta/resolution_applier.dart b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
index 8f85c98..5471ac5 100644
--- a/pkg/analyzer/lib/src/fasta/resolution_applier.dart
+++ b/pkg/analyzer/lib/src/fasta/resolution_applier.dart
@@ -43,42 +43,33 @@
 
   @override
   void visitAnnotation(Annotation node) {
+    Identifier name = node.name;
     SimpleIdentifier constructorName = node.constructorName;
 
-    SyntacticEntity entity;
-    if (constructorName != null) {
-      entity = constructorName;
-    } else {
-      var name = node.name;
-      if (name is PrefixedIdentifier) {
-        entity = name.identifier;
+    var data = _get(name);
+    if (name is SimpleIdentifier) {
+      name.staticElement = data.reference;
+      name.staticType = data.inferredType;
+      node.element = data.reference;
+    } else if (name is PrefixedIdentifier) {
+      if (data.prefixInfo != null) {
+        name.prefix.staticElement = data.prefixInfo;
+
+        data = _get(name.identifier);
+        name.identifier.staticElement = data.reference;
+        name.identifier.staticType = data.inferredType;
       } else {
-        entity = name;
+        name.prefix.staticElement = data.reference;
+        name.prefix.staticType = data.inferredType;
+        constructorName = name.identifier;
       }
     }
-    var data = _get(entity);
-
-    SimpleIdentifier topEntity;
-    if (data.prefixInfo != null) {
-      PrefixedIdentifier prefixedIdentifier = node.name;
-
-      SimpleIdentifier prefix = prefixedIdentifier.prefix;
-      prefix.staticElement = data.prefixInfo;
-
-      topEntity = prefixedIdentifier.identifier;
-    } else {
-      topEntity = node.name;
-    }
 
     ArgumentList argumentList = node.arguments;
     if (argumentList != null) {
       var data = _get(argumentList);
       ConstructorElement element = data.reference;
-      DartType type = data.inferredType;
-
       node.element = element;
-      topEntity.staticElement = element.enclosingElement;
-      topEntity.staticType = type;
 
       if (constructorName != null) {
         constructorName.staticElement = element;
@@ -87,26 +78,9 @@
 
       _applyResolutionToArguments(argumentList);
       _resolveNamedArguments(argumentList, element.parameters);
-    } else {
-      Element element = data.reference;
-      DartType type = data.inferredType;
-      node.element = element;
-      topEntity.staticElement = element;
-      topEntity.staticType = type;
     }
   }
 
-  ResolutionData<DartType, Element, Element, PrefixElement> _get(
-      SyntacticEntity entity,
-      {bool failIfAbsent: true}) {
-    int entityOffset = entity.offset;
-    var data = _data[entityOffset];
-    if (failIfAbsent && data == null) {
-      throw new StateError('No data for $entity at $entityOffset');
-    }
-    return data;
-  }
-
   @override
   void visitAsExpression(AsExpression node) {
     node.expression.accept(this);
@@ -333,25 +307,6 @@
     _typeContext.exitLocalFunction(element);
   }
 
-  void _storeFunctionType(DartType type, FunctionElementImpl element) {
-    if (type is FunctionType && element != null) {
-      element.returnType = type.returnType;
-      int normalParameterIndex = 0;
-      int optionalParameterIndex = 0;
-      for (ParameterElementImpl parameter in element.parameters) {
-        if (parameter.isNamed) {
-          parameter.type = type.namedParameterTypes[parameter.name];
-        } else if (normalParameterIndex < type.normalParameterTypes.length) {
-          parameter.type = type.normalParameterTypes[normalParameterIndex++];
-        } else if (optionalParameterIndex <
-            type.optionalParameterTypes.length) {
-          parameter.type =
-              type.optionalParameterTypes[optionalParameterIndex++];
-        }
-      }
-    }
-  }
-
   @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     node.function.accept(this);
@@ -694,6 +649,17 @@
     }
   }
 
+  ResolutionData<DartType, Element, Element, PrefixElement> _get(
+      SyntacticEntity entity,
+      {bool failIfAbsent: true}) {
+    int entityOffset = entity.offset;
+    var data = _data[entityOffset];
+    if (failIfAbsent && data == null) {
+      throw new StateError('No data for $entity at $entityOffset');
+    }
+    return data;
+  }
+
   /// Return the [SyntacticEntity] with which the front-end associates
   /// assignment to the given [leftHandSide].
   SyntacticEntity _getAssignmentEntity(Expression leftHandSide) {
@@ -729,6 +695,25 @@
     }
   }
 
+  void _storeFunctionType(DartType type, FunctionElementImpl element) {
+    if (type is FunctionType && element != null) {
+      element.returnType = type.returnType;
+      int normalParameterIndex = 0;
+      int optionalParameterIndex = 0;
+      for (ParameterElementImpl parameter in element.parameters) {
+        if (parameter.isNamed) {
+          parameter.type = type.namedParameterTypes[parameter.name];
+        } else if (normalParameterIndex < type.normalParameterTypes.length) {
+          parameter.type = type.normalParameterTypes[normalParameterIndex++];
+        } else if (optionalParameterIndex <
+            type.optionalParameterTypes.length) {
+          parameter.type =
+              type.optionalParameterTypes[optionalParameterIndex++];
+        }
+      }
+    }
+  }
+
   /// Apply the [type] that is created by the [constructorName] and the
   /// [constructorElement] it references.
   static void applyConstructorElement(
diff --git a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
index f20b373..0195c61 100644
--- a/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver_kernel_test.dart
@@ -211,31 +211,6 @@
 
   @override
   @failingTest
-  test_invalidAnnotation_constantVariable_topLevel_importWithPrefix() {
-    // type 'PrefixedIdentifierImpl' is not a subtype of type 'SimpleIdentifier'
-    // of 'topEntity'
-    return super
-        .test_invalidAnnotation_constantVariable_topLevel_importWithPrefix();
-  }
-
-  @override
-  @failingTest
-  test_invalidAnnotation_constConstructor_importWithPrefix() {
-    // type 'PrefixedIdentifierImpl' is not a subtype of type 'SimpleIdentifier'
-    // of 'topEntity'
-    return super.test_invalidAnnotation_constConstructor_importWithPrefix();
-  }
-
-  @override
-  @failingTest
-  test_invalidAnnotation_constConstructor_named_importWithPrefix() {
-    // Bad state: No data for named at 29
-    return super
-        .test_invalidAnnotation_constConstructor_named_importWithPrefix();
-  }
-
-  @override
-  @failingTest
   @FastaProblem('https://github.com/dart-lang/sdk/issues/31758')
   test_invocationOfNonFunction_Object() async {
     return super.test_invocationOfNonFunction_Object();
@@ -321,13 +296,6 @@
 
   @override
   @failingTest
-  @potentialAnalyzerProblem
-  test_staticAccessToInstanceMember_annotation() async {
-    return super.test_staticAccessToInstanceMember_annotation();
-  }
-
-  @override
-  @failingTest
   test_undefinedGetter_static_conditionalAccess() {
     // Bad state: No data for A at 36
     return super.test_undefinedGetter_static_conditionalAccess();
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
index 96d8327..c912d36 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_kernel_test.dart
@@ -24,22 +24,6 @@
   @override
   @failingTest
   @potentialAnalyzerProblem
-  test_annotation_prefixed_classConstructor() {
-    // TODO(paulberry): broken because prefixes are not working properly
-    return super.test_annotation_prefixed_classConstructor();
-  }
-
-  @override
-  @failingTest
-  @potentialAnalyzerProblem
-  test_annotation_prefixed_classConstructorNamed() {
-    // TODO(paulberry): broken because prefixes are not working properly
-    return super.test_annotation_prefixed_classConstructorNamed();
-  }
-
-  @override
-  @failingTest
-  @potentialAnalyzerProblem
   test_annotation_prefixed_classField() {
     // TODO(paulberry): broken because prefixes are not working properly
     return super.test_annotation_prefixed_classField();
@@ -47,14 +31,6 @@
 
   @override
   @failingTest
-  @potentialAnalyzerProblem
-  test_annotation_prefixed_topLevelVariable() {
-    // TODO(paulberry): broken because prefixes are not working properly
-    return super.test_annotation_prefixed_topLevelVariable();
-  }
-
-  @override
-  @failingTest
   @FastaProblem('https://github.com/dart-lang/sdk/issues/31605')
   test_constructor_redirected_generic() async {
     await super.test_constructor_redirected_generic();
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
index dc7cb05..033035c 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -128,77 +128,48 @@
     }
   }
 
-  test_annotation_constructor_withNestedConstructorInvocation() async {
-    addTestFile('''
-class C {
-  const C();
+  test_annotation_prefixed_classField() async {
+    var a = _p('/test/lib/a.dart');
+    provider.newFile(a, r'''
+class A {
+  static const a = 1;
 }
-class D {
-  final C c;
-  const D(this.c);
-}
-@D(const C())
-f() {}
 ''');
-    var result = await driver.getResult(testFile);
-    var elementC = AstFinder.getClass(result.unit, 'C').element;
-    var constructorC = elementC.constructors[0];
-    var elementD = AstFinder.getClass(result.unit, 'D').element;
-    var constructorD = elementD.constructors[0];
-    var atD = AstFinder.getTopLevelFunction(result.unit, 'f').metadata[0];
-    InstanceCreationExpression constC = atD.arguments.arguments[0];
+    addTestFile(r'''
+import 'a.dart' as p;
 
-    expect(atD.name.staticElement, elementD);
-    expect(atD.element, constructorD);
-
-    expect(constC.staticElement, constructorC);
-    expect(constC.staticType, elementC.type);
-
-    expect(constC.constructorName.staticElement, constructorC);
-    expect(constC.constructorName.type.type, elementC.type);
-  }
-
-  test_annotation_kind_reference() async {
-    String content = r'''
-const annotation_1 = 1;
-const annotation_2 = 1;
-@annotation_1
-@annotation_2
-void main() {
-  print(42);
-}
-''';
-    addTestFile(content);
-
+@p.A.a
+main() {}
+''');
     AnalysisResult result = await driver.getResult(testFile);
-    var typeProvider = result.unit.element.context.typeProvider;
+    CompilationUnit unit = result.unit;
+    var typeProvider = unit.element.context.typeProvider;
 
-    TopLevelVariableDeclaration declaration_1 = result.unit.declarations[0];
-    VariableDeclaration variable_1 = declaration_1.variables.variables[0];
-    TopLevelVariableElement element_1 = variable_1.element;
+    ImportElement aImport = unit.element.library.imports[0];
+    PrefixElement aPrefix = aImport.prefix;
+    LibraryElement aLibrary = aImport.importedLibrary;
 
-    TopLevelVariableDeclaration declaration_2 = result.unit.declarations[1];
-    VariableDeclaration variable_2 = declaration_2.variables.variables[0];
-    TopLevelVariableElement element_2 = variable_2.element;
+    CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
+    ClassElement aClass = aUnitElement.getType('A');
+    var aGetter = aClass.getField('a').getter;
 
-    FunctionDeclaration main = result.unit.declarations[2];
+    Annotation annotation = unit.declarations[0].metadata.single;
+    expect(annotation.element, same(aGetter));
+    PrefixedIdentifier prefixed = annotation.name;
 
-    Annotation annotation_1 = main.metadata[0];
-    expect(annotation_1.element, same(element_1.getter));
+    expect(prefixed.prefix.staticElement, same(aPrefix));
+    expect(prefixed.prefix.staticType, isNull);
 
-    SimpleIdentifier identifier_1 = annotation_1.name;
-    expect(identifier_1.staticElement, same(element_1.getter));
-    expect(identifier_1.staticType, typeProvider.intType);
+    expect(prefixed.identifier.staticElement, same(aClass));
+    expect(prefixed.prefix.staticType, isNull);
 
-    Annotation annotation_2 = main.metadata[1];
-    expect(annotation_2.element, same(element_2.getter));
+    expect(annotation.constructorName.staticElement, aGetter);
+    expect(annotation.constructorName.staticType, typeProvider.intType);
 
-    SimpleIdentifier identifier_2 = annotation_2.name;
-    expect(identifier_2.staticElement, same(element_2.getter));
-    expect(identifier_2.staticType, typeProvider.intType);
+    expect(annotation.arguments, isNull);
   }
 
-  test_annotation_prefixed_classConstructor() async {
+  test_annotation_prefixed_constructor() async {
     var a = _p('/test/lib/a.dart');
     provider.newFile(a, r'''
 class A {
@@ -240,7 +211,7 @@
     _assertArgumentToParameter(arguments[1], parameters[1]);
   }
 
-  test_annotation_prefixed_classConstructorNamed() async {
+  test_annotation_prefixed_constructor_named() async {
     var a = _p('/test/lib/a.dart');
     provider.newFile(a, r'''
 class A {
@@ -284,47 +255,6 @@
     _assertArgumentToParameter(arguments[1], parameters[1]);
   }
 
-  test_annotation_prefixed_classField() async {
-    var a = _p('/test/lib/a.dart');
-    provider.newFile(a, r'''
-class A {
-  static const a = 1;
-}
-''');
-    addTestFile(r'''
-import 'a.dart' as p;
-
-@p.A.a
-main() {}
-''');
-    AnalysisResult result = await driver.getResult(testFile);
-    CompilationUnit unit = result.unit;
-    var typeProvider = unit.element.context.typeProvider;
-
-    ImportElement aImport = unit.element.library.imports[0];
-    PrefixElement aPrefix = aImport.prefix;
-    LibraryElement aLibrary = aImport.importedLibrary;
-
-    CompilationUnitElement aUnitElement = aLibrary.definingCompilationUnit;
-    ClassElement aClass = aUnitElement.getType('A');
-    var aGetter = aClass.getField('a').getter;
-
-    Annotation annotation = unit.declarations[0].metadata.single;
-    expect(annotation.element, same(aGetter));
-    PrefixedIdentifier prefixed = annotation.name;
-
-    expect(prefixed.prefix.staticElement, same(aPrefix));
-    expect(prefixed.prefix.staticType, isNull);
-
-    expect(prefixed.identifier.staticElement, same(aClass));
-    expect(prefixed.prefix.staticType, isNull);
-
-    expect(annotation.constructorName.staticElement, aGetter);
-    expect(annotation.constructorName.staticType, typeProvider.intType);
-
-    expect(annotation.arguments, isNull);
-  }
-
   test_annotation_prefixed_topLevelVariable() async {
     var a = _p('/test/lib/a.dart');
     provider.newFile(a, r'''
@@ -360,6 +290,140 @@
     expect(annotation.arguments, isNull);
   }
 
+  test_annotation_unprefixed_constructor() async {
+    addTestFile(r'''
+@A(1, b: 2)
+main() {}
+
+class A {
+  const A(int a, {int b});
+}
+''');
+    AnalysisResult result = await driver.getResult(testFile);
+    CompilationUnit unit = result.unit;
+    CompilationUnitElement unitElement = unit.element;
+
+    ClassElement aClass = unitElement.getType('A');
+    ConstructorElement constructor = aClass.unnamedConstructor;
+
+    Annotation annotation = unit.declarations[0].metadata.single;
+    expect(annotation.element, same(constructor));
+
+    SimpleIdentifier name = annotation.name;
+    expect(name.staticElement, same(aClass));
+
+    expect(annotation.constructorName, isNull);
+
+    var arguments = annotation.arguments.arguments;
+    var parameters = constructor.parameters;
+    _assertArgumentToParameter(arguments[0], parameters[0]);
+    _assertArgumentToParameter(arguments[1], parameters[1]);
+  }
+
+  test_annotation_unprefixed_constructor_named() async {
+    addTestFile(r'''
+@A.named(1, b: 2)
+main() {}
+
+class A {
+  const A.named(int a, {int b});
+}
+''');
+    AnalysisResult result = await driver.getResult(testFile);
+    CompilationUnit unit = result.unit;
+    CompilationUnitElement unitElement = unit.element;
+
+    ClassElement aClass = unitElement.getType('A');
+    ConstructorElement constructor = aClass.constructors.single;
+
+    Annotation annotation = unit.declarations[0].metadata.single;
+    expect(annotation.element, same(constructor));
+    PrefixedIdentifier prefixed = annotation.name;
+
+    expect(prefixed.prefix.staticElement, same(aClass));
+    expect(prefixed.prefix.staticType, aClass.type);
+
+    expect(prefixed.identifier.staticElement, same(constructor));
+    expect(prefixed.identifier.staticType.toString(), '(int, {b: int}) → A');
+
+    expect(annotation.constructorName, isNull);
+
+    var arguments = annotation.arguments.arguments;
+    var parameters = constructor.parameters;
+    _assertArgumentToParameter(arguments[0], parameters[0]);
+    _assertArgumentToParameter(arguments[1], parameters[1]);
+  }
+
+  test_annotation_unprefixed_constructor_withNestedConstructorInvocation() async {
+    addTestFile('''
+class C {
+  const C();
+}
+class D {
+  final C c;
+  const D(this.c);
+}
+@D(const C())
+f() {}
+''');
+    var result = await driver.getResult(testFile);
+    var elementC = AstFinder.getClass(result.unit, 'C').element;
+    var constructorC = elementC.constructors[0];
+    var elementD = AstFinder.getClass(result.unit, 'D').element;
+    var constructorD = elementD.constructors[0];
+    var atD = AstFinder.getTopLevelFunction(result.unit, 'f').metadata[0];
+    InstanceCreationExpression constC = atD.arguments.arguments[0];
+
+    expect(atD.name.staticElement, elementD);
+    expect(atD.element, constructorD);
+
+    expect(constC.staticElement, constructorC);
+    expect(constC.staticType, elementC.type);
+
+    expect(constC.constructorName.staticElement, constructorC);
+    expect(constC.constructorName.type.type, elementC.type);
+  }
+
+  test_annotation_unprefixed_topLevelVariable() async {
+    String content = r'''
+const annotation_1 = 1;
+const annotation_2 = 1;
+@annotation_1
+@annotation_2
+void main() {
+  print(42);
+}
+''';
+    addTestFile(content);
+
+    AnalysisResult result = await driver.getResult(testFile);
+    var typeProvider = result.unit.element.context.typeProvider;
+
+    TopLevelVariableDeclaration declaration_1 = result.unit.declarations[0];
+    VariableDeclaration variable_1 = declaration_1.variables.variables[0];
+    TopLevelVariableElement element_1 = variable_1.element;
+
+    TopLevelVariableDeclaration declaration_2 = result.unit.declarations[1];
+    VariableDeclaration variable_2 = declaration_2.variables.variables[0];
+    TopLevelVariableElement element_2 = variable_2.element;
+
+    FunctionDeclaration main = result.unit.declarations[2];
+
+    Annotation annotation_1 = main.metadata[0];
+    expect(annotation_1.element, same(element_1.getter));
+
+    SimpleIdentifier identifier_1 = annotation_1.name;
+    expect(identifier_1.staticElement, same(element_1.getter));
+    expect(identifier_1.staticType, typeProvider.intType);
+
+    Annotation annotation_2 = main.metadata[1];
+    expect(annotation_2.element, same(element_2.getter));
+
+    SimpleIdentifier identifier_2 = annotation_2.name;
+    expect(identifier_2.staticElement, same(element_2.getter));
+    expect(identifier_2.staticType, typeProvider.intType);
+  }
+
   test_asExpression() async {
     String content = r'''
 void main() {