blob: b3fa84fe07ce9f8c28b7de9823a8211849821930 [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/element/element2.dart';
import 'package:analyzer/dart/element/type.dart' show DartType;
import 'package:collection/collection.dart';
import 'package:dartdoc/src/element_type.dart';
import 'package:dartdoc/src/model/accessor.dart';
import 'package:dartdoc/src/model/constructor.dart';
import 'package:dartdoc/src/model/container.dart';
import 'package:dartdoc/src/model/library.dart';
import 'package:dartdoc/src/model/model_element.dart';
import 'package:dartdoc/src/model/package_graph.dart';
/// Something that has a name.
mixin Nameable {
String get name;
/// A "fully" qualified name, used for things like for warnings printed in the
/// terminal; not for display use in rendered HTML.
///
/// "Fully" means the name is qualified through the library. For example, a
/// method named 'baz' in a class named 'Bar' in a library named 'foo' has a
/// fully qualified name of 'foo.Bar.baz'.
///
/// As dartdoc can document multiple packages at once, note that such
/// qualifying names may not be unique across all documented packages.
String get fullyQualifiedName => name;
/// The name to use as text in the rendered documentation.
String get displayName => name;
/// The name to use in breadcrumbs in the rendered documentation.
String get breadcrumbName => name;
/// Whether this is "package-public."
///
/// A "package-public" element satisfies the following requirements:
/// * is not documented with the `@nodoc` directive,
/// * for a library, adheres to the documentation for [Library.isPublic],
/// * for a library member, is in a _public_ library's exported namespace, and
/// is not privately named, nor an unnamed extension,
/// * for a container (class, enum, extension, extension type, mixin) member,
/// is in a _public_ container, and is not privately named.
bool get isPublic => name.isNotEmpty && !name.startsWith('_');
@override
String toString() => name;
PackageGraph get packageGraph;
/// Returns the [ModelElement] for [element], instantiating it if needed.
///
/// A convenience method for [ModelElement.for_], see its documentation.
ModelElement getModelFor(
Element2 element,
Library library, {
Container? enclosingContainer,
}) =>
ModelElement.for_(
element,
library,
packageGraph,
enclosingContainer: enclosingContainer,
);
/// Returns the [ModelElement] for [element], instantiating it if needed.
///
/// A convenience method for [ModelElement.forElement], see its
/// documentation.
ModelElement getModelForElement(Element2 element) =>
ModelElement.forElement(element, packageGraph);
/// Returns the [ModelElement] for [element], instantiating it if needed.
///
/// A convenience method for [ModelElement.forPropertyInducingElement], see
/// its documentation.
// TODO(srawlins): Most callers seem to determine `getter` and `setter`
// immediately before calling this method, and I imagine could instead just
// call `getModelFor`.
ModelElement getModelForPropertyInducingElement(
PropertyInducingElement2 element,
Library library, {
required Accessor? getter,
required Accessor? setter,
Container? enclosingContainer,
}) =>
ModelElement.forPropertyInducingElement(
element,
library,
packageGraph,
getter: getter,
setter: setter,
enclosingContainer: enclosingContainer,
);
/// Returns the [ElementType] for [type], instantiating it if needed.
ElementType getTypeFor(DartType type, Library library) =>
ElementType.for_(type, library, packageGraph);
}
/// Compares [a] with [b] by name.
int byName(Nameable a, Nameable b) {
if (a is Library && b is Library) {
return compareAsciiLowerCaseNatural(a.displayName, b.displayName);
}
if (a is Constructor && b is Constructor) {
var aName = a.name.replaceFirst('.new', '');
var bName = b.name.replaceFirst('.new', '');
return compareAsciiLowerCaseNatural(aName, bName);
}
var stringCompare = compareAsciiLowerCaseNatural(a.name, b.name);
if (stringCompare != 0) {
return stringCompare;
}
return a.hashCode.compareTo(b.hashCode);
}