1 //===-- SourceCodeTests.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 #include "Annotations.h"
9 #include "Context.h"
10 #include "Protocol.h"
11 #include "SourceCode.h"
12 #include "TestTU.h"
13 #include "clang/Basic/LangOptions.h"
14 #include "clang/Basic/SourceLocation.h"
15 #include "clang/Format/Format.h"
16 #include "llvm/Support/Error.h"
17 #include "llvm/Support/raw_os_ostream.h"
18 #include "llvm/Testing/Support/Annotations.h"
19 #include "llvm/Testing/Support/Error.h"
20 #include "gmock/gmock.h"
21 #include "gtest/gtest.h"
22 #include <tuple>
23 
24 namespace clang {
25 namespace clangd {
26 namespace {
27 
28 using llvm::Failed;
29 using llvm::HasValue;
30 using ::testing::UnorderedElementsAreArray;
31 
32 MATCHER_P2(Pos, Line, Col, "") {
33   return arg.line == int(Line) && arg.character == int(Col);
34 }
35 
36 MATCHER_P(MacroName, Name, "") { return arg.Name == Name; }
37 
38 /// A helper to make tests easier to read.
39 Position position(int line, int character) {
40   Position Pos;
41   Pos.line = line;
42   Pos.character = character;
43   return Pos;
44 }
45 
46 Range range(const std::pair<int, int> p1, const std::pair<int, int> p2) {
47   Range range;
48   range.start = position(p1.first, p1.second);
49   range.end = position(p2.first, p2.second);
50   return range;
51 }
52 
53 TEST(SourceCodeTests, lspLength) {
54   EXPECT_EQ(lspLength(""), 0UL);
55   EXPECT_EQ(lspLength("ascii"), 5UL);
56   // BMP
57   EXPECT_EQ(lspLength("↓"), 1UL);
58   EXPECT_EQ(lspLength("¥"), 1UL);
59   // astral
60   EXPECT_EQ(lspLength("��"), 2UL);
61 
62   WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
63   EXPECT_EQ(lspLength(""), 0UL);
64   EXPECT_EQ(lspLength("ascii"), 5UL);
65   // BMP
66   EXPECT_EQ(lspLength("↓"), 3UL);
67   EXPECT_EQ(lspLength("¥"), 2UL);
68   // astral
69   EXPECT_EQ(lspLength("��"), 4UL);
70 
71   WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
72   EXPECT_EQ(lspLength(""), 0UL);
73   EXPECT_EQ(lspLength("ascii"), 5UL);
74   // BMP
75   EXPECT_EQ(lspLength("↓"), 1UL);
76   EXPECT_EQ(lspLength("¥"), 1UL);
77   // astral
78   EXPECT_EQ(lspLength("��"), 1UL);
79 }
80 
81 // The = → �� below are ASCII (1 byte), BMP (3 bytes), and astral (4 bytes).
82 const char File[] = R"(0:0 = 0
83 1:0 → 8
84 2:0 �� 18)";
85 struct Line {
86   unsigned Number;
87   unsigned Offset;
88   unsigned Length;
89 };
90 Line FileLines[] = {Line{0, 0, 7}, Line{1, 8, 9}, Line{2, 18, 11}};
91 
92 TEST(SourceCodeTests, PositionToOffset) {
93   // line out of bounds
94   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
95   // first line
96   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
97                        llvm::Failed()); // out of range
98   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
99                        llvm::HasValue(0)); // first character
100   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
101                        llvm::HasValue(3)); // middle character
102   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
103                        llvm::HasValue(6)); // last character
104   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
105                        llvm::HasValue(7)); // the newline itself
106   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
107                        llvm::HasValue(7));
108   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
109                        llvm::HasValue(7)); // out of range
110   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
111                        llvm::Failed()); // out of range
112   // middle line
113   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
114                        llvm::Failed()); // out of range
115   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
116                        llvm::HasValue(8)); // first character
117   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
118                        llvm::HasValue(11)); // middle character
119   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
120                        llvm::HasValue(11));
121   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
122                        llvm::HasValue(16)); // last character
123   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
124                        llvm::HasValue(17)); // the newline itself
125   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
126                        llvm::HasValue(17)); // out of range
127   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
128                        llvm::Failed()); // out of range
129   // last line
130   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
131                        llvm::Failed()); // out of range
132   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
133                        llvm::HasValue(18)); // first character
134   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 3)),
135                        llvm::HasValue(21)); // middle character
136   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
137                        llvm::Failed()); // middle of surrogate pair
138   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5)),
139                        llvm::HasValue(26)); // middle of surrogate pair
140   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 6), false),
141                        llvm::HasValue(26)); // end of surrogate pair
142   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
143                        llvm::HasValue(28)); // last character
144   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9)),
145                        llvm::HasValue(29)); // EOF
146   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 10), false),
147                        llvm::Failed()); // out of range
148   // line out of bounds
149   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
150   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
151 
152   // Codepoints are similar, except near astral characters.
153   WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
154   // line out of bounds
155   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
156   // first line
157   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
158                        llvm::Failed()); // out of range
159   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
160                        llvm::HasValue(0)); // first character
161   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
162                        llvm::HasValue(3)); // middle character
163   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
164                        llvm::HasValue(6)); // last character
165   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
166                        llvm::HasValue(7)); // the newline itself
167   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
168                        llvm::HasValue(7));
169   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
170                        llvm::HasValue(7)); // out of range
171   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
172                        llvm::Failed()); // out of range
173   // middle line
174   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
175                        llvm::Failed()); // out of range
176   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
177                        llvm::HasValue(8)); // first character
178   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
179                        llvm::HasValue(11)); // middle character
180   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
181                        llvm::HasValue(11));
182   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
183                        llvm::HasValue(16)); // last character
184   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
185                        llvm::HasValue(17)); // the newline itself
186   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
187                        llvm::HasValue(17)); // out of range
188   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
189                        llvm::Failed()); // out of range
190   // last line
191   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
192                        llvm::Failed()); // out of range
193   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
194                        llvm::HasValue(18)); // first character
195   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 4)),
196                        llvm::HasValue(22)); // Before astral character.
197   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
198                        llvm::HasValue(26)); // after astral character
199   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 7)),
200                        llvm::HasValue(28)); // last character
201   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
202                        llvm::HasValue(29)); // EOF
203   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9), false),
204                        llvm::Failed()); // out of range
205   // line out of bounds
206   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
207   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
208 
209   // Test UTF-8, where transformations are trivial.
210   WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
211   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
212   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
213   for (Line L : FileLines) {
214     EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, -1)),
215                          llvm::Failed()); // out of range
216     for (unsigned I = 0; I <= L.Length; ++I)
217       EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, I)),
218                            llvm::HasValue(L.Offset + I));
219     EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, L.Length+1)),
220                          llvm::HasValue(L.Offset + L.Length));
221     EXPECT_THAT_EXPECTED(
222         positionToOffset(File, position(L.Number, L.Length + 1), false),
223         llvm::Failed()); // out of range
224   }
225 }
226 
227 TEST(SourceCodeTests, OffsetToPosition) {
228   EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
229   EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
230   EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
231   EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
232   EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
233   EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
234   EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
235   EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
236   EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
237   EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
238   EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
239   EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
240   EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
241   EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 6)) << "in astral char";
242   EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 6)) << "after astral char";
243   EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 8)) << "end of last line";
244   EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 9)) << "EOF";
245   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
246 
247   // Codepoints are similar, except near astral characters.
248   WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
249   EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
250   EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
251   EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
252   EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
253   EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
254   EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
255   EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
256   EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
257   EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
258   EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
259   EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
260   EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
261   EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
262   EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 5)) << "in astral char";
263   EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 5)) << "after astral char";
264   EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 7)) << "end of last line";
265   EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 8)) << "EOF";
266   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 8)) << "out of bounds";
267 
268   WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
269   for (Line L : FileLines) {
270     for (unsigned I = 0; I <= L.Length; ++I)
271       EXPECT_THAT(offsetToPosition(File, L.Offset + I), Pos(L.Number, I));
272   }
273   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 11)) << "out of bounds";
274 }
275 
276 TEST(SourceCodeTests, IsRangeConsecutive) {
277   EXPECT_TRUE(isRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
278   EXPECT_FALSE(
279       isRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
280   EXPECT_FALSE(
281       isRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
282 }
283 
284 TEST(SourceCodeTests, SourceLocationInMainFile) {
285   Annotations Source(R"cpp(
286     ^in^t ^foo
287     ^bar
288     ^baz ^() {}  {} {} {} { }^
289 )cpp");
290 
291   SourceManagerForFile Owner("foo.cpp", Source.code());
292   SourceManager &SM = Owner.get();
293 
294   SourceLocation StartOfFile = SM.getLocForStartOfFile(SM.getMainFileID());
295   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 0)),
296                        HasValue(StartOfFile));
297   // End of file.
298   EXPECT_THAT_EXPECTED(
299       sourceLocationInMainFile(SM, position(4, 0)),
300       HasValue(StartOfFile.getLocWithOffset(Source.code().size())));
301   // Column number is too large.
302   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 1)), Failed());
303   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 100)),
304                        Failed());
305   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(4, 1)), Failed());
306   // Line number is too large.
307   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(5, 0)), Failed());
308   // Check all positions mentioned in the test return valid results.
309   for (auto P : Source.points()) {
310     size_t Offset = llvm::cantFail(positionToOffset(Source.code(), P));
311     EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, P),
312                          HasValue(StartOfFile.getLocWithOffset(Offset)));
313   }
314 }
315 
316 TEST(SourceCodeTests, GetBeginningOfIdentifier) {
317   std::string Preamble = R"cpp(
318 struct Bar { int func(); };
319 #define MACRO(X) void f() { X; }
320 Bar* bar;
321   )cpp";
322   // First ^ is the expected beginning, last is the search position.
323   for (const std::string &Text : std::vector<std::string>{
324            "int ^f^oo();", // inside identifier
325            "int ^foo();",  // beginning of identifier
326            "int ^foo^();", // end of identifier
327            "int foo(^);",  // non-identifier
328            "^int foo();",  // beginning of file (can't back up)
329            "int ^f0^0();", // after a digit (lexing at N-1 is wrong)
330            "/^/ comments", // non-interesting token
331            "void f(int abc) { abc ^ ++; }",    // whitespace
332            "void f(int abc) { ^abc^++; }",     // range of identifier
333            "void f(int abc) { ++^abc^; }",     // range of identifier
334            "void f(int abc) { ++^abc; }",      // range of identifier
335            "void f(int abc) { ^+^+abc; }",     // range of operator
336            "void f(int abc) { ^abc^ ++; }",    // range of identifier
337            "void f(int abc) { abc ^++^; }",    // range of operator
338            "void f(int abc) { ^++^ abc; }",    // range of operator
339            "void f(int abc) { ++ ^abc^; }",    // range of identifier
340            "void f(int abc) { ^++^/**/abc; }", // range of operator
341            "void f(int abc) { ++/**/^abc; }",  // range of identifier
342            "void f(int abc) { ^abc^/**/++; }", // range of identifier
343            "void f(int abc) { abc/**/^++; }",  // range of operator
344            "void f() {^ }", // outside of identifier and operator
345            "int ^λλ^λ();",  // UTF-8 handled properly when backing up
346 
347            // identifier in macro arg
348            "MACRO(bar->^func())",  // beginning of identifier
349            "MACRO(bar->^fun^c())", // inside identifier
350            "MACRO(bar->^func^())", // end of identifier
351            "MACRO(^bar->func())",  // begin identifier
352            "MACRO(^bar^->func())", // end identifier
353            "^MACRO(bar->func())",  // beginning of macro name
354            "^MAC^RO(bar->func())", // inside macro name
355            "^MACRO^(bar->func())", // end of macro name
356        }) {
357     std::string WithPreamble = Preamble + Text;
358     Annotations TestCase(WithPreamble);
359     auto AST = TestTU::withCode(TestCase.code()).build();
360     const auto &SourceMgr = AST.getSourceManager();
361     SourceLocation Actual = getBeginningOfIdentifier(
362         TestCase.points().back(), SourceMgr, AST.getASTContext().getLangOpts());
363     Position ActualPos = offsetToPosition(
364         TestCase.code(),
365         SourceMgr.getFileOffset(SourceMgr.getSpellingLoc(Actual)));
366     EXPECT_EQ(TestCase.points().front(), ActualPos) << Text;
367   }
368 }
369 
370 TEST(SourceCodeTests, CollectIdentifiers) {
371   auto Style = format::getLLVMStyle();
372   auto IDs = collectIdentifiers(R"cpp(
373   #include "a.h"
374   void foo() { int xyz; int abc = xyz; return foo(); }
375   )cpp",
376                                 Style);
377   EXPECT_EQ(IDs.size(), 7u);
378   EXPECT_EQ(IDs["include"], 1u);
379   EXPECT_EQ(IDs["void"], 1u);
380   EXPECT_EQ(IDs["int"], 2u);
381   EXPECT_EQ(IDs["xyz"], 2u);
382   EXPECT_EQ(IDs["abc"], 1u);
383   EXPECT_EQ(IDs["return"], 1u);
384   EXPECT_EQ(IDs["foo"], 2u);
385 }
386 
387 TEST(SourceCodeTests, CollectWords) {
388   auto Words = collectWords(R"cpp(
389   #define FIZZ_BUZZ
390   // this is a comment
391   std::string getSomeText() { return "magic word"; }
392   )cpp");
393   std::set<std::string> ActualWords(Words.keys().begin(), Words.keys().end());
394   std::set<std::string> ExpectedWords = {"define",  "fizz",    "buzz",  "this",
395                                          "comment", "string", "some", "text",
396                                          "return",  "magic",  "word"};
397   EXPECT_EQ(ActualWords, ExpectedWords);
398 }
399 
400 TEST(SourceCodeTests, VisibleNamespaces) {
401   std::vector<std::pair<const char *, std::vector<std::string>>> Cases = {
402       {
403           R"cpp(
404             // Using directive resolved against enclosing namespaces.
405             using namespace foo;
406             namespace ns {
407             using namespace bar;
408           )cpp",
409           {"ns", "", "bar", "foo", "ns::bar"},
410       },
411       {
412           R"cpp(
413             // Don't include namespaces we've closed, ignore namespace aliases.
414             using namespace clang;
415             using std::swap;
416             namespace clang {
417             namespace clangd {}
418             namespace ll = ::llvm;
419             }
420             namespace clang {
421           )cpp",
422           {"clang", ""},
423       },
424       {
425           R"cpp(
426             // Using directives visible even if a namespace is reopened.
427             // Ignore anonymous namespaces.
428             namespace foo{ using namespace bar; }
429             namespace foo{ namespace {
430           )cpp",
431           {"foo", "", "bar", "foo::bar"},
432       },
433       {
434           R"cpp(
435             // Mismatched braces
436             namespace foo{}
437             }}}
438             namespace bar{
439           )cpp",
440           {"bar", ""},
441       },
442       {
443           R"cpp(
444             // Namespaces with multiple chunks.
445             namespace a::b {
446               using namespace c::d;
447               namespace e::f {
448           )cpp",
449           {
450               "a::b::e::f",
451               "",
452               "a",
453               "a::b",
454               "a::b::c::d",
455               "a::b::e",
456               "a::c::d",
457               "c::d",
458           },
459       },
460       {
461           "",
462           {""},
463       },
464       {
465           R"cpp(
466             // Parse until EOF
467             namespace bar{})cpp",
468           {""},
469       },
470   };
471   for (const auto& Case : Cases) {
472     EXPECT_EQ(Case.second,
473               visibleNamespaces(Case.first, format::getLLVMStyle()))
474         << Case.first;
475   }
476 }
477 
478 TEST(SourceCodeTests, GetMacros) {
479   Annotations Code(R"cpp(
480      #define MACRO 123
481      int abc = MA^CRO;
482    )cpp");
483   TestTU TU = TestTU::withCode(Code.code());
484   auto AST = TU.build();
485   auto Loc = getBeginningOfIdentifier(Code.point(), AST.getSourceManager(),
486                                       AST.getASTContext().getLangOpts());
487   auto Result = locateMacroAt(Loc, AST.getPreprocessor());
488   ASSERT_TRUE(Result);
489   EXPECT_THAT(*Result, MacroName("MACRO"));
490 }
491 
492 TEST(SourceCodeTests, IsInsideMainFile){
493   TestTU TU;
494   TU.HeaderCode = R"cpp(
495     #define DEFINE_CLASS(X) class X {};
496     #define DEFINE_YY DEFINE_CLASS(YY)
497 
498     class Header1 {};
499     DEFINE_CLASS(Header2)
500     class Header {};
501   )cpp";
502   TU.Code = R"cpp(
503     class Main1 {};
504     DEFINE_CLASS(Main2)
505     DEFINE_YY
506     class Main {};
507   )cpp";
508   TU.ExtraArgs.push_back("-DHeader=Header3");
509   TU.ExtraArgs.push_back("-DMain=Main3");
510   auto AST = TU.build();
511   const auto& SM = AST.getSourceManager();
512   auto DeclLoc = [&AST](llvm::StringRef Name) {
513     return findDecl(AST, Name).getLocation();
514   };
515   for (const auto *HeaderDecl : {"Header1", "Header2", "Header3"})
516     EXPECT_FALSE(isInsideMainFile(DeclLoc(HeaderDecl), SM));
517 
518   for (const auto *MainDecl : {"Main1", "Main2", "Main3", "YY"})
519     EXPECT_TRUE(isInsideMainFile(DeclLoc(MainDecl), SM));
520 }
521 
522 // Test for functions toHalfOpenFileRange and getHalfOpenFileRange
523 TEST(SourceCodeTests, HalfOpenFileRange) {
524   // Each marked range should be the file range of the decl with the same name
525   // and each name should be unique.
526   Annotations Test(R"cpp(
527     #define FOO(X, Y) int Y = ++X
528     #define BAR(X) X + 1
529     #define ECHO(X) X
530 
531     #define BUZZ BAZZ(ADD)
532     #define BAZZ(m) m(1)
533     #define ADD(a) int f = a + 1;
534     template<typename T>
535     class P {};
536 
537     int main() {
538       $a[[P<P<P<P<P<int>>>>> a]];
539       $b[[int b = 1]];
540       $c[[FOO(b, c)]];
541       $d[[FOO(BAR(BAR(b)), d)]];
542       // FIXME: We might want to select everything inside the outer ECHO.
543       ECHO(ECHO($e[[int) ECHO(e]]));
544       // Shouldn't crash.
545       $f[[BUZZ]];
546     }
547   )cpp");
548 
549   ParsedAST AST = TestTU::withCode(Test.code()).build();
550   llvm::errs() << Test.code();
551   const SourceManager &SM = AST.getSourceManager();
552   const LangOptions &LangOpts = AST.getASTContext().getLangOpts();
553   // Turn a SourceLocation into a pair of positions
554   auto SourceRangeToRange = [&SM](SourceRange SrcRange) {
555     return Range{sourceLocToPosition(SM, SrcRange.getBegin()),
556                  sourceLocToPosition(SM, SrcRange.getEnd())};
557   };
558   auto CheckRange = [&](llvm::StringRef Name) {
559     const NamedDecl &Decl = findUnqualifiedDecl(AST, Name);
560     auto FileRange = toHalfOpenFileRange(SM, LangOpts, Decl.getSourceRange());
561     SCOPED_TRACE("Checking range: " + Name);
562     ASSERT_NE(FileRange, llvm::None);
563     Range HalfOpenRange = SourceRangeToRange(*FileRange);
564     EXPECT_EQ(HalfOpenRange, Test.ranges(Name)[0]);
565   };
566 
567   CheckRange("a");
568   CheckRange("b");
569   CheckRange("c");
570   CheckRange("d");
571   CheckRange("e");
572   CheckRange("f");
573 }
574 
575 TEST(SourceCodeTests, HalfOpenFileRangePathologicalPreprocessor) {
576   const char *Case = R"cpp(
577 #define MACRO while(1)
578     void test() {
579 [[#include "Expand.inc"
580         br^eak]];
581     }
582   )cpp";
583   Annotations Test(Case);
584   auto TU = TestTU::withCode(Test.code());
585   TU.AdditionalFiles["Expand.inc"] = "MACRO\n";
586   auto AST = TU.build();
587 
588   const auto &Func = cast<FunctionDecl>(findDecl(AST, "test"));
589   const auto &Body = cast<CompoundStmt>(Func.getBody());
590   const auto &Loop = cast<WhileStmt>(*Body->child_begin());
591   llvm::Optional<SourceRange> Range = toHalfOpenFileRange(
592       AST.getSourceManager(), AST.getASTContext().getLangOpts(),
593       Loop->getSourceRange());
594   ASSERT_TRUE(Range) << "Failed to get file range";
595   EXPECT_EQ(AST.getSourceManager().getFileOffset(Range->getBegin()),
596             Test.llvm::Annotations::range().Begin);
597   EXPECT_EQ(AST.getSourceManager().getFileOffset(Range->getEnd()),
598             Test.llvm::Annotations::range().End);
599 }
600 
601 TEST(SourceCodeTests, IncludeHashLoc) {
602   const char *Case = R"cpp(
603 $foo^#include "foo.inc"
604 #define HEADER "bar.inc"
605   $bar^#  include HEADER
606   )cpp";
607   Annotations Test(Case);
608   auto TU = TestTU::withCode(Test.code());
609   TU.AdditionalFiles["foo.inc"] = "int foo;\n";
610   TU.AdditionalFiles["bar.inc"] = "int bar;\n";
611   auto AST = TU.build();
612   const auto& SM = AST.getSourceManager();
613 
614   FileID Foo = SM.getFileID(findDecl(AST, "foo").getLocation());
615   EXPECT_EQ(SM.getFileOffset(includeHashLoc(Foo, SM)),
616             Test.llvm::Annotations::point("foo"));
617   FileID Bar = SM.getFileID(findDecl(AST, "bar").getLocation());
618   EXPECT_EQ(SM.getFileOffset(includeHashLoc(Bar, SM)),
619             Test.llvm::Annotations::point("bar"));
620 }
621 
622 TEST(SourceCodeTests, GetEligiblePoints) {
623   constexpr struct {
624     const char *Code;
625     const char *FullyQualifiedName;
626     const char *EnclosingNamespace;
627   } Cases[] = {
628       {R"cpp(// FIXME: We should also mark positions before and after
629                  //declarations/definitions as eligible.
630               namespace ns1 {
631               namespace a { namespace ns2 {} }
632               namespace ns2 {^
633               void foo();
634               namespace {}
635               void bar() {}
636               namespace ns3 {}
637               class T {};
638               ^}
639               using namespace ns2;
640               })cpp",
641        "ns1::ns2::symbol", "ns1::ns2::"},
642       {R"cpp(
643               namespace ns1 {^
644               namespace a { namespace ns2 {} }
645               namespace b {}
646               namespace ns {}
647               ^})cpp",
648        "ns1::ns2::symbol", "ns1::"},
649       {R"cpp(
650               namespace x {
651               namespace a { namespace ns2 {} }
652               namespace b {}
653               namespace ns {}
654               }^)cpp",
655        "ns1::ns2::symbol", ""},
656       {R"cpp(
657               namespace ns1 {
658               namespace ns2 {^^}
659               namespace b {}
660               namespace ns2 {^^}
661               }
662               namespace ns1 {namespace ns2 {^^}})cpp",
663        "ns1::ns2::symbol", "ns1::ns2::"},
664       {R"cpp(
665               namespace ns1 {^
666               namespace ns {}
667               namespace b {}
668               namespace ns {}
669               ^}
670               namespace ns1 {^namespace ns {}^})cpp",
671        "ns1::ns2::symbol", "ns1::"},
672   };
673   for (auto Case : Cases) {
674     Annotations Test(Case.Code);
675 
676     auto Res = getEligiblePoints(Test.code(), Case.FullyQualifiedName,
677                                  format::getLLVMStyle());
678     EXPECT_THAT(Res.EligiblePoints, testing::ElementsAreArray(Test.points()))
679         << Test.code();
680     EXPECT_EQ(Res.EnclosingNamespace, Case.EnclosingNamespace) << Test.code();
681   }
682 }
683 
684 TEST(SourceCodeTests, IdentifierRanges) {
685   Annotations Code(R"cpp(
686    class [[Foo]] {};
687    // Foo
688    /* Foo */
689    void f([[Foo]]* foo1) {
690      [[Foo]] foo2;
691      auto S = [[Foo]]();
692 // cross-line identifier is not supported.
693 F\
694 o\
695 o foo2;
696    }
697   )cpp");
698   LangOptions LangOpts;
699   LangOpts.CPlusPlus = true;
700   EXPECT_EQ(Code.ranges(),
701             collectIdentifierRanges("Foo", Code.code(), LangOpts));
702 }
703 
704 } // namespace
705 } // namespace clangd
706 } // namespace clang
707