Augment. Add 'thisType' to AugmentedInstanceElement.

You still can access it through InstanceElement.thisType, but the
implementation goes through `augmented`. So we always return the
value for the start of the augmentation chain.

Maybe we should deprecate `InstanceElement.thisType`?

Change-Id: I9505af7ca10eaf32c8c1e3c48070e149284410b2
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/362660
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/dart/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index c715ba4..263ae8d 100644
--- a/pkg/analyzer/lib/dart/element/element.dart
+++ b/pkg/analyzer/lib/dart/element/element.dart
@@ -132,6 +132,9 @@
   /// [MethodElement]s are appended.
   List<MethodElement> get methods;
 
+  /// The type of `this` expression.
+  DartType get thisType;
+
   /// Returns the field from [fields] that has the given [name].
   FieldElement? getField(String name);
 
@@ -203,6 +206,9 @@
   /// augmentations.
   List<InterfaceType> get mixins;
 
+  @override
+  InterfaceType get thisType;
+
   /// The unnamed constructor from [constructors].
   ConstructorElement? get unnamedConstructor;
 
@@ -1538,11 +1544,7 @@
 
   /// The type of `this` expression.
   ///
-  /// For a class like `class MyClass<T, U> {}` the returned type is equivalent
-  /// to the type `MyClass<T, U>`. So, the type arguments are the types of the
-  /// type parameters, and either `none` or `star` is used for the nullability
-  /// suffix is used, depending on the nullability status of the declaring
-  /// library.
+  /// Same as `augmented.thisType`.
   DartType get thisType;
 }
 
diff --git a/pkg/analyzer/lib/src/dart/element/element.dart b/pkg/analyzer/lib/src/dart/element/element.dart
index cd93225..638e0c1 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -3492,9 +3492,6 @@
   /// The cached result of [allSupertypes].
   List<InterfaceType>? _allSupertypes;
 
-  /// The type defined by the class.
-  InterfaceType? _thisType;
-
   /// A flag indicating whether the types associated with the instance members
   /// of this class have been inferred.
   bool hasBeenInferred = false;
@@ -3624,21 +3621,7 @@
 
   @override
   InterfaceType get thisType {
-    if (_thisType == null) {
-      List<DartType> typeArguments;
-      if (typeParameters.isNotEmpty) {
-        typeArguments = typeParameters.map<DartType>((t) {
-          return t.instantiate(nullabilitySuffix: NullabilitySuffix.none);
-        }).toFixedList();
-      } else {
-        typeArguments = const <DartType>[];
-      }
-      return _thisType = instantiate(
-        typeArguments: typeArguments,
-        nullabilitySuffix: NullabilitySuffix.none,
-      );
-    }
-    return _thisType!;
+    return augmented.thisType;
   }
 
   @override
@@ -4986,6 +4969,9 @@
     implements AugmentedExtensionElement {
   @override
   ExtensionElementImpl get declaration;
+
+  @override
+  DartType get thisType => declaration.extendedType;
 }
 
 mixin MaybeAugmentedExtensionTypeElementMixin
@@ -5181,10 +5167,32 @@
 
 mixin MaybeAugmentedInterfaceElementMixin on MaybeAugmentedInstanceElementMixin
     implements AugmentedInterfaceElement {
+  InterfaceType? _thisType;
+
   @override
   InterfaceElementImpl get declaration;
 
   @override
+  InterfaceType get thisType {
+    if (_thisType == null) {
+      List<DartType> typeArguments;
+      final typeParameters = declaration.typeParameters;
+      if (typeParameters.isNotEmpty) {
+        typeArguments = typeParameters.map<DartType>((t) {
+          return t.instantiate(nullabilitySuffix: NullabilitySuffix.none);
+        }).toFixedList();
+      } else {
+        typeArguments = const <DartType>[];
+      }
+      return _thisType = declaration.instantiate(
+        typeArguments: typeArguments,
+        nullabilitySuffix: NullabilitySuffix.none,
+      );
+    }
+    return _thisType!;
+  }
+
+  @override
   ConstructorElement? get unnamedConstructor {
     return constructors.firstWhereOrNull((element) => element.name.isEmpty);
   }
diff --git a/pkg/analyzer/test/src/summary/element_text.dart b/pkg/analyzer/test/src/summary/element_text.dart
index 8aa3150..49002e1 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -135,14 +135,14 @@
 
   void _validateAugmentedInstanceElement(InstanceElementImpl e) {
     final augmented = e.augmented;
+    final thisType = e.thisType;
 
-    InstanceElementImpl? endOfAugmentations = e;
-    while (endOfAugmentations != null) {
-      expect(endOfAugmentations.augmented, same(augmented));
-      endOfAugmentations = endOfAugmentations.augmentationTarget;
+    InstanceElementImpl? current = e;
+    while (current != null) {
+      expect(current.augmented, same(augmented));
+      expect(current.thisType, same(thisType));
+      current = current.augmentationTarget;
     }
-
-    // TODO(scheglov): check `thisType`
   }
 
   void _writeAugmentation(ElementImpl e) {