@@ -392,225 +392,13 @@ DocComment *swift::getSingleDocComment(swift::markup::MarkupContext &MC,
392392 return DocComment::create (D, MC, RC);
393393}
394394
395- namespace {
396- // / Helper class for finding the comment providing decl for either a brief or
397- // / raw comment.
398- template <typename Result>
399- class CommentProviderFinder final {
400- using ResultWithDecl = std::pair<Result, const Decl *>;
401- using VisitFnTy = std::optional<Result> (*)(const Decl *);
402-
403- VisitFnTy VisitFn;
404-
405- public:
406- CommentProviderFinder (VisitFnTy visitFn) : VisitFn(visitFn) {}
407-
408- private:
409- std::optional<ResultWithDecl> visit (const Decl *D) {
410- // Adapt the provided visitor function to also return the decl.
411- if (auto result = VisitFn (D))
412- return {{*result, D}};
413- return std::nullopt ;
414- }
415-
416- std::optional<ResultWithDecl> findOverriddenDecl (const ValueDecl *VD) {
417- // Only applies to class member.
418- if (!VD->getDeclContext ()->getSelfClassDecl ())
419- return std::nullopt ;
420-
421- while (auto *baseDecl = VD->getOverriddenDecl ()) {
422- if (auto result = visit (baseDecl))
423- return result;
424-
425- VD = baseDecl;
426- }
427- return std::nullopt ;
428- }
429-
430- // / Check if there is an inherited protocol that has a default implementation
431- // / of `VD` with a doc comment.
432- std::optional<ResultWithDecl> findDefaultProvidedDecl (const ValueDecl *VD) {
433- NominalTypeDecl *nominalType =
434- dyn_cast_or_null<NominalTypeDecl>(VD->getDeclContext ()->getAsDecl ());
435- if (!nominalType) {
436- nominalType = VD->getDeclContext ()->getExtendedProtocolDecl ();
437- }
438- if (!nominalType)
439- return std::nullopt ;
440-
441- SmallVector<ValueDecl *, 2 > members;
442- nominalType->lookupQualified (nominalType, DeclNameRef (VD->getName ()),
443- VD->getLoc (), NLOptions::NL_ProtocolMembers,
444- members);
445-
446- std::optional<ResultWithDecl> result;
447- Type vdComparisonTy = VD->getInterfaceType ();
448- if (!vdComparisonTy) {
449- return std::nullopt ;
450- }
451- if (auto fnTy = vdComparisonTy->getAs <AnyFunctionType>()) {
452- // Strip off the 'Self' parameter.
453- vdComparisonTy = fnTy->getResult ();
454- }
455-
456- for (auto *member : members) {
457- if (isa<AbstractFunctionDecl>(member) || isa<AbstractStorageDecl>(member)) {
458- if (VD->isStatic () != member->isStatic ()) {
459- continue ;
460- }
461- Type memberComparisonTy = member->getInterfaceType ();
462- if (!memberComparisonTy) {
463- continue ;
464- }
465- if (auto fnTy = memberComparisonTy->getAs <AnyFunctionType>()) {
466- // Strip off the 'Self' parameter.
467- memberComparisonTy = fnTy->getResult ();
468- }
469- if (!vdComparisonTy->matches (memberComparisonTy, TypeMatchFlags::AllowOverride)) {
470- continue ;
471- }
472- }
473- auto newResult = visit (member);
474- if (!newResult)
475- continue ;
476-
477- if (result) {
478- // Found two or more decls with doc-comment.
479- return std::nullopt ;
480- }
481- result = newResult;
482- }
483- return result;
484- }
485-
486- std::optional<ResultWithDecl> findRequirementDecl (const ValueDecl *VD) {
487- std::queue<const ValueDecl *> requirements;
488- while (true ) {
489- for (auto *req : VD->getSatisfiedProtocolRequirements ()) {
490- if (auto result = visit (req))
491- return result;
492-
493- requirements.push (req);
494- }
495- if (requirements.empty ())
496- return std::nullopt ;
497-
498- VD = requirements.front ();
499- requirements.pop ();
500- }
501- }
502-
503- public:
504- std::optional<ResultWithDecl> findCommentProvider (const Decl *D) {
505- if (auto result = visit (D))
506- return result;
507-
508- auto *VD = dyn_cast<ValueDecl>(D);
509- if (!VD)
510- return std::nullopt ;
511-
512- if (auto result = findOverriddenDecl (VD))
513- return result;
514-
515- if (auto result = findRequirementDecl (VD))
516- return result;
517-
518- if (auto result = findDefaultProvidedDecl (VD))
519- return result;
520-
521- return std::nullopt ;
522- }
523- };
524- } // end anonymous namespace
525-
526- const Decl *swift::getDocCommentProvidingDecl (const Decl *D) {
527- // Search for the first decl we see with a non-empty raw comment.
528- auto finder = CommentProviderFinder<RawComment>(
529- [](const Decl *D) -> std::optional<RawComment> {
530- auto comment = D->getRawComment ();
531- if (comment.isEmpty ())
532- return std::nullopt ;
533- return comment;
534- });
535-
536- auto result = finder.findCommentProvider (D);
537- return result ? result->second : nullptr ;
538- }
539-
540- DocComment *swift::getCascadingDocComment (swift::markup::MarkupContext &MC,
541- const Decl *D) {
542- auto *docD = getDocCommentProvidingDecl (D);
543- if (!docD)
544- return nullptr ;
545-
546- auto *doc = getSingleDocComment (MC, docD);
547- assert (doc && " getDocCommentProvidingDecl() returned decl with no comment" );
548-
549- // If the doc-comment is inherited from other decl, add a note about it.
550- if (docD != D) {
551- doc->setDecl (D);
552- if (auto baseD = docD->getDeclContext ()->getSelfNominalTypeDecl ()) {
553- doc->addInheritanceNote (MC, baseD);
554-
555- // If the doc is inherited from protocol requirement, associate the
556- // requirement with the doc-comment.
557- // FIXME: This is to keep the old behavior.
558- if (isa<ProtocolDecl>(baseD))
559- doc->setDecl (docD);
560- }
561- }
562-
563- return doc;
564- }
565-
566- // / Retrieve the brief comment for a given decl \p D, without attempting to
567- // / walk any requirements or overrides.
568- static std::optional<StringRef> getDirectBriefComment (const Decl *D) {
569- if (!D->canHaveComment ())
570- return std::nullopt ;
571-
572- auto *ModuleDC = D->getDeclContext ()->getModuleScopeContext ();
573- auto &Ctx = ModuleDC->getASTContext ();
574-
575- // If we expect the comment to be in the swiftdoc, check for it if we loaded a
576- // swiftdoc. If missing from the swiftdoc, we know it will not be in the
577- // swiftsourceinfo either, so we can bail early.
578- if (auto *Unit = dyn_cast<FileUnit>(ModuleDC)) {
579- if (Unit->hasLoadedSwiftDoc ()) {
580- auto target = getDocCommentSerializationTargetFor (D);
581- if (target == DocCommentSerializationTarget::SwiftDocAndSourceInfo) {
582- auto C = Unit->getCommentForDecl (D);
583- if (!C)
584- return std::nullopt ;
585-
586- return C->Brief ;
587- }
588- }
589- }
590-
591- // Otherwise, parse the brief from the raw comment itself. This will look into
592- // the swiftsourceinfo if needed.
593- auto RC = D->getRawComment ();
594- if (RC.isEmpty ())
595- return std::nullopt ;
596-
597- SmallString<256 > BriefStr;
598- llvm::raw_svector_ostream OS (BriefStr);
599- printBriefComment (RC, OS);
600- return Ctx.AllocateCopy (BriefStr.str ());
601- }
602-
603- StringRef SemanticBriefCommentRequest::evaluate (Evaluator &evaluator,
604- const Decl *D) const {
605- // Perform a walk over the potential providers of the brief comment,
606- // retrieving the first one we come across.
607- CommentProviderFinder<StringRef> finder (getDirectBriefComment);
608- auto result = finder.findCommentProvider (D);
609- return result ? result->first : StringRef ();
395+ const Decl *Decl::getDocCommentProvidingDecl () const {
396+ return evaluateOrDefault (getASTContext ().evaluator ,
397+ DocCommentProvidingDeclRequest{this }, nullptr );
610398}
611399
612400StringRef Decl::getSemanticBriefComment () const {
613- if (!this -> canHaveComment ())
401+ if (!canHaveComment ())
614402 return StringRef ();
615403
616404 auto &eval = getASTContext ().evaluator ;
0 commit comments