Fine. Support for constructor constantInitializers.

Change-Id: Ib166a4348365053d332287c0a0ca73197909dac4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/422025
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
diff --git a/pkg/analyzer/lib/src/fine/manifest_ast.dart b/pkg/analyzer/lib/src/fine/manifest_ast.dart
index c7e4523..3efc9a6 100644
--- a/pkg/analyzer/lib/src/fine/manifest_ast.dart
+++ b/pkg/analyzer/lib/src/fine/manifest_ast.dart
@@ -136,6 +136,10 @@
     sink.writeUint30List(elementIndexList);
   }
 
+  static List<ManifestNode> readList(SummaryDataReader reader) {
+    return reader.readTypedList(() => ManifestNode.read(reader));
+  }
+
   static ManifestNode? readOptional(SummaryDataReader reader) {
     return reader.readOptionalObject(() => ManifestNode.read(reader));
   }
@@ -165,6 +169,11 @@
   }
 
   @override
+  void visitAssertInitializer(AssertInitializer node) {
+    node.visitChildren(this);
+  }
+
+  @override
   void visitBinaryExpression(BinaryExpression node) {
     node.visitChildren(this);
     _addElement(node.element);
@@ -174,6 +183,11 @@
   void visitBooleanLiteral(BooleanLiteral node) {}
 
   @override
+  void visitConstructorFieldInitializer(ConstructorFieldInitializer node) {
+    node.visitChildren(this);
+  }
+
+  @override
   void visitConstructorName(ConstructorName node) {
     node.visitChildren(this);
     _addElement(node.element);
@@ -265,6 +279,12 @@
   }
 
   @override
+  void visitRedirectingConstructorInvocation(
+      RedirectingConstructorInvocation node) {
+    node.visitChildren(this);
+  }
+
+  @override
   void visitSetOrMapLiteral(SetOrMapLiteral node) {
     node.visitChildren(this);
   }
@@ -293,6 +313,11 @@
   }
 
   @override
+  void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
+    node.visitChildren(this);
+  }
+
+  @override
   void visitTypeArgumentList(TypeArgumentList node) {
     node.visitChildren(this);
   }
@@ -310,6 +335,24 @@
   }
 }
 
+extension ListOfManifestNodeExtension on List<ManifestNode> {
+  bool match(MatchContext context, List<AstNode> nodes) {
+    if (nodes.length != length) {
+      return false;
+    }
+    for (var i = 0; i < length; i++) {
+      if (!this[i].match(context, nodes[i])) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  void writeList(BufferedSink sink) {
+    sink.writeList(this, (x) => x.write(sink));
+  }
+}
+
 extension ManifestNodeOrNullExtension on ManifestNode? {
   bool match(MatchContext context, AstNode? node) {
     var self = this;
diff --git a/pkg/analyzer/lib/src/fine/manifest_item.dart b/pkg/analyzer/lib/src/fine/manifest_item.dart
index 136b495..52d882e 100644
--- a/pkg/analyzer/lib/src/fine/manifest_item.dart
+++ b/pkg/analyzer/lib/src/fine/manifest_item.dart
@@ -363,6 +363,7 @@
   final bool isConst;
   final bool isFactory;
   final ManifestFunctionType functionType;
+  final List<ManifestNode> constantInitializers;
 
   InterfaceItemConstructorItem({
     required super.id,
@@ -371,6 +372,7 @@
     required this.isConst,
     required this.isFactory,
     required this.functionType,
+    required this.constantInitializers,
   });
 
   factory InterfaceItemConstructorItem.fromElement({
@@ -378,7 +380,6 @@
     required EncodeContext context,
     required ConstructorElementImpl2 element,
   }) {
-    // TODO(scheglov): initializers
     return InterfaceItemConstructorItem(
       id: id,
       metadata: ManifestMetadata.encode(context, element.metadata2),
@@ -386,6 +387,9 @@
       isConst: element.isConst,
       isFactory: element.isFactory,
       functionType: element.type.encode(context),
+      constantInitializers: element.constantInitializers
+          .map((initializer) => ManifestNode.encode(context, initializer))
+          .toFixedList(),
     );
   }
 
@@ -397,6 +401,7 @@
       isConst: reader.readBool(),
       isFactory: reader.readBool(),
       functionType: ManifestFunctionType.read(reader),
+      constantInitializers: ManifestNode.readList(reader),
     );
   }
 
@@ -405,7 +410,8 @@
     return super.match(context, element) &&
         isConst == element.isConst &&
         isFactory == element.isFactory &&
-        functionType.match(context, element.type);
+        functionType.match(context, element.type) &&
+        constantInitializers.match(context, element.constantInitializers);
   }
 
   @override
@@ -415,6 +421,7 @@
     sink.writeBool(isConst);
     sink.writeBool(isFactory);
     functionType.writeNoTag(sink);
+    constantInitializers.writeList(sink);
   }
 }
 
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index 9575945..d97ba7f 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -12390,6 +12390,570 @@
     );
   }
 
