clang-tools 17.0.0git
CodeCompletionStringsTests.cpp
Go to the documentation of this file.
1//===-- CodeCompletionStringsTests.cpp --------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "TestTU.h"
11#include "clang/Sema/CodeCompleteConsumer.h"
12#include "gmock/gmock.h"
13#include "gtest/gtest.h"
14
15namespace clang {
16namespace clangd {
17namespace {
18
19class CompletionStringTest : public ::testing::Test {
20public:
21 CompletionStringTest()
22 : Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
23 CCTUInfo(Allocator), Builder(*Allocator, CCTUInfo) {}
24
25protected:
26 void computeSignature(const CodeCompletionString &CCS,
27 CodeCompletionResult::ResultKind ResultKind =
28 CodeCompletionResult::ResultKind::RK_Declaration) {
29 Signature.clear();
30 Snippet.clear();
31 getSignature(CCS, &Signature, &Snippet, ResultKind,
32 /*CursorKind=*/CXCursorKind::CXCursor_NotImplemented,
33 /*RequiredQualifiers=*/nullptr);
34 }
35
36 std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
37 CodeCompletionTUInfo CCTUInfo;
38 CodeCompletionBuilder Builder;
39 std::string Signature;
40 std::string Snippet;
41};
42
43TEST_F(CompletionStringTest, ReturnType) {
44 Builder.AddResultTypeChunk("result");
45 Builder.AddResultTypeChunk("redundant result no no");
46 EXPECT_EQ(getReturnType(*Builder.TakeString()), "result");
47}
48
49TEST_F(CompletionStringTest, Documentation) {
50 Builder.addBriefComment("This is ignored");
51 EXPECT_EQ(formatDocumentation(*Builder.TakeString(), "Is this brief?"),
52 "Is this brief?");
53}
54
55TEST_F(CompletionStringTest, DocumentationWithAnnotation) {
56 Builder.addBriefComment("This is ignored");
57 Builder.AddAnnotation("Ano");
58 EXPECT_EQ(formatDocumentation(*Builder.TakeString(), "Is this brief?"),
59 "Annotation: Ano\n\nIs this brief?");
60}
61
62TEST_F(CompletionStringTest, GetDeclCommentBadUTF8) {
63 // <ff> is not a valid byte here, should be replaced by encoded <U+FFFD>.
64 auto TU = TestTU::withCode("/*x\xffy*/ struct X;");
65 auto AST = TU.build();
66 EXPECT_EQ("x\xef\xbf\xbdy",
67 getDeclComment(AST.getASTContext(), findDecl(AST, "X")));
68}
69
70TEST_F(CompletionStringTest, MultipleAnnotations) {
71 Builder.AddAnnotation("Ano1");
72 Builder.AddAnnotation("Ano2");
73 Builder.AddAnnotation("Ano3");
74
75 EXPECT_EQ(formatDocumentation(*Builder.TakeString(), ""),
76 "Annotations: Ano1 Ano2 Ano3\n");
77}
78
79TEST_F(CompletionStringTest, EmptySignature) {
80 Builder.AddTypedTextChunk("X");
81 Builder.AddResultTypeChunk("result no no");
82 computeSignature(*Builder.TakeString());
83 EXPECT_EQ(Signature, "");
84 EXPECT_EQ(Snippet, "");
85}
86
87TEST_F(CompletionStringTest, Function) {
88 Builder.AddResultTypeChunk("result no no");
89 Builder.addBriefComment("This comment is ignored");
90 Builder.AddTypedTextChunk("Foo");
91 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
92 Builder.AddPlaceholderChunk("p1");
93 Builder.AddChunk(CodeCompletionString::CK_Comma);
94 Builder.AddPlaceholderChunk("p2");
95 Builder.AddChunk(CodeCompletionString::CK_RightParen);
96
97 auto *CCS = Builder.TakeString();
98 computeSignature(*CCS);
99 EXPECT_EQ(Signature, "(p1, p2)");
100 EXPECT_EQ(Snippet, "(${1:p1}, ${2:p2})");
101 EXPECT_EQ(formatDocumentation(*CCS, "Foo's comment"), "Foo's comment");
102}
103
104TEST_F(CompletionStringTest, FunctionWithDefaultParams) {
105 // return_type foo(p1, p2 = 0, p3 = 0)
106 Builder.AddChunk(CodeCompletionString::CK_Comma);
107 Builder.AddTypedTextChunk("p3 = 0");
108 auto *DefaultParam2 = Builder.TakeString();
109
110 Builder.AddChunk(CodeCompletionString::CK_Comma);
111 Builder.AddTypedTextChunk("p2 = 0");
112 Builder.AddOptionalChunk(DefaultParam2);
113 auto *DefaultParam1 = Builder.TakeString();
114
115 Builder.AddResultTypeChunk("return_type");
116 Builder.AddTypedTextChunk("Foo");
117 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
118 Builder.AddPlaceholderChunk("p1");
119 Builder.AddOptionalChunk(DefaultParam1);
120 Builder.AddChunk(CodeCompletionString::CK_RightParen);
121
122 auto *CCS = Builder.TakeString();
123 computeSignature(*CCS);
124 EXPECT_EQ(Signature, "(p1, p2 = 0, p3 = 0)");
125 EXPECT_EQ(Snippet, "(${1:p1})");
126}
127
128TEST_F(CompletionStringTest, EscapeSnippet) {
129 Builder.AddTypedTextChunk("Foo");
130 Builder.AddChunk(CodeCompletionString::CK_LeftParen);
131 Builder.AddPlaceholderChunk("$p}1\\");
132 Builder.AddChunk(CodeCompletionString::CK_RightParen);
133
134 computeSignature(*Builder.TakeString());
135 EXPECT_EQ(Signature, "($p}1\\)");
136 EXPECT_EQ(Snippet, "(${1:\\$p\\}1\\\\})");
137}
138
139TEST_F(CompletionStringTest, SnippetsInPatterns) {
140 auto MakeCCS = [this]() -> const CodeCompletionString & {
141 CodeCompletionBuilder Builder(*Allocator, CCTUInfo);
142 Builder.AddTypedTextChunk("namespace");
143 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
144 Builder.AddPlaceholderChunk("name");
145 Builder.AddChunk(CodeCompletionString::CK_Equal);
146 Builder.AddPlaceholderChunk("target");
147 Builder.AddChunk(CodeCompletionString::CK_SemiColon);
148 return *Builder.TakeString();
149 };
150 computeSignature(MakeCCS());
151 EXPECT_EQ(Snippet, " ${1:name} = ${2:target};");
152
153 // When completing a pattern, the last placeholder holds the cursor position.
154 computeSignature(MakeCCS(),
155 /*ResultKind=*/CodeCompletionResult::ResultKind::RK_Pattern);
156 EXPECT_EQ(Snippet, " ${1:name} = $0;");
157}
158
159TEST_F(CompletionStringTest, IgnoreInformativeQualifier) {
160 Builder.AddTypedTextChunk("X");
161 Builder.AddInformativeChunk("info ok");
162 Builder.AddInformativeChunk("info no no::");
163 computeSignature(*Builder.TakeString());
164 EXPECT_EQ(Signature, "info ok");
165 EXPECT_EQ(Snippet, "");
166}
167
168TEST_F(CompletionStringTest, ObjectiveCMethodNoArguments) {
169 Builder.AddResultTypeChunk("void");
170 Builder.AddTypedTextChunk("methodName");
171
172 auto *CCS = Builder.TakeString();
173 computeSignature(*CCS);
174 EXPECT_EQ(Signature, "");
175 EXPECT_EQ(Snippet, "");
176}
177
178TEST_F(CompletionStringTest, ObjectiveCMethodOneArgument) {
179 Builder.AddResultTypeChunk("void");
180 Builder.AddTypedTextChunk("methodWithArg:");
181 Builder.AddPlaceholderChunk("(type)");
182
183 auto *CCS = Builder.TakeString();
184 computeSignature(*CCS);
185 EXPECT_EQ(Signature, "(type)");
186 EXPECT_EQ(Snippet, "${1:(type)}");
187}
188
189TEST_F(CompletionStringTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
190 Builder.AddResultTypeChunk("int");
191 Builder.AddTypedTextChunk("withFoo:");
192 Builder.AddPlaceholderChunk("(type)");
193 Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
194 Builder.AddTypedTextChunk("bar:");
195 Builder.AddPlaceholderChunk("(type2)");
196
197 auto *CCS = Builder.TakeString();
198 computeSignature(*CCS);
199 EXPECT_EQ(Signature, "(type) bar:(type2)");
200 EXPECT_EQ(Snippet, "${1:(type)} bar:${2:(type2)}");
201}
202
203TEST_F(CompletionStringTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
204 Builder.AddResultTypeChunk("int");
205 Builder.AddInformativeChunk("withFoo:");
206 Builder.AddTypedTextChunk("bar:");
207 Builder.AddPlaceholderChunk("(type2)");
208
209 auto *CCS = Builder.TakeString();
210 computeSignature(*CCS);
211 EXPECT_EQ(Signature, "(type2)");
212 EXPECT_EQ(Snippet, "${1:(type2)}");
213}
214
215} // namespace
216} // namespace clangd
217} // namespace clang
std::string Signature
std::string ReturnType
CodeCompletionBuilder Builder
std::string Snippet
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:221
std::string getDeclComment(const ASTContext &Ctx, const NamedDecl &Decl)
Similar to getDocComment, but returns the comment for a NamedDecl.
std::string getReturnType(const CodeCompletionString &CCS)
Gets detail to be used as the detail field in an LSP completion item.
void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, CodeCompletionResult::ResultKind ResultKind, CXCursorKind CursorKind, std::string *RequiredQualifiers)
Formats the signature for an item, as a display string and snippet.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:36