• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/rename.h"
17 #include <gtest/gtest.h>
18 #include <cstddef>
19 #include <cstdio>
20 #include <optional>
21 #include <string>
22 #include "lexer/token/letters.h"
23 #include "lsp/include/internal_api.h"
24 #include "lsp_api_test.h"
25 
26 using ark::es2panda::lsp::Initializer;
27 
28 class LspRenameInfoTests : public LSPAPITests {};
29 
TEST_F(LspRenameInfoTests,RenameInfoCreateTriggerSpanForNodeNumberLiteral)30 TEST_F(LspRenameInfoTests, RenameInfoCreateTriggerSpanForNodeNumberLiteral)
31 {
32     Initializer initializer = Initializer();
33 
34     es2panda_Context *ctx = initializer.CreateContext("trigger-span-literal.ets", ES2PANDA_STATE_CHECKED,
35                                                       "let number_literal: number = 1234\n");
36     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
37 
38     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
39     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
40         return node->IsNumberLiteral() && node->AsNumberLiteral()->Str() == "1234";
41     });
42     ASSERT_NE(targetNode, nullptr);
43 
44     auto result = ark::es2panda::lsp::CreateTriggerSpanForNode(targetNode);
45     size_t const expectedStart = 29;
46     size_t const expectedLength = 4;
47     ASSERT_EQ(result.start, expectedStart);
48     ASSERT_EQ(result.length, expectedLength);
49     initializer.DestroyContext(ctx);
50 }
51 
TEST_F(LspRenameInfoTests,RenameInfoCreateTriggerSpanForNodeStringLiteral)52 TEST_F(LspRenameInfoTests, RenameInfoCreateTriggerSpanForNodeStringLiteral)
53 {
54     Initializer initializer = Initializer();
55 
56     es2panda_Context *ctx = initializer.CreateContext("trigger-span-string-literal.ets", ES2PANDA_STATE_CHECKED,
57                                                       "let string_literal: string = \"hello\";\n");
58     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
59 
60     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
61     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
62         return node->IsStringLiteral() && node->AsStringLiteral()->Str() == "hello";
63     });
64     ASSERT_NE(targetNode, nullptr);
65 
66     auto result = ark::es2panda::lsp::CreateTriggerSpanForNode(targetNode);
67     size_t const expectedStart = 30;
68     size_t const expectedLength = 5;
69     ASSERT_EQ(result.start, expectedStart);
70     ASSERT_EQ(result.length, expectedLength);
71     initializer.DestroyContext(ctx);
72 }
73 
TEST_F(LspRenameInfoTests,RenameInfoCreateTriggerSpanForNodeEmptyStringLiteral)74 TEST_F(LspRenameInfoTests, RenameInfoCreateTriggerSpanForNodeEmptyStringLiteral)
75 {
76     Initializer initializer = Initializer();
77 
78     es2panda_Context *ctx =
79         initializer.CreateContext("trigger-span-empty-string.ets", ES2PANDA_STATE_CHECKED, "let emptyStr = \"\";");
80     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
81 
82     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
83     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
84         return node->IsStringLiteral() && node->AsStringLiteral()->Str() == "";
85     });
86     ASSERT_NE(targetNode, nullptr);
87 
88     auto result = ark::es2panda::lsp::CreateTriggerSpanForNode(targetNode);
89     size_t const expectedStart = 16;
90     size_t const expectedLength = 0;
91     ASSERT_EQ(result.start, expectedStart);
92     ASSERT_EQ(result.length, expectedLength);
93     initializer.DestroyContext(ctx);
94 }
95 
TEST_F(LspRenameInfoTests,RenameInfoNodeReturnTrueIfNodeIsNull)96 TEST_F(LspRenameInfoTests, RenameInfoNodeReturnTrueIfNodeIsNull)
97 {
98     ark::es2panda::ir::AstNode *nullNode = nullptr;
99     bool result = ark::es2panda::lsp::NodeIsMissing(nullNode);
100     EXPECT_TRUE(result);
101 }
102 
TEST_F(LspRenameInfoTests,RenameInfoNodeReturnTrueIfStartEqualEnd)103 TEST_F(LspRenameInfoTests, RenameInfoNodeReturnTrueIfStartEqualEnd)
104 {
105     Initializer initializer = Initializer();
106 
107     es2panda_Context *ctx = initializer.CreateContext("StartEqualEnd.ets", ES2PANDA_STATE_CHECKED, "");
108     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
109 
110     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
111     auto program = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->parserProgram;
112 
113     size_t const expectedIndex = 10;
114     size_t const expectedLength = 20;
115     auto srcPositionStart = ark::es2panda::lexer::SourcePosition(expectedIndex, expectedLength, program);
116     auto srcPositionEnd = ark::es2panda::lexer::SourcePosition(expectedIndex, expectedLength, program);
117     auto srcRange = ark::es2panda::lexer::SourceRange(srcPositionStart, srcPositionEnd);
118 
119     ast->SetRange(srcRange);
120     bool result = ark::es2panda::lsp::NodeIsMissing(ast);
121     EXPECT_TRUE(result);
122     initializer.DestroyContext(ctx);
123 }
124 
TEST_F(LspRenameInfoTests,RenameInfoNodeReturnFalseIfStartNotEqualEnd)125 TEST_F(LspRenameInfoTests, RenameInfoNodeReturnFalseIfStartNotEqualEnd)
126 {
127     Initializer initializer = Initializer();
128 
129     es2panda_Context *ctx = initializer.CreateContext("StartNotEqualEnd.ets", ES2PANDA_STATE_CHECKED, "");
130     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
131 
132     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
133     auto program = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->parserProgram;
134     size_t const expectedStartIndex = 10;
135     size_t const expectedEndIndex = 15;
136     size_t const expectedLength = 20;
137     auto srcPositionStart = ark::es2panda::lexer::SourcePosition(expectedStartIndex, expectedLength, program);
138     auto srcPositionEnd = ark::es2panda::lexer::SourcePosition(expectedEndIndex, expectedLength, program);
139     auto srcRange = ark::es2panda::lexer::SourceRange(srcPositionStart, srcPositionEnd);
140 
141     ast->SetRange(srcRange);
142     bool result = ark::es2panda::lsp::NodeIsMissing(ast);
143     EXPECT_FALSE(result);
144     initializer.DestroyContext(ctx);
145 }
146 
TEST_F(LspRenameInfoTests,RenameInfoNodeGetSourceTextOfNodeFromSourceFile)147 TEST_F(LspRenameInfoTests, RenameInfoNodeGetSourceTextOfNodeFromSourceFile)
148 {
149     Initializer initializer = Initializer();
150 
151     auto sourceView = ark::es2panda::util::StringView("function A(a:number, b:number) {\n  return a + b;\n}\nA(1, 2);");
152     es2panda_Context *ctx = initializer.CreateContext("GetTextOfNodeFromSourceFile.ets", ES2PANDA_STATE_CHECKED,
153                                                       "function A(a:number, b:number) {\n  return a + b;\n}\nA(1, 2);");
154     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
155 
156     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
157     auto program = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->parserProgram;
158     size_t const startIndex = 9;
159     size_t const startLength = 5;
160     size_t const endIndex = 10;
161     size_t const endLength = 5;
162     auto srcPositionStart = ark::es2panda::lexer::SourcePosition(startIndex, startLength, program);
163     auto srcPositionEnd = ark::es2panda::lexer::SourcePosition(endIndex, endLength, program);
164     auto srcRange = ark::es2panda::lexer::SourceRange(srcPositionStart, srcPositionEnd);
165     ast->SetRange(srcRange);
166 
167     std::string result = ark::es2panda::lsp::GetSourceTextOfNodeFromSourceFile(sourceView, ast);
168     ASSERT_EQ(result, "A");
169     ASSERT_NE(result, "B");
170     initializer.DestroyContext(ctx);
171 }
172 
TEST_F(LspRenameInfoTests,RenameInfoNodeGetSourceTextOfNodeFromSourceFileNullPtr)173 TEST_F(LspRenameInfoTests, RenameInfoNodeGetSourceTextOfNodeFromSourceFileNullPtr)
174 {
175     auto sourceView = ark::es2panda::util::StringView("function A(a:number, b:number) {\n  return a + b;\n}\nA(1, 2);");
176     ark::es2panda::ir::AstNode *ast = nullptr;
177     std::string result = ark::es2panda::lsp::GetSourceTextOfNodeFromSourceFile(sourceView, ast);
178     ASSERT_NE(result, "A");
179 }
180 
TEST_F(LspRenameInfoTests,RenameInfoNodeIsAncestorType)181 TEST_F(LspRenameInfoTests, RenameInfoNodeIsAncestorType)
182 {
183     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_ANY_KEYWORD), true);
184     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_UNKNOWN_KEYWORD), true);
185     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_NUMBER_KEYWORD), true);
186     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_BIGINT_KEYWORD), true);
187     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_OBJECT_KEYWORD), true);
188     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_BOOLEAN_KEYWORD), true);
189     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_STRING_KEYWORD), true);
190     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_VOID_KEYWORD), true);
191     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_UNDEFINED_KEYWORD), true);
192     ASSERT_EQ(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_NEVER_KEYWORD), true);
193 }
194 
TEST_F(LspRenameInfoTests,RenameInfoNodeIsNotAncestorType)195 TEST_F(LspRenameInfoTests, RenameInfoNodeIsNotAncestorType)
196 {
197     ASSERT_NE(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_ARRAY_TYPE), true);
198     ASSERT_NE(ark::es2panda::lsp::IsValidAncestorType(ark::es2panda::ir::AstNodeType::TS_FUNCTION_TYPE), true);
199 
200     size_t const invalidNum = 999;
201     auto invalidType = static_cast<ark::es2panda::ir::AstNodeType>(invalidNum);
202     ASSERT_NE(ark::es2panda::lsp::IsValidAncestorType(invalidType), true);
203 }
204 
TEST_F(LspRenameInfoTests,RenameInfoNodeIsQuoteOrBacktick)205 TEST_F(LspRenameInfoTests, RenameInfoNodeIsQuoteOrBacktick)
206 {
207     int charCode = ark::es2panda::lexer::LEX_CHAR_DOUBLE_QUOTE;
208     ASSERT_TRUE(ark::es2panda::lsp::IsQuoteOrBacktick(charCode));
209 
210     charCode = ark::es2panda::lexer::LEX_CHAR_0;
211     ASSERT_FALSE(ark::es2panda::lsp::IsQuoteOrBacktick(charCode));
212 }
213 
TEST_F(LspRenameInfoTests,RenameInfoIsStringOrNumericLiteralLike)214 TEST_F(LspRenameInfoTests, RenameInfoIsStringOrNumericLiteralLike)
215 {
216     Initializer initializer = Initializer();
217 
218     es2panda_Context *ctx = initializer.CreateContext("trigger-span-string-literal.ets", ES2PANDA_STATE_CHECKED,
219                                                       "let string_literal: string = \"hello\";\n");
220     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
221 
222     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
223     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
224         return node->IsStringLiteral() && node->AsStringLiteral()->Str() == "hello";
225     });
226 
227     ASSERT_TRUE(ark::es2panda::lsp::IsStringOrNumericLiteralLike(targetNode));
228     initializer.DestroyContext(ctx);
229 }
230 
TEST_F(LspRenameInfoTests,RenameInfoStripQuotes)231 TEST_F(LspRenameInfoTests, RenameInfoStripQuotes)
232 {
233     std::string hello = "'hello'";
234     ASSERT_EQ(ark::es2panda::lsp::StripQuotes(hello), "hello");
235 }
236 
TEST_F(LspRenameInfoTests,RenameInfoGetNodeKindForRenameInfo)237 TEST_F(LspRenameInfoTests, RenameInfoGetNodeKindForRenameInfo)
238 {
239     Initializer initializer = Initializer();
240 
241     es2panda_Context *ctx = initializer.CreateContext("token-pos-identifier.ets", ES2PANDA_STATE_CHECKED,
242                                                       "function A(a:number, b:number) {\n  return a + b;\n}\nA(1, 2);");
243     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
244 
245     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
246     ASSERT_EQ(ark::es2panda::lsp::GetNodeKindForRenameInfo(ast), "");
247     initializer.DestroyContext(ctx);
248 }
249 
TEST_F(LspRenameInfoTests,RenameInfoGetTextOfNode)250 TEST_F(LspRenameInfoTests, RenameInfoGetTextOfNode)
251 {
252     Initializer initializer = Initializer();
253 
254     std::vector<std::string> files = {"reanme_export1.ets"};
255     std::vector<std::string> texts = {
256         R"(export function A(a:number, b:number): number {return a + b;}
257         export function B(a:number, b:number): number {return a + b;})"};
258     auto filePaths = CreateTempFile(files, texts);
259     size_t const expectedFileCount = 1;
260     ASSERT_EQ(filePaths.size(), expectedFileCount);
261 
262     char const *fileName = filePaths[0].c_str();
263     auto ctx = initializer.CreateContext(fileName, ES2PANDA_STATE_CHECKED);
264     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
265 
266     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
267 
268     size_t const startIndex = 16;
269     size_t const startLength = 5;
270     size_t const endIndex = 17;
271     size_t const endLength = 5;
272 
273     auto program = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->parserProgram;
274     auto srcPositionStart = ark::es2panda::lexer::SourcePosition(startIndex, startLength, program);
275     auto srcPositionEnd = ark::es2panda::lexer::SourcePosition(endIndex, endLength, program);
276     auto srcRange = ark::es2panda::lexer::SourceRange(srcPositionStart, srcPositionEnd);
277     ast->SetRange(srcRange);
278 
279     ASSERT_EQ(ark::es2panda::lsp::GetTextOfNode(ast, program), "A");
280     initializer.DestroyContext(ctx);
281 }
282 
TEST_F(LspRenameInfoTests,RenameInfoGetRenameInfoError)283 TEST_F(LspRenameInfoTests, RenameInfoGetRenameInfoError)
284 {
285     ark::es2panda::lsp::RenameInfoFailure renameFailureFromFunction =
286         ark::es2panda::lsp::GetRenameInfoError("errorMessage");
287     ark::es2panda::lsp::RenameInfoFailure renameFailure = ark::es2panda::lsp::RenameInfoFailure(false, "errorMessage");
288     ASSERT_EQ(renameFailure.GetLocalizedErrorMessage(), renameFailureFromFunction.GetLocalizedErrorMessage());
289     ASSERT_EQ(renameFailure.GetCanRenameFailure(), renameFailureFromFunction.GetCanRenameFailure());
290 }
291 
TEST_F(LspRenameInfoTests,RenameInfoGetRenameInfoSuccess)292 TEST_F(LspRenameInfoTests, RenameInfoGetRenameInfoSuccess)
293 {
294     Initializer initializer = Initializer();
295 
296     es2panda_Context *ctx = initializer.CreateContext("token-pos-identifier.ets", ES2PANDA_STATE_CHECKED,
297                                                       "function A(a:number, b:number) {\n  return a + b;\n}\nA(1, 2);");
298     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
299 
300     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
301 
302     ark::es2panda::lsp::RenameInfoSuccess renameSuccessFromFunction =
303         ark::es2panda::lsp::GetRenameInfoSuccess("displayName", "fullDisplayName", "", "", ast);
304 
305     ark::es2panda::lsp::RenameInfoSuccess renameSuccess =
306         ark::es2panda::lsp::RenameInfoSuccess(true, "", "", "displayName", "fullDisplayName", "", TextSpan(1, 2));
307 
308     ASSERT_EQ(renameSuccess.GetDisplayName(), renameSuccessFromFunction.GetDisplayName());
309     ASSERT_EQ(renameSuccess.GetFullDisplayName(), renameSuccessFromFunction.GetFullDisplayName());
310     ASSERT_EQ(renameSuccess.GetKind(), renameSuccessFromFunction.GetKind());
311     ASSERT_EQ(renameSuccess.GetKindModifiers(), renameSuccessFromFunction.GetKindModifiers());
312     ASSERT_EQ(renameSuccess.GetCanRenameSuccess(), renameSuccessFromFunction.GetCanRenameSuccess());
313 
314     initializer.DestroyContext(ctx);
315 }
316 
TEST_F(LspRenameInfoTests,RenameInfoTryGetImportFromModuleSpecifier)317 TEST_F(LspRenameInfoTests, RenameInfoTryGetImportFromModuleSpecifier)
318 {
319     Initializer initializer = Initializer();
320 
321     std::vector<std::string> files = {"rename-module.ets"};
322     std::vector<std::string> texts = {R"(import { PI } from "std/math";
323     console.log(PI);)"};
324 
325     auto filePaths = CreateTempFile(files, texts);
326     int const expectedFileCount = 1;
327     ASSERT_EQ(filePaths.size(), expectedFileCount);
328 
329     size_t const startIndex = 0;
330     char const *referenceFileName = filePaths[startIndex].c_str();
331     auto ctx = initializer.CreateContext(referenceFileName, ES2PANDA_STATE_CHECKED);
332     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
333 
334     ark::es2panda::ir::AstNode *ast = nullptr;
335     ASSERT_EQ(ark::es2panda::lsp::TryGetImportFromModuleSpecifier(ast), nullptr);
336 
337     ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
338     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
339         return node->Type() == ark::es2panda::ir::AstNodeType::IMPORT_SPECIFIER;
340     });
341     ASSERT_EQ(ark::es2panda::lsp::TryGetImportFromModuleSpecifier(targetNode), targetNode->Parent());
342 
343     initializer.DestroyContext(ctx);
344 }
345 
TEST_F(LspRenameInfoTests,RenameInfoGetRenameInfoForModuleCaseModule1)346 TEST_F(LspRenameInfoTests, RenameInfoGetRenameInfoForModuleCaseModule1)
347 {
348     Initializer initializer = Initializer();
349 
350     std::vector<std::string> files = {"rename-module.ets"};
351     std::vector<std::string> texts = {R"(const s = "std/math/index";)"};
352     auto filePaths = CreateTempFile(files, texts);
353     size_t const expectedSize = 1;
354     ASSERT_EQ(filePaths.size(), expectedSize);
355 
356     size_t const startIndex = 0;
357     char const *filePath = filePaths[startIndex].c_str();
358     es2panda_Context *ctx = initializer.CreateContext(filePath, ES2PANDA_STATE_CHECKED);
359     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
360 
361     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
362     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
363         return node->IsStringLiteral() && node->AsStringLiteral()->ToString() == "std/math/index";
364     });
365     ASSERT_NE(targetNode, nullptr);
366 
367     auto renameInfo = ark::es2panda::lsp::GetRenameInfoForModule(
368         targetNode, reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->parserProgram);
369     ASSERT_EQ(renameInfo.value().GetDisplayName(), targetNode->AsStringLiteral()->ToString());
370     initializer.DestroyContext(ctx);
371 }
372 
TEST_F(LspRenameInfoTests,RenameInfoGetRenameInfoForModuleCaseModule2)373 TEST_F(LspRenameInfoTests, RenameInfoGetRenameInfoForModuleCaseModule2)
374 {
375     Initializer initializer = Initializer();
376 
377     std::vector<std::string> files = {"rename-module.ets"};
378     std::vector<std::string> texts = {R"(const s = "std/math.ets";)"};
379     auto filePaths = CreateTempFile(files, texts);
380     size_t const expectedSize = 1;
381     ASSERT_EQ(filePaths.size(), expectedSize);
382 
383     size_t const startIndex = 0;
384     char const *filePath = filePaths[startIndex].c_str();
385     es2panda_Context *ctx = initializer.CreateContext(filePath, ES2PANDA_STATE_CHECKED);
386     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
387 
388     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
389     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
390         return node->IsStringLiteral() && node->AsStringLiteral()->ToString() == "std/math.ets";
391     });
392     ASSERT_NE(targetNode, nullptr);
393 
394     auto renameInfo = ark::es2panda::lsp::GetRenameInfoForModule(
395         targetNode, reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->parserProgram);
396     ASSERT_EQ(renameInfo.value().GetDisplayName(), targetNode->AsStringLiteral()->ToString());
397     initializer.DestroyContext(ctx);
398 }
399 
TEST_F(LspRenameInfoTests,RenameInfoGetRenameInfoForModuleCaseDirectory)400 TEST_F(LspRenameInfoTests, RenameInfoGetRenameInfoForModuleCaseDirectory)
401 {
402     Initializer initializer = Initializer();
403 
404     std::vector<std::string> files = {"rename-directory.ets"};
405     std::vector<std::string> texts = {R"(const s = "std/math/index.ets";)"};
406     auto filePaths = CreateTempFile(files, texts);
407     size_t const expectedSize = 1;
408     ASSERT_EQ(filePaths.size(), expectedSize);
409 
410     size_t const startIndex = 0;
411     char const *filePath = filePaths[startIndex].c_str();
412     es2panda_Context *ctx = initializer.CreateContext(filePath, ES2PANDA_STATE_CHECKED);
413     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
414 
415     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
416     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
417         return node->IsStringLiteral() && node->AsStringLiteral()->ToString() == "std/math/index.ets";
418     });
419     ASSERT_NE(targetNode, nullptr);
420 
421     auto renameInfo = ark::es2panda::lsp::GetRenameInfoForModule(
422         targetNode, reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->parserProgram);
423     ASSERT_EQ(renameInfo.value().GetDisplayName(), "std/math");
424     initializer.DestroyContext(ctx);
425 }
426 
TEST_F(LspRenameInfoTests,RenameInfoGetRenameInfoForNode1)427 TEST_F(LspRenameInfoTests, RenameInfoGetRenameInfoForNode1)
428 {
429     Initializer initializer = Initializer();
430 
431     std::vector<std::string> files = {"rename.ets"};
432     std::vector<std::string> texts = {R"(import { PI } from "std/math"; console.log(PI);)"};
433 
434     auto filePaths = CreateTempFile(files, texts);
435     size_t const expectedFileCount = 1;
436     ASSERT_EQ(filePaths.size(), expectedFileCount);
437 
438     size_t const startIndex = 0;
439     char const *referenceFileName = filePaths[startIndex].c_str();
440     auto ctx = initializer.CreateContext(referenceFileName, ES2PANDA_STATE_CHECKED);
441     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
442 
443     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
444     auto checker = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->checker->AsETSChecker();
445     auto program = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx)->parserProgram;
446 
447     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
448         return node->IsIdentifier() && node->AsIdentifier()->ToString() == "PI";
449     });
450     ASSERT_EQ(ark::es2panda::lsp::GetRenameInfoForNode(targetNode, checker, program), std::nullopt);
451     initializer.DestroyContext(ctx);
452 }
453 
TEST_F(LspRenameInfoTests,RenameInfoNodeIsEligibleForRenameStringLiteral)454 TEST_F(LspRenameInfoTests, RenameInfoNodeIsEligibleForRenameStringLiteral)
455 {
456     Initializer initializer = Initializer();
457     es2panda_Context *ctx = initializer.CreateContext("trigger-span-string-literal.ets", ES2PANDA_STATE_CHECKED,
458                                                       "let string_literal: string = \"hello\";\n");
459     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
460 
461     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
462     auto targetNode = ast->FindChild([](ark::es2panda::ir::AstNode *node) {
463         return node->IsStringLiteral() && node->AsStringLiteral()->Str() == "hello";
464     });
465 
466     ASSERT_NE(targetNode, nullptr);
467     ASSERT_TRUE(ark::es2panda::lsp::NodeIsEligibleForRename(targetNode));
468     initializer.DestroyContext(ctx);
469 }
470 
TEST_F(LspRenameInfoTests,RenameInfoNodeIsEligibleForRenameNumberLiteralEnumMember)471 TEST_F(LspRenameInfoTests, RenameInfoNodeIsEligibleForRenameNumberLiteralEnumMember)
472 {
473     Initializer initializer = Initializer();
474     es2panda_Context *ctx = initializer.CreateContext("trigger-span-literal.ets", ES2PANDA_STATE_CHECKED,
475                                                       "enum MyEnum { FixedValue = 42 }");
476     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
477 
478     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
479     auto enumClass = ast->FindChild([](ark::es2panda::ir::AstNode *child) {
480         return child->IsClassDefinition() && child->AsClassDefinition()->Ident()->Name() == "MyEnum";
481     });
482     auto enumDecl = enumClass->AsClassDefinition()->OrigEnumDecl()->AsTSEnumDeclaration();
483     auto targetNode = enumDecl->FindChild([](ark::es2panda::ir::AstNode *node) {
484         return node->IsNumberLiteral() && node->AsNumberLiteral()->Str() == "42";
485     });
486 
487     ASSERT_NE(targetNode, nullptr);
488     ASSERT_FALSE(ark::es2panda::lsp::NodeIsEligibleForRename(targetNode));
489     initializer.DestroyContext(ctx);
490 }
491