[cfe] Remove Builder.parent setter

This also moves some uses from .parent to .declarationBuilder to reduce
the reliance on the Builder.parent getter.

Change-Id: Ie99a7237a0f2bb68016cd1e0643f4e9045600a1e
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/386140
Reviewed-by: Jens Johansen <jensj@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
diff --git a/pkg/front_end/lib/src/base/name_space.dart b/pkg/front_end/lib/src/base/name_space.dart
index 4d54282..0410f0a 100644
--- a/pkg/front_end/lib/src/base/name_space.dart
+++ b/pkg/front_end/lib/src/base/name_space.dart
@@ -428,7 +428,7 @@
       // Coverage-ignore-block(suite): Not run.
       bool needsPatching = false;
       for (ExtensionBuilder extensionBuilder in _extensions!) {
-        if (replacementMap.containsKey(extensionBuilder.parent)) {
+        if (replacementMap.containsKey(extensionBuilder.libraryBuilder)) {
           needsPatching = true;
           break;
         }
@@ -437,13 +437,12 @@
         Set<ExtensionBuilder> extensionsReplacement =
             new Set<ExtensionBuilder>();
         for (ExtensionBuilder extensionBuilder in _extensions!) {
-          if (replacementMap.containsKey(extensionBuilder.parent)) {
-            assert(replacementMap[extensionBuilder.parent]![
+          if (replacementMap.containsKey(extensionBuilder.libraryBuilder)) {
+            assert(replacementMap[extensionBuilder.libraryBuilder]![
                     extensionBuilder.name] !=
                 null);
-            extensionsReplacement.add(
-                replacementMap[extensionBuilder.parent]![extensionBuilder.name]
-                    as ExtensionBuilder);
+            extensionsReplacement.add(replacementMap[extensionBuilder
+                .libraryBuilder]![extensionBuilder.name] as ExtensionBuilder);
             break;
           } else {
             extensionsReplacement.add(extensionBuilder);
diff --git a/pkg/front_end/lib/src/base/scope.dart b/pkg/front_end/lib/src/base/scope.dart
index 6884926..8481e2b 100644
--- a/pkg/front_end/lib/src/base/scope.dart
+++ b/pkg/front_end/lib/src/base/scope.dart
@@ -703,11 +703,6 @@
   }
 
   @override
-  void set parent(Builder? value) {
-    throw new UnsupportedError('$runtimeType.parent=');
-  }
-
-  @override
   DeclarationBuilder get declarationBuilder {
     throw new UnsupportedError('$runtimeType.declarationBuilder');
   }
diff --git a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
index b1d4608..f882ea9 100644
--- a/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
+++ b/pkg/front_end/lib/src/builder/formal_parameter_builder.dart
@@ -21,6 +21,7 @@
 import '../source/constructor_declaration.dart';
 import '../source/source_factory_builder.dart';
 import '../source/source_field_builder.dart';
+import '../source/source_function_builder.dart';
 import '../source/source_library_builder.dart';
 import 'builder.dart';
 import 'constructor_builder.dart';
@@ -54,6 +55,11 @@
     implements VariableBuilder, ParameterBuilder, InferredTypeListener {
   static const String noNameSentinel = 'no name sentinel';
 
+  SourceFunctionBuilder? _parent;
+
+  @override
+  final int charOffset;
+
   @override
   final int modifiers;
 
@@ -94,18 +100,27 @@
   final bool isWildcard;
 
   FormalParameterBuilder(
-      this.kind, this.modifiers, this.type, this.name, int charOffset,
-      {required Uri fileUri,
+      this.kind, this.modifiers, this.type, this.name, this.charOffset,
+      {required this.fileUri,
       this.isExtensionThis = false,
       required this.hasImmediatelyDeclaredInitializer,
       this.isWildcard = false})
-      : this.fileUri = fileUri,
-        this.hasDeclaredInitializer = hasImmediatelyDeclaredInitializer,
-        super(null, charOffset) {
+      : this.hasDeclaredInitializer = hasImmediatelyDeclaredInitializer {
     type.registerInferredTypeListener(this);
   }
 
   @override
+  SourceFunctionBuilder get parent {
+    assert(_parent != null, "Parent has not been set for $this.");
+    return _parent!;
+  }
+
+  void set parent(SourceFunctionBuilder value) {
+    assert(_parent == null, "Parent has already been set for $this.");
+    _parent = value;
+  }
+
+  @override
   String get debugName => "FormalParameterBuilder";
 
   @override
@@ -185,7 +200,7 @@
         fileUri: fileUri,
         isExtensionThis: isExtensionThis,
         hasImmediatelyDeclaredInitializer: hasImmediatelyDeclaredInitializer)
-      ..parent = parent
+      .._parent = _parent
       ..variable = variable;
   }
 
@@ -246,9 +261,9 @@
     if (parent is ConstructorBuilder) {
       return true;
     } else if (parent is SourceFactoryBuilder) {
-      return parent!.isFactory;
+      return parent.isFactory;
     } else {
-      return parent!.isClassInstanceMember;
+      return parent.isClassInstanceMember;
     }
   }
 
@@ -258,7 +273,7 @@
     if (needsDefaultValuesBuiltAsOutlineExpressions) {
       if (initializerToken != null) {
         final DeclarationBuilder declarationBuilder =
-            parent!.parent as DeclarationBuilder;
+            parent.declarationBuilder!;
         LookupScope scope = declarationBuilder.scope;
         BodyBuilderContext bodyBuilderContext = new ParameterBodyBuilderContext(
             this,
diff --git a/pkg/front_end/lib/src/builder/library_builder.dart b/pkg/front_end/lib/src/builder/library_builder.dart
index 0837f19..b38163f 100644
--- a/pkg/front_end/lib/src/builder/library_builder.dart
+++ b/pkg/front_end/lib/src/builder/library_builder.dart
@@ -396,7 +396,7 @@
   @override
   bool mayImplementRestrictedTypes = false;
 
-  LibraryBuilderImpl(this.fileUri) : super(null, -1);
+  LibraryBuilderImpl(this.fileUri);
 
   @override
   // Coverage-ignore(suite): Not run.
@@ -407,6 +407,9 @@
   Builder? get parent => null;
 
   @override
+  int get charOffset => -1;
+
+  @override
   bool get isPart => false;
 
   @override
diff --git a/pkg/front_end/lib/src/builder/member_builder.dart b/pkg/front_end/lib/src/builder/member_builder.dart
index c83ba4c..2476cfb 100644
--- a/pkg/front_end/lib/src/builder/member_builder.dart
+++ b/pkg/front_end/lib/src/builder/member_builder.dart
@@ -19,8 +19,6 @@
 
   bool get isAssignable;
 
-  void set parent(Builder? value);
-
   LibraryBuilder get libraryBuilder;
 
   /// The declared name of this member;
@@ -104,13 +102,15 @@
   /// construction. However, for class members, the parent is initially the
   /// library and updated later.
   @override
-  Builder? parent;
+  Builder parent;
+
+  @override
+  final int charOffset;
 
   @override
   final Uri fileUri;
 
-  MemberBuilderImpl(this.parent, this.fileUri, int charOffset)
-      : super(parent, charOffset);
+  MemberBuilderImpl(this.parent, this.fileUri, this.charOffset);
 
   @override
   DeclarationBuilder? get declarationBuilder =>
diff --git a/pkg/front_end/lib/src/builder/modifier_builder.dart b/pkg/front_end/lib/src/builder/modifier_builder.dart
index 0e0bb45..0d71815 100644
--- a/pkg/front_end/lib/src/builder/modifier_builder.dart
+++ b/pkg/front_end/lib/src/builder/modifier_builder.dart
@@ -14,13 +14,7 @@
 
   String get debugName;
 
-  @override
-  Builder? parent;
-
-  @override
-  final int charOffset;
-
-  ModifierBuilderImpl(Builder? parent, this.charOffset) : this.parent = parent;
+  ModifierBuilderImpl();
 
   @override
   bool get isConst => (modifiers & constMask) != 0;
diff --git a/pkg/front_end/lib/src/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/builder/type_declaration_builder.dart
index 6702d8e..4a84ba5 100644
--- a/pkg/front_end/lib/src/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/builder/type_declaration_builder.dart
@@ -10,8 +10,6 @@
 
   bool get isNamedMixinApplication;
 
-  void set parent(Builder? value);
-
   List<MetadataBuilder>? get metadata;
 
   int get typeVariablesCount => 0;
@@ -65,6 +63,12 @@
 abstract class TypeDeclarationBuilderImpl extends ModifierBuilderImpl
     implements ITypeDeclarationBuilder {
   @override
+  final Builder? parent;
+
+  @override
+  final int charOffset;
+
+  @override
   final List<MetadataBuilder>? metadata;
 
   @override
@@ -74,8 +78,7 @@
   final String name;
 
   TypeDeclarationBuilderImpl(
-      this.metadata, this.modifiers, this.name, Builder? parent, int charOffset)
-      : super(parent, charOffset);
+      this.metadata, this.modifiers, this.name, this.parent, this.charOffset);
 
   @override
   TypeDeclarationBuilder get origin => this as TypeDeclarationBuilder;
diff --git a/pkg/front_end/lib/src/kernel/body_builder.dart b/pkg/front_end/lib/src/kernel/body_builder.dart
index 2426f009..01bfead 100644
--- a/pkg/front_end/lib/src/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder.dart
@@ -3315,8 +3315,8 @@
     } else if (declaration.isRegularMethod) {
       assert(declaration.isStatic || declaration.isTopLevel);
       MemberBuilder memberBuilder = declaration as MemberBuilder;
-      return new StaticAccessGenerator(this, nameToken, name,
-          memberBuilder.parent, memberBuilder.member, null);
+      return new StaticAccessGenerator(
+          this, nameToken, name, memberBuilder.member, null);
     } else if (declaration is PrefixBuilder) {
       assert(prefix == null);
       // Wildcard import prefixes are non-binding and cannot be used.
diff --git a/pkg/front_end/lib/src/kernel/body_builder_context.dart b/pkg/front_end/lib/src/kernel/body_builder_context.dart
index 846894f..fb433df 100644
--- a/pkg/front_end/lib/src/kernel/body_builder_context.dart
+++ b/pkg/front_end/lib/src/kernel/body_builder_context.dart
@@ -983,7 +983,7 @@
       required bool inMetadata,
       required bool inConstFields}) {
     final DeclarationBuilder declarationBuilder =
-        formalParameterBuilder.parent!.parent as DeclarationBuilder;
+        formalParameterBuilder.parent.declarationBuilder!;
     return new ParameterBodyBuilderContext._(declarationBuilder.libraryBuilder,
         declarationBuilder, formalParameterBuilder,
         inOutlineBuildingPhase: inOutlineBuildingPhase,
diff --git a/pkg/front_end/lib/src/kernel/expression_generator.dart b/pkg/front_end/lib/src/kernel/expression_generator.dart
index 4e629a5..86d3517 100644
--- a/pkg/front_end/lib/src/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/kernel/expression_generator.dart
@@ -37,7 +37,6 @@
 import '../base/scope.dart';
 import '../builder/builder.dart';
 import '../builder/declaration_builders.dart';
-import '../builder/library_builder.dart';
 import '../builder/member_builder.dart';
 import '../builder/named_type_builder.dart';
 import '../builder/nullability_builder.dart';
@@ -1408,16 +1407,10 @@
   final int? typeOffset;
   final bool isNullAware;
 
-  /// The builder for the parent of [readTarget] and [writeTarget]. This is
-  /// either the builder for the enclosing library,  class, or extension.
-  final Builder? parentBuilder;
-
   StaticAccessGenerator(ExpressionGeneratorHelper helper, Token token,
-      this.targetName, this.parentBuilder, this.readTarget, this.writeTarget,
+      this.targetName, this.readTarget, this.writeTarget,
       {this.typeOffset, this.isNullAware = false})
       : assert(readTarget != null || writeTarget != null),
-        assert(parentBuilder is DeclarationBuilder ||
-            parentBuilder is LibraryBuilder),
         super(helper, token);
 
   factory StaticAccessGenerator.fromBuilder(
@@ -1433,18 +1426,10 @@
     // class/extension.
     assert(getterBuilder == null ||
         setterBuilder == null ||
-        (getterBuilder.parent is LibraryBuilder &&
-            setterBuilder.parent is LibraryBuilder) ||
-        getterBuilder.parent == setterBuilder.parent);
-    return new StaticAccessGenerator(
-        helper,
-        token,
-        targetName,
-        getterBuilder?.parent ?? setterBuilder?.parent,
-        getterBuilder?.readTarget,
-        setterBuilder?.writeTarget,
-        typeOffset: typeOffset,
-        isNullAware: isNullAware);
+        getterBuilder.declarationBuilder == setterBuilder.declarationBuilder);
+    return new StaticAccessGenerator(helper, token, targetName,
+        getterBuilder?.readTarget, setterBuilder?.writeTarget,
+        typeOffset: typeOffset, isNullAware: isNullAware);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/kernel/macro/introspectors.dart b/pkg/front_end/lib/src/kernel/macro/introspectors.dart
index 1895f46..ca7814b 100644
--- a/pkg/front_end/lib/src/kernel/macro/introspectors.dart
+++ b/pkg/front_end/lib/src/kernel/macro/introspectors.dart
@@ -410,7 +410,7 @@
       List<macro.FormalParameterDeclarationImpl> namedParameters
     ) = _createParameters(builder.libraryBuilder, formals);
     macro.ParameterizedTypeDeclaration definingTypeDeclaration;
-    Builder? parent = builder.parent;
+    DeclarationBuilder? parent = builder.declarationBuilder;
     if (parent is ClassBuilder) {
       definingTypeDeclaration = getClassDeclaration(parent);
     } else if (parent is ExtensionTypeDeclarationBuilder) {
diff --git a/pkg/front_end/lib/src/source/class_declaration.dart b/pkg/front_end/lib/src/source/class_declaration.dart
index 9e565f4..d965482 100644
--- a/pkg/front_end/lib/src/source/class_declaration.dart
+++ b/pkg/front_end/lib/src/source/class_declaration.dart
@@ -102,9 +102,9 @@
           parent: this, includeDuplicates: true, includeAugmentations: true);
       while (iterator.moveNext()) {
         MemberBuilder declaration = iterator.current;
-        if (declaration.parent?.origin != origin) {
-          unexpected("$fileUri", "${declaration.parent!.fileUri}", charOffset,
-              fileUri);
+        if (declaration.declarationBuilder?.origin != origin) {
+          unexpected("$fileUri", "${declaration.declarationBuilder!.fileUri}",
+              charOffset, fileUri);
         }
         if (declaration is RedirectingFactoryBuilder) {
           // Compute the immediate redirection target, not the effective.
diff --git a/pkg/front_end/lib/src/source/source_enum_builder.dart b/pkg/front_end/lib/src/source/source_enum_builder.dart
index 78c4114..e0db936 100644
--- a/pkg/front_end/lib/src/source/source_enum_builder.dart
+++ b/pkg/front_end/lib/src/source/source_enum_builder.dart
@@ -418,7 +418,6 @@
     nameSpace.addLocalMember("_enumToString", toStringBuilder, setter: false);
     nameSpaceBuilder.checkTypeVariableConflict(libraryBuilder,
         toStringBuilder.name, toStringBuilder, toStringBuilder.fileUri!);
-    toStringBuilder.parent = this;
 
     String className = name;
 
diff --git a/pkg/front_end/lib/src/source/source_loader.dart b/pkg/front_end/lib/src/source/source_loader.dart
index cf62a09..5f594c5 100644
--- a/pkg/front_end/lib/src/source/source_loader.dart
+++ b/pkg/front_end/lib/src/source/source_loader.dart
@@ -2967,7 +2967,7 @@
         return;
       }
       if (mainBuilder.isField || mainBuilder.isGetter || mainBuilder.isSetter) {
-        if (mainBuilder.parent != libraryBuilder) {
+        if (mainBuilder.libraryBuilder != libraryBuilder) {
           libraryBuilder.addProblem(messageMainNotFunctionDeclarationExported,
               libraryBuilder.charOffset, noLength, libraryBuilder.fileUri,
               context: [
@@ -2984,7 +2984,7 @@
       } else {
         Procedure procedure = mainBuilder.member as Procedure;
         if (procedure.function.requiredParameterCount > 2) {
-          if (mainBuilder.parent != libraryBuilder) {
+          if (mainBuilder.libraryBuilder != libraryBuilder) {
             libraryBuilder.addProblem(
                 messageMainTooManyRequiredParametersExported,
                 libraryBuilder.charOffset,
@@ -3003,7 +3003,7 @@
           }
         } else if (procedure.function.namedParameters
             .any((parameter) => parameter.isRequired)) {
-          if (mainBuilder.parent != libraryBuilder) {
+          if (mainBuilder.libraryBuilder != libraryBuilder) {
             libraryBuilder.addProblem(
                 messageMainRequiredNamedParametersExported,
                 libraryBuilder.charOffset,
@@ -3026,7 +3026,7 @@
 
           if (!typeEnvironment.isSubtypeOf(listOfString, parameterType,
               SubtypeCheckMode.withNullabilities)) {
-            if (mainBuilder.parent != libraryBuilder) {
+            if (mainBuilder.libraryBuilder != libraryBuilder) {
               libraryBuilder.addProblem(
                   templateMainWrongParameterTypeExported.withArguments(
                       parameterType, listOfString),
diff --git a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
index 1e2731f..b2c378e 100644
--- a/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
+++ b/pkg/front_end/lib/src/source/type_parameter_scope_builder.dart
@@ -525,15 +525,13 @@
         String name, Builder declaration, Uri fileUri, int charOffset) {
       if (declaration is SourceExtensionBuilder &&
           declaration.isUnnamedExtension) {
-        declaration.parent = enclosingLibraryBuilder;
         extensions.add(declaration);
         return;
       }
 
-      if (declaration is MemberBuilder) {
-        declaration.parent = enclosingLibraryBuilder;
-      } else if (declaration is TypeDeclarationBuilder) {
-        declaration.parent = enclosingLibraryBuilder;
+      if (declaration is MemberBuilder ||
+          declaration is TypeDeclarationBuilder) {
+        // Expected.
       } else {
         // Coverage-ignore-block(suite): Not run.
         // Prefix builders are added when computing the import scope.
@@ -857,22 +855,14 @@
       }
     }
 
-    void setParent(MemberBuilder? member) {
-      while (member != null) {
-        member.parent = declarationBuilder;
-        member = member.next as MemberBuilder?;
-      }
-    }
-
-    void setParentAndCheckConflicts(String name, Builder member) {
+    void checkConflicts(String name, Builder member) {
       checkTypeVariableConflict(
           problemReporting, name, member, member.fileUri!);
-      setParent(member as MemberBuilder);
     }
 
-    getables.forEach(setParentAndCheckConflicts);
-    setables.forEach(setParentAndCheckConflicts);
-    constructors.forEach(setParentAndCheckConflicts);
+    getables.forEach(checkConflicts);
+    setables.forEach(checkConflicts);
+    constructors.forEach(checkConflicts);
 
     return new DeclarationNameSpaceImpl(
         getables: getables,
diff --git a/pkg/front_end/test/extensions/extensions_test.dart b/pkg/front_end/test/extensions/extensions_test.dart
index d5c4fab..3f2886b 100644
--- a/pkg/front_end/test/extensions/extensions_test.dart
+++ b/pkg/front_end/test/extensions/extensions_test.dart
@@ -134,7 +134,7 @@
     SourceLibraryBuilder libraryBuilder =
         lookupLibraryBuilder(compilerResult, library) as SourceLibraryBuilder;
     libraryBuilder.forEachExtensionInScope((ExtensionBuilder extension) {
-      LibraryBuilder library = extension.parent as LibraryBuilder;
+      LibraryBuilder library = extension.libraryBuilder;
       if (library.importUri.isScheme('dart')) {
         // Don't include dart: extensions.
         return;
diff --git a/pkg/front_end/test/fasta/generator_to_string_test.dart b/pkg/front_end/test/fasta/generator_to_string_test.dart
index c05001e..33ba32f 100644
--- a/pkg/front_end/test/fasta/generator_to_string_test.dart
+++ b/pkg/front_end/test/fasta/generator_to_string_test.dart
@@ -187,8 +187,7 @@
         "StaticAccessGenerator(offset: 4, targetName: foo,"
         " readTarget: $uri::myGetter,"
         " writeTarget: $uri::mySetter)",
-        new StaticAccessGenerator(
-            helper, token, 'foo', libraryBuilder, getter, setter));
+        new StaticAccessGenerator(helper, token, 'foo', getter, setter));
     check(
         "LoadLibraryGenerator(offset: 4,"
         " builder: Instance of 'LoadLibraryBuilder')",