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,ExactMatchFromSingleFile)30 TEST_F(NavigateToTest, ExactMatchFromSingleFile)
31 {
32 std::vector<SourceFile> files = {{"exatchMatch.sts", R"(
33 class Test {
34 yeke: number = 2;
35 method() {
36 let b = 3;
37 return b;
38 }
39 }
40 )"}};
41 Initializer initializer;
42 std::vector<ark::es2panda::lsp::NavigateToItem> allResults;
43 const int maxResultCount = 10;
44 const int expectedResultSize = 1;
45 std::string searchTerm = "yeke";
46 std::string containerName = "Test";
47
48 for (const auto &file : files) {
49 std::string sourceStr(file.source);
50 es2panda_Context *ctx =
51 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
52 ASSERT_NE(ctx, nullptr);
53
54 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
55 auto results = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, false);
56 allResults.insert(allResults.end(), results.begin(), results.end());
57 }
58
59 ASSERT_EQ(allResults.size(), expectedResultSize);
60 ASSERT_EQ(allResults[0].name, searchTerm);
61 ASSERT_EQ(allResults[0].matchKind, ark::es2panda::lsp::MatchKind::EXACT);
62 ASSERT_EQ(allResults[0].containerName, containerName);
63 }
64
TEST_F(NavigateToTest,ExactPrefixAndSubstringMatch)65 TEST_F(NavigateToTest, ExactPrefixAndSubstringMatch)
66 {
67 std::vector<SourceFile> files = {{"ExactPrefixAndSubstringMatch1.sts", R"(
68 function foo() {
69 let a = 1;
70 return a;
71 }
72 )"},
73 {"ExactPrefixAndSubstringMatch2.sts", R"(
74 function foobar() {
75 let b = 2;
76 return b;
77 }
78 )"},
79 {"ExactPrefixAndSubstringMatch3.sts", R"(
80 function my_foo() {
81 let c = 3;
82 return c;
83 }
84 )"}};
85 Initializer initializer;
86 std::vector<ark::es2panda::lsp::NavigateToItem> allResults;
87 const int maxResultCount = 10;
88 const int expectedResultSize = 3;
89 std::string searchTerm = "foo";
90 const int thirdValueOfArray = 2;
91 std::string searchTermFoobar = "foobar";
92 std::string searchTermMyFoo = "my_foo";
93
94 for (const auto &file : files) {
95 std::string sourceStr(file.source);
96 es2panda_Context *ctx =
97 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
98 ASSERT_NE(ctx, nullptr);
99
100 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
101 auto results = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, false);
102 allResults.insert(allResults.end(), results.begin(), results.end());
103
104 initializer.DestroyContext(ctx);
105 }
106 ASSERT_EQ(allResults.size(), expectedResultSize); // "foo", "foobar", "my_foo"
107 ASSERT_EQ(allResults[0].name, searchTerm);
108 ASSERT_EQ(allResults[0].matchKind, ark::es2panda::lsp::MatchKind::EXACT);
109 ASSERT_EQ(allResults[1].name, searchTermFoobar);
110 ASSERT_EQ(allResults[1].matchKind, ark::es2panda::lsp::MatchKind::PREFIX);
111 ASSERT_EQ(allResults[thirdValueOfArray].name, searchTermMyFoo);
112 ASSERT_EQ(allResults[thirdValueOfArray].matchKind, ark::es2panda::lsp::MatchKind::SUBSTRING);
113 }
114
TEST_F(NavigateToTest,CaseInsensitiveMatch)115 TEST_F(NavigateToTest, CaseInsensitiveMatch)
116 {
117 std::vector<SourceFile> files = {{"caseInsensitiveMatch1.sts", R"(
118 function foo() {
119 let a = 1;
120 return a;
121 }
122 )"},
123 {"caseInsensitiveMatch2.sts", R"(
124 function foobar() {
125 let b = 2;
126 return b;
127 }
128 )"},
129 {"caseInsensitiveMatch3.sts", R"(
130 function my_foo() {
131 let c = 3;
132 return c;
133 }
134 )"}};
135 Initializer initializer;
136 std::vector<ark::es2panda::lsp::NavigateToItem> allResults;
137 const int maxResultCount = 10;
138 const int expectedResultSize = 3;
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 results = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, false); // case-insensitive
149 allResults.insert(allResults.end(), results.begin(), results.end());
150
151 initializer.DestroyContext(ctx);
152 }
153 ASSERT_EQ(allResults.size(), expectedResultSize);
154 }
155
TEST_F(NavigateToTest,CaseSensitiveMismatch)156 TEST_F(NavigateToTest, CaseSensitiveMismatch)
157 {
158 std::vector<SourceFile> files = {{"caseSensitiveMismatch1.sts", R"(
159 function foo() {
160 let a = 1;
161 return a;
162 }
163 )"},
164 {"caseSensitiveMismatch2.sts", R"(
165 function foobar() {
166 let b = 2;
167 return b;
168 }
169 )"},
170 {"caseSensitiveMismatch3.sts", R"(
171 function my_foo() {
172 let c = 3;
173 return c;
174 }
175 )"}};
176 Initializer initializer;
177 std::vector<ark::es2panda::lsp::NavigateToItem> allResults;
178 const int maxResultCount = 10;
179 std::string searchTerm = "FOO";
180
181 for (const auto &file : files) {
182 std::string sourceStr(file.source);
183 es2panda_Context *ctx =
184 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
185 ASSERT_NE(ctx, nullptr);
186
187 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
188 auto results = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, true); // case-sensitive
189 allResults.insert(allResults.end(), results.begin(), results.end());
190
191 initializer.DestroyContext(ctx);
192 }
193 ASSERT_TRUE(allResults.empty());
194 }
195
TEST_F(NavigateToTest,NoMatchFound)196 TEST_F(NavigateToTest, NoMatchFound)
197 {
198 std::vector<SourceFile> files = {{"noMatchFound1.sts", R"(
199 function foo() {
200 let a = 1;
201 return a;
202 }
203 )"},
204 {"noMatchFound2.sts", R"(
205 function foobar() {
206 let b = 2;
207 return b;
208 }
209 )"},
210 {"noMatchFound3.sts", R"(
211 function my_foo() {
212 let c = 3;
213 return c;
214 }
215 )"}};
216 Initializer initializer;
217 std::vector<ark::es2panda::lsp::NavigateToItem> allResults;
218 const int maxResultCount = 10;
219 std::string searchTerm = "nonexistent";
220
221 for (const auto &file : files) {
222 std::string sourceStr(file.source);
223 es2panda_Context *ctx =
224 initializer.CreateContext(file.filePath.data(), ES2PANDA_STATE_CHECKED, sourceStr.c_str());
225 ASSERT_NE(ctx, nullptr);
226
227 std::vector<SourceFile> singleFile = {{file.filePath, sourceStr}};
228 auto results = GetNavigateToItems(ctx, singleFile, maxResultCount, searchTerm, false);
229 allResults.insert(allResults.end(), results.begin(), results.end());
230
231 initializer.DestroyContext(ctx);
232 }
233 ASSERT_TRUE(allResults.empty());
234 }
235
236 } // namespace