Tries to find a canonical ModelElement for this element. If we know this element is related to a particular class, pass preferredClass to disambiguate.
Source
ModelElement findCanonicalModelElementFor(Element e, {Class preferredClass}) { assert(allLibrariesAdded); Library lib = findCanonicalLibraryFor(e); if (lib == null && preferredClass != null) { lib = findCanonicalLibraryFor(preferredClass.element); } ModelElement modelElement; // TODO(jcollins-g): The data structures should be changed to eliminate guesswork // with member elements. if (e is ClassMemberElement || e is PropertyAccessorElement) { // Prefer Fields over Accessors. if (e is PropertyAccessorElement) e = (e as PropertyAccessorElement).variable; if (e is Member) e = getBasestElement(e); Set<ModelElement> candidates = new Set(); Tuple2<Element, Library> iKey = new Tuple2(e, lib); Tuple4<Element, Library, Class, ModelElement> key = new Tuple4(e, lib, null, null); Tuple4<Element, Library, Class, ModelElement> keyWithClass = new Tuple4(e, lib, preferredClass, null); if (_allConstructedModelElements.containsKey(key)) { candidates.add(_allConstructedModelElements[key]); } if (_allConstructedModelElements.containsKey(keyWithClass)) { candidates.add(_allConstructedModelElements[keyWithClass]); } if (candidates.isEmpty && _allInheritableElements.containsKey(iKey)) { candidates.addAll( _allInheritableElements[iKey].where((me) => me.isCanonical)); } Class canonicalClass = findCanonicalModelElementFor(e.enclosingElement); if (canonicalClass != null) { candidates.addAll(canonicalClass.allCanonicalModelElements.where((m) { if (m.element is FieldElement) { FieldElement fieldElement = m.element as FieldElement; Element getter; Element setter; if (fieldElement.getter?.isSynthetic == true) { getter = fieldElement.getter.variable; } else { getter = fieldElement.getter; } if (fieldElement.setter?.isSynthetic == true) { setter = fieldElement.setter.variable; } else { setter = fieldElement.setter; } if (setter == e || getter == e) return true; } if (m.element == e) return true; return false; })); } Set<ModelElement> matches = new Set() ..addAll(candidates.where((me) => me.isCanonical)); // This is for situations where multiple classes may actually be canonical // for an inherited element whose defining Class is not canonical. if (matches.length > 1 && preferredClass != null) { // Search for matches inside our superchain. List<Class> superChain = preferredClass.superChainRaw.map((et) => et.element).toList(); superChain.add(preferredClass); matches.removeWhere((me) => !superChain.contains((me as EnclosedElement).enclosingElement)); } assert(matches.length <= 1); if (!matches.isEmpty) modelElement = matches.first; } else { if (lib != null) modelElement = new ModelElement.from(e, lib); assert(modelElement is! Inheritable); if (modelElement != null && !modelElement.isCanonical) { modelElement = null; } } return modelElement; }