[Migrate] sdk_constraint_verifier.dart

Change-Id: Ieb50d8292dcaee51aebd243dddc6aaebbb2c0f96
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/403641
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/analyzer_use_new_elements.txt b/pkg/analyzer/analyzer_use_new_elements.txt
index d29932ec..6e888c2 100644
--- a/pkg/analyzer/analyzer_use_new_elements.txt
+++ b/pkg/analyzer/analyzer_use_new_elements.txt
@@ -99,7 +99,6 @@
 lib/src/generated/resolver.dart
 lib/src/generated/testing/element_factory.dart
 lib/src/generated/testing/test_type_provider.dart
-lib/src/hint/sdk_constraint_verifier.dart
 lib/src/lint/linter.dart
 lib/src/services/top_level_declarations.dart
 lib/src/summary2/ast_binary_reader.dart
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index c92de7d..0207a9e 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -4476,9 +4476,7 @@
   ElementKind get kind => ElementKind.PARAMETER;
 
   @override
-  LibraryElement2 get library2 =>
-      wrappedElement.thisOrAncestorOfType<LibraryElementImpl>()
-          as LibraryElement2;
+  LibraryElement2? get library2 => wrappedElement.library2;
 
   @override
   String? get name3 => wrappedElement.name;
@@ -4859,8 +4857,10 @@
       -1, metadata.cast<ElementAnnotationImpl>(), () => sinceSdkVersion);
 
   Version? get sinceSdkVersion {
-    var annotations = metadata.cast<ElementAnnotationImpl>();
-    return SinceSdkVersionComputer.fromAnnotations(annotations);
+    if (this is Element2) {
+      return SinceSdkVersionComputer().compute2(this as Element2);
+    }
+    return null;
   }
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/since_sdk_version.dart b/pkg/analyzer/lib/src/dart/element/since_sdk_version.dart
index 80f46af..4357dfb 100644
--- a/pkg/analyzer/lib/src/dart/element/since_sdk_version.dart
+++ b/pkg/analyzer/lib/src/dart/element/since_sdk_version.dart
@@ -2,6 +2,7 @@
 // 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:analyzer/dart/element/element2.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:pub_semver/pub_semver.dart';
@@ -40,27 +41,38 @@
     }
   }
 
-  /// Returns the maximal specified `@Since()` version from the [annotations].
-  ///
-  /// Returns `null` if none of the annotations is a `@Since` annotation.
-  static Version? fromAnnotations(List<ElementAnnotationImpl> annotations) {
-    // TODO(brianwilkerson): Replace the body of `_specifiedVersion` with this
-    //  method.
-    Version? result;
-    for (var annotation in annotations) {
-      if (annotation.isDartInternalSince) {
-        var arguments = annotation.annotationAst.arguments?.arguments;
-        var versionNode = arguments?.singleOrNull;
-        if (versionNode is SimpleStringLiteralImpl) {
-          var versionStr = versionNode.value;
-          var version = _parseVersion(versionStr);
-          if (version != null) {
-            result = result.maxWith(version);
-          }
-        }
-      }
+  /// The [element] is a `dart:xyz` library, so it can have `@Since` annotations.
+  /// Evaluates its annotations and returns the version.
+  Version? compute2(Element2 element) {
+    // Must be in a `dart:` library.
+    var libraryUri = element.library2?.uri;
+    if (libraryUri == null || !libraryUri.isScheme('dart')) {
+      return null;
     }
-    return result;
+
+    // Fields cannot be referenced outside.
+    if (element is FieldElement2 && element.isSynthetic) {
+      return null;
+    }
+
+    // We cannot add required parameters.
+    if (element is FormalParameterElement && element.isRequired) {
+      return null;
+    }
+
+    Version? specified;
+    if (element is Annotatable) {
+      specified = _specifiedVersion2(element as Annotatable);
+    }
+    if (element.enclosingElement2 case Annotatable enclosingElement?) {
+      var enclosing = enclosingElement.metadata2.sinceSdkVersion;
+      return specified.maxWith(enclosing);
+    } else if (element.library2 case var libraryElement?) {
+      var enclosing = libraryElement.metadata2.sinceSdkVersion;
+      return specified.maxWith(enclosing);
+    } else {
+      return specified;
+    }
   }
 
   /// Returns the parsed [Version], or `null` if wrong format.
@@ -96,6 +108,27 @@
     }
     return result;
   }
