blob: 3ef6de260ecbaa51ffee04d6c8707e6f521ad3bd [file] [log] [blame]
// Copyright (c) 2021, 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:dartdoc/src/element_type.dart';
import 'package:dartdoc/src/model/feature.dart';
import 'package:dartdoc/src/model/getter_setter_combo.dart';
import 'package:dartdoc/src/model/library.dart';
import 'package:dartdoc/src/model/model_object_builder.dart';
import 'package:dartdoc/src/model/package_graph.dart';
/// Represents a Dart annotation, attached to an element in the source code with
/// `@`.
class Annotation extends Feature with ModelBuilder {
final ElementAnnotation annotation;
final Library library;
@override
final PackageGraph packageGraph;
Annotation(this.annotation, this.library, this.packageGraph)
: super(annotation.element.name);
String _linkedNameWithParameters;
@override
String get linkedNameWithParameters => _linkedNameWithParameters ??=
packageGraph.rendererFactory.featureRenderer.renderAnnotation(this);
/// Return the linked name of the annotation.
@override
String get linkedName => annotation.element is PropertyAccessorElement
? modelBuilder.fromElement(annotation.element).linkedName
// TODO(jcollins-g): consider linking to constructor instead of type?
: modelType.linkedName;
ElementType _modelType;
ElementType get modelType {
if (_modelType == null) {
var annotatedWith = annotation.element;
if (annotatedWith is ConstructorElement) {
_modelType = modelBuilder.typeFrom(annotatedWith.returnType, library);
} else if (annotatedWith is PropertyAccessorElement) {
_modelType = (modelBuilder.fromElement(annotatedWith.variable)
as GetterSetterCombo)
.modelType;
} else {
assert(false,
'non-callable element used as annotation?: ${annotation.element}');
}
}
return _modelType;
}
String _parameterText;
String get parameterText {
// TODO(srawlins): Attempt to revive constructor arguments in an annotation,
// akin to source_gen's Reviver, in order to link to inner components. For
// example, in `@Foo(const Bar(), baz: <Baz>[Baz.one, Baz.two])`, link to
// `Foo`, `Bar`, `Baz`, `Baz.one`, and `Baz.two`.
if (_parameterText == null) {
var source = annotation.toSource();
var startIndex = source.indexOf('(');
_parameterText =
source.substring(startIndex == -1 ? source.length : startIndex);
}
return _parameterText;
}
@override
bool get isPublic =>
modelType.isPublic &&
modelType is DefinedElementType &&
!packageGraph.invisibleAnnotations
.contains((modelType as DefinedElementType).modelElement);
@override
bool operator ==(Object other) {
if (other is Annotation) {
return other.annotation == annotation;
}
return false;
}
@override
int get hashCode => annotation.hashCode;
}