clang-tools  14.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 
15 namespace clang {
16 namespace clangd {
17 namespace {
18 
19 class CompletionStringTest : public ::testing::Test {
20 public:
21  CompletionStringTest()
22  : Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
24 
25 protected:
26  void computeSignature(const CodeCompletionString &CCS,
27  bool CompletingPattern = false) {
28  Signature.clear();
29  Snippet.clear();
30  getSignature(CCS, &Signature, &Snippet, /*RequiredQualifier=*/nullptr,
31  CompletingPattern);
32  }
33 
34  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
35  CodeCompletionTUInfo CCTUInfo;
36  CodeCompletionBuilder Builder;
37  std::string Signature;
38  std::string Snippet;
39 };
40 
41 TEST_F(CompletionStringTest, ReturnType) {
42  Builder.AddResultTypeChunk("result");
43  Builder.AddResultTypeChunk("redundant result no no");
44  EXPECT_EQ(getReturnType(*Builder.TakeString()), "result");
45 }
46 
47 TEST_F(CompletionStringTest, Documentation) {
48  Builder.addBriefComment("This is ignored");
49  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), "Is this brief?"),
50  "Is this brief?");
51 }
52 
53 TEST_F(CompletionStringTest, DocumentationWithAnnotation) {
54  Builder.addBriefComment("This is ignored");
55  Builder.AddAnnotation("Ano");
56  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), "Is this brief?"),
57  "Annotation: Ano\n\nIs this brief?");
58 }
59 
60 TEST_F(CompletionStringTest, GetDeclCommentBadUTF8) {
61  // <ff> is not a valid byte here, should be replaced by encoded <U+FFFD>.
62  auto TU = TestTU::withCode("/*x\xffy*/ struct X;");
63  auto AST = TU.build();
64  EXPECT_EQ("x\xef\xbf\xbdy",
65  getDeclComment(AST.getASTContext(), findDecl(AST, "X")));
66 }
67 
68 TEST_F(CompletionStringTest, MultipleAnnotations) {
69  Builder.AddAnnotation("Ano1");
70  Builder.AddAnnotation("Ano2");
71  Builder.AddAnnotation("Ano3");
72 
73  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), ""),
74  "Annotations: Ano1 Ano2 Ano3\n");
75 }
76 
77 TEST_F(CompletionStringTest, EmptySignature) {
78  Builder.AddTypedTextChunk("X");
79  Builder.AddResultTypeChunk("result no no");
80  computeSignature(*Builder.TakeString());
81  EXPECT_EQ(Signature, "");
82  EXPECT_EQ(Snippet, "");
83 }
84 
85 TEST_F(CompletionStringTest, Function) {
86  Builder.AddResultTypeChunk("result no no");
87  Builder.addBriefComment("This comment is ignored");
88  Builder.AddTypedTextChunk("Foo");
89  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
90  Builder.AddPlaceholderChunk("p1");
91  Builder.AddChunk(CodeCompletionString::CK_Comma);
92  Builder.AddPlaceholderChunk("p2");
93  Builder.AddChunk(CodeCompletionString::CK_RightParen);
94 
95  auto *CCS = Builder.TakeString();
96  computeSignature(*CCS);
97  EXPECT_EQ(Signature, "(p1, p2)");
98  EXPECT_EQ(Snippet, "(${1:p1}, ${2:p2})");
99  EXPECT_EQ(formatDocumentation(*CCS, "Foo's comment"), "Foo's comment");
100 }
101 
102 TEST_F(CompletionStringTest, FunctionWithDefaultParams) {
103  // return_type foo(p1, p2 = 0, p3 = 0)
104  Builder.AddChunk(CodeCompletionString::CK_Comma);
105  Builder.AddTypedTextChunk("p3 = 0");
106  auto *DefaultParam2 = Builder.TakeString();
107 
108  Builder.AddChunk(CodeCompletionString::CK_Comma);
109  Builder.AddTypedTextChunk("p2 = 0");
110  Builder.AddOptionalChunk(DefaultParam2);
111  auto *DefaultParam1 = Builder.TakeString();
112 
113  Builder.AddResultTypeChunk("return_type");
114  Builder.AddTypedTextChunk("Foo");
115  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
116  Builder.AddPlaceholderChunk("p1");
117  Builder.AddOptionalChunk(DefaultParam1);
118  Builder.AddChunk(CodeCompletionString::CK_RightParen);
119 
120  auto *CCS = Builder.TakeString();
121  computeSignature(*CCS);
122  EXPECT_EQ(Signature, "(p1, p2 = 0, p3 = 0)");
123  EXPECT_EQ(Snippet, "(${1:p1})");
124 }
125 
126 TEST_F(CompletionStringTest, EscapeSnippet) {
127  Builder.AddTypedTextChunk("Foo");
128  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
129  Builder.AddPlaceholderChunk("$p}1\\");
130  Builder.AddChunk(CodeCompletionString::CK_RightParen);
131 
132  computeSignature(*Builder.TakeString());
133  EXPECT_EQ(Signature, "($p}1\\)");
134  EXPECT_EQ(Snippet, "(${1:\\$p\\}1\\\\})");
135 }
136 
137 TEST_F(CompletionStringTest, SnippetsInPatterns) {
138  auto MakeCCS = [this]() -> const CodeCompletionString & {
139  CodeCompletionBuilder Builder(*Allocator, CCTUInfo);
140  Builder.AddTypedTextChunk("namespace");
141  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
142  Builder.AddPlaceholderChunk("name");
143  Builder.AddChunk(CodeCompletionString::CK_Equal);
144  Builder.AddPlaceholderChunk("target");
145  Builder.AddChunk(CodeCompletionString::CK_SemiColon);
146  return *Builder.TakeString();
147  };
148  computeSignature(MakeCCS(), /*CompletingPattern=*/false);
149  EXPECT_EQ(Snippet, " ${1:name} = ${2:target};");
150 
151  // When completing a pattern, the last placeholder holds the cursor position.
152  computeSignature(MakeCCS(), /*CompletingPattern=*/true);
153  EXPECT_EQ(Snippet, " ${1:name} = ${0:target};");
154 }
155 
156 TEST_F(CompletionStringTest, IgnoreInformativeQualifier) {
157  Builder.AddTypedTextChunk("X");
158  Builder.AddInformativeChunk("info ok");
159  Builder.AddInformativeChunk("info no no::");
160  computeSignature(*Builder.TakeString());
161  EXPECT_EQ(Signature, "info ok");
162  EXPECT_EQ(Snippet, "");
163 }
164 
165 TEST_F(CompletionStringTest, ObjectiveCMethodNoArguments) {
166  Builder.AddResultTypeChunk("void");
167  Builder.AddTypedTextChunk("methodName");
168 
169  auto *CCS = Builder.TakeString();
170  computeSignature(*CCS);
171  EXPECT_EQ(Signature, "");
172  EXPECT_EQ(Snippet, "");
173 }
174 
175 TEST_F(CompletionStringTest, ObjectiveCMethodOneArgument) {
176  Builder.AddResultTypeChunk("void");
177  Builder.AddTypedTextChunk("methodWithArg:");
178  Builder.AddPlaceholderChunk("(type)");
179 
180  auto *CCS = Builder.TakeString();
181  computeSignature(*CCS);
182  EXPECT_EQ(Signature, "(type)");
183  EXPECT_EQ(Snippet, "${1:(type)}");
184 }
185 
186 TEST_F(CompletionStringTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
187  Builder.AddResultTypeChunk("int");
188  Builder.AddTypedTextChunk("withFoo:");
189  Builder.AddPlaceholderChunk("(type)");
190  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
191  Builder.AddTypedTextChunk("bar:");
192  Builder.AddPlaceholderChunk("(type2)");
193 
194  auto *CCS = Builder.TakeString();
195  computeSignature(*CCS);
196  EXPECT_EQ(Signature, "(type) bar:(type2)");
197  EXPECT_EQ(Snippet, "${1:(type)} bar:${2:(type2)}");
198 }
199 
200 TEST_F(CompletionStringTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
201  Builder.AddResultTypeChunk("int");
202  Builder.AddInformativeChunk("withFoo:");
203  Builder.AddTypedTextChunk("bar:");
204  Builder.AddPlaceholderChunk("(type2)");
205 
206  auto *CCS = Builder.TakeString();
207  computeSignature(*CCS);
208  EXPECT_EQ(Signature, "(type2)");
209  EXPECT_EQ(Snippet, "${1:(type2)}");
210 }
211 
212 } // namespace
213 } // namespace clangd
214 } // namespace clang
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:74
clang::clangd::findDecl
const NamedDecl & findDecl(ParsedAST &AST, llvm::StringRef QName)
Definition: TestTU.cpp:215
clang::clangd::ParsedAST::getASTContext
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
Definition: ParsedAST.cpp:532
TestTU.h
Signature
std::string Signature
Definition: CodeCompletionStringsTests.cpp:37
clang::clangd::TEST_F
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
Definition: BackgroundIndexTests.cpp:94
CCTUInfo
CodeCompletionTUInfo CCTUInfo
Definition: CodeCompletionStringsTests.cpp:35
Snippet
std::string Snippet
Definition: CodeCompletionStringsTests.cpp:38
clang::clangd::ParsedAST::build
static llvm::Optional< ParsedAST > build(llvm::StringRef Filename, const ParseInputs &Inputs, std::unique_ptr< clang::CompilerInvocation > CI, llvm::ArrayRef< Diag > CompilerInvocationDiags, std::shared_ptr< const PreambleData > Preamble)
Attempts to run Clang and store the parsed AST.
Definition: ParsedAST.cpp:248
clang::clangd::formatDocumentation
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
Definition: CodeCompletionStrings.cpp:242
CodeCompletionStrings.h
Builder
CodeCompletionBuilder Builder
Definition: CodeCompletionStringsTests.cpp:36
clang::clangd::TestTU::withCode
static TestTU withCode(llvm::StringRef Code)
Definition: TestTU.h:37
clang::clangd::getSignature
void getSignature(const CodeCompletionString &CCS, std::string *Signature, std::string *Snippet, std::string *RequiredQualifiers, bool CompletingPattern)
Formats the signature for an item, as a display string and snippet.
Definition: CodeCompletionStrings.cpp:98
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ApplyReplacements.h:27
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:272
ReturnType
std::string ReturnType
Definition: CodeComplete.cpp:433
Allocator
std::shared_ptr< clang::GlobalCodeCompletionAllocator > Allocator
Definition: CodeCompletionStringsTests.cpp:34