• 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/suggestion_diagnostics.h"
17 #include <gtest/gtest.h>
18 #include "lsp/include/internal_api.h"
19 #include "lsp/include/classifier.h"
20 #include "lsp_api_test.h"
21 #include "public/es2panda_lib.h"
22 namespace {
23 using ark::es2panda::lsp::Initializer;
24 
25 class LspSuggestionTests : public LSPAPITests {};
26 
TEST_F(LspSuggestionTests,canBeConvertedToAsync)27 TEST_F(LspSuggestionTests, canBeConvertedToAsync)
28 {
29     const char *source = "function add(x: number, y: number): number\n {return x + y;};";
30     Initializer initializer = Initializer();
31     es2panda_Context *ctx = initializer.CreateContext("sug-diag.ets", ES2PANDA_STATE_CHECKED, source);
32     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
33     auto node = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) {
34         return childNode->Type() == ark::es2panda::ir::AstNodeType::FUNCTION_EXPRESSION;
35     });
36     EXPECT_TRUE(ark::es2panda::lsp::CanBeConvertedToAsync(node));
37     initializer.DestroyContext(ctx);
38 }
39 
TEST_F(LspSuggestionTests,isFixablePromiseArgument)40 TEST_F(LspSuggestionTests, isFixablePromiseArgument)
41 {
42     const char *source =
43         "function add(x: number, y: number): number\n {return x + y;}"
44         "\nconsole.log(add(1,2));";
45     Initializer initializer = Initializer();
46     es2panda_Context *ctx = initializer.CreateContext("sug-diag.ets", ES2PANDA_STATE_CHECKED, source);
47     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
48     std::unordered_map<std::string, bool> visitedNestedConvertibleFunctions;
49     auto node = ast->FindChild([](ark::es2panda::ir::AstNode *childNode) {
50         return childNode->Type() == ark::es2panda::ir::AstNodeType::FUNCTION_EXPRESSION;
51     });
52     EXPECT_TRUE(ark::es2panda::lsp::IsFixablePromiseArgument(node, visitedNestedConvertibleFunctions));
53     initializer.DestroyContext(ctx);
54 }
TEST_F(LspSuggestionTests,hasSupportedNumberOfArguments)55 TEST_F(LspSuggestionTests, hasSupportedNumberOfArguments)
56 {
57     const char *source =
58         "function fetchData():Promise<string>{\n"
59         "\nreturn Promise.resolve(\"Success\");\n}\nfetchData().then();";
60     Initializer initializer = Initializer();
61     es2panda_Context *ctx = initializer.CreateContext("token-pos-literal.ets", ES2PANDA_STATE_CHECKED, source);
62     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
63     std::vector<ark::es2panda::ir::AstNode *> callExprs;
64     ast->FindChild([&callExprs](ark::es2panda::ir::AstNode *node) {
65         if (node->Type() == ark::es2panda::ir::AstNodeType::CALL_EXPRESSION) {
66             callExprs.push_back(node);
67         }
68         return false;
69     });
70     EXPECT_TRUE(ark::es2panda::lsp::HasSupportedNumberOfArguments(callExprs.at(0)));
71     initializer.DestroyContext(ctx);
72 }
TEST_F(LspSuggestionTests,hasSupportedNumberOfArguments2)73 TEST_F(LspSuggestionTests, hasSupportedNumberOfArguments2)
74 {
75     const char *source =
76         "function fetchData():Promise<string>{\n"
77         "\nreturn Promise.reject(\"Error\");\n}\nfetchData().catch();";
78     Initializer initializer = Initializer();
79     es2panda_Context *ctx = initializer.CreateContext("token-pos-literal.ets", ES2PANDA_STATE_CHECKED, source);
80     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
81     std::vector<ark::es2panda::ir::AstNode *> callExprs;
82     ast->FindChild([&callExprs](ark::es2panda::ir::AstNode *node) {
83         if (node->Type() == ark::es2panda::ir::AstNodeType::CALL_EXPRESSION) {
84             callExprs.push_back(node);
85         }
86 
87         return false;
88     });
89     EXPECT_TRUE(ark::es2panda::lsp::HasSupportedNumberOfArguments(callExprs.at(0)));
90     initializer.DestroyContext(ctx);
91 }
TEST_F(LspSuggestionTests,hasSupportedNumberOfArguments3)92 TEST_F(LspSuggestionTests, hasSupportedNumberOfArguments3)
93 {
94     const char *source =
95         "function fetchData():Promise<string>{\nreturn Promise.resolve(\"Success\");\n}"
96         "\nfetchData().finally();";
97     Initializer initializer = Initializer();
98     es2panda_Context *ctx = initializer.CreateContext("token-pos-literal.ets", ES2PANDA_STATE_CHECKED, source);
99     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
100     std::vector<ark::es2panda::ir::AstNode *> callExprs;
101     ast->FindChild([&callExprs](ark::es2panda::ir::AstNode *node) {
102         if (node->Type() == ark::es2panda::ir::AstNodeType::CALL_EXPRESSION) {
103             callExprs.push_back(node);
104         }
105         return false;
106     });
107     EXPECT_TRUE(ark::es2panda::lsp::HasSupportedNumberOfArguments(callExprs.at(0)));
108     initializer.DestroyContext(ctx);
109 }
TEST_F(LspSuggestionTests,hasSupportedNumberOfArguments4)110 TEST_F(LspSuggestionTests, hasSupportedNumberOfArguments4)
111 {
112     const char *source =
113         "function fetchData(name:string):Promise<string>{\n"
114         "\nreturn Promise.resolve(\"Success\");\n}\nfetchData(\"test\").finally();";
115     Initializer initializer = Initializer();
116     es2panda_Context *ctx = initializer.CreateContext("token-pos-literal.ets", ES2PANDA_STATE_CHECKED, source);
117     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
118     std::vector<ark::es2panda::ir::AstNode *> callExprs;
119     ast->FindChild([&callExprs](ark::es2panda::ir::AstNode *node) {
120         if (node->Type() == ark::es2panda::ir::AstNodeType::CALL_EXPRESSION) {
121             callExprs.push_back(node);
122         }
123         return false;
124     });
125     EXPECT_TRUE(ark::es2panda::lsp::HasSupportedNumberOfArguments(callExprs.at(0)));
126     initializer.DestroyContext(ctx);
127 }
128 
TEST_F(LspSuggestionTests,GetSuggestionDiagnostics)129 TEST_F(LspSuggestionTests, GetSuggestionDiagnostics)
130 {
131     const char *source =
132         "function fetchData(){\nreturn Promise.resolve(\"h\")\n;}\nfunction processData()"
133         "{\nreturn fetchData().finally();\n};\nprocessData();\n";
134     Initializer initializer = Initializer();
135     es2panda_Context *context = initializer.CreateContext("sug-diag.ets", ES2PANDA_STATE_CHECKED, source);
136     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(context);
137     auto diag = ark::es2panda::lsp::GetSuggestionDiagnosticsImpl(ast);
138     const auto message = "This_may_be_converted_to_an_async_function";
139     auto severity = DiagnosticSeverity::Hint;
140     int const startLine = 0;
141     int const endLine = 2;
142     int const startChar = 9;
143     int const endChar = 52;
144     ASSERT_EQ(diag.at(0).diagnostic.range_.start.line_, startLine);
145     ASSERT_EQ(diag.at(0).diagnostic.range_.end.line_, endLine);
146     ASSERT_EQ(diag.at(0).diagnostic.range_.start.character_, startChar);
147     ASSERT_EQ(diag.at(0).diagnostic.range_.end.character_, endChar);
148     ASSERT_EQ(diag.at(0).diagnostic.message_, message);
149     ASSERT_EQ(diag.at(0).diagnostic.severity_, severity);
150     initializer.DestroyContext(context);
151 }
152 
TEST_F(LspSuggestionTests,GetSuggestionDiagnostics2)153 TEST_F(LspSuggestionTests, GetSuggestionDiagnostics2)
154 {
155     Initializer initializer = Initializer();
156     es2panda_Context *ctx =
157         initializer.CreateContext("ds1.ets", ES2PANDA_STATE_CHECKED,
158                                   "function fetchData(){\nreturn Promise.resolve(\"h\")\n;}\nfunction processData()"
159                                   "{\nreturn fetchData().finally();\n};\nprocessData();\n");
160     LSPAPI const *lspApi = GetImpl();
161     auto diag = lspApi->getSuggestionDiagnostics(ctx);
162     initializer.DestroyContext(ctx);
163     const auto msg = "This_may_be_converted_to_an_async_function";
164     auto severity = DiagnosticSeverity::Hint;
165     int const startLine = 0;
166     int const endLine = 2;
167     int const startChar = 9;
168     int const endChar = 52;
169     ASSERT_EQ(diag.diagnostic.at(0).range_.start.line_, startLine);
170     ASSERT_EQ(diag.diagnostic.at(0).range_.end.line_, endLine);
171     ASSERT_EQ(diag.diagnostic.at(0).range_.start.character_, startChar);
172     ASSERT_EQ(diag.diagnostic.at(0).range_.end.character_, endChar);
173     ASSERT_EQ(diag.diagnostic.at(0).message_, msg);
174     ASSERT_EQ(diag.diagnostic.at(0).severity_, severity);
175 }
176 
TEST_F(LspSuggestionTests,isPromiseHandler)177 TEST_F(LspSuggestionTests, isPromiseHandler)
178 {
179     const char *source =
180         "function fetchData(name:string):Promise<string>{\n"
181         "\nreturn Promise.resolve(\"Success\");\n}\nfetchData(\"test\").finally();";
182     Initializer initializer = Initializer();
183     es2panda_Context *ctx = initializer.CreateContext("sug-diag.ets", ES2PANDA_STATE_CHECKED, source);
184     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
185     std::vector<ark::es2panda::ir::AstNode *> callExprs;
186     ast->FindChild([&callExprs](ark::es2panda::ir::AstNode *node) {
187         if (node->Type() == ark::es2panda::ir::AstNodeType::CALL_EXPRESSION) {
188             callExprs.push_back(node);
189         }
190         return false;
191     });
192     EXPECT_TRUE(ark::es2panda::lsp::IsPromiseHandler(callExprs.at(0)));
193     initializer.DestroyContext(ctx);
194 }
195 
TEST_F(LspSuggestionTests,isPromiseHandler2)196 TEST_F(LspSuggestionTests, isPromiseHandler2)
197 {
198     const char *source =
199         "function fetchData():Promise<string>{\n"
200         "\nreturn Promise.reject(\"Error\");\n}\nfetchData().catch();";
201     Initializer initializer = Initializer();
202     es2panda_Context *ctx = initializer.CreateContext("sug-diag.ets", ES2PANDA_STATE_CHECKED, source);
203     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
204     std::vector<ark::es2panda::ir::AstNode *> callExprs;
205     ast->FindChild([&callExprs](ark::es2panda::ir::AstNode *node) {
206         if (node->Type() == ark::es2panda::ir::AstNodeType::CALL_EXPRESSION) {
207             callExprs.push_back(node);
208         }
209         return false;
210     });
211     EXPECT_TRUE(ark::es2panda::lsp::IsPromiseHandler(callExprs.at(0)));
212     initializer.DestroyContext(ctx);
213 }
214 
TEST_F(LspSuggestionTests,isPromiseHandler3)215 TEST_F(LspSuggestionTests, isPromiseHandler3)
216 {
217     const char *source =
218         "function fetchData():Promise<string>{\n"
219         "\nreturn Promise.resolve(\"Success\");\n}\nfetchData().then();";
220     Initializer initializer = Initializer();
221     es2panda_Context *ctx = initializer.CreateContext("sug-diag.ets", ES2PANDA_STATE_CHECKED, source);
222     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
223     std::vector<ark::es2panda::ir::AstNode *> callExprs;
224     ast->FindChild([&callExprs](ark::es2panda::ir::AstNode *node) {
225         if (node->Type() == ark::es2panda::ir::AstNodeType::CALL_EXPRESSION) {
226             callExprs.push_back(node);
227         }
228         return false;
229     });
230     EXPECT_TRUE(ark::es2panda::lsp::IsPromiseHandler(callExprs.at(0)));
231     initializer.DestroyContext(ctx);
232 }
233 
TEST_F(LspSuggestionTests,isPromiseHandler4)234 TEST_F(LspSuggestionTests, isPromiseHandler4)
235 {
236     const char *source =
237         "function fetchData(name: string,name2:string):Promise<string>{\n"
238         "\nreturn Promise.resolve(\"Success\");\n}\nfetchData(\"test\",\"test2\").finally();";
239     Initializer initializer = Initializer();
240     es2panda_Context *ctx = initializer.CreateContext("sug-diag.ets", ES2PANDA_STATE_CHECKED, source);
241     auto ast = GetAstFromContext<ark::es2panda::ir::AstNode>(ctx);
242     std::vector<ark::es2panda::ir::AstNode *> callExprs;
243     ast->FindChild([&callExprs](ark::es2panda::ir::AstNode *node) {
244         if (node->Type() == ark::es2panda::ir::AstNodeType::CALL_EXPRESSION) {
245             callExprs.push_back(node);
246         }
247         return false;
248     });
249     EXPECT_TRUE(ark::es2panda::lsp::IsPromiseHandler(callExprs.at(0)));
250     initializer.DestroyContext(ctx);
251 }
252 }  // namespace