findCanonicalModelElementFor method
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;
}