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 <cstddef>
18 #include <cstdio>
19
20 #include "lsp_api_test.h"
21 #include "public/es2panda_lib.h"
22 #include "lsp/include/services/utilities.h"
23 #include "lsp/include/internal_api.h"
24 #include "lsp/include/api.h"
25
26 using ark::es2panda::lsp::Initializer;
27
28 class LspGILAPTests : public LSPAPITests {};
29
TEST_F(LspGILAPTests,GILAPIsInitializer_Test)30 TEST_F(LspGILAPTests, GILAPIsInitializer_Test)
31 {
32 Initializer initializer = Initializer();
33 const char *code = "class C {n: number = 0;constructor() {this.n = 12;};foo():this{return this}}";
34 es2panda_Context *ctx = initializer.CreateContext("dummy-node.ets", ES2PANDA_STATE_CHECKED, code);
35 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
36
37 size_t const offset = 20;
38 auto result = ark::es2panda::lsp::GetTouchingToken(ctx, offset, false);
39 ASSERT_NE(result, nullptr);
40 EXPECT_TRUE(ark::es2panda::lsp::IsInitializer(result));
41
42 initializer.DestroyContext(ctx);
43 }
44
TEST_F(LspGILAPTests,GILAPIsInitializer_Test1)45 TEST_F(LspGILAPTests, GILAPIsInitializer_Test1)
46 {
47 Initializer initializer = Initializer();
48 const char *code = "class C {n: number=0;foo():this{return this}};let a: C = new C();";
49 es2panda_Context *ctx = initializer.CreateContext("dummy-node.ets", ES2PANDA_STATE_CHECKED, code);
50 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
51
52 size_t const offset = 10;
53 auto result = ark::es2panda::lsp::GetTouchingToken(ctx, offset, false);
54 ASSERT_NE(result, nullptr);
55 EXPECT_TRUE(ark::es2panda::lsp::IsInitializer(result));
56
57 initializer.DestroyContext(ctx);
58 }
59
TEST_F(LspGILAPTests,GILAPIsReturnNode_Test)60 TEST_F(LspGILAPTests, GILAPIsReturnNode_Test)
61 {
62 Initializer initializer = Initializer();
63 const char *code = "function A(a:number, b:number):boolean{ return true;}";
64 es2panda_Context *ctx = initializer.CreateContext("dummy-node.ets", ES2PANDA_STATE_CHECKED, code);
65 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
66
67 size_t const offset = 48;
68 auto result = ark::es2panda::lsp::GetTouchingToken(ctx, offset, false);
69 ASSERT_NE(result, nullptr);
70 EXPECT_TRUE(ark::es2panda::lsp::IsReturnNode(result));
71
72 initializer.DestroyContext(ctx);
73 }
74
TEST_F(LspGILAPTests,GILAPIsThisNode_Test)75 TEST_F(LspGILAPTests, GILAPIsThisNode_Test)
76 {
77 Initializer initializer = Initializer();
78 const char *code = "class C {n: number = 0;foo():this{return this}}";
79 es2panda_Context *ctx = initializer.CreateContext("dummy-node.ets", ES2PANDA_STATE_CHECKED, code);
80 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
81
82 size_t const offset = 30;
83 auto result = ark::es2panda::lsp::GetTouchingToken(ctx, offset, false);
84 ASSERT_NE(result, nullptr);
85 EXPECT_TRUE(ark::es2panda::lsp::IsThis(result));
86
87 initializer.DestroyContext(ctx);
88 }
89
TEST_F(LspGILAPTests,GILAPIsThisNode_Test1)90 TEST_F(LspGILAPTests, GILAPIsThisNode_Test1)
91 {
92 Initializer initializer = Initializer();
93 const char *code = "class C {n: number = 0;foo():this{return this}}";
94 es2panda_Context *ctx = initializer.CreateContext("dummy-node.ets", ES2PANDA_STATE_CHECKED, code);
95 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
96
97 size_t const offset = 42;
98 auto result = ark::es2panda::lsp::GetTouchingToken(ctx, offset, false);
99 ASSERT_NE(result, nullptr);
100 EXPECT_TRUE(ark::es2panda::lsp::IsThis(result));
101
102 initializer.DestroyContext(ctx);
103 }
104
TEST_F(LspGILAPTests,GILAPIsValidImplementation_Test)105 TEST_F(LspGILAPTests, GILAPIsValidImplementation_Test)
106 {
107 Initializer initializer = Initializer();
108 const char *code = "function A(){ 1+2; }";
109 es2panda_Context *ctx = initializer.CreateContext("dummy-node.ets", ES2PANDA_STATE_CHECKED, code);
110 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
111
112 size_t const offset = 15;
113 auto result = ark::es2panda::lsp::GetTouchingToken(ctx, offset, false);
114 ASSERT_NE(result, nullptr);
115 EXPECT_TRUE(ark::es2panda::lsp::IsValidImplementation(result));
116
117 initializer.DestroyContext(ctx);
118 }
119
TEST_F(LspGILAPTests,GILAPIsAsTypeNode_Test)120 TEST_F(LspGILAPTests, GILAPIsAsTypeNode_Test)
121 {
122 Initializer initializer = Initializer();
123 const char *code =
124 "class Shape {}class Circle extends Shape {x: number = 5}class Square extends Shape {y: string = 'a'}function "
125 "createShape(): Shape {return new Circle()}let c2 = createShape() as Circle";
126 es2panda_Context *ctx = initializer.CreateContext("dummy-node.ets", ES2PANDA_STATE_CHECKED, code);
127 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
128
129 size_t const offset = 159;
130 auto result = ark::es2panda::lsp::GetTouchingToken(ctx, offset, false);
131 ASSERT_NE(result, nullptr);
132 ASSERT_TRUE(ark::es2panda::lsp::IsAsTypeNode(result));
133
134 initializer.DestroyContext(ctx);
135 }
136
TEST_F(LspGILAPTests,GILAPGetImplementationAtPosition_Test)137 TEST_F(LspGILAPTests, GILAPGetImplementationAtPosition_Test)
138 {
139 Initializer initializer = Initializer();
140 static std::string source = R"(
141 function Ali(a:number, b:number) {
142 return a + b;
143 }
144 Ali(1, 2);
145 function Ali(a:number) {
146 return a;
147 }
148 Ali(1);
149 )";
150 es2panda_Context *ctx =
151 initializer.CreateContext("implementation-at-position.ets", ES2PANDA_STATE_CHECKED, source.data());
152 ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
153
154 const int callOffset = 72;
155
156 auto result = GetImpl()->getImplementationLocationAtPosition(ctx, callOffset);
157
158 initializer.DestroyContext(ctx);
159 ASSERT_FALSE(result.empty());
160
161 const int sL = 1;
162 const int eL = 3;
163
164 const int sI = 5;
165 const int eI = 67;
166
167 ASSERT_EQ(result[0].range_.start.line_, sL);
168 ASSERT_EQ(result[0].range_.start.character_, sI);
169
170 ASSERT_EQ(result[0].range_.end.line_, eL);
171 ASSERT_EQ(result[0].range_.end.character_, eI);
172
173 ASSERT_EQ(result[0].uri_.compare("implementation-at-position.ets"), 0);
174 }
175