diff --git a/ets2panda/public/cppToCTypes.yaml b/ets2panda/public/cppToCTypes.yaml index 8e8f440bb0f04d4735ad0e557ee030c45452ad31..dbad89e81bbe86f8a31dd762b17df5250bc247af 100644 --- a/ets2panda/public/cppToCTypes.yaml +++ b/ets2panda/public/cppToCTypes.yaml @@ -2105,7 +2105,7 @@ change_types: namespace: "parser::" cast: expression: >- - auto |es2panda_arg.type.ptr_depth||arg_name|E2p = + auto |es2panda_arg.type.ptr_depth||arg_name|E2p = reinterpret_cast(|arg_name|); var_name: '|arg_name|E2p' reverse_cast: @@ -2135,7 +2135,7 @@ change_types: expression: auto &|arg_name|E2p = *reinterpret_cast(|arg_name|); var_name: '|arg_name|E2p' reverse_cast: - start: >- + start: >- reinterpret_cast( reinterpret_cast(context)->allocator->New( end: '))' @@ -2199,12 +2199,26 @@ change_types: type: name: 'Language' min_ptr_depth: 1 + optional: true new_args: + - type: + name: 'Es2pandaLanguage' + ptr_depth: 0 + name: '|arg_name|' + namespace: '' cast: expression: >- + auto |es2panda_arg.type.ptr_depth||arg_name|E2p = + reinterpret_cast(context)->allocator-> + New(static_cast(|arg_name|)); + default_expression: >- auto |es2panda_arg.type.ptr_depth||arg_name|E2p = reinterpret_cast(context)->allocator-> New(Language::Id::ETS); + reverse_cast: + start: >- + static_cast( + end: '->GetId())' var_name: '|arg_name|E2p' - es2panda_arg: @@ -2212,10 +2226,21 @@ change_types: type: name: 'Language' max_ptr_depth: 0 + optional: true new_args: + - type: + name: 'Es2pandaLanguage' + ptr_depth: 0 + name: '|arg_name|' + namespace: '' cast: expression: >- - ark::es2panda::Language |arg_name|E2p {Language::Id::ETS}; + ark::es2panda::Language |arg_name|E2p {static_cast(|arg_name|)}; + default_expression: ark::es2panda::Language |arg_name|E2p {Language::Id::ETS}; + reverse_cast: + start: >- + static_cast( + end: '.GetId())' var_name: '|arg_name|E2p' - es2panda_arg: @@ -3666,6 +3691,26 @@ change_types: current_class: TSInterfaceDeclaration max_ptr_depth: 0 min_ptr_depth: 0 + optional: true + default_new_args: + - name: 'id' + type: + name: es2panda_AstNode + ptr_depth: 1 + - name: 'typeParams' + type: + name: es2panda_AstNode + ptr_depth: 1 + - name: 'body' + type: + name: es2panda_AstNode + ptr_depth: 1 + - name: isStatic + type: + name: bool + - name: isExternal + type: + name: bool new_args: - name: 'id' type: @@ -3685,8 +3730,18 @@ change_types: - name: isExternal type: name: bool + - type: + name: 'Es2pandaLanguage' + ptr_depth: 0 + name: 'language' cast: expression: "\ + auto es2pandaId = reinterpret_cast(id);\n + auto es2pandaTypeParams = reinterpret_cast(typeParams);\n + auto es2pandaBody = reinterpret_cast(body);\n + ark::es2panda::Language es2pandaLang {static_cast(language)};\n + " + default_expression: "\ auto es2pandaId = reinterpret_cast(id);\n auto es2pandaTypeParams = reinterpret_cast(typeParams);\n auto es2pandaBody = reinterpret_cast(body);\n @@ -3701,6 +3756,7 @@ change_types: current_class: ScriptFunction max_ptr_depth: 0 min_ptr_depth: 0 + optional: true new_args: - name: '|arg_name|body' type: @@ -3717,16 +3773,43 @@ change_types: - name: '|arg_name|flags' type: name: int + - type: + name: 'Es2pandaLanguage' + ptr_depth: 0 + name: '|arg_name|lang' + default_new_args: + - name: '|arg_name|body' + type: + name: es2panda_AstNode + ptr_depth: 1 + - name: '|arg_name|signature' + type: + name: es2panda_FunctionSignature + ptr_depth: 1 + - name: '|arg_name|funcFlags' + type: + name: int + ptr_depth: 0 + - name: '|arg_name|flags' + type: + name: int cast: expression: " auto *|arg_name|bodyE2p = reinterpret_cast(|arg_name|body);\n auto |arg_name|signatureE2p = std::move(*reinterpret_cast(|arg_name|signature));\n auto |arg_name|funcFlagsE2p = E2pToIrScriptFunctionFlags((Es2pandaScriptFunctionFlags)|arg_name|funcFlags);\n auto |arg_name|flagsE2p = E2pToIrModifierFlags((Es2pandaModifierFlags)|arg_name|flags);\n - ark::es2panda::Language |arg_name|lang {Language::Id::ETS};\n + ark::es2panda::Language |arg_name|langE2p {static_cast(|arg_name|lang)};\n + " + default_expression: " + auto *|arg_name|bodyE2p = reinterpret_cast(|arg_name|body);\n + auto |arg_name|signatureE2p = std::move(*reinterpret_cast(|arg_name|signature));\n + auto |arg_name|funcFlagsE2p = E2pToIrScriptFunctionFlags((Es2pandaScriptFunctionFlags)|arg_name|funcFlags);\n + auto |arg_name|flagsE2p = E2pToIrModifierFlags((Es2pandaModifierFlags)|arg_name|flags);\n + ark::es2panda::Language |arg_name|langE2p {Language::Id::ETS};\n " var_name: "ir::ScriptFunction::ScriptFunctionData {|arg_name|bodyE2p, std::move(|arg_name|signatureE2p), - |arg_name|funcFlagsE2p, |arg_name|flagsE2p, |arg_name|lang}" + |arg_name|funcFlagsE2p, |arg_name|flagsE2p, |arg_name|langE2p}" - es2panda_arg: name: '|arg_name|' diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index f5380df3946cd335fc80d32f1712146182ec075c..ee4f4cb954afc6313354aaf7e9ee22b38c09b4a7 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -168,6 +168,13 @@ typedef struct es2panda_DiagnosticInfo { enum es2panda_PluginDiagnosticType { ES2PANDA_PLUGIN_WARNING, ES2PANDA_PLUGIN_ERROR, ES2PANDA_PLUGIN_SUGGESTION }; +typedef enum Es2pandaLanguage { + LANGUAGE_AS, + LANGUAGE_JS, + LANGUAGE_TS, + LANGUAGE_ETS, +} Es2pandaLanguage; + typedef enum es2panda_PluginDiagnosticType es2panda_PluginDiagnosticType; typedef enum es2panda_ContextState es2panda_ContextState; // CC-OFFNXT(G.INC.08) project code style diff --git a/ets2panda/public/es2panda_lib.rb b/ets2panda/public/es2panda_lib.rb index ea0f1efc6d44a0f9754fdd140dffeeabc902034c..f7a3fe26f232279373761f8c4098696f6725481a 100644 --- a/ets2panda/public/es2panda_lib.rb +++ b/ets2panda/public/es2panda_lib.rb @@ -33,6 +33,8 @@ module Es2pandaLibApi @is_scope_type = false @is_code_gen = false @is_decl_type = false + @is_optional = false + @default_optional = false @const = '' @base_namespace = '' @@ -245,7 +247,13 @@ module Es2pandaLibApi [found_change_type_link, err_msg] end - def initialize(arg_info, base_namespace) + def set_default_expression_cast(found_change_type) + return unless found_change_type && @is_optional && @default_optional + found_change_type.cast['expression'] = found_change_type.cast['default_expression'] + found_change_type.new_args = found_change_type.default_new_args || [] + end + + def initialize(arg_info, base_namespace, default_optional = false) found_change_type_link, err_msg = Arg.get_change_type_info_with_err_msg(arg_info) raise err_msg unless err_msg.nil? @@ -254,6 +262,7 @@ module Es2pandaLibApi @const = Arg.const(arg_info) @es2panda_arg['const'] = @const @base_namespace = base_namespace + @default_optional = default_optional @is_ast_node = Arg.is_ast_node(es2panda_arg) @is_ast_node_add_children = Arg.is_ast_node_add_children(es2panda_arg) @@ -267,6 +276,8 @@ module Es2pandaLibApi if found_change_type_link found_change_type = Marshal.load(Marshal.dump(found_change_type_link)) + @is_optional = found_change_type.es2panda_arg.respond_to?('optional') && found_change_type.es2panda_arg['optional'] + set_default_expression_cast(found_change_type) placeholders = find_placeholders(found_change_type.es2panda_arg) @@ -402,12 +413,13 @@ module Es2pandaLibApi Arg.set_const_modifier(@lib_args, @const) Arg.set_const_modifier(@idl_args, @const) - tmp = Arg.new(@lib_args[0], @base_namespace) + tmp = Arg.new(@lib_args[0], @base_namespace, @default_optional) @lib_args = tmp.lib_args @idl_args = tmp.idl_args @lib_cast = tmp.lib_cast @return_args = tmp.return_args @idl_return_args = tmp.idl_return_args + @is_optional = tmp.is_optional return if tmp.check_allowed_type(@lib_args[0]) nested_arg_transform @@ -508,6 +520,7 @@ module Es2pandaLibApi attr_reader :return_args attr_reader :idl_return_args attr_reader :const + attr_reader :is_optional def lib_args_to_str @lib_args.map do |lib_arg| @@ -806,31 +819,43 @@ module Es2pandaLibApi usings = usings_map constructor_overload = {} idl_constructor_overload = {} - dig(:constructors)&.each do |constructor| - if check_no_gen_constructor(constructor) - args = [] - begin - constructor_cast - constructor.args&.each do |arg| - arg['type'] = replace_with_usings(arg['type'], usings) - arg['type'] = add_base_namespace(arg['type']) - arg['type']['current_class'] = constructor.name - args << Arg.new(arg, class_base_namespace) + constructors = dig(:constructors) + constructors_with_optional = [] + [constructors, constructors_with_optional].each do |constructors_list| + is_with_optional_list = constructors_list == constructors_with_optional + constructors_list&.each do |constructor| + if check_no_gen_constructor(constructor) + begin + args = [] + constructor_cast + optional_args_info = [] + constructor.args&.each do |arg| + arg['type'] = replace_with_usings(arg['type'], usings) + arg['type'] = add_base_namespace(arg['type']) + arg['type']['current_class'] = constructor.name + processed_arg = Arg.new(arg, class_base_namespace, !is_with_optional_list) + if processed_arg.is_optional && !is_with_optional_list + optional_args_info << { name: arg['type']['name'] } + end + args << processed_arg + end + if !optional_args_info.empty? && !is_with_optional_list + constructors_with_optional << Marshal.load(Marshal.dump(constructor)) + end + rescue StandardError => e + error_catch_log('Constructor', constructor, e, 'Create' + class_name) + else + Es2pandaLibApi.stat_add_constructor(1, class_name, class_base_namespace, 'Create' + class_name) + Es2pandaLibApi.stat_add_class(1, class_name) + + Es2pandaLibApi.log('info', "Supported constructor for class '#{class_name}'\n") + res << { 'overload' => get_new_method_name(constructor_overload, '', ''), + 'idl_overload' => get_new_method_name(idl_constructor_overload, '', '', true), + 'args' => args, 'raw_decl' => constructor.raw_declaration } end - rescue StandardError => e - error_catch_log('Constructor', constructor, e, 'Create' + class_name) else - Es2pandaLibApi.stat_add_constructor(1, class_name, class_base_namespace, 'Create' + class_name) - Es2pandaLibApi.stat_add_class(1, class_name) - - Es2pandaLibApi.log('info', "Supported constructor for class '#{class_name}'\n") - - res << { 'overload' => get_new_method_name(constructor_overload, '', ''), - 'idl_overload' => get_new_method_name(idl_constructor_overload, '', '', true), - 'args' => args, 'raw_decl' => constructor.raw_declaration } + Es2pandaLibApi.log('info', "Banned constructor for class '#{class_name}'\n") end - else - Es2pandaLibApi.log('info', "Banned constructor for class '#{class_name}'\n") end end res @@ -985,39 +1010,52 @@ module Es2pandaLibApi template_extends.each do |template_extend| methods += Es2pandaLibApi.classes['ir'][template_extend]['methods'] end - methods.each do |method| - if check_no_gen_method(method) - begin - return_type = Type.new(add_base_namespace(replace_with_usings(method.return_type, usings)), - class_base_namespace, 'return') - const = get_const_modifier(method) - const_return = get_const_return_modifier(return_type) - - args = [] - method.args.each do |arg| - arg['type'] = add_base_namespace(replace_with_usings(arg['type'], usings)) - args << Arg.new(arg, class_base_namespace) + methods_with_optional = [] + [methods, methods_with_optional].each do |methods_list| + is_with_optional_list = methods_list == methods_with_optional + methods_list&.each do |method| + if check_no_gen_method(method) + begin + return_type = Type.new(add_base_namespace(replace_with_usings(method.return_type, usings)), + class_base_namespace, 'return') + const = get_const_modifier(method) + const_return = get_const_return_modifier(return_type) + + args = [] + optional_args_info = [] + method.args.each_with_index do |arg, arg_index| + arg['type'] = add_base_namespace(replace_with_usings(arg['type'], usings)) + processed_arg = Arg.new(arg, class_base_namespace, !is_with_optional_list) + if processed_arg.is_optional && !is_with_optional_list + optional_args_info << { name: arg['type']['name'] } + end + args << processed_arg + end + + if !optional_args_info.empty? && !is_with_optional_list + methods_with_optional << Marshal.load(Marshal.dump(method)) + end + + return_expr = get_return_expr(return_type, call_cast, [const, const_return], method, args, 'method') + rescue StandardError => e + stat_function_overload = Marshal.load(Marshal.dump(function_overload)) + error_catch_log('Method', method, e, class_name + + get_new_method_name(stat_function_overload, method.name, const)) + else + stat_function_overload = Marshal.load(Marshal.dump(function_overload)) + Es2pandaLibApi.stat_add_method(1, class_name, class_base_namespace, class_name + + get_new_method_name(stat_function_overload, method.name, const)) + Es2pandaLibApi.log('info', 'supported method: ', method.name, ' class: ', class_name, "\n") + + res << { 'name' => method.name, 'const' => const, 'return_arg_to_str' => return_type.return_args_to_str, + 'overload_name' => get_new_method_name(function_overload, method.name, const), 'args' => args, + 'idl_name' => get_new_method_name(idl_function_overload, method.name, const, true), + 'return_type' => return_type, 'return_expr' => return_expr, 'raw_decl' => method.raw_declaration, + 'const_return' => const_return, 'get_modifier' => method['additional_attributes'] } end - - return_expr = get_return_expr(return_type, call_cast, [const, const_return], method, args, 'method') - rescue StandardError => e - stat_function_overload = Marshal.load(Marshal.dump(function_overload)) - error_catch_log('Method', method, e, class_name + - get_new_method_name(stat_function_overload, method.name, const)) else - stat_function_overload = Marshal.load(Marshal.dump(function_overload)) - Es2pandaLibApi.stat_add_method(1, class_name, class_base_namespace, class_name + - get_new_method_name(stat_function_overload, method.name, const)) - Es2pandaLibApi.log('info', 'supported method: ', method.name, ' class: ', class_name, "\n") - - res << { 'name' => method.name, 'const' => const, 'return_arg_to_str' => return_type.return_args_to_str, - 'overload_name' => get_new_method_name(function_overload, method.name, const), 'args' => args, - 'idl_name' => get_new_method_name(idl_function_overload, method.name, const, true), - 'return_type' => return_type, 'return_expr' => return_expr, 'raw_decl' => method.raw_declaration, - 'const_return' => const_return, 'get_modifier' => method['additional_attributes'] } + Es2pandaLibApi.log('info', "Banned method\n") end - else - Es2pandaLibApi.log('info', "Banned method\n") end end res @@ -1380,6 +1418,7 @@ module Es2pandaLibApi es2panda_OverloadInfo es2panda_JsDocRecord es2panda_JsDocInfo + Es2pandaLanguage ] end diff --git a/ets2panda/public/ignoredAllowed.yaml b/ets2panda/public/ignoredAllowed.yaml index ec92b68d4549a4df1b0aca010da5aeb809d6c77e..3ef50f712b9588743e4293a88f1d3aba90c2f36a 100644 --- a/ets2panda/public/ignoredAllowed.yaml +++ b/ets2panda/public/ignoredAllowed.yaml @@ -96,7 +96,6 @@ ignored_list: - name: optional namespace: std - name: WrapperDesc - - name: Language - name: ScopedDebugInfoPlugin - name: Args namespace: parser diff --git a/ets2panda/test/unit/plugin/CMakeLists.txt b/ets2panda/test/unit/plugin/CMakeLists.txt index 2725a2a434a2f69048fcf82822f4a6c8cad108ad..aa37bfe93c77a685c6c457c891218771d7119141 100644 --- a/ets2panda/test/unit/plugin/CMakeLists.txt +++ b/ets2panda/test/unit/plugin/CMakeLists.txt @@ -113,6 +113,7 @@ set(PLUGIN_TESTS "plugin_proceed_to_state_test_case_block_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_function_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "pugin_proceed_to_state_annotationUsage_source_range_access compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" + "plugin_proceed_to_state_optional_language compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" ) set(RUNTIME_ARGUMENTS diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_optional_language.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_optional_language.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e237cdde7011237f3b06e1771ef51181951c7f52 --- /dev/null +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_optional_language.cpp @@ -0,0 +1,55 @@ +/** + * 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. + */ + +#include "util.h" +#include "public/es2panda_lib.h" + +// NOLINTBEGIN + +static es2panda_Impl *impl = nullptr; +static auto source = std::string("function main() { \nlet a = 5;\n arktest.assertEQ(a, 5);\n }"); + +static bool CheckLanguageOptionalArg(es2panda_Context *context) +{ + auto ident = impl->CreateIdentifier(context); + auto implicitEtsClassDef = + impl->CreateClassDefinition2(context, ident, Es2pandaClassDefinitionModifiers::CLASS_DEFINITION_MODIFIERS_NONE, + Es2pandaModifierFlags::MODIFIER_FLAGS_NONE); + auto explicitEtsClassDef = + impl->CreateClassDefinition5(context, ident, Es2pandaClassDefinitionModifiers::CLASS_DEFINITION_MODIFIERS_NONE, + Es2pandaModifierFlags::MODIFIER_FLAGS_NONE, Es2pandaLanguage::LANGUAGE_ETS); + auto explicitJSClassDef = + impl->CreateClassDefinition5(context, ident, Es2pandaClassDefinitionModifiers::CLASS_DEFINITION_MODIFIERS_NONE, + Es2pandaModifierFlags::MODIFIER_FLAGS_NONE, Es2pandaLanguage::LANGUAGE_JS); + if (implicitEtsClassDef == nullptr || explicitEtsClassDef == nullptr) { + return false; + } + if (impl->ClassDefinitionLanguageConst(context, explicitEtsClassDef) != Es2pandaLanguage::LANGUAGE_ETS || + impl->ClassDefinitionLanguageConst(context, implicitEtsClassDef) != Es2pandaLanguage::LANGUAGE_ETS || + impl->ClassDefinitionLanguageConst(context, explicitJSClassDef) != Es2pandaLanguage::LANGUAGE_JS) { + return false; + } + return true; +} + +int main(int argc, char **argv) +{ + std::map>> testFunctions; + testFunctions[ES2PANDA_STATE_CHECKED] = {CheckLanguageOptionalArg}; + ProccedToStatePluginTestData data = {argc, argv, &impl, testFunctions, true, source}; + return RunAllStagesWithTestFunction(data); +} + +// NOLINTEND