• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2022-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 "options.h"
17 
18 #include "os/filesystem.h"
19 #include "utils/pandargs.h"
20 
21 #include "arktsconfig.h"
22 
23 #include <random>
24 #include <utility>
25 
26 #ifdef PANDA_WITH_BYTECODE_OPTIMIZER
27 #include "bytecode_optimizer/bytecodeopt_options.h"
28 #include "compiler/compiler_options.h"
29 #endif
30 
31 namespace ark::es2panda::util {
32 template <class T>
RemoveExtension(T const & filename)33 T RemoveExtension(T const &filename)
34 {
35     typename T::size_type const p(filename.find_last_of('.'));
36     return p > 0 && p != T::npos ? filename.substr(0, p) : filename;
37 }
38 
39 // Options
40 
Options()41 Options::Options() : argparser_(new ark::PandArgParser()) {}
42 
~Options()43 Options::~Options()
44 {
45     delete argparser_;
46 }
47 
SplitToStringVector(std::string const & str)48 static std::vector<std::string> SplitToStringVector(std::string const &str)
49 {
50     std::vector<std::string> res;
51     std::string_view currStr {str};
52     auto ix = currStr.find(',');
53     while (ix != std::string::npos) {
54         if (ix != 0) {
55             res.emplace_back(currStr.substr(0, ix));
56         }
57         currStr = currStr.substr(ix + 1);
58         ix = currStr.find(',');
59     }
60 
61     if (!currStr.empty()) {
62         res.emplace_back(currStr);
63     }
64     return res;
65 }
66 
SplitToStringSet(std::string const & str)67 static std::unordered_set<std::string> SplitToStringSet(std::string const &str)
68 {
69     std::vector<std::string> vec = SplitToStringVector(str);
70     std::unordered_set<std::string> res;
71     for (auto &elem : vec) {
72         res.emplace(elem);
73     }
74     return res;
75 }
76 
77 // NOLINTNEXTLINE(modernize-avoid-c-arrays, hicpp-avoid-c-arrays)
SplitArgs(int argc,const char * argv[],std::vector<std::string> & es2pandaArgs,std::vector<std::string> & bcoCompilerArgs,std::vector<std::string> & bytecodeoptArgs)78 static void SplitArgs(int argc, const char *argv[], std::vector<std::string> &es2pandaArgs,
79                       std::vector<std::string> &bcoCompilerArgs, std::vector<std::string> &bytecodeoptArgs)
80 {
81     constexpr std::string_view COMPILER_PREFIX = "--bco-compiler";
82     constexpr std::string_view OPTIMIZER_PREFIX = "--bco-optimizer";
83 
84     enum class OptState { ES2PANDA, JIT_COMPILER, OPTIMIZER };
85     OptState optState = OptState::ES2PANDA;
86 
87     std::unordered_map<OptState, std::vector<std::string> *> argsMap = {{OptState::ES2PANDA, &es2pandaArgs},
88                                                                         {OptState::JIT_COMPILER, &bcoCompilerArgs},
89                                                                         {OptState::OPTIMIZER, &bytecodeoptArgs}};
90 
91     for (int i = 1; i < argc; i++) {
92         // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
93         const char *argI = argv[i];
94         if (COMPILER_PREFIX == argI) {
95             optState = OptState::JIT_COMPILER;
96             continue;
97         }
98 
99         if (OPTIMIZER_PREFIX == argI) {
100             optState = OptState::OPTIMIZER;
101             continue;
102         }
103 
104         argsMap[optState]->emplace_back(argI);
105         optState = OptState::ES2PANDA;
106     }
107 }
108 
109 template <class T>
ParseComponentArgs(const std::vector<std::string> & args,T & options)110 static bool ParseComponentArgs(const std::vector<std::string> &args, T &options)
111 {
112     ark::PandArgParser parser;
113     options.AddOptions(&parser);
114     if (!parser.Parse(args)) {
115         std::cerr << parser.GetErrorString();
116         std::cerr << parser.GetHelpString();
117         return false;
118     }
119 
120     if (auto optionsErr = options.Validate(); optionsErr) {
121         std::cerr << "Error: " << optionsErr.value().GetMessage() << std::endl;
122         return false;
123     }
124 
125     return true;
126 }
127 
ParseBCOCompilerOptions(const std::vector<std::string> & compilerArgs,const std::vector<std::string> & bytecodeoptArgs)128 static bool ParseBCOCompilerOptions([[maybe_unused]] const std::vector<std::string> &compilerArgs,
129                                     [[maybe_unused]] const std::vector<std::string> &bytecodeoptArgs)
130 {
131 #ifdef PANDA_WITH_BYTECODE_OPTIMIZER
132     if (!ParseComponentArgs(compilerArgs, ark::compiler::g_options)) {
133         return false;
134     }
135     if (!ParseComponentArgs(bytecodeoptArgs, ark::bytecodeopt::g_options)) {
136         return false;
137     }
138 #endif
139 
140     return true;
141 }
142 
ETSWarningsGroupSetter(const ark::PandArg<bool> & option)143 static inline bool ETSWarningsGroupSetter(const ark::PandArg<bool> &option)
144 {
145     return !option.WasSet() || (option.WasSet() && option.GetValue());
146 }
147 
SplitPath(std::string_view path)148 static std::tuple<std::string_view, std::string_view, std::string_view> SplitPath(std::string_view path)
149 {
150     std::string_view fileDirectory;
151     std::string_view fileBaseName = path;
152     auto lastDelimPos = fileBaseName.find_last_of(ark::os::file::File::GetPathDelim());
153     if (lastDelimPos != std::string_view::npos) {
154         ++lastDelimPos;
155         fileDirectory = fileBaseName.substr(0, lastDelimPos);
156         fileBaseName = fileBaseName.substr(lastDelimPos);
157     }
158 
159     // Save all extensions.
160     std::string_view fileExtensions;
161     auto fileBaseNamePos = fileBaseName.find_first_of('.');
162     if (fileBaseNamePos > 0 && fileBaseNamePos != std::string_view::npos) {
163         fileExtensions = fileBaseName.substr(fileBaseNamePos);
164         fileBaseName = fileBaseName.substr(0, fileBaseNamePos);
165     }
166 
167     return {fileDirectory, fileBaseName, fileExtensions};
168 }
169 
170 /**
171  * @brief Generate evaluated expression wrapping code.
172  * @param sourceFilePath used for generating a unique package name.
173  * @param input expression source code file stream.
174  * @param output stream for generating expression wrapper.
175  */
GenerateEvaluationWrapper(std::string_view sourceFilePath,std::ifstream & input,std::stringstream & output)176 static void GenerateEvaluationWrapper(std::string_view sourceFilePath, std::ifstream &input, std::stringstream &output)
177 {
178     static constexpr std::string_view EVAL_PREFIX = "eval_";
179     static constexpr std::string_view EVAL_SUFFIX = "_eval";
180 
181     auto splittedPath = SplitPath(sourceFilePath);
182     auto fileBaseName = std::get<1>(splittedPath);
183 
184     std::random_device rd;
185     std::stringstream ss;
186     ss << EVAL_PREFIX << fileBaseName << '_' << rd() << EVAL_SUFFIX;
187     auto methodName = ss.str();
188 
189     output << "package " << methodName << "; class " << methodName << " { private static " << methodName << "() { "
190            << input.rdbuf() << " } }";
191 }
192 
193 static auto constexpr DEFAULT_THREAD_COUNT = 0;
194 
195 struct AllArgs {
196     // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
197     ark::PandArg<bool> opHelp {"help", false, "Print this message and exit"};
198     ark::PandArg<bool> opVersion {"version", false, "Print message with version and exit"};
199 
200     // parser
201     ark::PandArg<std::string> inputExtension {"extension", "",
202                                               "Parse the input as the given extension (options: js | ts | as | sts)"};
203     ark::PandArg<bool> opModule {"module", false, "Parse the input as module (JS only option)"};
204     ark::PandArg<bool> opParseOnly {"parse-only", false, "Parse the input only"};
205     ark::PandArg<bool> opDumpAst {"dump-ast", false, "Dump the parsed AST"};
206     ark::PandArg<bool> opDumpAstOnlySilent {"dump-ast-only-silent", false,
207                                             "Dump parsed AST with all dumpers available but don't print to stdout"};
208     ark::PandArg<bool> opDumpCheckedAst {"dump-dynamic-ast", false,
209                                          "Dump AST with synthetic nodes for dynamic languages"};
210     ark::PandArg<bool> opListFiles {"list-files", false, "Print names of files that are part of compilation"};
211 
212     // compiler
213     ark::PandArg<bool> opDumpAssembly {"dump-assembly", false, "Dump pandasm"};
214     ark::PandArg<bool> opDebugInfo {"debug-info", false, "Compile with debug info"};
215     ark::PandArg<bool> opDumpDebugInfo {"dump-debug-info", false, "Dump debug info"};
216     ark::PandArg<int> opOptLevel {"opt-level", 0, "Compiler optimization level (options: 0 | 1 | 2)", 0, MAX_OPT_LEVEL};
217     ark::PandArg<bool> opEtsModule {"ets-module", false, "Compile the input as ets-module"};
218 
219     // ETS-warnings
220     ark::PandArg<bool> opEtsEnableAll {"ets-warnings-all", false, "Show performance-related ets-warnings"};
221     ark::PandArg<bool> opEtsWerror {"ets-werror", false, "Treat all enabled performance-related ets-warnings as error"};
222     ark::PandArg<bool> opEtsSubsetWarnings {"ets-subset-warnings", false, "Show ETS-warnings that keep you in subset"};
223     ark::PandArg<bool> opEtsNonsubsetWarnings {"ets-nonsubset-warnings", false,
224                                                "Show ETS-warnings that do not keep you in subset"};
225     ark::PandArg<bool> opEtsSuggestFinal {"ets-suggest-final", false,
226                                           "Suggest final keyword warning - ETS non-subset warning"};
227     ark::PandArg<bool> opEtsProhibitTopLevelStatements {"ets-prohibit-top-level-statements", false,
228                                                         "Prohibit top-level statements - ETS subset Warning"};
229     ark::PandArg<bool> opEtsBoostEqualityStatement {"ets-boost-equality-statement", false,
230                                                     "Suggest boosting Equality Statements - ETS Subset Warning"};
231     ark::PandArg<bool> opEtsRemoveAsync {
232         "ets-remove-async", false, "Suggests replacing async functions with coroutines - ETS Non Subset Warnings"};
233     ark::PandArg<bool> opEtsRemoveLambda {"ets-remove-lambda", false,
234                                           "Suggestions to replace lambda with regular functions - ETS Subset Warning"};
235     ark::PandArg<bool> opEtsImplicitBoxingUnboxing {
236         "ets-implicit-boxing-unboxing", false,
237         "Check if a program contains implicit boxing or unboxing - ETS Subset Warning"};
238 
239     ark::PandArg<bool> opDebuggerEvalMode {"debugger-eval-mode", false, "Compile given file in evaluation mode"};
240     ark::PandArg<uint64_t> opDebuggerEvalLine {
241         "debugger-eval-line", 0, "Debugger evaluation mode, line in the source file code where evaluate occurs."};
242     ark::PandArg<std::string> opDebuggerEvalSource {"debugger-eval-source", "",
243                                                     "Debugger evaluation mode, path to evaluation mode source file"};
244     ark::PandArg<std::string> opDebuggerEvalPandaFiles {
245         "debugger-eval-panda-files", "",
246         "Debugger evaluation mode, paths to evaluation mode (.abc) files, must be accessible"};
247 
248     ark::PandArg<int> opThreadCount {"thread", DEFAULT_THREAD_COUNT, "Number of worker threads"};
249     ark::PandArg<bool> opSizeStat {"dump-size-stat", false, "Dump size statistics"};
250     ark::PandArg<std::string> outputFile {"output", "", "Compiler binary output (.abc)"};
251     ark::PandArg<std::string> logLevel {"log-level", "error", "Log-level"};
252     ark::PandArg<std::string> stdLib {"stdlib", "", "Path to standard library"};
253     ark::PandArg<bool> genStdLib {"gen-stdlib", false, "Gen standard library"};
254     ark::PandArg<std::string> plugins {"plugins", "", "Plugins"};
255     ark::PandArg<std::string> skipPhases {"skip-phases", "", "Phases to skip"};
256     ark::PandArg<std::string> verifierWarnings {
257         "verifier-warnings", "CheckInfiniteLoopForAll",
258         "Print errors and continue compilation if AST tree is incorrect. "
259         "Possible values: "
260         "NodeHasParentForAll,EveryChildHasValidParentForAll,VariableHasScopeForAll,NodeHasTypeForAll,"
261         "IdentifierHasVariableForAll,ArithmeticOperationValidForAll,SequenceExpressionHasLastTypeForAll, "
262         "CheckInfiniteLoopForAll,"
263         "ForLoopCorrectlyInitializedForAll,VariableHasEnclosingScopeForAll,ModifierAccessValidForAll,"
264         "ImportExportAccessValid,NodeHasSourceRangeForAll,EveryChildInParentRangeForAll,"
265         "ReferenceTypeAnnotationIsNullForAll,VariableNameIdentifierNameSameForAll,CheckAbstractMethodForAll,"
266         "GetterSetterValidationForAll,CheckScopeDeclarationForAll,CheckConstPropertiesForAll"};
267     ark::PandArg<std::string> verifierErrors {
268         "verifier-errors",
269         "ForLoopCorrectlyInitializedForAll,SequenceExpressionHasLastTypeForAll,NodeHasTypeForAll,NodeHasParentForAll,"
270         "EveryChildHasValidParentForAll,ModifierAccessValidForAll,ArithmeticOperationValidForAll,"
271         "VariableHasScopeForAll,IdentifierHasVariableForAll,VariableHasEnclosingScopeForAll,"
272         "ReferenceTypeAnnotationIsNullForAll,VariableNameIdentifierNameSameForAll,CheckAbstractMethodForAll,"
273         "GetterSetterValidationForAll,CheckScopeDeclarationForAll,CheckConstPropertiesForAll",
274         "Print errors and stop compilation if AST tree is incorrect. "
275         "Possible values: "
276         "NodeHasParentForAll,EveryChildHasValidParentForAll,VariableHasScopeForAll,NodeHasTypeForAll,"
277         "IdentifierHasVariableForAll,ArithmeticOperationValidForAll,SequenceExpressionHasLastTypeForAll,"
278         "CheckInfiniteLoopForAll,"
279         "ForLoopCorrectlyInitializedForAll,VariableHasEnclosingScopeForAll,ModifierAccessValidForAll,"
280         "ImportExportAccessValid,NodeHasSourceRangeForAll,EveryChildInParentRangeForAll,"
281         "ReferenceTypeAnnotationIsNullForAll,VariableNameIdentifierNameSameForAll,CheckAbstractMethodForAll,"
282         "GetterSetterValidationForAll,CheckScopeDeclarationForAll,CheckConstPropertiesForAll"};
283     ark::PandArg<bool> verifierAllChecks {
284         "verifier-all-checks", false,
285         "Run verifier checks on every phase, monotonically expanding them on every phase"};
286     ark::PandArg<bool> verifierFullProgram {"verifier-full-program", false,
287                                             "Analyze full program, including program AST and it's dependencies"};
288     ark::PandArg<std::string> dumpBeforePhases {"dump-before-phases", "",
289                                                 "Generate program dump before running phases in the list"};
290     ark::PandArg<std::string> dumpEtsSrcBeforePhases {
291         "dump-ets-src-before-phases", "", "Generate program dump as ets source code before running phases in the list"};
292     ark::PandArg<std::string> dumpEtsSrcAfterPhases {
293         "dump-ets-src-after-phases", "", "Generate program dump as ets source code after running phases in the list"};
294     ark::PandArg<std::string> exitBeforePhase {"exit-before-phase", "",
295                                                "Exit compilation before running the provided phase"};
296     ark::PandArg<std::string> exitAfterPhase {"exit-after-phase", "",
297                                               "Exit compilation after running the provided phase"};
298     ark::PandArg<std::string> dumpAfterPhases {"dump-after-phases", "",
299                                                "Generate program dump after running phases in the list"};
300     ark::PandArg<bool> opListPhases {"list-phases", false, "Dump list of available phases"};
301 
302     // tail arguments
303     ark::PandArg<std::string> inputFile {"input", "", "input file"};
304 
305     ark::PandArg<std::string> arktsConfig;
306     // NOLINTEND(misc-non-private-member-variables-in-classes)
307 
AllArgsark::es2panda::util::AllArgs308     explicit AllArgs(const char *argv0)
309         : arktsConfig {"arktsconfig", ark::es2panda::JoinPaths(ark::es2panda::ParentPath(argv0), "arktsconfig.json"),
310                        "Path to arkts configuration file"}
311     {
312     }
313 
ParseInputOutputark::es2panda::util::AllArgs314     bool ParseInputOutput(CompilationMode compilationMode, std::string &errorMsg, std::string &sourceFile,
315                           std::string &parserInput, std::string &compilerOutput) const
316     {
317         auto isDebuggerEvalMode = opDebuggerEvalMode.GetValue();
318         if (isDebuggerEvalMode && compilationMode != CompilationMode::SINGLE_FILE) {
319             errorMsg = "Error: When compiling with --debugger-eval-mode single input file must be provided";
320             return false;
321         }
322 
323         sourceFile = inputFile.GetValue();
324         if (compilationMode == CompilationMode::SINGLE_FILE) {
325             sourceFile = os::GetAbsolutePath(inputFile.GetValue());
326             std::ifstream inputStream(sourceFile.c_str());
327             if (inputStream.fail()) {
328                 errorMsg = "Failed to open file: ";
329                 errorMsg.append(sourceFile);
330                 return false;
331             }
332 
333             std::stringstream ss;
334             if (isDebuggerEvalMode) {
335                 GenerateEvaluationWrapper(sourceFile, inputStream, ss);
336             } else {
337                 ss << inputStream.rdbuf();
338             }
339             parserInput = ss.str();
340         }
341 
342         if (!outputFile.GetValue().empty()) {
343             if (compilationMode == CompilationMode::PROJECT) {
344                 errorMsg = "Error: When compiling in project mode --output key is not needed";
345                 return false;
346             }
347             compilerOutput = outputFile.GetValue();
348         } else {
349             compilerOutput = RemoveExtension(BaseName(sourceFile)).append(".abc");
350         }
351 
352         return true;
353     }
354 
BindArgsark::es2panda::util::AllArgs355     void BindArgs(ark::PandArgParser &argparser)
356     {
357         argparser.Add(&opHelp);
358         argparser.Add(&opVersion);
359         argparser.Add(&opModule);
360         argparser.Add(&opDumpAst);
361         argparser.Add(&opDumpAstOnlySilent);
362         argparser.Add(&opDumpCheckedAst);
363         argparser.Add(&opParseOnly);
364         argparser.Add(&opDumpAssembly);
365         argparser.Add(&opDebugInfo);
366         argparser.Add(&opDumpDebugInfo);
367 
368         argparser.Add(&opOptLevel);
369         argparser.Add(&opEtsModule);
370         argparser.Add(&opThreadCount);
371         argparser.Add(&opSizeStat);
372         argparser.Add(&opListFiles);
373 
374         argparser.Add(&inputExtension);
375         argparser.Add(&outputFile);
376         argparser.Add(&logLevel);
377         argparser.Add(&stdLib);
378         argparser.Add(&genStdLib);
379         argparser.Add(&plugins);
380         argparser.Add(&skipPhases);
381         argparser.Add(&verifierAllChecks);
382         argparser.Add(&verifierFullProgram);
383         argparser.Add(&verifierWarnings);
384         argparser.Add(&verifierErrors);
385         argparser.Add(&dumpBeforePhases);
386         argparser.Add(&dumpEtsSrcBeforePhases);
387         argparser.Add(&exitBeforePhase);
388         argparser.Add(&dumpAfterPhases);
389         argparser.Add(&dumpEtsSrcAfterPhases);
390         argparser.Add(&exitAfterPhase);
391         argparser.Add(&opListPhases);
392         argparser.Add(&arktsConfig);
393 
394         argparser.Add(&opEtsEnableAll);
395         argparser.Add(&opEtsWerror);
396         argparser.Add(&opEtsSubsetWarnings);
397         argparser.Add(&opEtsNonsubsetWarnings);
398 
399         // ETS-subset warnings
400         argparser.Add(&opEtsProhibitTopLevelStatements);
401         argparser.Add(&opEtsBoostEqualityStatement);
402         argparser.Add(&opEtsRemoveLambda);
403         argparser.Add(&opEtsImplicitBoxingUnboxing);
404 
405         // ETS-non-subset warnings
406         argparser.Add(&opEtsSuggestFinal);
407         argparser.Add(&opEtsRemoveAsync);
408 
409         AddDebuggerEvaluationOptions(argparser);
410 
411         argparser.PushBackTail(&inputFile);
412         argparser.EnableTail();
413         argparser.EnableRemainder();
414     }
415 
InitCompilerOptionsark::es2panda::util::AllArgs416     void InitCompilerOptions(es2panda::CompilerOptions &compilerOptions, CompilationMode compilationMode) const
417     {
418         compilerOptions.dumpAsm = opDumpAssembly.GetValue();
419         compilerOptions.dumpAst = opDumpAst.GetValue();
420         compilerOptions.opDumpAstOnlySilent = opDumpAstOnlySilent.GetValue();
421         compilerOptions.dumpCheckedAst = opDumpCheckedAst.GetValue();
422         compilerOptions.dumpDebugInfo = opDumpDebugInfo.GetValue();
423         compilerOptions.isDebug = opDebugInfo.GetValue();
424         compilerOptions.parseOnly = opParseOnly.GetValue();
425         compilerOptions.stdLib = stdLib.GetValue();
426         compilerOptions.isEtsModule = opEtsModule.GetValue();
427         compilerOptions.plugins = SplitToStringVector(plugins.GetValue());
428         compilerOptions.skipPhases = SplitToStringSet(skipPhases.GetValue());
429         compilerOptions.verifierFullProgram = verifierFullProgram.GetValue();
430         compilerOptions.verifierAllChecks = verifierAllChecks.GetValue();
431         compilerOptions.verifierWarnings = SplitToStringSet(verifierWarnings.GetValue());
432         compilerOptions.verifierErrors = SplitToStringSet(verifierErrors.GetValue());
433         compilerOptions.dumpBeforePhases = SplitToStringSet(dumpBeforePhases.GetValue());
434         compilerOptions.dumpEtsSrcBeforePhases = SplitToStringSet(dumpEtsSrcBeforePhases.GetValue());
435         compilerOptions.exitBeforePhase = exitBeforePhase.GetValue();
436         compilerOptions.dumpAfterPhases = SplitToStringSet(dumpAfterPhases.GetValue());
437         compilerOptions.dumpEtsSrcAfterPhases = SplitToStringSet(dumpEtsSrcAfterPhases.GetValue());
438         compilerOptions.exitAfterPhase = exitAfterPhase.GetValue();
439 
440         // ETS-Warnings
441         compilerOptions.etsSubsetWarnings = opEtsSubsetWarnings.GetValue();
442         compilerOptions.etsWerror = opEtsWerror.GetValue();
443         compilerOptions.etsNonsubsetWarnings = opEtsNonsubsetWarnings.GetValue();
444         compilerOptions.etsEnableAll = opEtsEnableAll.GetValue();
445 
446         if (compilerOptions.etsEnableAll || compilerOptions.etsSubsetWarnings) {
447             // Adding subset warnings
448             compilerOptions.etsProhibitTopLevelStatements = ETSWarningsGroupSetter(opEtsProhibitTopLevelStatements);
449             compilerOptions.etsBoostEqualityStatement = ETSWarningsGroupSetter(opEtsBoostEqualityStatement);
450             compilerOptions.etsRemoveLambda = ETSWarningsGroupSetter(opEtsRemoveLambda);
451             compilerOptions.etsImplicitBoxingUnboxing = ETSWarningsGroupSetter(opEtsImplicitBoxingUnboxing);
452         }
453 
454         if (compilerOptions.etsEnableAll || compilerOptions.etsNonsubsetWarnings) {
455             // Adding non-subset warnings
456             compilerOptions.etsSuggestFinal = ETSWarningsGroupSetter(opEtsSuggestFinal);
457             compilerOptions.etsRemoveAsync = ETSWarningsGroupSetter(opEtsRemoveAsync);
458         }
459 
460         if (!compilerOptions.etsEnableAll && !compilerOptions.etsSubsetWarnings &&
461             !compilerOptions.etsNonsubsetWarnings) {
462             // If no warnings groups enabled - check all if enabled
463             compilerOptions.etsSuggestFinal = opEtsSuggestFinal.GetValue();
464             compilerOptions.etsProhibitTopLevelStatements = opEtsProhibitTopLevelStatements.GetValue();
465             compilerOptions.etsBoostEqualityStatement = opEtsBoostEqualityStatement.GetValue();
466             compilerOptions.etsRemoveAsync = opEtsRemoveAsync.GetValue();
467             compilerOptions.etsRemoveLambda = opEtsRemoveLambda.GetValue();
468             compilerOptions.etsImplicitBoxingUnboxing = opEtsImplicitBoxingUnboxing.GetValue();
469         }
470 
471         InitDebuggerEvaluationCompilerOptions(compilerOptions);
472 
473         // Pushing enabled warnings to warning collection
474         PushingEnabledWarnings(compilerOptions);
475 
476         compilerOptions.compilationMode = compilationMode;
477     }
478 
479 private:
PushingEnabledWarningsark::es2panda::util::AllArgs480     static void PushingEnabledWarnings(es2panda::CompilerOptions &compilerOptions)
481     {
482         if (compilerOptions.etsSuggestFinal) {
483             compilerOptions.etsWarningCollection.push_back(ETSWarnings::SUGGEST_FINAL);
484         }
485         if (compilerOptions.etsProhibitTopLevelStatements) {
486             compilerOptions.etsWarningCollection.push_back(ETSWarnings::PROHIBIT_TOP_LEVEL_STATEMENTS);
487         }
488         if (compilerOptions.etsBoostEqualityStatement) {
489             compilerOptions.etsWarningCollection.push_back(ETSWarnings::BOOST_EQUALITY_STATEMENT);
490         }
491         if (compilerOptions.etsRemoveAsync) {
492             compilerOptions.etsWarningCollection.push_back(ETSWarnings::REMOVE_ASYNC_FUNCTIONS);
493         }
494         if (compilerOptions.etsRemoveLambda) {
495             compilerOptions.etsWarningCollection.push_back(ETSWarnings::REMOVE_LAMBDA);
496         }
497         if (compilerOptions.etsImplicitBoxingUnboxing) {
498             compilerOptions.etsWarningCollection.push_back(ETSWarnings::IMPLICIT_BOXING_UNBOXING);
499         }
500         if (!compilerOptions.etsWarningCollection.empty()) {
501             compilerOptions.etsHasWarnings = true;
502         }
503     }
504 
AddDebuggerEvaluationOptionsark::es2panda::util::AllArgs505     void AddDebuggerEvaluationOptions(ark::PandArgParser &argparser)
506     {
507         argparser.Add(&opDebuggerEvalMode);
508         argparser.Add(&opDebuggerEvalLine);
509         argparser.Add(&opDebuggerEvalSource);
510         argparser.Add(&opDebuggerEvalPandaFiles);
511     }
512 
InitDebuggerEvaluationCompilerOptionsark::es2panda::util::AllArgs513     void InitDebuggerEvaluationCompilerOptions(es2panda::CompilerOptions &compilerOptions) const
514     {
515         compilerOptions.debuggerEvalMode = opDebuggerEvalMode.GetValue();
516         if (compilerOptions.debuggerEvalMode) {
517             compilerOptions.debuggerEvalLine = opDebuggerEvalLine.GetValue();
518             compilerOptions.debuggerEvalSource = opDebuggerEvalSource.GetValue();
519             compilerOptions.debuggerEvalPandaFiles = SplitToStringVector(opDebuggerEvalPandaFiles.GetValue());
520         }
521     }
522 };
523 
Usage(const ark::PandArgParser & argparser)524 static std::string Usage(const ark::PandArgParser &argparser)
525 {
526     std::stringstream ss;
527 
528     ss << argparser.GetErrorString() << std::endl;
529     ss << "Usage: "
530        << "es2panda"
531        << " [OPTIONS] [input file] -- [arguments]" << std::endl;
532     ss << std::endl;
533     ss << "optional arguments:" << std::endl;
534     ss << argparser.GetHelpString() << std::endl;
535 
536     ss << std::endl;
537     ss << "--bco-optimizer: Argument directly to bytecode optimizer can be passed after this prefix" << std::endl;
538     ss << "--bco-compiler: Argument directly to jit-compiler inside bytecode optimizer can be passed after this "
539           "prefix"
540        << std::endl;
541 
542     return ss.str();
543 }
544 
GetVersion()545 static std::string GetVersion()
546 {
547     std::stringstream ss;
548 
549     ss << std::endl;
550     ss << "  Es2panda Version " << ES2PANDA_VERSION << std::endl;
551 
552 // add check for PANDA_PRODUCT_BUILD after normal version tracking will be implemented
553 #ifdef ES2PANDA_DATE
554     ss << std::endl;
555     ss << "  Build date: ";
556     ss << ES2PANDA_DATE;
557 #endif  // ES2PANDA_DATE
558 #ifdef ES2PANDA_HASH
559     ss << std::endl;
560     ss << "  Last commit hash: ";
561     ss << ES2PANDA_HASH;
562     ss << std::endl;
563 #endif  // ES2PANDA_HASH
564 
565     return ss.str();
566 }
567 
Parse(int argc,const char ** argv)568 bool Options::Parse(int argc, const char **argv)
569 {
570     std::vector<std::string> es2pandaArgs;
571     std::vector<std::string> bcoCompilerArgs;
572     std::vector<std::string> bytecodeoptArgs;
573 
574     SplitArgs(argc, argv, es2pandaArgs, bcoCompilerArgs, bytecodeoptArgs);
575     if (!ParseBCOCompilerOptions(bcoCompilerArgs, bytecodeoptArgs)) {
576         return false;
577     }
578 
579     AllArgs allArgs(argv[0]);  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
580 
581     allArgs.BindArgs(*argparser_);
582     if (!argparser_->Parse(es2pandaArgs) || allArgs.opHelp.GetValue()) {
583         errorMsg_ = Usage(*argparser_);
584         return false;
585     }
586 
587     if (allArgs.opVersion.GetValue()) {
588         errorMsg_ = GetVersion();
589         return false;
590     }
591 
592     // Determine compilation mode
593     auto compilationMode = DetermineCompilationMode(allArgs.genStdLib, allArgs.inputFile);
594     if (!allArgs.ParseInputOutput(compilationMode, errorMsg_, sourceFile_, parserInput_, compilerOutput_)) {
595         return false;
596     }
597 
598     // Determine Extension
599     DetermineExtension(allArgs.inputExtension, allArgs.arktsConfig, compilationMode);
600     if (extension_ == es2panda::ScriptExtension::INVALID) {
601         return false;
602     }
603 
604     if (extension_ != es2panda::ScriptExtension::JS && allArgs.opModule.GetValue()) {
605         errorMsg_ = "Error: --module is not supported for this extension.";
606         return false;
607     }
608 
609     // Add Option Flags
610     AddOptionFlags(allArgs.opParseOnly, allArgs.opModule, allArgs.opSizeStat);
611 
612     if ((allArgs.dumpEtsSrcBeforePhases.GetValue().size() + allArgs.dumpEtsSrcAfterPhases.GetValue().size() > 0) &&
613         extension_ != es2panda::ScriptExtension::ETS) {
614         errorMsg_ = "--dump-ets-src-* option is valid only with ETS extension";
615         return false;
616     }
617 
618     DetermineLogLevel(allArgs.logLevel);
619     if (logLevel_ == util::LogLevel::INVALID) {
620         return false;
621     }
622 
623     allArgs.InitCompilerOptions(compilerOptions_, compilationMode);
624 
625     if (!ProcessEtsSpecificOptions(allArgs.arktsConfig.GetValue(), compilationMode)) {
626         return false;
627     }
628 
629     optLevel_ = allArgs.opOptLevel.GetValue();
630     threadCount_ = allArgs.opThreadCount.GetValue();
631     listFiles_ = allArgs.opListFiles.GetValue();
632     listPhases_ = allArgs.opListPhases.GetValue();
633 
634     return true;
635 }
636 }  // namespace ark::es2panda::util
637