xref: /llvm-project/clang-tools-extra/clangd/unittests/SourceCodeTests.cpp (revision bca3e24139cc301d7deae56a020057cf657035b6)
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 "Protocol.h"
10 #include "SourceCode.h"
11 #include "TestTU.h"
12 #include "support/Context.h"
13 #include "clang/Basic/LangOptions.h"
14 #include "clang/Basic/SourceLocation.h"
15 #include "clang/Basic/TokenKinds.h"
16 #include "clang/Format/Format.h"
17 #include "llvm/Support/Error.h"
18 #include "llvm/Support/raw_os_ostream.h"
19 #include "llvm/Testing/Support/Annotations.h"
20 #include "llvm/Testing/Support/Error.h"
21 #include "gmock/gmock.h"
22 #include "gtest/gtest.h"
23 #include <tuple>
24 
25 namespace clang {
26 namespace clangd {
27 namespace {
28 
29 using llvm::Failed;
30 using llvm::FailedWithMessage;
31 using llvm::HasValue;
32 
33 MATCHER_P2(Pos, Line, Col, "") {
34   return arg.line == int(Line) && arg.character == int(Col);
35 }
36 
37 MATCHER_P(MacroName, Name, "") { return arg.Name == Name; }
38 
39 /// A helper to make tests easier to read.
40 Position position(int Line, int Character) {
41   Position Pos;
42   Pos.line = Line;
43   Pos.character = Character;
44   return Pos;
45 }
46 
47 TEST(SourceCodeTests, lspLength) {
48   EXPECT_EQ(lspLength(""), 0UL);
49   EXPECT_EQ(lspLength("ascii"), 5UL);
50   // BMP
51   EXPECT_EQ(lspLength("↓"), 1UL);
52   EXPECT_EQ(lspLength("¥"), 1UL);
53   // astral
54   EXPECT_EQ(lspLength("��"), 2UL);
55 
56   WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
57   EXPECT_EQ(lspLength(""), 0UL);
58   EXPECT_EQ(lspLength("ascii"), 5UL);
59   // BMP
60   EXPECT_EQ(lspLength("↓"), 3UL);
61   EXPECT_EQ(lspLength("¥"), 2UL);
62   // astral
63   EXPECT_EQ(lspLength("��"), 4UL);
64 
65   WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
66   EXPECT_EQ(lspLength(""), 0UL);
67   EXPECT_EQ(lspLength("ascii"), 5UL);
68   // BMP
69   EXPECT_EQ(lspLength("↓"), 1UL);
70   EXPECT_EQ(lspLength("¥"), 1UL);
71   // astral
72   EXPECT_EQ(lspLength("��"), 1UL);
73 }
74 
75 TEST(SourceCodeTests, lspLengthBadUTF8) {
76   // Results are not well-defined if source file isn't valid UTF-8.
77   // However we shouldn't crash or return something totally wild.
78   const char *BadUTF8[] = {"\xa0", "\xff\xff\xff\xff\xff"};
79 
80   for (OffsetEncoding Encoding :
81        {OffsetEncoding::UTF8, OffsetEncoding::UTF16, OffsetEncoding::UTF32}) {
82     WithContextValue UTF32(kCurrentOffsetEncoding, Encoding);
83     for (const char *Bad : BadUTF8) {
84       EXPECT_GE(lspLength(Bad), 0u);
85       EXPECT_LE(lspLength(Bad), strlen(Bad));
86     }
87   }
88 }
89 
90 // The = → �� below are ASCII (1 byte), BMP (3 bytes), and astral (4 bytes).
91 const char File[] = R"(0:0 = 0
92 1:0 → 8
93 2:0 �� 18)";
94 struct Line {
95   unsigned Number;
96   unsigned Offset;
97   unsigned Length;
98 };
99 Line FileLines[] = {Line{0, 0, 7}, Line{1, 8, 9}, Line{2, 18, 11}};
100 
101 TEST(SourceCodeTests, PositionToOffset) {
102   // line out of bounds
103   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
104   // first line
105   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
106                        llvm::Failed()); // out of range
107   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
108                        llvm::HasValue(0)); // first character
109   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
110                        llvm::HasValue(3)); // middle character
111   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
112                        llvm::HasValue(6)); // last character
113   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
114                        llvm::HasValue(7)); // the newline itself
115   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
116                        llvm::HasValue(7));
117   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
118                        llvm::HasValue(7)); // out of range
119   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
120                        llvm::Failed()); // out of range
121   // middle line
122   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
123                        llvm::Failed()); // out of range
124   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
125                        llvm::HasValue(8)); // first character
126   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
127                        llvm::HasValue(11)); // middle character
128   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
129                        llvm::HasValue(11));
130   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
131                        llvm::HasValue(16)); // last character
132   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
133                        llvm::HasValue(17)); // the newline itself
134   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
135                        llvm::HasValue(17)); // out of range
136   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
137                        llvm::Failed()); // out of range
138   // last line
139   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
140                        llvm::Failed()); // out of range
141   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
142                        llvm::HasValue(18)); // first character
143   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 3)),
144                        llvm::HasValue(21)); // middle character
145   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
146                        llvm::Failed()); // middle of surrogate pair
147   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5)),
148                        llvm::HasValue(26)); // middle of surrogate pair
149   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 6), false),
150                        llvm::HasValue(26)); // end of surrogate pair
151   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
152                        llvm::HasValue(28)); // last character
153   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9)),
154                        llvm::HasValue(29)); // EOF
155   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 10), false),
156                        llvm::Failed()); // out of range
157   // line out of bounds
158   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
159   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
160 
161   // Codepoints are similar, except near astral characters.
162   WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
163   // line out of bounds
164   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
165   // first line
166   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
167                        llvm::Failed()); // out of range
168   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
169                        llvm::HasValue(0)); // first character
170   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
171                        llvm::HasValue(3)); // middle character
172   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
173                        llvm::HasValue(6)); // last character
174   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
175                        llvm::HasValue(7)); // the newline itself
176   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
177                        llvm::HasValue(7));
178   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
179                        llvm::HasValue(7)); // out of range
180   EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
181                        llvm::Failed()); // out of range
182   // middle line
183   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
184                        llvm::Failed()); // out of range
185   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
186                        llvm::HasValue(8)); // first character
187   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
188                        llvm::HasValue(11)); // middle character
189   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
190                        llvm::HasValue(11));
191   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
192                        llvm::HasValue(16)); // last character
193   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
194                        llvm::HasValue(17)); // the newline itself
195   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
196                        llvm::HasValue(17)); // out of range
197   EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
198                        llvm::Failed()); // out of range
199   // last line
200   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
201                        llvm::Failed()); // out of range
202   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
203                        llvm::HasValue(18)); // first character
204   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 4)),
205                        llvm::HasValue(22)); // Before astral character.
206   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
207                        llvm::HasValue(26)); // after astral character
208   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 7)),
209                        llvm::HasValue(28)); // last character
210   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
211                        llvm::HasValue(29)); // EOF
212   EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9), false),
213                        llvm::Failed()); // out of range
214   // line out of bounds
215   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
216   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
217 
218   // Test UTF-8, where transformations are trivial.
219   WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
220   EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
221   EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
222   for (Line L : FileLines) {
223     EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, -1)),
224                          llvm::Failed()); // out of range
225     for (unsigned I = 0; I <= L.Length; ++I)
226       EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, I)),
227                            llvm::HasValue(L.Offset + I));
228     EXPECT_THAT_EXPECTED(
229         positionToOffset(File, position(L.Number, L.Length + 1)),
230         llvm::HasValue(L.Offset + L.Length));
231     EXPECT_THAT_EXPECTED(
232         positionToOffset(File, position(L.Number, L.Length + 1), false),
233         llvm::Failed()); // out of range
234   }
235 }
236 
237 TEST(SourceCodeTests, OffsetToPosition) {
238   EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
239   EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
240   EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
241   EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
242   EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
243   EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
244   EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
245   EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
246   EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
247   EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
248   EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
249   EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
250   EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
251   EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 6)) << "in astral char";
252   EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 6)) << "after astral char";
253   EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 8)) << "end of last line";
254   EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 9)) << "EOF";
255   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
256 
257   // Codepoints are similar, except near astral characters.
258   WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
259   EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
260   EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
261   EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
262   EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
263   EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
264   EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
265   EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
266   EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
267   EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
268   EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
269   EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
270   EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
271   EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
272   EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 5)) << "in astral char";
273   EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 5)) << "after astral char";
274   EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 7)) << "end of last line";
275   EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 8)) << "EOF";
276   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 8)) << "out of bounds";
277 
278   WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
279   for (Line L : FileLines) {
280     for (unsigned I = 0; I <= L.Length; ++I)
281       EXPECT_THAT(offsetToPosition(File, L.Offset + I), Pos(L.Number, I));
282   }
283   EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 11)) << "out of bounds";
284 }
285 
286 TEST(SourceCodeTests, SourceLocationInMainFile) {
287   Annotations Source(R"cpp(
288     ^in^t ^foo
289     ^bar
290     ^baz ^() {}  {} {} {} { }^
291 )cpp");
292 
293   SourceManagerForFile Owner("foo.cpp", Source.code());
294   SourceManager &SM = Owner.get();
295 
296   SourceLocation StartOfFile = SM.getLocForStartOfFile(SM.getMainFileID());
297   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 0)),
298                        HasValue(StartOfFile));
299   // End of file.
300   EXPECT_THAT_EXPECTED(
301       sourceLocationInMainFile(SM, position(4, 0)),
302       HasValue(StartOfFile.getLocWithOffset(Source.code().size())));
303   // Column number is too large.
304   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 1)), Failed());
305   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 100)),
306                        Failed());
307   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(4, 1)), Failed());
308   // Line number is too large.
309   EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(5, 0)), Failed());
310   // Check all positions mentioned in the test return valid results.
311   for (auto P : Source.points()) {
312     size_t Offset = llvm::cantFail(positionToOffset(Source.code(), P));
313     EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, P),
314                          HasValue(StartOfFile.getLocWithOffset(Offset)));
315   }
316 }
317 
318 TEST(SourceCodeTests, CollectIdentifiers) {
319   auto Style = format::getLLVMStyle();
320   auto IDs = collectIdentifiers(R"cpp(
321   #include "a.h"
322   void foo() { int xyz; int abc = xyz; return foo(); }
323   )cpp",
324                                 Style);
325   EXPECT_EQ(IDs.size(), 7u);
326   EXPECT_EQ(IDs["include"], 1u);
327   EXPECT_EQ(IDs["void"], 1u);
328   EXPECT_EQ(IDs["int"], 2u);
329   EXPECT_EQ(IDs["xyz"], 2u);
330   EXPECT_EQ(IDs["abc"], 1u);
331   EXPECT_EQ(IDs["return"], 1u);
332   EXPECT_EQ(IDs["foo"], 2u);
333 }
334 
335 TEST(SourceCodeTests, CollectWords) {
336   auto Words = collectWords(R"cpp(
337   #define FIZZ_BUZZ
338   // this is a comment
339   std::string getSomeText() { return "magic word"; }
340   )cpp");
341   std::set<StringRef> ActualWords(Words.keys().begin(), Words.keys().end());
342   std::set<StringRef> ExpectedWords = {"define",  "fizz",   "buzz", "this",
343                                        "comment", "string", "some", "text",
344                                        "return",  "magic",  "word"};
345   EXPECT_EQ(ActualWords, ExpectedWords);
346 }
347 
348 class SpelledWordsTest : public ::testing::Test {
349   llvm::Optional<ParsedAST> AST;
350 
351   llvm::Optional<SpelledWord> tryWord(const char *Text) {
352     llvm::Annotations A(Text);
353     auto TU = TestTU::withCode(A.code());
354     AST = TU.build();
355     auto SW = SpelledWord::touching(
356         AST->getSourceManager().getComposedLoc(
357             AST->getSourceManager().getMainFileID(), A.point()),
358         AST->getTokens(), AST->getLangOpts());
359     if (A.ranges().size()) {
360       llvm::StringRef Want = A.code().slice(A.range().Begin, A.range().End);
361       EXPECT_EQ(Want, SW->Text) << Text;
362     }
363     return SW;
364   }
365 
366 protected:
367   SpelledWord word(const char *Text) {
368     auto Result = tryWord(Text);
369     EXPECT_TRUE(Result) << Text;
370     return Result.getValueOr(SpelledWord());
371   }
372 
373   void noWord(const char *Text) { EXPECT_FALSE(tryWord(Text)) << Text; }
374 };
375 
376 TEST_F(SpelledWordsTest, HeuristicBoundaries) {
377   word("// [[^foo]] ");
378   word("// [[f^oo]] ");
379   word("// [[foo^]] ");
380   word("// [[foo^]]+bar ");
381   noWord("//^ foo ");
382   noWord("// foo ^");
383 }
384 
385 TEST_F(SpelledWordsTest, LikelyIdentifier) {
386   EXPECT_FALSE(word("// ^foo ").LikelyIdentifier);
387   EXPECT_TRUE(word("// [[^foo_bar]] ").LikelyIdentifier);
388   EXPECT_TRUE(word("// [[^fooBar]] ").LikelyIdentifier);
389   EXPECT_FALSE(word("// H^TTP ").LikelyIdentifier);
390   EXPECT_TRUE(word("// \\p [[^foo]] ").LikelyIdentifier);
391   EXPECT_TRUE(word("// @param[in] [[^foo]] ").LikelyIdentifier);
392   EXPECT_TRUE(word("// `[[f^oo]]` ").LikelyIdentifier);
393   EXPECT_TRUE(word("// bar::[[f^oo]] ").LikelyIdentifier);
394   EXPECT_TRUE(word("// [[f^oo]]::bar ").LikelyIdentifier);
395 }
396 
397 TEST_F(SpelledWordsTest, Comment) {
398   auto W = word("// [[^foo]]");
399   EXPECT_FALSE(W.PartOfSpelledToken);
400   EXPECT_FALSE(W.SpelledToken);
401   EXPECT_FALSE(W.ExpandedToken);
402 }
403 
404 TEST_F(SpelledWordsTest, PartOfString) {
405   auto W = word(R"( auto str = "foo [[^bar]] baz"; )");
406   ASSERT_TRUE(W.PartOfSpelledToken);
407   EXPECT_EQ(W.PartOfSpelledToken->kind(), tok::string_literal);
408   EXPECT_FALSE(W.SpelledToken);
409   EXPECT_FALSE(W.ExpandedToken);
410 }
411 
412 TEST_F(SpelledWordsTest, DisabledSection) {
413   auto W = word(R"cpp(
414     #if 0
415     foo [[^bar]] baz
416     #endif
417     )cpp");
418   ASSERT_TRUE(W.SpelledToken);
419   EXPECT_EQ(W.SpelledToken->kind(), tok::identifier);
420   EXPECT_EQ(W.SpelledToken, W.PartOfSpelledToken);
421   EXPECT_FALSE(W.ExpandedToken);
422 }
423 
424 TEST_F(SpelledWordsTest, Macros) {
425   auto W = word(R"cpp(
426     #define ID(X) X
427     ID(int [[^i]]);
428     )cpp");
429   ASSERT_TRUE(W.SpelledToken);
430   EXPECT_EQ(W.SpelledToken->kind(), tok::identifier);
431   EXPECT_EQ(W.SpelledToken, W.PartOfSpelledToken);
432   ASSERT_TRUE(W.ExpandedToken);
433   EXPECT_EQ(W.ExpandedToken->kind(), tok::identifier);
434 
435   W = word(R"cpp(
436     #define OBJECT Expansion;
437     int [[^OBJECT]];
438     )cpp");
439   EXPECT_TRUE(W.SpelledToken);
440   EXPECT_FALSE(W.ExpandedToken) << "Expanded token is spelled differently";
441 }
442 
443 TEST(SourceCodeTests, VisibleNamespaces) {
444   std::vector<std::pair<const char *, std::vector<std::string>>> Cases = {
445       {
446           R"cpp(
447             // Using directive resolved against enclosing namespaces.
448             using namespace foo;
449             namespace ns {
450             using namespace bar;
451           )cpp",
452           {"ns", "", "bar", "foo", "ns::bar"},
453       },
454       {
455           R"cpp(
456             // Don't include namespaces we've closed, ignore namespace aliases.
457             using namespace clang;
458             using std::swap;
459             namespace clang {
460             namespace clangd {}
461             namespace ll = ::llvm;
462             }
463             namespace clang {
464           )cpp",
465           {"clang", ""},
466       },
467       {
468           R"cpp(
469             // Using directives visible even if a namespace is reopened.
470             // Ignore anonymous namespaces.
471             namespace foo{ using namespace bar; }
472             namespace foo{ namespace {
473           )cpp",
474           {"foo", "", "bar", "foo::bar"},
475       },
476       {
477           R"cpp(
478             // Mismatched braces
479             namespace foo{}
480             }}}
481             namespace bar{
482           )cpp",
483           {"bar", ""},
484       },
485       {
486           R"cpp(
487             // Namespaces with multiple chunks.
488             namespace a::b {
489               using namespace c::d;
490               namespace e::f {
491           )cpp",
492           {
493               "a::b::e::f",
494               "",
495               "a",
496               "a::b",
497               "a::b::c::d",
498               "a::b::e",
499               "a::c::d",
500               "c::d",
501           },
502       },
503       {
504           "",
505           {""},
506       },
507       {
508           R"cpp(
509             // Parse until EOF
510             namespace bar{})cpp",
511           {""},
512       },
513   };
514   for (const auto &Case : Cases) {
515     EXPECT_EQ(Case.second,
516               visibleNamespaces(Case.first, format::getFormattingLangOpts(
517                                                 format::getLLVMStyle())))
518         << Case.first;
519   }
520 }
521 
522 TEST(SourceCodeTests, GetMacros) {
523   Annotations Code(R"cpp(
524      #define MACRO 123
525      int abc = MA^CRO;
526    )cpp");
527   TestTU TU = TestTU::withCode(Code.code());
528   auto AST = TU.build();
529   auto CurLoc = sourceLocationInMainFile(AST.getSourceManager(), Code.point());
530   ASSERT_TRUE(bool(CurLoc));
531   const auto *Id = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens());
532   ASSERT_TRUE(Id);
533   auto Result = locateMacroAt(*Id, AST.getPreprocessor());
534   ASSERT_TRUE(Result);
535   EXPECT_THAT(*Result, MacroName("MACRO"));
536 }
537 
538 TEST(SourceCodeTests, WorksAtBeginOfFile) {
539   Annotations Code("^MACRO");
540   TestTU TU = TestTU::withCode(Code.code());
541   TU.HeaderCode = "#define MACRO int x;";
542   auto AST = TU.build();
543   auto CurLoc = sourceLocationInMainFile(AST.getSourceManager(), Code.point());
544   ASSERT_TRUE(bool(CurLoc));
545   const auto *Id = syntax::spelledIdentifierTouching(*CurLoc, AST.getTokens());
546   ASSERT_TRUE(Id);
547   auto Result = locateMacroAt(*Id, AST.getPreprocessor());
548   ASSERT_TRUE(Result);
549   EXPECT_THAT(*Result, MacroName("MACRO"));
550 }
551 
552 TEST(SourceCodeTests, IsInsideMainFile) {
553   TestTU TU;
554   TU.HeaderCode = R"cpp(
555     #define DEFINE_CLASS(X) class X {};
556     #define DEFINE_YY DEFINE_CLASS(YY)
557 
558     class Header1 {};
559     DEFINE_CLASS(Header2)
560     class Header {};
561   )cpp";
562   TU.Code = R"cpp(
563     #define DEFINE_MAIN4 class Main4{};
564     class Main1 {};
565     DEFINE_CLASS(Main2)
566     DEFINE_YY
567     class Main {};
568     DEFINE_MAIN4
569   )cpp";
570   TU.ExtraArgs.push_back("-DHeader=Header3");
571   TU.ExtraArgs.push_back("-DMain=Main3");
572   auto AST = TU.build();
573   const auto &SM = AST.getSourceManager();
574   auto DeclLoc = [&AST](llvm::StringRef Name) {
575     return findDecl(AST, Name).getLocation();
576   };
577   for (const auto *HeaderDecl : {"Header1", "Header2", "Header3"})
578     EXPECT_FALSE(isInsideMainFile(DeclLoc(HeaderDecl), SM)) << HeaderDecl;
579 
580   for (const auto *MainDecl : {"Main1", "Main2", "Main3", "Main4", "YY"})
581     EXPECT_TRUE(isInsideMainFile(DeclLoc(MainDecl), SM)) << MainDecl;
582 
583   // Main4 is *spelled* in the preamble, but in the main-file part of it.
584   EXPECT_TRUE(isInsideMainFile(SM.getSpellingLoc(DeclLoc("Main4")), SM));
585 }
586 
587 // Test for functions toHalfOpenFileRange and getHalfOpenFileRange
588 TEST(SourceCodeTests, HalfOpenFileRange) {
589   // Each marked range should be the file range of the decl with the same name
590   // and each name should be unique.
591   Annotations Test(R"cpp(
592     #define FOO(X, Y) int Y = ++X
593     #define BAR(X) X + 1
594     #define ECHO(X) X
595 
596     #define BUZZ BAZZ(ADD)
597     #define BAZZ(m) m(1)
598     #define ADD(a) int f = a + 1;
599     template<typename T>
600     class P {};
601 
602     int main() {
603       $a[[P<P<P<P<P<int>>>>> a]];
604       $b[[int b = 1]];
605       $c[[FOO(b, c)]];
606       $d[[FOO(BAR(BAR(b)), d)]];
607       // FIXME: We might want to select everything inside the outer ECHO.
608       ECHO(ECHO($e[[int) ECHO(e]]));
609       // Shouldn't crash.
610       $f[[BUZZ]];
611     }
612   )cpp");
613 
614   ParsedAST AST = TestTU::withCode(Test.code()).build();
615   llvm::errs() << Test.code();
616   const SourceManager &SM = AST.getSourceManager();
617   const LangOptions &LangOpts = AST.getLangOpts();
618   // Turn a SourceLocation into a pair of positions
619   auto SourceRangeToRange = [&SM](SourceRange SrcRange) {
620     return Range{sourceLocToPosition(SM, SrcRange.getBegin()),
621                  sourceLocToPosition(SM, SrcRange.getEnd())};
622   };
623   auto CheckRange = [&](llvm::StringRef Name) {
624     const NamedDecl &Decl = findUnqualifiedDecl(AST, Name);
625     auto FileRange = toHalfOpenFileRange(SM, LangOpts, Decl.getSourceRange());
626     SCOPED_TRACE("Checking range: " + Name);
627     ASSERT_NE(FileRange, llvm::None);
628     Range HalfOpenRange = SourceRangeToRange(*FileRange);
629     EXPECT_EQ(HalfOpenRange, Test.ranges(Name)[0]);
630   };
631 
632   CheckRange("a");
633   CheckRange("b");
634   CheckRange("c");
635   CheckRange("d");
636   CheckRange("e");
637   CheckRange("f");
638 }
639 
640 TEST(SourceCodeTests, HalfOpenFileRangePathologicalPreprocessor) {
641   const char *Case = R"cpp(
642 #define MACRO while(1)
643     void test() {
644 [[#include "Expand.inc"
645         br^eak]];
646     }
647   )cpp";
648   Annotations Test(Case);
649   auto TU = TestTU::withCode(Test.code());
650   TU.AdditionalFiles["Expand.inc"] = "MACRO\n";
651   auto AST = TU.build();
652 
653   const auto &Func = cast<FunctionDecl>(findDecl(AST, "test"));
654   const auto &Body = cast<CompoundStmt>(Func.getBody());
655   const auto &Loop = cast<WhileStmt>(*Body->child_begin());
656   llvm::Optional<SourceRange> Range = toHalfOpenFileRange(
657       AST.getSourceManager(), AST.getLangOpts(), Loop->getSourceRange());
658   ASSERT_TRUE(Range) << "Failed to get file range";
659   EXPECT_EQ(AST.getSourceManager().getFileOffset(Range->getBegin()),
660             Test.llvm::Annotations::range().Begin);
661   EXPECT_EQ(AST.getSourceManager().getFileOffset(Range->getEnd()),
662             Test.llvm::Annotations::range().End);
663 }
664 
665 TEST(SourceCodeTests, IncludeHashLoc) {
666   const char *Case = R"cpp(
667 $foo^#include "foo.inc"
668 #define HEADER "bar.inc"
669   $bar^#  include HEADER
670   )cpp";
671   Annotations Test(Case);
672   auto TU = TestTU::withCode(Test.code());
673   TU.AdditionalFiles["foo.inc"] = "int foo;\n";
674   TU.AdditionalFiles["bar.inc"] = "int bar;\n";
675   auto AST = TU.build();
676   const auto &SM = AST.getSourceManager();
677 
678   FileID Foo = SM.getFileID(findDecl(AST, "foo").getLocation());
679   EXPECT_EQ(SM.getFileOffset(includeHashLoc(Foo, SM)),
680             Test.llvm::Annotations::point("foo"));
681   FileID Bar = SM.getFileID(findDecl(AST, "bar").getLocation());
682   EXPECT_EQ(SM.getFileOffset(includeHashLoc(Bar, SM)),
683             Test.llvm::Annotations::point("bar"));
684 }
685 
686 TEST(SourceCodeTests, GetEligiblePoints) {
687   constexpr struct {
688     const char *Code;
689     const char *FullyQualifiedName;
690     const char *EnclosingNamespace;
691   } Cases[] = {
692       {R"cpp(// FIXME: We should also mark positions before and after
693                  //declarations/definitions as eligible.
694               namespace ns1 {
695               namespace a { namespace ns2 {} }
696               namespace ns2 {^
697               void foo();
698               namespace {}
699               void bar() {}
700               namespace ns3 {}
701               class T {};
702               ^}
703               using namespace ns2;
704               })cpp",
705        "ns1::ns2::symbol", "ns1::ns2::"},
706       {R"cpp(
707               namespace ns1 {^
708               namespace a { namespace ns2 {} }
709               namespace b {}
710               namespace ns {}
711               ^})cpp",
712        "ns1::ns2::symbol", "ns1::"},
713       {R"cpp(
714               namespace x {
715               namespace a { namespace ns2 {} }
716               namespace b {}
717               namespace ns {}
718               }^)cpp",
719        "ns1::ns2::symbol", ""},
720       {R"cpp(
721               namespace ns1 {
722               namespace ns2 {^^}
723               namespace b {}
724               namespace ns2 {^^}
725               }
726               namespace ns1 {namespace ns2 {^^}})cpp",
727        "ns1::ns2::symbol", "ns1::ns2::"},
728       {R"cpp(
729               namespace ns1 {^
730               namespace ns {}
731               namespace b {}
732               namespace ns {}
733               ^}
734               namespace ns1 {^namespace ns {}^})cpp",
735        "ns1::ns2::symbol", "ns1::"},
736   };
737   for (auto Case : Cases) {
738     Annotations Test(Case.Code);
739 
740     auto Res = getEligiblePoints(
741         Test.code(), Case.FullyQualifiedName,
742         format::getFormattingLangOpts(format::getLLVMStyle()));
743     EXPECT_THAT(Res.EligiblePoints, testing::ElementsAreArray(Test.points()))
744         << Test.code();
745     EXPECT_EQ(Res.EnclosingNamespace, Case.EnclosingNamespace) << Test.code();
746   }
747 }
748 
749 TEST(SourceCodeTests, IdentifierRanges) {
750   Annotations Code(R"cpp(
751    class [[Foo]] {};
752    // Foo
753    /* Foo */
754    void f([[Foo]]* foo1) {
755      [[Foo]] foo2;
756      auto S = [[Foo]]();
757 // cross-line identifier is not supported.
758 F\
759 o\
760 o foo2;
761    }
762   )cpp");
763   LangOptions LangOpts;
764   LangOpts.CPlusPlus = true;
765   EXPECT_EQ(Code.ranges(),
766             collectIdentifierRanges("Foo", Code.code(), LangOpts));
767 }
768 
769 TEST(SourceCodeTests, isHeaderFile) {
770   // Without lang options.
771   EXPECT_TRUE(isHeaderFile("foo.h"));
772   EXPECT_TRUE(isHeaderFile("foo.hh"));
773   EXPECT_TRUE(isHeaderFile("foo.hpp"));
774 
775   EXPECT_FALSE(isHeaderFile("foo.cpp"));
776   EXPECT_FALSE(isHeaderFile("foo.c++"));
777   EXPECT_FALSE(isHeaderFile("foo.cxx"));
778   EXPECT_FALSE(isHeaderFile("foo.cc"));
779   EXPECT_FALSE(isHeaderFile("foo.c"));
780   EXPECT_FALSE(isHeaderFile("foo.mm"));
781   EXPECT_FALSE(isHeaderFile("foo.m"));
782 
783   // With lang options
784   LangOptions LangOpts;
785   LangOpts.IsHeaderFile = true;
786   EXPECT_TRUE(isHeaderFile("string", LangOpts));
787   // Emulate cases where there is no "-x header" flag for a .h file, we still
788   // want to treat it as a header.
789   LangOpts.IsHeaderFile = false;
790   EXPECT_TRUE(isHeaderFile("header.h", LangOpts));
791 }
792 
793 TEST(SourceCodeTests, isKeywords) {
794   LangOptions LangOpts;
795   LangOpts.CPlusPlus20 = true;
796   EXPECT_TRUE(isKeyword("int", LangOpts));
797   EXPECT_TRUE(isKeyword("return", LangOpts));
798   EXPECT_TRUE(isKeyword("co_await", LangOpts));
799 
800   // these are identifiers (not keywords!) with special meaning in some
801   // contexts.
802   EXPECT_FALSE(isKeyword("final", LangOpts));
803   EXPECT_FALSE(isKeyword("override", LangOpts));
804 }
805 
806 struct IncrementalTestStep {
807   llvm::StringRef Src;
808   llvm::StringRef Contents;
809 };
810 
811 int rangeLength(llvm::StringRef Code, const Range &Rng) {
812   llvm::Expected<size_t> Start = positionToOffset(Code, Rng.start);
813   llvm::Expected<size_t> End = positionToOffset(Code, Rng.end);
814   assert(Start);
815   assert(End);
816   return *End - *Start;
817 }
818 
819 /// Send the changes one by one to updateDraft, verify the intermediate results.
820 void stepByStep(llvm::ArrayRef<IncrementalTestStep> Steps) {
821   std::string Code = Annotations(Steps.front().Src).code().str();
822 
823   for (size_t I = 1; I < Steps.size(); I++) {
824     Annotations SrcBefore(Steps[I - 1].Src);
825     Annotations SrcAfter(Steps[I].Src);
826     llvm::StringRef Contents = Steps[I - 1].Contents;
827     TextDocumentContentChangeEvent Event{
828         SrcBefore.range(),
829         rangeLength(SrcBefore.code(), SrcBefore.range()),
830         Contents.str(),
831     };
832 
833     EXPECT_THAT_ERROR(applyChange(Code, Event), llvm::Succeeded());
834     EXPECT_EQ(Code, SrcAfter.code());
835   }
836 }
837 
838 TEST(ApplyEditsTest, Simple) {
839   // clang-format off
840   IncrementalTestStep Steps[] =
841     {
842       // Replace a range
843       {
844 R"cpp(static int
845 hello[[World]]()
846 {})cpp",
847         "Universe"
848       },
849       // Delete a range
850       {
851 R"cpp(static int
852 hello[[Universe]]()
853 {})cpp",
854         ""
855       },
856       // Add a range
857       {
858 R"cpp(static int
859 hello[[]]()
860 {})cpp",
861         "Monde"
862       },
863       {
864 R"cpp(static int
865 helloMonde()
866 {})cpp",
867         ""
868       }
869     };
870   // clang-format on
871 
872   stepByStep(Steps);
873 }
874 
875 TEST(ApplyEditsTest, MultiLine) {
876   // clang-format off
877   IncrementalTestStep Steps[] =
878     {
879       // Replace a range
880       {
881 R"cpp(static [[int
882 helloWorld]]()
883 {})cpp",
884 R"cpp(char
885 welcome)cpp"
886       },
887       // Delete a range
888       {
889 R"cpp(static char[[
890 welcome]]()
891 {})cpp",
892         ""
893       },
894       // Add a range
895       {
896 R"cpp(static char[[]]()
897 {})cpp",
898         R"cpp(
899 cookies)cpp"
900       },
901       // Replace the whole file
902       {
903 R"cpp([[static char
904 cookies()
905 {}]])cpp",
906         R"cpp(#include <stdio.h>
907 )cpp"
908       },
909       // Delete the whole file
910       {
911         R"cpp([[#include <stdio.h>
912 ]])cpp",
913         "",
914       },
915       // Add something to an empty file
916       {
917         "[[]]",
918         R"cpp(int main() {
919 )cpp",
920       },
921       {
922         R"cpp(int main() {
923 )cpp",
924         ""
925       }
926     };
927   // clang-format on
928 
929   stepByStep(Steps);
930 }
931 
932 TEST(ApplyEditsTest, WrongRangeLength) {
933   std::string Code = "int main() {}\n";
934 
935   TextDocumentContentChangeEvent Change;
936   Change.range.emplace();
937   Change.range->start.line = 0;
938   Change.range->start.character = 0;
939   Change.range->end.line = 0;
940   Change.range->end.character = 2;
941   Change.rangeLength = 10;
942 
943   EXPECT_THAT_ERROR(applyChange(Code, Change),
944                     FailedWithMessage("Change's rangeLength (10) doesn't match "
945                                       "the computed range length (2)."));
946 }
947 
948 TEST(ApplyEditsTest, EndBeforeStart) {
949   std::string Code = "int main() {}\n";
950 
951   TextDocumentContentChangeEvent Change;
952   Change.range.emplace();
953   Change.range->start.line = 0;
954   Change.range->start.character = 5;
955   Change.range->end.line = 0;
956   Change.range->end.character = 3;
957 
958   EXPECT_THAT_ERROR(
959       applyChange(Code, Change),
960       FailedWithMessage(
961           "Range's end position (0:3) is before start position (0:5)"));
962 }
963 
964 TEST(ApplyEditsTest, StartCharOutOfRange) {
965   std::string Code = "int main() {}\n";
966 
967   TextDocumentContentChangeEvent Change;
968   Change.range.emplace();
969   Change.range->start.line = 0;
970   Change.range->start.character = 100;
971   Change.range->end.line = 0;
972   Change.range->end.character = 100;
973   Change.text = "foo";
974 
975   EXPECT_THAT_ERROR(
976       applyChange(Code, Change),
977       FailedWithMessage("utf-16 offset 100 is invalid for line 0"));
978 }
979 
980 TEST(ApplyEditsTest, EndCharOutOfRange) {
981   std::string Code = "int main() {}\n";
982 
983   TextDocumentContentChangeEvent Change;
984   Change.range.emplace();
985   Change.range->start.line = 0;
986   Change.range->start.character = 0;
987   Change.range->end.line = 0;
988   Change.range->end.character = 100;
989   Change.text = "foo";
990 
991   EXPECT_THAT_ERROR(
992       applyChange(Code, Change),
993       FailedWithMessage("utf-16 offset 100 is invalid for line 0"));
994 }
995 
996 TEST(ApplyEditsTest, StartLineOutOfRange) {
997   std::string Code = "int main() {}\n";
998 
999   TextDocumentContentChangeEvent Change;
1000   Change.range.emplace();
1001   Change.range->start.line = 100;
1002   Change.range->start.character = 0;
1003   Change.range->end.line = 100;
1004   Change.range->end.character = 0;
1005   Change.text = "foo";
1006 
1007   EXPECT_THAT_ERROR(applyChange(Code, Change),
1008                     FailedWithMessage("Line value is out of range (100)"));
1009 }
1010 
1011 TEST(ApplyEditsTest, EndLineOutOfRange) {
1012   std::string Code = "int main() {}\n";
1013 
1014   TextDocumentContentChangeEvent Change;
1015   Change.range.emplace();
1016   Change.range->start.line = 0;
1017   Change.range->start.character = 0;
1018   Change.range->end.line = 100;
1019   Change.range->end.character = 0;
1020   Change.text = "foo";
1021 
1022   EXPECT_THAT_ERROR(applyChange(Code, Change),
1023                     FailedWithMessage("Line value is out of range (100)"));
1024 }
1025 
1026 } // namespace
1027 } // namespace clangd
1028 } // namespace clang
1029