// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// 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.

/// @docImport 'package:dartdoc/src/mustachio/renderer_base.dart';
library;

import 'dart:collection';

import 'package:analyzer/dart/element/element2.dart';
import 'package:analyzer/dart/element/nullability_suffix.dart';
import 'package:analyzer/dart/element/type.dart';
import 'package:analyzer/dart/element/type_provider.dart';
import 'package:analyzer/dart/element/type_system.dart';
import 'package:dart_style/dart_style.dart';
import 'package:dartdoc/src/mustachio/annotations.dart';
import 'package:dartdoc/src/type_utils.dart';
import 'package:path/path.dart' as path;

import 'utilities.dart';

/// Builds [specs] into a Dart library containing runtime renderers.
String buildRuntimeRenderers(Set<RendererSpec> specs, Uri sourceUri,
    TypeProvider typeProvider, TypeSystem typeSystem,
    {bool rendererClassesArePublic = false}) {
  var visibleElements = specs
      .map((spec) => spec.visibleTypes)
      .reduce((value, element) => value.union(element))
      .map((type) => type.documentableElement2!)
      .toSet();
  var raw = RuntimeRenderersBuilder(
          sourceUri, typeProvider, typeSystem, visibleElements,
          rendererClassesArePublic: rendererClassesArePublic)
      ._buildTemplateRenderers(specs);
  return DartFormatter(languageVersion: DartFormatter.latestLanguageVersion)
      .format(raw);
}

/// This class builds runtime Mustache renderers from a set of [RendererSpec]s.
class RuntimeRenderersBuilder {
  static const _contextTypeVariable = 'CT_';

  final _buffer = StringBuffer();

  /// A queue of types to process, in order to find all types for which we need
  /// to build renderers.
  final _typesToProcess = Queue<_RendererInfo>();

  /// Maps a type to the name of the render function which can render that type
  /// as a context type.
  final _typeToRenderFunctionName = <InterfaceElement2, String>{};

  /// Maps a type to the name of the renderer class which can render that type
  /// as a context type.
  final _typeToRendererClassName = <InterfaceElement2, String>{};

  final Uri _sourceUri;

  final TypeProvider _typeProvider;
  final TypeSystem _typeSystem;

  final Set<Element2> _allVisibleElements;

  /// Whether renderer classes are public. This should only be true for testing.
  final bool _rendererClassesArePublic;

  /// A mapping of getter names on classes which are not "visible."
  final Map<String, Set<String>> _invisibleGetters = {};

  RuntimeRenderersBuilder(this._sourceUri, this._typeProvider, this._typeSystem,
      this._allVisibleElements,
      {bool rendererClassesArePublic = false})
      : _rendererClassesArePublic = rendererClassesArePublic;

  String _buildTemplateRenderers(Set<RendererSpec> specs) {
    // TODO(srawlins): There are some private renderer functions that are
    // unused. Figure out if we can detect these statically, and then not
    // generate them.
    // TODO(srawlins): To really get the correct list of imports, we need to use
    // the code_builder package.
    _buffer.writeln('''
// GENERATED CODE. DO NOT EDIT.
//
// To change the contents of this library, make changes to the builder source
// files in the tool/mustachio/ directory.

// ignore_for_file: camel_case_types, deprecated_member_use_from_same_package
// ignore_for_file: non_constant_identifier_names, unnecessary_string_escapes
// ignore_for_file: unused_import
// ignore_for_file: use_super_parameters

import 'package:dartdoc/src/element_type.dart';
import 'package:dartdoc/src/generator/template_data.dart';
import 'package:dartdoc/src/model/annotation.dart';
import 'package:dartdoc/src/model/attribute.dart';
import 'package:dartdoc/src/model/comment_referable.dart';
import 'package:dartdoc/src/model/feature_set.dart';
import 'package:dartdoc/src/model/language_feature.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/mustachio/parser.dart';
import 'package:dartdoc/src/mustachio/renderer_base.dart';
import 'package:dartdoc/src/warnings.dart';
import '${path.basename(_sourceUri.path)}';
''');

    specs.forEach(_addTypesForRendererSpec);
    var builtRenderers = <InterfaceElement2>{};
    var elementsToProcess = _typesToProcess.toList()
      ..sort((a, b) => a._typeName.compareTo(b._typeName));

    for (var info in elementsToProcess) {
      if (info.isFullRenderer) {
        var buildOnlyPublicFunction =
            builtRenderers.contains(info._contextClass);
        _buildRenderer(info, buildOnlyPublicFunction: buildOnlyPublicFunction);
        builtRenderers.add(info._contextClass);
      }
    }

    _writeInvisibleGetters();

    return _buffer.toString();
  }

