PackageGraph
class PackageGraphConstructors
PackageGraph.uninitialized()
PackageGraph.uninitialized(
DartdocOptionContext config,
DartSdk sdk,
bool hasEmbedderSdk,
PackageMetaProvider packageMetaProvider,
AnalysisContext _analysisContext,
)Implementation
PackageGraph.uninitialized(
this.config,
DartSdk sdk,
this.hasEmbedderSdk,
this.packageMetaProvider,
this._analysisContext,
) : packageMeta = config.topLevelPackageMeta,
sdkLibrarySources = {
for (var lib in sdk.sdkLibraries) sdk.mapDartUri(lib.shortName): lib
} {
// Make sure the default package exists, even if it has no libraries.
// This can happen for packages that only contain embedder SDKs.
Package.fromPackageMeta(packageMeta, this);
}Properties
allConstructedModelElements final
final Map<ConstructedModelElementsKey, ModelElement> allConstructedModelElementsAll ModelElements constructed for this package; a superset of the elements gathered in _gatherModelElements.
Implementation
final Map<ConstructedModelElementsKey, ModelElement>
allConstructedModelElements = {};allExtensionsAdded read / write
bool allExtensionsAddedgetter:
It is safe to cache values derived from the _extensions table if this is true.
setter:
It is safe to cache values derived from the _extensions table if this is true.
Implementation
bool allExtensionsAdded = false;allHrefs no setter
Map<String, Set<ModelElement>> get allHrefsA lookup index for hrefs to allow warnings to indicate where a broken link or orphaned file may have come from.
This is not cached because ModelElements can be created at any time.
Implementation
Map<String, Set<ModelElement>> get allHrefs {
final hrefMap = <String, Set<ModelElement>>{};
// TODO(jcollins-g ): handle calculating hrefs causing new elements better
// than toList().
for (final modelElement in allConstructedModelElements.values.toList()) {
// Technically speaking we should be able to use canonical model elements
// only here, but since the warnings that depend on this debug
// canonicalization problems, don't limit ourselves in case an href is
// generated for something non-canonical.
if (modelElement is Dynamic) continue;
// TODO: see [Accessor.enclosingCombo]
if (modelElement is Accessor) continue;
final href = modelElement.href;
if (href == null) continue;
hrefMap.putIfAbsent(href, () => {}).add(modelElement);
hrefMap
.putIfAbsent(href.replaceAll(htmlBasePlaceholder, ''), () => {})
.add(modelElement);
}
for (final library in _allLibraries.values) {
final href = library.href;
if (href == null) continue;
hrefMap.putIfAbsent(href, () => {}).add(library);
}
return hrefMap;
}allImplementersAdded read / write
bool allImplementersAddedgetter:
It is safe to cache values derived from the _implementers table if this is true.
setter:
It is safe to cache values derived from the _implementers table if this is true.
Implementation
bool allImplementersAdded = false;allInheritableElements final
final Map<InheritableElementsKey, Set<ModelElement>> allInheritableElementsAnything that might be inheritable, place here for later lookup.
Implementation
final Map<InheritableElementsKey, Set<ModelElement>> allInheritableElements =
{};allLibrariesAdded read / write
bool allLibrariesAddedImplementation
bool allLibrariesAdded = false;breadcrumbName no setter
String get breadcrumbNameThe name to use in breadcrumbs in the rendered documentation.
Implementation
@override
String get breadcrumbName => throw UnimplementedError();config final
final DartdocOptionContext configDartdoc's configuration flags.
Implementation
final DartdocOptionContext config;dartCoreObject late final
final late String dartCoreObjectThe String name representing the Object type.
Implementation
late final String dartCoreObject = libraries
.firstWhereOrNull((library) => library.name == 'dart:core')
?.classes
.firstWhereOrNull((c) => c.name == 'Object')
?.linkedName ??
'Object';defaultPackage late final
final late Package defaultPackageImplementation
late final Package defaultPackage =
Package.fromPackageMeta(packageMeta, this);defaultPackageName no setter
String get defaultPackageNameName of the default package.
Implementation
String get defaultPackageName => packageMeta.name;displayName no setter
String get displayNameThe name to use as text in the rendered documentation.
Implementation
@override
String get displayName => throw UnimplementedError();documentedName no setter inherited
String? get documentedNameInherited from Referable.
Implementation
String? get documentedName => null;elementTypeCache final
final Map<Record, ElementType> elementTypeCacheCache of ElementTypes instantiated during documentation generation.
Key is a record of (DartType, Library?, InstantiatedTypeAliasElement?).
Implementation
final elementTypeCache =
<(DartType, Library?, InstantiatedTypeAliasElement?), ElementType>{};extensions no setter
Iterable<Extension> get extensionsImplementation
Iterable<Extension> get extensions {
assert(allExtensionsAdded);
return _extensions;
}fullyQualifiedName no setter inherited
String get fullyQualifiedNameInherited from Referable.
Implementation
String get fullyQualifiedName => name;hasEmbedderSdk final
final bool hasEmbedderSdkImplementation
final bool hasEmbedderSdk;hasFooterVersion no setter
bool get hasFooterVersionImplementation
bool get hasFooterVersion => !config.excludeFooterVersion;hashCode no setter inherited
int get hashCodeThe hash code for this object.
A hash code is a single integer which represents the state of the object that affects operator == comparisons.
All objects have hash codes. The default hash code implemented by Object represents only the identity of the object, the same way as the default operator == implementation only considers objects equal if they are identical (see identityHashCode).
If operator == is overridden to use the object state instead, the hash code must also be changed to represent that state, otherwise the object cannot be used in hash based data structures like the default Set and Map implementations.
Hash codes must be the same for objects that are equal to each other according to operator ==. The hash code of an object should only change if the object changes in a way that affects equality. There are no further requirements for the hash codes. They need not be consistent between executions of the same program and there are no distribution guarantees.
Objects that are not equal are allowed to have the same hash code. It is even technically allowed that all instances have the same hash code, but if clashes happen too often, it may reduce the efficiency of hash-based data structures like HashSet or HashMap.
If a subclass overrides hashCode, it should override the operator == operator as well to maintain consistency.
Inherited from Object.
Implementation
external int get hashCode;href no setter inherited
String? get hrefInherited from Referable.
Implementation
String? get href => null;implementers no setter
Map<InheritingContainer, List<InheritingContainer>> get implementersImplementation
Map<InheritingContainer, List<InheritingContainer>> get implementers {
assert(allImplementersAdded);
return _implementers;
}libraries late final
final late List<Library> librariesThe set of all libraries (public and implementation) found across all packages.
Implementation
@visibleForTesting
/// The set of all libraries (public and implementation) found across all
/// [packages].
late final List<Library> libraries =
packages.expand((p) => p.libraries).toList(growable: false)..sort();library no setter inherited
Library? get libraryInherited from Referable.
Implementation
Library? get library => null;libraryCount no setter
int get libraryCountImplementation
int get libraryCount => libraries.length;libraryExports no setter
Map<LibraryElement, Set<Library>> get libraryExportsA mapping from a LibraryElement to all of the Librarys that export it, which is created if it is not yet populated.
Implementation
Map<LibraryElement, Set<Library>> get libraryExports {
// The map must be reset if we're still in the middle of adding libraries
// (though this shouldn't happen).
if (_allLibraries.keys.length != _previousSizeOfAllLibraries) {
assert(
_previousSizeOfAllLibraries == 0,
'Re-entered `libraryExports` while building all libraries',
);
_previousSizeOfAllLibraries = _allLibraries.keys.length;
_libraryExports = {};
for (var library in publicLibraries) {
_tagExportsFor(library, library.element);
}
}
return _libraryExports;
}localPackages no setter
List<Package> get localPackagesLocal packages are to be documented locally vs. remote or not at all.
Implementation
List<Package> get localPackages =>
publicPackages.where((p) => p.isLocal).toList(growable: false);localPublicLibraries late final
final late Set<Library> localPublicLibrariesImplementation
late final Set<Library> localPublicLibraries = () {
assert(allLibrariesAdded);
return _localLibraries.wherePublic.toSet();
}();name no setter
String get nameImplementation
@override
String get name => '';objectClass read / write
InheritingContainer objectClassgetter:
The Object class declared in the Dart SDK's 'dart:core' library.
setter:
The Object class declared in the Dart SDK's 'dart:core' library.
Implementation
late InheritingContainer objectClass;packageGraph no setter
PackageGraph get packageGraphImplementation
@override
PackageGraph get packageGraph => this;packageMap final
final Map<String, Package> packageMapMap of package name to Package.
This mapping must be complete before initializePackageGraph is called.
Implementation
final Map<String, Package> packageMap = {};packageMeta final
final PackageMeta packageMetaPackageMeta for the default package.
Implementation
final PackageMeta packageMeta;packageMetaProvider final
final PackageMetaProvider packageMetaProviderPackageMeta provider for building PackageMetas.
Implementation
final PackageMetaProvider packageMetaProvider;packages no setter
Iterable<Package> get packagesImplementation
Iterable<Package> get packages => packageMap.values;packageWarningCounter late final
final late PackageWarningCounter packageWarningCounterKeep track of warnings.
Implementation
late final PackageWarningCounter packageWarningCounter =
PackageWarningCounter(this);publicLibraries late final
final late Set<Library> publicLibrariesThe set of public libraries found across all packages.
Implementation
late final Set<Library> publicLibraries = () {
assert(allLibrariesAdded);
return libraries.wherePublic.toSet();
}();publicPackages late final
final late List<Package> publicPackagesImplementation
late final List<Package> publicPackages = () {
assert(allLibrariesAdded);
// Help the user if they pass us a package that doesn't exist.
var packageNames = packages.map((p) => p.name).toSet();
for (var packageName in config.packageOrder) {
if (!packageNames.contains(packageName)) {
warnOnElement(null, PackageWarning.packageOrderGivesMissingPackageName,
message: "$packageName, packages: ${packageNames.join(',')}");
}
}
return packages.where((p) => p.isPublic).toList(growable: false)..sort();
}();referenceChildren late final
final late Map<String, Referable> referenceChildrenMap of referenceName to the elements that are a member of this, but not this model element itself. Can be cached.
There is no need to duplicate references here that can be found via scope.
Implementation
@override
late final Map<String, Referable> referenceChildren = () {
// We have to use a stable order or otherwise references depending on
// ambiguous resolution (see below) will change where they resolve based on
// internal implementation details.
var sortedPackages = packages.toList(growable: false)..sort(byName);
var sortedDocumentedPackages = _documentedPackages.toList(growable: false)
..sort(byName);
return {
// TODO(jcollins-g): Warn about directly referencing top level items out
// of scope? Doing this will be even more ambiguous and potentially
// confusing than doing so with libraries.
...sortedDocumentedPackages
.expand((p) => p.publicLibrariesSorted)
.expand((l) => [
...l.constants.wherePublic,
...l.functions.wherePublic,
...l.properties.wherePublic,
...l.typedefs.wherePublic,
...l.extensions.wherePublic,
...l.extensionTypes.wherePublic,
...l.classes.wherePublic,
...l.enums.wherePublic,
...l.mixins.wherePublic,
])
.asMapByName,
// Libraries are next.
// TODO(jcollins-g): Warn about directly referencing libraries out of
// scope? Doing this is always going to be ambiguous and potentially
// confusing.
...sortedDocumentedPackages
.expand((p) => p.publicLibrariesSorted)
.asMapByName,
// Packages are the top priority.
...sortedPackages.asMapByName,
};
}();referenceGrandparentOverrides no setter inherited
Iterable<Referable>? get referenceGrandparentOverridesInherited from Referable.
Implementation
Iterable<Referable>? get referenceGrandparentOverrides => null;referenceName no setter inherited
String get referenceNameInherited from Referable.
Implementation
String get referenceName => name;referenceParents no setter
Iterable<Referable> get referenceParentsIterable of immediate "parents" to try resolving component parts. referenceBy stops at the first parent where a part is found. Can be cached.
Implementation
@override
Iterable<Referable> get referenceParents => const [];resourceProvider no setter
ResourceProvider get resourceProviderImplementation
ResourceProvider get resourceProvider => config.resourceProvider;runtimeType no setter inherited
Type get runtimeTypeA representation of the runtime type of the object.
Inherited from Object.
Implementation
external Type get runtimeType;scope no setter inherited
Scope? get scopeInherited from Referable.
Implementation
@visibleForOverriding
Scope? get scope => null;sdkLibrarySources final
final Map<Source?, SdkLibrary> sdkLibrarySourcesImplementation
final Map<Source?, SdkLibrary> sdkLibrarySources;workspacePackageNames final
final Set<String> workspacePackageNamesNames of packages that are workspace members, populated by the builder when workspaceDocs is enabled.
Used by Package.isLocal to determine if a package should be treated as local documentation.
Implementation
final Set<String> workspacePackageNames = {};Methods
addHtmlFragment()
void addHtmlFragment(String name, String content)Implementation
void addHtmlFragment(String name, String content) {
// TODO(srawlins): We have to add HTML fragments after documentation is
// built, in order to include fragments which come from macros which
// were generated by a tool. I think the macro/HTML-injection system needs
// to be overhauled to allow for this type of looping.
//assert(!_localDocumentationBuilt);
_htmlFragments[name] = content;
}addLibraryToGraph()
void addLibraryToGraph(DartDocResolvedLibrary resolvedLibrary)Adds resolvedLibrary to the package graph, adding it to _allLibraries, and to the Package which is created from the PackageMeta for the library.
Call during initialization to add a library to this PackageGraph.
Libraries added in this manner are assumed to be part of documented packages, even if 'includes' or 'embedder.yaml' files cause these to span packages.
Implementation
void addLibraryToGraph(DartDocResolvedLibrary resolvedLibrary) {
assert(!allLibrariesAdded);
var libraryElement2 = resolvedLibrary.element;
var packageMeta =
packageMetaProvider.fromElement(libraryElement2, config.sdkDir);
if (packageMeta == null) {
var libraryPath = libraryElement2.firstFragment.source.fullName;
var dartOrFlutter = config.flutterRoot == null ? 'dart' : 'flutter';
throw DartdocFailure(
"Unknown package for library: '$libraryPath'. Consider "
'`$dartOrFlutter pub get` and/or '
'`$dartOrFlutter pub global deactivate dartdoc` followed by '
'`$dartOrFlutter pub global activate dartdoc` to fix. Also, be sure '
'that `$dartOrFlutter analyze` completes without errors.');
}
var package = Package.fromPackageMeta(packageMeta, this);
var library = Library.fromLibraryResult(resolvedLibrary, this, package);
if (_shouldIncludeLibrary(resolvedLibrary.element)) {
package.libraries.add(library);
}
_allLibraries[libraryElement2.firstFragment.source.fullName] = library;
}addMacro()
void addMacro(String name, String content)Implementation
void addMacro(String name, String content) {
// TODO(srawlins): We have to add HTML fragments after documentation is
// built, in order to include fragments which come from macros which
// were generated by a tool. I think the macro/HTML-injection system needs
// to be overhauled to allow for this type of looping.
//assert(!_localDocumentationBuilt);
_macros[name] = content;
}dispose()
void dispose()Implementation
void dispose() {
// Clear out any cached tool snapshots and temporary directories.
// TODO(jcollins-g): Consider ownership change for these objects
// so they are tied to PackageGraph instead of being global.
SnapshotCache.instanceFor(config.resourceProvider).dispose();
ToolTempFileTracker.instanceFor(config.resourceProvider).dispose();
}findButDoNotCreateLibraryFor()
Library? findButDoNotCreateLibraryFor(Element e)This is used when we might need a Library object that isn't actually a documentation entry point (for elements that have no Library within the set of canonical Libraries).
Implementation
Library? findButDoNotCreateLibraryFor(Element e) {
// This is just a cache to avoid creating lots of libraries over and over.
return _allLibraries[e.library?.firstFragment.source.fullName];
}findCanonicalModelElementFor()
ModelElement? findCanonicalModelElementFor(
ModelElement? modelElement, {
Container? preferredClass,
})Tries to find a canonical ModelElement for modelElement.
If we know the element is related to a particular class, pass a preferredClass to disambiguate.
This can return null in a few ways: if modelElement is null, or if it has no canonical library, or if a possible canonical model element has a false value for isCanonical.
Implementation
ModelElement? findCanonicalModelElementFor(ModelElement? modelElement,
{Container? preferredClass}) {
assert(allLibrariesAdded);
if (modelElement == null) return null;
var e = modelElement.element;
if (preferredClass != null) {
var canonicalClass =
findCanonicalModelElementFor(preferredClass) as Container?;
if (canonicalClass != null) preferredClass = canonicalClass;
}
var library = modelElement.canonicalLibrary;
if (modelElement is Library) return library;
if (library == null && preferredClass != null) {
library = preferredClass.canonicalLibrary;
}
// For elements defined in extensions, they are canonical.
var enclosingElement = e.enclosingElement;
if (enclosingElement is ExtensionElement) {
library ??= getModelForElement(enclosingElement.library) as Library?;
// TODO(keertip): Find a better way to exclude members of extensions
// when libraries are specified using the "--include" flag.
if (library != null && library.isDocumented) {
return getModelFor(e, library, enclosingContainer: preferredClass);
}
}
// TODO(jcollins-g): The data structures should be changed to eliminate
// guesswork with member elements.
var declaration = e.baseElement;
ModelElement? canonicalModelElement;
if (e is ConstructorElement ||
e is MethodElement ||
e is FieldElement ||
e is PropertyAccessorElement) {
var declarationModelElement = getModelForElement(declaration);
e = declarationModelElement.element;
canonicalModelElement = _findCanonicalModelElementForAmbiguous(
declarationModelElement, library,
preferredClass: preferredClass as InheritingContainer?);
} else {
if (library != null) {
if (e case PropertyInducingElement(:var getter, :var setter)) {
var getterElement =
getter == null ? null : getModelFor(getter, library) as Accessor;
var setterElement =
setter == null ? null : getModelFor(setter, library) as Accessor;
canonicalModelElement = getModelForPropertyInducingElement(e, library,
getter: getterElement, setter: setterElement);
} else {
canonicalModelElement = getModelFor(e, library);
}
}
assert(canonicalModelElement is! Inheritable);
if (canonicalModelElement != null && !canonicalModelElement.isCanonical) {
canonicalModelElement = null;
}
}
// Prefer fields and top-level variables.
if (e is PropertyAccessorElement && canonicalModelElement is Accessor) {
canonicalModelElement = canonicalModelElement.enclosingCombo;
}
return canonicalModelElement;
}gatherModelNodes()
void gatherModelNodes(DartDocResolvedLibrary resolvedLibrary)Populate's _modelNodes with elements in resolvedLibrary.
This is done as Library model objects are created, while we are holding onto resolvedLibrary objects.
Implementation
// TODO(srawlins): I suspect we populate this mapping with way too many
// objects, too eagerly. They are only needed when writing the source code of
// an element to HTML, and maybe for resolving doc comments. We should find a
// way to get this data only when needed. But it's not immediately obvious to
// me how, because the data is on AST nodes, not the element model.
void gatherModelNodes(DartDocResolvedLibrary resolvedLibrary) {
for (var unit in resolvedLibrary.units) {
for (var directive in unit.directives.whereType<LibraryDirective>()) {
// There should be only one library directive. If there are more, there
// is no harm in grabbing ModelNode for each.
var commentData = directive.documentationComment?.data;
_modelNodes.putIfAbsent(
resolvedLibrary.element,
() => ModelNode(
directive,
resolvedLibrary.element,
_analysisContext,
commentData: commentData,
));
}
for (var declaration in unit.declarations) {
_populateModelNodeFor(declaration);
switch (declaration) {
case ClassDeclaration(body: BlockClassBody(:var members)):
for (var member in members) {
_populateModelNodeFor(member);
}
case EnumDeclaration():
if (declaration.declaredFragment?.element.isPublic ?? false) {
final body = declaration.body;
for (var constant in body.constants) {
_populateModelNodeFor(constant);
}
for (var member in body.members) {
_populateModelNodeFor(member);
}
}
case MixinDeclaration(body: BlockClassBody(:var members)):
for (var member in members) {
_populateModelNodeFor(member);
}
case ExtensionDeclaration():
if (declaration.declaredFragment?.element.isPublic ?? false) {
if (declaration.body case BlockClassBody body) {
for (var member in body.members) {
_populateModelNodeFor(member);
}
}
}
case ExtensionTypeDeclaration():
if (declaration.declaredFragment?.element.isPublic ?? false) {
if (declaration.body case BlockClassBody(:var members)) {
for (var member in members) {
_populateModelNodeFor(member);
}
}
}
}
}
}
}getHtmlFragment()
String? getHtmlFragment(String? name)Implementation
String? getHtmlFragment(String? name) {
assert(_localDocumentationBuilt);
if (name == null) {
return null;
}
return _htmlFragments[name];
}getMacro()
String? getMacro(String name)Returns a macro by name, or null if no macro is found.
Implementation
String? getMacro(String name) {
assert(_localDocumentationBuilt);
return _macros[name];
}getModelFor() inherited
ModelElement getModelFor(
Element element,
Library? library, {
Container? enclosingContainer,
})Returns the ModelElement for element, instantiating it if needed.
A convenience method for ModelElement.for_, see its documentation.
Inherited from Referable.
Implementation
ModelElement getModelFor(
Element element,
Library? library, {
Container? enclosingContainer,
}) =>
ModelElement.for_(
element,
library,
packageGraph,
enclosingContainer: enclosingContainer,
);getModelForElement() inherited
ModelElement getModelForElement(Element element)Returns the ModelElement for element, instantiating it if needed.
A convenience method for ModelElement.forElement, see its documentation.
Inherited from Referable.
Implementation
ModelElement getModelForElement(Element element) =>
ModelElement.forElement(element, packageGraph);getModelForPropertyInducingElement() inherited
ModelElement getModelForPropertyInducingElement(
PropertyInducingElement element,
Library library, {
required Accessor? getter,
required Accessor? setter,
Container? enclosingContainer,
})Returns the ModelElement for element, instantiating it if needed.
A convenience method for ModelElement.forPropertyInducingElement, see its documentation.
Inherited from Referable.
Implementation
// 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(
PropertyInducingElement element,
Library library, {
required Accessor? getter,
required Accessor? setter,
Container? enclosingContainer,
}) =>
ModelElement.forPropertyInducingElement(
element,
library,
packageGraph,
getter: getter,
setter: setter,
enclosingContainer: enclosingContainer,
);getModelNodeFor()
ModelNode? getModelNodeFor(Element element2)Implementation
ModelNode? getModelNodeFor(Element element2) => _modelNodes[element2];getTypeFor() inherited
ElementType getTypeFor(DartType type, Library? library)Returns the ElementType for type, instantiating it if needed.
Inherited from Referable.
Implementation
ElementType getTypeFor(DartType type, Library? library) =>
ElementType.for_(type, library, packageGraph);initializeCategories()
void initializeCategories()Initializes the category mappings in all packages.
Implementation
void initializeCategories() {
for (var package in packages) {
package.initializeCategories();
}
}initializePackageGraph()
Future<void> initializePackageGraph()Call after all libraries are added.
Implementation
Future<void> initializePackageGraph() async {
assert(!_localDocumentationBuilt);
allLibrariesAdded = true;
// Go through docs of every ModelElement in package to pre-build the macros
// index.
await _precacheLocalDocs().wait;
_localDocumentationBuilt = true;
// Scan all model elements to insure that interceptor and other special
// objects are found.
// Emit warnings for any local package that has no libraries.
// This must be done after the [allModelElements] traversal to be sure that
// all packages are picked up.
for (var package in _documentedPackages) {
for (var library in package.libraries) {
_addToImplementers(library.classesAndExceptions);
_addToImplementers(library.mixins);
_addToImplementers(library.extensionTypes);
if (library.isCanonical) {
_extensions.addAll(library.extensions.whereDocumented);
}
}
if (package.isLocal && !package.hasPublicLibraries) {
package.warn(PackageWarning.noDocumentableLibrariesInPackage);
}
}
allImplementersAdded = true;
allExtensionsAdded = true;
}noSuchMethod() inherited
dynamic noSuchMethod(Invocation invocation)Invoked when a nonexistent method or property is accessed.
A dynamic member invocation can attempt to call a member which doesn't exist on the receiving object. Example:
dynamic object = 1;
object.add(42); // Statically allowed, run-time errorThis invalid code will invoke the noSuchMethod method of the integer 1 with an Invocation representing the .add(42) call and arguments (which then throws).
Classes can override noSuchMethod to provide custom behavior for such invalid dynamic invocations.
A class with a non-default noSuchMethod invocation can also omit implementations for members of its interface. Example:
class MockList<T> implements List<T> {
noSuchMethod(Invocation invocation) {
log(invocation);
super.noSuchMethod(invocation); // Will throw.
}
}
void main() {
MockList().add(42);
}This code has no compile-time warnings or errors even though the MockList class has no concrete implementation of any of the List interface methods. Calls to List methods are forwarded to noSuchMethod, so this code will log an invocation similar to Invocation.method(#add, [42]) and then throw.
If a value is returned from noSuchMethod, it becomes the result of the original invocation. If the value is not of a type that can be returned by the original invocation, a type error occurs at the invocation.
The default behavior is to throw a NoSuchMethodError.
Inherited from Object.
Implementation
@pragma("vm:entry-point")
@pragma("wasm:entry-point")
external dynamic noSuchMethod(Invocation invocation);referenceBy() inherited
Referable? referenceBy(
List<String> reference, {
required bool Function(Referable?) filter,
bool tryParents = true,
Iterable<Referable>? parentOverrides,
})Looks up a comment reference by its component parts.
If tryParents is true, try looking up the same reference in any parents of this. Will skip over results that do not pass a given filter and keep searching.
Inherited from Referable.
Implementation
@nonVirtual
Referable? referenceBy(
List<String> reference, {
required bool Function(Referable?) filter,
bool tryParents = true,
Iterable<Referable>? parentOverrides,
}) {
parentOverrides ??= referenceParents;
if (reference.isEmpty) {
return tryParents ? null : this;
}
for (var referenceLookup in _childLookups(reference)) {
// First attempt: Ask analyzer's `Scope.lookup` API.
var result = _lookupViaScope(referenceLookup, filter: filter);
if (result != null) {
if (result is Prefix &&
result.name == '_' &&
library!.element.featureSet.isEnabled(Feature.wildcard_variables)) {
// A wildcard import prefix is non-binding.
continue;
}
return result;
}
// Second attempt: Look through `referenceChildren`.
final referenceChildren = this.referenceChildren;
final childrenResult = referenceChildren[referenceLookup.lookup];
if (childrenResult != null) {
var result = _recurseChildrenAndFilter(
referenceLookup,
childrenResult,
filter: filter,
);
if (result != null) {
return result;
}
}
}
// If we can't find it in children, try searching parents if allowed.
if (tryParents) {
for (var parent in parentOverrides) {
var result = parent.referenceBy(
reference,
tryParents: true,
parentOverrides: referenceGrandparentOverrides,
filter: filter,
);
if (result != null) return result;
}
}
return null;
}toString() override
String toString()A string representation of this object.
Some classes have a default textual representation, often paired with a static parse function (like int.parse). These classes will provide the textual representation as their string representation.
Other classes have no meaningful textual representation that a program will care about. Such classes will typically override toString to provide useful information when inspecting the object, mainly for debugging or logging.
Implementation
@override
String toString() {
const divider = '=========================================================';
final buffer = StringBuffer('PackageGraph built from ');
buffer.writeln(defaultPackageName);
buffer.writeln(divider);
buffer.writeln();
for (final name in packageMap.keys) {
final package = packageMap[name]!;
buffer.write('Package $name documented at ${package.documentedWhere} '
'with libraries: ');
buffer.writeAll(package.allLibraries);
buffer.writeln();
}
buffer.writeln(divider);
return buffer.toString();
}warnOnElement()
void warnOnElement(
Warnable? warnable,
PackageWarning kind, {
String? message,
Iterable<Warnable> referredFrom = const [],
Iterable<String> extendedDebug = const [],
})Implementation
void warnOnElement(Warnable? warnable, PackageWarning kind,
{String? message,
Iterable<Warnable> referredFrom = const [],
Iterable<String> extendedDebug = const []}) {
var newEntry = (warnable?.element, kind, message);
if (_warnAlreadySeen.contains(newEntry)) {
return;
}
// Warnings can cause other warnings. Queue them up via the stack but don't
// allow warnings we're already working on to get in there.
_warnAlreadySeen.add(newEntry);
_warnOnElement(warnable, kind,
message: message ?? '',
referredFrom: referredFrom,
extendedDebug: extendedDebug);
_warnAlreadySeen.remove(newEntry);
}Operators
operator ==() inherited
bool operator ==(Object other)The equality operator.
The default behavior for all Objects is to return true if and only if this object and other are the same object.
Override this method to specify a different equality relation on a class. The overriding method must still be an equivalence relation. That is, it must be:
Total: It must return a boolean for all arguments. It should never throw.
Reflexive: For all objects
o,o == omust be true.Symmetric: For all objects
o1ando2,o1 == o2ando2 == o1must either both be true, or both be false.Transitive: For all objects
o1,o2, ando3, ifo1 == o2ando2 == o3are true, theno1 == o3must be true.
The method should also be consistent over time, so whether two objects are equal should only change if at least one of the objects was modified.
If a subclass overrides the equality operator, it should override the hashCode method as well to maintain consistency.
Inherited from Object.
Implementation
external bool operator ==(Object other);