13af6ab5fSopenharmony_ci/** 23af6ab5fSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 33af6ab5fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 43af6ab5fSopenharmony_ci * you may not use this file except in compliance with the License. 53af6ab5fSopenharmony_ci * You may obtain a copy of the License at 63af6ab5fSopenharmony_ci * 73af6ab5fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 83af6ab5fSopenharmony_ci * 93af6ab5fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 103af6ab5fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 113af6ab5fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 123af6ab5fSopenharmony_ci * See the License for the specific language governing permissions and 133af6ab5fSopenharmony_ci * limitations under the License. 143af6ab5fSopenharmony_ci */ 153af6ab5fSopenharmony_ci 163af6ab5fSopenharmony_ci#include "ETSparser.h" 173af6ab5fSopenharmony_ci#include "ETSNolintParser.h" 183af6ab5fSopenharmony_ci 193af6ab5fSopenharmony_ci#include "lexer/lexer.h" 203af6ab5fSopenharmony_ci#include "ir/module/importNamespaceSpecifier.h" 213af6ab5fSopenharmony_ci 223af6ab5fSopenharmony_cinamespace ark::es2panda::parser { 233af6ab5fSopenharmony_ciETSNolintParser::ETSNolintParser(const ParserImpl *mainParser) : parser_(mainParser) 243af6ab5fSopenharmony_ci{ 253af6ab5fSopenharmony_ci line_ = parser_->Lexer()->Line(); 263af6ab5fSopenharmony_ci 273af6ab5fSopenharmony_ci warningsMap_ = { 283af6ab5fSopenharmony_ci {std::u32string(U"ets-implicit-boxing-unboxing"), ETSWarnings::IMPLICIT_BOXING_UNBOXING}, 293af6ab5fSopenharmony_ci {std::u32string(U"ets-prohibit-top-level-statements"), ETSWarnings::PROHIBIT_TOP_LEVEL_STATEMENTS}, 303af6ab5fSopenharmony_ci {std::u32string(U"ets-boost-equality-statement"), ETSWarnings::BOOST_EQUALITY_STATEMENT}, 313af6ab5fSopenharmony_ci {std::u32string(U"ets-remove-lambda"), ETSWarnings::REMOVE_LAMBDA}, 323af6ab5fSopenharmony_ci {std::u32string(U"ets-suggest-final"), ETSWarnings::SUGGEST_FINAL}, 333af6ab5fSopenharmony_ci {std::u32string(U"ets-remove-async"), ETSWarnings::REMOVE_ASYNC_FUNCTIONS}, 343af6ab5fSopenharmony_ci }; 353af6ab5fSopenharmony_ci} 363af6ab5fSopenharmony_ci 373af6ab5fSopenharmony_civoid ETSNolintParser::SetStartPos() 383af6ab5fSopenharmony_ci{ 393af6ab5fSopenharmony_ci line_ = parser_->Lexer()->Pos().Line(); 403af6ab5fSopenharmony_ci startPos_ = parser_->Lexer()->Pos().Iterator().Index(); 413af6ab5fSopenharmony_ci posOffset_ = startPos_; 423af6ab5fSopenharmony_ci 433af6ab5fSopenharmony_ci BackwardSymbol(startPos_); 443af6ab5fSopenharmony_ci} 453af6ab5fSopenharmony_ci 463af6ab5fSopenharmony_civoid ETSNolintParser::CollectETSNolints() 473af6ab5fSopenharmony_ci{ 483af6ab5fSopenharmony_ci SetStartPos(); 493af6ab5fSopenharmony_ci char32_t cp = PeekSymbol(); 503af6ab5fSopenharmony_ci 513af6ab5fSopenharmony_ci while (cp != lexer::LEX_CHAR_EOS && cp != lexer::UNICODE_CODE_POINT_MAX && cp != lexer::UNICODE_INVALID_CP) { 523af6ab5fSopenharmony_ci if (!IsEtsNolint()) { 533af6ab5fSopenharmony_ci NextSymbol(); 543af6ab5fSopenharmony_ci cp = PeekSymbol(); 553af6ab5fSopenharmony_ci continue; 563af6ab5fSopenharmony_ci } 573af6ab5fSopenharmony_ci std::size_t line = line_; 583af6ab5fSopenharmony_ci std::set<ETSWarnings> collection; 593af6ab5fSopenharmony_ci if (IsNextLine()) { 603af6ab5fSopenharmony_ci collection = ParseETSNolintArgs(); 613af6ab5fSopenharmony_ci line += 1; 623af6ab5fSopenharmony_ci } else if (IsBegin()) { 633af6ab5fSopenharmony_ci collection = ParseETSNolintArgs(); 643af6ab5fSopenharmony_ci for (const auto it : collection) { 653af6ab5fSopenharmony_ci applyingCollection_.insert(it); 663af6ab5fSopenharmony_ci } 673af6ab5fSopenharmony_ci } else if (IsEnd()) { 683af6ab5fSopenharmony_ci collection = ParseETSNolintArgs(); 693af6ab5fSopenharmony_ci 703af6ab5fSopenharmony_ci for (const auto it : collection) { 713af6ab5fSopenharmony_ci applyingCollection_.erase(it); 723af6ab5fSopenharmony_ci } 733af6ab5fSopenharmony_ci cp = PeekSymbol(); 743af6ab5fSopenharmony_ci continue; 753af6ab5fSopenharmony_ci } else { 763af6ab5fSopenharmony_ci collection = ParseETSNolintArgs(); 773af6ab5fSopenharmony_ci } 783af6ab5fSopenharmony_ci AddToETSNolintLinesCollection(line, collection); 793af6ab5fSopenharmony_ci cp = PeekSymbol(); 803af6ab5fSopenharmony_ci } 813af6ab5fSopenharmony_ci 823af6ab5fSopenharmony_ci RewindToStart(); 833af6ab5fSopenharmony_ci} 843af6ab5fSopenharmony_ci 853af6ab5fSopenharmony_civoid ETSNolintParser::ApplyETSNolintsToStatements(ArenaVector<ir::Statement *> &statements) const 863af6ab5fSopenharmony_ci{ 873af6ab5fSopenharmony_ci for (auto *it : statements) { 883af6ab5fSopenharmony_ci ApplyETSNolintsToNodesRecursively(it); 893af6ab5fSopenharmony_ci } 903af6ab5fSopenharmony_ci} 913af6ab5fSopenharmony_ci 923af6ab5fSopenharmony_civoid ETSNolintParser::NextSymbol() 933af6ab5fSopenharmony_ci{ 943af6ab5fSopenharmony_ci if (PeekSymbol() == lexer::LEX_CHAR_LF) { 953af6ab5fSopenharmony_ci if (!applyingCollection_.empty()) { 963af6ab5fSopenharmony_ci AddToETSNolintLinesCollection(line_, applyingCollection_); 973af6ab5fSopenharmony_ci } 983af6ab5fSopenharmony_ci line_++; 993af6ab5fSopenharmony_ci } 1003af6ab5fSopenharmony_ci 1013af6ab5fSopenharmony_ci posOffset_++; 1023af6ab5fSopenharmony_ci parser_->Lexer()->Pos().Iterator().Forward(1); 1033af6ab5fSopenharmony_ci} 1043af6ab5fSopenharmony_ci 1053af6ab5fSopenharmony_civoid ETSNolintParser::BackwardSymbol() 1063af6ab5fSopenharmony_ci{ 1073af6ab5fSopenharmony_ci posOffset_--; 1083af6ab5fSopenharmony_ci parser_->Lexer()->Pos().Iterator().Backward(1); 1093af6ab5fSopenharmony_ci 1103af6ab5fSopenharmony_ci if (PeekSymbol() == lexer::LEX_CHAR_LF) { 1113af6ab5fSopenharmony_ci line_--; 1123af6ab5fSopenharmony_ci } 1133af6ab5fSopenharmony_ci} 1143af6ab5fSopenharmony_ci 1153af6ab5fSopenharmony_civoid ETSNolintParser::NextSymbol(std::size_t i) 1163af6ab5fSopenharmony_ci{ 1173af6ab5fSopenharmony_ci for (; i > 0; --i) { 1183af6ab5fSopenharmony_ci NextSymbol(); 1193af6ab5fSopenharmony_ci } 1203af6ab5fSopenharmony_ci} 1213af6ab5fSopenharmony_ci 1223af6ab5fSopenharmony_civoid ETSNolintParser::BackwardSymbol(std::size_t i) 1233af6ab5fSopenharmony_ci{ 1243af6ab5fSopenharmony_ci for (; i > 0; --i) { 1253af6ab5fSopenharmony_ci BackwardSymbol(); 1263af6ab5fSopenharmony_ci } 1273af6ab5fSopenharmony_ci} 1283af6ab5fSopenharmony_ci 1293af6ab5fSopenharmony_civoid ETSNolintParser::RewindToStart() const 1303af6ab5fSopenharmony_ci{ 1313af6ab5fSopenharmony_ci parser_->Lexer()->Pos().Iterator().Backward(posOffset_ - startPos_); 1323af6ab5fSopenharmony_ci} 1333af6ab5fSopenharmony_ci 1343af6ab5fSopenharmony_civoid ETSNolintParser::AddToETSNolintLinesCollection(std::size_t line, const std::set<ETSWarnings> &collection) 1353af6ab5fSopenharmony_ci{ 1363af6ab5fSopenharmony_ci const auto search = linesCollection_.find(line); 1373af6ab5fSopenharmony_ci if (search != linesCollection_.end()) { 1383af6ab5fSopenharmony_ci search->second.insert(collection.begin(), collection.end()); 1393af6ab5fSopenharmony_ci return; 1403af6ab5fSopenharmony_ci } 1413af6ab5fSopenharmony_ci 1423af6ab5fSopenharmony_ci linesCollection_.insert({line, collection}); 1433af6ab5fSopenharmony_ci} 1443af6ab5fSopenharmony_ci 1453af6ab5fSopenharmony_cichar32_t ETSNolintParser::PeekSymbol() const 1463af6ab5fSopenharmony_ci{ 1473af6ab5fSopenharmony_ci return parser_->Lexer()->Pos().Iterator().Peek(); 1483af6ab5fSopenharmony_ci} 1493af6ab5fSopenharmony_ci 1503af6ab5fSopenharmony_cibool ETSNolintParser::TryPeekU32String(const std::u32string &u32str) 1513af6ab5fSopenharmony_ci{ 1523af6ab5fSopenharmony_ci std::size_t localPosOffset = 0; 1533af6ab5fSopenharmony_ci char32_t cp; 1543af6ab5fSopenharmony_ci 1553af6ab5fSopenharmony_ci for (const char32_t i : u32str) { 1563af6ab5fSopenharmony_ci cp = PeekSymbol(); 1573af6ab5fSopenharmony_ci if (i != cp) { 1583af6ab5fSopenharmony_ci BackwardSymbol(localPosOffset); 1593af6ab5fSopenharmony_ci return false; 1603af6ab5fSopenharmony_ci } 1613af6ab5fSopenharmony_ci NextSymbol(); 1623af6ab5fSopenharmony_ci localPosOffset++; 1633af6ab5fSopenharmony_ci } 1643af6ab5fSopenharmony_ci return true; 1653af6ab5fSopenharmony_ci} 1663af6ab5fSopenharmony_ci 1673af6ab5fSopenharmony_cibool ETSNolintParser::IsEtsNolint() 1683af6ab5fSopenharmony_ci{ 1693af6ab5fSopenharmony_ci static const std::u32string ETSNOLINT_CHAR32T = { 1703af6ab5fSopenharmony_ci lexer::LEX_CHAR_UPPERCASE_E, lexer::LEX_CHAR_UPPERCASE_T, lexer::LEX_CHAR_UPPERCASE_S, 1713af6ab5fSopenharmony_ci lexer::LEX_CHAR_UPPERCASE_N, lexer::LEX_CHAR_UPPERCASE_O, lexer::LEX_CHAR_UPPERCASE_L, 1723af6ab5fSopenharmony_ci lexer::LEX_CHAR_UPPERCASE_I, lexer::LEX_CHAR_UPPERCASE_N, lexer::LEX_CHAR_UPPERCASE_T}; 1733af6ab5fSopenharmony_ci 1743af6ab5fSopenharmony_ci char32_t cp; 1753af6ab5fSopenharmony_ci 1763af6ab5fSopenharmony_ci for (unsigned long i = 0; i < ETSNOLINT_CHAR32T.length(); i++) { 1773af6ab5fSopenharmony_ci cp = PeekSymbol(); 1783af6ab5fSopenharmony_ci if (ETSNOLINT_CHAR32T[i] != cp) { 1793af6ab5fSopenharmony_ci return false; 1803af6ab5fSopenharmony_ci } 1813af6ab5fSopenharmony_ci 1823af6ab5fSopenharmony_ci NextSymbol(); 1833af6ab5fSopenharmony_ci } 1843af6ab5fSopenharmony_ci 1853af6ab5fSopenharmony_ci return true; 1863af6ab5fSopenharmony_ci} 1873af6ab5fSopenharmony_ci 1883af6ab5fSopenharmony_cibool ETSNolintParser::IsNextLine() 1893af6ab5fSopenharmony_ci{ 1903af6ab5fSopenharmony_ci static const std::u32string NEXTLINE_CHAR32T = { 1913af6ab5fSopenharmony_ci lexer::LEX_CHAR_MINUS, lexer::LEX_CHAR_UPPERCASE_N, lexer::LEX_CHAR_UPPERCASE_E, 1923af6ab5fSopenharmony_ci lexer::LEX_CHAR_UPPERCASE_X, lexer::LEX_CHAR_UPPERCASE_T, lexer::LEX_CHAR_UPPERCASE_L, 1933af6ab5fSopenharmony_ci lexer::LEX_CHAR_UPPERCASE_I, lexer::LEX_CHAR_UPPERCASE_N, lexer::LEX_CHAR_UPPERCASE_E}; 1943af6ab5fSopenharmony_ci 1953af6ab5fSopenharmony_ci return TryPeekU32String(NEXTLINE_CHAR32T); 1963af6ab5fSopenharmony_ci} 1973af6ab5fSopenharmony_ci 1983af6ab5fSopenharmony_cibool ETSNolintParser::IsBegin() 1993af6ab5fSopenharmony_ci{ 2003af6ab5fSopenharmony_ci static const std::u32string BEGIN_CHAR32T = {lexer::LEX_CHAR_MINUS, lexer::LEX_CHAR_UPPERCASE_B, 2013af6ab5fSopenharmony_ci lexer::LEX_CHAR_UPPERCASE_E, lexer::LEX_CHAR_UPPERCASE_G, 2023af6ab5fSopenharmony_ci lexer::LEX_CHAR_UPPERCASE_I, lexer::LEX_CHAR_UPPERCASE_N}; 2033af6ab5fSopenharmony_ci 2043af6ab5fSopenharmony_ci return TryPeekU32String(BEGIN_CHAR32T); 2053af6ab5fSopenharmony_ci} 2063af6ab5fSopenharmony_ci 2073af6ab5fSopenharmony_cibool ETSNolintParser::IsEnd() 2083af6ab5fSopenharmony_ci{ 2093af6ab5fSopenharmony_ci static const std::u32string END_CHAR32T = {lexer::LEX_CHAR_MINUS, lexer::LEX_CHAR_UPPERCASE_E, 2103af6ab5fSopenharmony_ci lexer::LEX_CHAR_UPPERCASE_N, lexer::LEX_CHAR_UPPERCASE_D}; 2113af6ab5fSopenharmony_ci 2123af6ab5fSopenharmony_ci return TryPeekU32String(END_CHAR32T); 2133af6ab5fSopenharmony_ci} 2143af6ab5fSopenharmony_ci 2153af6ab5fSopenharmony_ciETSWarnings ETSNolintParser::MapETSNolintArg(const std::u32string &warningName) const 2163af6ab5fSopenharmony_ci{ 2173af6ab5fSopenharmony_ci const auto search = warningsMap_.find(warningName); 2183af6ab5fSopenharmony_ci ASSERT(search != warningsMap_.end()); 2193af6ab5fSopenharmony_ci 2203af6ab5fSopenharmony_ci return search->second; 2213af6ab5fSopenharmony_ci} 2223af6ab5fSopenharmony_ci 2233af6ab5fSopenharmony_cibool ETSNolintParser::ValidETSNolintArg(const std::u32string &warningName) const 2243af6ab5fSopenharmony_ci{ 2253af6ab5fSopenharmony_ci return warningsMap_.find(warningName) != warningsMap_.end(); 2263af6ab5fSopenharmony_ci} 2273af6ab5fSopenharmony_ci 2283af6ab5fSopenharmony_cistd::set<ETSWarnings> ETSNolintParser::ParseETSNolintArgs() 2293af6ab5fSopenharmony_ci{ 2303af6ab5fSopenharmony_ci std::set<ETSWarnings> warningsCollection; 2313af6ab5fSopenharmony_ci 2323af6ab5fSopenharmony_ci if (PeekSymbol() != lexer::LEX_CHAR_LEFT_PAREN) { 2333af6ab5fSopenharmony_ci for (const auto &it : warningsMap_) { 2343af6ab5fSopenharmony_ci warningsCollection.insert(it.second); 2353af6ab5fSopenharmony_ci } 2363af6ab5fSopenharmony_ci 2373af6ab5fSopenharmony_ci return warningsCollection; 2383af6ab5fSopenharmony_ci } 2393af6ab5fSopenharmony_ci 2403af6ab5fSopenharmony_ci NextSymbol(); 2413af6ab5fSopenharmony_ci char32_t cp = 0; 2423af6ab5fSopenharmony_ci std::u32string warningName; 2433af6ab5fSopenharmony_ci 2443af6ab5fSopenharmony_ci while (cp != lexer::LEX_CHAR_SP && cp != lexer::LEX_CHAR_LF && cp != lexer::LEX_CHAR_EOS) { 2453af6ab5fSopenharmony_ci cp = PeekSymbol(); 2463af6ab5fSopenharmony_ci if (cp != lexer::LEX_CHAR_MINUS && cp != lexer::LEX_CHAR_COMMA && cp != lexer::LEX_CHAR_RIGHT_PAREN && 2473af6ab5fSopenharmony_ci (cp < lexer::LEX_CHAR_LOWERCASE_A || cp > lexer::LEX_CHAR_LOWERCASE_Z)) { 2483af6ab5fSopenharmony_ci const std::string msg = "Unexpected character for ETSNOLINT argument! [VALID ONLY: a-z, '-']."; 2493af6ab5fSopenharmony_ci throw Error {ErrorType::SYNTAX, parser_->GetProgram()->SourceFilePath().Utf8(), msg.c_str(), line_ + 1, 0}; 2503af6ab5fSopenharmony_ci } 2513af6ab5fSopenharmony_ci if ((cp == lexer::LEX_CHAR_COMMA || cp == lexer::LEX_CHAR_RIGHT_PAREN) && !ValidETSNolintArg(warningName)) { 2523af6ab5fSopenharmony_ci const std::string msg = "Invalid argument for ETSNOLINT!"; 2533af6ab5fSopenharmony_ci throw Error {ErrorType::SYNTAX, parser_->GetProgram()->SourceFilePath().Utf8(), msg.c_str(), line_ + 1, 0}; 2543af6ab5fSopenharmony_ci } 2553af6ab5fSopenharmony_ci if ((cp == lexer::LEX_CHAR_COMMA || cp == lexer::LEX_CHAR_RIGHT_PAREN) && ValidETSNolintArg(warningName)) { 2563af6ab5fSopenharmony_ci warningsCollection.insert(MapETSNolintArg(warningName)); 2573af6ab5fSopenharmony_ci warningName.clear(); 2583af6ab5fSopenharmony_ci } else { 2593af6ab5fSopenharmony_ci warningName += cp; 2603af6ab5fSopenharmony_ci } 2613af6ab5fSopenharmony_ci if (cp == lexer::LEX_CHAR_RIGHT_PAREN) { 2623af6ab5fSopenharmony_ci break; 2633af6ab5fSopenharmony_ci } 2643af6ab5fSopenharmony_ci 2653af6ab5fSopenharmony_ci NextSymbol(); 2663af6ab5fSopenharmony_ci } 2673af6ab5fSopenharmony_ci 2683af6ab5fSopenharmony_ci return warningsCollection; 2693af6ab5fSopenharmony_ci} 2703af6ab5fSopenharmony_ci 2713af6ab5fSopenharmony_cibool ETSNolintParser::IsLineWithETSNolint(const std::size_t line) const 2723af6ab5fSopenharmony_ci{ 2733af6ab5fSopenharmony_ci return linesCollection_.find(line) != linesCollection_.end(); 2743af6ab5fSopenharmony_ci} 2753af6ab5fSopenharmony_ci 2763af6ab5fSopenharmony_cistd::set<ETSWarnings> ETSNolintParser::GetWarningsCollectionByLine(std::size_t line) const 2773af6ab5fSopenharmony_ci{ 2783af6ab5fSopenharmony_ci const auto search = linesCollection_.find(line); 2793af6ab5fSopenharmony_ci return search == linesCollection_.end() ? std::set<ETSWarnings> {} : search->second; 2803af6ab5fSopenharmony_ci} 2813af6ab5fSopenharmony_ci 2823af6ab5fSopenharmony_civoid ETSNolintParser::ApplyETSNolintsToNodesRecursively(ir::AstNode *node) const 2833af6ab5fSopenharmony_ci{ 2843af6ab5fSopenharmony_ci if (node == nullptr) { 2853af6ab5fSopenharmony_ci return; 2863af6ab5fSopenharmony_ci } 2873af6ab5fSopenharmony_ci const std::size_t line = node->Start().line; 2883af6ab5fSopenharmony_ci if (IsLineWithETSNolint(line)) { 2893af6ab5fSopenharmony_ci const std::set<ETSWarnings> warningsCollection = GetWarningsCollectionByLine(line); 2903af6ab5fSopenharmony_ci 2913af6ab5fSopenharmony_ci parser_->GetProgram()->AddNodeToETSNolintCollection(node, warningsCollection); 2923af6ab5fSopenharmony_ci } 2933af6ab5fSopenharmony_ci node->Iterate([&](auto *childNode) { ApplyETSNolintsToNodesRecursively(childNode); }); 2943af6ab5fSopenharmony_ci} 2953af6ab5fSopenharmony_ci} // namespace ark::es2panda::parser 296