blob: 9ca6fa1ad952d1585928f1c94bd42e3f8840357f [file] [log] [blame]
Sam McCallb536a2a2017-12-19 12:23:48 +00001//===-- SourceCodeTests.cpp ------------------------------------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Sam McCallb536a2a2017-12-19 12:23:48 +00006//
7//===----------------------------------------------------------------------===//
Ilya Biryukov060f7fe2019-01-29 14:31:19 +00008#include "Annotations.h"
Sam McCalla69698f2019-03-27 17:47:49 +00009#include "Context.h"
10#include "Protocol.h"
Sam McCallb536a2a2017-12-19 12:23:48 +000011#include "SourceCode.h"
Eric Liu00d99bd2019-04-11 09:36:36 +000012#include "clang/Format/Format.h"
Simon Marchi766338a2018-03-21 14:36:46 +000013#include "llvm/Support/Error.h"
Sam McCallb536a2a2017-12-19 12:23:48 +000014#include "llvm/Support/raw_os_ostream.h"
Simon Marchi766338a2018-03-21 14:36:46 +000015#include "llvm/Testing/Support/Error.h"
Sam McCallb536a2a2017-12-19 12:23:48 +000016#include "gmock/gmock.h"
17#include "gtest/gtest.h"
18
Sam McCallc008af62018-10-20 15:30:37 +000019namespace clang {
Sam McCallb536a2a2017-12-19 12:23:48 +000020namespace clangd {
Sam McCallb536a2a2017-12-19 12:23:48 +000021namespace {
22
Ilya Biryukov060f7fe2019-01-29 14:31:19 +000023using llvm::Failed;
24using llvm::HasValue;
Sam McCall9fb22b22019-05-06 10:25:10 +000025using ::testing::UnorderedElementsAreArray;
Ilya Biryukov060f7fe2019-01-29 14:31:19 +000026
Sam McCallb536a2a2017-12-19 12:23:48 +000027MATCHER_P2(Pos, Line, Col, "") {
Sam McCalla69698f2019-03-27 17:47:49 +000028 return arg.line == int(Line) && arg.character == int(Col);
Sam McCallb536a2a2017-12-19 12:23:48 +000029}
30
Ilya Biryukov7beea3a2018-02-14 10:52:04 +000031/// A helper to make tests easier to read.
32Position position(int line, int character) {
33 Position Pos;
34 Pos.line = line;
35 Pos.character = character;
36 return Pos;
37}
38
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +000039Range range(const std::pair<int, int> p1, const std::pair<int, int> p2) {
40 Range range;
41 range.start = position(p1.first, p1.second);
42 range.end = position(p2.first, p2.second);
43 return range;
44}
45
Sam McCall71891122018-10-23 11:51:53 +000046TEST(SourceCodeTests, lspLength) {
47 EXPECT_EQ(lspLength(""), 0UL);
48 EXPECT_EQ(lspLength("ascii"), 5UL);
49 // BMP
50 EXPECT_EQ(lspLength("↓"), 1UL);
51 EXPECT_EQ(lspLength("¥"), 1UL);
52 // astral
53 EXPECT_EQ(lspLength("😂"), 2UL);
Sam McCalla69698f2019-03-27 17:47:49 +000054
55 WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
56 EXPECT_EQ(lspLength(""), 0UL);
57 EXPECT_EQ(lspLength("ascii"), 5UL);
58 // BMP
59 EXPECT_EQ(lspLength("↓"), 3UL);
60 EXPECT_EQ(lspLength("¥"), 2UL);
61 // astral
62 EXPECT_EQ(lspLength("😂"), 4UL);
Sam McCall8b25d222019-03-28 14:37:51 +000063
64 WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
65 EXPECT_EQ(lspLength(""), 0UL);
66 EXPECT_EQ(lspLength("ascii"), 5UL);
67 // BMP
68 EXPECT_EQ(lspLength("↓"), 1UL);
69 EXPECT_EQ(lspLength("¥"), 1UL);
70 // astral
71 EXPECT_EQ(lspLength("😂"), 1UL);
Sam McCall71891122018-10-23 11:51:53 +000072}
73
Sam McCalla69698f2019-03-27 17:47:49 +000074// The = → 🡆 below are ASCII (1 byte), BMP (3 bytes), and astral (4 bytes).
75const char File[] = R"(0:0 = 0
761:0 8
772:0 🡆 18)";
78struct Line {
79 unsigned Number;
80 unsigned Offset;
81 unsigned Length;
82};
83Line FileLines[] = {Line{0, 0, 7}, Line{1, 8, 9}, Line{2, 18, 11}};
84
Sam McCallb536a2a2017-12-19 12:23:48 +000085TEST(SourceCodeTests, PositionToOffset) {
86 // line out of bounds
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000087 EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
Sam McCallb536a2a2017-12-19 12:23:48 +000088 // first line
Simon Marchi766338a2018-03-21 14:36:46 +000089 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000090 llvm::Failed()); // out of range
Simon Marchi766338a2018-03-21 14:36:46 +000091 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000092 llvm::HasValue(0)); // first character
Simon Marchi766338a2018-03-21 14:36:46 +000093 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000094 llvm::HasValue(3)); // middle character
Simon Marchi766338a2018-03-21 14:36:46 +000095 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000096 llvm::HasValue(6)); // last character
Simon Marchi766338a2018-03-21 14:36:46 +000097 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +000098 llvm::HasValue(7)); // the newline itself
Simon Marchi766338a2018-03-21 14:36:46 +000099 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000100 llvm::HasValue(7));
Simon Marchi766338a2018-03-21 14:36:46 +0000101 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000102 llvm::HasValue(7)); // out of range
Simon Marchi766338a2018-03-21 14:36:46 +0000103 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000104 llvm::Failed()); // out of range
Sam McCallb536a2a2017-12-19 12:23:48 +0000105 // middle line
Simon Marchi766338a2018-03-21 14:36:46 +0000106 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000107 llvm::Failed()); // out of range
Simon Marchi766338a2018-03-21 14:36:46 +0000108 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000109 llvm::HasValue(8)); // first character
Simon Marchi766338a2018-03-21 14:36:46 +0000110 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000111 llvm::HasValue(11)); // middle character
Simon Marchi766338a2018-03-21 14:36:46 +0000112 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000113 llvm::HasValue(11));
Simon Marchi766338a2018-03-21 14:36:46 +0000114 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000115 llvm::HasValue(16)); // last character
Simon Marchi766338a2018-03-21 14:36:46 +0000116 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000117 llvm::HasValue(17)); // the newline itself
Simon Marchi766338a2018-03-21 14:36:46 +0000118 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000119 llvm::HasValue(17)); // out of range
Simon Marchi766338a2018-03-21 14:36:46 +0000120 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000121 llvm::Failed()); // out of range
Sam McCallb536a2a2017-12-19 12:23:48 +0000122 // last line
Simon Marchi766338a2018-03-21 14:36:46 +0000123 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000124 llvm::Failed()); // out of range
Simon Marchi766338a2018-03-21 14:36:46 +0000125 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000126 llvm::HasValue(18)); // first character
Simon Marchi766338a2018-03-21 14:36:46 +0000127 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 3)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000128 llvm::HasValue(21)); // middle character
Sam McCalla4962cc2018-04-27 11:59:28 +0000129 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000130 llvm::Failed()); // middle of surrogate pair
Sam McCalla4962cc2018-04-27 11:59:28 +0000131 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000132 llvm::HasValue(26)); // middle of surrogate pair
Sam McCalla4962cc2018-04-27 11:59:28 +0000133 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 6), false),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000134 llvm::HasValue(26)); // end of surrogate pair
Simon Marchi766338a2018-03-21 14:36:46 +0000135 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000136 llvm::HasValue(28)); // last character
Sam McCalla4962cc2018-04-27 11:59:28 +0000137 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9)),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000138 llvm::HasValue(29)); // EOF
Sam McCalla4962cc2018-04-27 11:59:28 +0000139 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 10), false),
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000140 llvm::Failed()); // out of range
Sam McCallb536a2a2017-12-19 12:23:48 +0000141 // line out of bounds
Ilya Biryukovf2001aa2019-01-07 15:45:19 +0000142 EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
143 EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
Sam McCalla69698f2019-03-27 17:47:49 +0000144
Sam McCall8b25d222019-03-28 14:37:51 +0000145 // Codepoints are similar, except near astral characters.
146 WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
147 // line out of bounds
148 EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
149 // first line
150 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, -1)),
151 llvm::Failed()); // out of range
152 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 0)),
153 llvm::HasValue(0)); // first character
154 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 3)),
155 llvm::HasValue(3)); // middle character
156 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 6)),
157 llvm::HasValue(6)); // last character
158 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7)),
159 llvm::HasValue(7)); // the newline itself
160 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 7), false),
161 llvm::HasValue(7));
162 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8)),
163 llvm::HasValue(7)); // out of range
164 EXPECT_THAT_EXPECTED(positionToOffset(File, position(0, 8), false),
165 llvm::Failed()); // out of range
166 // middle line
167 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, -1)),
168 llvm::Failed()); // out of range
169 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 0)),
170 llvm::HasValue(8)); // first character
171 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3)),
172 llvm::HasValue(11)); // middle character
173 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 3), false),
174 llvm::HasValue(11));
175 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 6)),
176 llvm::HasValue(16)); // last character
177 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 7)),
178 llvm::HasValue(17)); // the newline itself
179 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8)),
180 llvm::HasValue(17)); // out of range
181 EXPECT_THAT_EXPECTED(positionToOffset(File, position(1, 8), false),
182 llvm::Failed()); // out of range
183 // last line
184 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, -1)),
185 llvm::Failed()); // out of range
186 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 0)),
187 llvm::HasValue(18)); // first character
188 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 4)),
189 llvm::HasValue(22)); // Before astral character.
190 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 5), false),
191 llvm::HasValue(26)); // after astral character
192 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 7)),
193 llvm::HasValue(28)); // last character
194 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 8)),
195 llvm::HasValue(29)); // EOF
196 EXPECT_THAT_EXPECTED(positionToOffset(File, position(2, 9), false),
197 llvm::Failed()); // out of range
198 // line out of bounds
199 EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
200 EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 1)), llvm::Failed());
201
Sam McCalla69698f2019-03-27 17:47:49 +0000202 // Test UTF-8, where transformations are trivial.
203 WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
204 EXPECT_THAT_EXPECTED(positionToOffset(File, position(-1, 2)), llvm::Failed());
205 EXPECT_THAT_EXPECTED(positionToOffset(File, position(3, 0)), llvm::Failed());
206 for (Line L : FileLines) {
207 EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, -1)),
208 llvm::Failed()); // out of range
209 for (unsigned I = 0; I <= L.Length; ++I)
210 EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, I)),
211 llvm::HasValue(L.Offset + I));
212 EXPECT_THAT_EXPECTED(positionToOffset(File, position(L.Number, L.Length+1)),
213 llvm::HasValue(L.Offset + L.Length));
214 EXPECT_THAT_EXPECTED(
215 positionToOffset(File, position(L.Number, L.Length + 1), false),
216 llvm::Failed()); // out of range
217 }
Sam McCallb536a2a2017-12-19 12:23:48 +0000218}
219
220TEST(SourceCodeTests, OffsetToPosition) {
221 EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
222 EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
223 EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
224 EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
225 EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
Sam McCalla4962cc2018-04-27 11:59:28 +0000226 EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
227 EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
228 EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
229 EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
230 EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
231 EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
232 EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
233 EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
234 EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 6)) << "in astral char";
235 EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 6)) << "after astral char";
236 EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 8)) << "end of last line";
237 EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 9)) << "EOF";
238 EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 9)) << "out of bounds";
Sam McCalla69698f2019-03-27 17:47:49 +0000239
Sam McCall8b25d222019-03-28 14:37:51 +0000240 // Codepoints are similar, except near astral characters.
241 WithContextValue UTF32(kCurrentOffsetEncoding, OffsetEncoding::UTF32);
242 EXPECT_THAT(offsetToPosition(File, 0), Pos(0, 0)) << "start of file";
243 EXPECT_THAT(offsetToPosition(File, 3), Pos(0, 3)) << "in first line";
244 EXPECT_THAT(offsetToPosition(File, 6), Pos(0, 6)) << "end of first line";
245 EXPECT_THAT(offsetToPosition(File, 7), Pos(0, 7)) << "first newline";
246 EXPECT_THAT(offsetToPosition(File, 8), Pos(1, 0)) << "start of second line";
247 EXPECT_THAT(offsetToPosition(File, 12), Pos(1, 4)) << "before BMP char";
248 EXPECT_THAT(offsetToPosition(File, 13), Pos(1, 5)) << "in BMP char";
249 EXPECT_THAT(offsetToPosition(File, 15), Pos(1, 5)) << "after BMP char";
250 EXPECT_THAT(offsetToPosition(File, 16), Pos(1, 6)) << "end of second line";
251 EXPECT_THAT(offsetToPosition(File, 17), Pos(1, 7)) << "second newline";
252 EXPECT_THAT(offsetToPosition(File, 18), Pos(2, 0)) << "start of last line";
253 EXPECT_THAT(offsetToPosition(File, 21), Pos(2, 3)) << "in last line";
254 EXPECT_THAT(offsetToPosition(File, 22), Pos(2, 4)) << "before astral char";
255 EXPECT_THAT(offsetToPosition(File, 24), Pos(2, 5)) << "in astral char";
256 EXPECT_THAT(offsetToPosition(File, 26), Pos(2, 5)) << "after astral char";
257 EXPECT_THAT(offsetToPosition(File, 28), Pos(2, 7)) << "end of last line";
258 EXPECT_THAT(offsetToPosition(File, 29), Pos(2, 8)) << "EOF";
259 EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 8)) << "out of bounds";
260
Sam McCalla69698f2019-03-27 17:47:49 +0000261 WithContextValue UTF8(kCurrentOffsetEncoding, OffsetEncoding::UTF8);
262 for (Line L : FileLines) {
263 for (unsigned I = 0; I <= L.Length; ++I)
264 EXPECT_THAT(offsetToPosition(File, L.Offset + I), Pos(L.Number, I));
265 }
266 EXPECT_THAT(offsetToPosition(File, 30), Pos(2, 11)) << "out of bounds";
Sam McCallb536a2a2017-12-19 12:23:48 +0000267}
268
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +0000269TEST(SourceCodeTests, IsRangeConsecutive) {
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000270 EXPECT_TRUE(isRangeConsecutive(range({2, 2}, {2, 3}), range({2, 3}, {2, 4})));
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +0000271 EXPECT_FALSE(
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000272 isRangeConsecutive(range({0, 2}, {0, 3}), range({2, 3}, {2, 4})));
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +0000273 EXPECT_FALSE(
Haojian Wuaa3ed5a2019-01-25 15:14:03 +0000274 isRangeConsecutive(range({2, 2}, {2, 3}), range({2, 4}, {2, 5})));
Kadir Cetinkayaa9c9d002018-08-13 08:23:01 +0000275}
276
Ilya Biryukov060f7fe2019-01-29 14:31:19 +0000277TEST(SourceCodeTests, SourceLocationInMainFile) {
278 Annotations Source(R"cpp(
279 ^in^t ^foo
280 ^bar
281 ^baz ^() {} {} {} {} { }^
282)cpp");
283
284 SourceManagerForFile Owner("foo.cpp", Source.code());
285 SourceManager &SM = Owner.get();
286
287 SourceLocation StartOfFile = SM.getLocForStartOfFile(SM.getMainFileID());
288 EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 0)),
289 HasValue(StartOfFile));
290 // End of file.
291 EXPECT_THAT_EXPECTED(
292 sourceLocationInMainFile(SM, position(4, 0)),
293 HasValue(StartOfFile.getLocWithOffset(Source.code().size())));
294 // Column number is too large.
295 EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 1)), Failed());
296 EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(0, 100)),
297 Failed());
298 EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(4, 1)), Failed());
299 // Line number is too large.
300 EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, position(5, 0)), Failed());
301 // Check all positions mentioned in the test return valid results.
302 for (auto P : Source.points()) {
303 size_t Offset = llvm::cantFail(positionToOffset(Source.code(), P));
304 EXPECT_THAT_EXPECTED(sourceLocationInMainFile(SM, P),
305 HasValue(StartOfFile.getLocWithOffset(Offset)));
306 }
307}
308
Eric Liu00d99bd2019-04-11 09:36:36 +0000309TEST(SourceCodeTests, CollectIdentifiers) {
310 auto Style = format::getLLVMStyle();
311 auto IDs = collectIdentifiers(R"cpp(
312 #include "a.h"
313 void foo() { int xyz; int abc = xyz; return foo(); }
314 )cpp",
315 Style);
316 EXPECT_EQ(IDs.size(), 7u);
317 EXPECT_EQ(IDs["include"], 1u);
318 EXPECT_EQ(IDs["void"], 1u);
319 EXPECT_EQ(IDs["int"], 2u);
320 EXPECT_EQ(IDs["xyz"], 2u);
321 EXPECT_EQ(IDs["abc"], 1u);
322 EXPECT_EQ(IDs["return"], 1u);
323 EXPECT_EQ(IDs["foo"], 2u);
324}
325
Sam McCall9fb22b22019-05-06 10:25:10 +0000326TEST(SourceCodeTests, CollectWords) {
327 auto Words = collectWords(R"cpp(
328 #define FIZZ_BUZZ
329 // this is a comment
330 std::string getSomeText() { return "magic word"; }
331 )cpp");
332 std::set<std::string> ActualWords(Words.keys().begin(), Words.keys().end());
333 std::set<std::string> ExpectedWords = {"define", "fizz", "buzz", "this",
334 "comment", "string", "some", "text",
335 "return", "magic", "word"};
336 EXPECT_EQ(ActualWords, ExpectedWords);
337}
338
Sam McCallc316b222019-04-26 07:45:49 +0000339TEST(SourceCodeTests, VisibleNamespaces) {
340 std::vector<std::pair<const char *, std::vector<std::string>>> Cases = {
341 {
342 R"cpp(
343 // Using directive resolved against enclosing namespaces.
344 using namespace foo;
345 namespace ns {
346 using namespace bar;
347 )cpp",
348 {"ns", "", "bar", "foo", "ns::bar"},
349 },
350 {
351 R"cpp(
352 // Don't include namespaces we've closed, ignore namespace aliases.
353 using namespace clang;
354 using std::swap;
355 namespace clang {
356 namespace clangd {}
357 namespace ll = ::llvm;
358 }
359 namespace clang {
360 )cpp",
361 {"clang", ""},
362 },
363 {
364 R"cpp(
365 // Using directives visible even if a namespace is reopened.
366 // Ignore anonymous namespaces.
367 namespace foo{ using namespace bar; }
368 namespace foo{ namespace {
369 )cpp",
370 {"foo", "", "bar", "foo::bar"},
371 },
372 {
373 R"cpp(
374 // Mismatched braces
375 namespace foo{}
376 }}}
377 namespace bar{
378 )cpp",
379 {"bar", ""},
380 },
381 {
382 R"cpp(
383 // Namespaces with multiple chunks.
384 namespace a::b {
385 using namespace c::d;
386 namespace e::f {
387 )cpp",
388 {
389 "a::b::e::f",
390 "",
391 "a",
392 "a::b",
393 "a::b::c::d",
394 "a::b::e",
395 "a::c::d",
396 "c::d",
397 },
398 },
399 };
400 for (const auto& Case : Cases) {
401 EXPECT_EQ(Case.second,
402 visibleNamespaces(Case.first, format::getLLVMStyle()))
403 << Case.first;
404 }
405}
406
Sam McCallb536a2a2017-12-19 12:23:48 +0000407} // namespace
408} // namespace clangd
409} // namespace clang