@@ -333,6 +333,9 @@ ModelElement _findRefElementInLibrary(String codeRef, Warnable element,
333
333
newCodeRef, element, commentRefs, preferredClass);
334
334
}
335
335
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.
336
339
results.remove (null );
337
340
// Oh, and someone might have some type parameters or other garbage.
338
341
if (results.isEmpty && codeRef.contains (trailingIgnoreStuff)) {
@@ -366,118 +369,30 @@ ModelElement _findRefElementInLibrary(String codeRef, Warnable element,
366
369
p.name == codeRefChomped || codeRefChomped.startsWith ("${p .name }." )));
367
370
}
368
371
}
369
-
370
372
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
- }
393
373
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);
406
376
results.remove (null );
407
377
408
378
// We now need the ref element cache to keep from repeatedly searching [Package.allModelElements].
409
379
// But if not, look for a fully qualified match. (That only makes sense
410
380
// 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);
428
382
results.remove (null );
429
383
430
384
// 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);
441
386
results.remove (null );
442
387
443
388
// 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);
456
390
results.remove (null );
457
391
458
392
// This could conceivably be a reference to an enum member. They don't show up in allModelElements.
459
393
// TODO(jcollins-g): Put enum members in allModelElements with useful hrefs without blowing up other assumptions about what that means.
460
394
// 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);
481
396
results.remove (null );
482
397
483
398
if (results.length > 1 ) {
@@ -560,6 +475,117 @@ ModelElement _findRefElementInLibrary(String codeRef, Warnable element,
560
475
return result;
561
476
}
562
477
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
+
563
589
// _getResultsForClass assumes codeRefChomped might be a member of tryClass (inherited or not)
564
590
// and will add to [results]
565
591
void _getResultsForClass (Class tryClass, String codeRefChomped,
0 commit comments