@@ -392,85 +392,122 @@ DocComment *swift::getSingleDocComment(swift::markup::MarkupContext &MC,
392392}
393393
394394namespace {
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;
404413 }
405414
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;
408419
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;
414423
415- ValueDecl *requirement = nullptr ;
424+ VD = baseDecl;
425+ }
426+ return None;
427+ }
416428
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 ;
422445
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 ;
430449
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;
432457 }
433- return requirement;
434- }
435458
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+
443466 requirements.push (req);
467+ }
468+ if (requirements.empty ())
469+ return None;
470+
471+ VD = requirements.front ();
472+ requirements.pop ();
444473 }
445- if (requirements.empty ())
446- return nullptr ;
447- VD = requirements.front ();
448- requirements.pop ();
449474 }
450- }
451- } // namespace
452475
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;
456480
457- if (!D->getRawComment ().isEmpty ())
458- return D;
481+ auto *VD = dyn_cast<ValueDecl>(D);
482+ if (!VD)
483+ return None;
459484
460- auto *VD = dyn_cast<ValueDecl>(D);
461- if (!VD)
462- return nullptr ;
485+ if (auto result = findOverriddenDecl (VD))
486+ return result;
463487
464- if (auto *overridden = findOverriddenDeclWithDocComment (VD))
465- return overridden ;
488+ if (auto result = findDefaultProvidedDecl (VD))
489+ return result ;
466490
467- if (auto *requirement = findDefaultProvidedDeclWithDocComment (VD))
468- return requirement ;
491+ if (auto result = findRequirementDecl (VD))
492+ return result ;
469493
470- if (auto *requirement = findRequirementDeclWithDocComment (VD))
471- return requirement;
494+ return None;
495+ }
496+ };
497+ } // end anonymous namespace
472498
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 ;
474511}
475512
476513DocComment *swift::getCascadingDocComment (swift::markup::MarkupContext &MC,
@@ -499,31 +536,50 @@ DocComment *swift::getCascadingDocComment(swift::markup::MarkupContext &MC,
499536 return doc;
500537}
501538
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;
506544
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+ }
511562 }
512563
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.
515566 auto RC = D->getRawComment ();
516- if (RC.isEmpty ()) {
517- if (auto *docD = getDocCommentProvidingDecl (D))
518- RC = docD->getRawComment ();
519- }
520567 if (RC.isEmpty ())
521- return StringRef () ;
568+ return None ;
522569
523570 SmallString<256 > BriefStr;
524571 llvm::raw_svector_ostream OS (BriefStr);
525572 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 ();
527583}
528584
529585StringRef Decl::getBriefComment () const {
0 commit comments