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_api_test.h"
17
18 #include <gtest/gtest.h>
19 #include <cstddef>
20
21 #include "ir/astNode.h"
22 #include "lsp/include/internal_api.h"
23 #include "public/es2panda_lib.h"
24
25 namespace {
26
27 using ark::es2panda::lsp::Initializer;
28
TEST_F(LSPAPITests,GetPrecedingToken1)29 TEST_F(LSPAPITests, GetPrecedingToken1)
30 {
31 using ark::es2panda::ir::AstNode;
32
33 LSPAPI const *lspApi = GetImpl();
34 Initializer initializer = Initializer();
35 es2panda_Context *context = initializer.CreateContext(
36
37 "precedingtoken_literal.ets", ES2PANDA_STATE_CHECKED,
38 "let number_literal: number = 1234;\nlet string_literal: string = \"hello\";\nconst str_property = "
39 "\"foo\";\n");
40 ASSERT_EQ(ContextState(context), ES2PANDA_STATE_CHECKED);
41 auto ast = GetAstFromContext<AstNode>(context);
42
43 size_t const numberLiteralOffset = 31; // 31: position of '3' in '1234'
44 size_t const stringLiteralOffset = 96; // 96: position of first 'o' in 'foo'
45 auto numberLiteral = ast->FindChild([](AstNode *node) { return node->IsExpressionStatement(); })
46 ->AsExpressionStatement()
47 ->GetExpression()
48 ->AsAssignmentExpression()
49 ->Right()
50 ->AsNumberLiteral();
51 auto result = reinterpret_cast<AstNode *>(lspApi->getPrecedingToken(context, numberLiteralOffset));
52 ASSERT_EQ(result->DumpJSON(), numberLiteral->DumpJSON());
53 ASSERT_EQ(result->Start().index, numberLiteral->Start().index);
54 ASSERT_EQ(result->End().index, numberLiteral->End().index);
55 auto stringLiteral = ast->FindChild(
56 [](AstNode *node) { return node->IsStringLiteral() && node->AsStringLiteral()->ToString() == "foo"; });
57 result = reinterpret_cast<AstNode *>(lspApi->getPrecedingToken(context, stringLiteralOffset));
58 ASSERT_EQ(result->DumpJSON(), stringLiteral->DumpJSON());
59 ASSERT_EQ(result->Start().index, stringLiteral->Start().index);
60 ASSERT_EQ(result->End().index, stringLiteral->End().index);
61 initializer.DestroyContext(context);
62 }
63
TEST_F(LSPAPITests,GetPrecedingToken2)64 TEST_F(LSPAPITests, GetPrecedingToken2)
65 {
66 using ark::es2panda::ir::AstNode;
67
68 LSPAPI const *lspApi = GetImpl();
69 Initializer initializer = Initializer();
70 es2panda_Context *context = initializer.CreateContext(
71 "precedingtoken_function.ets", ES2PANDA_STATE_CHECKED,
72 " \n\n\n\nfunction f() {\n le\n let a = 123;\n}\n\n\n\nconst s = \"hello\";\n\n\n");
73 auto ast = GetAstFromContext<AstNode>(context);
74
75 size_t const startOfFile = 0; // 0: position of start of file
76 size_t const secondSpaceBeforeLe = 25; // 25: position of second space before 'le'
77 size_t const endOfLe = 29; // 29: position of the end of 'le' identifier
78 size_t const secondSpaceBeforeLet = 32; // 32: position of second space before 'let'
79 size_t const startOfLine10 = 50; // 50: position of start of line 10
80 size_t const startOfLine14 = 72; // 72: position of start of line 14
81 ASSERT_EQ(lspApi->getPrecedingToken(context, startOfFile), nullptr);
82 ASSERT_EQ(lspApi->getPrecedingToken(context, secondSpaceBeforeLe), nullptr);
83 auto leIdentifier =
84 ast->FindChild([](AstNode *node) { return node->IsIdentifier() && node->AsIdentifier()->Name() == "le"; });
85 auto result = reinterpret_cast<AstNode *>(lspApi->getPrecedingToken(context, endOfLe));
86 ASSERT_EQ(result->DumpJSON(), leIdentifier->DumpJSON());
87 ASSERT_EQ(result->Start().index, leIdentifier->Start().index);
88 ASSERT_EQ(result->End().index, leIdentifier->End().index);
89 result = reinterpret_cast<AstNode *>(lspApi->getPrecedingToken(context, secondSpaceBeforeLet));
90 ASSERT_EQ(result->DumpJSON(), leIdentifier->DumpJSON());
91 ASSERT_EQ(result->Start().index, leIdentifier->Start().index);
92 ASSERT_EQ(result->End().index, leIdentifier->End().index);
93 auto numberLiteral = ast->FindChild(
94 [](AstNode *node) { return node->IsNumberLiteral() && node->AsNumberLiteral()->Str() == "123"; });
95 result = reinterpret_cast<AstNode *>(lspApi->getPrecedingToken(context, startOfLine10));
96 ASSERT_EQ(result->DumpJSON(), numberLiteral->DumpJSON());
97 ASSERT_EQ(result->Start().index, numberLiteral->Start().index);
98 ASSERT_EQ(result->End().index, numberLiteral->End().index);
99 auto stringLiteral = ast->FindChild([](AstNode *node) { return node->IsClassProperty(); })
100 ->AsClassProperty()
101 ->Value()
102 ->AsStringLiteral();
103 result = reinterpret_cast<AstNode *>(lspApi->getPrecedingToken(context, startOfLine14));
104 ASSERT_EQ(result->DumpJSON(), stringLiteral->DumpJSON());
105 ASSERT_EQ(result->Start().index, stringLiteral->Start().index);
106 ASSERT_EQ(result->End().index, stringLiteral->End().index);
107 initializer.DestroyContext(context);
108 }
109
110 } // namespace
111