  /// Adds type specified in [spec] to the [_typesToProcess] queue, as well as
  /// all supertypes, and the types of all valid getters, recursively.
  void _addTypesForRendererSpec(RendererSpec spec) {
    var element = spec.contextElement;
    var rendererInfo = _RendererInfo(element,
        public: _rendererClassesArePublic, publicApiFunctionName: spec.name);
    _typesToProcess.add(rendererInfo);
    _typeToRenderFunctionName[element] = rendererInfo._renderFunctionName;
    _typeToRendererClassName[element] = rendererInfo._rendererClassName;

    spec.contextType.getters.forEach(_addPropertyToProcess);

    for (var mixin in spec.contextElement.mixins) {
      _addTypeToProcess(mixin.element3,
          isFullRenderer: true, includeRenderFunction: false);
    }
    var superclass = spec.contextElement.supertype;

    while (superclass != null) {
      // Any type specified with a renderer spec (`@Renderer`) is full.
      _addTypeToProcess(superclass.element3,
          isFullRenderer: true, includeRenderFunction: false);
      for (var mixin in superclass.element3.mixins) {
        _addTypeToProcess(mixin.element3,
            isFullRenderer: true, includeRenderFunction: false);
      }
      superclass.getters.forEach(_addPropertyToProcess);
      superclass = superclass.element3.supertype;
    }
  }

  /// Adds the return type of [property] to the [_typesToProcess] queue, if it
  /// is a "valid" property.
  ///
  /// A "valid" property is a public, instance getter with an interface type
  /// return type. Getters annotated with `@internal`, `@protected`,
  ///  `@visibleForOverriding`, or `@visibleForTesting` are not valid.
  void _addPropertyToProcess(GetterElement property) {
    if (property.shouldBeOmitted) return;

    var type = _relevantTypeFrom(property.type.returnType);
    if (type == null) return;

    var types =
        _typesToProcess.where((rs) => rs._contextClass == type.element3);
    if (types.isNotEmpty) {
      assert(types.length == 1);
      if (types.first.includeRenderFunction) {
        // [type] has already been added to [_typesToProcess], and all of its
        // supertypes and properties have been visited.
        return;
      }
    }

    _addTypeHierarchyToProcess(
      type,
      isFullRenderer: _isVisibleToMustache(type.element3),
      // If [type.element] is not visible to mustache, then [renderSimple] will
      // be used, not [type.element]'s render function.
      includeRenderFunction: _isVisibleToMustache(type.element3),
    );
  }

  /// Returns an [InterfaceType] which may be relevant for generating a
  /// renderer, given a [type]:
  ///
  /// * If [type] is assignable to [Iterable<T>], returns the relevant type from
  ///   `T`.
  /// * If [type] is a [TypeParameterType] with a bound other than `dynamic`,
  ///   returns the relevant type from the bound.
  /// * If [type] is an [InterfaceType] (not assignable to [Iterable]), returns
  ///   [type].
  /// * Otherwise, returns `null`, indicating there is no relevant type.
  InterfaceType? _relevantTypeFrom(DartType type) {
    if (type is InterfaceType) {
      if (_typeSystem.isAssignableTo(type, _typeProvider.iterableDynamicType)) {
        var iterableElement = _typeProvider.iterableElement2;
        var iterableType = type.asInstanceOf2(iterableElement)!;
        var innerType = iterableType.typeArguments.first;

        return _relevantTypeFrom(innerType);
      } else {
        return type;
      }
    } else if (type is TypeParameterType) {
      var bound = type.bound;
      if (bound is DynamicType) {
        // Don't add functions for a generic type, for example
        // `List<E>.first` has type `E`, which we don't have a specific
        // renderer for.
        // TODO(srawlins): Find a solution for this. We can track all of the
        // concrete types substituted for `E` for example.
        return null;
      } else {
        return _relevantTypeFrom(bound);
      }
    } else {
      // We can do nothing with function types, record types, etc.
      return null;
    }
  }