+
+  /// Returns the maximal specified `@Since()` version, `null` if none.
+  static Version? _specifiedVersion2(Annotatable element) {
+    var annotations =
+        element.metadata2.annotations.cast<ElementAnnotationImpl>();
+    Version? result;
+    for (var annotation in annotations) {
+      if (annotation.isDartInternalSince) {
+        var arguments = annotation.annotationAst.arguments?.arguments;
+        var versionNode = arguments?.singleOrNull;
+        if (versionNode is SimpleStringLiteralImpl) {
+          var versionStr = versionNode.value;
+          var version = _parseVersion(versionStr);
+          if (version != null) {
+            result = result.maxWith(version);
+          }
+        }
+      }
+    }
+    return result;
+  }
 }
 
 extension on Version? {
diff --git a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
index e4df602..b5780a9 100644
--- a/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
+++ b/pkg/analyzer/lib/src/hint/sdk_constraint_verifier.dart
@@ -6,7 +6,7 @@
 import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/element2.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/error/codes.dart';
@@ -59,7 +59,7 @@
     // Named arguments are checked in [NamedExpression].
     for (var argument in node.arguments) {
       if (argument is! NamedExpression) {
-        var parameter = argument.staticParameterElement;
+        var parameter = argument.correspondingParameter;
         _checkSinceSdkVersion(parameter, node, errorEntity: argument);
       }
     }
@@ -69,8 +69,8 @@
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
-    _checkSinceSdkVersion(node.readElement, node);
-    _checkSinceSdkVersion(node.writeElement, node);
+    _checkSinceSdkVersion(node.readElement2, node);
+    _checkSinceSdkVersion(node.writeElement2, node);
     super.visitAssignmentExpression(node);
   }
 
@@ -90,13 +90,13 @@
 
   @override
   void visitConstructorName(ConstructorName node) {
-    _checkSinceSdkVersion(node.staticElement, node);
+    _checkSinceSdkVersion(node.element, node);
     super.visitConstructorName(node);
   }
 
   @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    _checkSinceSdkVersion(node.staticElement, node);
+    _checkSinceSdkVersion(node.element, node);
     super.visitFunctionExpressionInvocation(node);
   }
 
@@ -107,7 +107,7 @@
 
   @override
   void visitIndexExpression(IndexExpression node) {
-    _checkSinceSdkVersion(node.staticElement, node);
+    _checkSinceSdkVersion(node.element, node);
     super.visitIndexExpression(node);
   }
 
@@ -124,25 +124,25 @@
 
   @override
   void visitMethodInvocation(MethodInvocation node) {
-    _checkSinceSdkVersion(node.methodName.staticElement, node);
+    _checkSinceSdkVersion(node.methodName.element, node);
     super.visitMethodInvocation(node);
   }
 
   @override
   void visitNamedType(NamedType node) {
-    _checkSinceSdkVersion(node.element, node);
+    _checkSinceSdkVersion(node.element2, node);
     super.visitNamedType(node);
   }
 
   @override
   void visitPrefixedIdentifier(PrefixedIdentifier node) {
-    _checkSinceSdkVersion(node.staticElement, node);
+    _checkSinceSdkVersion(node.element, node);
     super.visitPrefixedIdentifier(node);
   }
 
   @override
   void visitPropertyAccess(PropertyAccess node) {
-    _checkSinceSdkVersion(node.propertyName.staticElement, node);
+    _checkSinceSdkVersion(node.propertyName.element, node);
     super.visitPropertyAccess(node);
   }
 
@@ -156,20 +156,21 @@
     if (node.inDeclarationContext()) {
       return;
     }
