@@ -8,9 +8,8 @@ library dartdoc.markdown_processor;
88import 'dart:convert' ;
99import 'dart:math' ;
1010
11- import 'package:analyzer/dart/ast/ast.dart' ;
11+ import 'package:analyzer/dart/ast/ast.dart' hide TypeParameter ;
1212import 'package:analyzer/dart/element/element.dart' ;
13- import 'package:analyzer/src/dart/element/member.dart' show Member;
1413import 'package:dartdoc/src/model_utils.dart' ;
1514import 'package:html/parser.dart' show parse;
1615import 'package:markdown/markdown.dart' as md;
@@ -254,46 +253,42 @@ MatchingLinkResult _getMatchingLinkElement(
254253 return new MatchingLinkResult (null , null , warn: false );
255254 }
256255
257- Element refElement ;
256+ ModelElement refModelElement ;
258257
259258 // Try expensive not-scoped lookup.
260- if (refElement == null ) {
259+ if (refModelElement == null ) {
261260 Class preferredClass = _getPreferredClass (element);
262- refElement =
261+ refModelElement =
263262 _findRefElementInLibrary (codeRef, element, commentRefs, preferredClass);
264263 }
265264
266- // This is faster but does not take canonicalization into account; try
267- // only as a last resort. TODO(jcollins-g): make analyzer comment references
268- // dartdoc-canonicalization-aware?
269- if (refElement == null ) {
270- refElement = _getRefElementFromCommentRefs (commentRefs, codeRef);
265+ // This is faster but does not know about libraries without imports in the
266+ // current context; try only as a last resort.
267+ // TODO(jcollins-g): make analyzer comment references dartdoc-canonicalization-aware?
268+ if (refModelElement == null ) {
269+ Element refElement = _getRefElementFromCommentRefs (commentRefs, codeRef);
270+ if (refElement != null ) {
271+ refModelElement = new ModelElement .fromElement (
272+ _getRefElementFromCommentRefs (commentRefs, codeRef), element.package);
273+ refModelElement =
274+ refModelElement.canonicalModelElement ?? refModelElement;
275+ }
271276 } else {
272- assert (refElement is ! PropertyAccessorElement );
273- assert (refElement is ! PrefixElement );
277+ assert (refModelElement is ! Accessor );
274278 }
275279
276280 // Did not find it anywhere.
277- if (refElement == null ) {
281+ if (refModelElement == null ) {
278282 // TODO(jcollins-g): remove squelching of non-canonical warnings here
279283 // once we no longer process full markdown for
280284 // oneLineDocs (#1417)
281285 return new MatchingLinkResult (null , null , warn: element.isCanonical);
282286 }
283287
284288 // Ignore all parameters.
285- if (refElement is ParameterElement || refElement is TypeParameterElement )
289+ if (refModelElement is Parameter || refModelElement is TypeParameter )
286290 return new MatchingLinkResult (null , null , warn: false );
287291
288- Library refLibrary = element.package.findOrCreateLibraryFor (refElement);
289- Element searchElement = refElement;
290- if (searchElement is Member )
291- searchElement = Package .getBasestElement (refElement);
292-
293- final Class preferredClass = _getPreferredClass (element);
294- ModelElement refModelElement = element.package.findCanonicalModelElementFor (
295- searchElement,
296- preferredClass: preferredClass);
297292 // There have been places in the code which helpfully cache entities
298293 // regardless of what package they are associated with. This assert
299294 // will protect us from reintroducing that.
@@ -302,23 +297,8 @@ MatchingLinkResult _getMatchingLinkElement(
302297 return new MatchingLinkResult (refModelElement, null );
303298 }
304299 // From this point on, we haven't been able to find a canonical ModelElement.
305- // So in this case, just find any ModelElement we can.
306- Accessor getter;
307- Accessor setter;
308- if (searchElement is FieldElement ) {
309- // TODO(jcollins-g): consolidate field element construction with inheritance
310- // checking.
311- if (searchElement.getter != null ) {
312- getter = new ModelElement .from (searchElement.getter, refLibrary);
313- }
314- if (searchElement.setter != null ) {
315- setter = new ModelElement .from (searchElement.setter, refLibrary);
316- }
317- }
318- refModelElement = new ModelElement .from (searchElement, refLibrary,
319- getter: getter, setter: setter);
320300 if (! refModelElement.isCanonical) {
321- if (refLibrary .isPublicAndPackageDocumented) {
301+ if (refModelElement.library .isPublicAndPackageDocumented) {
322302 refModelElement
323303 .warn (PackageWarning .noCanonicalFound, referredFrom: [element]);
324304 }
@@ -393,7 +373,7 @@ Map<String, Set<ModelElement>> _findRefElementCache;
393373// TODO(jcollins-g): Subcomponents of this function shouldn't be adding nulls to results, strip the
394374// removes out that are gratuitous and debug the individual pieces.
395375// TODO(jcollins-g): A complex package winds up spending a lot of cycles in here. Optimize.
396- Element _findRefElementInLibrary (String codeRef, Warnable element,
376+ ModelElement _findRefElementInLibrary (String codeRef, Warnable element,
397377 List <CommentReference > commentRefs, Class preferredClass) {
398378 assert (element != null );
399379 assert (element.package.allLibrariesAdded);
@@ -507,10 +487,17 @@ Element _findRefElementInLibrary(String codeRef, Warnable element,
507487 if (results.isEmpty &&
508488 codeRefChomped.contains ('.' ) &&
509489 _findRefElementCache.containsKey (codeRefChomped)) {
510- for (final modelElement in _findRefElementCache[codeRefChomped]) {
490+ for (final ModelElement modelElement
491+ in _findRefElementCache[codeRefChomped]) {
511492 if (! _ConsiderIfConstructor (codeRef, modelElement)) continue ;
493+ // For fully qualified matches, the original preferredClass passed
494+ // might make no sense. Instead, use the enclosing class from the
495+ // element in [_findRefElementCache], because that element's enclosing
496+ // class will be preferred from [codeRefChomped]'s perspective.
512497 results.add (package.findCanonicalModelElementFor (modelElement.element,
513- preferredClass: preferredClass));
498+ preferredClass: modelElement.enclosingElement is Class
499+ ? modelElement.enclosingElement
500+ : null ));
514501 }
515502 }
516503 results.remove (null );
@@ -563,8 +550,6 @@ Element _findRefElementInLibrary(String codeRef, Warnable element,
563550 }
564551 results.remove (null );
565552
566- Element result;
567-
568553 if (results.length > 1 ) {
569554 // If this name could refer to a class or a constructor, prefer the class.
570555 if (results.any ((r) => r is Class )) {
@@ -626,11 +611,12 @@ Element _findRefElementInLibrary(String codeRef, Warnable element,
626611 }
627612 }
628613
614+ ModelElement result;
629615 // TODO(jcollins-g): further disambiguations based on package information?
630616 if (results.isEmpty) {
631617 result = null ;
632618 } else if (results.length == 1 ) {
633- result = results.first.element ;
619+ result = results.first;
634620 } else {
635621 // Squelch ambiguous doc reference warnings for parameters, because we
636622 // don't link those anyway.
@@ -639,7 +625,7 @@ Element _findRefElementInLibrary(String codeRef, Warnable element,
639625 message:
640626 "[$codeRef ] => ${results .map ((r ) => "'${r .fullyQualifiedName }'" ).join (", " )}" );
641627 }
642- result = results.first.element ;
628+ result = results.first;
643629 }
644630 return result;
645631}
0 commit comments