diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 18981398469de33170db20561bd8b82c1aa5a565..457455f9123ce810d83cda4c676193f621b19be6 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -1193,6 +1193,8 @@ ark_gen("es2panda_diagnostic_gen") { "util/diagnostic/semantic.yaml", "util/diagnostic/warning.yaml", "util/diagnostic/fatal.yaml", + "declgen_ets2ts/declgen_ets2ts_error.yaml", + "declgen_ets2ts/declgen_ets2ts_warning.yaml", ] template_files = [ "diagnostic.h.erb" ] sources = "util/diagnostic" @@ -1202,6 +1204,8 @@ ark_gen("es2panda_diagnostic_gen") { "util/diagnostic/diagnostic.rb", "util/diagnostic/diagnostic.rb", "util/diagnostic/diagnostic.rb", + "util/diagnostic/diagnostic.rb", + "util/diagnostic/diagnostic.rb", ] } diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index f7874ec1d887c9d9a84d1820219a1b78e87b21e5..df91bb8eb9aa9b2c59b84b24810efa1b64ae5867 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -122,6 +122,8 @@ panda_gen( ${DIAGNOSTIC_DIR}/semantic.yaml ${DIAGNOSTIC_DIR}/warning.yaml ${DIAGNOSTIC_DIR}/fatal.yaml + ${CMAKE_CURRENT_SOURCE_DIR}/declgen_ets2ts/declgen_ets2ts_error.yaml + ${CMAKE_CURRENT_SOURCE_DIR}/declgen_ets2ts/declgen_ets2ts_warning.yaml TARGET_NAME es2panda_diagnostic_gen TEMPLATES diagnostic.h.erb SOURCE ${DIAGNOSTIC_DIR} @@ -131,6 +133,8 @@ panda_gen( ${DIAGNOSTIC_DIR}/diagnostic.rb ${DIAGNOSTIC_DIR}/diagnostic.rb ${DIAGNOSTIC_DIR}/diagnostic.rb + ${DIAGNOSTIC_DIR}/diagnostic.rb + ${DIAGNOSTIC_DIR}/diagnostic.rb ) panda_gen( diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp index 8fdf6552b952b983248a51df07ce6b6cc8c76aef..a3dca13373ee53c56b1f875c5cbbb33c0ba2867e 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.cpp @@ -15,6 +15,7 @@ #include "declgenEts2Ts.h" +#include "generated/diagnostic.h" #include "ir/base/classProperty.h" #include "ir/base/methodDefinition.h" #include "ir/base/scriptFunction.h" @@ -40,11 +41,6 @@ static void DebugPrint([[maybe_unused]] const std::string &msg) #endif } -static void Warning(const std::string &msg) -{ - std::cerr << "Warning declgen ets2ts: " << msg << std::endl; -} - void TSDeclGen::Generate() { std::stringstream license; @@ -104,19 +100,23 @@ void TSDeclGen::GenSeparated(const T &container, const CB &cb, const char *separ } } -void TSDeclGen::ThrowError(const std::string_view message, const lexer::SourcePosition &pos = lexer::SourcePosition()) +void TSDeclGen::LogError(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams ¶ms = {}, + const lexer::SourcePosition &pos = lexer::SourcePosition()) { - lexer::LineIndex index(program_->SourceCode()); - const lexer::SourceLocation loc = index.GetLocation(pos); + diagnosticEngine_.LogDiagnostic(kind, params, program_, pos); +} - throw util::ThrowableDiagnostic {util::DiagnosticType::FATAL, "declgen ets2ts: " + std::string(message), - program_->SourceFilePath().Utf8(), loc.line, loc.col}; +void TSDeclGen::LogWarning(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams ¶ms = {}, + const lexer::SourcePosition &pos = lexer::SourcePosition()) +{ + ASSERT(kind.Type() == util::DiagnosticType::DECLGEN_ETS2TS_WARNING); + LogError(kind, params, pos); } const ir::Identifier *TSDeclGen::GetKeyIdent(const ir::Expression *key) { if (!key->IsIdentifier()) { - ThrowError("Not identifier keys are not supported", key->Start()); + LogError(diagnostic::IDENT_KEY_SUPPORT, {}, key->Start()); } return key->AsIdentifier(); @@ -177,14 +177,14 @@ void TSDeclGen::GenType(const checker::Type *checkerType) GenUnionType(checkerType->AsETSUnionType()); return; default: - ThrowError(std::string("Unsupported type: '") + GetDebugTypeName(checkerType)); + LogError(diagnostic::UNSUPPORTED_TYPE, {GetDebugTypeName(checkerType)}); } } void TSDeclGen::GenLiteral(const ir::Literal *literal) { if (!literal->IsNumberLiteral()) { - ThrowError("Unsupported literal type", literal->Start()); + LogError(diagnostic::UNSUPPORTED_LITERAL_TYPE, {}, literal->Start()); } const auto number = literal->AsNumberLiteral()->Number(); @@ -205,7 +205,7 @@ void TSDeclGen::GenLiteral(const ir::Literal *literal) return; } - ThrowError("Unexpected number literal type", literal->Start()); + LogError(diagnostic::UNEXPECTED_NUMBER_LITERAL_TYPE, {}, literal->Start()); } void TSDeclGen::GenFunctionType(const checker::ETSFunctionType *etsFunctionType, const ir::MethodDefinition *methodDef) @@ -219,7 +219,7 @@ void TSDeclGen::GenFunctionType(const checker::ETSFunctionType *etsFunctionType, } if (!etsFunctionType->IsETSArrowType()) { const auto loc = methodDef != nullptr ? methodDef->Start() : lexer::SourcePosition(); - ThrowError("Method overloads are not supported", loc); + LogError(diagnostic::NOT_OVERLOAD_SUPPORT, {}, loc); } return etsFunctionType->CallSignatures()[0]; }(); @@ -260,7 +260,7 @@ void TSDeclGen::GenEnumType(const checker::ETSIntEnumType *enumType) for (auto *member : enumType->GetMembers()) { OutDts(INDENT); if (!member->IsTSEnumMember()) { - ThrowError("Member of enum not of type TSEnumMember", member->Start()); + LogError(diagnostic::INCORRECT_ENUM_MEMBER, {}, member->Start()); } const auto *enumMember = member->AsTSEnumMember(); @@ -270,7 +270,7 @@ void TSDeclGen::GenEnumType(const checker::ETSIntEnumType *enumType) OutDts(" = "); if (!init->IsLiteral()) { - ThrowError("Only literal enum initializers are supported", member->Start()); + LogError(diagnostic::NOT_LITERAL_ENUM_INITIALIZER, {}, member->Start()); } GenLiteral(init->AsLiteral()); @@ -311,7 +311,7 @@ void TSDeclGen::GenObjectType(const checker::ETSObjectType *objectType) auto typeName = objectType->Name(); if (typeName.Empty()) { - Warning("Object type name is empty"); + LogWarning(diagnostic::EMPTY_TYPE_NAME); OutDts("any"); } else { objectArguments_.insert(typeName.Mutf8()); @@ -425,14 +425,14 @@ void TSDeclGen::GenImportDeclaration(const ir::ETSImportDeclaration *importDecla OutDts("import { "); GenSeparated(specifiers, [this, &importDeclaration](ir::AstNode *specifier) { if (!specifier->IsImportSpecifier()) { - ThrowError("Only import specifiers are supported", importDeclaration->Start()); + LogError(diagnostic::IMPORT_SPECIFIERS_SUPPORT, {}, importDeclaration->Start()); } const auto local = specifier->AsImportSpecifier()->Local()->Name(); const auto imported = specifier->AsImportSpecifier()->Imported()->Name(); OutDts(local); if (local != imported) { - ThrowError("Imports with local bindings are not supported", importDeclaration->Start()); + LogError(diagnostic::UNSUPPORTED_LOCAL_BINDINGS, {}, importDeclaration->Start()); } }); @@ -638,7 +638,7 @@ void TSDeclGen::GenMethodDeclaration(const ir::MethodDefinition *methodDef, cons OutDts(methodName); if (methodDef->TsType() == nullptr) { - Warning("Untyped method encountered: " + methodName); + LogWarning(diagnostic::UNTYPED_METHOD, {methodName}, methodIdent->Start()); OutDts(": any"); } else { GenFunctionType(methodDef->TsType()->AsETSFunctionType(), methodDef); @@ -719,7 +719,7 @@ bool GenerateTsDeclarations(checker::ETSChecker *checker, const ark::es2panda::p std::ofstream outDtsStream(outDtsPath); if (outDtsStream.fail()) { - std::cerr << "Failed to open file: " << outDtsPath << std::endl; + checker->DiagnosticEngine().LogFatalError(util::DiagnosticMessageParams {"Failed to open file: ", outDtsPath}); return false; } diff --git a/ets2panda/declgen_ets2ts/declgenEts2Ts.h b/ets2panda/declgen_ets2ts/declgenEts2Ts.h index 92eea3d02e7256260f0912ce278e01eb386ba7e2..7d834f7279362bef402f71094dcc82ae13a2d0f8 100644 --- a/ets2panda/declgen_ets2ts/declgenEts2Ts.h +++ b/ets2panda/declgen_ets2ts/declgenEts2Ts.h @@ -21,6 +21,7 @@ #include "libpandabase/os/file.h" #include "libpandabase/utils/arena_containers.h" #include "util/options.h" +#include "util/diagnosticEngine.h" namespace ark::es2panda::declgen_ets2ts { @@ -39,6 +40,7 @@ public: TSDeclGen(checker::ETSChecker *checker, const ark::es2panda::parser::Program *program) : checker_(checker), program_(program), + diagnosticEngine_(checker->DiagnosticEngine()), allocator_(SpaceType::SPACE_TYPE_COMPILER, nullptr, true), objectArguments_(allocator_.Adapter()) { @@ -69,7 +71,11 @@ public: static constexpr std::string_view INDENT = " "; private: - void ThrowError(std::string_view message, const lexer::SourcePosition &pos); + void LogError(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams ¶ms, + const lexer::SourcePosition &pos); + void LogWarning(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams ¶ms, + const lexer::SourcePosition &pos); + const ir::Identifier *GetKeyIdent(const ir::Expression *key); void GenType(const checker::Type *checkerType); @@ -148,6 +154,7 @@ private: std::stringstream outputTs_; checker::ETSChecker *checker_ {}; const ark::es2panda::parser::Program *program_ {}; + util::DiagnosticEngine &diagnosticEngine_; ArenaAllocator allocator_; ArenaSet objectArguments_; DeclgenOptions declgenOptions_ {}; diff --git a/ets2panda/declgen_ets2ts/declgen_ets2ts_error.yaml b/ets2panda/declgen_ets2ts/declgen_ets2ts_error.yaml new file mode 100644 index 0000000000000000000000000000000000000000..6f730c1126aac781f3d0a664d2eee1b8b0cc1750 --- /dev/null +++ b/ets2panda/declgen_ets2ts/declgen_ets2ts_error.yaml @@ -0,0 +1,50 @@ +# Copyright (c) 2025 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. + +declgen_ets2ts_error: +- name: IDENT_KEY_SUPPORT + id: 1 + message: Only identifier keys are supported. + +- name: UNSUPPORTED_TYPE + id: 2 + message: Unsupported type {}. + +- name: UNSUPPORTED_LITERAL_TYPE + id: 3 + message: Unsupported literal type. + +- name: UNEXPECTED_NUMBER_LITERAL_TYPE + id: 4 + message: Unexpected number literal type. + +- name: NOT_OVERLOAD_SUPPORT + id: 5 + message: Method overloads are not supported. + +- name: INCORRECT_ENUM_MEMBER + id: 6 + message: Member of enum isn't of type TSEnumMember. + +- name: NOT_LITERAL_ENUM_INITIALIZER + id: 7 + message: Only literal enum initializers are supported. + +- name: IMPORT_SPECIFIERS_SUPPORT + id: 8 + message: Only import specifiers are supported. + +- name: UNSUPPORTED_LOCAL_BINDINGS + id: 9 + message: Imports with local bindings are not supported. + diff --git a/ets2panda/declgen_ets2ts/declgen_ets2ts_warning.yaml b/ets2panda/declgen_ets2ts/declgen_ets2ts_warning.yaml new file mode 100644 index 0000000000000000000000000000000000000000..610c7d89a182a2f4be5a41c73d7770f8f4d855c7 --- /dev/null +++ b/ets2panda/declgen_ets2ts/declgen_ets2ts_warning.yaml @@ -0,0 +1,21 @@ +# Copyright (c) 2025 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. + +declgen_ets2ts_warning: +- name: EMPTY_TYPE_NAME + id: 1 + message: Object type name is empty. + +- name: UNTYPED_METHOD + id: 2 + message: Untyped method encountered {}. diff --git a/ets2panda/util/diagnostic.cpp b/ets2panda/util/diagnostic.cpp index 85ed56a40487a07d719dc61a71b781cb4578a421..430991b66e31c2ef7c600f3636c927182e51b58f 100644 --- a/ets2panda/util/diagnostic.cpp +++ b/ets2panda/util/diagnostic.cpp @@ -156,6 +156,10 @@ const char *DiagnosticTypeToString(DiagnosticType type) return "Warning"; case DiagnosticType::PLUGIN: return "Plugin error"; + case DiagnosticType::DECLGEN_ETS2TS_ERROR: + return "Declgen ets2ts error"; + case DiagnosticType::DECLGEN_ETS2TS_WARNING: + return "Declgen ets2ts warning"; default: UNREACHABLE(); } @@ -206,4 +210,12 @@ Diagnostic::Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind, diagnosticParams_(FormatParams(diagnosticParams)) { } + +Diagnostic::Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind, + const util::DiagnosticMessageParams &diagnosticParams, const parser::Program *program, + const lexer::SourcePosition &poc) + : DiagnosticBase(program, poc), diagnosticKind_(&diagnosticKind), diagnosticParams_(FormatParams(diagnosticParams)) +{ +} + } // namespace ark::es2panda::util diff --git a/ets2panda/util/diagnostic.h b/ets2panda/util/diagnostic.h index 07ad69c54f0739c3e1745a565dc10168042367cc..524c887256815d173ad2307d7a1fc97d42831ce2 100644 --- a/ets2panda/util/diagnostic.h +++ b/ets2panda/util/diagnostic.h @@ -42,7 +42,18 @@ class SourceLocation; namespace ark::es2panda::util { -enum DiagnosticType { BEGIN = 0, FATAL = BEGIN, SYNTAX, SEMANTIC, WARNING, PLUGIN, COUNT = PLUGIN, INVALID }; +enum DiagnosticType { + BEGIN = 0, + FATAL = BEGIN, + SYNTAX, + SEMANTIC, + WARNING, + PLUGIN, + DECLGEN_ETS2TS_ERROR, + DECLGEN_ETS2TS_WARNING, + COUNT, + INVALID +}; const char *DiagnosticTypeToString(DiagnosticType type); class DiagnosticBase { @@ -159,6 +170,10 @@ public: explicit Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind, const util::DiagnosticMessageParams &diagnosticParams, std::string_view file = "", size_t line = 0, size_t offset = 0); + explicit Diagnostic(const diagnostic::DiagnosticKind &diagnosticKind, + const util::DiagnosticMessageParams &diagnosticParams, const parser::Program *program, + const lexer::SourcePosition &poc); + NO_COPY_SEMANTIC(Diagnostic); DEFAULT_MOVE_SEMANTIC(Diagnostic); ~Diagnostic() override = default; diff --git a/ets2panda/util/diagnostic/diagnostic.h.erb b/ets2panda/util/diagnostic/diagnostic.h.erb index 14c57a888ea78072a09c08db183a9a1decfe7442..184c12199b550226c58dbe706754302c44241ffe 100644 --- a/ets2panda/util/diagnostic/diagnostic.h.erb +++ b/ets2panda/util/diagnostic/diagnostic.h.erb @@ -58,14 +58,8 @@ private: const uint32_t id_; const std::string_view message_; }; -% error_types = { -% :syntax => 'SYNTAX', -% :semantic => 'SEMANTIC', -% :warning => 'WARNING', -% :fatal => 'FATAL' -% } % Diagnostic::diagnostics.each do |desc| - constexpr static DiagnosticKind <%= desc.name %> {util::DiagnosticType::<%= error_types[desc.type] %>, <%= desc.id %>, "<%= desc.message %>"}; + constexpr static DiagnosticKind <%= desc.name %> {util::DiagnosticType::<%= desc.type.upcase %>, <%= desc.id %>, "<%= desc.message %>"}; % end } // namespace ark::es2panda::diagnostic diff --git a/ets2panda/util/diagnosticEngine.cpp b/ets2panda/util/diagnosticEngine.cpp index 827df44bf450da127e29de7293ae564251a688e4..cde6b533aa6a230ce5b8907b6a820136cb336eee 100644 --- a/ets2panda/util/diagnosticEngine.cpp +++ b/ets2panda/util/diagnosticEngine.cpp @@ -95,8 +95,10 @@ bool DiagnosticEngine::IsError(DiagnosticType type) const case DiagnosticType::SYNTAX: case DiagnosticType::SEMANTIC: case DiagnosticType::PLUGIN: + case DiagnosticType::DECLGEN_ETS2TS_ERROR: return true; case DiagnosticType::WARNING: + case DiagnosticType::DECLGEN_ETS2TS_WARNING: return wError_; default: UNREACHABLE();