10 #include "clang/AST/ASTContext.h"
11 #include "clang/AST/RawCommentList.h"
12 #include "clang/Basic/SourceManager.h"
13 #include "clang/Sema/CodeCompleteConsumer.h"
14 #include "llvm/Support/JSON.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) {
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 if (!looksLikeDocComment(Doc))
92 if (!llvm::json::isUTF8(Doc))
93 Doc = llvm::json::fixUTF8(Doc);
98 std::string *Snippet, std::string *RequiredQualifiers,
99 bool CompletingPattern) {
102 unsigned CursorSnippetArg = std::numeric_limits<unsigned>::max();
103 if (CompletingPattern) {
110 llvm::count_if(CCS, [](
const CodeCompletionString::Chunk &
C) {
111 return C.Kind == CodeCompletionString::CK_Placeholder;
114 unsigned SnippetArg = 0;
115 bool HadObjCArguments =
false;
116 bool HadInformativeChunks =
false;
117 for (
const auto &Chunk : CCS) {
120 if (isInformativeQualifierChunk(Chunk))
123 switch (Chunk.Kind) {
124 case CodeCompletionString::CK_TypedText:
140 if (!llvm::StringRef(Chunk.Text).endswith(
":")) {
141 if (RequiredQualifiers)
142 *RequiredQualifiers = std::move(*
Signature);
152 if (!HadObjCArguments) {
153 HadObjCArguments =
true;
171 if (!HadInformativeChunks) {
172 if (RequiredQualifiers)
173 *RequiredQualifiers = std::move(*
Signature);
183 case CodeCompletionString::CK_Text:
187 case CodeCompletionString::CK_Optional:
188 assert(Chunk.Optional);
190 appendOptionalChunk(*Chunk.Optional,
Signature);
192 case CodeCompletionString::CK_Placeholder:
197 std::to_string(SnippetArg == CursorSnippetArg ? 0 : SnippetArg) +
':';
198 appendEscapeSnippet(Chunk.Text,
Snippet);
201 case CodeCompletionString::CK_Informative:
202 HadInformativeChunks =
true;
208 case CodeCompletionString::CK_ResultType:
211 case CodeCompletionString::CK_CurrentParameter:
214 llvm_unreachable(
"Unexpected CK_CurrentParameter while collecting "
217 case CodeCompletionString::CK_LeftParen:
218 case CodeCompletionString::CK_RightParen:
219 case CodeCompletionString::CK_LeftBracket:
220 case CodeCompletionString::CK_RightBracket:
221 case CodeCompletionString::CK_LeftBrace:
222 case CodeCompletionString::CK_RightBrace:
223 case CodeCompletionString::CK_LeftAngle:
224 case CodeCompletionString::CK_RightAngle:
225 case CodeCompletionString::CK_Comma:
226 case CodeCompletionString::CK_Colon:
227 case CodeCompletionString::CK_SemiColon:
228 case CodeCompletionString::CK_Equal:
229 case CodeCompletionString::CK_HorizontalSpace:
233 case CodeCompletionString::CK_VerticalSpace:
242 llvm::StringRef DocComment) {
246 const unsigned AnnotationCount = CCS.getAnnotationCount();
247 if (AnnotationCount > 0) {
248 Result +=
"Annotation";
249 if (AnnotationCount == 1) {
254 for (
unsigned I = 0; I < AnnotationCount; ++I) {
255 Result += CCS.getAnnotation(I);
256 Result.push_back(I == AnnotationCount - 1 ?
'\n' :
' ');
260 if (!DocComment.empty()) {
261 if (!Result.empty()) {
264 Result.push_back(
'\n');
266 Result += DocComment;
272 for (
const auto &Chunk : CCS)
273 if (Chunk.Kind == CodeCompletionString::CK_ResultType)