  /// Adds [type] to the queue of types to process, as well as related types:
  ///
  /// * its supertypes (if [type] is not a mixin),
  /// * mixed in types,
  /// * superclass constraints (if [type] a mixin),
  /// * types of relevant properties (recursively).
  void _addTypeHierarchyToProcess(
    InterfaceType? type, {
    required bool isFullRenderer,
    required bool includeRenderFunction,
  }) {
    while (type != null) {
      _addTypeToProcess(
        type.element3,
        isFullRenderer: isFullRenderer,
        includeRenderFunction: includeRenderFunction,
      );
      if (isFullRenderer) {
        for (var getter in type.getters) {
          var getterType = _relevantTypeFrom(getter.type.returnType);
          if (getterType == null) continue;
          _addPropertyToProcess(getter);
        }
      }
      for (var mixin in type.element3.mixins) {
        _addTypeHierarchyToProcess(
          mixin,
          isFullRenderer: isFullRenderer,
          includeRenderFunction: false,
        );
      }
      final typeElement = type.element3;
      if (typeElement is MixinElement2) {
        for (var constraint in typeElement.superclassConstraints) {
          _addTypeToProcess(
            constraint.element3,
            isFullRenderer: isFullRenderer,
            includeRenderFunction: false,
          );
        }
        break;
      } else {
        type = type.superclass;
        // Render functions are not needed for superclasses.
        includeRenderFunction = false;
      }
    }
  }

  /// Adds [element] to the [_typesToProcess] queue, if it is not already there.
  void _addTypeToProcess(
    InterfaceElement2 element, {
    required bool isFullRenderer,
    required bool includeRenderFunction,
  }) {
    var types = _typesToProcess.where((rs) => rs._contextClass == element);
    if (types.isEmpty) {
      var rendererInfo = _RendererInfo(
        element,
        isFullRenderer: isFullRenderer,
        includeRenderFunction: includeRenderFunction,
        public: _rendererClassesArePublic,
      );
      _typesToProcess.add(rendererInfo);
      if (isFullRenderer) {
        if (includeRenderFunction) {
          _typeToRenderFunctionName[element] = rendererInfo._renderFunctionName;
        }
        _typeToRendererClassName[element] = rendererInfo._rendererClassName;
      }
    } else {
      for (var typeToProcess in types) {
        // "Upgrade" the renderer info to include a render function if the
        // current one doesn't.
        if (includeRenderFunction && !typeToProcess.includeRenderFunction) {
          typeToProcess.includeRenderFunction = true;
        }
        // "Upgrade" the renderer info to "full" if the current one isn't.
        if (isFullRenderer && !typeToProcess.isFullRenderer) {
          typeToProcess.isFullRenderer = true;
        }

        // Log the names if we've perhaps just "upgraded" the renderer info.
        if (isFullRenderer) {
          if (typeToProcess.includeRenderFunction) {
            _typeToRenderFunctionName[element] =
                typeToProcess._renderFunctionName;
          }
          _typeToRendererClassName[element] = typeToProcess._rendererClassName;
        }
      }
    }
  }

  /// Returns whether [element] or any of its supertypes are "visible" to
  /// Mustache.
  bool _isVisibleToMustache(InterfaceElement2 element) {
    if (_allVisibleElements.contains(element)) {
      return true;
    }
    var supertype = element.supertype;
    if (supertype == null) {
      return false;
    }
    return _isVisibleToMustache(supertype.element3);
  }

  /// Builds render functions and the renderer class for [renderer].
  ///
  /// The function and the class are each written as Dart code to [_buffer].
  ///
  /// If [renderer] also specifies a `publicApiFunctionName`, then a public API
  /// function (which renders a context object using a template file at a path,
  /// rather than an AST) is also written.
  ///
  /// If [buildOnlyPublicFunction] is true, then the private render function and
  /// renderer classes are not built, having been built for a different
  /// [_RendererInfo].
  void _buildRenderer(_RendererInfo renderer,
      {required bool buildOnlyPublicFunction}) {
    var typeName = renderer._typeName;
    var typeWithVariables = '$typeName${renderer._typeVariablesString}';

    if (renderer.publicApiFunctionName != null) {
      _buffer.writeln('''
String ${renderer.publicApiFunctionName}${renderer._typeParametersString}(
    $typeWithVariables context, Template template) {
  var buffer = StringBuffer();
  ${renderer._renderFunctionName}(context, template.ast, template, buffer);
  return buffer.toString();
}
''');
    }

    if (buildOnlyPublicFunction) return;

    // Write out the render function.
    if (renderer.includeRenderFunction) {
      _buffer.writeln('''
void ${renderer._renderFunctionName}${renderer._typeParametersString}(
    $typeWithVariables context, List<MustachioNode> ast,
    Template template, StringSink sink,
    {RendererBase<Object>? parent}) {
  var renderer = ${renderer._rendererClassName}(context, parent, template, sink);
  renderer.renderBlock(ast);
}
''');
    }

    // Write out the renderer class.
    _buffer.write('''
class ${renderer._rendererClassName}${renderer._typeParametersString}
    extends RendererBase<$typeWithVariables> {
''');
    _writePropertyMap(renderer);
    // Write out the constructor.
    _buffer.writeln('''
  ${renderer._rendererClassName}(
        $typeWithVariables context, RendererBase<Object>? parent,
        Template template, StringSink sink)
      : super(context, parent, template, sink);
''');
    var propertyMapTypeArguments =
        renderer._typeArgumentsStringWith(typeWithVariables);
    var propertyMapName = 'propertyMap$propertyMapTypeArguments';
    // Write out `getProperty`.
    _buffer.writeln('''
  @override
  Property<$typeWithVariables>? getProperty(String key) {
    if ($propertyMapName().containsKey(key)) {
      return $propertyMapName()[key];
    } else {
      return null;
    }
  }
''');
    // Close the class.
    _buffer.writeln('}');
  }

