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/get_adjusted_location.h"
17 #include "gtest/gtest.h"
18 #include "lsp_api_test.h"
19 #include "public/es2panda_lib.h"
20 #include "test/utils/ast_verifier_test.h"
21 #include "lsp/include/internal_api.h"
22
23 using ark::es2panda::ir::AstNode;
24 using ark::es2panda::ir::AstNodeType;
25
26 namespace {
27 constexpr size_t PROPERTY_POS = 23;
28 constexpr size_t FUNCTION_POS = 10;
29 constexpr size_t PRIVATE_POS = 25;
30 constexpr size_t PUBLIC_POS = 47;
31 constexpr size_t STATIC_POS = 69;
32 constexpr size_t CLASS_POS = 6;
33 constexpr size_t METHOD_POS = 23;
34 constexpr size_t VARIABLE_POS = 5;
35 constexpr size_t MEMBER_POS = 28;
36 constexpr size_t TYPE_PARAM_POS = 7;
37 constexpr size_t ARRAY_TYPE_POS = 25;
38 constexpr size_t HERITAGE_POS = 45;
39 constexpr size_t EXPRESSION_POS = 9;
40 constexpr size_t IMPORT_POS = 7;
41 constexpr size_t EXPORT_POS = 7;
42 } // namespace
43
44 class LspGetAdjustedLocation : public LSPAPITests {};
45
TEST_F(LspGetAdjustedLocation,GetAdjustedLocationForVariableTest)46 TEST_F(LspGetAdjustedLocation, GetAdjustedLocationForVariableTest)
47 {
48 const char *source = R"(
49 let x = 42;
50 function test() {
51 let y = x;
52 return y;
53 }
54 let z = x;
55 )";
56
57 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
58 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
59 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
60 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
61 auto *varNode = ark::es2panda::lsp::GetTouchingPropertyName(ctx, VARIABLE_POS);
62 ASSERT_NE(varNode, nullptr);
63 auto adjustedVar = ark::es2panda::lsp::GetAdjustedLocation(varNode, true, context->allocator);
64 ASSERT_TRUE(adjustedVar.has_value());
65 EXPECT_TRUE((*adjustedVar)->IsIdentifier());
66 EXPECT_EQ((*adjustedVar)->AsIdentifier()->Name(), "x");
67 initializer.DestroyContext(ctx);
68 }
69
TEST_F(LspGetAdjustedLocation,GetTouchingPropertyNameTest)70 TEST_F(LspGetAdjustedLocation, GetTouchingPropertyNameTest)
71 {
72 const char *source = R"(
73 class Example {
74 property = "test";
75 }
76 )";
77
78 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
79 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_PARSED, source);
80 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_PARSED);
81 auto *node = ark::es2panda::lsp::GetTouchingPropertyName(ctx, PROPERTY_POS);
82 ASSERT_NE(node, nullptr);
83 EXPECT_TRUE(node->IsIdentifier());
84 EXPECT_EQ(node->AsIdentifier()->Name(), "property");
85 initializer.DestroyContext(ctx);
86 }
87
TEST_F(LspGetAdjustedLocation,GetAdjustedLocationForClassTest)88 TEST_F(LspGetAdjustedLocation, GetAdjustedLocationForClassTest)
89 {
90 const char *source = R"(
91 class MyClass {
92 prop = 0;
93 method() {
94 return this.prop;
95 }
96 }
97 let instance = new MyClass();
98 )";
99 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
100 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
101 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
102 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
103 AstNode *classNode = ark::es2panda::lsp::GetTouchingPropertyName(ctx, CLASS_POS);
104 ASSERT_NE(classNode, nullptr);
105 ASSERT_TRUE(classNode->IsClassDeclaration());
106 auto adjustedClass = ark::es2panda::lsp::GetAdjustedLocationForClass(classNode, context->allocator);
107 ASSERT_TRUE(adjustedClass.has_value());
108 ASSERT_NE(*adjustedClass, nullptr);
109 EXPECT_TRUE((*adjustedClass)->IsIdentifier());
110 EXPECT_EQ((*adjustedClass)->AsIdentifier()->Name(), "MyClass");
111 initializer.DestroyContext(ctx);
112 }
113
TEST_F(LspGetAdjustedLocation,GetAdjustedLocationForFunctionTest)114 TEST_F(LspGetAdjustedLocation, GetAdjustedLocationForFunctionTest)
115 {
116 const char *source = R"(
117 function testFunc(param: number) {
118 return param * 2;
119 }
120 let result = testFunc(21);
121 )";
122 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
123 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_PARSED, source);
124 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_PARSED);
125 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
126 auto *funcNode = ark::es2panda::lsp::GetTouchingPropertyName(ctx, FUNCTION_POS);
127 ASSERT_NE(funcNode, nullptr);
128 ASSERT_TRUE(funcNode->IsIdentifier());
129 EXPECT_EQ(funcNode->AsIdentifier()->Name(), "testFunc");
130 auto *parent = funcNode->Parent();
131 ASSERT_NE(parent, nullptr);
132 auto adjustedFunc = ark::es2panda::lsp::GetAdjustedLocationForFunction(parent, context->allocator);
133 ASSERT_TRUE(adjustedFunc.has_value());
134 ASSERT_NE(*adjustedFunc, nullptr);
135 EXPECT_TRUE((*adjustedFunc)->IsIdentifier());
136 EXPECT_EQ((*adjustedFunc)->AsIdentifier()->Name(), "testFunc");
137 initializer.DestroyContext(ctx);
138 }
139
TEST_F(LspGetAdjustedLocation,GetChildrenTest)140 TEST_F(LspGetAdjustedLocation, GetChildrenTest)
141 {
142 const char *source = R"(
143 class Test {
144 x = 1;
145 y = "test";
146 method() {}
147 }
148 )";
149 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
150 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
151 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
152 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
153 auto *classNode = ark::es2panda::lsp::GetTouchingPropertyName(ctx, CLASS_POS);
154 ASSERT_NE(classNode, nullptr);
155 auto children = ark::es2panda::lsp::GetChildren(classNode, context->allocator);
156 bool hasXProperty = false;
157 bool hasYProperty = false;
158 bool hasMethod = false;
159 for (const auto *child : children) {
160 if (child->IsIdentifier()) {
161 auto name = child->AsIdentifier()->Name();
162 if (name == "x") {
163 hasXProperty = true;
164 }
165 if (name == "y") {
166 hasYProperty = true;
167 }
168 if (name == "method") {
169 hasMethod = true;
170 }
171 }
172 }
173 EXPECT_TRUE(hasXProperty) << "x property not found";
174 EXPECT_TRUE(hasYProperty) << "y property not found";
175 EXPECT_TRUE(hasMethod) << "method not found";
176 initializer.DestroyContext(ctx);
177 }
178
TEST_F(LspGetAdjustedLocation,IsModifierTest)179 TEST_F(LspGetAdjustedLocation, IsModifierTest)
180 {
181 const char *source = R"(
182 class Test {
183 private x: number;
184 public y: string;
185 static z: boolean;
186 }
187 )";
188 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
189 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_PARSED, source);
190 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_PARSED);
191 auto *privateNode = ark::es2panda::lsp::GetTouchingPropertyName(ctx, PRIVATE_POS);
192 auto *publicNode = ark::es2panda::lsp::GetTouchingPropertyName(ctx, PUBLIC_POS);
193 auto *staticNode = ark::es2panda::lsp::GetTouchingPropertyName(ctx, STATIC_POS);
194 auto *nonModifierNode1 = ark::es2panda::lsp::GetTouchingPropertyName(ctx, PRIVATE_POS + 1);
195 auto *nonModifierNode2 = ark::es2panda::lsp::GetTouchingPropertyName(ctx, PUBLIC_POS + 1);
196 auto *nonModifierNode3 = ark::es2panda::lsp::GetTouchingPropertyName(ctx, STATIC_POS + 1);
197 if (privateNode != nullptr) {
198 EXPECT_TRUE(ark::es2panda::lsp::IsModifier(privateNode));
199 }
200 if (publicNode != nullptr) {
201 EXPECT_TRUE(ark::es2panda::lsp::IsModifier(publicNode));
202 }
203 if (staticNode != nullptr) {
204 EXPECT_TRUE(ark::es2panda::lsp::IsModifier(staticNode));
205 }
206 if (nonModifierNode1 != nullptr) {
207 EXPECT_FALSE(ark::es2panda::lsp::IsModifier(nonModifierNode1));
208 }
209 if (nonModifierNode2 != nullptr) {
210 EXPECT_FALSE(ark::es2panda::lsp::IsModifier(nonModifierNode2));
211 }
212 if (nonModifierNode3 != nullptr) {
213 EXPECT_FALSE(ark::es2panda::lsp::IsModifier(nonModifierNode3));
214 }
215 initializer.DestroyContext(ctx);
216 }
217
TEST_F(LspGetAdjustedLocation,GetAdjustedLocationForNestedScopeTest)218 TEST_F(LspGetAdjustedLocation, GetAdjustedLocationForNestedScopeTest)
219 {
220 const char *source =
221 "let x = 1;\n"
222 "class Test {\n"
223 " x: number = 2;\n"
224 " method() {\n"
225 " let x = 3;\n"
226 " return x;\n"
227 " }\n"
228 "}\n";
229 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
230 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
231 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
232 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
233 auto *globalVar = ark::es2panda::lsp::GetTouchingPropertyName(ctx, VARIABLE_POS);
234 if (globalVar != nullptr) {
235 auto adjustedGlobal = ark::es2panda::lsp::GetAdjustedLocation(globalVar, true, context->allocator);
236 if (adjustedGlobal.has_value()) {
237 EXPECT_TRUE((*adjustedGlobal)->IsIdentifier());
238 EXPECT_EQ((*adjustedGlobal)->AsIdentifier()->Name(), "x");
239 }
240 }
241 auto *memberVar = ark::es2panda::lsp::GetTouchingPropertyName(ctx, MEMBER_POS);
242 if (memberVar != nullptr) {
243 auto adjustedMember = ark::es2panda::lsp::GetAdjustedLocation(memberVar, true, context->allocator);
244 if (adjustedMember.has_value()) {
245 EXPECT_TRUE((*adjustedMember)->IsIdentifier());
246 EXPECT_EQ((*adjustedMember)->AsIdentifier()->Name(), "x");
247 }
248 }
249 initializer.DestroyContext(ctx);
250 }
251
TEST_F(LspGetAdjustedLocation,GetAdjustedLocationForImportTest)252 TEST_F(LspGetAdjustedLocation, GetAdjustedLocationForImportTest)
253 {
254 const char *source = R"(
255 class MyClass {
256 method() {}
257 }
258 let instance = new MyClass();
259 )";
260 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
261 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
262 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
263 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
264 auto *node = ark::es2panda::lsp::GetTouchingPropertyName(ctx, IMPORT_POS);
265 ASSERT_NE(node, nullptr);
266 auto adjusted = ark::es2panda::lsp::GetAdjustedLocation(node, true, context->allocator);
267 ASSERT_TRUE(adjusted.has_value());
268 EXPECT_TRUE((*adjusted)->IsIdentifier());
269 EXPECT_EQ((*adjusted)->AsIdentifier()->Name(), "MyClass");
270 initializer.DestroyContext(ctx);
271 }
272
TEST_F(LspGetAdjustedLocation,GetAdjustedLocationForExportTest)273 TEST_F(LspGetAdjustedLocation, GetAdjustedLocationForExportTest)
274 {
275 const char *source = R"(
276 class MyClass {
277 method() {}
278 }
279 let instance = new MyClass();
280 )";
281 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
282 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
283 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
284 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
285 auto *node = ark::es2panda::lsp::GetTouchingPropertyName(ctx, EXPORT_POS);
286 ASSERT_NE(node, nullptr);
287 auto adjusted = ark::es2panda::lsp::GetAdjustedLocation(node, true, context->allocator);
288 ASSERT_TRUE(adjusted.has_value());
289 EXPECT_TRUE((*adjusted)->IsIdentifier());
290 EXPECT_EQ((*adjusted)->AsIdentifier()->Name(), "MyClass");
291 initializer.DestroyContext(ctx);
292 }
293
TEST_F(LspGetAdjustedLocation,GetAdjustedLocationForHeritageTest)294 TEST_F(LspGetAdjustedLocation, GetAdjustedLocationForHeritageTest)
295 {
296 const char *source = R"(
297 class BaseClass {}
298 class ChildClass extends BaseClass {}
299 )";
300 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
301 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
302 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
303 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
304 auto *node = ark::es2panda::lsp::GetTouchingPropertyName(ctx, HERITAGE_POS);
305 ASSERT_NE(node, nullptr);
306 auto adjusted = ark::es2panda::lsp::GetAdjustedLocation(node, true, context->allocator);
307 ASSERT_TRUE(adjusted.has_value());
308 EXPECT_TRUE((*adjusted)->IsIdentifier());
309 EXPECT_EQ((*adjusted)->AsIdentifier()->Name(), "BaseClass");
310 initializer.DestroyContext(ctx);
311 }
312
TEST_F(LspGetAdjustedLocation,FindTypeReferenceTest)313 TEST_F(LspGetAdjustedLocation, FindTypeReferenceTest)
314 {
315 const char *source = R"(
316 class MyType {}
317 let variable: MyType;
318 )";
319 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
320 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
321 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
322 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
323 auto *node = ark::es2panda::lsp::GetTouchingPropertyName(ctx, TYPE_PARAM_POS);
324 ASSERT_NE(node, nullptr);
325 auto adjusted = ark::es2panda::lsp::GetAdjustedLocation(node, true, context->allocator);
326 ASSERT_TRUE(adjusted.has_value());
327 EXPECT_TRUE((*adjusted)->IsIdentifier());
328 EXPECT_EQ((*adjusted)->AsIdentifier()->Name(), "MyType");
329 initializer.DestroyContext(ctx);
330 }
331
TEST_F(LspGetAdjustedLocation,FindArrayTypeTest)332 TEST_F(LspGetAdjustedLocation, FindArrayTypeTest)
333 {
334 const char *source = R"(
335 type NumArray = number[];
336 let numbers: NumArray;
337 )";
338 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
339 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_PARSED, source);
340 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_PARSED);
341 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
342 auto *node = ark::es2panda::lsp::GetTouchingToken(ctx, ARRAY_TYPE_POS, true);
343 ASSERT_NE(node, nullptr);
344 auto children = ark::es2panda::lsp::GetChildren(node, context->allocator);
345 auto *arrayType = ark::es2panda::lsp::FindArrayType(node, children);
346 ASSERT_NE(arrayType, nullptr);
347 EXPECT_TRUE(arrayType->IsTSArrayType());
348 initializer.DestroyContext(ctx);
349 }
350
TEST_F(LspGetAdjustedLocation,SkipOuterExpressionsTest)351 TEST_F(LspGetAdjustedLocation, SkipOuterExpressionsTest)
352 {
353 const char *source = R"(
354 let x = (((42)));
355 )";
356 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
357 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
358 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
359 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
360 auto *node = ark::es2panda::lsp::GetTouchingPropertyName(ctx, VARIABLE_POS);
361 ASSERT_NE(node, nullptr);
362 auto adjusted = ark::es2panda::lsp::GetAdjustedLocation(node, true, context->allocator);
363 ASSERT_TRUE(adjusted.has_value());
364 EXPECT_TRUE((*adjusted)->IsIdentifier());
365 EXPECT_EQ((*adjusted)->AsIdentifier()->Name(), "x");
366 initializer.DestroyContext(ctx);
367 }
368
TEST_F(LspGetAdjustedLocation,FindFirstExpressionTest)369 TEST_F(LspGetAdjustedLocation, FindFirstExpressionTest)
370 {
371 const char *source = R"(
372 let x = 42 + (5 * 3);
373 )";
374 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
375 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
376 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
377 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
378 auto *node = ark::es2panda::lsp::GetTouchingPropertyName(ctx, VARIABLE_POS);
379 ASSERT_NE(node, nullptr);
380 auto children = ark::es2panda::lsp::GetChildren(node, context->allocator);
381 auto *found = ark::es2panda::lsp::FindFirstExpression(node, children);
382 ASSERT_NE(found, nullptr);
383 EXPECT_TRUE(found->IsExpression());
384 initializer.DestroyContext(ctx);
385 }
386
TEST_F(LspGetAdjustedLocation,FindFirstExpressionAfterTest)387 TEST_F(LspGetAdjustedLocation, FindFirstExpressionAfterTest)
388 {
389 const char *source = R"(let x = 1 + 2 + 3;)";
390 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
391 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
392 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
393 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
394 auto *node = ark::es2panda::lsp::GetTouchingToken(ctx, EXPRESSION_POS, true);
395 ASSERT_NE(node, nullptr);
396 auto children = ark::es2panda::lsp::GetChildren(node, context->allocator);
397 auto *firstExpr = ark::es2panda::lsp::FindFirstExpression(node, children);
398 ASSERT_NE(firstExpr, nullptr);
399 auto *afterFirst = ark::es2panda::lsp::FindFirstExpressionAfter(node, firstExpr, children);
400 ASSERT_NE(afterFirst, nullptr);
401 EXPECT_TRUE(afterFirst->IsExpression());
402 initializer.DestroyContext(ctx);
403 }
404
TEST_F(LspGetAdjustedLocation,FindNodeOfTypeTest)405 TEST_F(LspGetAdjustedLocation, FindNodeOfTypeTest)
406 {
407 const char *source = R"(
408 class TestClass {
409 method() {
410 return 42;
411 }
412 }
413 )";
414 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
415 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
416 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
417 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
418 auto *node = ark::es2panda::lsp::GetTouchingToken(ctx, METHOD_POS, true);
419 ASSERT_NE(node, nullptr);
420 auto children = ark::es2panda::lsp::GetChildren(node, context->allocator);
421 auto *methodBody = ark::es2panda::lsp::FindNodeOfType(node, AstNodeType::BLOCK_STATEMENT, children);
422 ASSERT_NE(methodBody, nullptr);
423 auto methodChildren = ark::es2panda::lsp::GetChildren(methodBody, context->allocator);
424 auto *found = ark::es2panda::lsp::FindNodeOfType(methodBody, AstNodeType::RETURN_STATEMENT, methodChildren);
425 ASSERT_NE(found, nullptr);
426 EXPECT_TRUE(found->IsReturnStatement());
427 initializer.DestroyContext(ctx);
428 }
429
TEST_F(LspGetAdjustedLocation,FindTypeParameterTest)430 TEST_F(LspGetAdjustedLocation, FindTypeParameterTest)
431 {
432 const char *source = R"(
433 class Container<T> {
434 value: T;
435 }
436 )";
437 ark::es2panda::lsp::Initializer initializer = ark::es2panda::lsp::Initializer();
438 es2panda_Context *ctx = initializer.CreateContext("test.ets", ES2PANDA_STATE_CHECKED, source);
439 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
440 auto *context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
441 auto *node = ark::es2panda::lsp::GetTouchingToken(ctx, TYPE_PARAM_POS, true);
442 ASSERT_NE(node, nullptr);
443 auto children = ark::es2panda::lsp::GetChildren(node, context->allocator);
444 auto *typeParam = ark::es2panda::lsp::FindTypeParameter(node, children);
445 ASSERT_NE(typeParam, nullptr);
446 EXPECT_TRUE(typeParam->IsTSTypeParameterDeclaration() || typeParam->IsIdentifier());
447 if (typeParam->IsIdentifier()) {
448 EXPECT_EQ(typeParam->AsIdentifier()->Name(), "T");
449 }
450 initializer.DestroyContext(ctx);
451 }