blob: 2deec641120e17b17dcbc7d5808a43c64cc73fb0 [file] [log] [blame]
Kirill Bobyrev5abe4782018-09-10 08:23:53 +00001//===-- DexTests.cpp ---------------------------------*- C++ -*-----------===//
Kirill Bobyrev5e82f052018-07-25 10:34:57 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Kirill Bobyrev19a94612018-09-06 12:54:43 +000010#include "FuzzyMatch.h"
11#include "TestFS.h"
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000012#include "TestIndex.h"
13#include "index/Index.h"
14#include "index/Merge.h"
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000015#include "index/dex/Dex.h"
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000016#include "index/dex/Iterator.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000017#include "index/dex/Token.h"
18#include "index/dex/Trigram.h"
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000019#include "llvm/Support/ScopedPrinter.h"
20#include "llvm/Support/raw_ostream.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000021#include "gmock/gmock.h"
22#include "gtest/gtest.h"
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000023#include <string>
24#include <vector>
25
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000026using ::testing::ElementsAre;
27using ::testing::UnorderedElementsAre;
Sam McCall9c7624e2018-09-03 14:37:43 +000028using namespace llvm;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000029
Kirill Bobyrev5e82f052018-07-25 10:34:57 +000030namespace clang {
31namespace clangd {
32namespace dex {
Kirill Bobyrev870aaf22018-08-20 14:39:32 +000033namespace {
Kirill Bobyrevbea258d2018-07-26 10:42:31 +000034
Kirill Bobyrev19a94612018-09-06 12:54:43 +000035std::vector<std::string> URISchemes = {"unittest"};
36
37//===----------------------------------------------------------------------===//
38// Query iterator tests.
39//===----------------------------------------------------------------------===//
40
Kirill Bobyreva98961b2018-08-24 11:25:43 +000041std::vector<DocID> consumeIDs(Iterator &It) {
42 auto IDAndScore = consume(It);
Kirill Bobyrev7413e982018-08-22 13:44:15 +000043 std::vector<DocID> IDs(IDAndScore.size());
44 for (size_t I = 0; I < IDAndScore.size(); ++I)
45 IDs[I] = IDAndScore[I].first;
46 return IDs;
47}
48
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000049TEST(DexIterators, DocumentIterator) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +000050 const PostingList L({4, 7, 8, 20, 42, 100});
51 auto DocIterator = L.iterator();
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000052
53 EXPECT_EQ(DocIterator->peek(), 4U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000054 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000055
56 DocIterator->advance();
57 EXPECT_EQ(DocIterator->peek(), 7U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000058 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000059
60 DocIterator->advanceTo(20);
61 EXPECT_EQ(DocIterator->peek(), 20U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000062 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000063
64 DocIterator->advanceTo(65);
65 EXPECT_EQ(DocIterator->peek(), 100U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000066 EXPECT_FALSE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000067
68 DocIterator->advanceTo(420);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000069 EXPECT_TRUE(DocIterator->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000070}
71
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000072TEST(DexIterators, AndWithEmpty) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +000073 const PostingList L0({});
74 const PostingList L1({0, 5, 7, 10, 42, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000075
Kirill Bobyrev249c5862018-09-13 17:11:03 +000076 auto AndEmpty = createAnd(L0.iterator());
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000077 EXPECT_TRUE(AndEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000078
Kirill Bobyrev249c5862018-09-13 17:11:03 +000079 auto AndWithEmpty = createAnd(L0.iterator(), L1.iterator());
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000080 EXPECT_TRUE(AndWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000081
Kirill Bobyrev7413e982018-08-22 13:44:15 +000082 EXPECT_THAT(consumeIDs(*AndWithEmpty), ElementsAre());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000083}
84
Kirill Bobyrev5abe4782018-09-10 08:23:53 +000085TEST(DexIterators, AndTwoLists) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +000086 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
87 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000088
Kirill Bobyrev249c5862018-09-13 17:11:03 +000089 auto And = createAnd(L1.iterator(), L0.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000090
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +000091 EXPECT_FALSE(And->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +000092 EXPECT_THAT(consumeIDs(*And), ElementsAre(0U, 7U, 10U, 320U, 9000U));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000093
Kirill Bobyrev249c5862018-09-13 17:11:03 +000094 And = createAnd(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +000095
96 And->advanceTo(0);
97 EXPECT_EQ(And->peek(), 0U);
98 And->advanceTo(5);
99 EXPECT_EQ(And->peek(), 7U);
100 And->advanceTo(10);
101 EXPECT_EQ(And->peek(), 10U);
102 And->advanceTo(42);
103 EXPECT_EQ(And->peek(), 320U);
104 And->advanceTo(8999);
105 EXPECT_EQ(And->peek(), 9000U);
106 And->advanceTo(9001);
107}
108
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000109TEST(DexIterators, AndThreeLists) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000110 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
111 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
112 const PostingList L2({1, 4, 7, 11, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000113
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000114 auto And = createAnd(L0.iterator(), L1.iterator(), L2.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000115 EXPECT_EQ(And->peek(), 7U);
116 And->advanceTo(300);
117 EXPECT_EQ(And->peek(), 320U);
118 And->advanceTo(100000);
119
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000120 EXPECT_TRUE(And->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000121}
122
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000123TEST(DexIterators, OrWithEmpty) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000124 const PostingList L0({});
125 const PostingList L1({0, 5, 7, 10, 42, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000126
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000127 auto OrEmpty = createOr(L0.iterator());
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000128 EXPECT_TRUE(OrEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000129
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000130 auto OrWithEmpty = createOr(L0.iterator(), L1.iterator());
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000131 EXPECT_FALSE(OrWithEmpty->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000132
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000133 EXPECT_THAT(consumeIDs(*OrWithEmpty),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000134 ElementsAre(0U, 5U, 7U, 10U, 42U, 320U, 9000U));
135}
136
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000137TEST(DexIterators, OrTwoLists) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000138 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
139 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000140
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000141 auto Or = createOr(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000142
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000143 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000144 EXPECT_EQ(Or->peek(), 0U);
145 Or->advance();
146 EXPECT_EQ(Or->peek(), 4U);
147 Or->advance();
148 EXPECT_EQ(Or->peek(), 5U);
149 Or->advance();
150 EXPECT_EQ(Or->peek(), 7U);
151 Or->advance();
152 EXPECT_EQ(Or->peek(), 10U);
153 Or->advance();
154 EXPECT_EQ(Or->peek(), 30U);
155 Or->advanceTo(42);
156 EXPECT_EQ(Or->peek(), 42U);
157 Or->advanceTo(300);
158 EXPECT_EQ(Or->peek(), 320U);
159 Or->advanceTo(9000);
160 EXPECT_EQ(Or->peek(), 9000U);
161 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000162 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000163
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000164 Or = createOr(L0.iterator(), L1.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000165
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000166 EXPECT_THAT(consumeIDs(*Or),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000167 ElementsAre(0U, 4U, 5U, 7U, 10U, 30U, 42U, 60U, 320U, 9000U));
168}
169
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000170TEST(DexIterators, OrThreeLists) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000171 const PostingList L0({0, 5, 7, 10, 42, 320, 9000});
172 const PostingList L1({0, 4, 7, 10, 30, 60, 320, 9000});
173 const PostingList L2({1, 4, 7, 11, 30, 60, 320, 9000});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000174
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000175 auto Or = createOr(L0.iterator(), L1.iterator(), L2.iterator());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000176
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000177 EXPECT_FALSE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000178 EXPECT_EQ(Or->peek(), 0U);
179
180 Or->advance();
181 EXPECT_EQ(Or->peek(), 1U);
182
183 Or->advance();
184 EXPECT_EQ(Or->peek(), 4U);
185
186 Or->advanceTo(7);
187
188 Or->advanceTo(59);
189 EXPECT_EQ(Or->peek(), 60U);
190
191 Or->advanceTo(9001);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000192 EXPECT_TRUE(Or->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000193}
194
195// FIXME(kbobyrev): The testcase below is similar to what is expected in real
196// queries. It should be updated once new iterators (such as boosting, limiting,
197// etc iterators) appear. However, it is not exhaustive and it would be
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000198// beneficial to implement automatic generation (e.g. fuzzing) of query trees
199// for more comprehensive testing.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000200TEST(DexIterators, QueryTree) {
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000201 //
202 // +-----------------+
203 // |And Iterator:1, 5|
204 // +--------+--------+
205 // |
206 // |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000207 // +-------------+----------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000208 // | |
209 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000210 // +----------v----------+ +----------v------------+
211 // |And Iterator: 1, 5, 9| |Or Iterator: 0, 1, 3, 5|
212 // +----------+----------+ +----------+------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000213 // | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000214 // +------+-----+ +---------------------+
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000215 // | | | | |
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000216 // +-------v-----+ +----+---+ +--v--+ +---v----+ +----v---+
217 // |1, 3, 5, 8, 9| |Boost: 2| |Empty| |Boost: 3| |Boost: 4|
218 // +-------------+ +----+---+ +-----+ +---+----+ +----+---+
219 // | | |
220 // +----v-----+ +-v--+ +---v---+
221 // |1, 5, 7, 9| |1, 5| |0, 3, 5|
222 // +----------+ +----+ +-------+
223 //
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000224 const PostingList L0({1, 3, 5, 8, 9});
225 const PostingList L1({1, 5, 7, 9});
226 const PostingList L3({});
227 const PostingList L4({1, 5});
228 const PostingList L5({0, 3, 5});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000229
230 // Root of the query tree: [1, 5]
231 auto Root = createAnd(
232 // Lower And Iterator: [1, 5, 9]
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000233 createAnd(L0.iterator(), createBoost(L1.iterator(), 2U)),
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000234 // Lower Or Iterator: [0, 1, 5]
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000235 createOr(L3.iterator(), createBoost(L4.iterator(), 3U),
236 createBoost(L5.iterator(), 4U)));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000237
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000238 EXPECT_FALSE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000239 EXPECT_EQ(Root->peek(), 1U);
240 Root->advanceTo(0);
241 // Advance multiple times. Shouldn't do anything.
242 Root->advanceTo(1);
243 Root->advanceTo(0);
244 EXPECT_EQ(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000245 auto ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000246 EXPECT_THAT(ElementBoost, 6);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000247 Root->advance();
248 EXPECT_EQ(Root->peek(), 5U);
249 Root->advanceTo(5);
250 EXPECT_EQ(Root->peek(), 5U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000251 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000252 EXPECT_THAT(ElementBoost, 8);
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000253 Root->advanceTo(9000);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000254 EXPECT_TRUE(Root->reachedEnd());
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000255}
256
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000257TEST(DexIterators, StringRepresentation) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000258 const PostingList L0({4, 7, 8, 20, 42, 100});
259 const PostingList L1({1, 3, 5, 8, 9});
260 const PostingList L2({1, 5, 7, 9});
261 const PostingList L3({0, 5});
262 const PostingList L4({0, 1, 5});
263 const PostingList L5({});
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000264
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000265 EXPECT_EQ(llvm::to_string(*(L0.iterator())), "[4]");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000266
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000267 auto Nested =
268 createAnd(createAnd(L1.iterator(), L2.iterator()),
269 createOr(L3.iterator(), L4.iterator(), L5.iterator()));
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000270
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000271 EXPECT_EQ(llvm::to_string(*Nested), "(& (| [5] [1] [END]) (& [1] [1]))");
Kirill Bobyreva522c1c2018-07-27 09:54:27 +0000272}
273
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000274TEST(DexIterators, Limit) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000275 const PostingList L0({3, 6, 7, 20, 42, 100});
276 const PostingList L1({1, 3, 5, 6, 7, 30, 100});
277 const PostingList L2({0, 3, 5, 7, 8, 100});
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000278
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000279 auto DocIterator = createLimit(L0.iterator(), 42);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000280 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7, 20, 42, 100));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000281
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000282 DocIterator = createLimit(L0.iterator(), 3);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000283 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre(3, 6, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000284
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000285 DocIterator = createLimit(L0.iterator(), 0);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000286 EXPECT_THAT(consumeIDs(*DocIterator), ElementsAre());
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000287
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000288 auto AndIterator = createAnd(
289 createLimit(createTrue(9000), 343), createLimit(L0.iterator(), 2),
290 createLimit(L1.iterator(), 3), createLimit(L2.iterator(), 42));
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000291 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(3, 7));
Kirill Bobyrev0a757662018-08-10 11:50:44 +0000292}
293
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000294TEST(DexIterators, True) {
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000295 auto TrueIterator = createTrue(0U);
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000296 EXPECT_TRUE(TrueIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000297 EXPECT_THAT(consumeIDs(*TrueIterator), ElementsAre());
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000298
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000299 const PostingList L0({1, 2, 5, 7});
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000300 TrueIterator = createTrue(7U);
301 EXPECT_THAT(TrueIterator->peek(), 0);
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000302 auto AndIterator = createAnd(L0.iterator(), move(TrueIterator));
Kirill Bobyrev6d8bd7f2018-08-20 09:16:14 +0000303 EXPECT_FALSE(AndIterator->reachedEnd());
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000304 EXPECT_THAT(consumeIDs(*AndIterator), ElementsAre(1, 2, 5));
305}
306
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000307TEST(DexIterators, Boost) {
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000308 auto BoostIterator = createBoost(createTrue(5U), 42U);
309 EXPECT_FALSE(BoostIterator->reachedEnd());
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000310 auto ElementBoost = BoostIterator->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000311 EXPECT_THAT(ElementBoost, 42U);
312
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000313 const PostingList L0({2, 4});
314 const PostingList L1({1, 4});
315 auto Root = createOr(createTrue(5U), createBoost(L0.iterator(), 2U),
316 createBoost(L1.iterator(), 3U));
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000317
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000318 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000319 EXPECT_THAT(ElementBoost, Iterator::DEFAULT_BOOST_SCORE);
320 Root->advance();
321 EXPECT_THAT(Root->peek(), 1U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000322 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000323 EXPECT_THAT(ElementBoost, 3);
324
325 Root->advance();
326 EXPECT_THAT(Root->peek(), 2U);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000327 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000328 EXPECT_THAT(ElementBoost, 2);
329
330 Root->advanceTo(4);
Kirill Bobyreva98961b2018-08-24 11:25:43 +0000331 ElementBoost = Root->consume();
Kirill Bobyrev7413e982018-08-22 13:44:15 +0000332 EXPECT_THAT(ElementBoost, 3);
Kirill Bobyrev30ffdf42018-08-20 08:47:30 +0000333}
334
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000335//===----------------------------------------------------------------------===//
336// Search token tests.
337//===----------------------------------------------------------------------===//
338
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000339testing::Matcher<std::vector<Token>>
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000340tokensAre(std::initializer_list<std::string> Strings, Token::Kind Kind) {
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000341 std::vector<Token> Tokens;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000342 for (const auto &TokenData : Strings) {
343 Tokens.push_back(Token(Kind, TokenData));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000344 }
345 return testing::UnorderedElementsAreArray(Tokens);
346}
347
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000348testing::Matcher<std::vector<Token>>
349trigramsAre(std::initializer_list<std::string> Trigrams) {
350 return tokensAre(Trigrams, Token::Kind::Trigram);
351}
352
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000353TEST(DexTrigrams, IdentifierTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000354 EXPECT_THAT(generateIdentifierTrigrams("X86"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000355 trigramsAre({"x86", "x$$", "x8$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000356
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000357 EXPECT_THAT(generateIdentifierTrigrams("nl"), trigramsAre({"nl$", "n$$"}));
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000358
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000359 EXPECT_THAT(generateIdentifierTrigrams("n"), trigramsAre({"n$$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000360
361 EXPECT_THAT(generateIdentifierTrigrams("clangd"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000362 trigramsAre({"c$$", "cl$", "cla", "lan", "ang", "ngd"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000363
364 EXPECT_THAT(generateIdentifierTrigrams("abc_def"),
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000365 trigramsAre({"a$$", "abc", "abd", "ade", "bcd", "bde", "cde",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000366 "def", "ab$", "ad$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000367
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000368 EXPECT_THAT(generateIdentifierTrigrams("a_b_c_d_e_"),
369 trigramsAre({"a$$", "a_$", "a_b", "abc", "abd", "acd", "ace",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000370 "bcd", "bce", "bde", "cde", "ab$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000371
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000372 EXPECT_THAT(generateIdentifierTrigrams("unique_ptr"),
373 trigramsAre({"u$$", "uni", "unp", "upt", "niq", "nip", "npt",
374 "iqu", "iqp", "ipt", "que", "qup", "qpt", "uep",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000375 "ept", "ptr", "un$", "up$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000376
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000377 EXPECT_THAT(
378 generateIdentifierTrigrams("TUDecl"),
379 trigramsAre({"t$$", "tud", "tde", "ude", "dec", "ecl", "tu$", "td$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000380
381 EXPECT_THAT(generateIdentifierTrigrams("IsOK"),
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000382 trigramsAre({"i$$", "iso", "iok", "sok", "is$", "io$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000383
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000384 EXPECT_THAT(
385 generateIdentifierTrigrams("abc_defGhij__klm"),
386 trigramsAre({"a$$", "abc", "abd", "abg", "ade", "adg", "adk", "agh",
387 "agk", "bcd", "bcg", "bde", "bdg", "bdk", "bgh", "bgk",
388 "cde", "cdg", "cdk", "cgh", "cgk", "def", "deg", "dek",
389 "dgh", "dgk", "dkl", "efg", "efk", "egh", "egk", "ekl",
390 "fgh", "fgk", "fkl", "ghi", "ghk", "gkl", "hij", "hik",
Kirill Bobyreve6d5fd82018-08-27 17:26:43 +0000391 "hkl", "ijk", "ikl", "jkl", "klm", "ab$", "ad$"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000392}
393
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000394TEST(DexTrigrams, QueryTrigrams) {
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000395 EXPECT_THAT(generateQueryTrigrams("c"), trigramsAre({"c$$"}));
396 EXPECT_THAT(generateQueryTrigrams("cl"), trigramsAre({"cl$"}));
397 EXPECT_THAT(generateQueryTrigrams("cla"), trigramsAre({"cla"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000398
Kirill Bobyrevff2dd902018-08-13 08:57:06 +0000399 EXPECT_THAT(generateQueryTrigrams("_"), trigramsAre({"_$$"}));
400 EXPECT_THAT(generateQueryTrigrams("__"), trigramsAre({"__$"}));
401 EXPECT_THAT(generateQueryTrigrams("___"), trigramsAre({"___"}));
402
403 EXPECT_THAT(generateQueryTrigrams("X86"), trigramsAre({"x86"}));
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000404
405 EXPECT_THAT(generateQueryTrigrams("clangd"),
406 trigramsAre({"cla", "lan", "ang", "ngd"}));
407
408 EXPECT_THAT(generateQueryTrigrams("abc_def"),
409 trigramsAre({"abc", "bcd", "cde", "def"}));
410
411 EXPECT_THAT(generateQueryTrigrams("a_b_c_d_e_"),
412 trigramsAre({"abc", "bcd", "cde"}));
413
414 EXPECT_THAT(generateQueryTrigrams("unique_ptr"),
415 trigramsAre({"uni", "niq", "iqu", "que", "uep", "ept", "ptr"}));
416
417 EXPECT_THAT(generateQueryTrigrams("TUDecl"),
418 trigramsAre({"tud", "ude", "dec", "ecl"}));
419
420 EXPECT_THAT(generateQueryTrigrams("IsOK"), trigramsAre({"iso", "sok"}));
421
422 EXPECT_THAT(generateQueryTrigrams("abc_defGhij__klm"),
423 trigramsAre({"abc", "bcd", "cde", "def", "efg", "fgh", "ghi",
424 "hij", "ijk", "jkl", "klm"}));
425}
426
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000427TEST(DexSearchTokens, SymbolPath) {
428 EXPECT_THAT(generateProximityURIs(
429 "unittest:///clang-tools-extra/clangd/index/Token.h"),
430 ElementsAre("unittest:///clang-tools-extra/clangd/index/Token.h",
431 "unittest:///clang-tools-extra/clangd/index",
432 "unittest:///clang-tools-extra/clangd",
433 "unittest:///clang-tools-extra", "unittest:///"));
434
435 EXPECT_THAT(generateProximityURIs("unittest:///a/b/c.h"),
436 ElementsAre("unittest:///a/b/c.h", "unittest:///a/b",
437 "unittest:///a", "unittest:///"));
438}
439
440//===----------------------------------------------------------------------===//
441// Index tests.
442//===----------------------------------------------------------------------===//
443
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000444TEST(Dex, Lookup) {
445 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000446 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
447 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000448 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000449 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000450 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000451 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000452}
453
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000454TEST(Dex, FuzzyFind) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000455 auto Index =
456 Dex::build(generateSymbols({"ns::ABC", "ns::BCD", "::ABC",
457 "ns::nested::ABC", "other::ABC", "other::A"}),
458 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000459 FuzzyFindRequest Req;
460 Req.Query = "ABC";
461 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000462 EXPECT_THAT(match(*Index, Req), UnorderedElementsAre("ns::ABC"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000463 Req.Scopes = {"ns::", "ns::nested::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000464 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000465 UnorderedElementsAre("ns::ABC", "ns::nested::ABC"));
466 Req.Query = "A";
467 Req.Scopes = {"other::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000468 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000469 UnorderedElementsAre("other::A", "other::ABC"));
470 Req.Query = "";
471 Req.Scopes = {};
Sam McCall9c7624e2018-09-03 14:37:43 +0000472 EXPECT_THAT(match(*Index, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000473 UnorderedElementsAre("ns::ABC", "ns::BCD", "::ABC",
474 "ns::nested::ABC", "other::ABC",
475 "other::A"));
476}
477
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000478TEST(DexTest, FuzzyMatchQ) {
479 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000480 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}),
481 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000482 FuzzyFindRequest Req;
483 Req.Query = "lol";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000484 Req.Limit = 2;
Sam McCall9c7624e2018-09-03 14:37:43 +0000485 EXPECT_THAT(match(*I, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000486 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
487}
488
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000489// FIXME(kbobyrev): This test is different for Dex and MemIndex: while
490// MemIndex manages response deduplication, Dex simply returns all matched
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000491// symbols which means there might be equivalent symbols in the response.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000492// Before drop-in replacement of MemIndex with Dex happens, FileIndex
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000493// should handle deduplication instead.
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000494TEST(DexTest, DexDeduplicate) {
Sam McCall9c7624e2018-09-03 14:37:43 +0000495 std::vector<Symbol> Symbols = {symbol("1"), symbol("2"), symbol("3"),
496 symbol("2") /* duplicate */};
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000497 FuzzyFindRequest Req;
Sam McCall9c7624e2018-09-03 14:37:43 +0000498 Req.Query = "2";
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000499 Dex I(Symbols, URISchemes);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000500 EXPECT_FALSE(Req.Limit);
Sam McCall9c7624e2018-09-03 14:37:43 +0000501 EXPECT_THAT(match(I, Req), ElementsAre("2", "2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000502}
503
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000504TEST(DexTest, DexLimitedNumMatches) {
505 auto I = Dex::build(generateNumSymbols(0, 100), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000506 FuzzyFindRequest Req;
507 Req.Query = "5";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000508 Req.Limit = 3;
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000509 bool Incomplete;
Sam McCall9c7624e2018-09-03 14:37:43 +0000510 auto Matches = match(*I, Req, &Incomplete);
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000511 EXPECT_TRUE(Req.Limit);
512 EXPECT_EQ(Matches.size(), *Req.Limit);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000513 EXPECT_TRUE(Incomplete);
514}
515
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000516TEST(DexTest, FuzzyMatch) {
517 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000518 generateSymbols({"LaughingOutLoud", "LionPopulation", "LittleOldLady"}),
519 URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000520 FuzzyFindRequest Req;
521 Req.Query = "lol";
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000522 Req.Limit = 2;
Sam McCall9c7624e2018-09-03 14:37:43 +0000523 EXPECT_THAT(match(*I, Req),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000524 UnorderedElementsAre("LaughingOutLoud", "LittleOldLady"));
525}
526
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000527TEST(DexTest, MatchQualifiedNamesWithoutSpecificScope) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000528 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000529 FuzzyFindRequest Req;
530 Req.Query = "y";
Sam McCall9c7624e2018-09-03 14:37:43 +0000531 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "b::y2", "y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000532}
533
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000534TEST(DexTest, MatchQualifiedNamesWithGlobalScope) {
Kirill Bobyrev249c5862018-09-13 17:11:03 +0000535 auto I = Dex::build(generateSymbols({"a::y1", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000536 FuzzyFindRequest Req;
537 Req.Query = "y";
538 Req.Scopes = {""};
Sam McCall9c7624e2018-09-03 14:37:43 +0000539 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000540}
541
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000542TEST(DexTest, MatchQualifiedNamesWithOneScope) {
543 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000544 generateSymbols({"a::y1", "a::y2", "a::x", "b::y2", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000545 FuzzyFindRequest Req;
546 Req.Query = "y";
547 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000548 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000549}
550
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000551TEST(DexTest, MatchQualifiedNamesWithMultipleScopes) {
552 auto I = Dex::build(
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000553 generateSymbols({"a::y1", "a::y2", "a::x", "b::y3", "y3"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000554 FuzzyFindRequest Req;
555 Req.Query = "y";
556 Req.Scopes = {"a::", "b::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000557 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1", "a::y2", "b::y3"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000558}
559
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000560TEST(DexTest, NoMatchNestedScopes) {
561 auto I = Dex::build(generateSymbols({"a::y1", "a::b::y2"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000562 FuzzyFindRequest Req;
563 Req.Query = "y";
564 Req.Scopes = {"a::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000565 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("a::y1"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000566}
567
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000568TEST(DexTest, IgnoreCases) {
569 auto I = Dex::build(generateSymbols({"ns::ABC", "ns::abc"}), URISchemes);
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000570 FuzzyFindRequest Req;
571 Req.Query = "AB";
572 Req.Scopes = {"ns::"};
Sam McCall9c7624e2018-09-03 14:37:43 +0000573 EXPECT_THAT(match(*I, Req), UnorderedElementsAre("ns::ABC", "ns::abc"));
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000574}
575
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000576TEST(DexTest, Lookup) {
577 auto I = Dex::build(generateSymbols({"ns::abc", "ns::xyz"}), URISchemes);
Sam McCall9c7624e2018-09-03 14:37:43 +0000578 EXPECT_THAT(lookup(*I, SymbolID("ns::abc")), UnorderedElementsAre("ns::abc"));
579 EXPECT_THAT(lookup(*I, {SymbolID("ns::abc"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000580 UnorderedElementsAre("ns::abc", "ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000581 EXPECT_THAT(lookup(*I, {SymbolID("ns::nonono"), SymbolID("ns::xyz")}),
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000582 UnorderedElementsAre("ns::xyz"));
Sam McCall9c7624e2018-09-03 14:37:43 +0000583 EXPECT_THAT(lookup(*I, SymbolID("ns::nonono")), UnorderedElementsAre());
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000584}
585
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000586TEST(DexTest, ProximityPathsBoosting) {
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000587 auto RootSymbol = symbol("root::abc");
588 RootSymbol.CanonicalDeclaration.FileURI = "unittest:///file.h";
589 auto CloseSymbol = symbol("close::abc");
590 CloseSymbol.CanonicalDeclaration.FileURI = "unittest:///a/b/c/d/e/f/file.h";
591
592 std::vector<Symbol> Symbols{CloseSymbol, RootSymbol};
Kirill Bobyrev5abe4782018-09-10 08:23:53 +0000593 Dex I(Symbols, URISchemes);
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000594
595 FuzzyFindRequest Req;
596 Req.Query = "abc";
597 // The best candidate can change depending on the proximity paths.
Kirill Bobyreve6dd0802018-09-13 14:27:03 +0000598 Req.Limit = 1;
Kirill Bobyrev19a94612018-09-06 12:54:43 +0000599
600 // FuzzyFind request comes from the file which is far from the root: expect
601 // CloseSymbol to come out.
602 Req.ProximityPaths = {testPath("a/b/c/d/e/f/file.h")};
603 EXPECT_THAT(match(I, Req), ElementsAre("close::abc"));
604
605 // FuzzyFind request comes from the file which is close to the root: expect
606 // RootSymbol to come out.
607 Req.ProximityPaths = {testPath("file.h")};
608 EXPECT_THAT(match(I, Req), ElementsAre("root::abc"));
609}
610
Kirill Bobyrev870aaf22018-08-20 14:39:32 +0000611} // namespace
Kirill Bobyrev5e82f052018-07-25 10:34:57 +0000612} // namespace dex
613} // namespace clangd
614} // namespace clang