clang-tools  10.0.0svn
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 "clang/Sema/CodeCompleteConsumer.h"
11 #include "gmock/gmock.h"
12 #include "gtest/gtest.h"
13 
14 namespace clang {
15 namespace clangd {
16 namespace {
17 
18 class CompletionStringTest : public ::testing::Test {
19 public:
20  CompletionStringTest()
21  : Allocator(std::make_shared<clang::GlobalCodeCompletionAllocator>()),
23 
24 protected:
25  void computeSignature(const CodeCompletionString &CCS,
26  bool CompletingPattern = false) {
27  Signature.clear();
28  Snippet.clear();
29  getSignature(CCS, &Signature, &Snippet, /*RequiredQualifier=*/nullptr,
30  CompletingPattern);
31  }
32 
33  std::shared_ptr<clang::GlobalCodeCompletionAllocator> Allocator;
34  CodeCompletionTUInfo CCTUInfo;
35  CodeCompletionBuilder Builder;
36  std::string Signature;
37  std::string Snippet;
38 };
39 
40 TEST_F(CompletionStringTest, ReturnType) {
41  Builder.AddResultTypeChunk("result");
42  Builder.AddResultTypeChunk("redundant result no no");
43  EXPECT_EQ(getReturnType(*Builder.TakeString()), "result");
44 }
45 
46 TEST_F(CompletionStringTest, Documentation) {
47  Builder.addBriefComment("This is ignored");
48  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), "Is this brief?"),
49  "Is this brief?");
50 }
51 
52 TEST_F(CompletionStringTest, DocumentationWithAnnotation) {
53  Builder.addBriefComment("This is ignored");
54  Builder.AddAnnotation("Ano");
55  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), "Is this brief?"),
56  "Annotation: Ano\n\nIs this brief?");
57 }
58 
59 TEST_F(CompletionStringTest, MultipleAnnotations) {
60  Builder.AddAnnotation("Ano1");
61  Builder.AddAnnotation("Ano2");
62  Builder.AddAnnotation("Ano3");
63 
64  EXPECT_EQ(formatDocumentation(*Builder.TakeString(), ""),
65  "Annotations: Ano1 Ano2 Ano3\n");
66 }
67 
68 TEST_F(CompletionStringTest, EmptySignature) {
69  Builder.AddTypedTextChunk("X");
70  Builder.AddResultTypeChunk("result no no");
71  computeSignature(*Builder.TakeString());
72  EXPECT_EQ(Signature, "");
73  EXPECT_EQ(Snippet, "");
74 }
75 
76 TEST_F(CompletionStringTest, Function) {
77  Builder.AddResultTypeChunk("result no no");
78  Builder.addBriefComment("This comment is ignored");
79  Builder.AddTypedTextChunk("Foo");
80  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
81  Builder.AddPlaceholderChunk("p1");
82  Builder.AddChunk(CodeCompletionString::CK_Comma);
83  Builder.AddPlaceholderChunk("p2");
84  Builder.AddChunk(CodeCompletionString::CK_RightParen);
85 
86  auto *CCS = Builder.TakeString();
87  computeSignature(*CCS);
88  EXPECT_EQ(Signature, "(p1, p2)");
89  EXPECT_EQ(Snippet, "(${1:p1}, ${2:p2})");
90  EXPECT_EQ(formatDocumentation(*CCS, "Foo's comment"), "Foo's comment");
91 }
92 
93 TEST_F(CompletionStringTest, FunctionWithDefaultParams) {
94  // return_type foo(p1, p2 = 0, p3 = 0)
95  Builder.AddChunk(CodeCompletionString::CK_Comma);
96  Builder.AddTypedTextChunk("p3 = 0");
97  auto *DefaultParam2 = Builder.TakeString();
98 
99  Builder.AddChunk(CodeCompletionString::CK_Comma);
100  Builder.AddTypedTextChunk("p2 = 0");
101  Builder.AddOptionalChunk(DefaultParam2);
102  auto *DefaultParam1 = Builder.TakeString();
103 
104  Builder.AddResultTypeChunk("return_type");
105  Builder.AddTypedTextChunk("Foo");
106  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
107  Builder.AddPlaceholderChunk("p1");
108  Builder.AddOptionalChunk(DefaultParam1);
109  Builder.AddChunk(CodeCompletionString::CK_RightParen);
110 
111  auto *CCS = Builder.TakeString();
112  computeSignature(*CCS);
113  EXPECT_EQ(Signature, "(p1, p2 = 0, p3 = 0)");
114  EXPECT_EQ(Snippet, "(${1:p1})");
115 }
116 
117 TEST_F(CompletionStringTest, EscapeSnippet) {
118  Builder.AddTypedTextChunk("Foo");
119  Builder.AddChunk(CodeCompletionString::CK_LeftParen);
120  Builder.AddPlaceholderChunk("$p}1\\");
121  Builder.AddChunk(CodeCompletionString::CK_RightParen);
122 
123  computeSignature(*Builder.TakeString());
124  EXPECT_EQ(Signature, "($p}1\\)");
125  EXPECT_EQ(Snippet, "(${1:\\$p\\}1\\\\})");
126 }
127 
128 TEST_F(CompletionStringTest, SnippetsInPatterns) {
129  auto MakeCCS = [this]() -> const CodeCompletionString & {
130  CodeCompletionBuilder Builder(*Allocator, CCTUInfo);
131  Builder.AddTypedTextChunk("namespace");
132  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
133  Builder.AddPlaceholderChunk("name");
134  Builder.AddChunk(CodeCompletionString::CK_Equal);
135  Builder.AddPlaceholderChunk("target");
136  Builder.AddChunk(CodeCompletionString::CK_SemiColon);
137  return *Builder.TakeString();
138  };
139  computeSignature(MakeCCS(), /*CompletingPattern=*/false);
140  EXPECT_EQ(Snippet, " ${1:name} = ${2:target};");
141 
142  // When completing a pattern, the last placeholder holds the cursor position.
143  computeSignature(MakeCCS(), /*CompletingPattern=*/true);
144  EXPECT_EQ(Snippet, " ${1:name} = ${0:target};");
145 }
146 
147 TEST_F(CompletionStringTest, IgnoreInformativeQualifier) {
148  Builder.AddTypedTextChunk("X");
149  Builder.AddInformativeChunk("info ok");
150  Builder.AddInformativeChunk("info no no::");
151  computeSignature(*Builder.TakeString());
152  EXPECT_EQ(Signature, "info ok");
153  EXPECT_EQ(Snippet, "");
154 }
155 
156 TEST_F(CompletionStringTest, ObjectiveCMethodNoArguments) {
157  Builder.AddResultTypeChunk("void");
158  Builder.AddTypedTextChunk("methodName");
159 
160  auto *CCS = Builder.TakeString();
161  computeSignature(*CCS);
162  EXPECT_EQ(Signature, "");
163  EXPECT_EQ(Snippet, "");
164 }
165 
166 TEST_F(CompletionStringTest, ObjectiveCMethodOneArgument) {
167  Builder.AddResultTypeChunk("void");
168  Builder.AddTypedTextChunk("methodWithArg:");
169  Builder.AddPlaceholderChunk("(type)");
170 
171  auto *CCS = Builder.TakeString();
172  computeSignature(*CCS);
173  EXPECT_EQ(Signature, "(type)");
174  EXPECT_EQ(Snippet, "${1:(type)}");
175 }
176 
177 TEST_F(CompletionStringTest, ObjectiveCMethodTwoArgumentsFromBeginning) {
178  Builder.AddResultTypeChunk("int");
179  Builder.AddTypedTextChunk("withFoo:");
180  Builder.AddPlaceholderChunk("(type)");
181  Builder.AddChunk(CodeCompletionString::CK_HorizontalSpace);
182  Builder.AddTypedTextChunk("bar:");
183  Builder.AddPlaceholderChunk("(type2)");
184 
185  auto *CCS = Builder.TakeString();
186  computeSignature(*CCS);
187  EXPECT_EQ(Signature, "(type) bar:(type2)");
188  EXPECT_EQ(Snippet, "${1:(type)} bar:${2:(type2)}");
189 }
190 
191 TEST_F(CompletionStringTest, ObjectiveCMethodTwoArgumentsFromMiddle) {
192  Builder.AddResultTypeChunk("int");
193  Builder.AddInformativeChunk("withFoo:");
194  Builder.AddTypedTextChunk("bar:");
195  Builder.AddPlaceholderChunk("(type2)");
196 
197  auto *CCS = Builder.TakeString();
198  computeSignature(*CCS);
199  EXPECT_EQ(Signature, "(type2)");
200  EXPECT_EQ(Snippet, "${1:(type2)}");
201 }
202 
203 } // namespace
204 } // namespace clangd
205 } // namespace clang
std::shared_ptr< clang::GlobalCodeCompletionAllocator > Allocator
std::string getReturnType(const CodeCompletionString &CCS)
Gets detail to be used as the detail field in an LSP completion item.
TEST_F(BackgroundIndexTest, NoCrashOnErrorFile)
std::string formatDocumentation(const CodeCompletionString &CCS, llvm::StringRef DocComment)
Assembles formatted documentation for a completion result.
std::string ReturnType
std::string Signature
CodeCompletionBuilder Builder
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
CodeCompletionTUInfo CCTUInfo
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.