diff --git a/BUILD.gn b/BUILD.gn index 3994d80850dbec10fe1b3f088f7e5a9abc678108..f59a105c3ec219c5aca426f9f469abf62bdf5084 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -251,6 +251,7 @@ libes2panda_sources = [ "checker/ASchecker.cpp", "checker/JSchecker.cpp", "checker/ets/aliveAnalyzer.cpp", + "checker/ets/etsWarningAnalyzer.cpp", "checker/ets/arithmetic.cpp", "checker/ets/baseAnalyzer.cpp", "checker/ets/boxingConverter.cpp", diff --git a/CMakeLists.txt b/CMakeLists.txt index b57fe60cec3c82e3bb54f4af6de42b6efe03cb2c..41f1cec415cb5b06b4ec51d5eb560be49141e8fc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -305,6 +305,7 @@ set(ES2PANDA_LIB_SRC checker/ASchecker.cpp checker/JSchecker.cpp checker/ets/aliveAnalyzer.cpp + checker/ets/etsWarningAnalyzer.cpp checker/ets/arithmetic.cpp checker/ets/baseAnalyzer.cpp checker/ets/boxingConverter.cpp diff --git a/aot/options.cpp b/aot/options.cpp index 2030841d58405f43bf3a616b3e697b16a884e04c..3bbb94dc06172b4fe36613f9fd9888dc468cb996 100644 --- a/aot/options.cpp +++ b/aot/options.cpp @@ -36,6 +36,11 @@ Options::~Options() delete argparser_; } +static inline bool ETSWarningsGroupSetter(const panda::PandArg &option) +{ + return !option.WasSet() || (option.WasSet() && option.GetValue()); +} + // NOLINTNEXTLINE(readability-function-size) bool Options::Parse(int argc, const char **argv) { @@ -58,6 +63,15 @@ bool Options::Parse(int argc, const char **argv) panda::PandArg op_opt_level("opt-level", 0, "Compiler optimization level (options: 0 | 1 | 2)"); panda::PandArg op_ets_module("ets-module", false, "Compile the input as ets-module"); + // ETS-warnings + panda::PandArg op_ets_warnings_all("ets-warnings-all", false, "Show performance-related warnings"); + panda::PandArg op_ets_subset_warnings("ets-subset-warnings", false, + "Show ETS-warnings that keep you in subset"); + panda::PandArg op_ets_nonsubset_warnings("ets-nonsubset-warnings", false, + "Show ETS-warnings that do not keep you in subset"); + panda::PandArg op_ets_suggest_final("ets-suggest-final", false, + "Suggest final keyword warning - ETS non-subset warning"); + auto constexpr DEFAULT_THREAD_COUNT = 2; panda::PandArg op_thread_count("thread", DEFAULT_THREAD_COUNT, "Number of worker threads"); panda::PandArg op_size_stat("dump-size-stat", false, "Dump size statistics"); @@ -92,6 +106,15 @@ bool Options::Parse(int argc, const char **argv) argparser_->Add(&gen_std_lib); argparser_->Add(&arkts_config); + argparser_->Add(&op_ets_warnings_all); + argparser_->Add(&op_ets_subset_warnings); + argparser_->Add(&op_ets_nonsubset_warnings); + + // ETS-subset warnings + + // ETS-non-subset warnings + argparser_->Add(&op_ets_suggest_final); + argparser_->PushBackTail(&input_file); argparser_->EnableTail(); argparser_->EnableRemainder(); @@ -255,6 +278,36 @@ bool Options::Parse(int argc, const char **argv) compiler_options_.compilation_mode = compilation_mode; compiler_options_.is_ets_module = op_ets_module.GetValue(); + // ETS-Warnings + compiler_options_.ets_subset_warnings = op_ets_subset_warnings.GetValue(); + compiler_options_.ets_nonsubset_warnings = op_ets_nonsubset_warnings.GetValue(); + compiler_options_.ets_warnings_all = op_ets_warnings_all.GetValue(); + + if (compiler_options_.ets_warnings_all || compiler_options_.ets_subset_warnings) { + // Adding subset warnings + // Will be added + } + + if (compiler_options_.ets_warnings_all || compiler_options_.ets_nonsubset_warnings) { + // Adding non-subset warnings + compiler_options_.ets_suggest_final = ETSWarningsGroupSetter(op_ets_suggest_final); + } + + if (!compiler_options_.ets_warnings_all && !compiler_options_.ets_subset_warnings && + !compiler_options_.ets_nonsubset_warnings) { + // If no warnings groups enabled - check all if enabled + compiler_options_.ets_suggest_final = op_ets_suggest_final.GetValue(); + } + + // Pushing positive warnings to warning collection + if (compiler_options_.ets_suggest_final) { + compiler_options_.ets_warning_collection.push_back(ETSWarnings::ETSNonSubsetWarnings::SUGGEST_FINAL); + } + + if (!compiler_options_.ets_warning_collection.empty()) { + compiler_options_.has_ets_warnings = true; + } + return true; } -} // namespace panda::es2panda::aot +} // namespace panda::es2panda::aot \ No newline at end of file diff --git a/checker/ETSchecker.cpp b/checker/ETSchecker.cpp index 4a8ee97c195d59d5774a7edeb254dad5aeb8e50c..217a580035e3f1e20d3a9555eba7f17305dd3997 100644 --- a/checker/ETSchecker.cpp +++ b/checker/ETSchecker.cpp @@ -23,6 +23,7 @@ #include "plugins/ecmascript/es2panda/binder/ETSBinder.h" #include "plugins/ecmascript/es2panda/parser/program/program.h" #include "plugins/ecmascript/es2panda/checker/ets/aliveAnalyzer.h" +#include "plugins/ecmascript/es2panda/checker/ets/etsWarningAnalyzer.h" #include "plugins/ecmascript/es2panda/ir/base/scriptFunction.h" #include "plugins/ecmascript/es2panda/util/helpers.h" @@ -103,6 +104,10 @@ bool ETSChecker::StartChecker([[maybe_unused]] binder::Binder *binder, const Com std::cout << Program()->Dump() << std::endl; } + if (options.has_ets_warnings) { + CheckWarnings(Program(), options); + } + return true; } @@ -130,6 +135,14 @@ void ETSChecker::CheckProgram(parser::Program *program, bool run_analysis) SetProgram(saved_program); } +void ETSChecker::CheckWarnings([[maybe_unused]] parser::Program *program, const CompilerOptions &options) +{ + auto ets_warning_collection = options.ets_warning_collection; + for (auto warning : ets_warning_collection) { + ETSWarningAnalyzer(Program()->Ast(), this, Program(), warning); + } +} + Type *ETSChecker::CheckTypeCached(ir::Expression *expr) { if (expr->TsType() == nullptr) { diff --git a/checker/ETSchecker.h b/checker/ETSchecker.h index 9182f4f7c91ffe1afde11ce61ab0f2be13683e34..00f038d692c1aa9bf949a8b294ef85792a51426f 100644 --- a/checker/ETSchecker.h +++ b/checker/ETSchecker.h @@ -501,6 +501,7 @@ private: ETSObjectType *CreateETSObjectTypeCheckBuiltins(util::StringView name, ir::AstNode *decl_node, ETSObjectFlags flags); void CheckProgram(parser::Program *program, bool run_analysis = false); + void CheckWarnings(parser::Program *program, const CompilerOptions &options); template UType HandleModulo(UType left_value, UType right_value); diff --git a/checker/ets/etsWarningAnalyzer.cpp b/checker/ets/etsWarningAnalyzer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0672ed167e2969b9260f8c44e7e7a988685b4c60 --- /dev/null +++ b/checker/ets/etsWarningAnalyzer.cpp @@ -0,0 +1,40 @@ +/** + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "etsWarningAnalyzer.h" + +#include "plugins/ecmascript/es2panda/parser/program/program.h" +#include "plugins/ecmascript/es2panda/aot/options.h" + +namespace panda::es2panda::checker { + +void ETSWarningAnalyzer::ETSWarningSuggestFinal([[maybe_unused]] const ir::AstNode *node, + [[maybe_unused]] ETSChecker *checker) +{ + ASSERT(node != nullptr); + // Implement me +} + +void ETSWarningAnalyzer::ETSThrowWarning(const util::StringView &message, const lexer::SourcePosition &pos) +{ + lexer::LineIndex index(program_->SourceCode()); + lexer::SourceLocation location = index.GetLocation(pos); + + std::cout << "ETS Warning: " << message << "." + << " [" << panda::es2panda::aot::BaseName(program_->SourceFile().Utf8()) << ":" << location.line << ":" + << location.col << "]" << std::endl; +} + +} // namespace panda::es2panda::checker diff --git a/checker/ets/etsWarningAnalyzer.h b/checker/ets/etsWarningAnalyzer.h new file mode 100644 index 0000000000000000000000000000000000000000..22563ca0d528a12f6743465902b0ff2f098fc2ed --- /dev/null +++ b/checker/ets/etsWarningAnalyzer.h @@ -0,0 +1,50 @@ +/** + * Copyright (c) 2021 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ES2PANDA_COMPILER_CHECKER_ETS_ETS_WARNING_ANALYZER_H +#define ES2PANDA_COMPILER_CHECKER_ETS_ETS_WARNING_ANALYZER_H + +#include "plugins/ecmascript/es2panda/checker/ETSchecker.h" + +namespace panda::es2panda::checker { +class ETSWarningAnalyzer { +public: + ETSWarningAnalyzer(const ir::AstNode *node, ETSChecker *checker, parser::Program *program, const int &warning) + : checker_(checker), program_(program) + { + if (node == nullptr) { + return; + } + + switch (warning) { // NOLINT(hicpp-multiway-paths-covered) + case ETSWarnings::ETSNonSubsetWarnings::SUGGEST_FINAL: + ETSWarningSuggestFinal(node, checker_); + break; + default: + break; + } + } + +private: + void ETSThrowWarning(const util::StringView &message, const lexer::SourcePosition &position); + + static void ETSWarningSuggestFinal(const ir::AstNode *node, ETSChecker *checker); + + ETSChecker *checker_; + parser::Program *program_; +}; +} // namespace panda::es2panda::checker + +#endif diff --git a/es2panda.h b/es2panda.h index 5cf614d4a772912deef2fce285b07d1eb6e9ed1d..09bd669d2b62b2633ab6df147b04200432506ac1 100644 --- a/es2panda.h +++ b/es2panda.h @@ -83,6 +83,17 @@ struct SourceFile { // NOLINTEND(misc-non-private-member-variables-in-classes) }; +struct ETSWarnings { + enum ETSSubsetWarnings { + IMPLICIT_BOXING_UNBOXING_COMMON = 2, + IMPLICIT_BOXING_UNBOXING_DETAILED = 3, + KICK_FOR_OF = 4, + }; + enum ETSNonSubsetWarnings { + SUGGEST_FINAL = 1, + }; +}; + struct CompilerOptions { // NOLINTBEGIN(misc-non-private-member-variables-in-classes) bool is_debug {}; @@ -99,6 +110,19 @@ struct CompilerOptions { std::shared_ptr arkts_config {}; CompilationMode compilation_mode {}; // NOLINTEND(misc-non-private-member-variables-in-classes) + + // ETS Warning Groups + bool ets_warnings_all {}; // Enable all ETS-warnings for System ArkTS + bool ets_subset_warnings {}; // Enable only ETS-warnings that keep you in subset + bool ets_nonsubset_warnings {}; // Enable only ETS-warnings that do not keep you in subset + bool has_ets_warnings = false; + + // Subset ETS-Warnings + + // Non-subset ETS-Warnings + bool ets_suggest_final {}; + + std::vector ets_warning_collection = {}; }; enum class ErrorType {