Verify parent of child in ResolvedAstPrinter.

Fix found issues.

Change-Id: I72f3eed470f0cb474ae9db75ec7ee4f0fd805563
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/262841
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Samuel Rawlins <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 6c3f075..6f97840 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -1478,10 +1478,13 @@
   @override
   final DartPatternImpl pattern;
 
-  CaseClauseImpl(
-      {required this.caseKeyword,
-      required this.pattern,
-      required this.whenClause});
+  CaseClauseImpl({
+    required this.caseKeyword,
+    required this.pattern,
+    required this.whenClause,
+  }) {
+    _becomeParentOf(pattern);
+  }
 
   @override
   Token get beginToken => caseKeyword;
@@ -2769,10 +2772,12 @@
   @override
   final Token? constKeyword;
 
-  @override
-  ExpressionImpl expression;
+  ExpressionImpl _expression;
 
-  ConstantPatternImpl({required this.constKeyword, required this.expression}) {
+  ConstantPatternImpl({
+    required this.constKeyword,
+    required ExpressionImpl expression,
+  }) : _expression = expression {
     _becomeParentOf(expression);
   }
 
@@ -2783,6 +2788,13 @@
   Token get endToken => expression.endToken;
 
   @override
+  ExpressionImpl get expression => _expression;
+
+  set expression(ExpressionImpl expression) {
+    _expression = _becomeParentOf(expression);
+  }
+
+  @override
   ChildEntities get _childEntities => super._childEntities
     ..addToken('const', constKeyword)
     ..addNode('expression', expression);
@@ -10606,6 +10618,7 @@
     required this.rightParenthesis,
     required this.question,
   }) {
+    _becomeParentOf(namedFields);
     this.positionalFields._initialize(this, positionalFields);
   }
 
diff --git a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
index ae02e70..85e583d 100644
--- a/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
+++ b/pkg/analyzer/test/src/summary/resolved_ast_printer.dart
@@ -1510,6 +1510,25 @@
     }
   }
 
+  /// Check that the actual parent of [child] is [parent].
+  void _checkParentOfChild(AstNode parent, AstNode child) {
+    final actualParent = child.parent;
+    if (actualParent == null) {
+      fail('''
+No parent.
+Child: (${child.runtimeType}) $child
+Expected parent: (${parent.runtimeType}) $parent
+''');
+    } else if (actualParent != parent) {
+      fail('''
+Wrong parent.
+Child: (${child.runtimeType}) $child
+Actual parent: (${actualParent.runtimeType}) $actualParent
+Expected parent: (${parent.runtimeType}) $parent
+''');
+    }
+  }
+
   String _elementToReferenceString(Element element) {
     final enclosingElement = element.enclosingElement;
     final reference = (element as ElementImpl).reference;
@@ -1741,6 +1760,7 @@
       if (value is Token) {
         _writeToken(entity.name, value);
       } else if (value is AstNode) {
+        _checkParentOfChild(node, value);
         if (value is ArgumentList && skipArgumentList) {
         } else {
           _writeNode(entity.name, value);
@@ -1748,7 +1768,7 @@
       } else if (value is List<Token>) {
         _writeTokenList(entity.name, value);
       } else if (value is List<AstNode>) {
-        _writeNodeList(entity.name, value);
+        _writeNodeList(node, entity.name, value);
       } else {
         throw UnimplementedError('(${value.runtimeType}) $value');
       }
@@ -1763,11 +1783,12 @@
     }
   }
 
-  void _writeNodeList(String name, List<AstNode> nodeList) {
+  void _writeNodeList(AstNode parent, String name, List<AstNode> nodeList) {
     if (nodeList.isNotEmpty) {
       _writelnWithIndent(name);
       _withIndent(() {
         for (var node in nodeList) {
+          _checkParentOfChild(parent, node);
           _sink.write(_indent);
           node.accept(this);
         }