  /// Write out the property map for [renderer].
  ///
  /// For each valid property of the context type of [renderer], this maps the
  /// property's name to the property's [Property] object.
  void _writePropertyMap(_RendererInfo renderer) {
    var contextClass = renderer._contextClass;
    var generics = renderer._typeParametersStringWith(
        '$_contextTypeVariable extends ${renderer._typeName}');
    // It would be simplest if [propertyMap] were just a getter, but it must be
    // parameterized on `CT_`, so it is a static method. Due to the possibly
    // extensive amount of spreading (supertypes, mixins) and object
    // construction (lots of [Property] objects with function literals), we
    // cache the construction of each one, keyed to the `CT_` value. Each cache
    // should not have many entries, as there are probably not many values for
    // each type variable, `CT_`, typically one.
    _buffer.writeln('''
    static final Map<Type, Object> _propertyMapCache = {};
    static Map<String, Property<$_contextTypeVariable>> propertyMap$generics() =>
        _propertyMapCache.putIfAbsent($_contextTypeVariable, () => {''');
    var supertype = contextClass.supertype;
    if (supertype != null) {
      var superclassRendererName = _typeToRendererClassName[supertype.element3];
      if (superclassRendererName != null) {
        var superMapName = '$superclassRendererName.propertyMap';
        var generics = asGenerics([
          ...supertype.typeArguments.map((e) => e.getDisplayString()),
          _contextTypeVariable
        ]);
        _buffer.writeln('    ...$superMapName$generics(),');
      }
    }
    // Mixins are spread into the property map _after_ the super class, so
    // that they override any values which need to be overridden. Superclass
    // and mixins override from left to right, as do spreads:
    // `class C extends E with M, N` first takes members from N, then M, then
    // E. Similarly, `{...a, ...b, ...c}` will feature elements from `c` which
    // override `b` and `a`.
    for (var mixin in contextClass.mixins) {
      var mixinRendererName = _typeToRendererClassName[mixin.element3];
      if (mixinRendererName != null) {
        var mixinMapName = '$mixinRendererName.propertyMap';
        var generics = asGenerics([
          ...mixin.typeArguments.map((e) => e.getDisplayString()),
          _contextTypeVariable
        ]);
        _buffer.writeln('    ...$mixinMapName$generics(),');
      }
    }
    for (var property in [...contextClass.getters2]
      ..sort((a, b) => a.name3!.compareTo(b.name3!))) {
      var returnType = property.type.returnType;
      if (returnType is InterfaceType) {
        _writeProperty(renderer, property, returnType);
      } else if (returnType is TypeParameterType &&
          returnType.bound is! DynamicType) {
        _writeProperty(renderer, property, returnType.bound as InterfaceType);
      }
    }
    _buffer.writeln('}) as Map<String, Property<$_contextTypeVariable>>;');
    _buffer.writeln('');
  }

