| // 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/element/element.dart'; |
| import 'package:analyzer/dart/element/element2.dart'; |
| import 'package:analyzer/source/line_info.dart'; |
| // ignore: implementation_imports |
| import 'package:analyzer/src/dart/element/element.dart'; |
| // ignore: implementation_imports |
| import 'package:analyzer/src/utilities/extensions/element.dart'; |
| import 'package:dartdoc/src/element_type.dart'; |
| import 'package:dartdoc/src/model/comment_referable.dart'; |
| import 'package:dartdoc/src/model/kind.dart'; |
| import 'package:dartdoc/src/model/model.dart'; |
| import 'package:dartdoc/src/model_utils.dart'; |
| |
| class Constructor extends ModelElement with ContainerMember, TypeParameters { |
| @override |
| // ignore: analyzer_use_new_elements |
| ConstructorElement get element => element2.asElement; |
| |
| @override |
| final ConstructorElement2 element2; |
| |
| Constructor(this.element2, super.library, super.packageGraph); |
| |
| @override |
| CharacterLocation? get characterLocation { |
| if (element2.isSynthetic) { |
| // Make warnings for a synthetic constructor refer to somewhere reasonable |
| // since a synthetic constructor has no definition independent of the |
| // parent class. |
| return enclosingElement.characterLocation; |
| } |
| final lineInfo = unitElement.lineInfo; |
| var offset = element2.firstFragment.nameOffset2 ?? |
| (element2.firstFragment as ConstructorElementImpl).typeNameOffset; |
| if (offset != null && offset >= 0) { |
| return lineInfo.getLocation(offset); |
| } |
| return null; |
| } |
| |
| @override |
| bool get isPublic { |
| if (!super.isPublic) return false; |
| if (element2.hasPrivateName) return false; |
| var class_ = element2.enclosingElement2; |
| // Enums cannot be explicitly constructed or extended. |
| if (class_ is EnumElement2) return false; |
| if (class_ is ClassElement2) { |
| if (element2.isFactory) return true; |
| if (class_.isSealed || |
| (class_.isAbstract && class_.isFinal) || |
| (class_.isAbstract && class_.isInterface)) { |
| /// Sealed classes, abstract final classes, and abstract interface |
| /// classes, cannot be instantiated nor extended, from outside the |
| /// declaring library. Avoid documenting them. |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| @override |
| List<TypeParameter> get typeParameters => |
| (enclosingElement as Constructable).typeParameters; |
| |
| @override |
| Container get enclosingElement => |
| getModelFor2(element2.enclosingElement2, library) as Container; |
| |
| @override |
| String get fileName => |
| // TODO(srawlins): It would be great to use `new.html` as the file name. |
| isUnnamedConstructor ? '${enclosingElement.name}.html' : '$name.html'; |
| |
| @override |
| String get aboveSidebarPath => enclosingElement.sidebarPath; |
| |
| @override |
| String? get belowSidebarPath => null; |
| |
| String get fullKind { |
| if (isConst) return 'const $kind'; |
| if (isFactory) return 'factory $kind'; |
| return kind.toString(); |
| } |
| |
| @override |
| String get fullyQualifiedName => '${library.name}.$name'; |
| |
| @override |
| bool get isConst => element2.isConst; |
| |
| bool get isUnnamedConstructor => element2.name3 == 'new'; |
| |
| bool get isFactory => element2.isFactory; |
| |
| @override |
| Kind get kind => Kind.constructor; |
| |
| late final Callable modelType = |
| getTypeFor(element2.type, library) as Callable; |
| |
| @override |
| String get name => |
| // TODO(jcollins-g): After the old lookup code is retired, rationalize |
| // [name] around the conventions used in referenceChildren and replace |
| // code there and elsewhere with simple references to the name. |
| '${enclosingElement.name}.${element2.name3}'; |
| |
| @override |
| String get nameWithGenerics { |
| var constructorName = element2.name3!; |
| if (constructorName == 'new') { |
| return '${enclosingElement.name}$genericParameters'; |
| } |
| return '${enclosingElement.name}$genericParameters.$constructorName'; |
| } |
| |
| String? get shortName { |
| if (name.contains('.')) { |
| return name.substring(element2.enclosingElement2.name3!.length + 1); |
| } else { |
| return name; |
| } |
| } |
| |
| @override |
| late final Map<String, CommentReferable> referenceChildren = () { |
| // Find the element that [parameter] is _really_ referring to. |
| Element2? dereferenceParameter(FormalParameterElement? parameter) => |
| switch (parameter) { |
| FieldFormalParameterElement2() => parameter.field2, |
| SuperFormalParameterElement2() => |
| dereferenceParameter(parameter.superConstructorParameter2), |
| _ => parameter |
| }; |
| |
| var parameterElements = parameters.map((parameter) { |
| var element = dereferenceParameter(parameter.element2); |
| return element == null ? parameter : getModelForElement2(element); |
| }); |
| return { |
| for (var element in parameterElements) element.referenceName: element, |
| for (var tp in typeParameters) tp.referenceName: tp, |
| }; |
| }(); |
| |
| @override |
| String get referenceName => |
| isUnnamedConstructor ? enclosingElement.name : element2.name3!; |
| } |