+  test_manifest_class_constructor_initializers_isConst_add() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  const A.named(int x);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+''',
+      updatedCode: r'''
+class A {
+  const A.named(int x) : assert(x > 0);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M2
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_assert() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  const A.named(int x) : assert(x > 0);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+''',
+      updatedCode: r'''
+class A {
+  const A.named(int x) : assert(x > 1);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M2
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_fieldInitializer_name() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  final int foo;
+  const A.named() : bar = 0;
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          foo: #M1
+          named: #M2
+''',
+      updatedCode: r'''
+class A {
+  final int foo;
+  const A.named() : foo = 0;
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          foo: #M1
+          named: #M3
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_fieldInitializer_value() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  final int foo;
+  const A.named() : foo = 0;
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          foo: #M1
+          named: #M2
+''',
+      updatedCode: r'''
+class A {
+  final int foo;
+  const A.named() : foo = 1;
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          foo: #M1
+          named: #M3
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_redirect_argument() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  final int f;
+  const A.c1(int a) : f = a;
+  const A.c2() : this.c1(0);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          c1: #M1
+          c2: #M2
+          f: #M3
+''',
+      updatedCode: r'''
+class A {
+  final int f;
+  const A.c1(int a) : f = a;
+  const A.c2() : this.c1(1);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          c1: #M1
+          c2: #M4
+          f: #M3
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_redirect_name() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  final int f;
+  const A.c1() : f = 0;
+  const A.c2() : f = 1;
+  const A.c3() : this.c1();
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          c1: #M1
+          c2: #M2
+          c3: #M3
+          f: #M4
+''',
+      updatedCode: r'''
+class A {
+  final int f;
+  const A.c1() : f = 0;
+  const A.c2() : f = 1;
+  const A.c3() : this.c2();
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          c1: #M1
+          c2: #M2
+          c3: #M5
+          f: #M4
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_remove() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  const A.named(int x) : assert(x > 0);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+''',
+      updatedCode: r'''
+class A {
+  const A.named(int x);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M2
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_super_argument() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  const A.named(int _);
+}
+
+class B extends A {
+  const A.named() : super.named(0);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+      B: #M2
+        declaredMembers
+          named: #M3
+''',
+      updatedCode: r'''
+class A {
+  const A.named(int _);
+}
+
+class B extends A {
+  const A.named() : super.named(1);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+      B: #M2
+        declaredMembers
+          named: #M4
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_super_name() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  final int f;
+  const A.c1() : f = 0;
+  const A.c2() : f = 1;
+}
+
+class B extends A {
+  const A.named() : super.c1(0);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          c1: #M1
+          c2: #M2
+          f: #M3
+      B: #M4
+        declaredMembers
+          named: #M5
+        inheritedMembers
+          f: #M3
+''',
+      updatedCode: r'''
+class A {
+  final int f;
+  const A.c1() : f = 0;
+  const A.c2() : f = 1;
+}
+
+class B extends A {
+  const A.named() : super.c2(0);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          c1: #M1
+          c2: #M2
+          f: #M3
+      B: #M4
+        declaredMembers
+          named: #M6
+        inheritedMembers
+          f: #M3
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_isConst_super_transitive() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  final int f;
+  const A.named() : f = 0;
+}
+
+class B extends A {
+  const A.named() : super.named();
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          f: #M1
+          named: #M2
+      B: #M3
+        declaredMembers
+          named: #M4
+        inheritedMembers
+          f: #M1
+''',
+      updatedCode: r'''
+class A {
+  final int f;
+  const A.named() : f = 1;
+}
+
+class B extends A {
+  const A.named() : super.named();
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          f: #M1
+          named: #M5
+      B: #M3
+        declaredMembers
+          named: #M6
+        inheritedMembers
+          f: #M1
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_notConst_assert() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  A.named(int x) : assert(x > 0);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+''',
+      updatedCode: r'''
+class A {
+  A.named(int x) : assert(x > 1);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_notConst_fieldInitializer_value() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  final int foo;
+  A.named() : foo = 0;
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          foo: #M1
+          named: #M2
+''',
+      updatedCode: r'''
+class A {
+  final int foo;
+  A.named() : foo = 1;
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          foo: #M1
+          named: #M2
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_notConst_redirect_argument() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  final int f;
+  A.c1(int a) : f = a;
+  A.c2() : this.c1(0);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          c1: #M1
+          c2: #M2
+          f: #M3
+''',
+      updatedCode: r'''
+class A {
+  final int f;
+  A.c1(int a) : f = a;
+  A.c2() : this.c1(1);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          c1: #M1
+          c2: #M2
+          f: #M3
+''',
+    );
+  }
+
+  test_manifest_class_constructor_initializers_notConst_super_argument() async {
+    await _runLibraryManifestScenario(
+      initialCode: r'''
+class A {
+  const A.named(int _);
+}
+
+class B extends A {
+  A.named() : super.named(0);
+}
+''',
+      expectedInitialEvents: r'''
+[operation] linkLibraryCycle SDK
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+      B: #M2
+        declaredMembers
+          named: #M3
+''',
+      updatedCode: r'''
+class A {
+  const A.named(int _);
+}
+
+class B extends A {
+  A.named() : super.named(1);
+}
+''',
+      expectedUpdatedEvents: r'''
+[operation] linkLibraryCycle
+  package:test/test.dart
+    manifest
+      A: #M0
+        declaredMembers
+          named: #M1
+      B: #M2
+        declaredMembers
+          named: #M3
+''',
+    );
+  }
+
   test_manifest_class_constructor_isConst_falseToTrue() async {
     await _runLibraryManifestScenario(
       initialCode: r'''