1 //=== unittests/Sema/CodeCompleteTest.cpp - Code Complete tests ==============//
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
7 //===----------------------------------------------------------------------===//
9 #include "clang/Frontend/CompilerInstance.h"
10 #include "clang/Frontend/FrontendActions.h"
11 #include "clang/Lex/Preprocessor.h"
12 #include "clang/Parse/ParseAST.h"
13 #include "clang/Sema/Sema.h"
14 #include "clang/Sema/SemaDiagnostic.h"
15 #include "clang/Tooling/Tooling.h"
16 #include "llvm/Testing/Annotations/Annotations.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
24 using namespace clang
;
25 using namespace clang::tooling
;
26 using ::testing::AllOf
;
27 using ::testing::Contains
;
28 using ::testing::Each
;
29 using ::testing::UnorderedElementsAre
;
31 const char TestCCName
[] = "test.cc";
33 struct CompletionContext
{
34 std::vector
<std::string
> VisitedNamespaces
;
35 std::string PreferredType
;
36 // String representation of std::ptrdiff_t on a given platform. This is a hack
37 // to properly account for different configurations of clang.
38 std::string PtrDiffType
;
41 struct CompletedFunctionDecl
{
46 MATCHER_P(named
, name
, "") { return arg
.Name
== name
; }
47 MATCHER_P(isStatic
, value
, "") { return arg
.IsStatic
== value
; }
48 MATCHER_P(canBeCall
, value
, "") { return arg
.CanBeCall
== value
; }
50 class SaveCompletedFunctions
: public CodeCompleteConsumer
{
52 SaveCompletedFunctions(std::vector
<CompletedFunctionDecl
> &CompletedFuncDecls
)
53 : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}),
54 CompletedFuncDecls(CompletedFuncDecls
),
55 CCTUInfo(std::make_shared
<GlobalCodeCompletionAllocator
>()) {}
57 void ProcessCodeCompleteResults(Sema
&S
, CodeCompletionContext Context
,
58 CodeCompletionResult
*Results
,
59 unsigned NumResults
) override
{
60 for (unsigned I
= 0; I
< NumResults
; ++I
) {
62 if (R
.Kind
== CodeCompletionResult::RK_Declaration
) {
63 auto *ND
= R
.getDeclaration();
64 if (auto *Template
= llvm::dyn_cast
<FunctionTemplateDecl
>(ND
))
65 ND
= Template
->getTemplatedDecl();
66 if (const auto *FD
= llvm::dyn_cast
<FunctionDecl
>(ND
)) {
67 CompletedFunctionDecl D
;
68 D
.Name
= FD
->getNameAsString();
69 D
.CanBeCall
= R
.FunctionCanBeCall
;
70 D
.IsStatic
= FD
->isStatic();
71 CompletedFuncDecls
.emplace_back(std::move(D
));
78 CodeCompletionAllocator
&getAllocator() override
{
79 return CCTUInfo
.getAllocator();
82 CodeCompletionTUInfo
&getCodeCompletionTUInfo() override
{ return CCTUInfo
; }
84 std::vector
<CompletedFunctionDecl
> &CompletedFuncDecls
;
86 CodeCompletionTUInfo CCTUInfo
;
89 class VisitedContextFinder
: public CodeCompleteConsumer
{
91 VisitedContextFinder(CompletionContext
&ResultCtx
)
92 : CodeCompleteConsumer(/*CodeCompleteOpts=*/{}), ResultCtx(ResultCtx
),
93 CCTUInfo(std::make_shared
<GlobalCodeCompletionAllocator
>()) {}
95 void ProcessCodeCompleteResults(Sema
&S
, CodeCompletionContext Context
,
96 CodeCompletionResult
*Results
,
97 unsigned NumResults
) override
{
98 ResultCtx
.VisitedNamespaces
=
99 getVisitedNamespace(Context
.getVisitedContexts());
100 ResultCtx
.PreferredType
= Context
.getPreferredType().getAsString();
101 ResultCtx
.PtrDiffType
=
102 S
.getASTContext().getPointerDiffType().getAsString();
105 CodeCompletionAllocator
&getAllocator() override
{
106 return CCTUInfo
.getAllocator();
109 CodeCompletionTUInfo
&getCodeCompletionTUInfo() override
{ return CCTUInfo
; }
112 std::vector
<std::string
> getVisitedNamespace(
113 CodeCompletionContext::VisitedContextSet VisitedContexts
) const {
114 std::vector
<std::string
> NSNames
;
115 for (const auto *Context
: VisitedContexts
)
116 if (const auto *NS
= llvm::dyn_cast
<NamespaceDecl
>(Context
))
117 NSNames
.push_back(NS
->getQualifiedNameAsString());
121 CompletionContext
&ResultCtx
;
122 CodeCompletionTUInfo CCTUInfo
;
125 class CodeCompleteAction
: public SyntaxOnlyAction
{
127 CodeCompleteAction(ParsedSourceLocation P
, CodeCompleteConsumer
*Consumer
)
128 : CompletePosition(std::move(P
)), Consumer(Consumer
) {}
130 bool BeginInvocation(CompilerInstance
&CI
) override
{
131 CI
.getFrontendOpts().CodeCompletionAt
= CompletePosition
;
132 CI
.setCodeCompletionConsumer(Consumer
);
137 // 1-based code complete position <Line, Col>;
138 ParsedSourceLocation CompletePosition
;
139 CodeCompleteConsumer
*Consumer
;
142 ParsedSourceLocation
offsetToPosition(llvm::StringRef Code
, size_t Offset
) {
143 Offset
= std::min(Code
.size(), Offset
);
144 StringRef Before
= Code
.substr(0, Offset
);
145 int Lines
= Before
.count('\n');
146 size_t PrevNL
= Before
.rfind('\n');
147 size_t StartOfLine
= (PrevNL
== StringRef::npos
) ? 0 : (PrevNL
+ 1);
148 return {TestCCName
, static_cast<unsigned>(Lines
+ 1),
149 static_cast<unsigned>(Offset
- StartOfLine
+ 1)};
152 CompletionContext
runCompletion(StringRef Code
, size_t Offset
) {
153 CompletionContext ResultCtx
;
154 clang::tooling::runToolOnCodeWithArgs(
155 std::make_unique
<CodeCompleteAction
>(offsetToPosition(Code
, Offset
),
156 new VisitedContextFinder(ResultCtx
)),
157 Code
, {"-std=c++11"}, TestCCName
);
161 CompletionContext
runCodeCompleteOnCode(StringRef AnnotatedCode
) {
162 llvm::Annotations
A(AnnotatedCode
);
163 return runCompletion(A
.code(), A
.point());
166 std::vector
<std::string
>
167 collectPreferredTypes(StringRef AnnotatedCode
,
168 std::string
*PtrDiffType
= nullptr) {
169 llvm::Annotations
A(AnnotatedCode
);
170 std::vector
<std::string
> Types
;
171 for (size_t Point
: A
.points()) {
172 auto Results
= runCompletion(A
.code(), Point
);
174 assert(PtrDiffType
->empty() || *PtrDiffType
== Results
.PtrDiffType
);
175 *PtrDiffType
= Results
.PtrDiffType
;
177 Types
.push_back(Results
.PreferredType
);
182 std::vector
<CompletedFunctionDecl
>
183 CollectCompletedFunctions(StringRef Code
, std::size_t Point
) {
184 std::vector
<CompletedFunctionDecl
> Result
;
185 clang::tooling::runToolOnCodeWithArgs(
186 std::make_unique
<CodeCompleteAction
>(offsetToPosition(Code
, Point
),
187 new SaveCompletedFunctions(Result
)),
188 Code
, {"-std=c++11"}, TestCCName
);
192 TEST(SemaCodeCompleteTest
, FunctionCanBeCall
) {
193 llvm::Annotations
Code(R
"cpp(
195 static int staticMethod();
197 template <typename T, typename U, typename V = int>
199 template <typename T, int U = 3>
200 static T staticGeneric();
208 struct Derived : Foo {
221 ; // Prevent parsing as 'f.f'
227 d.Derived::$canBeCall^
235 ; // Prevent parsing as 'f.f'
241 d.Derived::$canBeCall^
245 for (const auto &P
: Code
.points("canBeCall")) {
246 auto Results
= CollectCompletedFunctions(Code
.code(), P
);
247 EXPECT_THAT(Results
, Contains(AllOf(named("method"), isStatic(false),
249 EXPECT_THAT(Results
, Contains(AllOf(named("generic"), isStatic(false),
253 for (const auto &P
: Code
.points("cannotBeCall")) {
254 auto Results
= CollectCompletedFunctions(Code
.code(), P
);
255 EXPECT_THAT(Results
, Contains(AllOf(named("method"), isStatic(false),
257 EXPECT_THAT(Results
, Contains(AllOf(named("generic"), isStatic(false),
261 // static method can always be a call
262 for (const auto &P
: Code
.points()) {
263 auto Results
= CollectCompletedFunctions(Code
.code(), P
);
264 EXPECT_THAT(Results
, Contains(AllOf(named("staticMethod"), isStatic(true),
266 EXPECT_THAT(Results
, Contains(AllOf(named("staticGeneric"), isStatic(true),
271 TEST(SemaCodeCompleteTest
, VisitedNSForValidQualifiedId
) {
272 auto VisitedNS
= runCodeCompleteOnCode(R
"cpp(
276 namespace ns3 { namespace nns3 {} }
280 namespace ns4 {} // not visited
281 namespace { using namespace ns2; }
282 inline namespace bar { using namespace ns3::nns3; }
284 namespace ns { foo::^ }
287 EXPECT_THAT(VisitedNS
, UnorderedElementsAre("foo", "ns1", "ns2", "ns3::nns3",
288 "foo::(anonymous)"));
291 TEST(SemaCodeCompleteTest
, VisitedNSForInvalidQualifiedId
) {
292 auto VisitedNS
= runCodeCompleteOnCode(R
"cpp(
300 EXPECT_THAT(VisitedNS
, UnorderedElementsAre("ns1", "na"));
303 TEST(SemaCodeCompleteTest
, VisitedNSWithoutQualifier
) {
304 auto VisitedNS
= runCodeCompleteOnCode(R
"cpp(
312 EXPECT_THAT(VisitedNS
, UnorderedElementsAre("n1", "n1::n2"));
315 TEST(PreferredTypeTest
, BinaryExpr
) {
316 // Check various operations for arithmetic types.
317 StringRef Code
= R
"cpp(
320 x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
321 x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
323 EXPECT_THAT(collectPreferredTypes(Code
), Each("int"));
328 x += ^10; x -= ^10; x *= ^10; x /= ^10; x %= ^10;
329 x + ^10; x - ^10; x * ^10; x / ^10; x % ^10;
331 EXPECT_THAT(collectPreferredTypes(Code
), Each("float"));
335 void test(int *ptr) {
339 EXPECT_THAT(collectPreferredTypes(Code
), Each("int *"));
342 void test(int *ptr) {
349 auto Types
= collectPreferredTypes(Code
, &PtrDiff
);
350 EXPECT_THAT(Types
, Each(PtrDiff
));
353 // Comparison operators.
356 i <= ^1; i < ^1; i >= ^1; i > ^1; i == ^1; i != ^1;
359 EXPECT_THAT(collectPreferredTypes(Code
), Each("int"));
362 void test(int *ptr) {
363 ptr <= ^ptr; ptr < ^ptr; ptr >= ^ptr; ptr > ^ptr;
364 ptr == ^ptr; ptr != ^ptr;
367 EXPECT_THAT(collectPreferredTypes(Code
), Each("int *"));
369 // Relational operations.
371 void test(int i, int *ptr) {
373 ptr && ^1; ptr || ^1;
376 EXPECT_THAT(collectPreferredTypes(Code
), Each("_Bool"));
378 // Bitwise operations.
380 void test(long long ll) {
384 EXPECT_THAT(collectPreferredTypes(Code
), Each("long long"));
392 EXPECT_THAT(collectPreferredTypes(Code
), Each("A"));
397 // This is technically illegal with the 'enum class' without overloaded
398 // operators, but we pretend it's fine.
402 EXPECT_THAT(collectPreferredTypes(Code
), Each("A"));
406 void test(int i, long long ll) {
413 EXPECT_THAT(collectPreferredTypes(Code
), Each("int"));
415 // Comma does not provide any useful information.
418 void test(int i, int* ptr, Cls x) {
424 EXPECT_THAT(collectPreferredTypes(Code
), Each("NULL TYPE"));
426 // User-defined types do not take operator overloading into account.
427 // However, they provide heuristics for some common cases.
431 // we assume arithmetic and comparions ops take the same type.
432 c + ^c; c - ^c; c * ^c; c / ^c; c % ^c;
433 c == ^c; c != ^c; c < ^c; c <= ^c; c > ^c; c >= ^c;
434 // same for the assignments.
435 c = ^c; c += ^c; c -= ^c; c *= ^c; c /= ^c; c %= ^c;
438 EXPECT_THAT(collectPreferredTypes(Code
), Each("Cls"));
443 // we assume relational ops operate on bools.
447 EXPECT_THAT(collectPreferredTypes(Code
), Each("_Bool"));
452 // we make no assumptions about the following operators, since they are
453 // often overloaded with a non-standard meaning.
454 c << ^c; c >> ^c; c | ^c; c & ^c;
455 c <<= ^c; c >>= ^c; c |= ^c; c &= ^c;
458 EXPECT_THAT(collectPreferredTypes(Code
), Each("NULL TYPE"));
461 TEST(PreferredTypeTest
, Members
) {
462 StringRef Code
= R
"cpp(
469 a = ^vector().^clone().^begin();
472 EXPECT_THAT(collectPreferredTypes(Code
), Each("int *"));
475 TEST(PreferredTypeTest
, Conditions
) {
476 StringRef Code
= R
"cpp(
482 if (^vector().^empty()) {}
483 while (^vector().^empty()) {}
484 for (; ^vector().^empty();) {}
487 EXPECT_THAT(collectPreferredTypes(Code
), Each("_Bool"));
490 TEST(PreferredTypeTest
, InitAndAssignment
) {
491 StringRef Code
= R
"cpp(
497 const int* x = ^vector().^begin();
498 x = ^vector().^begin();
500 if (const int* y = ^vector().^begin()) {}
503 EXPECT_THAT(collectPreferredTypes(Code
), Each("const int *"));
506 TEST(PreferredTypeTest
, UnaryExprs
) {
507 StringRef Code
= R
"cpp(
508 void test(long long a) {
515 EXPECT_THAT(collectPreferredTypes(Code
), Each("long long"));
518 void test(int a, int *ptr) {
528 EXPECT_THAT(collectPreferredTypes(Code
), Each("_Bool"));
535 EXPECT_THAT(collectPreferredTypes(Code
), Each("const int"));
543 EXPECT_THAT(collectPreferredTypes(Code
), Each("int *"));
554 TEST(PreferredTypeTest
, ParenExpr
) {
555 StringRef Code
= R
"cpp(
556 const int *i = ^(^(^(^10)));
558 EXPECT_THAT(collectPreferredTypes(Code
), Each("const int *"));
561 TEST(PreferredTypeTest
, FunctionArguments
) {
562 StringRef Code
= R
"cpp(
563 void foo(const int*);
565 void bar(const int*);
566 void bar(const int*, int b);
572 foo(^(^(^(^vec^tor^().^da^ta^()))));
573 bar(^(^(^(^vec^tor^().^da^ta^()))));
576 EXPECT_THAT(collectPreferredTypes(Code
), Each("const int *"));
579 void bar(int, volatile double *);
580 void bar(int, volatile double *, int, int);
586 struct class_members {
587 void bar(int, volatile double *);
588 void bar(int, volatile double *, int, int);
591 bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
592 class_members().bar(10, ^(^(^(^vec^tor^().^da^ta^()))));
595 EXPECT_THAT(collectPreferredTypes(Code
), Each("volatile double *"));
602 void accepts_vector(ns::vector);
605 accepts_vector(^::^ns::^vector());
608 EXPECT_THAT(collectPreferredTypes(Code
), Each("ns::vector"));
612 struct vector { using self = vector; };
614 void accepts_vector(vector<int>);
618 accepts_vector(^::^vector<decltype(foo(1))>::^self);
621 EXPECT_THAT(collectPreferredTypes(Code
), Each("vector<int>"));
624 TEST(PreferredTypeTest
, NoCrashOnInvalidTypes
) {
625 StringRef Code
= R
"cpp(
626 auto x = decltype(&1)(^);
627 auto y = new decltype(&1)(^);
628 // GNU decimal type extension is not supported in clang.
629 auto z = new _Decimal128(^);
630 void foo() { (void)(foo)(^); }
632 EXPECT_THAT(collectPreferredTypes(Code
), Each("NULL TYPE"));