• 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/completions.h"
18 #include "lsp/include/internal_api.h"
19 #include "lsp/include/api.h"
20 #include "lsp/include/completions_details.h"
21 #include "lsp/include/quick_info.h"
22 #include "lsp/include/suggestion_diagnostics.h"
23 #include "compiler/lowering/util.h"
24 
25 namespace {
26 
27 class LSPCompletionsEntryDetailsTests : public LSPAPITests {};
28 
29 using ark::es2panda::lsp::Initializer;
30 
TEST_F(LSPCompletionsEntryDetailsTests,GetCompletionEntryDetails0)31 TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails0)
32 {
33     Initializer initializer = Initializer();
34     es2panda_Context *ctx = initializer.CreateContext("completion_entry_details.ets", ES2PANDA_STATE_CHECKED,
35                                                       R"(enum MyStrings { A = 'hello' };)");
36     size_t const offset = 17;
37     LSPAPI const *lspApi = GetImpl();
38     const char *entryName = "MyStrings";
39     auto completionEntryDetails =
40         lspApi->getCompletionEntryDetails(entryName, "completion_entry_details.ets", ctx, offset);
41     ASSERT_NE(completionEntryDetails, CompletionEntryDetails());
42     std::vector<SymbolDisplayPart> source {};
43     std::vector<SymbolDisplayPart> sourceDisplay {};
44     std::vector<SymbolDisplayPart> document {};
45     const std::string kind = "class";
46     const std::string kindModifiers = "final";
47     const std::string expectedFileName = "completion_entry_details.ets";
48 
49     std::vector<SymbolDisplayPart> expected;
50     expected.emplace_back("enum", "keyword");
51     expected.emplace_back(" ", "space");
52     expected.emplace_back("MyStrings", "className");
53 
54     auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document,
55                                                                  source, sourceDisplay, expectedFileName);
56     initializer.DestroyContext(ctx);
57     ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails);
58 }
59 
TEST_F(LSPCompletionsEntryDetailsTests,GetCompletionEntryDetails1)60 TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails1)
61 {
62     Initializer initializer = Initializer();
63     es2panda_Context *ctx = initializer.CreateContext("completion_entry_details1.ets", ES2PANDA_STATE_CHECKED,
64                                                       "class MyClass {\n  public myProp: number = 0;\n}");
65     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
66     size_t const offset = 9;
67     LSPAPI const *lspApi = GetImpl();
68     const char *entryName = "MyClass";
69     const std::string fileName = "completion_entry_details1.ets";
70     auto completionEntryDetails =
71         lspApi->getCompletionEntryDetails(entryName, "completion_entry_details1.ets", ctx, offset);
72     ASSERT_NE(completionEntryDetails, CompletionEntryDetails());
73     std::vector<SymbolDisplayPart> source {};
74     std::vector<SymbolDisplayPart> sourceDisplay {};
75     std::vector<SymbolDisplayPart> document {};
76     const std::string kind = "class";
77     const std::string kindModifiers;
78     const std::string expectedFileName = "completion_entry_details1.ets";
79 
80     std::vector<SymbolDisplayPart> expected;
81     expected.emplace_back("class", "keyword");
82     expected.emplace_back(" ", "space");
83     expected.emplace_back("MyClass", "className");
84 
85     auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document,
86                                                                  source, sourceDisplay, expectedFileName);
87     ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails);
88 
89     initializer.DestroyContext(ctx);
90 }
91 
TEST_F(LSPCompletionsEntryDetailsTests,GetCompletionEntryDetails2)92 TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails2)
93 {
94     Initializer initializer = Initializer();
95     es2panda_Context *ctx =
96         initializer.CreateContext("completion_entry_details2.ets", ES2PANDA_STATE_CHECKED,
97                                   "interface objI { key : string; }\nlet obj : objI = { key:\"valueaaaaaaaaa,\" }");
98     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
99     size_t const offset = 7;
100     LSPAPI const *lspApi = GetImpl();
101     const char *entryName = "objI";
102     const std::string fileName = "completion_entry_details2.ets";
103     auto completionEntryDetails =
104         lspApi->getCompletionEntryDetails(entryName, "completion_entry_details2.ets", ctx, offset);
105     ASSERT_NE(completionEntryDetails, CompletionEntryDetails());
106     std::vector<SymbolDisplayPart> source {};
107     std::vector<SymbolDisplayPart> sourceDisplay {};
108     std::vector<SymbolDisplayPart> document {};
109     const std::string kind = "interface";
110     const std::string kindModifiers = "static public";
111     const std::string expectedFileName = "completion_entry_details2.ets";
112     std::vector<SymbolDisplayPart> expected;
113 
114     expected.emplace_back("interface", "keyword");
115     expected.emplace_back(" ", "space");
116     expected.emplace_back("objI", "className");
117 
118     auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document,
119                                                                  source, sourceDisplay, expectedFileName);
120     ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails);
121 
122     initializer.DestroyContext(ctx);
123 }
124 
TEST_F(LSPCompletionsEntryDetailsTests,GetCompletionEntryDetails3)125 TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails3)
126 {
127     Initializer initializer = Initializer();
128     es2panda_Context *ctx = initializer.CreateContext("completion_entry_details9.ets", ES2PANDA_STATE_CHECKED,
129                                                       R"(function name (params: string) {
130   new CC().getName()
131 }
132 
133 class CC {
134   getName() {
135   }
136 })");
137     size_t const offset = 79;
138     LSPAPI const *lspApi = GetImpl();
139     const char *entryName = "getName";
140     auto completionEntryDetails =
141         lspApi->getCompletionEntryDetails(entryName, "completion_entry_details9.ets", ctx, offset);
142     ASSERT_NE(completionEntryDetails, CompletionEntryDetails());
143     std::vector<SymbolDisplayPart> source {};
144     std::vector<SymbolDisplayPart> sourceDisplay {};
145     std::vector<SymbolDisplayPart> document {};
146     const std::string kind = "function";
147     const std::string kindModifiers = "public";
148     const std::string expectedFileName = "completion_entry_details9.ets";
149 
150     std::vector<SymbolDisplayPart> expected;
151     expected.emplace_back("CC", "className");
152     expected.emplace_back(".", "punctuation");
153     expected.emplace_back("getName", "functionName");
154     expected.emplace_back("(", "punctuation");
155     expected.emplace_back(")", "punctuation");
156     expected.emplace_back(":", "punctuation");
157     expected.emplace_back(" ", "space");
158     expected.emplace_back("void", "returnType");
159 
160     auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document,
161                                                                  source, sourceDisplay, expectedFileName);
162     initializer.DestroyContext(ctx);
163     ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails);
164 }
165 
TEST_F(LSPCompletionsEntryDetailsTests,GetCompletionEntryDetails4)166 TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails4)
167 {
168     Initializer initializer = Initializer();
169     es2panda_Context *ctx = initializer.CreateContext("completion_entry_details10.ets", ES2PANDA_STATE_CHECKED,
170                                                       R"(interface DuttonInterface {
171   ff(): number;
172 }
173 
174 declare const Dutton: DuttonInterface;)");
175     size_t const offset = 66;
176     LSPAPI const *lspApi = GetImpl();
177     const char *entryName = "Dutton";
178     auto completionEntryDetails =
179         lspApi->getCompletionEntryDetails(entryName, "completion_entry_details10.ets", ctx, offset);
180     ASSERT_NE(completionEntryDetails, CompletionEntryDetails());
181     std::vector<SymbolDisplayPart> source {};
182     std::vector<SymbolDisplayPart> sourceDisplay {};
183     std::vector<SymbolDisplayPart> document {};
184     const std::string kind = "property";
185     const std::string kindModifiers = "static public declare const";
186     const std::string expectedFileName = "completion_entry_details10.ets";
187 
188     std::vector<SymbolDisplayPart> expected;
189     expected.emplace_back("const", "keyword");
190     expected.emplace_back(" ", "space");
191     expected.emplace_back("Dutton", "property");
192     expected.emplace_back(":", "punctuation");
193     expected.emplace_back(" ", "space");
194     expected.emplace_back("DuttonInterface", "typeName");
195 
196     auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document,
197                                                                  source, sourceDisplay, expectedFileName);
198     initializer.DestroyContext(ctx);
199     ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails);
200 }
201 
TEST_F(LSPCompletionsEntryDetailsTests,GetCompletionEntryDetails5)202 TEST_F(LSPCompletionsEntryDetailsTests, GetCompletionEntryDetails5)
203 {
204     Initializer initializer = Initializer();
205     es2panda_Context *ctx = initializer.CreateContext("completion_entry_details11.ets", ES2PANDA_STATE_CHECKED,
206                                                       R"(class DuttonInterface {
207   ff : number;
208   constructor(ff:number) {
209     this.ff = ff;
210   }
211   static buttonRun(value: string | number | boolean):number{
212     return 1;
213   }
214 }
215 
216  function aa() {
217    let Dutton: DuttonInterface = new DuttonInterface(1);
218    let  a = DuttonInterface.buttonRun(1)
219 })");
220     size_t const offset = 280;
221     LSPAPI const *lspApi = GetImpl();
222     const char *entryName = "buttonRun";
223     auto completionEntryDetails =
224         lspApi->getCompletionEntryDetails(entryName, "completion_entry_details11.ets", ctx, offset);
225     ASSERT_NE(completionEntryDetails, CompletionEntryDetails());
226     std::vector<SymbolDisplayPart> source {};
227     std::vector<SymbolDisplayPart> sourceDisplay {};
228     std::vector<SymbolDisplayPart> document {};
229     const std::string kind = "function";
230     const std::string kindModifiers = "static public";
231     const std::string expectedFileName = "completion_entry_details11.ets";
232 
233     std::vector<SymbolDisplayPart> expected;
234     expected.emplace_back("DuttonInterface", "className");
235     expected.emplace_back(".", "punctuation");
236     expected.emplace_back("buttonRun", "functionName");
237     expected.emplace_back("(", "punctuation");
238     expected.emplace_back("value", "functionParameter");
239     expected.emplace_back(":", "punctuation");
240     expected.emplace_back(" ", "space");
241     expected.emplace_back("string|number|boolean", "typeParameter");
242     expected.emplace_back(")", "punctuation");
243     expected.emplace_back(":", "punctuation");
244     expected.emplace_back(" ", "space");
245     expected.emplace_back("number", "returnType");
246 
247     auto expectedCompletionEntryDetails = CompletionEntryDetails(entryName, kind, kindModifiers, expected, document,
248                                                                  source, sourceDisplay, expectedFileName);
249     initializer.DestroyContext(ctx);
250     ASSERT_EQ(completionEntryDetails, expectedCompletionEntryDetails);
251 }
252 
TEST_F(LSPCompletionsEntryDetailsTests,CreateDisplayForClass)253 TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForClass)
254 {
255     Initializer initializer = Initializer();
256     es2panda_Context *ctx =
257         initializer.CreateContext("completion_entry_details3.ets", ES2PANDA_STATE_CHECKED,
258                                   "class Test {\n  private _a: number = 1;\n  public get a(): number {\n    "
259                                   "return this._a;\n  }\n  public static ccc:number = 1\n\n  constructor(a : "
260                                   "number) {\n  }\n}\n\nlet a = 1\nlet test: Test = new Test(a)\nlet t_a = test.a");
261     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
262     const char *entryName = "Test";
263     auto context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
264     auto ast = reinterpret_cast<ark::es2panda::ir::AstNode *>(context->parserProgram->Ast());
265     auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) {
266         return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName);
267     };
268     auto found = ast->FindChild(checkFunc);
269     auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier());
270     std::vector<SymbolDisplayPart> display = ark::es2panda::lsp::CreateDisplayForClass(targetNode);
271     std::vector<SymbolDisplayPart> expected;
272     auto keyword1 = SymbolDisplayPart("class", "keyword");
273     auto keyword2 = SymbolDisplayPart(" ", "space");
274     auto keyword3 = SymbolDisplayPart("Test", "className");
275     expected.push_back(keyword1);
276     expected.push_back(keyword2);
277     expected.push_back(keyword3);
278     ASSERT_EQ(expected, display);
279     initializer.DestroyContext(ctx);
280 }
281 
TEST_F(LSPCompletionsEntryDetailsTests,CreateDisplayForClassDeclarationTypeParameter)282 TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForClassDeclarationTypeParameter)
283 {
284     Initializer initializer = Initializer();
285     es2panda_Context *ctx = initializer.CreateContext("completion_entry_details4.ets", ES2PANDA_STATE_CHECKED,
286                                                       "class Queue<T> { private items: T[] = []; }");
287     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
288     const char *entryName = "T";
289     auto context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
290     auto ast = reinterpret_cast<ark::es2panda::ir::AstNode *>(context->parserProgram->Ast());
291     auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) {
292         return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName);
293     };
294     auto found = ast->FindChild(checkFunc);
295     auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier());
296     std::vector<SymbolDisplayPart> display = ark::es2panda::lsp::CreateDisplayForTypeParameter(targetNode);
297     std::vector<SymbolDisplayPart> expected;
298     expected.emplace_back("T", "typeParameter");
299     expected.emplace_back(" ", "space");
300     expected.emplace_back("in", "keyword");
301     expected.emplace_back(" ", "space");
302     expected.emplace_back("Queue", "className");
303     expected.emplace_back("<", "punctuation");
304     expected.emplace_back("T", "typeParameter");
305     expected.emplace_back(">", "punctuation");
306     ASSERT_EQ(expected, display);
307     initializer.DestroyContext(ctx);
308 }
309 
TEST_F(LSPCompletionsEntryDetailsTests,CreateDisplayForUnionTypeAlias)310 TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForUnionTypeAlias)
311 {
312     Initializer initializer = Initializer();
313     es2panda_Context *ctx = initializer.CreateContext("completion_entry_details5.ets", ES2PANDA_STATE_CHECKED,
314                                                       "type TestUnion = string | number;");
315     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
316     const char *entryName = "TestUnion";
317     auto context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
318     auto ast = reinterpret_cast<ark::es2panda::ir::AstNode *>(context->parserProgram->Ast());
319     auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) {
320         return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName);
321     };
322     auto found = ast->FindChild(checkFunc);
323     auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier());
324     std::vector<SymbolDisplayPart> display = ark::es2panda::lsp::CreateDisplayForTypeAlias(targetNode);
325     std::vector<SymbolDisplayPart> expected;
326     expected.emplace_back("type", "keyword");
327     expected.emplace_back(" ", "space");
328     expected.emplace_back("TestUnion", "className");
329     expected.emplace_back(" ", "space");
330     expected.emplace_back("=", "operator");
331     expected.emplace_back(" ", "space");
332     expected.emplace_back("string|number", "typeName");
333     ASSERT_EQ(expected, display);
334     initializer.DestroyContext(ctx);
335 }
336 
TEST_F(LSPCompletionsEntryDetailsTests,CreateDisplayForTypeAlias)337 TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForTypeAlias)
338 {
339     Initializer initializer = Initializer();
340     es2panda_Context *ctx =
341         initializer.CreateContext("completion_entry_details6.ets", ES2PANDA_STATE_CHECKED, "type TestType = string;");
342     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
343     const char *entryName = "TestType";
344     auto context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
345     auto ast = reinterpret_cast<ark::es2panda::ir::AstNode *>(context->parserProgram->Ast());
346     auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) {
347         return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName);
348     };
349     auto found = ast->FindChild(checkFunc);
350     auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier());
351     std::vector<SymbolDisplayPart> display = ark::es2panda::lsp::CreateDisplayForTypeAlias(targetNode);
352     std::vector<SymbolDisplayPart> expected;
353     expected.emplace_back("type", "keyword");
354     expected.emplace_back(" ", "space");
355     expected.emplace_back("TestType", "className");
356     expected.emplace_back(" ", "space");
357     expected.emplace_back("=", "operator");
358     expected.emplace_back(" ", "space");
359     expected.emplace_back("string", "typeName");
360     ASSERT_EQ(expected, display);
361     initializer.DestroyContext(ctx);
362 }
363 
TEST_F(LSPCompletionsEntryDetailsTests,CreateDisplayForInterface)364 TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForInterface)
365 {
366     Initializer initializer = Initializer();
367     es2panda_Context *ctx = initializer.CreateContext(
368         "completion_entry_details7.ets", ES2PANDA_STATE_CHECKED,
369         "interface Inner { key : string; }\ninterface Outer { inner : Inner; keyValue : number; }");
370     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
371     const char *entryName = "Inner";
372     auto context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
373     auto ast = reinterpret_cast<ark::es2panda::ir::AstNode *>(context->parserProgram->Ast());
374     auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) {
375         return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName);
376     };
377     auto found = ast->FindChild(checkFunc);
378     auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier());
379     std::vector<SymbolDisplayPart> display = ark::es2panda::lsp::CreateDisplayForInterface(targetNode);
380     std::vector<SymbolDisplayPart> expected;
381     auto keyword1 = SymbolDisplayPart("interface", "keyword");
382     auto keyword2 = SymbolDisplayPart(" ", "space");
383     auto keyword3 = SymbolDisplayPart("Inner", "className");
384     expected.push_back(keyword1);
385     expected.push_back(keyword2);
386     expected.push_back(keyword3);
387     ASSERT_EQ(expected, display);
388     initializer.DestroyContext(ctx);
389 }
390 
TEST_F(LSPCompletionsEntryDetailsTests,CreateDisplayForTypeAliasTypeParameter)391 TEST_F(LSPCompletionsEntryDetailsTests, CreateDisplayForTypeAliasTypeParameter)
392 {
393     Initializer initializer = Initializer();
394     es2panda_Context *ctx =
395         initializer.CreateContext("completion_entry_details8.ets", ES2PANDA_STATE_CHECKED, "type list<T> = T[]");
396     ASSERT_EQ(ContextState(ctx), ES2PANDA_STATE_CHECKED);
397     const char *entryName = "T";
398     auto context = reinterpret_cast<ark::es2panda::public_lib::Context *>(ctx);
399     auto ast = reinterpret_cast<ark::es2panda::ir::AstNode *>(context->parserProgram->Ast());
400     auto checkFunc = [entryName](ark::es2panda::ir::AstNode *node) {
401         return ark::es2panda::lsp::HasPropertyAccessExpressionWithName(node, entryName);
402     };
403     auto found = ast->FindChild(checkFunc);
404     auto targetNode = ark::es2panda::compiler::DeclarationFromIdentifier(found->AsIdentifier());
405     std::vector<SymbolDisplayPart> display = ark::es2panda::lsp::CreateDisplayForTypeParameter(targetNode);
406     std::vector<SymbolDisplayPart> expected;
407     expected.emplace_back("T", "typeParameter");
408     expected.emplace_back(" ", "space");
409     expected.emplace_back("in", "keyword");
410     expected.emplace_back(" ", "space");
411     expected.emplace_back("type", "keyword");
412     expected.emplace_back(" ", "space");
413     expected.emplace_back("list", "typeName");
414     expected.emplace_back("<", "punctuation");
415     expected.emplace_back("T", "typeParameter");
416     expected.emplace_back(">", "punctuation");
417     ASSERT_EQ(expected, display);
418     initializer.DestroyContext(ctx);
419 }
420 
421 }  // namespace