1 /**
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include <gtest/gtest.h>
17 #include "lsp_api_test.h"
18 #include "lsp/include/navigate_to.h"
19
20 namespace {
21
22 using ark::es2panda::SourceFile;
23 using ark::es2panda::lsp::GetNavigateToItems;
24 using ark::es2panda::lsp::Initializer;
25 using std::string;
26 using std::vector;
27
28 class NavigateToTest : public LSPAPITests {};
29
TEST_F(NavigateToTest,MatchLimitRespected)30 TEST_F(NavigateToTest, MatchLimitRespected)
31 {
32 std::vector<SourceFile> files = {{"matchLimitRespected1.sts", R"(
33 function foo() {
34 let a = 1;
35 return a;
36 }
37 )"},
38 {"matchLimitRespected2.sts", R"(
39 function foobar() {
40 let b = 2;
41 return b;
42 }
43 )"},
44 {"matchLimitRespected3.sts", R"(
45 function my_foo() {
46 let c = 3;
47 return c;
48 }
49 )"}};
50 const int maxResultCountTwo = 2;
51 const int expectedResultSize = 2;
52 std::string searchTerm = "foo";
53
54 Initializer initializer;
55 std::vector<ark::es2panda::lsp::NavigateToItem> allResults;
56
57 for (const auto &file : files) {
58 std::string sourceStr(file.source);
59 es2panda_Context *ctx =
60 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
61 ASSERT_NE(ctx, nullptr);
62
63 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
64 auto matches = GetNavigateToItems(ctx, singleFile, maxResultCountTwo, searchTerm, false);
65 allResults.insert(allResults.end(), matches.begin(), matches.end());
66
67 initializer.DestroyContext(ctx);
68 }
69
70 ASSERT_LE(allResults.size(), expectedResultSize);
71 }
72
TEST_F(NavigateToTest,MultiFileSubstringMatch)73 TEST_F(NavigateToTest, MultiFileSubstringMatch)
74 {
75 std::vector<SourceFile> files = {{"multiFileSubstringMatch1.sts", R"(
76 function foo() {
77 let a = 1;
78 return a;
79 }
80 )"},
81 {"multiFileSubstringMatch2.sts", R"(
82 function foobar() {
83 let b = 2;
84 return b;
85 }
86 )"},
87 {"multiFileSubstringMatch3.sts", R"(
88 function my_foo() {
89 let c = 3;
90 return c;
91 }
92 )"}};
93 Initializer initializer;
94 const int maxResultCount = 10;
95 size_t totalMatches = 0;
96 std::string searchTerm = "_foo";
97 const int expectedResultSize = 1;
98
99 for (const auto &file : files) {
100 std::string sourceStr(file.source);
101 es2panda_Context *ctx =
102 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
103 ASSERT_NE(ctx, nullptr);
104
105 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
106 auto matches = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, false);
107 totalMatches += matches.size();
108
109 initializer.DestroyContext(ctx);
110 }
111
112 ASSERT_EQ(totalMatches, expectedResultSize);
113 }
114
TEST_F(NavigateToTest,PrefixMatchOnly)115 TEST_F(NavigateToTest, PrefixMatchOnly)
116 {
117 std::vector<SourceFile> files = {{"prefixMatchOnly1.sts", R"(
118 function foo() {
119 let a = 1;
120 return a;
121 }
122 )"},
123 {"prefixMatchOnly2.sts", R"(
124 function foobar() {
125 let b = 2;
126 return b;
127 }
128 )"},
129 {"prefixMatchOnly3.sts", R"(
130 function my_foo() {
131 let c = 3;
132 return c;
133 }
134 )"}};
135 Initializer initializer;
136 const int maxResultCount = 10;
137 size_t prefixCount = 0;
138 const int expectedResultSize = 1;
139 std::string searchTerm = "foo";
140
141 for (const auto &file : files) {
142 std::string sourceStr(file.source);
143 es2panda_Context *ctx =
144 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
145 ASSERT_NE(ctx, nullptr);
146
147 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
148 auto matches = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, false);
149 for (const auto &match : matches) {
150 if (match.matchKind == ark::es2panda::lsp::MatchKind::PREFIX) {
151 ++prefixCount;
152 }
153 }
154
155 initializer.DestroyContext(ctx);
156 }
157
158 ASSERT_EQ(prefixCount, expectedResultSize); // Only "foobar" is a PREFIX of "foo"
159 }
160
TEST_F(NavigateToTest,MatchFromSecondFile)161 TEST_F(NavigateToTest, MatchFromSecondFile)
162 {
163 std::vector<SourceFile> files = {{"matchFromSecondFile1.sts", R"(
164 function foo() {
165 let a = 1;
166 return a;
167 }
168 )"},
169 {"matchFromSecondFile2.sts", R"(
170 function foobar() {
171 let b = 2;
172 return b;
173 }
174 )"},
175 {"matchFromSecondFile3.sts", R"(
176 function my_foo() {
177 let c = 3;
178 return c;
179 }
180 )"}};
181 Initializer initializer;
182 const int maxResultCount = 10;
183 const int expectedResultSize = 1;
184 std::string searchTerm = "foobar";
185 std::vector<ark::es2panda::lsp::NavigateToItem> matches;
186
187 for (const auto &file : files) {
188 std::string sourceStr(file.source);
189 es2panda_Context *ctx =
190 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
191 ASSERT_NE(ctx, nullptr);
192
193 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
194 auto results = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, false);
195 matches.insert(matches.end(), results.begin(), results.end());
196
197 initializer.DestroyContext(ctx);
198 }
199 ASSERT_EQ(matches.size(), expectedResultSize);
200 ASSERT_EQ(matches[0].name, searchTerm);
201 }
202
TEST_F(NavigateToTest,MatchOnClassMember)203 TEST_F(NavigateToTest, MatchOnClassMember)
204 {
205 std::vector<SourceFile> files = {{"matchOnClassMember1.sts", R"(
206 class Test {
207 yeke: number = 2;
208 method() {
209 let b = 3;
210 return b;
211 }
212 }
213 )"},
214 {"matchOnClassMember2.sts", R"(
215 function foobar() {
216 let b = 2;
217 return b;
218 }
219 )"},
220 {"matchOnClassMember3.sts", R"(
221 function my_foo() {
222 let c = 3;
223 return c;
224 }
225 )"}};
226 Initializer initializer;
227 const int maxResultCount = 10;
228 const int expectedResultSize = 1;
229 std::string searchTerm = "yeke";
230 std::string containerName = "Test";
231 std::vector<ark::es2panda::lsp::NavigateToItem> results;
232
233 for (const auto &file : files) {
234 std::string sourceStr(file.source);
235 es2panda_Context *ctx =
236 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
237 ASSERT_NE(ctx, nullptr);
238
239 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
240 auto items = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, false);
241 results.insert(results.end(), items.begin(), items.end());
242
243 initializer.DestroyContext(ctx);
244 }
245
246 ASSERT_EQ(results.size(), expectedResultSize);
247 ASSERT_EQ(results[0].name, searchTerm);
248 ASSERT_EQ(results[0].containerName, containerName);
249 }
250
251 } // namespace