-    _checkSinceSdkVersion(node.staticElement, node);
+    _checkSinceSdkVersion(node.element, node);
   }
 
   void _checkSinceSdkVersion(
-    Element? element,
+    Element2? element,
     AstNode target, {
     SyntacticEntity? errorEntity,
   }) {
-    if (element != null) {
-      var sinceSdkVersion = element.sinceSdkVersion;
+    element = element?.nonSynthetic2;
+    if (element is Annotatable) {
+      var sinceSdkVersion = (element as Annotatable).metadata2.sinceSdkVersion;
       if (sinceSdkVersion != null) {
         if (!_versionConstraint.requiresAtLeast(sinceSdkVersion)) {
           if (errorEntity == null) {
-            if (!_shouldReportEnumIndex(target, element)) {
+            if (!_shouldReportEnumIndex(target, element!)) {
               return;
             }
             if (target is AssignmentExpression) {
@@ -217,8 +218,8 @@
   /// Returns `true` if [element] is something else, or if the target is a
   /// concrete enum. The `index` was always available for concrete enums,
   /// but there was no common `Enum` supertype for all enums.
-  static bool _shouldReportEnumIndex(AstNode node, Element element) {
-    if (element is PropertyAccessorElement && element.name == 'index') {
+  static bool _shouldReportEnumIndex(AstNode node, Element2 element) {
+    if (element is PropertyAccessorElement2 && element.name3 == 'index') {
       DartType? targetType;
       if (node is PrefixedIdentifier) {
         targetType = node.prefix.staticType;
@@ -226,8 +227,8 @@
         targetType = node.realTarget.staticType;
       }
       if (targetType != null) {
-        var targetElement = targetType.element;
-        return targetElement is ClassElement && targetElement.isDartCoreEnum;
+        var targetElement = targetType.element3;
+        return targetElement is ClassElement2 && targetElement.isDartCoreEnum;
       }
       return false;
     } else {
diff --git a/pkg/analyzer/test/src/summary/elements/since_sdk_version_test.dart b/pkg/analyzer/test/src/summary/elements/since_sdk_version_test.dart
index 29dd95e..4313461 100644
--- a/pkg/analyzer/test/src/summary/elements/since_sdk_version_test.dart
+++ b/pkg/analyzer/test/src/summary/elements/since_sdk_version_test.dart
@@ -103,6 +103,7 @@
       constructors
         named
           firstFragment: dart:foo::<fragment>::@class::A::@constructor::named
+          sinceSdkVersion: 2.15.0
     class B
       reference: dart:foo::@class::B
       firstFragment: dart:foo::<fragment>::@class::B
@@ -198,9 +199,11 @@
       getters
         synthetic get foo
           firstFragment: dart:foo::<fragment>::@class::A::@getter::foo
+          sinceSdkVersion: 2.15.0
       setters
         synthetic set foo
           firstFragment: dart:foo::<fragment>::@class::A::@setter::foo
+          sinceSdkVersion: 2.15.0
           formalParameters
             requiredPositional _foo
               type: int
@@ -273,6 +276,7 @@
       getters
         get foo
           firstFragment: dart:foo::<fragment>::@class::A::@getter::foo
+          sinceSdkVersion: 2.15.0
 ''');
   }
 
@@ -328,6 +332,7 @@
         foo
           reference: dart:foo::@class::A::@method::foo
           firstFragment: dart:foo::<fragment>::@class::A::@method::foo
+          sinceSdkVersion: 2.15.0
 ''');
   }
 
@@ -441,7 +446,7 @@
         foo
           reference: dart:foo::@class::A::@method::foo
           firstFragment: dart:foo::<fragment>::@class::A::@method::foo
-          sinceSdkVersion: 2.14.0
+          sinceSdkVersion: 2.15.0
 ''');
   }
 
@@ -517,6 +522,7 @@
       setters
         set foo
           firstFragment: dart:foo::<fragment>::@class::A::@setter::foo
+          sinceSdkVersion: 2.15.0
           formalParameters
             requiredPositional _
               type: int
@@ -739,12 +745,15 @@
       getters
         synthetic static get v
           firstFragment: dart:foo::<fragment>::@enum::E::@getter::v
+          sinceSdkVersion: 2.15.0
         synthetic static get values
           firstFragment: dart:foo::<fragment>::@enum::E::@getter::values
+          sinceSdkVersion: 2.15.0
       methods
         foo
           reference: dart:foo::@enum::E::@method::foo
           firstFragment: dart:foo::<fragment>::@enum::E::@method::foo
+          sinceSdkVersion: 2.15.0
 ''');
   }
 
@@ -801,6 +810,7 @@
         foo
           reference: dart:foo::@extension::E::@method::foo
           firstFragment: dart:foo::<fragment>::@extension::E::@method::foo
+          sinceSdkVersion: 2.15.0
 ''');
   }
 
@@ -860,6 +870,7 @@
         foo
           reference: dart:foo::@mixin::M::@method::foo
           firstFragment: dart:foo::<fragment>::@mixin::M::@method::foo
+          sinceSdkVersion: 2.15.0
 ''');
   }
 
@@ -1077,6 +1088,7 @@
     foo
       reference: dart:foo::@function::foo
       firstFragment: dart:foo::<fragment>::@function::foo
+      sinceSdkVersion: 2.15.0
       returnType: void
 ''');
   }