  void _writeProperty(_RendererInfo renderer, GetterElement property,
      InterfaceType getterType) {
    if (getterType == _typeProvider.typeType) {
      // The [Type] type is the first case of a type we don't want to traverse.
      return;
    }

    if (property.shouldBeOmitted) return;

    _buffer.writeln("'${property.name3}': Property(");
    _buffer
        .writeln('getValue: ($_contextTypeVariable c) => c.${property.name3},');

    var getterName = property.name3;
    var getterTypeString =
        _typeSystem.promoteToNonNull(getterType).getDisplayString();
    // Only add a `getProperties` function, which returns the property map for
    // [getterType], if [getterType] is a renderable type.
    if (_typeToRendererClassName.containsKey(getterType.element3)) {
      var rendererClassName = _typeToRendererClassName[getterType.element3];
      _buffer.writeln('''
renderVariable:
    ($_contextTypeVariable c,
     Property<$_contextTypeVariable> self,
     List<String> remainingNames) {
  if (remainingNames.isEmpty) {
    return self.getValue(c).toString();
  }
  var name = remainingNames.first;
  var nextProperty = $rendererClassName.propertyMap().getValue(name);
  return nextProperty.renderVariable(
      self.getValue(c) as $getterTypeString,
      nextProperty, [...remainingNames.skip(1)]);
},
''');
    } else {
      // [getterType] does not have a full renderer, so we just render a simple
      // variable, with no opportunity to access fields on [getterType].

      _buffer.writeln('''
renderVariable:
    ($_contextTypeVariable c, Property<CT_> self, List<String> remainingNames) =>
        self.renderSimpleVariable(c, remainingNames, '$getterTypeString'),
''');
    }

    if (getterType.isDartCoreBool) {
      _buffer.write(
        'getBool: ($_contextTypeVariable c) => c.$getterName',
      );
      if (getterType.nullabilitySuffix != NullabilitySuffix.none) {
        _buffer.writeln(' == true,');
      } else {
        _buffer.writeln(',');
      }
    } else if (_typeSystem.isAssignableTo(
        getterType, _typeProvider.iterableDynamicType)) {
      var iterableElement = _typeProvider.iterableElement2;
      var iterableType = getterType.asInstanceOf2(iterableElement);
      // Not sure why [iterableType] would be null... unresolved type?
      if (iterableType != null) {
        var innerType = iterableType.typeArguments.first;
        // Don't add Iterable functions for a generic type, for example
        // `List<E>.reversed` has inner type `E`, which we don't have a specific
        // renderer for.
        // TODO(srawlins): Find a solution for this. We can track all of the
        // concrete types substituted for `E` for example.
        if (innerType is! TypeParameterType) {
          var innerTypeElement = innerType.documentableElement2;
          var renderFunctionName = _typeToRenderFunctionName[innerTypeElement];
          String renderCall;
          if (renderFunctionName == null) {
            var typeName = innerTypeElement!.name3!;
            if (innerType is InterfaceType) {
              _invisibleGetters.putIfAbsent(
                  typeName, () => innerType.element3.allAccessorNames);
            }
            renderCall = 'renderSimple(e, ast, r.template, sink, parent: r, '
                "getters: _invisibleGetters['$typeName']!)";
          } else {
            var bang = _typeSystem.isPotentiallyNullable(innerType) ? '!' : '';
            renderCall =
                '$renderFunctionName(e$bang, ast, r.template, sink, parent: r)';
          }
          _buffer.writeln('''
renderIterable:
    ($_contextTypeVariable c, RendererBase<$_contextTypeVariable> r,
     List<MustachioNode> ast, StringSink sink) {
  return c.$getterName.map((e) => $renderCall);
},
''');
        }
      }
    } else {
      // Don't add Iterable functions for a generic type, for example
      // `List<E>.first` has type `E`, which we don't have a specific
      // renderer for.
      // TODO(srawlins): Find a solution for this. We can track all of the
      // concrete types substituted for `E` for example.
      if (getterName is! TypeParameterType) {
        var renderFunctionName = _typeToRenderFunctionName[getterType.element3];
        String renderCall;
        if (renderFunctionName == null) {
          var typeName = getterType.element3.name3!;
          _invisibleGetters.putIfAbsent(
              typeName, () => getterType.element3.allAccessorNames);
          renderCall =
              'renderSimple(c.$getterName, ast, r.template, sink, parent: r, '
              "getters: _invisibleGetters['$typeName']!)";
        } else {
          var bang = _typeSystem.isPotentiallyNullable(getterType) ? '!' : '';
          renderCall =
              '$renderFunctionName(c.$getterName$bang, ast, r.template, sink, parent: r)';
        }
        var nullValueGetter =
            getterType.nullabilitySuffix == NullabilitySuffix.none
                ? 'false'
                : 'c.$getterName == null';
        _buffer.writeln('''
isNullValue: ($_contextTypeVariable c) => $nullValueGetter,

renderValue:
    ($_contextTypeVariable c, RendererBase<$_contextTypeVariable> r,
     List<MustachioNode> ast, StringSink sink) {
  $renderCall;
},
''');
      }
    }
    _buffer.writeln('),');
  }

