1 /**
2 * Copyright (c) 2021-2024 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 "helpers.h"
17
18 #include "generated/signatures.h"
19 #include "varbinder/privateBinding.h"
20 #include "checker/types/ets/types.h"
21 #include "ir/astNode.h"
22 #include "ir/base/classDefinition.h"
23 #include "ir/base/classProperty.h"
24 #include "ir/base/methodDefinition.h"
25 #include "ir/base/property.h"
26 #include "ir/base/scriptFunction.h"
27 #include "ir/base/spreadElement.h"
28 #include "ir/expressions/arrayExpression.h"
29 #include "ir/expressions/assignmentExpression.h"
30 #include "ir/expressions/callExpression.h"
31 #include "ir/expressions/functionExpression.h"
32 #include "ir/expressions/identifier.h"
33 #include "ir/expressions/literals/numberLiteral.h"
34 #include "ir/expressions/literals/stringLiteral.h"
35 #include "ir/expressions/literals/booleanLiteral.h"
36 #include "ir/expressions/literals/nullLiteral.h"
37 #include "ir/expressions/objectExpression.h"
38 #include "ir/statements/returnStatement.h"
39 #include "ir/statements/variableDeclaration.h"
40 #include "ir/statements/variableDeclarator.h"
41 #include "ir/module/importSpecifier.h"
42 #include "ir/ets/etsImportDeclaration.h"
43 #include "ir/ts/tsParameterProperty.h"
44 #include "ir/ts/tsInterfaceDeclaration.h"
45 #include "ir/ts/tsEnumDeclaration.h"
46 #include "ir/ets/etsParameterExpression.h"
47 #include "ir/module/importDeclaration.h"
48 #include "lexer/token/letters.h"
49 #include "libpandabase/utils/utf.h"
50 #include "libpandabase/os/filesystem.h"
51 #include "ir/module/importDefaultSpecifier.h"
52 #include <iomanip>
53
54 namespace ark::es2panda::util {
55 // Helpers
56
IsGlobalIdentifier(const util::StringView &str)57 bool Helpers::IsGlobalIdentifier(const util::StringView &str)
58 {
59 return (str.Is("NaN") || str.Is("undefined") || str.Is("Infinity"));
60 }
61
ContainSpreadElement(const ArenaVector<ir::Expression *> &args)62 bool Helpers::ContainSpreadElement(const ArenaVector<ir::Expression *> &args)
63 {
64 return std::any_of(args.begin(), args.end(), [](const auto *it) { return it->IsSpreadElement(); });
65 }
66
LiteralToPropName(const ir::Expression *lit)67 util::StringView Helpers::LiteralToPropName(const ir::Expression *lit)
68 {
69 switch (lit->Type()) {
70 case ir::AstNodeType::IDENTIFIER: {
71 return lit->AsIdentifier()->Name();
72 }
73 case ir::AstNodeType::STRING_LITERAL: {
74 return lit->AsStringLiteral()->Str();
75 }
76 case ir::AstNodeType::NUMBER_LITERAL: {
77 return lit->AsNumberLiteral()->Str();
78 }
79 case ir::AstNodeType::NULL_LITERAL: {
80 return "null";
81 }
82 case ir::AstNodeType::UNDEFINED_LITERAL: {
83 return "undefined";
84 }
85 default: {
86 UNREACHABLE();
87 }
88 }
89 }
90
IsIndex(double number)91 bool Helpers::IsIndex(double number)
92 {
93 if (number >= 0 && number < static_cast<double>(INVALID_INDEX)) {
94 auto intNum = static_cast<uint32_t>(number);
95
96 if (static_cast<double>(intNum) == number) {
97 return true;
98 }
99 }
100
101 return false;
102 }
103
IsDigit(char c)104 static bool IsDigit(char c)
105 {
106 return (c >= '0' && c <= '9');
107 }
108
GetIndex(const util::StringView &str)109 int64_t Helpers::GetIndex(const util::StringView &str)
110 {
111 const auto &s = str.Utf8();
112
113 if (s.empty() || (*s.begin() == '0' && s.length() > 1)) {
114 return INVALID_INDEX;
115 }
116
117 int64_t value = 0;
118 for (const auto c : s) {
119 if (!IsDigit(c)) {
120 return INVALID_INDEX;
121 }
122
123 constexpr auto MULTIPLIER = 10;
124 value *= MULTIPLIER;
125 value += (c - '0');
126
127 if (value >= INVALID_INDEX) {
128 return INVALID_INDEX;
129 }
130 }
131
132 return value;
133 }
134
ToString(double number)135 std::string Helpers::ToString(double number)
136 {
137 std::string str;
138
139 if (Helpers::IsInteger<int32_t>(number)) {
140 str = std::to_string(static_cast<int32_t>(number));
141 } else {
142 str = std::to_string(number);
143 }
144
145 return str;
146 }
147
ToStringView(ArenaAllocator *allocator, double number)148 util::StringView Helpers::ToStringView(ArenaAllocator *allocator, double number)
149 {
150 util::UString str(ToString(number), allocator);
151 return str.View();
152 }
153
ToStringView(ArenaAllocator *allocator, uint32_t number)154 util::StringView Helpers::ToStringView(ArenaAllocator *allocator, uint32_t number)
155 {
156 ASSERT(number <= static_cast<uint32_t>(std::numeric_limits<int32_t>::max()));
157 return ToStringView(allocator, static_cast<int32_t>(number));
158 }
159
ToStringView(ArenaAllocator *allocator, int32_t number)160 util::StringView Helpers::ToStringView(ArenaAllocator *allocator, int32_t number)
161 {
162 util::UString str(ToString(number), allocator);
163 return str.View();
164 }
165
EndsWith(const std::string &str, const std::string &suffix)166 bool Helpers::EndsWith(const std::string &str, const std::string &suffix)
167 {
168 if (str.length() < suffix.length()) {
169 return false;
170 }
171 size_t expectPos = str.length() - suffix.length();
172 return str.find(suffix, expectPos) == expectPos;
173 }
174
GetContainingConstructor(const ir::AstNode *node)175 const ir::ScriptFunction *Helpers::GetContainingConstructor(const ir::AstNode *node)
176 {
177 const ir::ScriptFunction *iter = GetContainingFunction(node);
178
179 while (iter != nullptr) {
180 if (iter->IsConstructor()) {
181 return iter;
182 }
183
184 if (!iter->IsArrow()) {
185 return nullptr;
186 }
187
188 iter = GetContainingFunction(iter);
189 }
190
191 return iter;
192 }
193
GetContainingEnumDeclaration(const ir::AstNode *node)194 const ir::TSEnumDeclaration *Helpers::GetContainingEnumDeclaration(const ir::AstNode *node)
195 {
196 auto *iter = node;
197
198 while (iter != nullptr) {
199 if (iter->IsTSEnumDeclaration()) {
200 return iter->AsTSEnumDeclaration();
201 }
202
203 iter = iter->Parent();
204 }
205
206 return nullptr;
207 }
208
GetContainingObjectType(const ir::AstNode *node)209 const checker::ETSObjectType *Helpers::GetContainingObjectType(const ir::AstNode *node)
210 {
211 const auto *iter = node;
212
213 while (iter != nullptr) {
214 if (iter->IsClassDefinition()) {
215 auto *ret = iter->AsClassDefinition()->TsType();
216 return ret != nullptr ? ret->AsETSObjectType() : nullptr;
217 }
218
219 if (iter->IsTSInterfaceDeclaration()) {
220 auto *ret = iter->AsTSInterfaceDeclaration()->TsType();
221 return ret != nullptr ? ret->AsETSObjectType() : nullptr;
222 }
223
224 if (iter->IsTSEnumDeclaration()) {
225 auto *ret = iter->AsTSEnumDeclaration()->TsType();
226 return ret != nullptr ? ret->AsETSObjectType() : nullptr;
227 }
228
229 iter = iter->Parent();
230 }
231
232 return nullptr;
233 }
234
GetContainingClassDefinition(const ir::AstNode *node)235 const ir::ClassDefinition *Helpers::GetContainingClassDefinition(const ir::AstNode *node)
236 {
237 const auto *iter = node;
238
239 while (iter != nullptr) {
240 if (iter->IsClassDefinition()) {
241 return iter->AsClassDefinition();
242 }
243
244 iter = iter->Parent();
245 }
246
247 return nullptr;
248 }
249
GetContainingInterfaceDeclaration(const ir::AstNode *node)250 const ir::TSInterfaceDeclaration *Helpers::GetContainingInterfaceDeclaration(const ir::AstNode *node)
251 {
252 const auto *iter = node;
253
254 while (iter != nullptr) {
255 if (iter->IsTSInterfaceDeclaration()) {
256 return iter->AsTSInterfaceDeclaration();
257 }
258
259 iter = iter->Parent();
260 }
261
262 return nullptr;
263 }
264
GetContainingClassMethodDefinition(const ir::AstNode *node)265 const ir::MethodDefinition *Helpers::GetContainingClassMethodDefinition(const ir::AstNode *node)
266 {
267 const auto *iter = node;
268
269 while (iter != nullptr) {
270 if (iter->IsMethodDefinition()) {
271 return iter->AsMethodDefinition();
272 }
273
274 if (iter->IsClassDefinition()) {
275 break;
276 }
277
278 iter = iter->Parent();
279 }
280
281 return nullptr;
282 }
283
GetContainingClassStaticBlock(const ir::AstNode *node)284 const ir::ClassStaticBlock *Helpers::GetContainingClassStaticBlock(const ir::AstNode *node)
285 {
286 const auto *iter = node;
287
288 while (iter != nullptr) {
289 if (iter->IsClassStaticBlock()) {
290 return iter->AsClassStaticBlock();
291 }
292
293 if (iter->IsClassDefinition()) {
294 break;
295 }
296
297 iter = iter->Parent();
298 }
299
300 return nullptr;
301 }
302
GetContainingConstructor(const ir::ClassProperty *node)303 const ir::ScriptFunction *Helpers::GetContainingConstructor(const ir::ClassProperty *node)
304 {
305 for (const auto *parent = node->Parent(); parent != nullptr; parent = parent->Parent()) {
306 if (parent->IsClassDefinition()) {
307 ASSERT(parent->AsClassDefinition()->Ctor() != nullptr);
308 return parent->AsClassDefinition()->Ctor()->Function();
309 }
310 }
311
312 return nullptr;
313 }
314
GetContainingFunction(const ir::AstNode *node)315 const ir::ScriptFunction *Helpers::GetContainingFunction(const ir::AstNode *node)
316 {
317 for (const auto *parent = node->Parent(); parent != nullptr; parent = parent->Parent()) {
318 if (parent->IsScriptFunction()) {
319 return parent->AsScriptFunction();
320 }
321 }
322
323 return nullptr;
324 }
325
GetClassDefiniton(const ir::ScriptFunction *node)326 const ir::ClassDefinition *Helpers::GetClassDefiniton(const ir::ScriptFunction *node)
327 {
328 ASSERT(node->IsConstructor());
329 ASSERT(node->Parent()->IsFunctionExpression());
330 ASSERT(node->Parent()->Parent()->IsMethodDefinition());
331 ASSERT(node->Parent()->Parent()->Parent()->IsClassDefinition());
332
333 return node->Parent()->Parent()->Parent()->AsClassDefinition();
334 }
335
IsSpecialPropertyKey(const ir::Expression *expr)336 bool Helpers::IsSpecialPropertyKey(const ir::Expression *expr)
337 {
338 if (!expr->IsStringLiteral()) {
339 return false;
340 }
341
342 auto *lit = expr->AsStringLiteral();
343 return lit->Str().Is("prototype") || lit->Str().Is("constructor");
344 }
345
IsConstantPropertyKey(const ir::Expression *expr, bool isComputed)346 bool Helpers::IsConstantPropertyKey(const ir::Expression *expr, bool isComputed)
347 {
348 switch (expr->Type()) {
349 case ir::AstNodeType::IDENTIFIER: {
350 return !isComputed;
351 }
352 case ir::AstNodeType::NUMBER_LITERAL:
353 case ir::AstNodeType::STRING_LITERAL:
354 case ir::AstNodeType::BOOLEAN_LITERAL:
355 case ir::AstNodeType::NULL_LITERAL: {
356 return true;
357 }
358 default:
359 break;
360 }
361
362 return false;
363 }
364
ToConstantLiteral(const ir::Expression *expr)365 compiler::Literal Helpers::ToConstantLiteral(const ir::Expression *expr)
366 {
367 switch (expr->Type()) {
368 case ir::AstNodeType::NUMBER_LITERAL: {
369 auto *lit = expr->AsNumberLiteral();
370 if (util::Helpers::IsInteger<uint32_t>(lit->Number().GetDouble())) {
371 return compiler::Literal(static_cast<uint32_t>(lit->Number().GetDouble()));
372 }
373 return compiler::Literal(lit->Number().GetDouble());
374 }
375 case ir::AstNodeType::STRING_LITERAL: {
376 auto *lit = expr->AsStringLiteral();
377 return compiler::Literal(lit->Str());
378 }
379 case ir::AstNodeType::BOOLEAN_LITERAL: {
380 auto *lit = expr->AsBooleanLiteral();
381 return compiler::Literal(lit->Value());
382 }
383 case ir::AstNodeType::NULL_LITERAL: {
384 return compiler::Literal::NullLiteral();
385 }
386 case ir::AstNodeType::UNDEFINED_LITERAL: {
387 return compiler::Literal::UndefinedLiteral();
388 }
389 default:
390 break;
391 }
392
393 return compiler::Literal();
394 }
395
IsBindingPattern(const ir::AstNode *node)396 bool Helpers::IsBindingPattern(const ir::AstNode *node)
397 {
398 return node->IsArrayPattern() || node->IsObjectPattern();
399 }
400
IsPattern(const ir::AstNode *node)401 bool Helpers::IsPattern(const ir::AstNode *node)
402 {
403 return node->IsArrayPattern() || node->IsObjectPattern() || node->IsAssignmentPattern();
404 }
405
CollectBindingName(ir::AstNode *node, std::vector<ir::Identifier *> *bindings)406 static void CollectBindingName(ir::AstNode *node, std::vector<ir::Identifier *> *bindings)
407 {
408 switch (node->Type()) {
409 case ir::AstNodeType::IDENTIFIER: {
410 if (!Helpers::IsGlobalIdentifier(node->AsIdentifier()->Name())) {
411 bindings->push_back(node->AsIdentifier());
412 }
413
414 break;
415 }
416 case ir::AstNodeType::OBJECT_PATTERN: {
417 for (auto *prop : node->AsObjectPattern()->Properties()) {
418 CollectBindingName(prop, bindings);
419 }
420 break;
421 }
422 case ir::AstNodeType::ARRAY_PATTERN: {
423 for (auto *element : node->AsArrayPattern()->Elements()) {
424 CollectBindingName(element, bindings);
425 }
426 break;
427 }
428 case ir::AstNodeType::ASSIGNMENT_PATTERN: {
429 CollectBindingName(node->AsAssignmentPattern()->Left(), bindings);
430 break;
431 }
432 case ir::AstNodeType::PROPERTY: {
433 CollectBindingName(node->AsProperty()->Value(), bindings);
434 break;
435 }
436 case ir::AstNodeType::REST_ELEMENT: {
437 CollectBindingName(node->AsRestElement()->Argument(), bindings);
438 break;
439 }
440 default:
441 break;
442 }
443 }
444
CollectBindingNames(ir::AstNode *node)445 std::vector<ir::Identifier *> Helpers::CollectBindingNames(ir::AstNode *node)
446 {
447 std::vector<ir::Identifier *> bindings;
448 CollectBindingName(node, &bindings);
449 return bindings;
450 }
451
CheckImportedName(const ArenaVector<ir::ImportSpecifier *> &specifiers, const ir::ImportSpecifier *specifier, const std::string &fileName)452 void Helpers::CheckImportedName(const ArenaVector<ir::ImportSpecifier *> &specifiers,
453 const ir::ImportSpecifier *specifier, const std::string &fileName)
454 {
455 auto newIdentName = specifier->Imported()->Name();
456 auto newAliasName = specifier->Local()->Name();
457 std::stringstream message {};
458
459 for (auto *it : specifiers) {
460 auto savedIdentName = it->Imported()->Name();
461 auto savedAliasName = it->Local()->Name();
462 if (savedIdentName == savedAliasName && savedAliasName == newIdentName) {
463 message << "Warning: '" << newIdentName << "' has already imported ";
464 break;
465 }
466 if (savedIdentName == newIdentName && newAliasName != savedAliasName) {
467 message << "Warning: '" << newIdentName << "' is explicitly used with alias several times ";
468 break;
469 }
470 }
471
472 if (message.rdbuf()->in_avail() > 0) {
473 std::cerr << message.str() << "[" << fileName.c_str() << ":" << specifier->Start().line << ":"
474 << specifier->Start().index << "]" << std::endl;
475 }
476 }
477
CheckDefaultImportedName(const ArenaVector<ir::ImportDefaultSpecifier *> &specifiers, const ir::ImportDefaultSpecifier *specifier, const std::string &fileName)478 void Helpers::CheckDefaultImportedName(const ArenaVector<ir::ImportDefaultSpecifier *> &specifiers,
479 const ir::ImportDefaultSpecifier *specifier, const std::string &fileName)
480 {
481 for (auto *it : specifiers) {
482 if (specifier->Local()->Name() != it->Local()->Name()) {
483 std::cerr << "Warning: default element is explicitly used with alias several times [" << fileName.c_str()
484 << ":" << specifier->Start().line << ":" << specifier->Start().index << "]" << std::endl;
485 return;
486 }
487 }
488 }
489
CheckDefaultImport(const ArenaVector<ir::ETSImportDeclaration *> &statements)490 void Helpers::CheckDefaultImport(const ArenaVector<ir::ETSImportDeclaration *> &statements)
491 {
492 for (auto statement : statements) {
493 for (auto specifier : statement->Specifiers()) {
494 if (specifier->Type() == ir::AstNodeType::IMPORT_DEFAULT_SPECIFIER) {
495 auto fileName = statement->ResolvedSource()->Str();
496 std::cerr << "Warning: default element has already imported [" << fileName << ":"
497 << specifier->Start().line << ":" << specifier->Start().index << "]" << std::endl;
498 return;
499 }
500 }
501 }
502 }
503
FunctionNameFromParent(const ir::AstNode *parent, ArenaAllocator *allocator)504 static util::StringView FunctionNameFromParent(const ir::AstNode *parent, ArenaAllocator *allocator)
505 {
506 switch (parent->Type()) {
507 case ir::AstNodeType::VARIABLE_DECLARATOR: {
508 const ir::VariableDeclarator *varDecl = parent->AsVariableDeclarator();
509
510 if (varDecl->Id()->IsIdentifier()) {
511 return varDecl->Id()->AsIdentifier()->Name();
512 }
513
514 break;
515 }
516 case ir::AstNodeType::METHOD_DEFINITION: {
517 const ir::MethodDefinition *methodDef = parent->AsMethodDefinition();
518
519 if (methodDef->Key()->IsIdentifier()) {
520 auto *ident = methodDef->Id();
521 ASSERT(ident != nullptr);
522
523 if (!ident->IsPrivateIdent()) {
524 return ident->Name();
525 }
526
527 return util::UString(varbinder::PrivateBinding::ToPrivateBinding(ident->Name()), allocator).View();
528 }
529
530 break;
531 }
532 case ir::AstNodeType::ASSIGNMENT_EXPRESSION: {
533 const ir::AssignmentExpression *assignment = parent->AsAssignmentExpression();
534
535 if (assignment->Left()->IsIdentifier()) {
536 return assignment->Left()->AsIdentifier()->Name();
537 }
538
539 break;
540 }
541 case ir::AstNodeType::ASSIGNMENT_PATTERN: {
542 const ir::AssignmentExpression *assignment = parent->AsAssignmentPattern();
543
544 if (assignment->Left()->IsIdentifier()) {
545 return assignment->Left()->AsIdentifier()->Name();
546 }
547
548 break;
549 }
550 case ir::AstNodeType::PROPERTY: {
551 const ir::Property *prop = parent->AsProperty();
552
553 if (prop->Kind() != ir::PropertyKind::PROTO &&
554 Helpers::IsConstantPropertyKey(prop->Key(), prop->IsComputed())) {
555 return Helpers::LiteralToPropName(prop->Key());
556 }
557
558 break;
559 }
560 default:
561 break;
562 }
563
564 return util::StringView();
565 }
566
FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func)567 util::StringView Helpers::FunctionName(ArenaAllocator *allocator, const ir::ScriptFunction *func)
568 {
569 if (func->Id() != nullptr) {
570 return func->Id()->Name();
571 }
572
573 if (func->Parent()->IsFunctionDeclaration()) {
574 return "*default*";
575 }
576
577 const ir::AstNode *parent = func->Parent()->Parent();
578
579 if (func->IsConstructor()) {
580 parent = parent->Parent();
581 if (parent->AsClassDefinition()->Ident() != nullptr) {
582 return parent->AsClassDefinition()->Ident()->Name();
583 }
584
585 parent = parent->Parent()->Parent();
586 }
587
588 return FunctionNameFromParent(parent, allocator);
589 }
590
ParamName(ArenaAllocator *allocator, const ir::AstNode *param, uint32_t index)591 std::tuple<util::StringView, bool> Helpers::ParamName(ArenaAllocator *allocator, const ir::AstNode *param,
592 uint32_t index)
593 {
594 switch (param->Type()) {
595 case ir::AstNodeType::IDENTIFIER: {
596 return {param->AsIdentifier()->Name(), false};
597 }
598 case ir::AstNodeType::ASSIGNMENT_PATTERN: {
599 const auto *lhs = param->AsAssignmentPattern()->Left();
600 if (lhs->IsIdentifier()) {
601 return {param->AsAssignmentPattern()->Left()->AsIdentifier()->Name(), false};
602 }
603 break;
604 }
605 case ir::AstNodeType::REST_ELEMENT: {
606 if (param->AsRestElement()->Argument()->IsIdentifier()) {
607 return {param->AsRestElement()->Argument()->AsIdentifier()->Name(), false};
608 }
609 break;
610 }
611 case ir::AstNodeType::TS_PARAMETER_PROPERTY: {
612 return ParamName(allocator, param->AsTSParameterProperty()->Parameter(), index);
613 }
614 case ir::AstNodeType::ETS_PARAMETER_EXPRESSION: {
615 return {param->AsETSParameterExpression()->Ident()->Name(), false};
616 }
617 default:
618 break;
619 }
620
621 return {Helpers::ToStringView(allocator, index), true};
622 }
623
GetEscapedCharacter(const unsigned char c)624 static std::string GetEscapedCharacter(const unsigned char c)
625 {
626 std::stringstream escapedStr;
627 escapedStr << '\\';
628 switch (c) {
629 case lexer::LEX_CHAR_DOUBLE_QUOTE: {
630 escapedStr << '"';
631 break;
632 }
633 case lexer::LEX_CHAR_BS: {
634 escapedStr << 'b';
635 break;
636 }
637 case lexer::LEX_CHAR_TAB: {
638 escapedStr << 't';
639 break;
640 }
641 case lexer::LEX_CHAR_LF: {
642 escapedStr << 'n';
643 break;
644 }
645 case lexer::LEX_CHAR_VT: {
646 escapedStr << 'v';
647 break;
648 }
649 case lexer::LEX_CHAR_FF: {
650 escapedStr << 'f';
651 break;
652 }
653 case lexer::LEX_CHAR_CR: {
654 escapedStr << 'r';
655 break;
656 }
657 case lexer::LEX_CHAR_NULL: {
658 escapedStr << '0';
659 break;
660 }
661 default: {
662 escapedStr << 'u' << std::hex << std::setw(4U) << std::setfill('0') << static_cast<unsigned int>(c);
663 break;
664 }
665 }
666 return escapedStr.str();
667 }
668
CreateEscapedString(const std::string &str)669 std::string Helpers::CreateEscapedString(const std::string &str)
670 {
671 std::string escapedStr;
672 for (const unsigned char c : str) {
673 // check if a given character is printable
674 // the cast is necessary to avoid undefined behaviour
675 if (LIKELY((std::isprint(c) != 0U || c >= lexer::LEX_ASCII_MAX_BITS) && c != lexer::LEX_CHAR_DOUBLE_QUOTE)) {
676 escapedStr += c;
677 } else {
678 escapedStr += GetEscapedCharacter(c);
679 }
680 }
681 return escapedStr;
682 }
683
UTF16toUTF8(const char16_t c)684 std::string Helpers::UTF16toUTF8(const char16_t c)
685 {
686 const utf::Utf8Char utf8Ch = utf::ConvertUtf16ToUtf8(c, 0, false);
687 return std::string(reinterpret_cast<const char *>(utf8Ch.ch.data()), utf8Ch.n);
688 }
689
SplitSignature(std::string_view signature)690 std::pair<std::string_view, std::string_view> Helpers::SplitSignature(std::string_view signature)
691 {
692 auto idx = signature.find_last_of(':');
693 auto stripped = signature.substr(0, idx);
694 idx = stripped.find_last_of('.');
695 auto fullClassName = stripped.substr(0, idx);
696 auto methodName = stripped.substr(idx + 1);
697 idx = fullClassName.find_last_of('.');
698 auto className = fullClassName.substr(idx + 1);
699 return {className, methodName};
700 }
701
StdLib()702 std::vector<std::string> &Helpers::StdLib()
703 {
704 static std::vector<std::string> stdlib {"std/core", "std/math", "std/containers", "std/time",
705 "std/interop/js", "std/debug", "std/debug/concurrency", "std/testing",
706 "escompat"};
707 return stdlib;
708 }
709
IsStdLib(const parser::Program *program)710 bool Helpers::IsStdLib(const parser::Program *program)
711 {
712 auto stdlib = StdLib();
713
714 // NOTE(rsipka): early check: if program is not a package module then it is not part of the stdlib either
715 if (!program->IsPackageModule()) {
716 return false;
717 }
718
719 stdlib.emplace_back("std/math/consts");
720
721 auto fileFolder = program->ModuleName().Mutf8();
722 std::replace(fileFolder.begin(), fileFolder.end(), *compiler::Signatures::METHOD_SEPARATOR.begin(),
723 *compiler::Signatures::NAMESPACE_SEPARATOR.begin());
724 return std::count(stdlib.begin(), stdlib.end(), fileFolder) != 0;
725 }
726
727 } // namespace ark::es2panda::util
728