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 #include <iostream>
16 #include <ostream>
17 #include <string>
18
19 #include "public/es2panda_lib.h"
20 #include "util.h"
21
22 // NOLINTBEGIN
23
24 /*
25 * Covered C API List:
26 * size_t(*SourcePositionIndex)(es2panda_Context *context, es2panda_SourcePosition *position);
27 * size_t(*SourcePositionLine)(es2panda_Context *context, es2panda_SourcePosition *position);
28 * es2panda_Config *(*CreateConfig)(int argc, char const * const *argv);
29 * es2panda_Context *(*CreateContextFromString)(es2panda_Config *config, const char *source, char const *file_name);
30 * es2panda_SourcePosition *(*CreateSourcePosition)(es2panda_Context *context, size_t index, size_t line);
31 * es2panda_SourceRange *(*CreateSourceRange)(es2panda_Context *context, es2panda_SourcePosition *start,
32 * es2panda_SourcePosition *end);
33 * es2panda_SourcePosition *(*SourceRangeStart)(es2panda_Context *context, es2panda_SourceRange *range);
34 * es2panda_SourcePosition *(*SourceRangeEnd)(es2panda_Context *context, es2panda_SourceRange *range);
35 * es2panda_AstNode *(*CreateNumberLiteral)(es2panda_Context *ctx, int32_t value);
36 * es2panda_AstNode *(*CreateNumberLiteral1)(es2panda_Context *ctx, int64_t value);
37 * es2panda_AstNode *(*CreateNumberLiteral2)(es2panda_Context *ctx, double value);
38 * es2panda_AstNode *(*CreateNumberLiteral3)(es2panda_Context *ctx, float value);
39 * es2panda_AstNode *(*UpdateNumberLiteral)(es2panda_Context *ctx, es2panda_AstNode *original, int32_t value);
40 * es2panda_AstNode *(*UpdateNumberLiteral1)(es2panda_Context *ctx, es2panda_AstNode *original, int64_t value);
41 * es2panda_AstNode *(*UpdateNumberLiteral2)(es2panda_Context *ctx, es2panda_AstNode *original, double value);
42 * es2panda_AstNode *(*UpdateNumberLiteral3)(es2panda_Context *ctx, es2panda_AstNode *original, float value);
43 * bool(*NumberLiteralSetInt)(es2panda_AstNode *node, int32_t new_value);
44 * bool(*NumberLiteralSetLong)(es2panda_AstNode *node, int64_t new_value);
45 * bool(*NumberLiteralSetDouble)(es2panda_AstNode *node, double new_value);
46 * bool(*NumberLiteralSetFloat)(es2panda_AstNode *node, float new_value);
47 * char *(*)(es2panda_Context *, Es2pandaEnum);
48 * Es2pandaEnum (*)(es2panda_Context *, const char *);
49 * void(*DestroyContext)(es2panda_Context *context);
50 * void(*DestroyConfig)(es2panda_Config *config);
51 * es2panda_Program *(*ContextProgram)(es2panda_Context *context);
52 * es2panda_Context *(*ProceedToState)(es2panda_Context *context, es2panda_ContextState state);
53 * es2panda_ExternalSource **(*ProgramExternalSources)(es2panda_Program *program, size_t *len_p)
54 * char const *(*ExternalSourceName)(es2panda_ExternalSource *e_source)
55 * es2panda_Program **(*ExternalSourcePrograms)(es2panda_ExternalSource *e_source, size_t *len_p)
56 */
57
58 namespace {
59 // these FAIL_CODE does not share with other files.
60 constexpr int SOURCE_POSITION_FAIL_CODE = 0x10;
61 constexpr int NUMBER_LITERAL_FAIL_CODE = 0x11;
62 constexpr int ENUM_STRING_CONVERSION_FAIL_CODE = 0x12;
63 constexpr int EXTERNAL_SOURCE_FAIL_CODE = 0x13;
64
65 es2panda_Impl *g_impl = nullptr;
66 } // namespace
67
IsSourcePositionEqual(es2panda_Context * ctx,es2panda_SourcePosition * firstPos,es2panda_SourcePosition * secondPos)68 bool IsSourcePositionEqual(es2panda_Context *ctx, es2panda_SourcePosition *firstPos, es2panda_SourcePosition *secondPos)
69 {
70 if (firstPos == nullptr || secondPos == nullptr) {
71 return false;
72 }
73 if (g_impl->SourcePositionIndex(ctx, firstPos) != g_impl->SourcePositionIndex(ctx, secondPos)) {
74 return false;
75 }
76 if (g_impl->SourcePositionLine(ctx, firstPos) != g_impl->SourcePositionLine(ctx, secondPos)) {
77 return false;
78 }
79
80 return true;
81 }
82
CheckSourcePosition(es2panda_Context * ctx)83 bool CheckSourcePosition(es2panda_Context *ctx)
84 {
85 es2panda_SourcePosition *pos = g_impl->CreateSourcePosition(ctx, 3, 5);
86 size_t origPosIndex {3};
87 size_t origPosLine {5};
88 size_t posIndex = g_impl->SourcePositionIndex(ctx, pos);
89 if (posIndex != origPosIndex) {
90 return false;
91 }
92 size_t posLine = g_impl->SourcePositionLine(ctx, pos);
93 if (posLine != origPosLine) {
94 return false;
95 }
96
97 es2panda_SourcePosition *leftPos = g_impl->CreateSourcePosition(ctx, 4, 1);
98 es2panda_SourcePosition *rightPos = g_impl->CreateSourcePosition(ctx, 4, 5);
99 es2panda_SourceRange *posRange = g_impl->CreateSourceRange(ctx, leftPos, rightPos);
100 if (!IsSourcePositionEqual(ctx, leftPos, g_impl->SourceRangeStart(ctx, posRange))) {
101 return false;
102 }
103 if (!IsSourcePositionEqual(ctx, rightPos, g_impl->SourceRangeEnd(ctx, posRange))) {
104 return false;
105 }
106 return true;
107 }
108
CheckNumberLiteral(es2panda_Context * ctx)109 bool CheckNumberLiteral(es2panda_Context *ctx)
110 {
111 auto *int32AstNode = g_impl->CreateNumberLiteral(ctx, 0);
112 if (int32AstNode == nullptr) {
113 return false;
114 }
115 auto *int64AstNode = g_impl->CreateNumberLiteral1(ctx, 1);
116 if (int64AstNode == nullptr) {
117 return false;
118 }
119 auto *doubleAstNode = g_impl->CreateNumberLiteral2(ctx, 2.0);
120 if (doubleAstNode == nullptr) {
121 return false;
122 }
123 auto *floatAstNode = g_impl->CreateNumberLiteral3(ctx, 3.0);
124 if (floatAstNode == nullptr) {
125 return false;
126 }
127
128 auto *updatedInt32AstNode = g_impl->UpdateNumberLiteral(ctx, int32AstNode, 4);
129 if (updatedInt32AstNode == nullptr) {
130 return false;
131 }
132 auto *updatedInt64AstNode = g_impl->UpdateNumberLiteral1(ctx, int64AstNode, 5);
133 if (updatedInt64AstNode == nullptr) {
134 return false;
135 }
136 auto *updatedDoubleAstNode = g_impl->UpdateNumberLiteral2(ctx, doubleAstNode, 6.0);
137 if (updatedDoubleAstNode == nullptr) {
138 return false;
139 }
140 auto *updatedFloatAstNode = g_impl->UpdateNumberLiteral3(ctx, floatAstNode, 7.0);
141 if (updatedFloatAstNode == nullptr) {
142 return false;
143 }
144
145 bool setInt32Result = g_impl->NumberLiteralSetInt(updatedInt32AstNode, 8);
146 bool setInt64Result = g_impl->NumberLiteralSetLong(updatedInt64AstNode, 9);
147 bool setDoubleResult = g_impl->NumberLiteralSetDouble(updatedDoubleAstNode, 10.0);
148 bool setFloatResult = g_impl->NumberLiteralSetFloat(updatedFloatAstNode, 11.0);
149 return setInt32Result && setInt64Result && setDoubleResult && setFloatResult;
150 }
151
CheckEnumStringConversion(es2panda_Context * ctx)152 bool CheckEnumStringConversion(es2panda_Context *ctx)
153 {
154 auto enumNodeHasParent =
155 g_impl->Es2pandaEnumFromString(ctx, g_impl->Es2pandaEnumToString(ctx, Es2pandaEnum::ENUM_NODE_HAS_PARENT));
156 if (enumNodeHasParent != Es2pandaEnum::ENUM_NODE_HAS_PARENT) {
157 return false;
158 }
159
160 auto enumFirst = g_impl->Es2pandaEnumFromString(ctx, g_impl->Es2pandaEnumToString(ctx, Es2pandaEnum::ENUM_FIRST));
161 if (enumFirst != Es2pandaEnum::ENUM_FIRST) {
162 return false;
163 }
164
165 return true;
166 }
167
CheckExternalSource(es2panda_Context * ctx)168 bool CheckExternalSource(es2panda_Context *ctx)
169 {
170 auto *program = g_impl->ContextProgram(ctx);
171 g_impl->ProceedToState(ctx, ES2PANDA_STATE_BOUND);
172
173 size_t externalSourceCnt {0};
174 auto **externalSourceList = g_impl->ProgramExternalSources(ctx, program, &externalSourceCnt);
175 if (externalSourceList == nullptr) {
176 return false;
177 }
178
179 auto externalSourceName = g_impl->ExternalSourceName(externalSourceList[0]);
180 if (externalSourceName == nullptr) {
181 return false;
182 }
183
184 size_t externalProgramCount {0};
185 auto **programList = g_impl->ExternalSourcePrograms(externalSourceList[0], &externalProgramCount);
186 if (programList == nullptr) {
187 return false;
188 }
189
190 return true;
191 }
192
main(int argc,char ** argv)193 int main(int argc, char **argv)
194 {
195 if (argc < MIN_ARGC) {
196 return INVALID_ARGC_ERROR_CODE;
197 }
198 g_impl = GetImpl();
199 if (g_impl == nullptr) {
200 return NULLPTR_IMPL_ERROR_CODE;
201 }
202 auto config = g_impl->CreateConfig(argc - 1, argv + 1);
203 auto src = std::string("function foo(builder: () => void) {}\nfoo(() => {})");
204 auto context = g_impl->CreateContextFromString(config, src.c_str(), argv[argc - 1]);
205 if (context == nullptr) {
206 std::cerr << "FAILED TO CREATE CONTEXT" << std::endl;
207 return NULLPTR_CONTEXT_ERROR_CODE;
208 }
209
210 if (!CheckSourcePosition(context)) {
211 return SOURCE_POSITION_FAIL_CODE;
212 }
213
214 if (!CheckNumberLiteral(context)) {
215 return NUMBER_LITERAL_FAIL_CODE;
216 }
217
218 if (!CheckEnumStringConversion(context)) {
219 return ENUM_STRING_CONVERSION_FAIL_CODE;
220 }
221
222 if (!CheckExternalSource(context)) {
223 return EXTERNAL_SOURCE_FAIL_CODE;
224 }
225
226 g_impl->DestroyContext(context);
227 g_impl->DestroyConfig(config);
228
229 return 0;
230 }
231
232 // NOLINTEND