10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/DeclObjC.h"
12 #include "clang/AST/RawCommentList.h"
13 #include "clang/Basic/SourceManager.h"
14 #include "clang/Sema/CodeCompleteConsumer.h"
22 bool isInformativeQualifierChunk(CodeCompletionString::Chunk
const &Chunk) {
23 return Chunk.Kind == CodeCompletionString::CK_Informative &&
24 llvm::StringRef(Chunk.Text).endswith(
"::");
27 void appendEscapeSnippet(
const llvm::StringRef Text, std::string *
Out) {
28 for (
const auto Character : Text) {
29 if (Character ==
'$' || Character ==
'}' || Character ==
'\\')
31 Out->push_back(Character);
35 void appendOptionalChunk(
const CodeCompletionString &CCS, std::string *
Out) {
36 for (
const CodeCompletionString::Chunk &C : CCS) {
38 case CodeCompletionString::CK_Optional:
40 "Expected the optional code completion string to be non-null.");
41 appendOptionalChunk(*C.Optional,
Out);
50 bool looksLikeDocComment(llvm::StringRef CommentText) {
56 return CommentText.find_first_not_of(
"/*-= \t\r\n") != llvm::StringRef::npos;
62 const CodeCompletionResult &Result,
63 bool CommentsFromHeaders) {
67 if (Result.Kind != CodeCompletionResult::RK_Declaration)
74 if (isa<NamespaceDecl>(
Decl)) {
81 const RawComment *RC = getCompletionComment(
Ctx, &
Decl);
86 assert(!
Ctx.getSourceManager().isLoadedSourceLocation(RC->getBeginLoc()));
88 RC->getFormattedText(
Ctx.getSourceManager(),
Ctx.getDiagnostics());
89 return looksLikeDocComment(Doc) ? Doc :
"";
93 std::string *Snippet, std::string *RequiredQualifiers,
94 bool CompletingPattern) {
97 unsigned CursorSnippetArg = std::numeric_limits<unsigned>::max();
98 if (CompletingPattern) {
105 llvm::count_if(CCS, [](
const CodeCompletionString::Chunk &C) {
106 return C.Kind == CodeCompletionString::CK_Placeholder;
109 unsigned SnippetArg = 0;
110 bool HadObjCArguments =
false;
111 for (
const auto &Chunk : CCS) {
114 if (isInformativeQualifierChunk(Chunk))
117 switch (Chunk.Kind) {
118 case CodeCompletionString::CK_TypedText:
130 if (!llvm::StringRef(Chunk.Text).endswith(
":")) {
131 if (RequiredQualifiers)
132 *RequiredQualifiers = std::move(*
Signature);
142 if (!HadObjCArguments) {
143 HadObjCArguments =
true;
151 case CodeCompletionString::CK_Text:
155 case CodeCompletionString::CK_Optional:
156 assert(Chunk.Optional);
158 appendOptionalChunk(*Chunk.Optional,
Signature);
160 case CodeCompletionString::CK_Placeholder:
165 std::to_string(SnippetArg == CursorSnippetArg ? 0 : SnippetArg) +
':';
166 appendEscapeSnippet(Chunk.Text,
Snippet);
169 case CodeCompletionString::CK_Informative:
175 case CodeCompletionString::CK_ResultType:
178 case CodeCompletionString::CK_CurrentParameter:
181 llvm_unreachable(
"Unexpected CK_CurrentParameter while collecting "
184 case CodeCompletionString::CK_LeftParen:
185 case CodeCompletionString::CK_RightParen:
186 case CodeCompletionString::CK_LeftBracket:
187 case CodeCompletionString::CK_RightBracket:
188 case CodeCompletionString::CK_LeftBrace:
189 case CodeCompletionString::CK_RightBrace:
190 case CodeCompletionString::CK_LeftAngle:
191 case CodeCompletionString::CK_RightAngle:
192 case CodeCompletionString::CK_Comma:
193 case CodeCompletionString::CK_Colon:
194 case CodeCompletionString::CK_SemiColon:
195 case CodeCompletionString::CK_Equal:
196 case CodeCompletionString::CK_HorizontalSpace:
200 case CodeCompletionString::CK_VerticalSpace:
209 llvm::StringRef DocComment) {
213 const unsigned AnnotationCount = CCS.getAnnotationCount();
214 if (AnnotationCount > 0) {
215 Result +=
"Annotation";
216 if (AnnotationCount == 1) {
221 for (
unsigned I = 0; I < AnnotationCount; ++I) {
222 Result += CCS.getAnnotation(I);
223 Result.push_back(I == AnnotationCount - 1 ?
'\n' :
' ');
227 if (!DocComment.empty()) {
228 if (!Result.empty()) {
231 Result.push_back(
'\n');
233 Result += DocComment;
239 for (
const auto &Chunk : CCS)
240 if (Chunk.Kind == CodeCompletionString::CK_ResultType)