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 "lsp/include/script_element_kind.h"
17 #include "lsp_api_test.h"
18 #include "lsp/include/internal_api.h"
19 #include <gtest/gtest.h>
20
21 using ark::es2panda::lsp::CompletionEntryKind;
22 using ark::es2panda::lsp::Initializer;
23
24 namespace {
25
26 class LspScriptElementKindTests : public LSPAPITests {};
27
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_1)28 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_1)
29 {
30 LSPAPI const *lspApi = GetImpl();
31 ASSERT_TRUE(lspApi != nullptr);
32
33 Initializer initializer = Initializer();
34 es2panda_Context *context = initializer.CreateContext(
35 "script_element_kind_1.ets", ES2PANDA_STATE_CHECKED,
36 "let number_literal: number = 1234;\nlet string_literal: string = \"hello\";\nconst str_property = "
37 "\"foo\";\n");
38
39 ASSERT_EQ(ContextState(context), ES2PANDA_STATE_CHECKED);
40 size_t const numberLiteralOffset = 31; // 31: position of '3' in '1234'
41 size_t const stringLiteralOffset = 96; // 96: position of first 'o' in 'foo'
42
43 auto result = lspApi->getAliasScriptElementKind(context, numberLiteralOffset);
44 ASSERT_EQ(result, CompletionEntryKind::TEXT); // Literal is VALUE
45 result = lspApi->getAliasScriptElementKind(context, stringLiteralOffset);
46 ASSERT_EQ(result, CompletionEntryKind::TEXT);
47 initializer.DestroyContext(context);
48 }
49
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_2)50 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_2)
51 {
52 LSPAPI const *lspApi = GetImpl();
53 Initializer initializer = Initializer();
54 es2panda_Context *context =
55 initializer.CreateContext("script_element_kind_2.ets", ES2PANDA_STATE_CHECKED,
56 " \nfunction f() {\n let a = 123;\n}\nconst s = \"hello\";\n");
57
58 size_t const startOfFile = 0; // 0: position of start of file, first space
59 size_t const firstleftCurlyBrance = 18; // 18:position of left curly brance after f()
60 size_t const numberLiteralOffset = 33; // 33: position of '2' in '123'
61 size_t const stringLiteralOffset = 50; // 50: position of 'h' in 'hello'
62
63 ASSERT_EQ(lspApi->getAliasScriptElementKind(context, startOfFile), CompletionEntryKind::TEXT);
64 ASSERT_EQ(lspApi->getAliasScriptElementKind(context, firstleftCurlyBrance), CompletionEntryKind::TEXT);
65 ASSERT_EQ(lspApi->getAliasScriptElementKind(context, numberLiteralOffset), CompletionEntryKind::TEXT);
66 ASSERT_EQ(lspApi->getAliasScriptElementKind(context, stringLiteralOffset), CompletionEntryKind::TEXT);
67
68 initializer.DestroyContext(context);
69 }
70
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_3)71 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_3)
72 {
73 LSPAPI const *lspApi = GetImpl();
74 Initializer initializer = Initializer();
75
76 const char *statement = R"(let empty: null = null;
77 let notAssigned: undefined = undefined;)";
78 es2panda_Context *context =
79 initializer.CreateContext("script_element_kind_3.ets", ES2PANDA_STATE_CHECKED, statement);
80
81 size_t const nullLiteral = 19; // 19:position of the second null.
82 size_t const etsNullType = 25; // 25: position of the second let.
83 size_t const undefinedLiteral = 54; // 54: position of the second undefined.
84
85 ASSERT_EQ(lspApi->getAliasScriptElementKind(context, nullLiteral), CompletionEntryKind::TEXT);
86 ASSERT_EQ(lspApi->getAliasScriptElementKind(context, etsNullType), CompletionEntryKind::TEXT);
87 ASSERT_EQ(lspApi->getAliasScriptElementKind(context, undefinedLiteral), CompletionEntryKind::TEXT);
88
89 initializer.DestroyContext(context);
90 }
91
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_4)92 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_4)
93 {
94 LSPAPI const *lspApi = GetImpl();
95 ASSERT_TRUE(lspApi != nullptr);
96 const std::string text = R"(class Person {
97 private body_ : string = '1';
98 }
99
100 type alias/*1*/ = Person;)";
101
102 auto pos = text.find("/*1*/");
103 ASSERT_NE(pos, std::string::npos);
104 Initializer initializer = Initializer();
105 auto context = initializer.CreateContext("aliasScriptElementKind_4.ets", ES2PANDA_STATE_CHECKED, text.c_str());
106
107 auto result = lspApi->getAliasScriptElementKind(context, pos);
108 EXPECT_EQ(result, CompletionEntryKind::CLASS);
109 initializer.DestroyContext(context);
110 }
111
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_5)112 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_5)
113 {
114 LSPAPI const *lspApi = GetImpl();
115 ASSERT_TRUE(lspApi != nullptr);
116 const std::string text = R"(
117 interface MockInterface {
118 parameter1: number;
119 parameter2: string;
120 parameter3: boolean;
121 }
122
123 type alias/*1*/ = MockInterface;)";
124
125 auto pos = text.find("/*1*/");
126 ASSERT_NE(pos, std::string::npos);
127 Initializer initializer = Initializer();
128 auto context = initializer.CreateContext("aliasScriptElementKind_5.ets", ES2PANDA_STATE_CHECKED, text.c_str());
129
130 auto result = lspApi->getAliasScriptElementKind(context, pos);
131 EXPECT_EQ(result, CompletionEntryKind::INTERFACE);
132 initializer.DestroyContext(context);
133 }
134
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_6)135 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_6)
136 {
137 LSPAPI const *lspApi = GetImpl();
138 ASSERT_TRUE(lspApi != nullptr);
139 const std::string text = R"(
140 @Entry
141 @Component
142 struct Index {
143 @State message: string = 'Hello World';
144
145 build() {
146 RelativeContainer() {
147 Text(this.message)
148 .id('HelloWorld')
149 .fontSize($r('app.float.page_text_font_size'))
150 .fontWeight(FontWeight.Bold)
151 .alignRules({
152 center: { anchor: '__container__', align: VerticalAlign.Center },
153 middle: { anchor: '__container__', align: HorizontalAlign.Center }
154 })
155 .onClick(() => {
156 this.message = 'Welcome';
157 })
158 }
159 .height('100%')
160 .width('100%')
161 }
162 }
163
164 type alias/*1*/ = Index;)";
165
166 auto pos = text.find("/*1*/");
167 ASSERT_NE(pos, std::string::npos);
168 Initializer initializer = Initializer();
169 auto context = initializer.CreateContext("aliasScriptElementKind_6.ets", ES2PANDA_STATE_CHECKED, text.c_str());
170
171 auto result = lspApi->getAliasScriptElementKind(context, pos);
172 EXPECT_EQ(result, CompletionEntryKind::CLASS);
173 initializer.DestroyContext(context);
174 }
175
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_7)176 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_7)
177 {
178 LSPAPI const *lspApi = GetImpl();
179 ASSERT_TRUE(lspApi != nullptr);
180 const std::string text = R"(type alias/*1*/ = '2';)";
181
182 auto pos = text.find("/*1*/");
183 ASSERT_NE(pos, std::string::npos);
184 Initializer initializer = Initializer();
185 auto context = initializer.CreateContext("aliasScriptElementKind_7.ets", ES2PANDA_STATE_CHECKED, text.c_str());
186
187 auto result = lspApi->getAliasScriptElementKind(context, pos);
188 EXPECT_EQ(result, CompletionEntryKind::VALUE);
189 initializer.DestroyContext(context);
190 }
191
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_8)192 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_8)
193 {
194 LSPAPI const *lspApi = GetImpl();
195 ASSERT_TRUE(lspApi != nullptr);
196 const std::string text = R"(type alias/*1*/ = undefinedType11;)";
197
198 auto pos = text.find("/*1*/");
199 ASSERT_NE(pos, std::string::npos);
200 Initializer initializer = Initializer();
201 auto context = initializer.CreateContext("aliasScriptElementKind_8.ets", ES2PANDA_STATE_CHECKED, text.c_str());
202 auto result = lspApi->getAliasScriptElementKind(context, pos);
203 EXPECT_EQ(result, CompletionEntryKind::ALIAS_TYPE);
204 initializer.DestroyContext(context);
205 }
206
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_9)207 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_9)
208 {
209 LSPAPI const *lspApi = GetImpl();
210 ASSERT_TRUE(lspApi != nullptr);
211 const std::string text = R"(type TestUnion/*1*/ = string | number;)";
212
213 auto pos = text.find("/*1*/");
214 ASSERT_NE(pos, std::string::npos);
215 Initializer initializer = Initializer();
216 auto context = initializer.CreateContext("aliasScriptElementKind_9.ets", ES2PANDA_STATE_CHECKED, text.c_str());
217 auto result = lspApi->getAliasScriptElementKind(context, pos);
218 EXPECT_EQ(result, CompletionEntryKind::TYPE_PARAMETER);
219 initializer.DestroyContext(context);
220 }
221
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_10)222 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_10)
223 {
224 LSPAPI const *lspApi = GetImpl();
225 ASSERT_TRUE(lspApi != nullptr);
226 const std::string text = R"(type Callback/*1*/ = (result: string) => void;)";
227
228 auto pos = text.find("/*1*/");
229 ASSERT_NE(pos, std::string::npos);
230 Initializer initializer = Initializer();
231 auto context = initializer.CreateContext("aliasScriptElementKind_10.ets", ES2PANDA_STATE_CHECKED, text.c_str());
232 auto result = lspApi->getAliasScriptElementKind(context, pos);
233 EXPECT_EQ(result, CompletionEntryKind::FUNCTION);
234 initializer.DestroyContext(context);
235 }
236
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_11)237 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_11)
238 {
239 LSPAPI const *lspApi = GetImpl();
240 ASSERT_TRUE(lspApi != nullptr);
241 const std::string text = R"(type Callback/*1*/ = () => {};)";
242
243 auto pos = text.find("/*1*/");
244 ASSERT_NE(pos, std::string::npos);
245 Initializer initializer = Initializer();
246 auto context = initializer.CreateContext("aliasScriptElementKind_11.ets", ES2PANDA_STATE_CHECKED, text.c_str());
247 auto result = lspApi->getAliasScriptElementKind(context, pos);
248 EXPECT_EQ(result, CompletionEntryKind::FUNCTION);
249 initializer.DestroyContext(context);
250 }
251
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_12)252 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_12)
253 {
254 LSPAPI const *lspApi = GetImpl();
255 ASSERT_TRUE(lspApi != nullptr);
256 const std::string text = R"(class Person {
257 private body_ : string = '1';
258 private body_ : string = 'ad';
259 }
260 type alias/*1*/ = Person;)";
261
262 auto pos = text.find("/*1*/");
263 ASSERT_NE(pos, std::string::npos);
264 Initializer initializer = Initializer();
265 auto context = initializer.CreateContext("aliasScriptElementKind_12.ets", ES2PANDA_STATE_CHECKED, text.c_str());
266 auto result = lspApi->getAliasScriptElementKind(context, pos);
267 EXPECT_EQ(result, CompletionEntryKind::CLASS);
268 initializer.DestroyContext(context);
269 }
270
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_13)271 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_13)
272 {
273 LSPAPI const *lspApi = GetImpl();
274 ASSERT_TRUE(lspApi != nullptr);
275
276 const std::string text = R"(type TestA<T>/*1*/ = Array<TestA<T>>;)";
277
278 auto pos = text.find("/*1*/");
279 ASSERT_NE(pos, std::string::npos);
280 Initializer initializer = Initializer();
281 auto context = initializer.CreateContext("aliasScriptElementKind_13.ets", ES2PANDA_STATE_CHECKED, text.c_str());
282 auto result = lspApi->getAliasScriptElementKind(context, pos);
283 EXPECT_EQ(result, CompletionEntryKind::CLASS);
284 initializer.DestroyContext(context);
285 }
286
TEST_F(LspScriptElementKindTests,GetAliasScriptElementKind_14)287 TEST_F(LspScriptElementKindTests, GetAliasScriptElementKind_14)
288 {
289 LSPAPI const *lspApi = GetImpl();
290 ASSERT_TRUE(lspApi != nullptr);
291
292 const std::string text = R"(type TestB<T>/*1*/ = string | Array<TestB<T>>;)";
293
294 auto pos = text.find("/*1*/");
295 ASSERT_NE(pos, std::string::npos);
296 Initializer initializer = Initializer();
297 auto context = initializer.CreateContext("aliasScriptElementKind_14.ets", ES2PANDA_STATE_CHECKED, text.c_str());
298 auto result = lspApi->getAliasScriptElementKind(context, pos);
299 EXPECT_EQ(result, CompletionEntryKind::TYPE_PARAMETER);
300 initializer.DestroyContext(context);
301 }
302
303 } // namespace
304