Index: include/clang/Sema/CodeCompleteConsumer.h =================================================================== --- include/clang/Sema/CodeCompleteConsumer.h +++ include/clang/Sema/CodeCompleteConsumer.h @@ -46,6 +46,7 @@ class NestedNameSpecifier; class Preprocessor; class Sema; +class RawComment; /// \brief Default priority values for code-completion results based /// on their kind. @@ -1073,6 +1074,23 @@ virtual CodeCompletionTUInfo &getCodeCompletionTUInfo() = 0; }; +/// \brief Get the documentation comment used to produce +/// CodeCompletionString::BriefComment for RK_Declaration. +const RawComment *getCompletionComment(const ASTContext &Ctx, + const NamedDecl *Decl); + +/// \brief Get the documentation comment used to produce +/// CodeCompletionString::BriefComment for RK_Pattern. +const RawComment *getPatternCompletionComment(const ASTContext &Ctx, + const NamedDecl *Decl); + +/// \brief Get the documentation comment used to produce +/// CodeCompletionString::BriefComment for OverloadCandidate. +const RawComment * +getParameterComment(const ASTContext &Ctx, + const CodeCompleteConsumer::OverloadCandidate &Result, + unsigned CurrentArg); + /// \brief A simple code-completion consumer that prints the results it /// receives in a simple format. class PrintingCodeCompleteConsumer : public CodeCompleteConsumer { Index: lib/Sema/SemaCodeComplete.cpp =================================================================== --- lib/Sema/SemaCodeComplete.cpp +++ lib/Sema/SemaCodeComplete.cpp @@ -2765,27 +2765,11 @@ if (Declaration) { Result.addParentContext(Declaration->getDeclContext()); Pattern->ParentName = Result.getParentName(); - // Provide code completion comment for self.GetterName where - // GetterName is the getter method for a property with name - // different from the property name (declared via a property - // getter attribute. - const NamedDecl *ND = Declaration; - if (const ObjCMethodDecl *M = dyn_cast(ND)) - if (M->isPropertyAccessor()) - if (const ObjCPropertyDecl *PDecl = M->findPropertyDecl()) - if (PDecl->getGetterName() == M->getSelector() && - PDecl->getIdentifier() != M->getIdentifier()) { - if (const RawComment *RC = - Ctx.getRawCommentForAnyRedecl(M)) { - Result.addBriefComment(RC->getBriefText(Ctx)); - Pattern->BriefComment = Result.getBriefComment(); - } - else if (const RawComment *RC = - Ctx.getRawCommentForAnyRedecl(PDecl)) { - Result.addBriefComment(RC->getBriefText(Ctx)); - Pattern->BriefComment = Result.getBriefComment(); - } - } + if (const RawComment *RC = + getPatternCompletionComment(Ctx, Declaration)) { + Result.addBriefComment(RC->getBriefText(Ctx)); + Pattern->BriefComment = Result.getBriefComment(); + } } return Pattern; @@ -2845,14 +2829,9 @@ if (IncludeBriefComments) { // Add documentation comment, if it exists. - if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(ND)) { + if (const RawComment *RC = getCompletionComment(Ctx, Declaration)) { Result.addBriefComment(RC->getBriefText(Ctx)); } - else if (const ObjCMethodDecl *OMD = dyn_cast(ND)) - if (OMD->isPropertyAccessor()) - if (const ObjCPropertyDecl *PDecl = OMD->findPropertyDecl()) - if (const RawComment *RC = Ctx.getRawCommentForAnyRedecl(PDecl)) - Result.addBriefComment(RC->getBriefText(Ctx)); } if (StartsNestedNameSpecifier) { @@ -3042,6 +3021,61 @@ return Result.TakeString(); } +const RawComment *clang::getCompletionComment(const ASTContext &Ctx, + const NamedDecl *ND) { + if (!ND) + return nullptr; + if (auto *RC = Ctx.getRawCommentForAnyRedecl(ND)) + return RC; + + // Try to find comment from a property for ObjC methods. + const ObjCMethodDecl *M = dyn_cast(ND); + if (!M) + return nullptr; + const ObjCPropertyDecl *PDecl = M->findPropertyDecl(); + if (!PDecl) + return nullptr; + + return Ctx.getRawCommentForAnyRedecl(PDecl); +} + +const RawComment *clang::getPatternCompletionComment(const ASTContext &Ctx, + const NamedDecl *ND) { + const ObjCMethodDecl *M = dyn_cast_or_null(ND); + if (!M || !M->isPropertyAccessor()) + return nullptr; + + // Provide code completion comment for self.GetterName where + // GetterName is the getter method for a property with name + // different from the property name (declared via a property + // getter attribute. + const ObjCPropertyDecl *PDecl = M->findPropertyDecl(); + if (!PDecl) + return nullptr; + if (PDecl->getGetterName() == M->getSelector() && + PDecl->getIdentifier() != M->getIdentifier()) { + if (auto *RC = Ctx.getRawCommentForAnyRedecl(M)) + return RC; + if (auto *RC = Ctx.getRawCommentForAnyRedecl(PDecl)) + return RC; + } + return nullptr; +} + +/// \brief Get the documentation comment used to produce +/// CodeCompletionString::BriefComment. +const RawComment *clang::getParameterComment( + const ASTContext &Ctx, + const CodeCompleteConsumer::OverloadCandidate &Result, + unsigned CurrentArg) { + auto FDecl = Result.getFunction(); + if (!FDecl) + return nullptr; + if (CurrentArg < FDecl->getNumParams()) + return Ctx.getRawCommentForAnyRedecl(FDecl->getParamDecl(CurrentArg)); + return nullptr; +} + /// \brief Add function overload parameter chunks to the given code completion /// string. static void AddOverloadParameterChunks(ASTContext &Context, @@ -3137,10 +3171,10 @@ } if (FDecl) { - if (IncludeBriefComments && CurrentArg < FDecl->getNumParams()) - if (auto RC = S.getASTContext().getRawCommentForAnyRedecl( - FDecl->getParamDecl(CurrentArg))) + if (IncludeBriefComments) { + if (auto RC = getParameterComment(S.getASTContext(), *this, CurrentArg)) Result.addBriefComment(RC->getBriefText(S.getASTContext())); + } AddResultTypeChunk(S.Context, Policy, FDecl, QualType(), Result); Result.AddTextChunk( Result.getAllocator().CopyString(FDecl->getNameAsString()));