@@ -333,6 +333,9 @@ ModelElement _findRefElementInLibrary(String codeRef, Warnable element,
333333 newCodeRef, element, commentRefs, preferredClass);
334334 }
335335
336+ // Remove any "null" objects after each step of trying to add to results.
337+ // TODO(jcollins-g): Eliminate all situations where nulls can be added
338+ // to the results set.
336339 results.remove (null );
337340 // Oh, and someone might have some type parameters or other garbage.
338341 if (results.isEmpty && codeRef.contains (trailingIgnoreStuff)) {
@@ -366,118 +369,30 @@ ModelElement _findRefElementInLibrary(String codeRef, Warnable element,
366369 p.name == codeRefChomped || codeRefChomped.startsWith ("${p .name }." )));
367370 }
368371 }
369-
370372 results.remove (null );
371- if (results.isEmpty) {
372- // Maybe this is local to a class.
373- // TODO(jcollins-g): tryClasses is a strict subset of the superclass chain. Optimize.
374- List <Class > tryClasses = [preferredClass];
375- Class realClass = tryClasses.first;
376- if (element is Inheritable ) {
377- Inheritable overriddenElement = element.overriddenElement;
378- while (overriddenElement != null ) {
379- tryClasses.add (
380- (element.overriddenElement as EnclosedElement ).enclosingElement);
381- overriddenElement = overriddenElement.overriddenElement;
382- }
383- }
384-
385- for (Class tryClass in tryClasses) {
386- if (tryClass != null ) {
387- _getResultsForClass (
388- tryClass, codeRefChomped, results, codeRef, packageGraph);
389- }
390- results.remove (null );
391- if (results.isNotEmpty) break ;
392- }
393373
394- if (results.isEmpty && realClass != null ) {
395- for (Class superClass
396- in realClass.publicSuperChain.map ((et) => et.element as Class )) {
397- if (! tryClasses.contains (superClass)) {
398- _getResultsForClass (
399- superClass, codeRefChomped, results, codeRef, packageGraph);
400- }
401- results.remove (null );
402- if (results.isNotEmpty) break ;
403- }
404- }
405- }
374+ // This could be local to the class, look there first.
375+ _findWithinTryClasses (results, preferredClass, element, codeRefChomped, codeRef, packageGraph);
406376 results.remove (null );
407377
408378 // We now need the ref element cache to keep from repeatedly searching [Package.allModelElements].
409379 // But if not, look for a fully qualified match. (That only makes sense
410380 // if the codeRef might be qualified, and contains periods.)
411- if (results.isEmpty &&
412- codeRefChomped.contains ('.' ) &&
413- packageGraph.findRefElementCache.containsKey (codeRefChomped)) {
414- for (final ModelElement modelElement
415- in packageGraph.findRefElementCache[codeRefChomped]) {
416- if (! _ConsiderIfConstructor (codeRef, modelElement)) continue ;
417- // For fully qualified matches, the original preferredClass passed
418- // might make no sense. Instead, use the enclosing class from the
419- // element in [_findRefElementCache], because that element's enclosing
420- // class will be preferred from [codeRefChomped]'s perspective.
421- results.add (packageGraph.findCanonicalModelElementFor (
422- modelElement.element,
423- preferredClass: modelElement.enclosingElement is Class
424- ? modelElement.enclosingElement
425- : null ));
426- }
427- }
381+ _findWithinRefElementCache (results, codeRefChomped, packageGraph, codeRef);
428382 results.remove (null );
429383
430384 // Only look for partially qualified matches if we didn't find a fully qualified one.
431- if (results.isEmpty) {
432- for (final modelElement in library.allModelElements) {
433- if (! _ConsiderIfConstructor (codeRef, modelElement)) continue ;
434- if (codeRefChomped == modelElement.fullyQualifiedNameWithoutLibrary) {
435- results.add (packageGraph.findCanonicalModelElementFor (
436- modelElement.element,
437- preferredClass: preferredClass));
438- }
439- }
440- }
385+ _findPartiallyQualifiedMatches (results, library, codeRef, codeRefChomped, packageGraph, preferredClass);
441386 results.remove (null );
442387
443388 // And if we still haven't found anything, just search the whole ball-of-wax.
444- if (results.isEmpty &&
445- packageGraph.findRefElementCache.containsKey (codeRefChomped)) {
446- for (final modelElement
447- in packageGraph.findRefElementCache[codeRefChomped]) {
448- if (codeRefChomped == modelElement.fullyQualifiedNameWithoutLibrary ||
449- (modelElement is Library &&
450- codeRefChomped == modelElement.fullyQualifiedName)) {
451- results.add (
452- packageGraph.findCanonicalModelElementFor (modelElement.element));
453- }
454- }
455- }
389+ _findGlobalWithinRefElementCache (results, packageGraph, codeRefChomped);
456390 results.remove (null );
457391
458392 // This could conceivably be a reference to an enum member. They don't show up in allModelElements.
459393 // TODO(jcollins-g): Put enum members in allModelElements with useful hrefs without blowing up other assumptions about what that means.
460394 // TODO(jcollins-g): This doesn't provide good warnings if an enum and class have the same name in different libraries in the same package. Fix that.
461- if (results.isEmpty) {
462- List <String > codeRefChompedParts = codeRefChomped.split ('.' );
463- if (codeRefChompedParts.length >= 2 ) {
464- String maybeEnumName = codeRefChompedParts
465- .sublist (0 , codeRefChompedParts.length - 1 )
466- .join ('.' );
467- String maybeEnumMember = codeRefChompedParts.last;
468- if (packageGraph.findRefElementCache.containsKey (maybeEnumName)) {
469- for (final modelElement
470- in packageGraph.findRefElementCache[maybeEnumName]) {
471- if (modelElement is Enum ) {
472- if (modelElement.constants.any ((e) => e.name == maybeEnumMember)) {
473- results.add (modelElement);
474- break ;
475- }
476- }
477- }
478- }
479- }
480- }
395+ _findEnumReferences (results, codeRefChomped, packageGraph);
481396 results.remove (null );
482397
483398 if (results.length > 1 ) {
@@ -560,6 +475,117 @@ ModelElement _findRefElementInLibrary(String codeRef, Warnable element,
560475 return result;
561476}
562477
478+ void _findEnumReferences (Set <ModelElement > results, String codeRefChomped, PackageGraph packageGraph) {
479+ if (results.isEmpty) {
480+ List <String > codeRefChompedParts = codeRefChomped.split ('.' );
481+ if (codeRefChompedParts.length >= 2 ) {
482+ String maybeEnumName = codeRefChompedParts
483+ .sublist (0 , codeRefChompedParts.length - 1 )
484+ .join ('.' );
485+ String maybeEnumMember = codeRefChompedParts.last;
486+ if (packageGraph.findRefElementCache.containsKey (maybeEnumName)) {
487+ for (final modelElement
488+ in packageGraph.findRefElementCache[maybeEnumName]) {
489+ if (modelElement is Enum ) {
490+ if (modelElement.constants.any ((e) => e.name == maybeEnumMember)) {
491+ results.add (modelElement);
492+ break ;
493+ }
494+ }
495+ }
496+ }
497+ }
498+ }
499+ }
500+
501+ void _findGlobalWithinRefElementCache (Set <ModelElement > results, PackageGraph packageGraph, String codeRefChomped) {
502+ if (results.isEmpty &&
503+ packageGraph.findRefElementCache.containsKey (codeRefChomped)) {
504+ for (final modelElement
505+ in packageGraph.findRefElementCache[codeRefChomped]) {
506+ if (codeRefChomped == modelElement.fullyQualifiedNameWithoutLibrary ||
507+ (modelElement is Library &&
508+ codeRefChomped == modelElement.fullyQualifiedName)) {
509+ results.add (
510+ packageGraph.findCanonicalModelElementFor (modelElement.element));
511+ }
512+ }
513+ }
514+ }
515+
516+ void _findPartiallyQualifiedMatches (Set <ModelElement > results, Library library, String codeRef, String codeRefChomped, PackageGraph packageGraph, Class preferredClass) {
517+ // Only look for partially qualified matches if we didn't find a fully qualified one.
518+ if (results.isEmpty && library.modelElementsNameMap.containsKey (codeRefChomped)) {
519+ for (final modelElement in library.modelElementsNameMap[codeRefChomped]) {
520+ if (! _ConsiderIfConstructor (codeRef, modelElement)) continue ;
521+ results.add (packageGraph.findCanonicalModelElementFor (
522+ modelElement.element,
523+ preferredClass: preferredClass));
524+ }
525+ }
526+ }
527+
528+ void _findWithinRefElementCache (Set <ModelElement > results, String codeRefChomped, PackageGraph packageGraph, String codeRef) {
529+ // We now need the ref element cache to keep from repeatedly searching [Package.allModelElements].
530+ // But if not, look for a fully qualified match. (That only makes sense
531+ // if the codeRef might be qualified, and contains periods.)
532+ if (results.isEmpty &&
533+ codeRefChomped.contains ('.' ) &&
534+ packageGraph.findRefElementCache.containsKey (codeRefChomped)) {
535+ for (final ModelElement modelElement
536+ in packageGraph.findRefElementCache[codeRefChomped]) {
537+ if (! _ConsiderIfConstructor (codeRef, modelElement)) continue ;
538+ // For fully qualified matches, the original preferredClass passed
539+ // might make no sense. Instead, use the enclosing class from the
540+ // element in [_findRefElementCache], because that element's enclosing
541+ // class will be preferred from [codeRefChomped]'s perspective.
542+ results.add (packageGraph.findCanonicalModelElementFor (
543+ modelElement.element,
544+ preferredClass: modelElement.enclosingElement is Class
545+ ? modelElement.enclosingElement
546+ : null ));
547+ }
548+ }
549+ }
550+
551+ void _findWithinTryClasses (Set <ModelElement > results, Class preferredClass, Warnable element, String codeRefChomped, String codeRef, PackageGraph packageGraph) {
552+ if (results.isEmpty) {
553+ // Maybe this is local to a class.
554+ // TODO(jcollins-g): tryClasses is a strict subset of the superclass chain. Optimize.
555+ List <Class > tryClasses = [preferredClass];
556+ Class realClass = tryClasses.first;
557+ if (element is Inheritable ) {
558+ Inheritable overriddenElement = element.overriddenElement;
559+ while (overriddenElement != null ) {
560+ tryClasses.add (
561+ (element.overriddenElement as EnclosedElement ).enclosingElement);
562+ overriddenElement = overriddenElement.overriddenElement;
563+ }
564+ }
565+
566+ for (Class tryClass in tryClasses) {
567+ if (tryClass != null ) {
568+ _getResultsForClass (
569+ tryClass, codeRefChomped, results, codeRef, packageGraph);
570+ }
571+ results.remove (null );
572+ if (results.isNotEmpty) break ;
573+ }
574+
575+ if (results.isEmpty && realClass != null ) {
576+ for (Class superClass
577+ in realClass.publicSuperChain.map ((et) => et.element as Class )) {
578+ if (! tryClasses.contains (superClass)) {
579+ _getResultsForClass (
580+ superClass, codeRefChomped, results, codeRef, packageGraph);
581+ }
582+ results.remove (null );
583+ if (results.isNotEmpty) break ;
584+ }
585+ }
586+ }
587+ }
588+
563589// _getResultsForClass assumes codeRefChomped might be a member of tryClass (inherited or not)
564590// and will add to [results]
565591void _getResultsForClass (Class tryClass, String codeRefChomped,
0 commit comments