@@ -391,229 +391,3 @@ DocComment *swift::getSingleDocComment(swift::markup::MarkupContext &MC,
391
391
return nullptr ;
392
392
return DocComment::create (D, MC, RC);
393
393
}
394
-
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 ();
610
- }
611
-
612
- StringRef Decl::getSemanticBriefComment () const {
613
- if (!this ->canHaveComment ())
614
- return StringRef ();
615
-
616
- auto &eval = getASTContext ().evaluator ;
617
- return evaluateOrDefault (eval, SemanticBriefCommentRequest{this },
618
- StringRef ());
619
- }
0 commit comments