  /// Writes the mapping of invisible getters, used to report simple renderer
  /// errors.
  void _writeInvisibleGetters() {
    _buffer.write('const _invisibleGetters = {');
    for (var class_ in _invisibleGetters.keys.toList()..sort()) {
      _buffer.write("'$class_':");
      var getters = _invisibleGetters[class_]!.toList()..sort();
      _buffer.write('{${getters.map((e) => "'$e'").join(', ')}},');
    }
    _buffer.write('};');
  }
}

/// A container with the information needed to distinguish one
/// renderer-to-be-built from another.
///
/// This can be used when building a set of renderers to build (both the render
/// functions and the renderer class), and also to refer from one renderer to
/// another.
class _RendererInfo {
  final InterfaceElement2 _contextClass;

  /// The name of the top level render function.
  ///
  /// This function is public when specified in a @Renderer annotation, and
  /// private otherwise.
  final String _renderFunctionName;

  /// Whether the renderer should be a full renderer.
  ///
  /// If a render spec is not specified with @Renderer, then a class needs to be
  /// annotated with @visibleToRender in order to get a full renderer.
  /// Otherwise, the [SimpleRenderer] will be used.
  ///
  /// It may be initially determined that we only need an abbreviated, then
  /// later determined that we need a full renderer, so this field is not final.
  bool isFullRenderer;

  bool includeRenderFunction;

  /// The public API function name specified with @Renderer, or null.
  String? publicApiFunctionName;

  factory _RendererInfo(
    InterfaceElement2 contextClass, {
    bool public = false,
    bool isFullRenderer = true,
    bool includeRenderFunction = true,
    String? publicApiFunctionName,
  }) {
    var typeBaseName = contextClass.name3;
    var renderFunctionName = '_render_$typeBaseName';
    var rendererClassName =
        public ? 'Renderer_$typeBaseName' : '_Renderer_$typeBaseName';

    return _RendererInfo._(
      contextClass,
      renderFunctionName,
      rendererClassName,
      isFullRenderer: isFullRenderer,
      includeRenderFunction: includeRenderFunction,
      publicApiFunctionName: publicApiFunctionName,
    );
  }

  _RendererInfo._(
    this._contextClass,
    this._renderFunctionName,
    this._rendererClassName, {
    required this.isFullRenderer,
    required this.includeRenderFunction,
    this.publicApiFunctionName,
  });

  String get _typeName => _contextClass.name3!;

  final String _rendererClassName;

  String get _typeParametersString => _contextClass.typeParametersString;

  String get _typeVariablesString => _contextClass.typeVariablesString;

  String _typeParametersStringWith(String extra) =>
      _contextClass.typeParametersStringWith(extra);

  String _renderSingleType(DartType tp) {
    var displayString = tp.getDisplayString();
    var nullabilitySuffix =
        tp.nullabilitySuffix == NullabilitySuffix.question ? '?' : '';
    return '$displayString$nullabilitySuffix';
  }

  /// Returns the type arguments of the context type, and [extra], as they
  /// appear in a list of generics.
  String _typeArgumentsStringWith(String extra) {
    return asGenerics([
      ..._contextClass.thisType.typeArguments
          // withNullability will give star types, we actually want nullable or
          // non-nullable only for generation.
          .map(_renderSingleType),
      extra,
    ]);
  }
}

extension on InterfaceElement2 {
  /// A set of the names of all accessors on this [ClassElement2], including
  /// supertypes.
  Set<String> get allAccessorNames {
    return {
      ...?supertype?.element3.allAccessorNames,
      ...getters2.where((e) => e.isPublic && !e.isStatic).map((e) => e.name3!),
    };
  }
}

extension on GetterElement {
  // Whether this getter should be omitted from the runtime renderer code.
  bool get shouldBeOmitted {
    var variable = variable3;
    return isPrivate ||
        isStatic ||
        metadata2.hasInternal ||
        metadata2.hasProtected ||
        metadata2.hasVisibleForOverriding ||
        metadata2.hasVisibleForTesting ||
        variable == null ||
        variable.metadata2.hasInternal ||
        variable.metadata2.hasProtected ||
        variable.metadata2.hasVisibleForOverriding ||
        variable.metadata2.hasVisibleForTesting;
  }
}
