blob: 13c234f88dc587b321e1ce5de8f792b9ea1c3ae5 [file] [log] [blame]
// Copyright (c) 2019, 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.
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/model_utils.dart' as model_utils;
import 'package:dartdoc/src/render/enum_field_renderer.dart';
/// The [Enum] class only inherits from [InheritingContainer] because declared
/// `enum`s inherit methods from [Object]. It can't actually participate
/// meaningfully in other inheritance or have class modifiers.
class Enum extends InheritingContainer
with Constructable, TypeImplementing, MixedInTypes {
final EnumElement element;
Enum(this.element, super.library, super.packageGraph);
late final List<ModelElement> allModelElements = [
late final List<InheritingContainer> inheritanceChain = [
for (var container in mixedInTypes.reversed.modelElements)
for (var container in superChain.modelElements)
String get sidebarPath =>
Kind get kind => Kind.enum_;
String get relationshipsClass => 'eNum-relationships';
Iterable<Field> get constantFields =>
declaredFields.where((f) => f is! EnumField && f.isConst);
late final Iterable<Field> publicEnumValues =
bool get hasPublicEnumValues => publicEnumValues.isNotEmpty;
bool get isAbstract => false;
bool get isBase => false;
bool get isInterface => false;
bool get isMixinClass => false;
bool get isSealed => false;
/// A field specific to an enum's values.
/// Enum's value fields are virtual, so we do a little work to create usable
/// entries for the docs.
class EnumField extends Field {
final int index;
EnumField.forConstant(this.index, FieldElement element, Library library,
PackageGraph packageGraph, Accessor? getter)
: super(
element, library, packageGraph, getter as ContainerAccessor?, null);
bool get isEnumValue => true;
bool get hasConstantValueForDisplay {
final enum_ = element.enclosingElement as EnumElement;
final enumHasDefaultConstructor =
enum_.constructors.any((c) => c.isDefaultConstructor);
// If this enum does not have any explicit constructors (and so only has a
// default constructor), then there is no meaningful constant initializer to
// display.
return !enumHasDefaultConstructor;
String get constantValueBase =>
? super.constantValueBase
: _fieldRenderer.renderValue(this);
List<DocumentationComment> get documentationFrom {
if (name == 'values' || name == 'index') return [this];
return super.documentationFrom;
String? get href {
if (!identical(canonicalModelElement, this)) {
return canonicalModelElement?.href;
assert(canonicalLibrary == library);
assert(canonicalEnclosingContainer == enclosingElement);
// TODO(jcollins-g): EnumField should not depend on enclosingElement, but
// we sort of have to while we are half-converted to [FileStructure].
return '${package.baseHref}${enclosingElement.library.dirName}/${enclosingElement.fileStructure.fileName}';
String get linkedName => _fieldRenderer.renderLinkedName(this);
bool get isCanonical {
if (name == 'index') return false;
// If this is something inherited from Object, e.g. hashCode, let the
// normal rules apply.
// TODO(jcollins-g): We don't actually document this as a separate entity;
// do that or change this to false and deal with the
// consequences.
return true;
String get oneLineDoc => documentationAsHtml;
Inheritable? get overriddenElement => null;
EnumFieldRenderer get _fieldRenderer =>