clang-tools 8.0.0

CodeCompletionStrings.cpp
Go to the documentation of this file.
1 //===--- CodeCompletionStrings.cpp -------------------------------*- C++-*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "CodeCompletionStrings.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/DeclObjC.h"
13 #include "clang/AST/RawCommentList.h"
14 #include "clang/Basic/SourceManager.h"
15 #include <utility>
16
17 namespace clang {
18 namespace clangd {
19 namespace {
20
21 bool isInformativeQualifierChunk(CodeCompletionString::Chunk const &Chunk) {
22 return Chunk.Kind == CodeCompletionString::CK_Informative &&
23 llvm::StringRef(Chunk.Text).endswith("::");
24 }
25
26 void appendEscapeSnippet(const llvm::StringRef Text, std::string *Out) {
27 for (const auto Character : Text) {
28 if (Character == '$' || Character == '}' || Character == '\\')
29 Out->push_back('\\');
30 Out->push_back(Character);
31 }
32 }
33
34 bool looksLikeDocComment(llvm::StringRef CommentText) {
35 // We don't report comments that only contain "special" chars.
36 // This avoids reporting various delimiters, like:
37 // =================
38 // -----------------
39 // *****************
40 return CommentText.find_first_not_of("/*-= \t\r\n") != llvm::StringRef::npos;
41 }
42
43 } // namespace
44
45 std::string getDocComment(const ASTContext &Ctx,
46 const CodeCompletionResult &Result,
47 bool CommentsFromHeaders) {
48 // FIXME: clang's completion also returns documentation for RK_Pattern if they
49 // contain a pattern for ObjC properties. Unfortunately, there is no API to
50 // get this declaration, so we don't show documentation in that case.
51 if (Result.Kind != CodeCompletionResult::RK_Declaration)
52 return "";
53 return Result.getDeclaration() ? getDeclComment(Ctx, *Result.getDeclaration())
54 : "";
55 }
56
57 std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl) {
58 if (isa<NamespaceDecl>(Decl)) {
59 // Namespaces often have too many redecls for any particular redecl comment
60 // to be useful. Moreover, we often confuse file headers or generated
61 // comments with namespace comments. Therefore we choose to just ignore
62 // the comments for namespaces.
63 return "";
64 }
65 const RawComment *RC = getCompletionComment(Ctx, &Decl);
66 if (!RC)
67 return "";
68 // Sanity check that the comment does not come from the PCH. We choose to not
69 // write them into PCH, because they are racy and slow to load.
70 assert(!Ctx.getSourceManager().isLoadedSourceLocation(RC->getBeginLoc()));
71 std::string Doc =
72 RC->getFormattedText(Ctx.getSourceManager(), Ctx.getDiagnostics());
73 return looksLikeDocComment(Doc) ? Doc : "";
74 }
75
76 void getSignature(const CodeCompletionString &CCS, std::string *Signature,
77 std::string *Snippet, std::string *RequiredQualifiers) {
78 unsigned ArgCount = 0;
79 bool HadObjCArguments = false;
80 for (const auto &Chunk : CCS) {
81 // Informative qualifier chunks only clutter completion results, skip
82 // them.
83 if (isInformativeQualifierChunk(Chunk))
84 continue;
85
86 switch (Chunk.Kind) {
87 case CodeCompletionString::CK_TypedText:
88 // The typed-text chunk is the actual name. We don't record this chunk.
89 // C++:
90 // In general our string looks like <qualifiers><name><signature>.
91 // So once we see the name, any text we recorded so far should be
92 // reclassified as qualifiers.
93 //
94 // Objective-C:
95 // Objective-C methods may have multiple typed-text chunks, so we must
96 // treat them carefully. For Objective-C methods, all typed-text chunks
97 // will end in ':' (unless there are no arguments, in which case we
98 // can safely treat them as C++).
99 if (!llvm::StringRef(Chunk.Text).endswith(":")) { // Treat as C++.
100 if (RequiredQualifiers)
101 *RequiredQualifiers = std::move(*Signature);
102 Signature->clear();
103 Snippet->clear();
104 } else { // Objective-C method with args.
105 // If this is the first TypedText to the Objective-C method, discard any
106 // text that we've previously seen (such as previous parameter selector,
107 // which will be marked as Informative text).
108 //
109 // TODO: Make previous parameters part of the signature for Objective-C
110 // methods.
111 if (!HadObjCArguments) {
112 HadObjCArguments = true;
113 Signature->clear();
114 } else { // Subsequent argument, considered part of snippet/signature.
115 *Signature += Chunk.Text;
116 *Snippet += Chunk.Text;
117 }
118 }
119 break;
120 case CodeCompletionString::CK_Text:
121 *Signature += Chunk.Text;
122 *Snippet += Chunk.Text;
123 break;
124 case CodeCompletionString::CK_Optional:
125 break;
126 case CodeCompletionString::CK_Placeholder:
127 *Signature += Chunk.Text;
128 ++ArgCount;
129 *Snippet += "${" + std::to_string(ArgCount) + ':';
130 appendEscapeSnippet(Chunk.Text, Snippet);
131 *Snippet += '}';
132 break;
133 case CodeCompletionString::CK_Informative:
134 // For example, the word "const" for a const method, or the name of
135 // the base class for methods that are part of the base class.
136 *Signature += Chunk.Text;
137 // Don't put the informative chunks in the snippet.
138 break;
139 case CodeCompletionString::CK_ResultType:
140 // This is not part of the signature.
141 break;
142 case CodeCompletionString::CK_CurrentParameter:
143 // This should never be present while collecting completion items,
144 // only while collecting overload candidates.
145 llvm_unreachable("Unexpected CK_CurrentParameter while collecting "
146 "CompletionItems");
147 break;
148 case CodeCompletionString::CK_LeftParen:
149 case CodeCompletionString::CK_RightParen:
150 case CodeCompletionString::CK_LeftBracket:
151 case CodeCompletionString::CK_RightBracket:
152 case CodeCompletionString::CK_LeftBrace:
153 case CodeCompletionString::CK_RightBrace:
154 case CodeCompletionString::CK_LeftAngle:
155 case CodeCompletionString::CK_RightAngle:
156 case CodeCompletionString::CK_Comma:
157 case CodeCompletionString::CK_Colon:
158 case CodeCompletionString::CK_SemiColon:
159 case CodeCompletionString::CK_Equal:
160 case CodeCompletionString::CK_HorizontalSpace:
161 *Signature += Chunk.Text;
162 *Snippet += Chunk.Text;
163 break;
164 case CodeCompletionString::CK_VerticalSpace:
165 *Snippet += Chunk.Text;
166 // Don't even add a space to the signature.
167 break;
168 }
169 }
170 }
171
172 std::string formatDocumentation(const CodeCompletionString &CCS,
173 llvm::StringRef DocComment) {
174 // Things like __attribute__((nonnull(1,3))) and [[noreturn]]. Present this
175 // information in the documentation field.
176 std::string Result;
177 const unsigned AnnotationCount = CCS.getAnnotationCount();
178 if (AnnotationCount > 0) {
179 Result += "Annotation";
180 if (AnnotationCount == 1) {
181 Result += ": ";
182 } else /* AnnotationCount > 1 */ {
183 Result += "s: ";
184 }
185 for (unsigned I = 0; I < AnnotationCount; ++I) {
186 Result += CCS.getAnnotation(I);
187 Result.push_back(I == AnnotationCount - 1 ? '\n' : ' ');
188 }
189 }
190 // Add brief documentation (if there is any).
191 if (!DocComment.empty()) {
192 if (!Result.empty()) {
193 // This means we previously added annotations. Add an extra newline
194 // character to make the annotations stand out.
195 Result.push_back('\n');
196 }
197 Result += DocComment;
198 }
199 return Result;
200 }
201
202 std::string getReturnType(const CodeCompletionString &CCS) {
203 for (const auto &Chunk : CCS)
204 if (Chunk.Kind == CodeCompletionString::CK_ResultType)
205 return Chunk.Text;
206 return "";
207 }
208
209 } // namespace clangd
210 } // namespace clang
clang::clangd::getDocComment
std::string getDocComment(const ASTContext &Ctx, const CodeCompletionResult &Result, bool CommentsFromHeaders)
Gets a minimally formatted documentation comment of Result, with comment markers stripped.
Definition: CodeCompletionStrings.cpp:45
clang::clangd::getReturnType
std::string getReturnType(const CodeCompletionString &CCS)
Gets detail to be used as the detail field in an LSP completion item.
Definition: CodeCompletionStrings.cpp:202
Ctx
Context Ctx
Definition: TUScheduler.cpp:224
CodeCompletionStrings.h
Signature
std::string Signature
Definition: CodeComplete.cpp:416
Result
llvm::Optional< llvm::Expected< tooling::AtomicChanges > > Result
Definition: ClangdServer.cpp:60
clang::clangd::formatDocumentation
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
Definition: CodeCompletionStrings.cpp:172
clang::clangd::getDeclComment
std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl)
Similar to getDocComment, but returns the comment for a NamedDecl.
Definition: CodeCompletionStrings.cpp:57
clang::clangd::getSignature
void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, std::string *RequiredQualifiers)
Formats the signature for an item, as a display string and snippet.
Definition: CodeCompletionStrings.cpp:76
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ChangeNamespace.cpp:18