• 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_api_test.h"
17 #include "lsp/include/isolated_declaration.h"
18 
19 namespace {
20 using ark::es2panda::lsp::Initializer;
21 
22 class LSPIsolatedDeclarationTests : public LSPAPITests {};
23 
TEST_F(LSPIsolatedDeclarationTests,IsolatedDeclaration1)24 TEST_F(LSPIsolatedDeclarationTests, IsolatedDeclaration1)
25 {
26     std::vector<std::string> files = {"IsolatedDeclaration1_export.ets", "IsolatedDeclaration1.ets"};
27     std::vector<std::string> texts = {R"(export class C {
28   pro1: number = 123;
29   pro2: string = "hello";
30   pro3: boolean = false;
31 }
32 )",
33                                       R"(import {C} from './IsolatedDeclaration1_export';
34 export function foo(n: number) {
35   if (n < 3) {
36     return n + 2;
37   }
38   const c = new C();
39   if (c.pro1 < 100) {
40     return c;
41   }
42   if (c.pro3) {
43     return c.pro3;
44   }
45   return c.pro2;
46 }
47 )"};
48     auto filePaths = CreateTempFile(files, texts);
49     const size_t expectedFileCount = 2;
50     ASSERT_EQ(filePaths.size(), expectedFileCount);
51 
52     Initializer initializer = Initializer();
53     auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED);
54     auto ctx = reinterpret_cast<ark::es2panda::public_lib::Context *>(context);
55     auto checker = reinterpret_cast<ark::es2panda::checker::ETSChecker *>(ctx->checker);
56     auto ast = ctx->parserProgram->Ast();
57     auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) {
58         return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo";
59     });
60     auto textChange = ark::es2panda::lsp::ProcessIdentifier(id->AsIdentifier(), checker, ctx->parserProgram);
61     const size_t expectedStart = 79;
62     ASSERT_EQ(textChange.has_value(), true);
63     ASSERT_EQ(textChange.value().newText, ": string | boolean | number | C");
64     ASSERT_EQ(textChange.value().span.start, expectedStart);
65     ASSERT_EQ(textChange.value().span.length, 0);
66 
67     initializer.DestroyContext(context);
68 }
69 
TEST_F(LSPIsolatedDeclarationTests,IsolatedDeclaration2)70 TEST_F(LSPIsolatedDeclarationTests, IsolatedDeclaration2)
71 {
72     std::vector<std::string> files = {"IsolatedDeclaration2_export.ets", "IsolatedDeclaration2.ets"};
73     std::vector<std::string> texts = {R"(export const arr = [1, 2, 3];
74 export const tuple = [1, "hello", true];
75 )",
76                                       R"(import {arr, tuple} from './IsolatedDeclaration2_export';
77 export function foo(n: number) {
78   if (n < 3) {
79     return n + 2;
80   }
81   if (n < 7) {
82     return arr;
83   }
84   return tuple;
85 }
86 )"};
87     auto filePaths = CreateTempFile(files, texts);
88     const size_t expectedFileCount = 2;
89     ASSERT_EQ(filePaths.size(), expectedFileCount);
90 
91     Initializer initializer = Initializer();
92     auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED);
93     auto ctx = reinterpret_cast<ark::es2panda::public_lib::Context *>(context);
94     auto checker = reinterpret_cast<ark::es2panda::checker::ETSChecker *>(ctx->checker);
95     auto ast = ctx->parserProgram->Ast();
96     auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) {
97         return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo";
98     });
99     auto textChange = ark::es2panda::lsp::ProcessIdentifier(id->AsIdentifier(), checker, ctx->parserProgram);
100     const size_t expectedStart = 88;
101     ASSERT_EQ(textChange.has_value(), true);
102     ASSERT_EQ(textChange.value().newText, ": [number, string, boolean] | number | number[]");
103     ASSERT_EQ(textChange.value().span.start, expectedStart);
104     ASSERT_EQ(textChange.value().span.length, 0);
105 
106     initializer.DestroyContext(context);
107 }
108 
TEST_F(LSPIsolatedDeclarationTests,IsolatedDeclaration3)109 TEST_F(LSPIsolatedDeclarationTests, IsolatedDeclaration3)
110 {
111     std::vector<std::string> files = {"IsolatedDeclaration3_export.ets", "IsolatedDeclaration3.ets"};
112     std::vector<std::string> texts = {R"(export class C {
113   pro1: number = 123;
114   pro2: string = "hello";
115   pro3: boolean = false;
116 }
117 )",
118                                       R"(import {C} from './IsolatedDeclaration3_export';
119 export const foo = () => {
120   const c = new C();
121   if (c.pro1 < 100) {
122     return c.pro1;
123   }
124   return c.pro2;
125 };
126 )"};
127     auto filePaths = CreateTempFile(files, texts);
128     const size_t expectedFileCount = 2;
129     ASSERT_EQ(filePaths.size(), expectedFileCount);
130 
131     Initializer initializer = Initializer();
132     auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED);
133     auto ctx = reinterpret_cast<ark::es2panda::public_lib::Context *>(context);
134     auto checker = reinterpret_cast<ark::es2panda::checker::ETSChecker *>(ctx->checker);
135     auto ast = ctx->parserProgram->Ast();
136     auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) {
137         return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo";
138     });
139     auto textChange = ark::es2panda::lsp::ProcessIdentifier(id->AsIdentifier(), checker, ctx->parserProgram);
140     const size_t expectedStart = 70;
141     ASSERT_EQ(textChange.has_value(), true);
142     ASSERT_EQ(textChange.value().newText, ": number | string");
143     ASSERT_EQ(textChange.value().span.start, expectedStart);
144     ASSERT_EQ(textChange.value().span.length, 0);
145 
146     initializer.DestroyContext(context);
147 }
148 
TEST_F(LSPIsolatedDeclarationTests,IsolatedDeclaration4)149 TEST_F(LSPIsolatedDeclarationTests, IsolatedDeclaration4)
150 {
151     std::vector<std::string> files = {"IsolatedDeclaration4_export.ets", "IsolatedDeclaration4.ets"};
152     std::vector<std::string> texts = {R"(export const arr = [1, 2, 3];
153 export const tuple = [1, "hello", true];
154 )",
155                                       R"(import {arr, tuple} from './IsolatedDeclaration4_export';
156 export class A {
157   public foo(n: number) {
158     if (n < 3) {
159         return n + 2;
160     }
161     if (n < 7) {
162         return arr;
163     }
164     return tuple;
165   }
166 }
167 )"};
168     auto filePaths = CreateTempFile(files, texts);
169     const size_t expectedFileCount = 2;
170     ASSERT_EQ(filePaths.size(), expectedFileCount);
171 
172     Initializer initializer = Initializer();
173     auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED);
174     auto ctx = reinterpret_cast<ark::es2panda::public_lib::Context *>(context);
175     auto checker = reinterpret_cast<ark::es2panda::checker::ETSChecker *>(ctx->checker);
176     auto ast = ctx->parserProgram->Ast();
177     auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) {
178         return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo";
179     });
180     auto textChange = ark::es2panda::lsp::ProcessIdentifier(id->AsIdentifier(), checker, ctx->parserProgram);
181     const size_t expectedStart = 98;
182     ASSERT_EQ(textChange.has_value(), true);
183     ASSERT_EQ(textChange.value().newText, ": [number, string, boolean] | number | number[]");
184     ASSERT_EQ(textChange.value().span.start, expectedStart);
185     ASSERT_EQ(textChange.value().span.length, 0);
186 
187     initializer.DestroyContext(context);
188 }
189 
TEST_F(LSPIsolatedDeclarationTests,IsolatedDeclaration5)190 TEST_F(LSPIsolatedDeclarationTests, IsolatedDeclaration5)
191 {
192     std::vector<std::string> files = {"IsolatedDeclaration5_export.ets", "IsolatedDeclaration5.ets"};
193     std::vector<std::string> texts = {R"(export const arr = [1, 2, 3];
194 export const tuple = [1, "hello", true];
195 )",
196                                       R"(import {arr, tuple} from './IsolatedDeclaration5_export';
197 export class A {
198   public foo = (n: number) => {
199     if (n < 3) {
200         return n + 2;
201     }
202     if (n < 7) {
203         return arr;
204     }
205     return tuple;
206   }
207 }
208 )"};
209     auto filePaths = CreateTempFile(files, texts);
210     const size_t expectedFileCount = 2;
211     ASSERT_EQ(filePaths.size(), expectedFileCount);
212 
213     Initializer initializer = Initializer();
214     auto context = initializer.CreateContext(filePaths[1].c_str(), ES2PANDA_STATE_CHECKED);
215     auto ctx = reinterpret_cast<ark::es2panda::public_lib::Context *>(context);
216     auto checker = reinterpret_cast<ark::es2panda::checker::ETSChecker *>(ctx->checker);
217     auto ast = ctx->parserProgram->Ast();
218     auto id = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) {
219         return childNode->IsIdentifier() && childNode->AsIdentifier()->Name() == "foo";
220     });
221     auto textChange = ark::es2panda::lsp::ProcessIdentifier(id->AsIdentifier(), checker, ctx->parserProgram);
222     const size_t expectedStart = 101;
223     ASSERT_EQ(textChange.has_value(), true);
224     ASSERT_EQ(textChange.value().newText, ": [number, string, boolean] | number | number[]");
225     ASSERT_EQ(textChange.value().span.start, expectedStart);
226     ASSERT_EQ(textChange.value().span.length, 0);
227 
228     initializer.DestroyContext(context);
229 }
230 }  // namespace