@@ -392,85 +392,122 @@ DocComment *swift::getSingleDocComment(swift::markup::MarkupContext &MC,
392
392
}
393
393
394
394
namespace {
395
- const ValueDecl *findOverriddenDeclWithDocComment (const ValueDecl *VD) {
396
- // Only applies to class member.
397
- if (!VD->getDeclContext ()->getSelfClassDecl ())
398
- return nullptr ;
399
-
400
- while (auto *baseDecl = VD->getOverriddenDecl ()) {
401
- if (!baseDecl->getRawComment ().isEmpty ())
402
- return baseDecl;
403
- VD = baseDecl;
395
+ // / Helper class for finding the comment providing decl for either a brief or
396
+ // / raw comment.
397
+ template <typename Result>
398
+ class CommentProviderFinder final {
399
+ using ResultWithDecl = std::pair<Result, const Decl *>;
400
+ using VisitFnTy = Optional<Result>(*)(const Decl *);
401
+
402
+ VisitFnTy VisitFn;
403
+
404
+ public:
405
+ CommentProviderFinder (VisitFnTy visitFn) : VisitFn(visitFn) {}
406
+
407
+ private:
408
+ Optional<ResultWithDecl> visit (const Decl *D) {
409
+ // Adapt the provided visitor function to also return the decl.
410
+ if (auto result = VisitFn (D))
411
+ return {{*result, D}};
412
+ return None;
404
413
}
405
414
406
- return nullptr ;
407
- }
415
+ Optional<ResultWithDecl> findOverriddenDecl (const ValueDecl *VD) {
416
+ // Only applies to class member.
417
+ if (!VD->getDeclContext ()->getSelfClassDecl ())
418
+ return None;
408
419
409
- const ValueDecl *findDefaultProvidedDeclWithDocComment (const ValueDecl *VD) {
410
- auto protocol = VD->getDeclContext ()->getExtendedProtocolDecl ();
411
- // Only applies to protocol extension member.
412
- if (!protocol)
413
- return nullptr ;
420
+ while (auto *baseDecl = VD->getOverriddenDecl ()) {
421
+ if (auto result = visit (baseDecl))
422
+ return result;
414
423
415
- ValueDecl *requirement = nullptr ;
424
+ VD = baseDecl;
425
+ }
426
+ return None;
427
+ }
416
428
417
- SmallVector<ValueDecl *, 2 > members;
418
- protocol->lookupQualified (const_cast <ProtocolDecl *>(protocol),
419
- DeclNameRef (VD->getName ()),
420
- NLOptions::NL_ProtocolMembers,
421
- members);
429
+ Optional<ResultWithDecl> findDefaultProvidedDecl (const ValueDecl *VD) {
430
+ // Only applies to protocol extension member.
431
+ auto *protocol = VD->getDeclContext ()->getExtendedProtocolDecl ();
432
+ if (!protocol)
433
+ return None;
434
+
435
+ SmallVector<ValueDecl *, 2 > members;
436
+ protocol->lookupQualified (const_cast <ProtocolDecl *>(protocol),
437
+ DeclNameRef (VD->getName ()),
438
+ NLOptions::NL_ProtocolMembers, members);
439
+
440
+ Optional<ResultWithDecl> result;
441
+ for (auto *member : members) {
442
+ if (!isa<ProtocolDecl>(member->getDeclContext ()) ||
443
+ !member->isProtocolRequirement ())
444
+ continue ;
422
445
423
- for (auto *member : members) {
424
- if (!isa<ProtocolDecl>(member->getDeclContext ()) ||
425
- !member->isProtocolRequirement () || member->getRawComment ().isEmpty ())
426
- continue ;
427
- if (requirement)
428
- // Found two or more decls with doc-comment.
429
- return nullptr ;
446
+ auto newResult = visit (member);
447
+ if (!newResult)
448
+ continue ;
430
449
431
- requirement = member;
450
+ if (result) {
451
+ // Found two or more decls with doc-comment.
452
+ return None;
453
+ }
454
+ result = newResult;
455
+ }
456
+ return result;
432
457
}
433
- return requirement;
434
- }
435
458
436
- const ValueDecl * findRequirementDeclWithDocComment (const ValueDecl *VD) {
437
- std::queue<const ValueDecl *> requirements;
438
- while (true ) {
439
- for (auto *req : VD->getSatisfiedProtocolRequirements ()) {
440
- if (!req-> getRawComment (). isEmpty ( ))
441
- return req ;
442
- else
459
+ Optional<ResultWithDecl> findRequirementDecl (const ValueDecl *VD) {
460
+ std::queue<const ValueDecl *> requirements;
461
+ while (true ) {
462
+ for (auto *req : VD->getSatisfiedProtocolRequirements ()) {
463
+ if (auto result = visit (req ))
464
+ return result ;
465
+
443
466
requirements.push (req);
467
+ }
468
+ if (requirements.empty ())
469
+ return None;
470
+
471
+ VD = requirements.front ();
472
+ requirements.pop ();
444
473
}
445
- if (requirements.empty ())
446
- return nullptr ;
447
- VD = requirements.front ();
448
- requirements.pop ();
449
474
}
450
- }
451
- } // namespace
452
475
453
- const Decl *swift::getDocCommentProvidingDecl (const Decl *D) {
454
- if (!D->canHaveComment ())
455
- return nullptr ;
476
+ public:
477
+ Optional<ResultWithDecl> findCommentProvider (const Decl *D) {
478
+ if (auto result = visit (D))
479
+ return result;
456
480
457
- if (!D->getRawComment ().isEmpty ())
458
- return D;
481
+ auto *VD = dyn_cast<ValueDecl>(D);
482
+ if (!VD)
483
+ return None;
459
484
460
- auto *VD = dyn_cast<ValueDecl>(D);
461
- if (!VD)
462
- return nullptr ;
485
+ if (auto result = findOverriddenDecl (VD))
486
+ return result;
463
487
464
- if (auto *overridden = findOverriddenDeclWithDocComment (VD))
465
- return overridden ;
488
+ if (auto result = findDefaultProvidedDecl (VD))
489
+ return result ;
466
490
467
- if (auto *requirement = findDefaultProvidedDeclWithDocComment (VD))
468
- return requirement ;
491
+ if (auto result = findRequirementDecl (VD))
492
+ return result ;
469
493
470
- if (auto *requirement = findRequirementDeclWithDocComment (VD))
471
- return requirement;
494
+ return None;
495
+ }
496
+ };
497
+ } // end anonymous namespace
472
498
473
- return nullptr ;
499
+ const Decl *swift::getDocCommentProvidingDecl (const Decl *D) {
500
+ // Search for the first decl we see with a non-empty raw comment.
501
+ auto finder = CommentProviderFinder<RawComment>(
502
+ [](const Decl *D) -> Optional<RawComment> {
503
+ auto comment = D->getRawComment ();
504
+ if (comment.isEmpty ())
505
+ return None;
506
+ return comment;
507
+ });
508
+
509
+ auto result = finder.findCommentProvider (D);
510
+ return result ? result->second : nullptr ;
474
511
}
475
512
476
513
DocComment *swift::getCascadingDocComment (swift::markup::MarkupContext &MC,
@@ -499,31 +536,50 @@ DocComment *swift::getCascadingDocComment(swift::markup::MarkupContext &MC,
499
536
return doc;
500
537
}
501
538
502
- StringRef
503
- BriefCommentRequest::evaluate (Evaluator &evaluator, const Decl *D) const {
504
- auto *DC = D->getDeclContext ();
505
- auto &ctx = DC->getASTContext ();
539
+ // / Retrieve the brief comment for a given decl \p D, without attempting to
540
+ // / walk any requirements or overrides.
541
+ static Optional<StringRef> getDirectBriefComment (const Decl *D) {
542
+ if (!D->canHaveComment ())
543
+ return None;
506
544
507
- // Check if the brief comment is available in the swiftdoc.
508
- if (auto *Unit = dyn_cast<FileUnit>(DC->getModuleScopeContext ())) {
509
- if (auto C = Unit->getCommentForDecl (D))
510
- return C->Brief ;
545
+ auto *ModuleDC = D->getDeclContext ()->getModuleScopeContext ();
546
+ auto &Ctx = ModuleDC->getASTContext ();
547
+
548
+ // If we expect the comment to be in the swiftdoc, check for it if we loaded a
549
+ // swiftdoc. If missing from the swiftdoc, we know it will not be in the
550
+ // swiftsourceinfo either, so we can bail early.
551
+ if (auto *Unit = dyn_cast<FileUnit>(ModuleDC)) {
552
+ if (Unit->hasLoadedSwiftDoc ()) {
553
+ auto target = getDocCommentSerializationTargetFor (D);
554
+ if (target == DocCommentSerializationTarget::SwiftDocAndSourceInfo) {
555
+ auto C = Unit->getCommentForDecl (D);
556
+ if (!C)
557
+ return None;
558
+
559
+ return C->Brief ;
560
+ }
561
+ }
511
562
}
512
563
513
- // Otherwise, parse the brief from the raw comment itself. This will look into the
514
- // swiftsourceinfo if needed.
564
+ // Otherwise, parse the brief from the raw comment itself. This will look into
565
+ // the swiftsourceinfo if needed.
515
566
auto RC = D->getRawComment ();
516
- if (RC.isEmpty ()) {
517
- if (auto *docD = getDocCommentProvidingDecl (D))
518
- RC = docD->getRawComment ();
519
- }
520
567
if (RC.isEmpty ())
521
- return StringRef () ;
568
+ return None ;
522
569
523
570
SmallString<256 > BriefStr;
524
571
llvm::raw_svector_ostream OS (BriefStr);
525
572
printBriefComment (RC, OS);
526
- return ctx.AllocateCopy (BriefStr.str ());
573
+ return Ctx.AllocateCopy (BriefStr.str ());
574
+ }
575
+
576
+ StringRef BriefCommentRequest::evaluate (Evaluator &evaluator,
577
+ const Decl *D) const {
578
+ // Perform a walk over the potential providers of the brief comment,
579
+ // retrieving the first one we come across.
580
+ CommentProviderFinder finder (getDirectBriefComment);
581
+ auto result = finder.findCommentProvider (D);
582
+ return result ? result->first : StringRef ();
527
583
}
528
584
529
585
StringRef Decl::getBriefComment () const {
0 commit comments