From 9e83e8bd191b36aec6317b48afcc527632379fb1 Mon Sep 17 00:00:00 2001 From: zengzengran Date: Tue, 10 Jun 2025 15:18:36 +0800 Subject: [PATCH 1/3] Implement overload declaration Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICFDGM Description: 1. Create ASTNode ir::OverloadDeclaration and perform scope initialization. 2. Check ir::OverloadDeclaration. 3. Implement first match (currently only for OverloadDeclaration call, current overload cannot be removed for the time). If the match fails, clear the TypeError and ASTNode check information. Tested-by: ninja tests (passed) ets_testrunner (passed) Signed-off-by: zengzengran Signed-off-by: tengtengh --- ets2panda/BUILD.gn | 24 +- ets2panda/CMakeLists.txt | 2 + .../ast_verifier/invariants/nodeHasType.cpp | 3 +- ets2panda/checker/ETSAnalyzer.cpp | 92 +++++ ets2panda/checker/ETSchecker.h | 35 ++ ets2panda/checker/SemanticAnalyzer.h | 1 + ets2panda/checker/TSAnalyzerUnreachable.cpp | 5 + ets2panda/checker/checker.h | 36 ++ ets2panda/checker/ets/function.cpp | 333 +++++++++++++++++- ets2panda/checker/ets/helpers.cpp | 10 + ets2panda/checker/ets/object.cpp | 124 +++++-- ets2panda/checker/ets/typeCheckingHelpers.cpp | 200 +++++++++++ ets2panda/checker/ets/validateHelpers.cpp | 4 + ets2panda/checker/types/ets/etsObjectType.cpp | 206 +++++++---- ets2panda/checker/types/ets/etsObjectType.h | 15 +- .../compiler/core/ETSCompilerUnrechable.cpp | 5 + ets2panda/compiler/core/ETSemitter.cpp | 43 +++ ets2panda/compiler/core/ETSemitter.h | 1 + .../compiler/core/JSCompilerUnreachable.cpp | 5 + ...defaultParametersInConstructorLowering.cpp | 2 +- .../ets/interfaceObjectLiteralLowering.cpp | 7 + .../compiler/lowering/ets/lambdaLowering.cpp | 15 +- .../lowering/ets/overloadMappingLowering.cpp | 83 +++++ .../lowering/ets/overloadMappingLowering.h | 31 ++ .../lowering/ets/restTupleLowering.cpp | 2 +- .../topLevelStmts/globalDeclTransformer.cpp | 5 + .../ets/topLevelStmts/globalDeclTransformer.h | 1 + .../ets/topLevelStmts/importExportDecls.cpp | 5 + .../ets/topLevelStmts/importExportDecls.h | 1 + ets2panda/compiler/lowering/phase.cpp | 2 + .../lowering/scopesInit/scopesInitPhase.cpp | 117 +++++- .../lowering/scopesInit/scopesInitPhase.h | 3 + ets2panda/compiler/scripts/signatures.yaml | 7 + ets2panda/ir/astNode.cpp | 13 +- ets2panda/ir/astNode.h | 2 + ets2panda/ir/astNodeFlags.h | 14 +- ets2panda/ir/astNodeMapping.h | 1 + ets2panda/ir/base/methodDefinition.cpp | 5 + ets2panda/ir/base/overloadDeclaration.cpp | 134 +++++++ ets2panda/ir/base/overloadDeclaration.h | 140 ++++++++ ets2panda/ir/base/scriptFunction.h | 5 + .../ir/ets/etsNewArrayInstanceExpression.cpp | 9 + .../ir/ets/etsNewArrayInstanceExpression.h | 1 + .../etsNewMultiDimArrayInstanceExpression.cpp | 9 + .../etsNewMultiDimArrayInstanceExpression.h | 1 + ets2panda/ir/ets/etsUnionType.cpp | 2 + ets2panda/ir/expressions/arrayExpression.cpp | 10 + ets2panda/ir/expressions/arrayExpression.h | 1 + ets2panda/ir/expressions/memberExpression.cpp | 5 + ets2panda/ir/expressions/objectExpression.cpp | 7 + ets2panda/ir/expressions/objectExpression.h | 2 + ets2panda/ir/opaqueTypeNode.cpp | 3 + ets2panda/ir/opaqueTypeNode.h | 1 + ets2panda/lexer/scripts/keywords.yaml | 4 + ets2panda/parser/ETSparser.cpp | 91 ++++- ets2panda/parser/ETSparser.h | 6 + ets2panda/parser/ETSparserClasses.cpp | 81 ++++- ets2panda/parser/ETSparserStatements.cpp | 4 + ets2panda/parser/parserImpl.cpp | 2 +- ets2panda/public/CMakeLists.txt | 2 + .../public/headers_parser/supported_types.py | 1 + .../ets/first_match/abstract_method.ets | 23 ++ .../ets/first_match/access_modifiers.ets | 50 +++ .../ets/first_match/access_modifiers_2.ets | 36 ++ .../compiler/ets/first_match/arrayliteral.ets | 39 ++ .../compiler/ets/first_match/constructor.ets | 52 +++ .../ets/first_match/invalid_declaration.ets | 33 ++ .../ets/first_match/invalid_declaration_2.ets | 31 ++ .../ets/first_match/invalid_declaration_3.ets | 25 ++ .../ets/first_match/invalid_declaration_4.ets | 23 ++ .../ets/first_match/invalid_identifier.ets | 52 +++ .../ets/first_match/invalid_paramter.ets | 40 +++ .../ets/first_match/modifier_async.ets | 29 ++ .../ets/first_match/modifier_static.ets | 29 ++ .../ast/compiler/ets/first_match/override.ets | 39 ++ .../class_overloaded_name_must_ident.ets | 24 ++ ...constructor_overloaded_name_must_ident.ets | 24 ++ ...on_overloaded_name_must_qualified_name.ets | 26 ++ .../interface_overloaded_name_must_ident.ets | 23 ++ .../overload/overload_duplicate_function.ets | 33 ++ .../overload_duplicate_function_2.ets | 37 ++ .../overload/overload_duplicate_method.ets | 34 ++ .../overload_duplicate_overload_name_1.ets | 26 ++ .../overload/overload_from_super_class.ets | 26 ++ .../overload_overloaded_method_exported.ets | 20 ++ ...verload_overloaded_name_at_most_once_1.ets | 31 ++ ...erload_overloaded_name_used_as_value_1.ets | 27 ++ ...erload_overloaded_name_used_as_value_2.ets | 27 ++ .../ets/overload/overload_union_call.ets | 38 ++ .../ets/overload/overload_union_call_2.ets | 35 ++ .../parser/ets/overload_class_method_test.ets | 33 ++ .../ast/parser/ets/overload_constructor.ets | 34 ++ ...verload_global_function_our_style_test.ets | 32 ++ .../ets/overload_interface_method_test.ets | 25 ++ .../overload_modifier_overloaddefinition.ets | 64 ++++ .../ets/first_match/access_modifiers.ets | 50 +++ .../test/runtime/ets/first_match/array.ets | 45 +++ .../ets/first_match/array_and_tuple.ets | 42 +++ .../first_match/ctor_need_fix_bytecode.ets | 59 ++++ .../test/runtime/ets/first_match/enum.ets | 90 +++++ .../test/runtime/ets/first_match/enum2.ets | 35 ++ .../function_need_fix_variable.ets | 39 ++ .../test/runtime/ets/first_match/generics.ets | 50 +++ .../runtime/ets/first_match/generics_2.ets | 44 +++ .../runtime/ets/first_match/lambda_infer.ets | 44 +++ .../runtime/ets/first_match/lambda_order.ets | 51 +++ .../ets/first_match/lambda_type_alias.ets | 46 +++ .../runtime/ets/first_match/namespace.ets | 35 ++ .../runtime/ets/first_match/namespace2.ets | 46 +++ .../runtime/ets/first_match/namespace3.ets | 44 +++ .../first_match/objectliteral_optional.ets | 69 ++++ .../ets/first_match/objectliteral_order.ets | 48 +++ .../ets/first_match/objectliteral_same.ets | 53 +++ .../ets/first_match/optinal_parameter.ets | 47 +++ .../ets/first_match/override_class.ets | 48 +++ .../ets/first_match/override_interface.ets | 55 +++ .../runtime/ets/first_match/primitive.ets | 48 +++ .../ets/first_match/rest_parameter.ets | 52 +++ .../ets/first_match/static_and_nonstatic.ets | 42 +++ .../runtime/ets/first_match/stringliteral.ets | 35 ++ .../ets/first_match/trailing_lambda.ets | 53 +++ .../test/runtime/ets/first_match/union.ets | 43 +++ .../ets/overload_declaration/15445.ets | 36 ++ .../ets/overload_declaration/15502.ets | 36 ++ .../ets/overload_declaration/Enum2.ets | 61 ++++ .../FirstMatchSignature01.ets | 28 ++ .../FirstMatchSignature02.ets | 28 ++ .../FirstMatchSignature03.ets | 28 ++ .../FirstMatchSignature04.ets | 28 ++ .../FirstMatchSignature05.ets | 32 ++ .../FirstMatchSignature06.ets | 32 ++ .../FirstMatchSignature07.ets | 33 ++ .../overload_declaration/FixFunctionCall.ets | 27 ++ .../overload_declaration/FunctionOverload.ets | 44 +++ .../InterfacePrivateMethod2.ets | 43 +++ .../ets/overload_declaration/RestTuple4.ets | 47 +++ .../ets/overload_declaration/RestTuple8.ets | 47 +++ .../ets/overload_declaration/SmartCast_03.ets | 74 ++++ .../async-func-overload-and-type-infer.ets | 41 +++ .../async_method_with_same_name02.ets | 31 ++ .../conditionalExpressionLUB.ets | 94 +++++ .../constructor-issue.ets | 61 ++++ ...constructor_overload_sig_with_ref_type.ets | 41 +++ .../default_parameter1.ets | 28 ++ .../first_match_method_with_rest_param_2.ets | 27 ++ .../first_match_method_with_rest_param_3.ets | 21 ++ .../ets/overload_declaration/generic-set.ets | 96 +++++ .../keyword_get_set_as_identfier2.ets | 31 ++ .../ets/overload_declaration/notNull.ets | 169 +++++++++ .../overload_declaration/objectLiteral.ets | 75 ++++ .../overload-primitive-and-object.ets | 41 +++ .../overload-resolution-rest-1.ets | 37 ++ .../overload-resolution-rest-2.ets | 28 ++ .../ets/overload_declaration/overload_1.ets | 25 ++ .../overload_declaration/overload_call_1.ets | 39 ++ .../signature_match_lambda.ets | 43 +++ .../visible_signatures.ets | 59 ++++ ets2panda/util/diagnostic/semantic.yaml | 40 +++ ets2panda/util/diagnostic/syntax.yaml | 12 + ets2panda/util/diagnosticEngine.cpp | 23 ++ ets2panda/util/diagnosticEngine.h | 8 + ets2panda/varbinder/ETSBinder.cpp | 13 +- ets2panda/varbinder/ETSBinder.h | 1 + ets2panda/varbinder/variableFlags.h | 1 + 164 files changed, 6001 insertions(+), 122 deletions(-) create mode 100644 ets2panda/compiler/lowering/ets/overloadMappingLowering.cpp create mode 100644 ets2panda/compiler/lowering/ets/overloadMappingLowering.h create mode 100644 ets2panda/ir/base/overloadDeclaration.cpp create mode 100644 ets2panda/ir/base/overloadDeclaration.h create mode 100644 ets2panda/test/ast/compiler/ets/first_match/abstract_method.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/access_modifiers.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/access_modifiers_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/arrayliteral.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/constructor.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/invalid_declaration.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_3.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_4.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/invalid_identifier.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/invalid_paramter.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/modifier_async.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/modifier_static.ets create mode 100644 ets2panda/test/ast/compiler/ets/first_match/override.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/class_overloaded_name_must_ident.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/constructor_overloaded_name_must_ident.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/function_overloaded_name_must_qualified_name.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/interface_overloaded_name_must_ident.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_duplicate_function.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_duplicate_function_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_duplicate_method.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_duplicate_overload_name_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_from_super_class.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_overloaded_method_exported.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_at_most_once_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_used_as_value_1.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_used_as_value_2.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_union_call.ets create mode 100644 ets2panda/test/ast/compiler/ets/overload/overload_union_call_2.ets create mode 100644 ets2panda/test/ast/parser/ets/overload_class_method_test.ets create mode 100644 ets2panda/test/ast/parser/ets/overload_constructor.ets create mode 100644 ets2panda/test/ast/parser/ets/overload_global_function_our_style_test.ets create mode 100644 ets2panda/test/ast/parser/ets/overload_interface_method_test.ets create mode 100644 ets2panda/test/ast/parser/ets/overload_modifier_overloaddefinition.ets create mode 100644 ets2panda/test/runtime/ets/first_match/access_modifiers.ets create mode 100644 ets2panda/test/runtime/ets/first_match/array.ets create mode 100644 ets2panda/test/runtime/ets/first_match/array_and_tuple.ets create mode 100644 ets2panda/test/runtime/ets/first_match/ctor_need_fix_bytecode.ets create mode 100644 ets2panda/test/runtime/ets/first_match/enum.ets create mode 100644 ets2panda/test/runtime/ets/first_match/enum2.ets create mode 100644 ets2panda/test/runtime/ets/first_match/function_need_fix_variable.ets create mode 100644 ets2panda/test/runtime/ets/first_match/generics.ets create mode 100644 ets2panda/test/runtime/ets/first_match/generics_2.ets create mode 100644 ets2panda/test/runtime/ets/first_match/lambda_infer.ets create mode 100644 ets2panda/test/runtime/ets/first_match/lambda_order.ets create mode 100644 ets2panda/test/runtime/ets/first_match/lambda_type_alias.ets create mode 100644 ets2panda/test/runtime/ets/first_match/namespace.ets create mode 100644 ets2panda/test/runtime/ets/first_match/namespace2.ets create mode 100644 ets2panda/test/runtime/ets/first_match/namespace3.ets create mode 100644 ets2panda/test/runtime/ets/first_match/objectliteral_optional.ets create mode 100644 ets2panda/test/runtime/ets/first_match/objectliteral_order.ets create mode 100644 ets2panda/test/runtime/ets/first_match/objectliteral_same.ets create mode 100644 ets2panda/test/runtime/ets/first_match/optinal_parameter.ets create mode 100644 ets2panda/test/runtime/ets/first_match/override_class.ets create mode 100644 ets2panda/test/runtime/ets/first_match/override_interface.ets create mode 100644 ets2panda/test/runtime/ets/first_match/primitive.ets create mode 100644 ets2panda/test/runtime/ets/first_match/rest_parameter.ets create mode 100644 ets2panda/test/runtime/ets/first_match/static_and_nonstatic.ets create mode 100644 ets2panda/test/runtime/ets/first_match/stringliteral.ets create mode 100644 ets2panda/test/runtime/ets/first_match/trailing_lambda.ets create mode 100644 ets2panda/test/runtime/ets/first_match/union.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/15445.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/15502.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/Enum2.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature01.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature02.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature03.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature04.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature05.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature06.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature07.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FixFunctionCall.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/FunctionOverload.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/InterfacePrivateMethod2.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/RestTuple4.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/RestTuple8.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/SmartCast_03.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/async-func-overload-and-type-infer.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/async_method_with_same_name02.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/conditionalExpressionLUB.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/constructor-issue.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/constructor_overload_sig_with_ref_type.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/default_parameter1.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/first_match_method_with_rest_param_2.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/first_match_method_with_rest_param_3.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/generic-set.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/keyword_get_set_as_identfier2.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/notNull.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/objectLiteral.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/overload-primitive-and-object.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/overload-resolution-rest-1.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/overload-resolution-rest-2.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/overload_1.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/overload_call_1.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/signature_match_lambda.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/visible_signatures.ets diff --git a/ets2panda/BUILD.gn b/ets2panda/BUILD.gn index 6d25361c19..d1471136ff 100644 --- a/ets2panda/BUILD.gn +++ b/ets2panda/BUILD.gn @@ -103,6 +103,7 @@ libes2panda_sources = [ "checker/types/ets/byteType.cpp", "checker/types/ets/charType.cpp", "checker/types/ets/doubleType.cpp", + "checker/types/ets/etsAnyType.cpp", "checker/types/ets/etsArrayType.cpp", "checker/types/ets/etsAsyncFuncReturnType.cpp", "checker/types/ets/etsBigIntType.cpp", @@ -127,7 +128,6 @@ libes2panda_sources = [ "checker/types/ets/intType.cpp", "checker/types/ets/longType.cpp", "checker/types/ets/shortType.cpp", - "checker/types/ets/etsAnyType.cpp", "checker/types/ets/wildcardType.cpp", "checker/types/globalTypesHolder.cpp", "checker/types/gradualType.cpp", @@ -206,6 +206,8 @@ libes2panda_sources = [ "compiler/function/generatorFunctionBuilder.cpp", "compiler/lowering/checkerPhase.cpp", "compiler/lowering/ets/ambientLowering.cpp", + "compiler/lowering/ets/annotationCopyLowering.cpp", + "compiler/lowering/ets/annotationCopyPostLowering.cpp", "compiler/lowering/ets/arrayLiteralLowering.cpp", "compiler/lowering/ets/asyncMethodLowering.cpp", "compiler/lowering/ets/bigintLowering.cpp", @@ -218,6 +220,7 @@ libes2panda_sources = [ "compiler/lowering/ets/declGenPhase.cpp", "compiler/lowering/ets/defaultParametersInConstructorLowering.cpp", "compiler/lowering/ets/defaultParametersLowering.cpp", + "compiler/lowering/ets/dynamicImport.cpp", "compiler/lowering/ets/enumLowering.cpp", "compiler/lowering/ets/enumPostCheckLowering.cpp", "compiler/lowering/ets/enumPropertiesInAnnotationsLowering.cpp", @@ -230,9 +233,8 @@ libes2panda_sources = [ "compiler/lowering/ets/insertOptionalParametersAnnotation.cpp", "compiler/lowering/ets/interfaceObjectLiteralLowering.cpp", "compiler/lowering/ets/interfacePropertyDeclarations.cpp", - "compiler/lowering/ets/lateInitialization.cpp", "compiler/lowering/ets/lambdaLowering.cpp", - "compiler/lowering/ets/dynamicImport.cpp", + "compiler/lowering/ets/lateInitialization.cpp", "compiler/lowering/ets/localClassLowering.cpp", "compiler/lowering/ets/objectIndexAccess.cpp", "compiler/lowering/ets/objectIterator.cpp", @@ -240,6 +242,7 @@ libes2panda_sources = [ "compiler/lowering/ets/opAssignment.cpp", "compiler/lowering/ets/optionalArgumentsLowering.cpp", "compiler/lowering/ets/optionalLowering.cpp", + "compiler/lowering/ets/overloadMappingLowering.cpp", "compiler/lowering/ets/packageImplicitImport.cpp", "compiler/lowering/ets/partialExportClassGen.cpp", "compiler/lowering/ets/primitiveConversionPhase.cpp", @@ -260,8 +263,6 @@ libes2panda_sources = [ "compiler/lowering/ets/typeFromLowering.cpp", "compiler/lowering/ets/unboxLowering.cpp", "compiler/lowering/ets/unionLowering.cpp", - "compiler/lowering/ets/annotationCopyLowering.cpp", - "compiler/lowering/ets/annotationCopyPostLowering.cpp", "compiler/lowering/phase.cpp", "compiler/lowering/plugin_phase.cpp", "compiler/lowering/resolveIdentifiers.cpp", @@ -294,6 +295,7 @@ libes2panda_sources = [ "ir/base/decorator.cpp", "ir/base/metaProperty.cpp", "ir/base/methodDefinition.cpp", + "ir/base/overloadDeclaration.cpp", "ir/base/property.cpp", "ir/base/scriptFunction.cpp", "ir/base/scriptFunctionSignature.cpp", @@ -727,6 +729,7 @@ HEADERS_TO_BE_PARSED = [ "ir/ts/tsImportEqualsDeclaration.h", "ir/validationInfo.h", "ir/base/methodDefinition.h", + "ir/base/overloadDeclaration.h", "ir/ts/tsIntersectionType.h", "checker/types/ts/nullType.h", "checker/types/ts/unknownType.h", @@ -782,7 +785,7 @@ HEADERS_TO_BE_PARSED = [ "ast_verifier/ASTVerifier.h", "util/importPathManager.h", "util/path.h", - "util/arktsconfig.h" + "util/arktsconfig.h", ] ES2PANDA_API_GENERATED = [ @@ -975,6 +978,7 @@ ES2PANDA_API_GENERATED = [ "$LIBGEN_DIR/gen/headers/ir/expressions/directEvalExpression.yaml", "$LIBGEN_DIR/gen/headers/ir/ts/tsTypeParameterDeclaration.yaml", "$LIBGEN_DIR/gen/headers/ir/base/methodDefinition.yaml", + "$LIBGEN_DIR/gen/headers/ir/base/overloadDeclaration.yaml", "$LIBGEN_DIR/gen/headers/ir/ts/tsNullKeyword.yaml", "$LIBGEN_DIR/gen/headers/ir/ts/tsInterfaceHeritage.yaml", "$LIBGEN_DIR/gen/headers/checker/types/ts/enumLiteralType.yaml", @@ -1050,7 +1054,7 @@ ES2PANDA_API_GENERATED = [ "$LIBGEN_DIR/gen/headers/ast_verifier/ASTVerifier.yaml", "$LIBGEN_DIR/gen/headers/util/importPathManager.yaml", "$LIBGEN_DIR/gen/headers/util/path.yaml", - "$LIBGEN_DIR/gen/headers/util/arktsconfig.yaml" + "$LIBGEN_DIR/gen/headers/util/arktsconfig.yaml", ] ES2PANDA_API = [ @@ -1068,9 +1072,9 @@ action("libes2panda_public_parse_headers") { script = "./public/headers_parser/main.py" deps = [ + ":check_build_system_consistency", ":es2panda_options_gen_options_h", ":gen_es2panda_lexer_tokenType_h", - ":check_build_system_consistency", ] generated_headers = [ @@ -1110,8 +1114,8 @@ ark_gen("gen") { # libes2panda does not include bytecode optimizer, because it is used in # libarkruntime, and conflict with JIT setup ensues libes2panda_public_sources = [ - "declgen_ets2ts/isolatedDeclgenChecker.cpp", "declgen_ets2ts/declgenEts2Ts.cpp", + "declgen_ets2ts/isolatedDeclgenChecker.cpp", "public/${LIB_NAME}.cpp", "util/generateBin.cpp", "util/options.cpp", @@ -1163,10 +1167,10 @@ ohos_source_set("libes2panda_frontend_static") { ":es2panda_options_gen_options_h", ":gen_${LIB_NAME}_decl_inc", ":gen_${LIB_NAME}_enums_inc", + ":gen_${LIB_NAME}_idl", ":gen_${LIB_NAME}_impl_inc", ":gen_${LIB_NAME}_include_inc", ":gen_${LIB_NAME}_list_inc", - ":gen_${LIB_NAME}_idl", ":gen_es2panda_compiler_signatures_h", ":gen_es2panda_lexer_keywords_h", ":gen_es2panda_lexer_tokenType_h", diff --git a/ets2panda/CMakeLists.txt b/ets2panda/CMakeLists.txt index c53de4f112..1f0676370b 100644 --- a/ets2panda/CMakeLists.txt +++ b/ets2panda/CMakeLists.txt @@ -308,6 +308,7 @@ set(ES2PANDA_LIB_SRC compiler/lowering/ets/unionLowering.cpp compiler/lowering/ets/optionalArgumentsLowering.cpp compiler/lowering/ets/optionalLowering.cpp + compiler/lowering/ets/overloadMappingLowering.cpp compiler/lowering/ets/expandBrackets.cpp compiler/lowering/ets/packageImplicitImport.cpp compiler/lowering/ets/partialExportClassGen.cpp @@ -342,6 +343,7 @@ set(ES2PANDA_LIB_SRC ir/base/decorator.cpp ir/base/metaProperty.cpp ir/base/methodDefinition.cpp + ir/base/overloadDeclaration.cpp ir/base/property.cpp ir/base/scriptFunction.cpp ir/base/scriptFunctionSignature.cpp diff --git a/ets2panda/ast_verifier/invariants/nodeHasType.cpp b/ets2panda/ast_verifier/invariants/nodeHasType.cpp index 4cfa95f5ca..e9f4d335a7 100644 --- a/ets2panda/ast_verifier/invariants/nodeHasType.cpp +++ b/ets2panda/ast_verifier/invariants/nodeHasType.cpp @@ -38,7 +38,8 @@ public: { return nulltypeNode_->IsIdentifier() || MatchFunctionExpression() || nulltypeNode_->IsTSClassImplements() || nulltypeNode_->IsSpreadElement() || nulltypeNode_->IsTSThisType() || nulltypeNode_->IsETSNullType() || - nulltypeNode_->IsStringLiteral() || AnyChildStringLiteral(); + nulltypeNode_->IsStringLiteral() || AnyChildStringLiteral() || nulltypeNode_->IsOverloadDeclaration() || + nulltypeNode_->IsProperty(); } auto ShouldSkipSubtree() const diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 951f221722..d2febf0224 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -23,6 +23,7 @@ #include "evaluate/scopedDebugInfoPlugin.h" #include "types/signature.h" #include "compiler/lowering/ets/setJumpTarget.h" +#include "compiler/lowering/util.h" #include "checker/types/ets/etsAsyncFuncReturnType.h" #include "types/ts/nullType.h" #include "types/type.h" @@ -309,6 +310,77 @@ void ETSAnalyzer::CheckMethodModifiers(ir::MethodDefinition *node) const } } +static void CheckDuplicationInOverloadDeclaration(ETSChecker *const checker, ir::OverloadDeclaration *const node) +{ + auto overloadedNameSet = ArenaSet(checker->ProgramAllocator()->Adapter()); + for (ir::Expression *const overloadedName : node->OverloadedList()) { + bool isQualifiedName = true; + std::function getFullOverloadedName = + [&isQualifiedName, &getFullOverloadedName](ir::Expression *const expr) -> std::string { + if (!isQualifiedName) { + return ""; + } + if (expr->IsIdentifier()) { + return expr->AsIdentifier()->Name().Mutf8(); + } + if (expr->IsMemberExpression()) { + return getFullOverloadedName(expr->AsMemberExpression()->Object()) + "." + + getFullOverloadedName(expr->AsMemberExpression()->Property()); + } + isQualifiedName = false; + return ""; + }; + std::string fullOverloadedName = getFullOverloadedName(overloadedName); + if (!isQualifiedName) { + continue; + } + if (overloadedNameSet.find(fullOverloadedName) != overloadedNameSet.end()) { + checker->LogError(diagnostic::DUPLICATE_OVERLOADED_NAME, overloadedName->Start()); + continue; + } + overloadedNameSet.insert(fullOverloadedName); + } +} + +checker::Type *ETSAnalyzer::Check(ir::OverloadDeclaration *node) const +{ + ETSChecker *checker = GetETSChecker(); + ES2PANDA_ASSERT(node != nullptr); + ES2PANDA_ASSERT(node->Key()); + + CheckDuplicationInOverloadDeclaration(checker, node); + + if (!node->Key()->IsIdentifier()) { + checker->LogError(diagnostic::OVERLOAD_NAME_MUST_BE_IDENTIFIER, {}, node->Key()->Start()); + } + + if (node->IsConstructorOverloadDeclaration()) { + ES2PANDA_ASSERT(node->Parent()->IsClassDefinition()); + checker->CheckConstructorOverloadDeclaration(checker, node); + return nullptr; + } + + if (node->IsFunctionOverloadDeclaration()) { + ES2PANDA_ASSERT(node->Parent()->IsClassDefinition() && compiler::HasGlobalClassParent(node)); + checker->CheckFunctionOverloadDeclaration(checker, node); + return nullptr; + } + + if (node->IsClassMethodOverloadDeclaration()) { + ES2PANDA_ASSERT(node->Parent()->IsClassDefinition()); + checker->CheckClassMethodOverloadDeclaration(checker, node); + return nullptr; + } + + if (node->IsInterfaceMethodOverloadDeclaration()) { + ES2PANDA_ASSERT(node->Parent()->Parent()->IsTSInterfaceDeclaration()); + checker->CheckInterfaceMethodOverloadDeclaration(checker, node); + return nullptr; + } + + return nullptr; +} + checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::Property *expr) const { ETSChecker *checker = GetETSChecker(); @@ -1335,6 +1407,18 @@ static bool LambdaIsField(ir::CallExpression *expr) return me->PropVar() != nullptr; } +static bool OverloadDeclaration(ir::Expression *expr) +{ + while (expr->IsMemberExpression()) { + expr = expr->AsMemberExpression()->Property(); + } + + if (expr->IsIdentifier() && expr->AsIdentifier()->Variable() != nullptr) { + return expr->AsIdentifier()->Variable()->HasFlag(varbinder::VariableFlags::OVERLOAD); + } + return false; +} + checker::Signature *ETSAnalyzer::ResolveSignature(ETSChecker *checker, ir::CallExpression *expr, checker::Type *calleeType) const { @@ -1348,6 +1432,10 @@ checker::Signature *ETSAnalyzer::ResolveSignature(ETSChecker *checker, ir::CallE return checker->ResolveCallExpressionAndTrailingLambda(checker->GetOverloadSigContainer(), expr, expr->Start()); } + if (calleeType->IsETSFunctionType() && OverloadDeclaration(expr->Callee())) { + return checker->FirstMatchSignatures(expr, calleeType); + } + if (calleeType->IsETSExtensionFuncHelperType()) { auto *signature = ResolveCallForETSExtensionFuncHelperType(calleeType->AsETSExtensionFuncHelperType(), checker, expr); @@ -1400,6 +1488,7 @@ Type *ETSAnalyzer::GetReturnType(ir::CallExpression *expr, Type *calleeType) con } Signature *const signature = ResolveSignature(checker, expr, calleeType); + if (signature == nullptr) { return checker->GlobalTypeError(); } @@ -1682,6 +1771,9 @@ static Type *TransformTypeForMethodReference(ETSChecker *checker, ir::Expression if (expr->Parent()->IsCallExpression() && expr->Parent()->AsCallExpression()->Callee() == expr) { return type; // type is actually used as method } + if (expr->Parent()->IsOverloadDeclaration()) { + return type; // Don't trans overloaded name to arrow type. + } auto *const functionType = type->AsETSFunctionType(); auto &signatures = functionType->CallSignatures(); diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index a66869952a..ed6580fb88 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -273,6 +273,8 @@ public: void CheckCyclicConstructorCall(Signature *signature); std::vector ResolveMemberReference(const ir::MemberExpression *memberExpr, const ETSObjectType *target); + varbinder::LocalVariable *ResolveOverloadReference(const ir::Identifier *ident, ETSObjectType *objType, + PropertySearchFlags searchFlags); void WarnForEndlessLoopInGetterSetter(const ir::MemberExpression *const memberExpr); varbinder::Variable *GetExtensionFuncVarInGlobalFunction(const ir::MemberExpression *const memberExpr); varbinder::Variable *GetExtensionFuncVarInGlobalField(const ir::MemberExpression *const memberExpr); @@ -477,6 +479,31 @@ public: TypeRelationFlag flags, bool reportError, bool unique); void ThrowSignatureMismatch(ArenaVector &signatures, const ArenaVector &arguments, const lexer::SourcePosition &pos, std::string_view signatureKind); + Signature *FirstMatchSignatures(ir::CallExpression *expr, checker::Type *calleeType); + Signature *MatchOrderSignatures(ArenaVector &signatures, + const ir::TSTypeParameterInstantiation *typeArguments, + const ArenaVector &arguments, const lexer::SourcePosition &pos, + TypeRelationFlag resolveFlags); + void CleanArgumentsInformation(const ArenaVector &arguments); + Signature *ValidateOrderSignature( + std::tuple info, + const ArenaVector &arguments, const lexer::SourcePosition &pos, + const std::vector &argTypeInferenceRequired, const bool unique); + bool ValidateOrderSignatureRequiredParams(Signature *substitutedSig, const ArenaVector &arguments, + TypeRelationFlag flags, + const std::vector &argTypeInferenceRequired); + bool ValidateOrderSignatureInvocationContext(Signature *substitutedSig, ir::Expression *argument, std::size_t index, + TypeRelationFlag flags); + void ThrowOverloadMismatch(util::StringView callName, const ArenaVector &arguments, + const lexer::SourcePosition &pos, std::string_view signatureKind); + Signature *ResolveTrailingLambda(ArenaVector &signatures, ir::CallExpression *callExpr, + const lexer::SourcePosition &pos, + TypeRelationFlag reportFlag = TypeRelationFlag::NONE); + Signature *ResolvePotentialTrailingLambda(ir::CallExpression *callExpr, ArenaVector const &signatures, + ArenaVector &arguments); + bool SetPreferredTypeBeforeValidate(Signature *substitutedSig, ir::Expression *argument, size_t index, + TypeRelationFlag flags, const std::vector &argTypeInferenceRequired); + // CC-OFFNXT(G.FUN.01-CPP) solid logic Signature *ValidateSignatures(ArenaVector &signatures, const ir::TSTypeParameterInstantiation *typeArguments, @@ -666,6 +693,7 @@ public: static bool IsVariableStatic(const varbinder::Variable *var); static bool IsVariableGetterSetter(const varbinder::Variable *var); static bool IsVariableExtensionAccessor(const varbinder::Variable *var); + static bool IsVariableOverloadDeclaration(const varbinder::Variable *var); bool IsSameDeclarationType(varbinder::LocalVariable *target, varbinder::LocalVariable *compare); void SaveCapturedVariable(varbinder::Variable *var, ir::Identifier *ident); bool SaveCapturedVariableInLocalClass(varbinder::Variable *var, ir::Identifier *ident); @@ -683,6 +711,12 @@ public: ir::BlockStatement *FindFinalizerOfTryStatement(ir::AstNode *startFrom, const ir::AstNode *p); void CheckExceptionClauseType(const std::vector &exceptions, ir::CatchClause *catchClause, checker::Type *clauseType); + + void CheckConstructorOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const; + void CheckFunctionOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const; + void CheckClassMethodOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const; + void CheckInterfaceMethodOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const; + ETSObjectType *GetRelevantArgumentedTypeFromChild(ETSObjectType *child, ETSObjectType *target); util::StringView GetHashFromTypeArguments(const ArenaVector &typeArgTypes); util::StringView GetHashFromSubstitution(const Substitution *substitution, const bool isExtensionFuncFlag); @@ -978,6 +1012,7 @@ private: PropertySearchFlags GetInitialSearchFlags(const ir::MemberExpression *memberExpr); const varbinder::Variable *GetTargetRef(const ir::MemberExpression *memberExpr); Type *GetTypeOfSetterGetter([[maybe_unused]] varbinder::Variable *var); + ETSFunctionType *CreateSyntheticTypeFromOverload(varbinder::Variable *const var); void IterateInVariableContext([[maybe_unused]] varbinder::Variable *const var); bool CheckInit(ir::Identifier *ident, ir::TypeNode *typeAnnotation, ir::Expression *init, checker::Type *annotationType, varbinder::Variable *const bindingVar); diff --git a/ets2panda/checker/SemanticAnalyzer.h b/ets2panda/checker/SemanticAnalyzer.h index db3d9007a8..1126ba93c0 100644 --- a/ets2panda/checker/SemanticAnalyzer.h +++ b/ets2panda/checker/SemanticAnalyzer.h @@ -27,6 +27,7 @@ #include "ir/base/decorator.h" #include "ir/base/metaProperty.h" #include "ir/base/methodDefinition.h" +#include "ir/base/overloadDeclaration.h" #include "ir/base/property.h" #include "ir/base/scriptFunction.h" #include "ir/base/spreadElement.h" diff --git a/ets2panda/checker/TSAnalyzerUnreachable.cpp b/ets2panda/checker/TSAnalyzerUnreachable.cpp index 8b0a749ef1..43a987d1cb 100644 --- a/ets2panda/checker/TSAnalyzerUnreachable.cpp +++ b/ets2panda/checker/TSAnalyzerUnreachable.cpp @@ -48,6 +48,11 @@ checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::MethodDefinition *node) co ES2PANDA_UNREACHABLE(); } +checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::OverloadDeclaration *node) const +{ + ES2PANDA_UNREACHABLE(); +} + checker::Type *TSAnalyzer::Check([[maybe_unused]] ir::Property *expr) const { ES2PANDA_UNREACHABLE(); diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index e3ae34e684..04d1c37692 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -483,6 +483,42 @@ private: Type *type_ {}; }; +class SignatureMatchContext { +public: + explicit SignatureMatchContext(Checker *checker, util::DiagnosticType diagnosticKind, bool isLogError = true) + : diagnosticEngine_(checker->DiagnosticEngine()), + diagnosticCheckpoint_(), + diagnosticKind_(diagnosticKind), + isLogError_(isLogError) + { + diagnosticCheckpoint_ = diagnosticEngine_.Save(); + } + + bool ValidSignatureMatchStatus() + { + std::array diagnosticCheckpoint = diagnosticEngine_.Save(); + return diagnosticCheckpoint_[diagnosticKind_] == diagnosticCheckpoint[diagnosticKind_]; + } + + ~SignatureMatchContext() + { + if (isLogError_) { + return; + } + + diagnosticEngine_.Rollback(diagnosticCheckpoint_); + } + + NO_COPY_SEMANTIC(SignatureMatchContext); + NO_MOVE_SEMANTIC(SignatureMatchContext); + +private: + util::DiagnosticEngine &diagnosticEngine_; + std::array diagnosticCheckpoint_; + util::DiagnosticType diagnosticKind_; + bool isLogError_; +}; + } // namespace ark::es2panda::checker #endif /* CHECKER_H */ diff --git a/ets2panda/checker/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 3e78b0fc52..7740649e4c 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -396,13 +396,13 @@ static void ClearPreferredTypeForArray(checker::ETSChecker *checker, ir::Express { if (argument->IsArrayExpression()) { // fixed array and resizeable array will cause problem here, so clear it. - argument->AsArrayExpression()->ClearPreferredType(); + argument->AsArrayExpression()->CleanCheckInformation(); argument->AsArrayExpression()->SetPreferredTypeBasedOnFuncParam(checker, paramType, flags); } else if (argument->IsETSNewArrayInstanceExpression()) { - argument->AsETSNewArrayInstanceExpression()->ClearPreferredType(); + argument->AsETSNewArrayInstanceExpression()->CleanCheckInformation(); argument->AsETSNewArrayInstanceExpression()->SetPreferredTypeBasedOnFuncParam(checker, paramType, flags); } else if (argument->IsETSNewMultiDimArrayInstanceExpression()) { - argument->AsETSNewMultiDimArrayInstanceExpression()->ClearPreferredType(); + argument->AsETSNewMultiDimArrayInstanceExpression()->CleanCheckInformation(); argument->AsETSNewMultiDimArrayInstanceExpression()->SetPreferredTypeBasedOnFuncParam(checker, paramType, flags); } else { @@ -1289,6 +1289,7 @@ void ETSChecker::UpdateDeclarationFromSignature(ir::CallExpression *expr, checke auto newDecl = allocator->New(allocator, sigName, declNode); auto newVar = allocator->New(newDecl, varbinder::VariableFlags::METHOD | varbinder::VariableFlags::SYNTHETIC); + newVar->SetTsType(declNode->AsMethodDefinition()->TsType()->Clone(this)); callIdentifier->SetVariable(newVar); } @@ -1360,6 +1361,12 @@ Signature *ETSChecker::ResolveCallExpressionAndTrailingLambda(ArenaVector &arguments, const lexer::SourcePosition &pos) { + auto *var = type->GetProperty(compiler::Signatures::CONSTRUCTOR_OVERLOAD_DEFINITION_NAME, + PropertySearchFlags::SEARCH_STATIC_METHOD); + if (var != nullptr && var->TsType()->IsETSFunctionType()) { + return MatchOrderSignatures(var->TsType()->AsETSFunctionType()->CallSignatures(), nullptr, arguments, pos, + TypeRelationFlag::NONE); + } // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) return ValidateSignatures(type->ConstructSignatures(), nullptr, arguments, pos, "construct"); } @@ -2497,4 +2504,324 @@ bool ETSChecker::HasSameAssemblySignatures(ETSFunctionType const *const func1, return false; } +Signature *ETSChecker::FirstMatchSignatures(ir::CallExpression *expr, checker::Type *calleeType) +{ + if (expr->TrailingBlock() == nullptr) { + auto *signature = + MatchOrderSignatures(calleeType->AsETSFunctionType()->CallSignaturesOfMethodOrArrow(), expr->TypeParams(), + expr->Arguments(), expr->Start(), TypeRelationFlag::NONE); + if (signature == nullptr) { + ThrowOverloadMismatch(calleeType->AsETSFunctionType()->Name(), expr->Arguments(), expr->Start(), "call"); + return nullptr; + } + UpdateDeclarationFromSignature(expr, signature); + return signature; + } + + auto &signatures = expr->IsETSConstructorCall() ? calleeType->AsETSObjectType()->ConstructSignatures() + : calleeType->AsETSFunctionType()->CallSignaturesOfMethodOrArrow(); + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return ResolveTrailingLambda(signatures, expr, expr->Start()); +} + +Signature *ETSChecker::MatchOrderSignatures(ArenaVector &signatures, + const ir::TSTypeParameterInstantiation *typeArguments, + const ArenaVector &arguments, + const lexer::SourcePosition &pos, TypeRelationFlag resolveFlags) +{ + Signature *compatibleSignatures = nullptr; + Signature *notVisibleSignature = nullptr; + std::vector argTypeInferenceRequired = FindTypeInferenceArguments(arguments); + + auto collectSignatures = [&](TypeRelationFlag relationFlags) { + for (auto *sig : signatures) { + if (notVisibleSignature != nullptr && + !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) { + continue; + } + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + auto *concreteSig = ValidateOrderSignature(std::make_tuple(sig, typeArguments, relationFlags), arguments, + pos, argTypeInferenceRequired, signatures.size() == 1); + + if (concreteSig == nullptr) { + CleanArgumentsInformation(arguments); + continue; + } + if (notVisibleSignature == nullptr && + !IsSignatureAccessible(sig, Context().ContainingClass(), Relation())) { + CleanArgumentsInformation(arguments); + notVisibleSignature = concreteSig; + } else { + compatibleSignatures = concreteSig; + return; + } + } + }; + + collectSignatures(signatures.size() == 1 ? TypeRelationFlag::WIDENING | resolveFlags + : TypeRelationFlag::WIDENING | TypeRelationFlag::NO_THROW | resolveFlags); + + if (compatibleSignatures != nullptr) { + return compatibleSignatures; + } + + if (notVisibleSignature != nullptr && ((resolveFlags & TypeRelationFlag::NO_THROW) == 0)) { + LogError(diagnostic::SIG_INVISIBLE, {notVisibleSignature->Function()->Id()->Name(), notVisibleSignature}, pos); + } + + return nullptr; +} + +Signature *ETSChecker::ValidateOrderSignature( + std::tuple info, + const ArenaVector &arguments, const lexer::SourcePosition &pos, + const std::vector &argTypeInferenceRequired, const bool unique) +{ + auto [baseSignature, typeArguments, flags] = info; + // In case of overloads, it is necessary to iterate through the compatible signatures again, + // setting the boxing/unboxing flag for the arguments if needed. + // So handle substitution arguments only in the case of unique function or collecting signature phase. + Signature *const signature = + MaybeSubstituteTypeParameters(this, baseSignature, typeArguments, arguments, pos, flags); + if (signature == nullptr) { + return nullptr; + } + + // When process first match, if current signature is not matched, do not log TypeError + SignatureMatchContext signatureMatchContext(this, util::DiagnosticType::SEMANTIC, + (flags & TypeRelationFlag::NO_THROW) == 0); + + size_t const argCount = arguments.size(); + auto const hasRestParameter = signature->RestVar() != nullptr; + size_t compareCount = argCount; + if ((flags & TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA) != 0 && !signature->Params().empty() && + signature->Params().back()->Declaration()->Node()->AsETSParameterExpression()->IsOptional()) { + compareCount = compareCount - 1; + } + + if (compareCount < signature->MinArgCount() || (argCount > signature->ArgCount() && !hasRestParameter)) { + LogError(diagnostic::PARAM_COUNT_MISMATCH, {signature->MinArgCount(), argCount}, pos); + return nullptr; + } + + if (argCount > signature->ArgCount() && hasRestParameter && (flags & TypeRelationFlag::IGNORE_REST_PARAM) != 0) { + return nullptr; + } + + auto count = std::min(signature->ArgCount(), argCount); + // Check all required formal parameter(s) first + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + if (!ValidateOrderSignatureRequiredParams(signature, arguments, flags, argTypeInferenceRequired) || + !signatureMatchContext.ValidSignatureMatchStatus()) { + return nullptr; + } + + // Check rest parameter(s) if any exists + if (!hasRestParameter || (count >= argCount && !signature->RestVar()->TsType()->IsETSTupleType())) { + return signature; + } + if (!ValidateSignatureRestParams(signature, arguments, flags, true, unique)) { + return nullptr; + } + + return signature; +} + +bool ETSChecker::SetPreferredTypeBeforeValidate(Signature *substitutedSig, ir::Expression *argument, size_t index, + TypeRelationFlag flags, + const std::vector &argTypeInferenceRequired) +{ + auto const paramType = GetNonNullishType(substitutedSig->Params()[index]->TsType()); + if (argument->IsObjectExpression()) { + argument->AsObjectExpression()->SetPreferredType(paramType); + } + + if (argument->IsMemberExpression()) { + SetArrayPreferredTypeForNestedMemberExpressions(argument->AsMemberExpression(), paramType); + } + + if (argTypeInferenceRequired[index]) { + if (!paramType->IsETSFunctionType()) { + return false; + } + ES2PANDA_ASSERT(argument->IsArrowFunctionExpression()); + auto *param = substitutedSig->Params()[index]->Declaration()->Node()->AsETSParameterExpression(); + auto *lambda = argument->AsArrowFunctionExpression(); + if (lambda->Function()->Params().size() > + paramType->AsETSFunctionType()->CallSignaturesOfMethodOrArrow().front()->Params().size()) { + return false; + } + return CheckLambdaInfer(param->TypeAnnotation(), argument->AsArrowFunctionExpression(), paramType); + } + + if (argument->IsArrayExpression()) { + argument->AsArrayExpression()->SetPreferredTypeBasedOnFuncParam(this, paramType, flags); + } + + if (argument->IsETSNewArrayInstanceExpression()) { + argument->AsETSNewArrayInstanceExpression()->SetPreferredTypeBasedOnFuncParam(this, paramType, flags); + } + + if (argument->IsETSNewMultiDimArrayInstanceExpression()) { + argument->AsETSNewMultiDimArrayInstanceExpression()->SetPreferredTypeBasedOnFuncParam(this, paramType, flags); + } + + return true; +} + +bool ETSChecker::ValidateOrderSignatureRequiredParams(Signature *substitutedSig, + const ArenaVector &arguments, + TypeRelationFlag flags, + const std::vector &argTypeInferenceRequired) +{ + auto commonArity = std::min(arguments.size(), substitutedSig->ArgCount()); + if ((flags & TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA) != 0) { + commonArity = commonArity - 1; + } + for (size_t index = 0; index < commonArity; ++index) { + auto &argument = arguments[index]; + if (!SetPreferredTypeBeforeValidate(substitutedSig, argument, index, flags, argTypeInferenceRequired)) { + return false; + } + + if (argument->IsSpreadElement()) { + LogError(diagnostic::SPREAD_ONTO_SINGLE_PARAM, {}, argument->Start()); + return false; + } + + if (argument->IsIdentifier() && ValidateArgumentAsIdentifier(argument->AsIdentifier())) { + LogError(diagnostic::ARG_IS_CLASS_ID, {}, argument->Start()); + return false; + } + + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + if (!ValidateOrderSignatureInvocationContext(substitutedSig, argument, index, flags)) { + return false; + } + } + + if ((flags & TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA) != 0 && arguments.back()->IsArrowFunctionExpression()) { + ir::ScriptFunction *const lambda = arguments.back()->AsArrowFunctionExpression()->Function(); + auto targetParm = substitutedSig->GetSignatureInfo()->params.back()->Declaration()->Node(); + if (!CheckLambdaAssignable(targetParm->AsETSParameterExpression(), lambda)) { + return false; + } + } + return true; +} + +void ETSChecker::CleanArgumentsInformation(const ArenaVector &arguments) +{ + if (arguments.empty()) { + return; + } + for (auto *argument : arguments) { + argument->CleanCheckInformation(); + } +} + +bool ETSChecker::ValidateOrderSignatureInvocationContext(Signature *substitutedSig, ir::Expression *argument, + std::size_t index, TypeRelationFlag flags) +{ + Type *targetType = substitutedSig->Params()[index]->TsType(); + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + Type *argumentType = argument->Check(this); + + flags |= TypeRelationFlag::ONLY_CHECK_WIDENING; + + auto const invocationCtx = + checker::InvocationContext(Relation(), argument, argumentType, targetType, argument->Start(), + {{diagnostic::TYPE_MISMATCH_AT_IDX, {argumentType, targetType, index + 1}}}, flags); + + return invocationCtx.IsInvocable(); +} + +Signature *ETSChecker::ResolveTrailingLambda(ArenaVector &signatures, ir::CallExpression *callExpr, + const lexer::SourcePosition &pos, const TypeRelationFlag reportFlag) +{ + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + auto arguments = ExtendArgumentsWithFakeLamda(callExpr); + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + auto sig = ResolvePotentialTrailingLambda(callExpr, signatures, arguments); + if (sig != nullptr) { + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + TransformTraillingLambda(callExpr, sig); + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + TrailingLambdaTypeInference(sig, callExpr->Arguments()); + UpdateDeclarationFromSignature(callExpr, sig); + callExpr->SetIsTrailingCall(true); + return sig; + } + + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + sig = MatchOrderSignatures(signatures, callExpr->TypeParams(), callExpr->Arguments(), pos, reportFlag); + if (sig != nullptr) { + EnsureValidCurlyBrace(callExpr); + } + + UpdateDeclarationFromSignature(callExpr, sig); + return sig; +} + +Signature *ETSChecker::ResolvePotentialTrailingLambda(ir::CallExpression *callExpr, + ArenaVector const &signatures, + ArenaVector &arguments) +{ + auto *trailingLambda = arguments.back()->AsArrowFunctionExpression(); + ArenaVector normalSig(ProgramAllocator()->Adapter()); + ArenaVector sigContainLambdaWithReceiverAsParam(ProgramAllocator()->Adapter()); + Signature *signature = nullptr; + for (auto sig : signatures) { + if (!IsLastParameterLambdaWithReceiver(sig)) { + normalSig.emplace_back(sig); + continue; + } + + auto *candidateFunctionType = + sig->Function()->Params().back()->AsETSParameterExpression()->TypeAnnotation()->AsETSFunctionType(); + auto *currentReceiver = candidateFunctionType->Params()[0]; + trailingLambda->Function()->EmplaceParams(currentReceiver); + sigContainLambdaWithReceiverAsParam.emplace_back(sig); + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + signature = MatchOrderSignatures(sigContainLambdaWithReceiverAsParam, callExpr->TypeParams(), arguments, + callExpr->Start(), + TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA); + if (signature != nullptr) { + return signature; + } + sigContainLambdaWithReceiverAsParam.clear(); + trailingLambda->Function()->ClearParams(); + } + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + return MatchOrderSignatures(normalSig, callExpr->TypeParams(), arguments, callExpr->Start(), + TypeRelationFlag::NO_THROW | TypeRelationFlag::NO_CHECK_TRAILING_LAMBDA); +} + +void ETSChecker::ThrowOverloadMismatch(util::StringView callName, const ArenaVector &arguments, + const lexer::SourcePosition &pos, std::string_view signatureKind) +{ + std::string msg {}; + msg.append(callName.Mutf8()); + msg += "("; + + for (std::size_t index = 0U; index < arguments.size(); ++index) { + auto const &argument = arguments[index]; + Type const *const argumentType = argument->Check(this); + if (!argumentType->IsTypeError()) { + msg += argumentType->ToString(); + } else { + // NOTE (DZ): extra cases for some specific nodes can be added here (as for 'ArrowFunctionExpression') + msg += argument->ToString(); + } + + if (index == arguments.size() - 1U) { + msg += ")"; + LogError(diagnostic::NO_MATCHING_SIG, {signatureKind, msg.c_str()}, pos); + return; + } + + msg += ", "; + } +} + } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index 2886671c98..d5781e2b7c 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -72,6 +72,12 @@ bool ETSChecker::IsVariableGetterSetter(const varbinder::Variable *var) return var != nullptr && var->TsType() != nullptr && var->TsType()->HasTypeFlag(TypeFlag::GETTER_SETTER); } +bool ETSChecker::IsVariableOverloadDeclaration(const varbinder::Variable *var) +{ + return var != nullptr && var->Declaration() != nullptr && var->Declaration()->Node() != nullptr && + var->Declaration()->Node()->IsOverloadDeclaration(); +} + bool ETSChecker::IsVariableExtensionAccessor(const varbinder::Variable *var) { return var != nullptr && var->TsType() != nullptr && var->TsType()->IsETSFunctionType() && @@ -314,6 +320,10 @@ Type *ETSChecker::ResolveIdentifier(ir::Identifier *ident) ValidatePropertyAccess(resolved, Context().ContainingClass(), ident->Start()); SaveCapturedVariable(resolved, ident); + if (IsVariableOverloadDeclaration(resolved)) { + return CreateSyntheticTypeFromOverload(resolved); + } + return GetTypeOfVariable(resolved); } diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 3c0ab334a3..2a283129c7 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -82,8 +82,35 @@ static bool CheckGetterSetterDecl(varbinder::LocalVariable const *child, varbind return checkChild && checkParent && (child->TsType()->IsETSFunctionType() || parent->TsType()->IsETSFunctionType()); } +static bool CheckOverloadDecl(varbinder::LocalVariable *child, varbinder::LocalVariable *parent) +{ + if (!child->Declaration()->Node()->IsOverloadDeclaration() || + !parent->Declaration()->Node()->IsOverloadDeclaration()) { + return false; + } + + auto *childOverload = child->Declaration()->Node()->AsOverloadDeclaration(); + auto *parentOverload = parent->Declaration()->Node()->AsOverloadDeclaration(); + for (auto *baseMethodName : parentOverload->OverloadedList()) { + ES2PANDA_ASSERT(baseMethodName->IsIdentifier()); + auto res = std::find_if(childOverload->OverloadedList().begin(), childOverload->OverloadedList().end(), + [baseMethodName](ir::Expression *subMethodName) { + return subMethodName->IsIdentifier() && subMethodName->AsIdentifier()->Name() == + baseMethodName->AsIdentifier()->Name(); + }); + if (res == childOverload->OverloadedList().end()) { + return false; + } + } + return true; +} + static bool CheckFunctionDecl(varbinder::LocalVariable *child, varbinder::LocalVariable *parent) { + if (child->Declaration()->Node()->IsOverloadDeclaration() || + parent->Declaration()->Node()->IsOverloadDeclaration()) { + return false; + } ES2PANDA_ASSERT(child->Declaration()->Type() == parent->Declaration()->Type()); if (!child->TsType()->IsETSMethodType()) { return true; @@ -565,49 +592,57 @@ static void ResolveDeclaredMethodsOfObject(ETSChecker *checker, const ETSObjectT { for (auto &[_, it] : scope->InstanceMethodScope()->Bindings()) { (void)_; - auto *method = it->Declaration()->Node()->AsMethodDefinition(); - auto *function = method->Function(); - if (function->IsProxy()) { - continue; - } + if (it->Declaration()->Node()->IsMethodDefinition()) { + auto *method = it->Declaration()->Node()->AsMethodDefinition(); + auto *function = method->Function(); + if (function->IsProxy()) { + continue; + } - it->AddFlag(checker->GetAccessFlagFromNode(method)); - auto *funcType = checker->BuildMethodSignature(method); - if (!funcType->IsTypeError()) { - funcType->SetVariable(it); + it->AddFlag(checker->GetAccessFlagFromNode(method)); + auto *funcType = checker->BuildMethodSignature(method); + if (!funcType->IsTypeError()) { + funcType->SetVariable(it); + } + it->SetTsType(funcType); + method->SetTsType(funcType); + type->AddProperty(it->AsLocalVariable()); + } else if (it->Declaration()->Node()->IsOverloadDeclaration()) { + type->AddProperty(it->AsLocalVariable()); + } else { + ES2PANDA_UNREACHABLE(); } - it->SetTsType(funcType); - method->SetTsType(funcType); - type->AddProperty(it->AsLocalVariable()); } for (auto &[_, it] : scope->StaticMethodScope()->Bindings()) { (void)_; - if (!it->Declaration()->Node()->IsMethodDefinition()) { - continue; - } + if (it->Declaration()->Node()->IsMethodDefinition()) { + auto *method = it->Declaration()->Node()->AsMethodDefinition(); + auto *function = method->Function(); - auto *method = it->Declaration()->Node()->AsMethodDefinition(); - auto *function = method->Function(); + if (function->IsProxy()) { + continue; + } - if (function->IsProxy()) { - continue; - } + it->AddFlag(checker->GetAccessFlagFromNode(method)); + auto *funcType = checker->BuildMethodSignature(method); + if (!funcType->IsTypeError()) { + funcType->SetVariable(it); + } + it->SetTsType(funcType); + method->SetTsType(funcType); - it->AddFlag(checker->GetAccessFlagFromNode(method)); - auto *funcType = checker->BuildMethodSignature(method); - if (!funcType->IsTypeError()) { - funcType->SetVariable(it); - } - it->SetTsType(funcType); - method->SetTsType(funcType); + if (method->IsConstructor() && funcType->IsETSFunctionType()) { + type->AddConstructSignature(funcType->AsETSFunctionType()->CallSignatures()); + continue; + } - if (method->IsConstructor() && funcType->IsETSFunctionType()) { - type->AddConstructSignature(funcType->AsETSFunctionType()->CallSignatures()); + type->AddProperty(it->AsLocalVariable()); + } else if (it->Declaration()->Node()->IsOverloadDeclaration()) { + type->AddProperty(it->AsLocalVariable()); + } else { continue; } - - type->AddProperty(it->AsLocalVariable()); } } @@ -715,6 +750,10 @@ std::vector ETSChecker::CollectAbstractSignaturesFromObject(const E { std::vector abstracts; for (const auto &prop : objType->Methods()) { + if (prop->Declaration()->Node()->IsOverloadDeclaration()) { + continue; + } + GetTypeOfVariable(prop); if (!prop->TsType()->IsETSFunctionType()) { @@ -913,6 +952,10 @@ void ETSChecker::CheckInterfaceFunctions(ETSObjectType *classType) for (auto *const &interface : interfaces) { for (auto *const &prop : interface->Methods()) { + if (prop->Declaration()->Node()->IsOverloadDeclaration()) { + continue; + } + ir::MethodDefinition *node = prop->Declaration()->Node()->AsMethodDefinition(); if (prop->TsType()->IsTypeError()) { continue; @@ -1935,6 +1978,10 @@ PropertySearchFlags ETSChecker::GetInitialSearchFlags(const ir::MemberExpression } break; } + case ir::AstNodeType::OVERLOAD_DECLARATION: { + return FUNCTIONAL_FLAGS | GETTER_FLAGS; + break; + } case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: { if (memberExpr->Parent()->AsETSNewClassInstanceExpression()->GetTypeRef() == memberExpr) { return PropertySearchFlags::SEARCH_DECL; @@ -2249,6 +2296,17 @@ std::vector ETSChecker::ResolveMemberReference(const ir::Member return resolveRes; } +varbinder::LocalVariable *ETSChecker::ResolveOverloadReference(const ir::Identifier *ident, ETSObjectType *objType, + PropertySearchFlags searchFlags) +{ + auto *var = objType->GetProperty(ident->Name(), searchFlags); + if (var == nullptr) { + return nullptr; + } + ValidatePropertyAccess(var, objType, ident->Start()); + return var; +} + void ETSChecker::WarnForEndlessLoopInGetterSetter(const ir::MemberExpression *const memberExpr) { if (!memberExpr->Object()->IsThisExpression() || memberExpr->Property() == nullptr || @@ -2329,6 +2387,8 @@ void ETSChecker::CheckProperties(ETSObjectType *classType, ir::ClassDefinition * if (CheckGetterSetterDecl(it, found)) { return; } + } else if (CheckOverloadDecl(it, found)) { + return; } else if (CheckFunctionDecl(it, found)) { return; } @@ -2347,6 +2407,8 @@ void ETSChecker::CheckProperties(ETSObjectType *classType, ir::ClassDefinition * targetType = "namespace"; } else if (it->HasFlag(varbinder::VariableFlags::ENUM_LITERAL)) { targetType = "enum"; + } else if (it->HasFlag(varbinder::VariableFlags::OVERLOAD)) { + targetType = "overload"; } else { ES2PANDA_UNREACHABLE(); } diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 77d3cf08eb..7fae85b785 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -477,6 +477,30 @@ Type *ETSChecker::GetTypeOfSetterGetter(varbinder::Variable *const var) return propType->FindSetter()->Params()[0]->TsType(); } +ETSFunctionType *ETSChecker::CreateSyntheticTypeFromOverload(varbinder::Variable *const var) +{ + auto *overloadDeclaration = var->Declaration()->Node()->AsOverloadDeclaration(); + std::vector signatures; + ETSFunctionType *syntheticFunctionType = + CreateETSMethodType(overloadDeclaration->Id()->Name(), {{}, Allocator()->Adapter()}); + + for (auto *overloadFunction : overloadDeclaration->OverloadedList()) { + Type *functionType = overloadFunction->Check(this); + ES2PANDA_ASSERT(functionType->IsETSFunctionType()); + auto *signature = functionType->AsETSFunctionType()->CallSignatures().front(); + if (std::find(signatures.begin(), signatures.end(), signature) != signatures.end()) { + continue; + } + signatures.emplace_back(signature); + } + + for (auto &s : signatures) { + syntheticFunctionType->AddCallSignature(s); + } + + return syntheticFunctionType; +} + void ETSChecker::IterateInVariableContext(varbinder::Variable *const var) { // Before computing the given variables type, we have to make a new checker context frame so that the checking is @@ -1619,4 +1643,180 @@ void ETSChecker::CheckExceptionClauseType(const std::vectorLogError(diagnostic::OVERLOAD_MODIFIERS_ABSTRACT, {}, pos); + return false; + } + + if (((overLoadAliasFlags ^ overloadedMethodFlags) & (ir::ModifierFlags::STATIC | ir::ModifierFlags::ASYNC)) != 0) { + checker->LogError(diagnostic::OVERLOAD_SAME_ACCESS_MODIFIERS_STATIC_ASYNC, {}, pos); + return false; + } + + if (((overLoadAliasFlags ^ overloadedMethodFlags) & (ir::ModifierFlags::CONSTRUCTOR)) != 0) { + checker->LogError(diagnostic::OVERLOAD_MUST_BOTH_CONSTRUCT, {}, pos); + return false; + } + + if ((overLoadAliasFlags & ir::ModifierFlags::EXPORT) != 0 && + (overloadedMethodFlags & ir::ModifierFlags::EXPORT) == 0) { + checker->LogError(diagnostic::OVERLOADED_NAME_MUST_ALSO_EXPORTED, {}, pos); + return false; + } + return true; +} + +static bool CheckOverloadedName(ETSChecker *checker, ir::OverloadDeclaration *node, ir::Expression *overloadedName) +{ + if (overloadedName->Variable()->Declaration() == nullptr) { + checker->LogError(diagnostic::OVERLOADED_NAME_MUST_FUNCTION, {}, overloadedName->Start()); + overloadedName->SetTsType(checker->GlobalTypeError()); + return false; + } + + auto *identDeclNode = overloadedName->Variable()->Declaration()->Node(); + if (!identDeclNode->IsMethodDefinition()) { + checker->LogError(diagnostic::OVERLOADED_NAME_MUST_FUNCTION, {}, overloadedName->Start()); + overloadedName->SetTsType(checker->GlobalTypeError()); + return false; + } + // Constructor will lowering to multiple Constructor if have rest parameters or optional parameters. + // Need to modify RestTupleConstructionPhase. + if (!identDeclNode->AsMethodDefinition()->Overloads().empty() && !identDeclNode->IsConstructor()) { + checker->LogError(diagnostic::OVERLOADED_NAME_REFER_TO_OVERLOAD_FUNCTION, {overloadedName->Variable()->Name()}, + overloadedName->Start()); + overloadedName->SetTsType(checker->GlobalTypeError()); + return false; + } + + return CheckAccessModifierForOverloadDeclaration(checker, node->Modifiers(), identDeclNode->Modifiers(), + overloadedName->Start()); +} + +void ETSChecker::CheckFunctionOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const +{ + for (auto *overloadedName : node->OverloadedList()) { + if (overloadedName->IsMemberExpression()) { + overloadedName->Check(checker); + overloadedName->SetVariable(overloadedName->AsMemberExpression()->Property()->Variable()); + } else if (overloadedName->IsIdentifier()) { + ir::Identifier *ident = overloadedName->AsIdentifier(); + + Type *classType = node->Parent()->AsClassDefinition()->TsType(); + ES2PANDA_ASSERT(classType->IsETSObjectType()); + + PropertySearchFlags searchFlags = PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::SEARCH_IN_BASE | + PropertySearchFlags::SEARCH_IN_INTERFACES | + PropertySearchFlags::IS_GETTER; + auto *variable = + checker->ResolveOverloadReference(ident->AsIdentifier(), classType->AsETSObjectType(), searchFlags); + if (variable == nullptr) { + checker->LogError(diagnostic::OVERLOADED_NAME_MUST_FUNCTION, {}, ident->Start()); + ident->SetTsType(checker->GlobalTypeError()); + continue; + } + + ident->SetTsType(variable->TsType()); + ident->SetVariable(variable); + + if (!CheckOverloadedName(checker, node, overloadedName)) { + continue; + } + } else { + overloadedName->SetTsType(checker->GlobalTypeError()); + continue; + } + } +} + +void ETSChecker::CheckClassMethodOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const +{ + for (auto *overloadedName : node->OverloadedList()) { + if (!overloadedName->IsIdentifier()) { + overloadedName->SetTsType(checker->GlobalTypeError()); + continue; + } + ir::Identifier *ident = overloadedName->AsIdentifier(); + + Type *classType = node->Parent()->AsClassDefinition()->TsType(); + ES2PANDA_ASSERT(classType->IsETSObjectType()); + + PropertySearchFlags searchFlags = PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::SEARCH_IN_BASE | + PropertySearchFlags::SEARCH_IN_INTERFACES | PropertySearchFlags::IS_GETTER; + auto *variable = + checker->ResolveOverloadReference(ident->AsIdentifier(), classType->AsETSObjectType(), searchFlags); + if (variable == nullptr) { + checker->LogError(diagnostic::OVERLOADED_NAME_MUST_FUNCTION, {}, ident->Start()); + ident->SetTsType(checker->GlobalTypeError()); + continue; + } + + ident->SetTsType(variable->TsType()); + ident->SetVariable(variable); + + if (!CheckOverloadedName(checker, node, overloadedName)) { + continue; + } + } +} + +void ETSChecker::CheckInterfaceMethodOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const +{ + for (auto *overloadedName : node->OverloadedList()) { + if (!overloadedName->IsIdentifier()) { + overloadedName->SetTsType(checker->GlobalTypeError()); + continue; + } + ir::Identifier *ident = overloadedName->AsIdentifier(); + + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + Type *identType = checker->ResolveIdentifier(ident); + ident->SetTsType(identType); + if (!CheckOverloadedName(checker, node, overloadedName)) { + continue; + } + } +} + +void ETSChecker::CheckConstructorOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const +{ + for (auto *overloadedName : node->OverloadedList()) { + if (!overloadedName->IsIdentifier()) { + overloadedName->SetTsType(checker->GlobalTypeError()); + continue; + } + ir::Identifier *ident = overloadedName->AsIdentifier(); + + // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) + Type *identType = checker->ResolveIdentifier(ident->AsIdentifier()); + ident->SetTsType(identType); + if (identType->IsTypeError()) { + continue; + } + + ES2PANDA_ASSERT(identType->IsETSFunctionType()); + const size_t singleSignatureSize = 1; + if (identType->AsETSFunctionType()->CallSignatures().size() > singleSignatureSize) { + size_t userDefinedConstructorSize = + std::count_if(identType->AsETSFunctionType()->CallSignatures().begin(), + identType->AsETSFunctionType()->CallSignatures().end(), + [](Signature *sig) { return !sig->Function()->IsSynthetic(); }); + if (userDefinedConstructorSize > singleSignatureSize) { + checker->LogError(diagnostic::OVERLOADED_NAME_REFER_TO_OVERLOAD_FUNCTION, {ident->Name()}, + node->Start()); + continue; + } + } + + if (!CheckOverloadedName(checker, node, overloadedName)) { + continue; + } + } +} + } // namespace ark::es2panda::checker diff --git a/ets2panda/checker/ets/validateHelpers.cpp b/ets2panda/checker/ets/validateHelpers.cpp index 685c1d8b4b..e944b05b04 100644 --- a/ets2panda/checker/ets/validateHelpers.cpp +++ b/ets2panda/checker/ets/validateHelpers.cpp @@ -64,6 +64,10 @@ void ETSChecker::ValidateCallExpressionIdentifier(ir::Identifier *const ident, T } ES2PANDA_ASSERT(ident->Variable() != nullptr); + if (ident->Variable()->Declaration()->Node() != nullptr && + ident->Variable()->Declaration()->Node()->IsOverloadDeclaration()) { + return; + } if (ident->Variable()->Declaration()->Node() != nullptr && ident->Variable()->Declaration()->Node()->IsImportNamespaceSpecifier()) { std::ignore = TypeError(ident->Variable(), diagnostic::NAMESPACE_CALL, {ident->ToString()}, ident->Start()); diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 72c5694774..2a920a8376 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -25,10 +25,6 @@ namespace ark::es2panda::checker { -static std::multimap GetSignaturesForSyntheticType(ETSObjectType const *owner, - util::StringView name, - PropertySearchFlags flags); - void ETSObjectType::Iterate(const PropertyTraverser &cb) const { for (const auto *prop : GetAllProperties()) { @@ -212,7 +208,11 @@ static void UpdateDeclarationForGetterSetter(varbinder::LocalVariable *res, cons if (!HasAccessor(flags, funcType) || res->Declaration() != nullptr) { return; } - auto var = funcType->CallSignatures().front()->OwnerVar(); + + auto frontGetter = std::find_if(funcType->CallSignatures().begin(), funcType->CallSignatures().end(), + [](Signature *sig) { return sig->Function()->IsGetter(); }); + auto var = frontGetter == funcType->CallSignatures().end() ? funcType->CallSignatures().front()->OwnerVar() + : (*frontGetter)->OwnerVar(); auto decl = var->Declaration(); if (decl == nullptr || decl->Node() == nullptr) { return; @@ -220,20 +220,32 @@ static void UpdateDeclarationForGetterSetter(varbinder::LocalVariable *res, cons res->Reset(decl, var->Flags()); } -varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(util::StringView name, +varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(const util::StringView &name, PropertySearchFlags flags) const { - auto signatureSet = GetSignaturesForSyntheticType(this, name, flags); - if (signatureSet.empty()) { + std::vector signatures; + // Since both "first match" and "best match" exist at present, overloadDeclarationCall is temporarily used. After + // "best match" removed, this marking needs to be removed. + bool overloadDeclarationCall = false; + varbinder::LocalVariable *functionalInterface = + CollectSignaturesForSyntheticType(signatures, name, flags, overloadDeclarationCall); + // #22952: the called function *always* returns nullptr + ES2PANDA_ASSERT(functionalInterface == nullptr); + (void)functionalInterface; + + if (signatures.empty()) { return nullptr; } - varbinder::LocalVariable *res = allocator_->New(varbinder::VariableFlags::SYNTHETIC | - varbinder::VariableFlags::METHOD); + varbinder::VariableFlags varianceFlag = + overloadDeclarationCall ? varbinder::VariableFlags::SYNTHETIC | varbinder::VariableFlags::METHOD | + varbinder::VariableFlags::OVERLOAD + : varbinder::VariableFlags::SYNTHETIC | varbinder::VariableFlags::METHOD; + varbinder::LocalVariable *res = allocator_->New(varianceFlag); ETSFunctionType *funcType = CreateMethodTypeForProp(name); - for (auto &s : signatureSet) { - funcType->AddCallSignature(s.second); + for (auto &s : signatures) { + funcType->AddCallSignature(s); } res->SetTsType(funcType); funcType->SetVariable(res); @@ -249,89 +261,137 @@ ETSFunctionType *ETSObjectType::CreateMethodTypeForProp(util::StringView name) c return GetRelation()->GetChecker()->AsETSChecker()->CreateETSMethodType(name, {{}, Allocator()->Adapter()}); } -static void ReplaceArgInSig(std::multimap *signatureSet, Signature *sigToInsert, - TypeRelation *relation) +bool ETSObjectType::ReplaceArgumentInSignature(std::vector &signatures, Signature *sigToInsert, + TypeRelation *relation) const { - auto range = signatureSet->equal_range(sigToInsert->ArgCount()); - for (auto it = range.first; it != range.second; ++it) { - auto sigToReplace = it->second; - + for (auto *&sigToReplace : signatures) { + if (sigToReplace->ArgCount() != sigToInsert->ArgCount()) { + continue; + } if (relation->IsSupertypeOf(sigToInsert->Owner(), sigToReplace->Owner()) && relation->SignatureIsSupertypeOf(sigToInsert, sigToReplace)) { // Already overridden by a subtype's signature - return; + return true; } if (relation->IsSupertypeOf(sigToReplace->Owner(), sigToInsert->Owner()) && relation->SignatureIsSupertypeOf(sigToReplace, sigToInsert)) { - signatureSet->erase(it); - signatureSet->insert({sigToInsert->ArgCount(), sigToInsert}); - return; + sigToReplace = sigToInsert; + return true; } } - signatureSet->insert({sigToInsert->ArgCount(), sigToInsert}); + + return false; } -// CC-OFFNXT(huge_depth) solid logic -static void AddSignatureToSignatureSet(std::multimap *signatureSet, - varbinder::LocalVariable *found, TypeRelation *relation, - PropertySearchFlags flags) +void ETSObjectType::AddSignatureFromFunction(std::vector &signatures, PropertySearchFlags flags, + ETSChecker *checker, varbinder::LocalVariable *found) const { - for (auto *sigToInsert : found->TsType()->AsETSFunctionType()->CallSignatures()) { - if (((flags & PropertySearchFlags::IGNORE_ABSTRACT) != 0) && - sigToInsert->HasSignatureFlag(SignatureFlags::ABSTRACT)) { + for (auto *it : found->TsType()->AsETSFunctionType()->CallSignatures()) { + if (std::find(signatures.begin(), signatures.end(), it) != signatures.end()) { + continue; + } + if (((flags & PropertySearchFlags::IGNORE_ABSTRACT) != 0) && it->HasSignatureFlag(SignatureFlags::ABSTRACT)) { + continue; + } + if (ReplaceArgumentInSignature(signatures, it, checker->Relation())) { continue; } + signatures.emplace_back(it); + } +} - if (signatureSet->count(sigToInsert->ArgCount()) != 0U) { - ReplaceArgInSig(signatureSet, sigToInsert, relation); - } else { - signatureSet->insert({sigToInsert->ArgCount(), sigToInsert}); +void ETSObjectType::AddSignatureFromOverload(std::vector &signatures, PropertySearchFlags flags, + varbinder::LocalVariable *found, bool &overloadDeclarationCall) const +{ + auto *overloadDeclaration = found->Declaration()->Node()->AsOverloadDeclaration(); + std::vector methodSignature; + if (overloadDeclaration->Id()->IsErrorPlaceHolder()) { + return; + } + + overloadDeclarationCall |= true; + if (overloadDeclaration->IsConstructorOverloadDeclaration()) { + return AddSignatureFromConstructor(signatures, found); + } + + for (auto *method : overloadDeclaration->OverloadedList()) { + // Identical type cannot be obtained directly, because typeparamter has not been substitute. + methodSignature.clear(); + util::StringView methodName = + method->IsIdentifier() ? method->AsIdentifier()->Name() : method->AsTSQualifiedName()->Right()->Name(); + CollectSignaturesForSyntheticType(methodSignature, methodName, flags, overloadDeclarationCall); + if (!methodSignature.empty()) { + signatures.emplace_back(methodSignature.front()); } } } -static void CollectSignaturesForSyntheticType(ETSObjectType const *owner, - std::multimap *signatureSet, util::StringView name, - PropertySearchFlags flags) +void ETSObjectType::AddSignatureFromConstructor(std::vector &signatures, + varbinder::LocalVariable *found) const { - if ((flags & PropertySearchFlags::SEARCH_STATIC_METHOD) != 0) { - if (auto *found = owner->GetOwnProperty(name); - found != nullptr && !found->TsType()->IsTypeError()) { - ES2PANDA_ASSERT(found->TsType()->IsETSFunctionType()); - AddSignatureToSignatureSet(signatureSet, found, owner->GetRelation(), flags); + auto *overloadDeclaration = found->Declaration()->Node()->AsOverloadDeclaration(); + for (auto *method : overloadDeclaration->OverloadedList()) { + util::StringView orderConstructorName = method->AsIdentifier()->Name(); + + // Constructor will lowering to multiple Constructor if have rest parameters or optional parameters. + // Need to modify RestTupleConstructionPhase. + std::vector matches; + std::copy_if( + constructSignatures_.begin(), constructSignatures_.end(), std::back_inserter(matches), + [orderConstructorName](Signature *sig) { return sig->Function()->Id()->Name() == orderConstructorName; }); + + if (!matches.empty()) { + std::copy(matches.begin(), matches.end(), std::back_inserter(signatures)); } } +} - if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) != 0) { - if (auto *found = owner->GetOwnProperty(name); - found != nullptr && !found->TsType()->IsTypeError()) { - ES2PANDA_ASSERT(found->TsType()->IsETSFunctionType()); - AddSignatureToSignatureSet(signatureSet, found, owner->GetRelation(), flags); +void ETSObjectType::AddSignature(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, + varbinder::LocalVariable *found, bool &overloadDeclarationCall) const +{ + if (found != nullptr && found->HasFlag(varbinder::VariableFlags::OVERLOAD)) { + if (!found->Declaration()->Node()->IsOverloadDeclaration()) { + return; } + AddSignatureFromOverload(signatures, flags, found, overloadDeclarationCall); + } else if (found != nullptr && !found->TsType()->IsTypeError()) { + ES2PANDA_ASSERT(found->TsType()->IsETSFunctionType()); + AddSignatureFromFunction(signatures, flags, checker, found); + } +} + +varbinder::LocalVariable *ETSObjectType::CollectSignaturesForSyntheticType(std::vector &signatures, + const util::StringView &name, + PropertySearchFlags flags, + bool &overloadDeclarationCall) const +{ + auto *checker = GetRelation()->GetChecker()->AsETSChecker(); + + if ((flags & PropertySearchFlags::SEARCH_STATIC_METHOD) != 0) { + auto *found = GetOwnProperty(name); + AddSignature(signatures, flags, checker, found, overloadDeclarationCall); + } + + if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) != 0) { + auto *found = GetOwnProperty(name); + AddSignature(signatures, flags, checker, found, overloadDeclarationCall); } if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) == 0) { - return; + return nullptr; } - if (owner->SuperType() != nullptr && ((flags & PropertySearchFlags::SEARCH_IN_BASE) != 0)) { - CollectSignaturesForSyntheticType(owner->SuperType(), signatureSet, name, flags); + if (superType_ != nullptr && ((flags & PropertySearchFlags::SEARCH_IN_BASE) != 0)) { + superType_->CollectSignaturesForSyntheticType(signatures, name, flags, overloadDeclarationCall); } if ((flags & PropertySearchFlags::SEARCH_IN_INTERFACES) != 0) { - for (auto *interface : owner->Interfaces()) { - CollectSignaturesForSyntheticType(interface, signatureSet, name, flags); + for (auto *interface : Interfaces()) { + interface->CollectSignaturesForSyntheticType(signatures, name, flags, overloadDeclarationCall); } } -} -static std::multimap GetSignaturesForSyntheticType(ETSObjectType const *owner, - util::StringView name, - PropertySearchFlags flags) -{ - std::multimap signatureSet; - CollectSignaturesForSyntheticType(owner, &signatureSet, name, flags); - return signatureSet; + return nullptr; } std::vector ETSObjectType::GetAllProperties() const @@ -370,16 +430,42 @@ std::vector ETSObjectType::GetAllProperties() const return allProperties; } +std::vector ETSObjectType::Overloads() const +{ + std::vector methods; + for (const auto &[_, prop] : InstanceMethods()) { + (void)_; + if (prop->HasFlag(varbinder::VariableFlags::OVERLOAD)) { + methods.push_back(prop); + } + } + + for (const auto &[_, prop] : StaticMethods()) { + (void)_; + if (prop->HasFlag(varbinder::VariableFlags::OVERLOAD)) { + methods.push_back(prop); + } + } + + return methods; +} + std::vector ETSObjectType::Methods() const { std::vector methods; for (const auto &[_, prop] : InstanceMethods()) { (void)_; + if (prop->HasFlag(varbinder::VariableFlags::OVERLOAD)) { + continue; + } methods.push_back(prop); } for (const auto &[_, prop] : StaticMethods()) { (void)_; + if (prop->HasFlag(varbinder::VariableFlags::OVERLOAD)) { + continue; + } methods.push_back(prop); } diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index 672914ec1c..a56cf8fd0e 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -342,8 +342,21 @@ public: TypeRelation *relation, GlobalTypesHolder *globalTypes); std::vector Methods() const; std::vector Fields() const; - varbinder::LocalVariable *CreateSyntheticVarFromEverySignature(util::StringView name, + std::vector Overloads() const; + varbinder::LocalVariable *CreateSyntheticVarFromEverySignature(const util::StringView &name, PropertySearchFlags flags) const; + varbinder::LocalVariable *CollectSignaturesForSyntheticType(std::vector &signatures, + const util::StringView &name, PropertySearchFlags flags, + bool &overloadDeclarationCall) const; + void AddSignature(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, + varbinder::LocalVariable *found, bool &overloadDeclarationCall) const; + void AddSignatureFromFunction(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, + varbinder::LocalVariable *found) const; + void AddSignatureFromOverload(std::vector &signatures, PropertySearchFlags flags, + varbinder::LocalVariable *found, bool &overloadDeclarationCall) const; + void AddSignatureFromConstructor(std::vector &signatures, varbinder::LocalVariable *found) const; + bool ReplaceArgumentInSignature(std::vector &signatures, Signature *sigToInsert, + TypeRelation *relation) const; bool CheckIdenticalFlags(ETSObjectType *other) const; ETSObjectType *CreateETSObjectType(ir::AstNode *declNode, ETSObjectFlags flags); void Iterate(const PropertyTraverser &cb) const; diff --git a/ets2panda/compiler/core/ETSCompilerUnrechable.cpp b/ets2panda/compiler/core/ETSCompilerUnrechable.cpp index 4536b5cebf..77abdb301f 100644 --- a/ets2panda/compiler/core/ETSCompilerUnrechable.cpp +++ b/ets2panda/compiler/core/ETSCompilerUnrechable.cpp @@ -52,6 +52,11 @@ void ETSCompiler::Compile([[maybe_unused]] const ir::MethodDefinition *node) con ES2PANDA_UNREACHABLE(); } +void ETSCompiler::Compile([[maybe_unused]] const ir::OverloadDeclaration *node) const +{ + ES2PANDA_UNREACHABLE(); +} + void ETSCompiler::Compile([[maybe_unused]] const ir::Property *expr) const { ES2PANDA_UNREACHABLE(); diff --git a/ets2panda/compiler/core/ETSemitter.cpp b/ets2panda/compiler/core/ETSemitter.cpp index 376ae87f82..c416ee4805 100644 --- a/ets2panda/compiler/core/ETSemitter.cpp +++ b/ets2panda/compiler/core/ETSemitter.cpp @@ -15,6 +15,7 @@ #include "ETSemitter.h" +#include "annotation.h" #include "compiler/core/ETSGen.h" #include "varbinder/varbinder.h" #include "varbinder/ETSBinder.h" @@ -155,6 +156,10 @@ static pandasm::Function GenScriptFunction(const ir::ScriptFunction *scriptFunc, func.metadata->SetAnnotations(emitter->GenCustomAnnotations(scriptFunc->Annotations(), func.name)); } + if (scriptFunc->IsConstructor()) { + func.metadata->SetAttribute(Signatures::CONSTRUCTOR); + } + return func; } @@ -531,6 +536,13 @@ void ETSEmitter::GenInterfaceRecord(const ir::TSInterfaceDeclaration *interfaceD } } + if (std::any_of(interfaceDecl->Body()->Body().begin(), interfaceDecl->Body()->Body().end(), + [](const ir::AstNode *node) { return node->IsOverloadDeclaration(); })) { + std::vector annotations {}; + annotations.emplace_back(GenAnnotationFunctionOverload(interfaceDecl->Body()->Body())); + interfaceRecord.metadata->AddAnnotations(annotations); + } + if (external) { interfaceRecord.metadata->SetAttribute(Signatures::EXTERNAL); Program()->recordTable.emplace(interfaceRecord.name, std::move(interfaceRecord)); @@ -577,6 +589,11 @@ std::vector ETSEmitter::GenAnnotations(const ir::ClassD annotations.push_back(GenAnnotationDynamicCall(*callNames)); } + if (std::any_of(classDef->Body().begin(), classDef->Body().end(), + [](const ir::AstNode *node) { return node->IsOverloadDeclaration(); })) { + annotations.push_back(GenAnnotationFunctionOverload(classDef->Body())); + } + return annotations; } @@ -949,6 +966,32 @@ pandasm::AnnotationData ETSEmitter::GenAnnotationModule(const ir::ClassDefinitio return moduleAnno; } +pandasm::AnnotationData ETSEmitter::GenAnnotationFunctionOverload(const ArenaVector &body) +{ + GenAnnotationRecord(Signatures::ETS_ANNOTATION_FUNCTION_OVERLOAD); + pandasm::AnnotationData overloadAnno(Signatures::ETS_ANNOTATION_FUNCTION_OVERLOAD); + + for (auto *node : body) { + if (!node->IsOverloadDeclaration()) { + continue; + } + std::vector overloadDeclRecords {}; + + for (auto *overloadedName : node->AsOverloadDeclaration()->OverloadedList()) { + auto *methodDef = overloadedName->Variable()->Declaration()->Node()->AsMethodDefinition(); + overloadDeclRecords.emplace_back(pandasm::ScalarValue::Create( + methodDef->Function()->Scope()->InternalName().Mutf8())); + } + + pandasm::AnnotationElement value( + node->AsOverloadDeclaration()->Id()->Name().Mutf8(), + std::make_unique(pandasm::Value::Type::RECORD, std::move(overloadDeclRecords))); + + overloadAnno.AddElement(std::move(value)); + } + return overloadAnno; +} + pandasm::AnnotationData ETSEmitter::GenAnnotationSignature(const ir::ClassDefinition *classDef) { std::vector parts {}; diff --git a/ets2panda/compiler/core/ETSemitter.h b/ets2panda/compiler/core/ETSemitter.h index db06f5bd5d..084964321b 100644 --- a/ets2panda/compiler/core/ETSemitter.h +++ b/ets2panda/compiler/core/ETSemitter.h @@ -110,6 +110,7 @@ private: void GenClassInheritedFields(const checker::ETSObjectType *baseType, pandasm::Record &classRecord); pandasm::AnnotationData GenAnnotationSignature(const ir::ClassDefinition *classDef); pandasm::AnnotationData GenAnnotationModule(const ir::ClassDefinition *classDef); + pandasm::AnnotationData GenAnnotationFunctionOverload(const ArenaVector &body); pandasm::AnnotationData GenAnnotationEnclosingClass(std::string_view className); pandasm::AnnotationData GenAnnotationEnclosingMethod(const ir::MethodDefinition *methodDef); pandasm::AnnotationData GenAnnotationFunctionalReference(const ir::ClassDefinition *classDef); diff --git a/ets2panda/compiler/core/JSCompilerUnreachable.cpp b/ets2panda/compiler/core/JSCompilerUnreachable.cpp index 8a4b29a9a5..d38cf39039 100644 --- a/ets2panda/compiler/core/JSCompilerUnreachable.cpp +++ b/ets2panda/compiler/core/JSCompilerUnreachable.cpp @@ -48,6 +48,11 @@ void JSCompiler::Compile([[maybe_unused]] const ir::MethodDefinition *node) cons ES2PANDA_UNREACHABLE(); } +void JSCompiler::Compile([[maybe_unused]] const ir::OverloadDeclaration *node) const +{ + ES2PANDA_UNREACHABLE(); +} + void JSCompiler::Compile([[maybe_unused]] const ir::Property *expr) const { ES2PANDA_UNREACHABLE(); diff --git a/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp b/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp index bf69507850..2c0f2d3203 100644 --- a/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp +++ b/ets2panda/compiler/lowering/ets/defaultParametersInConstructorLowering.cpp @@ -181,7 +181,7 @@ static void CreateFunctionOverload(ir::MethodDefinition *method, ArenaVector( allocator, method->Kind(), ident, funcExpression, method->Modifiers(), allocator, false); - overloadMethod->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD); + overloadMethod->Function()->AddFlag(ir::ScriptFunctionFlags::OVERLOAD | ir::ScriptFunctionFlags::SYNTHETIC); overloadMethod->SetRange(funcExpression->Range()); if (!method->IsDeclare() && method->Parent()->IsTSInterfaceBody()) { diff --git a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp index 2833087baa..753e708f12 100644 --- a/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp +++ b/ets2panda/compiler/lowering/ets/interfaceObjectLiteralLowering.cpp @@ -126,6 +126,10 @@ static void FillClassBody(public_lib::Context *ctx, ArenaVector * checker::ETSObjectType *currentType = nullptr) { for (auto *it : ifaceBody) { + if (it->IsOverloadDeclaration()) { + continue; + } + ES2PANDA_ASSERT(it->IsMethodDefinition()); auto *ifaceMethod = it->AsMethodDefinition(); @@ -375,6 +379,9 @@ static void HandleInterfaceLowering(public_lib::Context *ctx, ir::ObjectExpressi static bool CheckInterfaceShouldGenerateAnonClass(ir::TSInterfaceDeclaration *interfaceDecl) { for (auto it : interfaceDecl->Body()->Body()) { + if (it->IsOverloadDeclaration()) { + continue; + } ES2PANDA_ASSERT(it->IsMethodDefinition()); auto methodDef = it->AsMethodDefinition(); if (!methodDef->Function()->IsGetter() && !methodDef->Function()->IsSetter()) { diff --git a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp index 0c4e4caf52..befb732fa6 100644 --- a/ets2panda/compiler/lowering/ets/lambdaLowering.cpp +++ b/ets2panda/compiler/lowering/ets/lambdaLowering.cpp @@ -1223,6 +1223,17 @@ static bool IsValidFunctionDeclVar(const varbinder::Variable *const var) !var->TsType()->HasTypeFlag(checker::TypeFlag::GETTER_SETTER); } +static bool IsOverloadedName(ir::Expression *const expr) +{ + if ((!expr->IsIdentifier() && !expr->IsMemberExpression()) || !expr->Parent()->IsOverloadDeclaration()) { + return false; + } + + auto overloadedList = expr->Parent()->AsOverloadDeclaration()->OverloadedList(); + return std::any_of(overloadedList.begin(), overloadedList.end(), + [&expr](const ir::Expression *overloadedName) { return overloadedName == expr; }); +} + static ir::AstNode *BuildLambdaClassWhenNeeded(public_lib::Context *ctx, ir::AstNode *node) { if (node->IsArrowFunctionExpression()) { @@ -1236,7 +1247,7 @@ static ir::AstNode *BuildLambdaClassWhenNeeded(public_lib::Context *ctx, ir::Ast // so it is correct to pass ETS extension here to isReference() if (id->IsReference(ScriptExtension::ETS) && id->TsType() != nullptr && id->TsType()->IsETSFunctionType() && !IsInCalleePosition(id) && !IsEnumFunctionCall(id) && IsValidFunctionDeclVar(var) && - !id->Variable()->HasFlag(varbinder::VariableFlags::DYNAMIC)) { + !id->Variable()->HasFlag(varbinder::VariableFlags::DYNAMIC) && !IsOverloadedName(id)) { return ConvertFunctionReference(ctx, id); } } @@ -1250,7 +1261,7 @@ static ir::AstNode *BuildLambdaClassWhenNeeded(public_lib::Context *ctx, ir::Ast checker::PropertySearchFlags::SEARCH_INSTANCE_METHOD | checker::PropertySearchFlags::SEARCH_STATIC_METHOD | checker::PropertySearchFlags::SEARCH_IN_BASE | checker::PropertySearchFlags::DISALLOW_SYNTHETIC_METHOD_CREATION); - if (IsValidFunctionDeclVar(var) && !IsInCalleePosition(mexpr)) { + if (IsValidFunctionDeclVar(var) && !IsInCalleePosition(mexpr) && !IsOverloadedName(mexpr)) { return ConvertFunctionReference(ctx, mexpr); } } diff --git a/ets2panda/compiler/lowering/ets/overloadMappingLowering.cpp b/ets2panda/compiler/lowering/ets/overloadMappingLowering.cpp new file mode 100644 index 0000000000..a72a5c6517 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/overloadMappingLowering.cpp @@ -0,0 +1,83 @@ +/* + * 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 "overloadMappingLowering.h" +#include "checker/ETSchecker.h" +#include "compiler/lowering/util.h" + +namespace ark::es2panda::compiler { + +using AstNodePtr = ir::AstNode *; + +std::string_view OverloadMappingLowering::Name() const +{ + return "OverloadMappingLowering"; +} + +static ir::CallExpression *MethodMapping(public_lib::Context *ctx, ir::CallExpression *callExpression) +{ + auto *checker = ctx->GetChecker()->AsETSChecker(); + auto *allocator = ctx->Allocator(); + + auto *signature = callExpression->Signature(); + ES2PANDA_ASSERT(signature->OwnerVar()->Declaration()->Node()->IsMethodDefinition()); + auto *methodDef = signature->OwnerVar()->Declaration()->Node()->AsMethodDefinition(); + + ir::AstNode *callee = callExpression->Callee(); + while (callee->IsMemberExpression()) { + callee = callee->AsMemberExpression()->Property(); + } + auto *ident = callee->AsIdentifier(); + ident->SetName(methodDef->Id()->Name()); + + varbinder::LocalVariable *syntheticVariable = allocator->New( + varbinder::VariableFlags::SYNTHETIC | varbinder::VariableFlags::METHOD); + ident->SetVariable(syntheticVariable); + checker::ETSFunctionType *funcType = + checker->CreateETSMethodType(methodDef->Id()->Name(), {{}, allocator->Adapter()}); + funcType->AddCallSignature(signature); + syntheticVariable->SetTsType(funcType); + + return callExpression; +} + +static bool IsOverloadDeclarationCall(ir::Expression *expr) +{ + while (expr->IsMemberExpression()) { + expr = expr->AsMemberExpression()->Property(); + } + + if (expr->IsIdentifier() && expr->AsIdentifier()->Variable() != nullptr) { + return expr->AsIdentifier()->Variable()->HasFlag(varbinder::VariableFlags::OVERLOAD); + } + return false; +} + +bool OverloadMappingLowering::PerformForModule(public_lib::Context *ctx, parser::Program *program) +{ + program->Ast()->TransformChildrenRecursively( + // CC-OFFNXT(G.FMT.14-CPP) project code style + [ctx](ir::AstNode *const node) -> AstNodePtr { + if (node->IsCallExpression() && IsOverloadDeclarationCall(node->AsCallExpression()->Callee())) { + return MethodMapping(ctx, node->AsCallExpression()); + } + return node; + }, + Name()); + + return true; +} + +} // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/ets/overloadMappingLowering.h b/ets2panda/compiler/lowering/ets/overloadMappingLowering.h new file mode 100644 index 0000000000..2efcadbdc4 --- /dev/null +++ b/ets2panda/compiler/lowering/ets/overloadMappingLowering.h @@ -0,0 +1,31 @@ +/* + * 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. + */ + +#ifndef ES2PANDA_COMPILER_LOWERING_OVERLOAD_MAPPING_LOWERING_H +#define ES2PANDA_COMPILER_LOWERING_OVERLOAD_MAPPING_LOWERING_H + +#include "compiler/lowering/phase.h" + +namespace ark::es2panda::compiler { + +class OverloadMappingLowering : public PhaseForDeclarations { +public: + std::string_view Name() const override; + bool PerformForModule(public_lib::Context *ctx, parser::Program *program) override; +}; + +} // namespace ark::es2panda::compiler + +#endif diff --git a/ets2panda/compiler/lowering/ets/restTupleLowering.cpp b/ets2panda/compiler/lowering/ets/restTupleLowering.cpp index 9d388f9afb..c01e578292 100644 --- a/ets2panda/compiler/lowering/ets/restTupleLowering.cpp +++ b/ets2panda/compiler/lowering/ets/restTupleLowering.cpp @@ -261,7 +261,7 @@ ir::ScriptFunction *CreateNewScriptFunction(public_lib::Context *ctx, ir::Script auto *newScriptFunc = ctx->AllocNode( allocator, ir::ScriptFunction::ScriptFunctionData { body, ir::FunctionSignature(newParamDeclaration, std::move(newParams), newReturnTypeAnno), - scriptFunc->Flags()}); + scriptFunc->Flags() | ir::ScriptFunctionFlags::SYNTHETIC}); newScriptFunc->AddModifier(scriptFunc->AsScriptFunction()->Modifiers()); ArenaVector annotationUsages {allocator->Adapter()}; diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.cpp index 1560a75375..4c4576fa1b 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.cpp @@ -48,6 +48,11 @@ void GlobalDeclTransformer::VisitExpressionStatement(ir::ExpressionStatement *ex result_.immediateInit.emplace_back(exprStmt); } +void GlobalDeclTransformer::VisitOverloadDeclaration(ir::OverloadDeclaration *overloadDeclaration) +{ + result_.classProperties.emplace_back(overloadDeclaration); +} + void GlobalDeclTransformer::VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl) { auto *funcExpr = util::NodeAllocator::ForceSetParent(allocator_, funcDecl->Function()); diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h b/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h index eada14a27c..e8631b95a2 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/globalDeclTransformer.h @@ -79,6 +79,7 @@ public: */ ResultT TransformStatements(const ArenaVector &stmts); + void VisitOverloadDeclaration(ir::OverloadDeclaration *overloadDeclaration) override; void VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl) override; void VisitVariableDeclaration(ir::VariableDeclaration *varDecl) override; void VisitClassStaticBlock(ir::ClassStaticBlock *classStaticBlock) override; diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp index f173d3fa47..54dfc6d2f4 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.cpp @@ -176,6 +176,11 @@ void ImportExportDecls::VisitFunctionDeclaration(ir::FunctionDeclaration *funcDe fieldMap_.emplace(funcDecl->Function()->Id()->Name(), funcDecl->Function()); } +void ImportExportDecls::VisitOverloadDeclaration(ir::OverloadDeclaration *overloadDeclaration) +{ + fieldMap_.emplace(overloadDeclaration->Id()->Name(), overloadDeclaration); +} + void ImportExportDecls::VisitVariableDeclaration(ir::VariableDeclaration *varDecl) { for (const auto &decl : varDecl->Declarators()) { diff --git a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.h b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.h index c6c8f76314..27b17db341 100644 --- a/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.h +++ b/ets2panda/compiler/lowering/ets/topLevelStmts/importExportDecls.h @@ -74,6 +74,7 @@ public: void PreMergeNamespaces(parser::Program *program); private: + void VisitOverloadDeclaration(ir::OverloadDeclaration *overloadDeclaration) override; void VisitFunctionDeclaration(ir::FunctionDeclaration *funcDecl) override; void VisitVariableDeclaration(ir::VariableDeclaration *varDecl) override; void VisitExportNamedDeclaration(ir::ExportNamedDeclaration *exportDecl) override; diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index 18eefa5f2d..800aef488d 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -54,6 +54,7 @@ #include "compiler/lowering/ets/opAssignment.h" #include "compiler/lowering/ets/optionalArgumentsLowering.h" #include "compiler/lowering/ets/optionalLowering.h" +#include "compiler/lowering/ets/overloadMappingLowering.h" #include "compiler/lowering/ets/packageImplicitImport.h" #include "compiler/lowering/ets/partialExportClassGen.h" #include "compiler/lowering/ets/primitiveConversionPhase.h" @@ -135,6 +136,7 @@ std::vector GetETSPhaseList() new AnnotationCopyPostLowering, new AsyncMethodLowering, new DeclareOverloadLowering, + new OverloadMappingLowering, new EnumPostCheckLoweringPhase, new SpreadConstructionPhase, new RestArgsLowering, diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index 49e83d88f1..c5a51475ae 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -414,7 +414,19 @@ void ScopesInitPhase::IterateNoTParams(ir::ClassDefinition *classDef) CallNode(classDef->Annotations()); CallNode(classDef->Implements()); CallNode(classDef->Ctor()); - CallNode(classDef->Body()); + + for (auto property : classDef->Body()) { + if (property->IsOverloadDeclaration()) { + continue; + } + CallNode(property); + } + + for (auto property : classDef->Body()) { + if (property->IsOverloadDeclaration()) { + CallNode(property); + } + } } void ScopesInitPhase::LogDiagnostic(const diagnostic::DiagnosticKind &kind, const util::DiagnosticMessageParams ¶ms, @@ -1036,6 +1048,96 @@ void InitScopesPhaseETS::MaybeAddOverload(ir::MethodDefinition *method, ir::Iden } } +void InitScopesPhaseETS::VisitOverloadDeclaration(ir::OverloadDeclaration *overload) +{ + auto *curScope = VarBinder()->GetScope(); + const auto overloadName = overload->Id(); + auto res = + curScope->Find(overloadName->Name(), overload->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC + : varbinder::ResolveBindingOptions::ALL_NON_STATIC); + if (res.variable != nullptr) { + VarBinder()->ThrowRedeclaration(overloadName->Start(), res.name, varbinder::DeclType::METHOD); + } + + auto result = curScope->FindLocal(overloadName->Name(), varbinder::ResolveBindingOptions::ALL_DECLARATION); + if (result != nullptr) { + VarBinder()->ThrowLocalRedeclaration(overloadName->Start(), result->Name()); + } + + Iterate(overload); + DeclareClassOverload(overload); +} + +varbinder::LocalScope *InitScopesPhaseETS::OverloadTargetScope(ir::OverloadDeclaration *overloadDef, + varbinder::ClassScope *clsScope) +{ + varbinder::LocalScope *targetScope {}; + if (overloadDef->IsConstructorOverloadDeclaration()) { + targetScope = clsScope->StaticMethodScope(); + + auto *found = targetScope->FindLocal(Signatures::CONSTRUCTOR_NAME, varbinder::ResolveBindingOptions::BINDINGS); + if (found == nullptr || + (!overloadDef->OverloadedList().empty() && overloadDef->OverloadedList().front()->IsIdentifier() && + overloadDef->OverloadedList().front()->AsIdentifier()->Name().Is(Signatures::CONSTRUCTOR_NAME))) { + return targetScope; + } + ir::Identifier *anonyConstructor = Allocator()->New(Signatures::CONSTRUCTOR_NAME, Allocator()); + overloadDef->PushFront(anonyConstructor); + anonyConstructor->SetParent(overloadDef); + } else { + targetScope = overloadDef->IsStatic() ? clsScope->StaticMethodScope() : clsScope->InstanceMethodScope(); + } + + return targetScope; +} + +void InitScopesPhaseETS::DeclareClassOverload(ir::OverloadDeclaration *overloadDef) +{ + ES2PANDA_ASSERT(VarBinder()->GetScope()->IsClassScope()); + + const auto overloadName = overloadDef->Id(); + auto *const clsScope = VarBinder()->GetScope()->AsClassScope(); + auto options = + overloadDef->IsStatic() + ? varbinder::ResolveBindingOptions::STATIC_VARIABLES | varbinder::ResolveBindingOptions::STATIC_DECLARATION + : varbinder::ResolveBindingOptions::VARIABLES | varbinder::ResolveBindingOptions::DECLARATION; + auto variable = clsScope->FindLocal(overloadName->Name(), options); + if (variable != nullptr) { + VarBinder()->ThrowRedeclaration(overloadName->Start(), overloadName->Name(), variable->Declaration()->Type()); + } + + varbinder::LocalScope *targetScope = OverloadTargetScope(overloadDef, clsScope); + for (auto *methodName : overloadDef->OverloadedList()) { + if (!methodName->IsIdentifier()) { + continue; + } + + auto *found = + targetScope->FindLocal(methodName->AsIdentifier()->Name(), varbinder::ResolveBindingOptions::BINDINGS); + + if (found == nullptr) { + continue; + } + + if (!found->Declaration()->Node()->IsMethodDefinition()) { + VarBinder()->ThrowError(methodName->Start(), diagnostic::OVERLOADED_NAME_MUST_FUNCTION); + continue; + } + + methodName->SetVariable(found); + } + + auto classCtx = varbinder::LexicalScope::Enter(VarBinder(), targetScope); + auto var = std::get<1>(VarBinder()->NewVarDecl(overloadName->Start(), Allocator(), + overloadName->Name(), overloadDef)); + var->SetScope(clsScope); + if (targetScope->HasFlag(varbinder::ScopeFlags::STATIC)) { + var->AddFlag(varbinder::VariableFlags::STATIC); + } + var->AddFlag(varbinder::VariableFlags::OVERLOAD); + overloadName->SetVariable(var); +} + void InitScopesPhaseETS::VisitETSReExportDeclaration(ir::ETSReExportDeclaration *reExport) { if (!reExport->GetETSImportDeclarations()->IsValid()) { @@ -1270,7 +1372,18 @@ void InitScopesPhaseETS::VisitClassDefinition(ir::ClassDefinition *classDef) void InitScopesPhaseETS::VisitTSInterfaceBody(ir::TSInterfaceBody *interfBody) { - Iterate(interfBody); + for (auto property : interfBody->Body()) { + if (property->IsOverloadDeclaration()) { + continue; + } + CallNode(property); + } + + for (auto property : interfBody->Body()) { + if (property->IsOverloadDeclaration()) { + CallNode(property); + } + } FilterInterfaceOverloads(interfBody->Body()); } diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h index e3b5d7e556..75f98406d4 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h @@ -344,6 +344,8 @@ private: void DeclareClassMethod(ir::MethodDefinition *method); void MaybeAddOverload(ir::MethodDefinition *method, ir::Identifier *methodName, varbinder::Variable *found, varbinder::ClassScope *clsScope, varbinder::LocalScope *targetScope); + void DeclareClassOverload(ir::OverloadDeclaration *overloadDef); + varbinder::LocalScope *OverloadTargetScope(ir::OverloadDeclaration *overloadDef, varbinder::ClassScope *clsScope); void VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock) override; void VisitBlockExpression(ir::BlockExpression *blockExpr) override; @@ -354,6 +356,7 @@ private: void VisitETSParameterExpression(ir::ETSParameterExpression *paramExpr) override; void VisitETSImportDeclaration(ir::ETSImportDeclaration *importDecl) override; void VisitTSEnumMember(ir::TSEnumMember *enumMember) override; + void VisitOverloadDeclaration(ir::OverloadDeclaration *overload) override; void VisitMethodDefinition(ir::MethodDefinition *method) override; void VisitETSFunctionType(ir::ETSFunctionType *funcType) override; void VisitETSNewClassInstanceExpression(ir::ETSNewClassInstanceExpression *newClassExpr) override; diff --git a/ets2panda/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index 5f96465346..d44d0d0c16 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -109,6 +109,9 @@ defines: - name: ets/annotation/FunctionalReference ref: ETS_ANNOTATION_FUNCTIONAL_REFERENCE comment: Ets record + - name: ets/annotation/FunctionOverload + ref: ETS_ANNOTATION_FUNCTION_OVERLOAD + comment: Ets record - name: ets/coroutine/Async ref: ETS_COROUTINE_ASYNC - name: ets/annotation/DynamicCall @@ -248,6 +251,10 @@ defines: ref: UNUSED_ETSGLOBAL_MAIN - name: "initialize" ref: CLASS_INITIALIZE_METHOD + - name: 'constructor' + ref: CONSTRUCTOR_NAME + - name: 'gensym%%_constructor_overload_declaration' + ref: CONSTRUCTOR_OVERLOAD_DEFINITION_NAME packages: - name: 'std.core' diff --git a/ets2panda/ir/astNode.cpp b/ets2panda/ir/astNode.cpp index 696841c7b6..8114961153 100644 --- a/ets2panda/ir/astNode.cpp +++ b/ets2panda/ir/astNode.cpp @@ -88,13 +88,13 @@ void AstNode::ClearScope() noexcept ir::ClassElement *AstNode::AsClassElement() { - ES2PANDA_ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock()); + ES2PANDA_ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock() || IsOverloadDeclaration()); return reinterpret_cast(this); } const ir::ClassElement *AstNode::AsClassElement() const { - ES2PANDA_ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock()); + ES2PANDA_ASSERT(IsMethodDefinition() || IsClassProperty() || IsClassStaticBlock() || IsOverloadDeclaration()); return reinterpret_cast(this); } @@ -312,4 +312,13 @@ bool AstNode::HistoryInitialized() const return history_ != nullptr; } +void AstNode::CleanCheckInformation() +{ + if (IsTyped()) { + this->AsTyped()->SetTsType(nullptr); + this->AsTyped()->SetPreferredType(nullptr); + } + Iterate([&](auto *childNode) { childNode->CleanCheckInformation(); }); +} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/astNode.h b/ets2panda/ir/astNode.h index 3f5a8edd9a..751d44cefc 100644 --- a/ets2panda/ir/astNode.h +++ b/ets2panda/ir/astNode.h @@ -690,6 +690,8 @@ public: AstNode *GetOrCreateHistoryNode() const; + virtual void CleanCheckInformation(); + protected: AstNode(AstNode const &other); diff --git a/ets2panda/ir/astNodeFlags.h b/ets2panda/ir/astNodeFlags.h index ea8783348a..86f9c39c08 100644 --- a/ets2panda/ir/astNodeFlags.h +++ b/ets2panda/ir/astNodeFlags.h @@ -81,7 +81,18 @@ enum class ModifierFlags : uint32_t { EXPORTED = EXPORT | DEFAULT_EXPORT | EXPORT_TYPE }; -enum class PrivateFieldKind { FIELD, METHOD, GET, SET, STATIC_FIELD, STATIC_METHOD, STATIC_GET, STATIC_SET }; +enum class PrivateFieldKind { + FIELD, + METHOD, + GET, + SET, + STATIC_FIELD, + STATIC_METHOD, + STATIC_GET, + STATIC_SET, + OVERLOAD, + STATIC_OVERLOAD +}; enum class ScriptFunctionFlags : uint32_t { NONE = 0U, @@ -109,6 +120,7 @@ enum class ScriptFunctionFlags : uint32_t { HAS_THROW = 1U << 21U, IN_RECORD = 1U << 22U, TRAILING_LAMBDA = 1U << 23U, + SYNTHETIC = 1U << 24U, }; enum class TSOperatorType { READONLY, KEYOF, UNIQUE }; diff --git a/ets2panda/ir/astNodeMapping.h b/ets2panda/ir/astNodeMapping.h index 06ece5eff0..34908d0e7c 100644 --- a/ets2panda/ir/astNodeMapping.h +++ b/ets2panda/ir/astNodeMapping.h @@ -73,6 +73,7 @@ _(UNDEFINED_LITERAL, UndefinedLiteral) \ _(NUMBER_LITERAL, NumberLiteral) \ _(OMITTED_EXPRESSION, OmittedExpression) \ + _(OVERLOAD_DECLARATION, OverloadDeclaration) \ _(PREFIX_ASSERTION_EXPRESSION, PrefixAssertionExpression) \ _(PROPERTY, Property) \ _(REGEXP_LITERAL, RegExpLiteral) \ diff --git a/ets2panda/ir/base/methodDefinition.cpp b/ets2panda/ir/base/methodDefinition.cpp index 6f705a2f97..c226b741b3 100644 --- a/ets2panda/ir/base/methodDefinition.cpp +++ b/ets2panda/ir/base/methodDefinition.cpp @@ -345,6 +345,11 @@ void MethodDefinition::Dump(ir::SrcDumper *dumper) const } DumpPrefix(dumper); + if (IsConstructor() && + !(Key()->IsIdentifier() && Key()->AsIdentifier()->Name().Is(compiler::Signatures::CONSTRUCTOR_NAME))) { + dumper->Add(std::string(compiler::Signatures::CONSTRUCTOR_NAME) + " "); + } + auto key = Key(); if (key != nullptr) { key->Dump(dumper); diff --git a/ets2panda/ir/base/overloadDeclaration.cpp b/ets2panda/ir/base/overloadDeclaration.cpp new file mode 100644 index 0000000000..7af8f592ff --- /dev/null +++ b/ets2panda/ir/base/overloadDeclaration.cpp @@ -0,0 +1,134 @@ +/* + * 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 "overloadDeclaration.h" +#include "checker/ETSchecker.h" +#include "compiler/lowering/util.h" + +namespace ark::es2panda::ir { +PrivateFieldKind OverloadDeclaration::ToPrivateFieldKind(bool const isStatic) const +{ + return isStatic ? PrivateFieldKind::STATIC_OVERLOAD : PrivateFieldKind::OVERLOAD; +} + +void OverloadDeclaration::ResolveReferences(const NodeTraverser &cb) const +{ + cb(key_); + + for (auto *it : VectorIterationGuard(overloadedList_)) { + cb(it); + } +} + +void OverloadDeclaration::TransformChildren(const NodeTransformer &cb, std::string_view const transformationName) +{ + cb(key_); + for (auto *&it : VectorIterationGuard(overloadedList_)) { + if (auto *transformedNode = cb(it); it != transformedNode) { + it->SetTransformedNode(transformationName, transformedNode); + it = transformedNode->AsIdentifier(); + } + } +} + +void OverloadDeclaration::Iterate(const NodeTraverser &cb) const +{ + cb(key_); + for (auto *it : VectorIterationGuard(overloadedList_)) { + cb(it); + } +} + +void OverloadDeclaration::Dump(ir::AstDumper *dumper) const +{ + dumper->Add({{"type", "OverloadDeclaration"}, + {"key", key_}, + {"optional", AstDumper::Optional(AstDumper::ModifierToString(flags_))}, + {"static", IsStatic()}, + {"overloadedList", overloadedList_}}); +} + +void OverloadDeclaration::DumpModifier(ir::SrcDumper *dumper) const +{ + if (compiler::HasGlobalClassParent(this) && !dumper->IsDeclgen()) { + if (IsExported()) { + dumper->Add("export "); + } + } + + if (Parent() != nullptr && Parent()->IsClassDefinition() && !Parent()->AsClassDefinition()->IsLocal() && + !compiler::HasGlobalClassParent(this)) { + if (IsPrivate()) { + dumper->Add("private "); + } else if (IsProtected()) { + dumper->Add("protected "); + } else if (IsInternal()) { + dumper->Add("internal "); + } else { + dumper->Add("public "); + } + + if (IsStatic()) { + dumper->Add("static "); + } + } + + if (IsAsync()) { + dumper->Add("async "); + } +} + +void OverloadDeclaration::Dump(ir::SrcDumper *dumper) const +{ + DumpModifier(dumper); + dumper->Add("overload "); + dumper->Add(IsConstructor() ? "constructor " : key_->AsIdentifier()->Name().Mutf8()); + dumper->Add("{"); + for (size_t i = 0; i < overloadedList_.size(); i++) { + if (i != 0) { + dumper->Add(", "); + } + overloadedList_[i]->Dump(dumper); + } + dumper->Add("};"); +} + +void OverloadDeclaration::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} + +checker::Type *OverloadDeclaration::Check([[maybe_unused]] checker::TSChecker *checker) +{ + return nullptr; +} + +checker::VerifiedType OverloadDeclaration::Check([[maybe_unused]] checker::ETSChecker *checker) +{ + return {this, checker->GetAnalyzer()->Check(this)}; +} + +OverloadDeclaration *OverloadDeclaration::Construct(ArenaAllocator *allocator) +{ + return allocator->New(nullptr, ModifierFlags::NONE, allocator); +} + +void OverloadDeclaration::CopyTo(AstNode *other) const +{ + auto otherImpl = other->AsOverloadDeclaration(); + + otherImpl->overloadFlags_ = overloadFlags_; + otherImpl->overloadedList_ = overloadedList_; + ClassElement::CopyTo(other); +} + +} // namespace ark::es2panda::ir \ No newline at end of file diff --git a/ets2panda/ir/base/overloadDeclaration.h b/ets2panda/ir/base/overloadDeclaration.h new file mode 100644 index 0000000000..667c653f8d --- /dev/null +++ b/ets2panda/ir/base/overloadDeclaration.h @@ -0,0 +1,140 @@ +/** + * 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. + */ + +#ifndef ES2PANDA_IR_OVERLOAD_DEFINITION_H +#define ES2PANDA_IR_OVERLOAD_DEFINITION_H + +#include "classDefinition.h" +#include "ir/typeNode.h" +#include "methodDefinition.h" + +namespace ark::es2panda::ir { + +using ENUMBITOPS_OPERATORS; + +enum class OverloadDeclFlags : std::uint8_t { + NONE = 0U, + FUNCTION = 1U << 0U, // Function Overload Declaration + CLASS_METHOD = 1U << 1U, // Class Method Overload Declaration + INTERFACE_METHOD = 1U << 2U, // Interface Method Overload Declaration + // CONSTURCTOR = 1U << 3U, // Constructor Overload Declarations +}; +} // namespace ark::es2panda::ir + +namespace enumbitops { + +template <> +struct IsAllowedType : std::true_type { +}; + +} // namespace enumbitops + +namespace ark::es2panda::ir { +class OverloadDeclaration : public ClassElement { +public: + OverloadDeclaration() = delete; + ~OverloadDeclaration() override = default; + + NO_COPY_SEMANTIC(OverloadDeclaration); + NO_MOVE_SEMANTIC(OverloadDeclaration); + + explicit OverloadDeclaration(Expression *const key, ModifierFlags const modifiers, ArenaAllocator *const allocator) + : ClassElement(AstNodeType::OVERLOAD_DECLARATION, key, nullptr, modifiers, allocator, false), + overloadedList_(allocator->Adapter()), + overloadFlags_(OverloadDeclFlags::NONE) + { + InitHistory(); + } + + OverloadDeclFlags Flag() const + { + return GetHistoryNodeAs()->overloadFlags_; + } + + [[nodiscard]] ArenaVector &OverloadedList() noexcept + { + return GetOrCreateHistoryNodeAs()->overloadedList_; + } + + void SetOverloadedList(ArenaVector overloadedList) + { + auto newNode = GetOrCreateHistoryNodeAs(); + newNode->overloadedList_ = std::move(overloadedList); + } + + void PushFront(Identifier *const overloadedExpression) + { + auto newNode = GetOrCreateHistoryNodeAs(); + newNode->overloadedList_.insert(overloadedList_.begin(), overloadedExpression); + } + + void AddOverloadDeclFlag(OverloadDeclFlags overloadFlag) + { + auto newNode = GetOrCreateHistoryNodeAs(); + newNode->overloadFlags_ |= overloadFlag; + } + + [[nodiscard]] bool HasOverloadDeclFlag(OverloadDeclFlags overloadFlag) const + { + return (Flag() & overloadFlag) != 0; + } + + [[nodiscard]] bool IsConstructorOverloadDeclaration() + { + return IsConstructor(); + } + + [[nodiscard]] bool IsFunctionOverloadDeclaration() + { + return (Flag() & OverloadDeclFlags::FUNCTION) != 0; + } + + [[nodiscard]] bool IsClassMethodOverloadDeclaration() + { + return (Flag() & OverloadDeclFlags::CLASS_METHOD) != 0; + } + + [[nodiscard]] bool IsInterfaceMethodOverloadDeclaration() + { + return (Flag() & OverloadDeclFlags::INTERFACE_METHOD) != 0; + } + + void ResolveReferences(const NodeTraverser &cb) const; + + PrivateFieldKind ToPrivateFieldKind(bool isStatic) const override; + void TransformChildren(const NodeTransformer &cb, std::string_view transformationName) override; + void Iterate(const NodeTraverser &cb) const override; + void Dump(ir::AstDumper *dumper) const override; + void Dump(ir::SrcDumper *dumper) const override; + void DumpModifier(ir::SrcDumper *dumper) const; + void Compile([[maybe_unused]] compiler::PandaGen *pg) const override; + checker::Type *Check([[maybe_unused]] checker::TSChecker *checker) override; + checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; + void Accept(ASTVisitorT *v) override + { + v->Accept(this); + } + +protected: + OverloadDeclaration *Construct(ArenaAllocator *allocator) override; + void CopyTo(AstNode *other) const override; + +private: + ArenaVector overloadedList_; + OverloadDeclFlags overloadFlags_; +}; +} // namespace ark::es2panda::ir + +#endif diff --git a/ets2panda/ir/base/scriptFunction.h b/ets2panda/ir/base/scriptFunction.h index 56ba72e368..f8d619152e 100644 --- a/ets2panda/ir/base/scriptFunction.h +++ b/ets2panda/ir/base/scriptFunction.h @@ -257,6 +257,11 @@ public: return (Flags() & ir::ScriptFunctionFlags::TRAILING_LAMBDA) != 0; } + [[nodiscard]] bool IsSynthetic() const noexcept + { + return (Flags() & ir::ScriptFunctionFlags::SYNTHETIC) != 0; + } + [[nodiscard]] bool IsDynamic() const noexcept { return Language().IsDynamic(); diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp index db8c7b5eea..638627789f 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.cpp @@ -109,6 +109,15 @@ void ETSNewArrayInstanceExpression::ClearPreferredType() SetTsType(nullptr); } +void ETSNewArrayInstanceExpression::CleanCheckInformation() +{ + SetPreferredType(nullptr); + SetTsType(nullptr); + if (dimension_ != nullptr) { + dimension_->CleanCheckInformation(); + } +} + void ETSNewArrayInstanceExpression::SetPreferredTypeBasedOnFuncParam(checker::ETSChecker *checker, checker::Type *param, checker::TypeRelationFlag flags) { diff --git a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h index b1b4885340..002a1cb1a6 100644 --- a/ets2panda/ir/ets/etsNewArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewArrayInstanceExpression.h @@ -113,6 +113,7 @@ public: } void ClearPreferredType(); + void CleanCheckInformation() override; private: ir::TypeNode *typeReference_; diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp index d5cd0530e8..f18b4e7a3a 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.cpp @@ -89,6 +89,15 @@ void ETSNewMultiDimArrayInstanceExpression::ClearPreferredType() SetTsType(nullptr); } +void ETSNewMultiDimArrayInstanceExpression::CleanCheckInformation() +{ + SetPreferredType(nullptr); + SetTsType(nullptr); + for (auto *dim : dimensions_) { + dim->CleanCheckInformation(); + } +} + ETSNewMultiDimArrayInstanceExpression::ETSNewMultiDimArrayInstanceExpression( ETSNewMultiDimArrayInstanceExpression const &other, ArenaAllocator *const allocator) : Expression(static_cast(other)), diff --git a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h index 31aab67ffa..20d8be5d48 100644 --- a/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h +++ b/ets2panda/ir/ets/etsNewMultiDimArrayInstanceExpression.h @@ -110,6 +110,7 @@ public: } void ClearPreferredType(); + void CleanCheckInformation() override; private: ir::TypeNode *typeReference_; diff --git a/ets2panda/ir/ets/etsUnionType.cpp b/ets2panda/ir/ets/etsUnionType.cpp index de035bcd61..19f2311988 100644 --- a/ets2panda/ir/ets/etsUnionType.cpp +++ b/ets2panda/ir/ets/etsUnionType.cpp @@ -49,6 +49,7 @@ void ETSUnionType::Dump(ir::AstDumper *dumper) const void ETSUnionType::Dump(ir::SrcDumper *dumper) const { + dumper->Add("("); for (auto *anno : Annotations()) { anno->Dump(dumper); } @@ -58,6 +59,7 @@ void ETSUnionType::Dump(ir::SrcDumper *dumper) const dumper->Add(" | "); } } + dumper->Add(")"); } void ETSUnionType::Compile([[maybe_unused]] compiler::PandaGen *pg) const {} diff --git a/ets2panda/ir/expressions/arrayExpression.cpp b/ets2panda/ir/expressions/arrayExpression.cpp index 418e936818..3e0a753d33 100644 --- a/ets2panda/ir/expressions/arrayExpression.cpp +++ b/ets2panda/ir/expressions/arrayExpression.cpp @@ -363,6 +363,16 @@ void ArrayExpression::ClearPreferredType() } } +void ArrayExpression::CleanCheckInformation() +{ + SetPreferredType(nullptr); + SetTsType(nullptr); + for (auto *element : elements_) { + element->SetAstNodeFlags(ir::AstNodeFlags::NO_OPTS); + element->CleanCheckInformation(); + } +} + bool ArrayExpression::TrySetPreferredTypeForNestedArrayExpr(checker::ETSChecker *const checker, ArrayExpression *const nestedArrayExpr, const std::size_t idx) const diff --git a/ets2panda/ir/expressions/arrayExpression.h b/ets2panda/ir/expressions/arrayExpression.h index f2028094c1..c49bd60998 100644 --- a/ets2panda/ir/expressions/arrayExpression.h +++ b/ets2panda/ir/expressions/arrayExpression.h @@ -121,6 +121,7 @@ public: } void ClearPreferredType(); + void CleanCheckInformation() override; [[nodiscard]] ArrayExpression *Clone(ArenaAllocator *allocator, AstNode *parent) override; diff --git a/ets2panda/ir/expressions/memberExpression.cpp b/ets2panda/ir/expressions/memberExpression.cpp index 4fde4e957d..ae65ae697c 100644 --- a/ets2panda/ir/expressions/memberExpression.cpp +++ b/ets2panda/ir/expressions/memberExpression.cpp @@ -207,6 +207,11 @@ checker::Type *MemberExpression::TraverseUnionMember(checker::ETSChecker *checke return; } + if (memberType->IsETSMethodType() && memberType->Variable()->HasFlag(varbinder::VariableFlags::OVERLOAD)) { + checker->LogError(diagnostic::OVERLOADED_UNION_CALL, {}, Start()); + return; + } + if (!commonPropType->IsETSMethodType() && !memberType->IsETSMethodType()) { if (!checker->IsTypeIdenticalTo(commonPropType, memberType)) { checker->LogError(diagnostic::MEMBER_TYPE_MISMATCH_ACROSS_UNION, {}, Start()); diff --git a/ets2panda/ir/expressions/objectExpression.cpp b/ets2panda/ir/expressions/objectExpression.cpp index 81da3dda08..062a325899 100644 --- a/ets2panda/ir/expressions/objectExpression.cpp +++ b/ets2panda/ir/expressions/objectExpression.cpp @@ -406,4 +406,11 @@ checker::VerifiedType ObjectExpression::Check(checker::ETSChecker *checker) { return {this, checker->GetAnalyzer()->Check(this)}; } + +void ObjectExpression::CleanCheckInformation() +{ + SetPreferredType(nullptr); + SetTsType(nullptr); + this->Iterate([&](auto *childNode) { childNode->CleanCheckInformation(); }); +} } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/expressions/objectExpression.h b/ets2panda/ir/expressions/objectExpression.h index 350633d4df..7c7abd4ca7 100644 --- a/ets2panda/ir/expressions/objectExpression.h +++ b/ets2panda/ir/expressions/objectExpression.h @@ -119,6 +119,8 @@ public: SetPreferredType(nullptr); } + void CleanCheckInformation() override; + private: std::tuple CheckPatternIsShorthand( CheckPatternIsShorthandArgs *args); diff --git a/ets2panda/ir/opaqueTypeNode.cpp b/ets2panda/ir/opaqueTypeNode.cpp index 4a74b38975..e6d0623f08 100644 --- a/ets2panda/ir/opaqueTypeNode.cpp +++ b/ets2panda/ir/opaqueTypeNode.cpp @@ -77,4 +77,7 @@ checker::VerifiedType OpaqueTypeNode::Check([[maybe_unused]] checker::ETSChecker { return {this, checker->GetAnalyzer()->Check(this)}; } + +void OpaqueTypeNode::CleanCheckInformation() {} + } // namespace ark::es2panda::ir diff --git a/ets2panda/ir/opaqueTypeNode.h b/ets2panda/ir/opaqueTypeNode.h index f4871890a3..acc764870a 100644 --- a/ets2panda/ir/opaqueTypeNode.h +++ b/ets2panda/ir/opaqueTypeNode.h @@ -48,6 +48,7 @@ public: checker::Type *GetType([[maybe_unused]] checker::TSChecker *checker) override; checker::VerifiedType Check([[maybe_unused]] checker::ETSChecker *checker) override; checker::Type *GetType([[maybe_unused]] checker::ETSChecker *checker) override; + void CleanCheckInformation() override; void Accept(ASTVisitorT *v) override { diff --git a/ets2panda/lexer/scripts/keywords.yaml b/ets2panda/lexer/scripts/keywords.yaml index 3b03c20867..58cffbda4f 100644 --- a/ets2panda/lexer/scripts/keywords.yaml +++ b/ets2panda/lexer/scripts/keywords.yaml @@ -421,6 +421,10 @@ keywords: token: KEYW_OUT keyword_like: [ets] + - name: 'overload' + token: KEYW_OVERLOAD + keyword: [ets] + - name: 'override' token: KEYW_OVERRIDE keyword: [ets] diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 3aae7a2ec9..aa2000a8af 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -635,9 +635,15 @@ ir::AstNode *ETSParser::ParseInnerConstructorDeclaration(ir::ModifierFlags membe 0) { LogError(diagnostic::INVALID_DECORATOR_CONSTRUCTOR); } - auto *memberName = AllocNode(Lexer()->GetToken().Ident(), Allocator()); + + lexer::Token constructorToken = Lexer()->GetToken(); + Lexer()->TryEatTokenType(lexer::TokenType::KEYW_CONSTRUCTOR); memberModifiers |= ir::ModifierFlags::CONSTRUCTOR; - Lexer()->NextToken(); + + ir::Identifier *memberName = Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT + ? ExpectIdentifier(false, true) + : AllocNode(constructorToken.Ident(), Allocator()); + auto *classMethod = ParseClassMethodDefinition(memberName, memberModifiers, isDefault); classMethod->SetStart(startLoc); @@ -697,6 +703,12 @@ ir::AstNode *ETSParser::ParseInnerRest(const ArenaVector &propert } } + if (Lexer()->TryEatTokenFromKeywordType(lexer::TokenType::KEYW_OVERLOAD)) { + auto *classOverload = ParseClassOverloadDeclaration(memberModifiers); + classOverload->SetStart(startLoc); + return classOverload; + } + auto *memberName = ExpectIdentifier(false, false, TypeAnnotationParsingOptions::NO_OPTS); // don't report error if (memberName == nullptr) { // log error here LogUnexpectedToken(Lexer()->GetToken()); @@ -2144,6 +2156,81 @@ void ETSParser::CheckDeclare() } } +void ETSParser::ValidateOverloadDeclarationModifiers(ir::ModifierFlags modifiers) +{ + ir::ModifierFlags allowModifiers = + ir::ModifierFlags::STATIC | ir::ModifierFlags::ASYNC | ir::ModifierFlags::ACCESS | ir::ModifierFlags::EXPORTED; + if ((modifiers & ~allowModifiers) != 0) { + LogError(diagnostic::OVERLOAD_MODIFIERS); + } +} + +bool ETSParser::ParseOverloadListElement(ArenaVector &overloads, + ir::OverloadDeclaration *overloadDecl) +{ + if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + LogExpectedToken(lexer::TokenType::LITERAL_IDENT); + } + ir::Expression *qualifiedName = AllocNode(Lexer()->GetToken().Ident(), Allocator()); + qualifiedName->SetRange(Lexer()->GetToken().Loc()); + Lexer()->NextToken(); + while (Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_PERIOD)) { + if (Lexer()->GetToken().Type() != lexer::TokenType::LITERAL_IDENT) { + LogExpectedToken(lexer::TokenType::LITERAL_IDENT); + } + auto *identNode = AllocNode(Lexer()->GetToken().Ident(), Allocator()); + identNode->SetRange(Lexer()->GetToken().Loc()); + auto start = qualifiedName->Start(); + qualifiedName = AllocNode(qualifiedName, identNode, + ir::MemberExpressionKind::PROPERTY_ACCESS, false, false); + qualifiedName->SetRange({start, identNode->End()}); + Lexer()->NextToken(); + } + + qualifiedName->SetParent(overloadDecl); + overloads.push_back(qualifiedName); + return true; +} + +ir::OverloadDeclaration *ETSParser::ParseOverloadDeclaration(ir::ModifierFlags modifiers) +{ + ValidateOverloadDeclarationModifiers(modifiers); + Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_OVERLOAD); + auto *overloadName = ExpectIdentifier(false, true, TypeAnnotationParsingOptions::REPORT_ERROR); + auto *overloadDef = AllocNode(overloadName->Clone(Allocator(), nullptr)->AsExpression(), + modifiers, Allocator()); + overloadDef->AddOverloadDeclFlag(ir::OverloadDeclFlags::FUNCTION); + + auto startLoc = Lexer()->GetToken().Start(); + if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) { + LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE); + } + ArenaVector overloads(Allocator()->Adapter()); + lexer::SourcePosition endLoc; + + ParseList( + lexer::TokenType::PUNCTUATOR_RIGHT_BRACE, lexer::NextTokenFlags::NONE, + [this, &overloads, overloadDef]() { return ParseOverloadListElement(overloads, overloadDef); }, &endLoc, true); + overloadDef->SetOverloadedList(std::move(overloads)); + overloadDef->SetRange({startLoc, endLoc}); + for (ir::Expression *overloadedName : overloadDef->OverloadedList()) { + std::function checkQualifiedName = [&checkQualifiedName](ir::Expression *expr) -> bool { + if (expr->IsIdentifier()) { + return true; + } + if (expr->IsMemberExpression()) { + return expr->AsMemberExpression()->Property()->IsIdentifier() && + checkQualifiedName(expr->AsMemberExpression()->Object()); + } + return false; + }; + if (!checkQualifiedName(overloadedName)) { + LogError(diagnostic::FUNCTION_OVERLOADED_NAME_MUST_QUALIFIED_NAME, {}, overloadedName->Start()); + } + } + return overloadDef; +} + ir::FunctionDeclaration *ETSParser::ParseFunctionDeclaration(bool canBeAnonymous, ir::ModifierFlags modifiers) { lexer::SourcePosition startLoc = Lexer()->GetToken().Start(); diff --git a/ets2panda/parser/ETSparser.h b/ets2panda/parser/ETSparser.h index f72293d3da..46b62895de 100644 --- a/ets2panda/parser/ETSparser.h +++ b/ets2panda/parser/ETSparser.h @@ -231,12 +231,17 @@ private: ir::AstNode *ParseInterfaceField(); ir::TypeNode *ParseInterfaceTypeAnnotation(ir::Identifier *name); void ParseInterfaceModifiers(ir::ModifierFlags &fieldModifiers, bool &optionalField); + ir::OverloadDeclaration *ParseInterfaceOverload(ir::ModifierFlags modifiers); ir::MethodDefinition *ParseInterfaceMethod(ir::ModifierFlags flags, ir::MethodDefinitionKind methodKind); void ReportAccessModifierError(const lexer::Token &token); std::tuple ParseClassMemberAccessModifiers(); ir::ModifierFlags ParseClassFieldModifiers(bool seenStatic); ir::ModifierFlags ParseClassMethodModifierFlag(); ir::ModifierFlags ParseClassMethodModifiers(bool seenStatic); + void ValidateOverloadDeclarationModifiers(ir::ModifierFlags modifiers); + bool ParseOverloadListElement(ArenaVector &overloads, ir::OverloadDeclaration *overloadDecl); + void ValidateOverloadList(ArenaVector const &overloadList); + ir::OverloadDeclaration *ParseClassOverloadDeclaration(ir::ModifierFlags modifiers); ir::MethodDefinition *ParseClassMethodDefinition(ir::Identifier *methodName, ir::ModifierFlags modifiers, bool isDefault); ir::ScriptFunction *ParseFunction(ParserStatus newStatus); @@ -391,6 +396,7 @@ private: ir::Statement *ParseInterfaceDeclaration(bool isStatic) override; ir::TypeNode *ParseThisType(TypeAnnotationParsingOptions *options); ir::Statement *ParseFunctionStatement(StatementParsingFlags flags) override; + ir::OverloadDeclaration *ParseOverloadDeclaration(ir::ModifierFlags modifiers); ir::FunctionDeclaration *ParseFunctionDeclaration(bool canBeAnonymous, ir::ModifierFlags modifiers); ir::FunctionDeclaration *ParseAccessorWithReceiver(ir::ModifierFlags modifiers); ir::TypeNode *ParseExtensionFunctionsTypeAnnotation(); diff --git a/ets2panda/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index 1ca0f3e10c..b00b428802 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -514,6 +514,50 @@ void ETSParser::ParseClassFieldDefinition(ir::Identifier *fieldName, ir::Modifie declarations->push_back(field); } +void ETSParser::ValidateOverloadList(ArenaVector const &overloadList) +{ + for (ir::Expression *overloadedName : overloadList) { + if (!overloadedName->IsIdentifier()) { + LogError(diagnostic::CLASS_INTERFACE_METHOD_OVERLOADED_NAME_MUST_IDENT, {}, overloadedName->Start()); + } + } +} + +ir::OverloadDeclaration *ETSParser::ParseClassOverloadDeclaration(ir::ModifierFlags modifiers) +{ + ValidateOverloadDeclarationModifiers(modifiers); + ir::Identifier *overloadName = nullptr; + // To avoid duplicate names with anonymous constructors, overload constructor name is + // "constructorOverloadDeclaration", instead of "constructor" + if (Lexer()->GetToken().Type() == lexer::TokenType::KEYW_CONSTRUCTOR) { + overloadName = + AllocNode(compiler::Signatures::CONSTRUCTOR_OVERLOAD_DEFINITION_NAME, Allocator()); + modifiers |= ir::ModifierFlags::CONSTRUCTOR; + Lexer()->NextToken(); + } else { + overloadName = ExpectIdentifier(false, true, TypeAnnotationParsingOptions::REPORT_ERROR); + } + + auto *overloadDef = AllocNode(overloadName->Clone(Allocator(), nullptr)->AsExpression(), + modifiers, Allocator()); + overloadDef->AddOverloadDeclFlag(ir::OverloadDeclFlags::CLASS_METHOD); + + auto startLoc = Lexer()->GetToken().Start(); + if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) { + LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE); + } + ArenaVector overloads(Allocator()->Adapter()); + lexer::SourcePosition endLoc; + + ParseList( + lexer::TokenType::PUNCTUATOR_RIGHT_BRACE, lexer::NextTokenFlags::NONE, + [this, &overloads, overloadDef]() { return ParseOverloadListElement(overloads, overloadDef); }, &endLoc, true); + overloadDef->SetOverloadedList(std::move(overloads)); + overloadDef->SetRange({startLoc, endLoc}); + ValidateOverloadList(overloadDef->OverloadedList()); + return overloadDef; +} + ir::MethodDefinition *ETSParser::ParseClassMethodDefinition(ir::Identifier *methodName, ir::ModifierFlags modifiers, bool isDefault) { @@ -930,7 +974,8 @@ ir::ModifierFlags ETSParser::ParseInterfaceMethodModifiers() { if (Lexer()->GetToken().Type() == lexer::TokenType::LITERAL_IDENT || Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_SQUARE_BRACKET || - Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS) { + Lexer()->GetToken().Type() == lexer::TokenType::PUNCTUATOR_LEFT_PARENTHESIS || + Lexer()->GetToken().Type() == lexer::TokenType::KEYW_OVERLOAD) { return ir::ModifierFlags::PUBLIC; } @@ -1044,6 +1089,31 @@ static lexer::SourcePosition GetEndLoc(ir::BlockStatement *body, ir::ScriptFunct return lexer->GetToken().End(); } +ir::OverloadDeclaration *ETSParser::ParseInterfaceOverload(ir::ModifierFlags modifiers) +{ + ValidateOverloadDeclarationModifiers(modifiers); + auto *overloadName = ExpectIdentifier(false, true, TypeAnnotationParsingOptions::REPORT_ERROR); + auto *overloadDef = AllocNode(overloadName->Clone(Allocator(), nullptr)->AsExpression(), + modifiers, Allocator()); + overloadDef->AddOverloadDeclFlag(ir::OverloadDeclFlags::INTERFACE_METHOD); + + auto startLoc = Lexer()->GetToken().Start(); + if (!Lexer()->TryEatTokenType(lexer::TokenType::PUNCTUATOR_LEFT_BRACE)) { + LogExpectedToken(lexer::TokenType::PUNCTUATOR_LEFT_BRACE); + } + ArenaVector overloads(Allocator()->Adapter()); + lexer::SourcePosition endLoc; + + ParseList( + lexer::TokenType::PUNCTUATOR_RIGHT_BRACE, lexer::NextTokenFlags::NONE, + [this, &overloads, overloadDef]() { return ParseOverloadListElement(overloads, overloadDef); }, &endLoc, true); + + overloadDef->SetOverloadedList(std::move(overloads)); + overloadDef->SetRange({startLoc, endLoc}); + ValidateOverloadList(overloadDef->OverloadedList()); + return overloadDef; +} + ir::MethodDefinition *ETSParser::ParseInterfaceMethod(ir::ModifierFlags flags, ir::MethodDefinitionKind methodKind) { ir::Identifier *name = nullptr; @@ -1168,6 +1238,12 @@ ir::AstNode *ETSParser::ParseTypeLiteralOrInterfaceMember() auto readonlyTok = Lexer()->TryEatTokenKeyword(lexer::TokenType::KEYW_READONLY); bool isReadonly = readonlyTok.has_value(); + if (Lexer()->TryEatTokenFromKeywordType(lexer::TokenType::KEYW_OVERLOAD)) { + auto *overloadDeclaration = ParseInterfaceOverload(modifiers); + overloadDeclaration->SetStart(startLoc); + return overloadDeclaration; + } + if (nextCp == lexer::LEX_CHAR_LEFT_PAREN || nextCp == lexer::LEX_CHAR_LESS_THAN) { if (isReadonly) { LogError(diagnostic::READONLY_INTERFACE_METHOD, {}, startLoc); @@ -1331,7 +1407,8 @@ std::pair ETSParser::ParseMemberModifi } Lexer()->NextToken(); - if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION) { + if (Lexer()->GetToken().Type() != lexer::TokenType::KEYW_FUNCTION && + Lexer()->GetToken().KeywordType() != lexer::TokenType::KEYW_OVERLOAD) { // async_function_bas.ets if (isAsync) { LogError(diagnostic::ASYNC_FLAG_ONLY_FOR_TOP_FUN); diff --git a/ets2panda/parser/ETSparserStatements.cpp b/ets2panda/parser/ETSparserStatements.cpp index f59b4794d5..7f59b8b0e3 100644 --- a/ets2panda/parser/ETSparserStatements.cpp +++ b/ets2panda/parser/ETSparserStatements.cpp @@ -179,6 +179,7 @@ bool ETSParser::IsInitializerBlockStart() const return validStart; } +// CC-OFFNXT(huge_method[C++], G.FUN.01-CPP, G.FUD.05) solid logic, big switch case ir::Statement *ETSParser::ParseTopLevelDeclStatement(StatementParsingFlags flags) { auto [memberModifiers, startLoc] = ParseMemberModifiers(); @@ -209,6 +210,9 @@ ir::Statement *ETSParser::ParseTopLevelDeclStatement(StatementParsingFlags flags case lexer::TokenType::KEYW_CLASS: result = ParseTypeDeclaration(IsInitializerBlockStart()); break; + case lexer::TokenType::KEYW_OVERLOAD: + result = ParseOverloadDeclaration(memberModifiers); + break; case lexer::TokenType::PUNCTUATOR_AT: result = ParseTopLevelAnnotation(memberModifiers); break; diff --git a/ets2panda/parser/parserImpl.cpp b/ets2panda/parser/parserImpl.cpp index 4f66296e62..b5c33731a2 100644 --- a/ets2panda/parser/parserImpl.cpp +++ b/ets2panda/parser/parserImpl.cpp @@ -683,7 +683,7 @@ ir::MethodDefinition *ParserImpl::BuildImplicitConstructor(ir::ClassDefinitionMo } auto *ctor = AllocNode(ir::MethodDefinitionKind::CONSTRUCTOR, key, funcExpr, - ir::ModifierFlags::NONE, Allocator(), false); + ir::ModifierFlags::CONSTRUCTOR, Allocator(), false); const auto rangeImplicitContstuctor = lexer::SourceRange(startLoc, startLoc); ctor->IterateRecursively( diff --git a/ets2panda/public/CMakeLists.txt b/ets2panda/public/CMakeLists.txt index a5f869fddb..5440dba17c 100644 --- a/ets2panda/public/CMakeLists.txt +++ b/ets2panda/public/CMakeLists.txt @@ -250,6 +250,7 @@ set (HEADERS_TO_BE_PARSED ${ES2PANDA_ROOT}/ir/ts/tsImportEqualsDeclaration.h ${ES2PANDA_ROOT}/ir/validationInfo.h ${ES2PANDA_ROOT}/ir/base/methodDefinition.h + ${ES2PANDA_ROOT}/ir/base/overloadDeclaration.h ${ES2PANDA_ROOT}/ir/ts/tsIntersectionType.h ${ES2PANDA_ROOT}/checker/types/ts/nullType.h ${ES2PANDA_ROOT}/checker/types/ts/unknownType.h @@ -499,6 +500,7 @@ set (ES2PANDA_API_GENERATED ${LIBGEN_DIR}/gen/headers/ir/expressions/directEvalExpression.yaml ${LIBGEN_DIR}/gen/headers/ir/ts/tsTypeParameterDeclaration.yaml ${LIBGEN_DIR}/gen/headers/ir/base/methodDefinition.yaml + ${LIBGEN_DIR}/gen/headers/ir/base/overloadDeclaration.yaml ${LIBGEN_DIR}/gen/headers/ir/ts/tsNullKeyword.yaml ${LIBGEN_DIR}/gen/headers/ir/ts/tsInterfaceHeritage.yaml ${LIBGEN_DIR}/gen/headers/checker/types/ts/enumLiteralType.yaml diff --git a/ets2panda/public/headers_parser/supported_types.py b/ets2panda/public/headers_parser/supported_types.py index 3934a02ee8..c10aabea13 100644 --- a/ets2panda/public/headers_parser/supported_types.py +++ b/ets2panda/public/headers_parser/supported_types.py @@ -64,6 +64,7 @@ ast_nodes_supported = [ "MemberExpression", "MetaProperty", "MethodDefinition", + "OverloadDeclaration", "NamedType", "NewExpression", "NullLiteral", diff --git a/ets2panda/test/ast/compiler/ets/first_match/abstract_method.ets b/ets2panda/test/ast/compiler/ets/first_match/abstract_method.ets new file mode 100644 index 0000000000..c79e3ffb02 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/abstract_method.ets @@ -0,0 +1,23 @@ +/* + * 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. + */ + +abstract class Base { + abstract fooNumber(a: number): string; + abstract fooString(a: string): string; + overload foo {/* @@ label1 */fooNumber,/* @@ label2 */fooString } +} + +/* @@@ label1 Error TypeError: overload declaration cannot contain abstract methods. */ +/* @@@ label2 Error TypeError: overload declaration cannot contain abstract methods. */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/access_modifiers.ets b/ets2panda/test/ast/compiler/ets/first_match/access_modifiers.ets new file mode 100644 index 0000000000..46cd5f3a15 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/access_modifiers.ets @@ -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. + */ + +class Base { + private fooPrivate(x: string) {} + protected fooProtected(x: number) {} + public fooPublic(x: boolean) {} + + overload foo{ fooPrivate, fooProtected, fooPublic } + + bar(){ + this.foo("abc"); + this.foo(1); + this.foo(true); + } +} + +class Sub extends Base { + bar() { + /* @@ label1 */this.foo("abc"); + this.foo(1); + this.foo(true); + } +} + +function main() { + let a = new Base(); + /* @@ label2 */a.foo("abc"); + /* @@ label3 */a.foo(1); + a.foo(true); +} + +/* @@@ label1 Error TypeError: Signature fooPrivate(x: String): void is not visible here. */ +/* @@@ label1 Error TypeError: No matching call signature for foo("abc") */ +/* @@@ label2 Error TypeError: Signature fooPrivate(x: String): void is not visible here. */ +/* @@@ label2 Error TypeError: No matching call signature for foo("abc") */ +/* @@@ label3 Error TypeError: Signature fooProtected(x: Double): void is not visible here. */ +/* @@@ label3 Error TypeError: No matching call signature for foo(Int) */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/access_modifiers_2.ets b/ets2panda/test/ast/compiler/ets/first_match/access_modifiers_2.ets new file mode 100644 index 0000000000..8c7362de22 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/access_modifiers_2.ets @@ -0,0 +1,36 @@ +/* + * 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. + */ + +class Test1 { + foo1(a: number) { } + foo2(a: string) { } + native overload foo{ foo1, foo2 } +} + +class Test2 { + foo1(a: number) { } + foo2(a: string) { } + readonly overload foo{ foo1, foo2 } +} + +class Test3 { + foo1(a: number) { } + foo2(a: string) { } + abstract overload foo{ foo1, foo2 } +} + +/* @@? 19:21 Error SyntaxError: Overload Declaration only allow use modifier 'static' | 'async'. */ +/* @@? 25:23 Error SyntaxError: Overload Declaration only allow use modifier 'static' | 'async'. */ +/* @@? 31:23 Error SyntaxError: Overload Declaration only allow use modifier 'static' | 'async'. */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/arrayliteral.ets b/ets2panda/test/ast/compiler/ets/first_match/arrayliteral.ets new file mode 100644 index 0000000000..7e8ca5089a --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/arrayliteral.ets @@ -0,0 +1,39 @@ +/* + * 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. + */ + +class Test{ + foo1(a:[string,string,string]){ + console.log("invoke1") + } + foo2(a:[number,string,boolean]){ + console.log("invoke2") + } + foo3(a:number[]){ + console.log("invoke3") + } + + overload foo111{foo1,foo2,foo3} +} + +function main(){ + let a:Test = new Test(); + a.foo111(["abc","abc",1]); + a.foo111(["abc","abc",true]); + a.foo111([123,"abc",true]); + a.foo111([123,123,123]); +} + +/* @@? 32:5 Error TypeError: No matching call signature for foo111(Array) */ +/* @@? 33:5 Error TypeError: No matching call signature for foo111(Array) */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/constructor.ets b/ets2panda/test/ast/compiler/ets/first_match/constructor.ets new file mode 100644 index 0000000000..db1517374c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/constructor.ets @@ -0,0 +1,52 @@ +/* + * 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. + */ + +class Test1{ + constructor(a?:number,b?:number){} + constructor con1(){} + overload constructor{con1} +} + +class Test2{ + constructor(a:number,b:number){} + constructor con1(){} + overload constructor{con1} +} + +class Test3{ + constructor(a:number,...args:[string,number]){} + constructor con1(){} + overload constructor{con1} +} + +class Test4{ + constructor(a?:number,b?:number){} + constructor(a:string){} + constructor con1(){} + /* @@ label1 */constructor con1(){} + /* @@ label2 */overload constructor{con1} +} + +class Test5{ + constructor(a:number,...args:[string,number]){} + constructor(a:string){} + constructor con1(){} + /* @@ label3 */overload constructor{con1} +} + +/* @@@ label1 Error TypeError: Function con1 is already declared. */ +/* @@@ label2 Error TypeError: The overloaded name 'constructor' can't refer to a function with overload signatures. */ +/* @@@ label2 Error TypeError: The overloaded name 'con1' can't refer to a function with overload signatures. */ +/* @@@ label3 Error TypeError: The overloaded name 'constructor' can't refer to a function with overload signatures. */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration.ets b/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration.ets new file mode 100644 index 0000000000..0d0f584988 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration.ets @@ -0,0 +1,33 @@ +/* + * 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. + */ + +class Test { + foo1(a: number) { } + foo2(a: string) { } + overload: foo{ foo1, foo2 } +} + +/* @@? 19:13 Error SyntaxError: Identifier expected, got ':'. */ +/* @@? 19:15 Error SyntaxError: Unexpected token, expected '{'. */ +/* @@? 19:15 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 19:15 Error TypeError: overloaded name must refer to an accessible method. */ +/* @@? 19:18 Error SyntaxError: Unexpected token, expected ',' or '}'. */ +/* @@? 19:18 Error SyntaxError: Unexpected token '{'. */ +/* @@? 19:20 Error TypeError: Variable 'foo1' has already been declared. */ +/* @@? 19:24 Error SyntaxError: Field type annotation expected. */ +/* @@? 19:24 Error SyntaxError: Unexpected token ','. */ +/* @@? 19:26 Error TypeError: Variable 'foo2' has already been declared. */ +/* @@? 19:31 Error SyntaxError: Field type annotation expected. */ +/* @@? 20:1 Error SyntaxError: Unexpected token '}'. */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_2.ets b/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_2.ets new file mode 100644 index 0000000000..63be2fcf48 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_2.ets @@ -0,0 +1,31 @@ +/* + * 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. + */ + +class Base { + foo1(a: number) { } + foo2(a: string) { } + overload foo(foo1, foo2) +} + +/* @@? 19:17 Error SyntaxError: Unexpected token, expected '{'. */ +/* @@? 19:17 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 19:17 Error TypeError: overloaded name must refer to an accessible method. */ +/* @@? 19:18 Error SyntaxError: Unexpected token, expected ',' or '}'. */ +/* @@? 19:18 Error TypeError: Variable 'foo1' has already been declared. */ +/* @@? 19:22 Error SyntaxError: Field type annotation expected. */ +/* @@? 19:22 Error SyntaxError: Unexpected token ','. */ +/* @@? 19:24 Error TypeError: Variable 'foo2' has already been declared. */ +/* @@? 19:28 Error SyntaxError: Field type annotation expected. */ +/* @@? 19:28 Error SyntaxError: Unexpected token ')'. */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_3.ets b/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_3.ets new file mode 100644 index 0000000000..c6e43822e8 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_3.ets @@ -0,0 +1,25 @@ +/* + * 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. + */ + +class Base { + foo1(a: number) { } + foo2(a: string) { } + overload { foo1, foo2 } +} + +/* @@? 19:14 Error SyntaxError: Identifier expected, got '{'. */ +/* @@? 19:16 Error SyntaxError: Unexpected token, expected '{'. */ +/* @@? 19:16 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 19:16 Error TypeError: overloaded name must refer to an accessible method. */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_4.ets b/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_4.ets new file mode 100644 index 0000000000..a3d50ec721 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/invalid_declaration_4.ets @@ -0,0 +1,23 @@ +/* + * 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. + */ + +class Base { + foo1(a: number) { } + foo2(a: string) { } + overload foo{ fo, fo2 } +} + +/* @@? 19:19 Error TypeError: overloaded name must refer to an accessible method. */ +/* @@? 19:23 Error TypeError: overloaded name must refer to an accessible method. */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/invalid_identifier.ets b/ets2panda/test/ast/compiler/ets/first_match/invalid_identifier.ets new file mode 100644 index 0000000000..ae4fa8c990 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/invalid_identifier.ets @@ -0,0 +1,52 @@ +/* + * 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. + */ + +class Test{ + foo1(a:[string,string,string]){ + console.log("invoke1") + } + + overload foo111(foo1,foo2,foo3){} //syntaxError, do not crash + overload foo112(foo1,foo2) //syntaxError, do not crash +} + +function main(){ + let a:Test = new Test(); + a.foo111(["abc","abc",1]); +} + +/* @@? 21:20 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 21:20 Error SyntaxError: Unexpected token, expected '{'. */ +/* @@? 21:20 Error TypeError: overloaded name must refer to an accessible method. */ +/* @@? 21:21 Error SyntaxError: Unexpected token, expected ',' or '}'. */ +/* @@? 21:21 Error TypeError: Variable 'foo1' has already been declared. */ +/* @@? 21:25 Error SyntaxError: Field type annotation expected. */ +/* @@? 21:25 Error SyntaxError: Unexpected token ','. */ +/* @@? 21:30 Error SyntaxError: Field type annotation expected. */ +/* @@? 21:30 Error SyntaxError: Unexpected token ','. */ +/* @@? 21:35 Error SyntaxError: Field type annotation expected. */ +/* @@? 21:35 Error SyntaxError: Unexpected token ')'. */ +/* @@? 21:36 Error SyntaxError: Unexpected token '{'. */ +/* @@? 22:20 Error SyntaxError: Unexpected token, expected '{'. */ +/* @@? 22:20 Error SyntaxError: Unexpected token, expected an identifier. */ +/* @@? 22:20 Error TypeError: overloaded name must refer to an accessible method. */ +/* @@? 22:21 Error SyntaxError: Unexpected token, expected ',' or '}'. */ +/* @@? 22:21 Error TypeError: Unresolved reference foo1 */ +/* @@? 22:25 Error SyntaxError: Unexpected token ','. */ +/* @@? 22:26 Error SyntaxError: Unexpected token 'foo2'. */ +/* @@? 22:26 Error TypeError: Unresolved reference foo2 */ +/* @@? 22:30 Error SyntaxError: Unexpected token ')'. */ +/* @@? 23:1 Error SyntaxError: Unexpected token '}'. */ +/* @@? 27:7 Error TypeError: Property 'foo111' does not exist on type 'Test' */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/invalid_paramter.ets b/ets2panda/test/ast/compiler/ets/first_match/invalid_paramter.ets new file mode 100644 index 0000000000..ab6be8fcab --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/invalid_paramter.ets @@ -0,0 +1,40 @@ +/* + * 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. + */ + +class A {} +class B {} + +class Test { + foo1(a?: A,) { + console.log("invoke1") + } + foo2(a?: A, b?: B) { + console.log("invoke2") + } + + overload foo111{ foo1, foo2, foo3, foo4 } +} + +function main() { + let a: Test = new Test(); + a.foo111(new A(), new A()) + a.foo111(new A(), new A(), new A()) +} + +/* @@? 27:34 Error TypeError: overloaded name must refer to an accessible method. */ +/* @@? 27:40 Error TypeError: overloaded name must refer to an accessible method. */ +/* @@? 32:5 Error TypeError: No matching call signature for foo111(A, A) */ +/* @@? 33:5 Error TypeError: No matching call signature for foo111(A, A, A) */ + diff --git a/ets2panda/test/ast/compiler/ets/first_match/modifier_async.ets b/ets2panda/test/ast/compiler/ets/first_match/modifier_async.ets new file mode 100644 index 0000000000..1c3ba11c80 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/modifier_async.ets @@ -0,0 +1,29 @@ +/* + * 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. + */ + +class Base1 { + async fooNumber(a: number): Promise {} + fooString(a: string): void {} + overload foo {/* @@ label1 */fooNumber, fooString } +} + +class Base2 { + async fooNumber(a: number): Promise {} + fooString(a: string): void {} + async overload foo {fooNumber, /* @@ label2 */fooString } +} + +/* @@@ label1 Error TypeError: Overload alias and overloaded method name must have exactly the same modifiers (static, async). */ +/* @@@ label2 Error TypeError: Overload alias and overloaded method name must have exactly the same modifiers (static, async). */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/modifier_static.ets b/ets2panda/test/ast/compiler/ets/first_match/modifier_static.ets new file mode 100644 index 0000000000..216411ca48 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/modifier_static.ets @@ -0,0 +1,29 @@ +/* + * 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. + */ + +class Base1 { + static fooNumber(a: number): void {} + fooString(a: string): void {} + overload foo {/* @@ label1 */fooNumber, fooString } +} + +class Base2 { + static fooNumber(a: number): void {} + fooString(a: string): void {} + static overload foo {fooNumber, /* @@ label2 */fooString } +} + +/* @@@ label1 Error TypeError: Overload alias and overloaded method name must have exactly the same modifiers (static, async). */ +/* @@@ label2 Error TypeError: Overload alias and overloaded method name must have exactly the same modifiers (static, async). */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/override.ets b/ets2panda/test/ast/compiler/ets/first_match/override.ets new file mode 100644 index 0000000000..2bb8873b99 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/override.ets @@ -0,0 +1,39 @@ +/* + * 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. + */ + +class Base{ + overload foo {fooNumber,fooString} + fooNumber(a:number):string{ + return "invoke1"; + } + fooString(a:string):string{ + return "invoke2"; + } +} + +class Sub1 extends Base{ + override fooNumber(a:number):string{ + return "invoke3"; + } +} + +class Sub2 extends Base{ + fooInt(a:int):string{ + return "invoke4"; + } + overload foo{fooInt,fooNumber} +} + +/* @@? 32:20 Error TypeError: Cannot inherit from class Base, because overload foo is inherited with a different declaration type */ diff --git a/ets2panda/test/ast/compiler/ets/overload/class_overloaded_name_must_ident.ets b/ets2panda/test/ast/compiler/ets/overload/class_overloaded_name_must_ident.ets new file mode 100644 index 0000000000..6559e6d66b --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/class_overloaded_name_must_ident.ets @@ -0,0 +1,24 @@ +/* + * 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. + */ + +class B { + foo1() {} +} + +class C { + overload foo { /* @@label1 */B.foo1 } +} + +/* @@@ label1 Error SyntaxError: The overloaded method name in class/interface method overload declaration must be identifier. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/constructor_overloaded_name_must_ident.ets b/ets2panda/test/ast/compiler/ets/overload/constructor_overloaded_name_must_ident.ets new file mode 100644 index 0000000000..d4a9648f60 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/constructor_overloaded_name_must_ident.ets @@ -0,0 +1,24 @@ +/* + * 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. + */ + +class B { + constructor foo1() {} +} + +class C { + overload constructor { /* @@label1 */B.foo1 } +} + +/* @@@ label1 Error SyntaxError: The overloaded method name in class/interface method overload declaration must be identifier. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/function_overloaded_name_must_qualified_name.ets b/ets2panda/test/ast/compiler/ets/overload/function_overloaded_name_must_qualified_name.ets new file mode 100644 index 0000000000..70eb87ba28 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/function_overloaded_name_must_qualified_name.ets @@ -0,0 +1,26 @@ +/* + * 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. + */ + + +namespace NS { + export function foo1() {} + export class A { + static foo2() {} + } +} + +overload foo {NS.foo1, NS.A.foo2, /* @@ label1 */NS.A.foo2} + +/* @@@ label1 Error TypeError: Duplicate overloaded method. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/interface_overloaded_name_must_ident.ets b/ets2panda/test/ast/compiler/ets/overload/interface_overloaded_name_must_ident.ets new file mode 100644 index 0000000000..3d5f01eb89 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/interface_overloaded_name_must_ident.ets @@ -0,0 +1,23 @@ +/* + * 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. + */ +class B { + foo1() {} +} + +interface I { + overload foo { /* @@label1 */B.foo1 } +} + +/* @@@ label1 Error SyntaxError: The overloaded method name in class/interface method overload declaration must be identifier. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_function.ets b/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_function.ets new file mode 100644 index 0000000000..3b4308b99f --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_function.ets @@ -0,0 +1,33 @@ +/* + * 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. + */ + +class A { } +class B { } +class C { } + +function foo111(a: A): A { + return a; +} +function foo112(a: B): B { + return a; +} + +function foo113(a: C): C { + return a; +} + +overload foo{ foo111, foo112, foo113,/* @@ label1 */foo111 } + +/* @@@ label1 Error TypeError: Duplicate overloaded method. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_function_2.ets b/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_function_2.ets new file mode 100644 index 0000000000..fa182d50da --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_function_2.ets @@ -0,0 +1,37 @@ +/* + * 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. + */ + +namespace NS { + export namespace NS2 { + export function foo1(a: string): string { + return "invoke1" + }; + export namespace NS3 { + export function foo2(a: number): string { + return "invoke2" + }; + } + } + + export function foo3(a: boolean): string { + return "invoke3" + }; +} + + +overload foo{ NS.NS2.foo1, NS.NS2.NS3.foo2, NS.foo3, /* @@ label1 */NS.NS2.NS3.foo2}; + +/* @@@ label1 Error TypeError: Duplicate overloaded method. */ + diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_method.ets b/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_method.ets new file mode 100644 index 0000000000..2d656eb4b7 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_method.ets @@ -0,0 +1,34 @@ +/* + * 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. + */ + +class A { } +class B { } +class C { } + +class Test1 { + foo111(a: A): A { + return a; + } + foo112(a: B): B { + return a; + } + + foo113(a: C): C { + return a; + } + overload foo{ foo111, foo112, foo113,/* @@ label1 */foo111 } +} + +/* @@@ label1 Error TypeError: Duplicate overloaded method. */ \ No newline at end of file diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_overload_name_1.ets b/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_overload_name_1.ets new file mode 100644 index 0000000000..95eddfc644 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_duplicate_overload_name_1.ets @@ -0,0 +1,26 @@ +/* + * 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. + */ + +class Base { + foo/* @@ label1 */(a: number) : string + foo(a: string) : string + overload /* @@ label2 */foo {/* @@ label3 */foo, /* @@ label4 */foo} +} + +/* @@@ label1 Error TypeError: Only abstract or native methods can't have body. */ +/* @@@ label2 Error TypeError: Variable 'foo' has already been declared. */ +/* @@@ label3 Error TypeError: overloaded name must refer to an accessible method. */ +/* @@@ label4 Error TypeError: Duplicate overloaded method. */ +/* @@@ label4 Error TypeError: overloaded name must refer to an accessible method. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_from_super_class.ets b/ets2panda/test/ast/compiler/ets/overload/overload_from_super_class.ets new file mode 100644 index 0000000000..81f8d0f398 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_from_super_class.ets @@ -0,0 +1,26 @@ +/* + * 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. + */ + + +class B extends A { + fooB() { + } + overload foo{fooB, fooA} +} + +class A{ + fooA() {} +} + diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_method_exported.ets b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_method_exported.ets new file mode 100644 index 0000000000..b5511a3f9e --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_method_exported.ets @@ -0,0 +1,20 @@ +/* + * 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. + */ + +export function foo1() {} +function foo2() {} +export overload foo {foo1, /* @@ label1 */foo2} + +/* @@@ label1 Error TypeError: Overload alias is exported, then overload functions must also be exported. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_at_most_once_1.ets b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_at_most_once_1.ets new file mode 100644 index 0000000000..1a2ab17c31 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_at_most_once_1.ets @@ -0,0 +1,31 @@ +/* + * 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. + */ + +class A{} +class B{} + +class Test0 { + foo111(a: A): void { } +} + +class Test1 extends Test0 { + + foo112(a: B): B { + return a; + } + overload foo{foo111, /* @@ label1 */foo111, foo112} +} + +/* @@@ label1 Error TypeError: Duplicate overloaded method. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_used_as_value_1.ets b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_used_as_value_1.ets new file mode 100644 index 0000000000..dec7657edd --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_used_as_value_1.ets @@ -0,0 +1,27 @@ +/* + * 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. + */ + + +class E { + foo1() {} + foo2() {} + overload foo{foo1, foo2} + foo3() { + let f = this.foo; + } +} + +/* @@? 22:22 Error TypeError: Overloaded method is used as value */ + diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_used_as_value_2.ets b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_used_as_value_2.ets new file mode 100644 index 0000000000..19db7f31f9 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_name_used_as_value_2.ets @@ -0,0 +1,27 @@ +/* + * 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. + */ + + + +function foo1() {} +function foo2() {} +overload foo{foo1, foo2} +let OL = /* @@ label */foo; + +/* @@@ label Error TypeError: Identifier 'foo' is used in wrong context. */ +/* @@@ label Error TypeError: Overloaded method is used as value */ +/* @@@ label Error TypeError: Identifier 'foo' is used in wrong context. */ +/* @@@ label Error TypeError: Overloaded method is used as value */ + diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_union_call.ets b/ets2panda/test/ast/compiler/ets/overload/overload_union_call.ets new file mode 100644 index 0000000000..f377a79a6a --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_union_call.ets @@ -0,0 +1,38 @@ +/* + * 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. + */ + +class A { + foo2(a: int) { } + foo1() { + return 1 + } + overload foo{ foo1, foo2 } +} + +class B { + foo2(a: int) { } + foo1() { + return 2 + } + overload foo{ foo1, foo2 } +} + +type AAA = A | B + +function foo(a: T) { + return /* @@ label1 */a.foo() +} + +/* @@@ label1 Error TypeError: Overload declaration cannot be called by union. */ diff --git a/ets2panda/test/ast/compiler/ets/overload/overload_union_call_2.ets b/ets2panda/test/ast/compiler/ets/overload/overload_union_call_2.ets new file mode 100644 index 0000000000..e718f62443 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/overload/overload_union_call_2.ets @@ -0,0 +1,35 @@ +/* + * 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. + */ + +class A { + foo2(a: int) { } + foo1() { + return 1 + } + overload foo{ foo1, foo2 } +} + +class B { + foo() { } +} + +type AAA = A | B + +function foo(a: T) { + return /* @@ label1 */a.foo() +} + +/* @@@ label1 Error TypeError: Member type must be the same for all union objects. */ +/* @@@ label1 Error TypeError: No matching call signature */ diff --git a/ets2panda/test/ast/parser/ets/overload_class_method_test.ets b/ets2panda/test/ast/parser/ets/overload_class_method_test.ets new file mode 100644 index 0000000000..ad83ee5240 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/overload_class_method_test.ets @@ -0,0 +1,33 @@ +/* + * 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. + */ + +class A{} +class B{} +class C{} + +class Test1 { + foo111(a: A): A { + return a; + } + foo112(a: B): B { + return a; + } + + foo113(a: C): C { + console.log(a) + return a; + } + overload foo{foo111,foo112,foo113} +} diff --git a/ets2panda/test/ast/parser/ets/overload_constructor.ets b/ets2panda/test/ast/parser/ets/overload_constructor.ets new file mode 100644 index 0000000000..4a250cf986 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/overload_constructor.ets @@ -0,0 +1,34 @@ +/* + * 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. + */ + +class A { } +class B { } +class C { } + +class Test1 { + constructor fromA(a: A){ } + constructor fromB(a: B){ } + constructor fromC(a: C){ } + + overload constructor { fromA, fromB, fromC } +} + +class Test2 { + constructor() { } + constructor fromA(a: A){ } + constructor fromB(a: B){ } + + overload constructor { fromA, fromB } +} diff --git a/ets2panda/test/ast/parser/ets/overload_global_function_our_style_test.ets b/ets2panda/test/ast/parser/ets/overload_global_function_our_style_test.ets new file mode 100644 index 0000000000..4237ee173f --- /dev/null +++ b/ets2panda/test/ast/parser/ets/overload_global_function_our_style_test.ets @@ -0,0 +1,32 @@ +/* + * 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. + */ + +class A{} +class B{} +class C{} + +function foo111(a: A): A { + return a; +} +function foo112(a: B): B { + return a; +} + +function foo113(a: C): C { + console.log(a) + return a; +} + +overload foo{ foo111, foo112, foo113 } diff --git a/ets2panda/test/ast/parser/ets/overload_interface_method_test.ets b/ets2panda/test/ast/parser/ets/overload_interface_method_test.ets new file mode 100644 index 0000000000..d418c4eacf --- /dev/null +++ b/ets2panda/test/ast/parser/ets/overload_interface_method_test.ets @@ -0,0 +1,25 @@ +/* + * 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. + */ + +class A{} +class B{} +class C{} + +interface Test1 { + foo111(a: A): A; + foo112(a: B): B; + foo113(a: C): C; + overload foo{foo111,foo112,foo113}; +} diff --git a/ets2panda/test/ast/parser/ets/overload_modifier_overloaddefinition.ets b/ets2panda/test/ast/parser/ets/overload_modifier_overloaddefinition.ets new file mode 100644 index 0000000000..c261c9fca0 --- /dev/null +++ b/ets2panda/test/ast/parser/ets/overload_modifier_overloaddefinition.ets @@ -0,0 +1,64 @@ +/* + * 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. + */ + +class A{} +class B{} +class C{} +class TempAny{} + +class Test1 { + async foo111(a: A): Promise { + return a; + } + async foo112(a: B): Promise { + return a; + } + + async foo113(a: C): Promise { + console.log(a) + return a; + } + async overload foo{foo111,foo112,foo113} +} + +class Test2 { + static foo111(a: A): A { + return a; + } + static foo112(a: B): B { + return a; + } + + static foo113(a: C): C { + console.log(a) + return a; + } + static overload foo{foo111,foo112,foo113} +} + +class Test3 { + private foo111(a: A): A { + return a; + } + private foo112(a: B): B { + return a; + } + + private foo113(a: C): C { + console.log(a) + return a; + } + private overload foo{foo111,foo112,foo113} +} diff --git a/ets2panda/test/runtime/ets/first_match/access_modifiers.ets b/ets2panda/test/runtime/ets/first_match/access_modifiers.ets new file mode 100644 index 0000000000..c8affb5755 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/access_modifiers.ets @@ -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. + */ + +class Base { + private fooPrivate(x: string): string { + return "invoke1" + } + protected fooProtected(x: number): string { + return "invoke2" + } + public fooPublic(x: boolean): string { + return "invoke3" + } + + overload foo{ fooPrivate, fooProtected, fooPublic } + + test(){ + arktest.assertEQ(this.foo("abc"), "invoke1"); + arktest.assertEQ(this.foo(1), "invoke2"); + arktest.assertEQ(this.foo(true), "invoke3"); + } +} + +class Sub extends Base { + test() { + arktest.assertEQ(this.foo(1), "invoke2"); + arktest.assertEQ(this.foo(true), "invoke3"); + } +} + +function main() { + let a = new Base(); + arktest.assertEQ(a.foo(true), "invoke3"); + a.test(); + + let b = new Sub(); + b.test(); +} diff --git a/ets2panda/test/runtime/ets/first_match/array.ets b/ets2panda/test/runtime/ets/first_match/array.ets new file mode 100644 index 0000000000..5ca310bce3 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/array.ets @@ -0,0 +1,45 @@ +/* + * 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. + */ + +class Test { + foo1(a: string[]): string { + return "invoke1" + } + foo2(a: number[]): string { + return "invoke2" + } + foo3(a: Array): string { + return "invoke3" + } + foo4(a: Array): string { + return "invoke4" + } + foo5(a: string[][]): string { + return "invoke5" + } + foo6(a: number[][]): string { + return "invoke6" + } + + overload foo{ foo1, foo2, foo3, foo4, foo5, foo6 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo([123, 123, 123]), "invoke2"); + arktest.assertEQ(a.foo(new number[5]), "invoke2"); + arktest.assertEQ(a.foo(new Array(2)), "invoke2"); + arktest.assertEQ(a.foo(new number[5][10]), "invoke6"); +} diff --git a/ets2panda/test/runtime/ets/first_match/array_and_tuple.ets b/ets2panda/test/runtime/ets/first_match/array_and_tuple.ets new file mode 100644 index 0000000000..9a6b55a98e --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/array_and_tuple.ets @@ -0,0 +1,42 @@ +/* + * 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. + */ + +class Test { + foo1(a: [string, string, string]): string { + return "invoke1"; + } + foo2(a: [number, string, boolean]): string { + return "invoke2"; + } + foo3(a: number[]): string { + return "invoke3"; + } + + overload foo{ foo1, foo2, foo3 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo(["abc", "abc", "abc"]), "invoke1"); + arktest.assertEQ(a.foo([123, "abc", true]), "invoke2"); + arktest.assertEQ(a.foo([123, 123, 123]), "invoke3"); + + let param1: [string, string, string] = ["abc", "abc", "abc"]; + let param2: [number, string, boolean] = [123, "abc", true]; + let param3: number[] = [123, 123, 123] + arktest.assertEQ(a.foo(param1), "invoke1"); + arktest.assertEQ(a.foo(param2), "invoke2"); + arktest.assertEQ(a.foo(param3), "invoke3"); +} diff --git a/ets2panda/test/runtime/ets/first_match/ctor_need_fix_bytecode.ets b/ets2panda/test/runtime/ets/first_match/ctor_need_fix_bytecode.ets new file mode 100644 index 0000000000..a089ad0a17 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/ctor_need_fix_bytecode.ets @@ -0,0 +1,59 @@ +/* + * 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. + */ + +class A{} + +class Test { + constructor(a: number) { + this.testString = "invoke1" + } + constructor con1(a: string){ + this.testString = "invoke2" + } + constructor con2(a: A){ + this.testString = "invoke3" + } + + testString = "" + + overload constructor{ con1, con2 } +} + +class Test2 { + constructor con1(a: string){ + this.testString = "invoke4" + } + constructor con2(a: A){ + this.testString = "invoke5" + } + + testString = "" + + overload constructor{ con1, con2 } +} + +function main() { + let var1 = new Test(10); + let var2 = new Test("123"); + let var3 = new Test(new A()); + arktest.assertEQ(var1.testString, "invoke1") + arktest.assertEQ(var2.testString, "invoke2") + arktest.assertEQ(var3.testString, "invoke3") + + let var4 = new Test2("123"); + let var5 = new Test2(new A()) + arktest.assertEQ(var4.testString, "invoke4") + arktest.assertEQ(var5.testString, "invoke5") +} diff --git a/ets2panda/test/runtime/ets/first_match/enum.ets b/ets2panda/test/runtime/ets/first_match/enum.ets new file mode 100644 index 0000000000..6ff320e92c --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/enum.ets @@ -0,0 +1,90 @@ +/* + * 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. + */ + +enum TestEnum1 { + A = 0, + B = 1, + C = 2, + D = 3, +} + +enum TestEnum2 { + A = "A", + B = "B", + C = "C", + D = "D", +} + +class Test { + foo1(a: TestEnum1): string { + return "invoke1" + } + foo2(a: TestEnum2): string { + return "invoke2" + } + foo3(a: TestEnum1 | TestEnum2): string { + return "invoke3" + } + + overload foo{ foo1, foo2, foo3 } +} + +class Test2 { + foo1(a: string, b: TestEnum1): string { + return "invoke1" + } + foo2(a: number, b: TestEnum2): string { + return "invoke2" + } + foo3(a: string | number, b: TestEnum1 | TestEnum2): string { + return "invoke3" + } + + overload foo{ foo1, foo2, foo3 } +} + +class Test3 { + foo1(a: string): string { + return "invoke1" + } + foo2(a: number): string { + return "invoke2" + } + foo3(a: string | number): string { + return "invoke3" + } + + overload foo{ foo1, foo2, foo3 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo(TestEnum1.A), "invoke1"); + arktest.assertEQ(a.foo(TestEnum2.B), "invoke2"); + arktest.assertEQ(a.foo(TestEnum1.A), "invoke1"); + + let b: Test2 = new Test2(); + arktest.assertEQ(b.foo("123", TestEnum1.A), "invoke1"); + arktest.assertEQ(b.foo(123, TestEnum1.A), "invoke3"); + arktest.assertEQ(b.foo("123", TestEnum2.C), "invoke3"); + arktest.assertEQ(b.foo(123, TestEnum2.C), "invoke2"); + + let c: Test3 = new Test3(); + arktest.assertEQ(c.foo(TestEnum1.A), "invoke2"); + arktest.assertEQ(c.foo(TestEnum2.B), "invoke1"); + arktest.assertEQ(c.foo(TestEnum1.A.valueOf()), "invoke2"); + arktest.assertEQ(c.foo(TestEnum2.B.valueOf()), "invoke1"); +} + diff --git a/ets2panda/test/runtime/ets/first_match/enum2.ets b/ets2panda/test/runtime/ets/first_match/enum2.ets new file mode 100644 index 0000000000..424c56ea6c --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/enum2.ets @@ -0,0 +1,35 @@ +/* + * 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. + */ + +enum MyEnum { + a = 1, +} + +function foo1(a: int): string { + return "invoke1" +} + +function foo2(a: MyEnum): string { + return "invoke2" +} + +overload foo{ foo1, foo2 } + +overload fooo{ foo2, foo1 } + +function main() { + arktest.assertEQ(foo(MyEnum.a), "invoke1") + arktest.assertEQ(fooo(MyEnum.a), "invoke2") +} diff --git a/ets2panda/test/runtime/ets/first_match/function_need_fix_variable.ets b/ets2panda/test/runtime/ets/first_match/function_need_fix_variable.ets new file mode 100644 index 0000000000..049b787496 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/function_need_fix_variable.ets @@ -0,0 +1,39 @@ +/* + * 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. + */ + +namespace NS { + export function foo3(a: string): string { + return "invoke3" + } +} + +class A { } + +function foo1(a: A): string { + return "invoke1" +} + +function foo2(a: number): string { + return "invoke2" +} + +overload foo{ foo1, foo2 } + +function main() { + arktest.assertEQ(foo(new A()), "invoke1") + arktest.assertEQ(foo(123), "invoke2") + arktest.assertEQ(NS.foo3("123"), "invoke3") +} + diff --git a/ets2panda/test/runtime/ets/first_match/generics.ets b/ets2panda/test/runtime/ets/first_match/generics.ets new file mode 100644 index 0000000000..8175ad3985 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/generics.ets @@ -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. + */ + +class Test { + foo1(a: T[]): string { + return "invoke1"; + } + foo2(a: string[]): string { + return "invoke2"; + } + foo3(a: Array): string { + return "invoke3"; + } + foo4(a: Array): string { + return "invoke4"; + } + foo5(a: T[][]): string { + return "invoke5"; + } + foo6(a: string[][]): string { + return "invoke6"; + } + + overload foo{ foo1, foo2, foo3, foo4, foo5, foo6 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo([123, 123, 123]), "invoke1"); + arktest.assertEQ(a.foo(new number[5]), "invoke1"); + arktest.assertEQ(a.foo(new Array(2)), "invoke1"); + arktest.assertEQ(a.foo(new number[5][10]), "invoke5"); + + arktest.assertEQ(a.foo(["abc", "abc", "abc"]), "invoke2"); + arktest.assertEQ(a.foo(new string[5]), "invoke2"); + arktest.assertEQ(a.foo(new Array(2)), "invoke2"); + arktest.assertEQ(a.foo(new string[5][10]), "invoke6"); +} diff --git a/ets2panda/test/runtime/ets/first_match/generics_2.ets b/ets2panda/test/runtime/ets/first_match/generics_2.ets new file mode 100644 index 0000000000..d494c08ab4 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/generics_2.ets @@ -0,0 +1,44 @@ +/* + * 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. + */ + +class A { + field: string = "A" +} + +class Test { + foo1(a: string): string { + return "invoke1" + } + foo2(a: T): string { + return "invoke2" + } + foo3(a: T1): string { + return "invoke3" + } + foo4(a: T1, b: T2): string { + return "invoke4" + } + + overload foo{ foo1, foo2, foo3, foo4 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo(new A()), "invoke2"); + arktest.assertEQ(a.foo(10), "invoke3"); + arktest.assertEQ(a.foo(10, "abc"), "invoke4"); + arktest.assertEQ(a.foo(10), "invoke3"); + arktest.assertEQ(a.foo(10, "abc"), "invoke4"); +} diff --git a/ets2panda/test/runtime/ets/first_match/lambda_infer.ets b/ets2panda/test/runtime/ets/first_match/lambda_infer.ets new file mode 100644 index 0000000000..62842d63ae --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/lambda_infer.ets @@ -0,0 +1,44 @@ +/* + * 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. + */ + +class Test { + foo1(lambda: () => void): string { + return "invoke1"; + } + foo2(lambda: (p1: string, p2: number) => void): string { + lambda("invoke2", 123456); + return "invoke2"; + } + foo3(lambda: (p1: number, p2: string) => void): string { + lambda(123456, "invoke3"); + return "invoke3"; + } + foo4(lambda: (p1: number, p2: string, p3: boolean) => void) { + lambda(123, "123", true); + return "invoke4"; + } + + overload foo{ foo1, foo2, foo3, foo4 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo(() => { }), "invoke1"); + arktest.assertEQ(a.foo((p1: string, p2) => { }), "invoke2"); + arktest.assertEQ(a.foo((p1: number, p2) => { }), "invoke3"); + arktest.assertEQ(a.foo((p1, p2) => { }), "invoke2"); + arktest.assertEQ(a.foo((p1: number, p2, p3) => { }), "invoke4"); + arktest.assertEQ(a.foo((p1, p2, p3) => { }), "invoke4"); +} diff --git a/ets2panda/test/runtime/ets/first_match/lambda_order.ets b/ets2panda/test/runtime/ets/first_match/lambda_order.ets new file mode 100644 index 0000000000..0783b9485e --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/lambda_order.ets @@ -0,0 +1,51 @@ +/* + * 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. + */ + +class Test { + foo1(lambda: () => void): string { + return "invoke1"; + } + foo2(lambda: (p1: string, p2: number) => void): string { + lambda("invoke2", 123456); + return "invoke2"; + } + foo3(lambda: (p1: number, p2: string) => void): string { + lambda(123456, "invoke3"); + return "invoke3"; + } + foo4(lambda: (p1: number, p2: string, p3: boolean) => void): string { + lambda(123, "123", true); + return "invoke4" + } + + overload foo{ foo1, foo2, foo3, foo4 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo((): void => { }), "invoke1"); + arktest.assertEQ(a.foo((p1: string, p2: number): void => { }), "invoke2"); + arktest.assertEQ(a.foo((p1: number, p2: string): void => { }), "invoke3"); + arktest.assertEQ(a.foo((p1: number, p2: string, p3: boolean): void => { }), "invoke4"); + + let param1 = (): void => { }; + let param2 = (p1: string, p2: number): void => { }; + let param3 = (p1: number, p2: string): void => { }; + let param4 = (p1: number, p2: string, p3: boolean): void => { }; + arktest.assertEQ(a.foo(param1), "invoke1"); + arktest.assertEQ(a.foo(param2), "invoke2"); + arktest.assertEQ(a.foo(param3), "invoke3"); + arktest.assertEQ(a.foo(param4), "invoke4"); +} diff --git a/ets2panda/test/runtime/ets/first_match/lambda_type_alias.ets b/ets2panda/test/runtime/ets/first_match/lambda_type_alias.ets new file mode 100644 index 0000000000..2a1147db22 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/lambda_type_alias.ets @@ -0,0 +1,46 @@ +/* + * 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. + */ + +type AsyncCallback = (err: T, data: T) => void; +type AsyncCallback2 = (err: string, data: number, data2: number) => void; + +function getBundleInfo1(userId?: number): string { + return "invoke1" +} + +function getBundleInfo2(callback: AsyncCallback): string { + callback(666, 66); + return "invoke2" +} + +function getBundleInfo3(callback: AsyncCallback2): string { + callback("invoke3", 66, 66); + return "invoke3" +} + +overload getBundleInfo{ getBundleInfo1, getBundleInfo2, getBundleInfo3 } + +function main() { + arktest.assertEQ(getBundleInfo((err, data) => { + arktest.assertEQ(err, 666); + arktest.assertEQ(data, 66) + }), "invoke2") + + arktest.assertEQ(getBundleInfo((err: string, data1: number, data2: number) => { + arktest.assertEQ(err, "invoke3"); + arktest.assertEQ(data1, 66); + arktest.assertEQ(data2, 66); + }), "invoke3") +} diff --git a/ets2panda/test/runtime/ets/first_match/namespace.ets b/ets2panda/test/runtime/ets/first_match/namespace.ets new file mode 100644 index 0000000000..7df1fa2c27 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/namespace.ets @@ -0,0 +1,35 @@ +/* + * 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. + */ + +namespace NS { + export function foo1(a: string): string { + return "invoke1" + }; + export function foo2(a: boolean): string { + return "invoke2" + }; +} + +function foo3(a: number): string { + return "invoke3" +}; + +overload foo{ foo3, NS.foo1, NS.foo2 }; + +function main() { + arktest.assertEQ(foo("123"), "invoke1") + arktest.assertEQ(foo(1), "invoke3") + arktest.assertEQ(foo(true), "invoke2") +} diff --git a/ets2panda/test/runtime/ets/first_match/namespace2.ets b/ets2panda/test/runtime/ets/first_match/namespace2.ets new file mode 100644 index 0000000000..b7c09fe150 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/namespace2.ets @@ -0,0 +1,46 @@ +/* + * 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. + */ + +namespace NS { + export namespace NS2 { + export function foo1(a: string): string { + return "invoke1" + }; + export namespace NS3 { + export function foo2(a: number): string { + return "invoke2" + }; + } + } + + export function foo3(a: boolean): string { + return "invoke3" + }; +} + +class A { } + +function foo4(a: A): string { + return "invoke4" +}; + +overload foo{ foo4, NS.NS2.foo1, NS.NS2.NS3.foo2, NS.foo3 }; + +function main() { + arktest.assertEQ(foo("aaa"),"invoke1"); + arktest.assertEQ(foo(1),"invoke2"); + arktest.assertEQ(foo(true),"invoke3"); + arktest.assertEQ(foo(new A()),"invoke4"); +} diff --git a/ets2panda/test/runtime/ets/first_match/namespace3.ets b/ets2panda/test/runtime/ets/first_match/namespace3.ets new file mode 100644 index 0000000000..37ad202c81 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/namespace3.ets @@ -0,0 +1,44 @@ +/* + * 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. + */ + +namespace NS { + export function foo1(a: string): string { + return "invoke1" + }; + export function foo2(a: boolean): string { + return "invoke2" + }; +} + +namespace NS2 { + export function foo3(a: number): string { + return "invoke3" + } +} + +class A { } + +function foo4(a: A): string { + return "invoke4" +}; + +overload foo{ foo4, NS.foo1, NS.foo2, NS2.foo3 }; + +function main() { + arktest.assertEQ(foo("123"), "invoke1") + arktest.assertEQ(foo(true), "invoke2") + arktest.assertEQ(foo(1), "invoke3") + arktest.assertEQ(foo(new A()), "invoke4") +} diff --git a/ets2panda/test/runtime/ets/first_match/objectliteral_optional.ets b/ets2panda/test/runtime/ets/first_match/objectliteral_optional.ets new file mode 100644 index 0000000000..57514500e8 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/objectliteral_optional.ets @@ -0,0 +1,69 @@ +/* + * 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. + */ + +enum TestEnum{ + Kind1 = 0, + Kind2 = 1, + Kind3 = 2, +} +class A{ + field1:number = 0; + field2:string = "abc" + field3:boolean = true; +} + +class B{ + field1:string = "abc"; + field2?:number = 0; + field3:boolean = true; + field4?:TestEnum; +} + +class C{ + field1:number = 0; + field2?:string = "abc"; + field3?:string = "abc"; + field4:string = "abc" +} + + +class Test{ + foo1(a:A):string{ + return "invoke1"; + } + foo2(a:B):string{ + return "invoke2"; + } + foo3(a:C):string{ + return "invoke3"; + } + + overload foo{foo1,foo2,foo3} +} + +function main(){ + let a:Test = new Test(); + arktest.assertEQ(a.foo({field1:1,field2:"abc",field3:true}),"invoke1"); + + arktest.assertEQ(a.foo({field1:"abc",field2:0,field3:true,field4:TestEnum.Kind1}),"invoke2"); + arktest.assertEQ(a.foo({field1:"abc",field3:true,field4:TestEnum.Kind1}),"invoke2"); + arktest.assertEQ(a.foo({field1:"abc",field2:0,field3:true}),"invoke2"); + arktest.assertEQ(a.foo({field1:"abc",field3:true}),"invoke2"); + + arktest.assertEQ(a.foo({field1:1,field2:"abc",field3:"abc",field4:"abc"}),"invoke3"); + arktest.assertEQ(a.foo({field1:1,field2:"abc",field4:"abc"}),"invoke3"); + arktest.assertEQ(a.foo({field1:1,field3:"abc",field4:"abc"}),"invoke3"); + arktest.assertEQ(a.foo({field1:1,field4:"abc"}),"invoke3"); +} diff --git a/ets2panda/test/runtime/ets/first_match/objectliteral_order.ets b/ets2panda/test/runtime/ets/first_match/objectliteral_order.ets new file mode 100644 index 0000000000..316970ab3b --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/objectliteral_order.ets @@ -0,0 +1,48 @@ +/* + * 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. + */ + +class A { + field: number = 0; +} + +class B { + field: string = "abc"; +} + +class C { + field1: number = 0; + field2: string = "abc"; +} + +class Test { + foo1(a: A): string { + return "invoke1"; + } + foo2(a: B): string { + return "invoke2"; + } + foo3(a: C): string { + return "invoke3"; + } + + overload foo{ foo1, foo2, foo3 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo({ field: 1 }), "invoke1"); + arktest.assertEQ(a.foo({ field: "abc" }), "invoke2"); + arktest.assertEQ(a.foo({ field1: 1, field2: "abc" }), "invoke3"); +} diff --git a/ets2panda/test/runtime/ets/first_match/objectliteral_same.ets b/ets2panda/test/runtime/ets/first_match/objectliteral_same.ets new file mode 100644 index 0000000000..11d2198e46 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/objectliteral_same.ets @@ -0,0 +1,53 @@ +/* + * 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. + */ + +class A { + field1: number = 0; + field2: string = "abc" + field3: boolean = true; +} + +class B { + field1: number = 0; + field2: string = "abc" + field3: boolean = true; +} + +class C { + field1: number = 0; + field2: string = "abc" + field3: boolean = true; +} + + +class Test { + foo1(a: A): string { + return "invoke1"; + } + foo2(a: B): string { + return "invoke2"; + } + foo3(a: C): string { + return "invoke3"; + } + + overload foo{ foo1, foo2, foo3 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo({ field1: 1, field2: "abc", field3: true }), "invoke1"); + arktest.assertEQ(a.foo({ field1: 1, field2: "abc", field3: false }), "invoke1"); +} diff --git a/ets2panda/test/runtime/ets/first_match/optinal_parameter.ets b/ets2panda/test/runtime/ets/first_match/optinal_parameter.ets new file mode 100644 index 0000000000..f1d5da2864 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/optinal_parameter.ets @@ -0,0 +1,47 @@ +/* + * 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. + */ + +class A { + field: string = "A" +} +class B { + field: string = "B" +} + +class Test { + foo1(a?: A,): string { + return "invoke1"; + } + foo2(a?: A, b?: B): string { + return "invoke2"; + } + foo3(a?: B, b?: A): string { + return "invoke3"; + } + foo4(a?: B, b?: B): string { + return "invoke4"; + } + + overload foo{ foo1, foo2, foo3, foo4 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo(new A()), "invoke1"); + arktest.assertEQ(a.foo(new B()), "invoke3"); + arktest.assertEQ(a.foo(new A(), new B()), "invoke2"); + arktest.assertEQ(a.foo(new B(), new A()), "invoke3"); + arktest.assertEQ(a.foo(new B(), new B()), "invoke4"); +} diff --git a/ets2panda/test/runtime/ets/first_match/override_class.ets b/ets2panda/test/runtime/ets/first_match/override_class.ets new file mode 100644 index 0000000000..aaec7eb4e5 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/override_class.ets @@ -0,0 +1,48 @@ +/* + * 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. + */ + +class Base { + overload foo { fooNumber, fooString } + fooNumber(a: number):string{ + return "invoke1"; + } + fooString(a: string):string{ + return "invoke2"; + } +} + +class Sub1 extends Base { + override fooNumber(a: number): string { + return "invoke3"; + } +} + +class Sub2 extends Base { + fooInt(a: int): string { + return "invoke4"; + } + overload foo{ fooInt, fooNumber, fooString } +} + +function main() { + let a = new Sub1(); + arktest.assertEQ(a.fooNumber(1), "invoke3") + arktest.assertEQ(a.foo(1), "invoke3") + arktest.assertEQ(a.foo("abc"), "invoke2") + + let b = new Sub2(); + arktest.assertEQ(b.foo(1), "invoke4") + arktest.assertEQ(b.foo("abc"), "invoke2") +} diff --git a/ets2panda/test/runtime/ets/first_match/override_interface.ets b/ets2panda/test/runtime/ets/first_match/override_interface.ets new file mode 100644 index 0000000000..8bfbb15df8 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/override_interface.ets @@ -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. + */ + +interface Base { + overload foo { fooNumber, fooString } + + fooNumber(a: number):string + fooString(a: string):string +} + +class Sub1 implements Base { + fooNumber(a: number): string { + return "invoke1" + } + fooString(a: string): string { + return "invoke2" + } +} + +class Sub2 implements Base { + fooInt(a: int): string { + return "invoke1" + } + fooNumber(a: number): string { + return "invoke2" + } + fooString(a: string): string { + return "invoke3" + } + + overload foo{ fooInt, fooNumber, fooString } +} + +function main() { + let a = new Sub1(); + arktest.assertEQ(a.fooNumber(1), "invoke1"); + arktest.assertEQ(a.foo(1), "invoke1"); + arktest.assertEQ(a.foo("abc"), "invoke2"); + + let b = new Sub2(); + arktest.assertEQ(b.foo(1), "invoke1"); + arktest.assertEQ(b.foo("abc"), "invoke3"); +} diff --git a/ets2panda/test/runtime/ets/first_match/primitive.ets b/ets2panda/test/runtime/ets/first_match/primitive.ets new file mode 100644 index 0000000000..fdb2a3acc9 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/primitive.ets @@ -0,0 +1,48 @@ +/* + * 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. + */ + +class Test { + foo1(a: byte): string { return "invoke1" } + foo2(a: int): string { return "invoke2" } + foo3(a: float): string { return "invoke3" } + foo4(a: number): string { return "invoke4" } + foo5(a: char): string { return "invoke5" } + foo6(a: string): string { return "invoke6" } + foo7(a: Byte): string { return "invoke7" } + foo8(a: Int): string { return "invoke8" } + foo9(a: Number): string { return "invoke9" } + foo10(a: Float): string { return "invoke10" } + + overload foo{ foo1, foo2, foo3, foo4, foo5, foo6, foo7, foo8, foo9, foo10 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo(1), "invoke2") + arktest.assertEQ(a.foo(1 as byte), "invoke1") + arktest.assertEQ(a.foo(1 as int), "invoke2") + arktest.assertEQ(a.foo(1 as number), "invoke4") + arktest.assertEQ(a.foo(1.0), "invoke4") + arktest.assertEQ(a.foo(1.0 as float), "invoke3") + arktest.assertEQ(a.foo('a'), "invoke6") + arktest.assertEQ(a.foo("abcd"), "invoke6") + + let param1: Int = 1; + let param2: Number = 1; + let param3: Float = 1; + arktest.assertEQ(a.foo(param1), "invoke2") + arktest.assertEQ(a.foo(param2), "invoke4") + arktest.assertEQ(a.foo(param3), "invoke3") +} diff --git a/ets2panda/test/runtime/ets/first_match/rest_parameter.ets b/ets2panda/test/runtime/ets/first_match/rest_parameter.ets new file mode 100644 index 0000000000..1f25bf060d --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/rest_parameter.ets @@ -0,0 +1,52 @@ +/* + * 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. + */ + +class A { + field: string = "A" +} +class B { + field: string = "B" +} + +class Test { + foo1(a: string): string { + return "invoke1" + } + foo2(a: A, b: B, ...args: string[]): string { + return "invoke2" + } + foo3(a: B, ...args: string[]): string { + return "invoke3" + } + + overload foo{ foo1, foo2, foo3 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo("abc"), "invoke1"); + + let restparam1: string[] = ["abc", "abc"] + arktest.assertEQ(a.foo(new A(), new B()), "invoke2"); + arktest.assertEQ(a.foo(new A(), new B(), "abc"), "invoke2"); + arktest.assertEQ(a.foo(new A(), new B(), "abc", "abc", "abc"), "invoke2"); + arktest.assertEQ(a.foo(new A(), new B(), ...restparam1), "invoke2"); + + let restparam2: string[] = ["abc", "abc"] + arktest.assertEQ(a.foo(new B()), "invoke3"); + arktest.assertEQ(a.foo(new B(), "abc"), "invoke3"); + arktest.assertEQ(a.foo(new B(), "abc", "abc", "abc"), "invoke3"); + arktest.assertEQ(a.foo(new B(), ...restparam1), "invoke3"); +} diff --git a/ets2panda/test/runtime/ets/first_match/static_and_nonstatic.ets b/ets2panda/test/runtime/ets/first_match/static_and_nonstatic.ets new file mode 100644 index 0000000000..0d5661146a --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/static_and_nonstatic.ets @@ -0,0 +1,42 @@ +/* + * 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. + */ + +class A { + static foo1(a: number): string { + return "invoke1" + }; + static foo2(a: string): string { + return "invoke2" + }; + + static overload foo{ foo1, foo2 } + + foo3(a: number): string { + return "invoke3" + }; + foo4(a: string): string { + return "invoke4" + }; + + overload foo{ foo3, foo4 } +} + +function main() { + let a = new A(); + arktest.assertEQ(a.foo(1), "invoke3") + arktest.assertEQ(a.foo("aaa"), "invoke4") + arktest.assertEQ(A.foo(1), "invoke1") + arktest.assertEQ(A.foo("aaa"), "invoke2") +} diff --git a/ets2panda/test/runtime/ets/first_match/stringliteral.ets b/ets2panda/test/runtime/ets/first_match/stringliteral.ets new file mode 100644 index 0000000000..2f354314af --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/stringliteral.ets @@ -0,0 +1,35 @@ +/* + * 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. + */ + +function on1(type: "click", callback: () => void): string { + return "invoke1" +} + +function on2(type: "gestrue", callback: () => void): string { + return "invoke2" +} + +function on3(type: "Roll", callback: (param1: number) => void): string { + return "invoke3" +} + +overload on{ on1, on2, on3 } + +function main() { + arktest.assertEQ(on("click", () => { }), "invoke1") + arktest.assertEQ(on("gestrue", () => { }), "invoke2") + arktest.assertEQ(on("Roll", (a: number) => { }), "invoke3") +} + diff --git a/ets2panda/test/runtime/ets/first_match/trailing_lambda.ets b/ets2panda/test/runtime/ets/first_match/trailing_lambda.ets new file mode 100644 index 0000000000..74e0a50c3c --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/trailing_lambda.ets @@ -0,0 +1,53 @@ +/* + * 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. + */ + +class A { } +class B { } + +class Test { + foo1(a: A, lambda1: () => void): string { + lambda1() + return "invoke1"; + } + foo2(a: A, b: B, lambda1: (a: number) => void): string { + lambda1(1) + return "invoke2"; + } + foo3(a: A, b: B, lambda1: () => void): string { + lambda1() + return "invoke3"; + } + foo4(a: B, b: A, lambda1: () => void): string { + lambda1() + return "invoke4"; + } + + overload foo{ foo1, foo2, foo3, foo4 } +} + +function main() { + let a: Test = new Test(); + + arktest.assertEQ(a.foo(new A(), () => { }), "invoke1") + arktest.assertEQ(a.foo(new A()){ return; }, "invoke1") + + arktest.assertEQ(a.foo(new A(), new B(), (a: number) => { }), "invoke2") + + arktest.assertEQ(a.foo(new A(), new B(), () => { }), "invoke2") + arktest.assertEQ(a.foo(new A(), new B()){ return; }, "invoke2") + + arktest.assertEQ(a.foo(new B(), new A(), () => { }), "invoke4") + arktest.assertEQ(a.foo(new B(), new A()){ return; }, "invoke4") +} diff --git a/ets2panda/test/runtime/ets/first_match/union.ets b/ets2panda/test/runtime/ets/first_match/union.ets new file mode 100644 index 0000000000..34ee5b7f0e --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/union.ets @@ -0,0 +1,43 @@ +/* + * 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. + */ + +class A { + field: string = "A" +} +class B { + field: string = "B" +} + +class Test { + foo1(a: string): string { + return "invoke1"; + } + foo2(a: A | number): string { + return "invoke2"; + } + foo3(a: A | B | string | number): string { + return "invoke3"; + } + + overload foo{ foo1, foo2, foo3 } +} + +function main() { + let a: Test = new Test(); + arktest.assertEQ(a.foo(new A()), "invoke2"); + arktest.assertEQ(a.foo(new B()), "invoke3"); + arktest.assertEQ(a.foo("abc"), "invoke1"); + arktest.assertEQ(a.foo(123), "invoke2"); +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/15445.ets b/ets2panda/test/runtime/ets/overload_declaration/15445.ets new file mode 100644 index 0000000000..04863ae70f --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/15445.ets @@ -0,0 +1,36 @@ +/* + * 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. + */ + +class A { + public static foo1(fn: (a1: A1) => void, arg: A1): void { + fn(arg) + } + public static foo2(fn: (a1: A1, a2: A2) => void, arg1: A1, arg2: A2): void { + fn(arg1, arg2) + } + static overload foo{ foo1, foo2 } +} + +function t1(s: String): void { +} + +function t2(s: String, n: int): void { +} + +function main(): int { + A.foo(t1, "lll"); + A.foo(t2, "llll", 1) + return 0 +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/15502.ets b/ets2panda/test/runtime/ets/overload_declaration/15502.ets new file mode 100644 index 0000000000..05439ef6ee --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/15502.ets @@ -0,0 +1,36 @@ +/* + * 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. + */ + +class A { + public static foo1(fn: (a: A1) => void, arg: A1): void { + fn(arg) + } + public static foo2(fn: (a1: A1, a2: A2) => void, arg1: A1, arg2: A2): void { + fn(arg1, arg2) + } + static overload foo{ foo1, foo2 } +} + +function t1(s: String): void { +} + +function t2(s: String, n: int): void { +} + +function main(): int { + A.foo(t1, "lll"); + A.foo(t2, "llll", 1) + return 0 +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/Enum2.ets b/ets2panda/test/runtime/ets/overload_declaration/Enum2.ets new file mode 100644 index 0000000000..9d25d2fc0a --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/Enum2.ets @@ -0,0 +1,61 @@ +/* + * 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. + */ + +enum Color { Red, Green, Blue } + +class ColorEnumDelegate { + private static values_: Color[] = [Color.Red, Color.Green, Color.Blue]; + private static names_: String[] = ["Red", "Green", "Blue"]; + + public static values(): Color[] { return ColorEnumDelegate.values_; } + + public static ordinal(x: Color): int { return x as int; } + + public static toString(x: Color): String { return ColorEnumDelegate.names_[x as int]; } + + public static valueOf1(name: String): Color { + for (let i = 0; i < ColorEnumDelegate.values_.length; i++) { + if (ColorEnumDelegate.names_[i] == name) { return ColorEnumDelegate.values_[i]; } + } + + arktest.assertTrue(false, "No enum constant Color") + return Color.Red; + } + + public static valueOf2(ordinal: int): Color { + if (0 <= ordinal && ordinal < ColorEnumDelegate.values_.length) { + return ColorEnumDelegate.values_[ordinal]; + } + + arktest.assertTrue(false, "No enum constant Color") + return Color.Red; + } + + static overload valueOf{ valueOf1, valueOf2 } +} + +function main(): void { + let red: Color = Color.Red; + arktest.assertEQ(ColorEnumDelegate.toString(red), "Red") + + arktest.assertEQ(ColorEnumDelegate.ordinal(red), 0) + arktest.assertEQ(ColorEnumDelegate.ordinal(Color.Green), 1) + + arktest.assertEQ(ColorEnumDelegate.valueOf(2), Color.Blue) + arktest.assertEQ(ColorEnumDelegate.valueOf(ColorEnumDelegate.ordinal(Color.Red)), red) + + arktest.assertEQ(ColorEnumDelegate.valueOf("Green"), Color.Green) + arktest.assertEQ(ColorEnumDelegate.valueOf(ColorEnumDelegate.toString(Color.Blue)), Color.Blue) +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature01.ets b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature01.ets new file mode 100644 index 0000000000..73ef400a6b --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature01.ets @@ -0,0 +1,28 @@ +/* + * 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. + */ + +function main(): void { + arktest.assertEQ(foo(5), 5); +} + +function foo2(a: int, b: int = 10): int { + return a + b; +} + +function foo1(a: int): int { + return a; +} + +overload foo{ foo1, foo2 } diff --git a/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature02.ets b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature02.ets new file mode 100644 index 0000000000..e0a6e440fe --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature02.ets @@ -0,0 +1,28 @@ +/* + * 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. + */ + +function main(): void { + arktest.assertEQ(foo(5), 5); +} + +function foo2(a: int, b?: int): int { + return a + 2; +} + +function foo1(a: int): int { + return a; +} + +overload foo{ foo1, foo2 } diff --git a/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature03.ets b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature03.ets new file mode 100644 index 0000000000..fe270edcf8 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature03.ets @@ -0,0 +1,28 @@ +/* + * 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. + */ + +function main(): void { + arktest.assertEQ(foo(5), 5); +} + +function foo2(a: int, ...b: int[]): int { + return a + 2; +} + +function foo1(a: int): int { + return a; +} + +overload foo{ foo1, foo2 } diff --git a/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature04.ets b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature04.ets new file mode 100644 index 0000000000..54029d15cc --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature04.ets @@ -0,0 +1,28 @@ +/* + * 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. + */ + +function main(): void { + arktest.assertEQ(foo(5, 2), 7); +} + +function foo2(a: int, ...b: int[]): int { + return 0; +} + +function foo1(a: int, b: int): int { + return a + b; +} + +overload foo{ foo1, foo2 } diff --git a/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature05.ets b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature05.ets new file mode 100644 index 0000000000..1fa99e6569 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature05.ets @@ -0,0 +1,32 @@ +/* + * 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. + */ + +function main(): void { + arktest.assertEQ(foo(5, 2), "aaaa"); +} + +function foo1(a: int, b: int): string { + return "aaaa"; +} + +function foo3(a: int, ...b: int[]): string { + return "bbbb"; +} + +function foo2(a: int, b: int, c?: int): string { + return "cccc"; +} + +overload foo{ foo1, foo2, foo3 } diff --git a/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature06.ets b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature06.ets new file mode 100644 index 0000000000..ff27d701d5 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature06.ets @@ -0,0 +1,32 @@ +/* + * 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. + */ + +function main(): void { + arktest.assertEQ(foo(5, 2), "aaaa"); +} + +function foo1(a: int, b: int): string { + return "aaaa"; +} + +function foo3(a: int, ...b: int[]): string { + return "bbbb"; +} + +function foo2(a: int, b: int, c: int = 10): string { + return "cccc"; +} + +overload foo{ foo1, foo2, foo3 } diff --git a/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature07.ets b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature07.ets new file mode 100644 index 0000000000..da6662e4b3 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FirstMatchSignature07.ets @@ -0,0 +1,33 @@ +/* + * 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. + */ + +function main(): void { + arktest.assertEQ(foo("1"), 3); +} + +class A { } +class B { } + +function foo2(x: string, y?: A) { + return 1 +} +function foo3(x: string, y?: B) { + return 2 +} +function foo1(x: string) { + return 3 +} + +overload foo{ foo1, foo2, foo3 } diff --git a/ets2panda/test/runtime/ets/overload_declaration/FixFunctionCall.ets b/ets2panda/test/runtime/ets/overload_declaration/FixFunctionCall.ets new file mode 100644 index 0000000000..1594345abf --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FixFunctionCall.ets @@ -0,0 +1,27 @@ +/* + * 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. + */ + +export type AsyncCallback = (err: T, data: T) => void; + +function getBundleInfo1(userId?: number): void { } +function getBundleInfo2(callback: AsyncCallback): void { + callback(666, 66); +} +overload getBundleInfo{ getBundleInfo1, getBundleInfo2 } + +getBundleInfo((err, data) => { + arktest.assertEQ(err, 666); + arktest.assertEQ(data, 66) +}); diff --git a/ets2panda/test/runtime/ets/overload_declaration/FunctionOverload.ets b/ets2panda/test/runtime/ets/overload_declaration/FunctionOverload.ets new file mode 100644 index 0000000000..84ad4d8400 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/FunctionOverload.ets @@ -0,0 +1,44 @@ +/* + * 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. + */ + +class Overload { + public static func1(): string { + return "zero"; + } + + public static func2(a: number): string { + return "one"; + } + + public static func3(a: number, b: number): string { + return "two"; + } + + public static func4(...args: number[]): string { + return "variadic"; + } + + static overload func{ func1, func2, func3, func4 } +} + +function main(): void { + arktest.assertEQ(Overload.func(), "zero") + arktest.assertEQ(Overload.func(1), "one") + arktest.assertEQ(Overload.func(1, 2), "two") + arktest.assertEQ(Overload.func(1, 2, 3), "variadic") + + let arr: number[] = [1, 2]; + arktest.assertEQ(Overload.func(...arr), "variadic") +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/InterfacePrivateMethod2.ets b/ets2panda/test/runtime/ets/overload_declaration/InterfacePrivateMethod2.ets new file mode 100644 index 0000000000..7a415f960b --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/InterfacePrivateMethod2.ets @@ -0,0 +1,43 @@ +/* + * 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. + */ + +interface Vehicle { + getHorsePower31(rpm: int, trq: int): int{ + return (rpm * trq) / 5252; + } + + getPwrIndex1(trq: int): int{ + return this.getHorsePower3(5252, trq); + } + + getHorsePower32(rpm: int): int{ + return rpm; + } + + getPwrIndex2(trq: int, second: int): int{ + return this.getHorsePower3(trq + second); + } + + overload getHorsePower3{ getHorsePower31, getHorsePower32 } + + overload getPwrIndex{ getPwrIndex1, getPwrIndex2 } +} + +class Car implements Vehicle { } + +function main(): void { + arktest.assertEQ(new Car().getPwrIndex(1), 1) + arktest.assertEQ(new Car().getPwrIndex(1, 1), 2) +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/RestTuple4.ets b/ets2panda/test/runtime/ets/overload_declaration/RestTuple4.ets new file mode 100644 index 0000000000..b6cc175535 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/RestTuple4.ets @@ -0,0 +1,47 @@ +/* + * 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. + */ + +class A { + public field: number + constructor constructor2(...numbers: [number, number, number]) { + this.field = numbers[0] + numbers[1] + numbers[2] + } + + constructor constructor1(a: int, ...numbers: [number, number, number]) { + this.field = a + numbers[0] + numbers[1] + numbers[2] + } + + overload constructor{ constructor1, constructor2 } +} + +function main() { + let tuple: [number, number, number] = [30, 40, 50] + + let res: A = new A(10, 20, 30) + let res2: A = new A(10, 20, 30, 40) + + let res3: A = new A(...tuple) + let res4: A = new A(10, ...tuple) + + let res5: A = new A(...([30, 40, 50] as [number, number, number])) + let res6: A = new A(10, ...([30, 40, 50] as [number, number, number])) + + arktest.assertEQ(res.field, 60) + arktest.assertEQ(res2.field, 100) + arktest.assertEQ(res3.field, 120) + arktest.assertEQ(res4.field, 130) + arktest.assertEQ(res5.field, 120) + arktest.assertEQ(res6.field, 130) +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/RestTuple8.ets b/ets2panda/test/runtime/ets/overload_declaration/RestTuple8.ets new file mode 100644 index 0000000000..5a33c0f26e --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/RestTuple8.ets @@ -0,0 +1,47 @@ +/* + * 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. + */ + +class A { } +class B { } + +class C { + public field: boolean + + constructor constructor2(...p: [A, B]) { + this.field = p[0] == p[1] + } + + constructor constructor1(a: int, ...p: [A, B]) { + this.field = p[0] == p[1] + } + + overload constructor{ constructor1, constructor2 } +} + +function main() { + let a1: [A, B] = [new A, new B] + + arktest.assertTrue((new C(...a1)).field == false) + arktest.assertTrue((new C(22, ...a1)).field == false) + + arktest.assertTrue((new C(...[new A, new B])).field == false) + arktest.assertTrue((new C(22, ...[new A, new B])).field == false) + + arktest.assertTrue((new C(...[new A, new B] as [A, B])).field == false) + arktest.assertTrue((new C(22, ...[new A, new B] as [A, B])).field == false) + + arktest.assertTrue((new C(new A, new B)).field == false) + arktest.assertTrue((new C(22, new A, new B)).field == false) +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/SmartCast_03.ets b/ets2panda/test/runtime/ets/overload_declaration/SmartCast_03.ets new file mode 100644 index 0000000000..7077075c1a --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/SmartCast_03.ets @@ -0,0 +1,74 @@ +/* + * 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. + */ + +class C { + constructor constructor1() { } + + constructor constructor2(a: int) { + this.x = a; + } + + overload constructor{ constructor1, constructor2 } + + bar(): string { + return "Class C"; + } + + baz(): int { + return this.x; + } + + private x: int = 7; +} + +function foo(c: Object | null | undefined): string { + if (c instanceof string && (c.length == 11 || c == "Test")) { + c = "Case 1"; + } else if (c instanceof C && c.baz() == 7) { + arktest.assertEQ(c.bar(), "Class C") + c = "Case 2"; + } else if (c instanceof Int && c >= 0) { + arktest.assertTrue(c >= 0) + c = "Case 3"; + } else if (c instanceof null) { + arktest.assertEQ(c, null) + c = "Case 4"; + } else { + c = "Case 5"; + } + + arktest.assertEQ(c.length, 6) + return c; +} + +function main(): void { + arktest.assertEQ(foo("Test string"), "Case 1") + arktest.assertEQ(foo("Test"), "Case 1") + arktest.assertEQ(foo("Test string 2"), "Case 5") + arktest.assertEQ(foo("test"), "Case 5") + + arktest.assertEQ(foo(new Int(5)), "Case 3") + arktest.assertEQ(foo(new Int(0)), "Case 3") + arktest.assertEQ(foo(new Int(-5)), "Case 5") + + arktest.assertEQ(foo(new C(7)), "Case 2") + arktest.assertEQ(foo(new C()), "Case 2") + arktest.assertEQ(foo(new C(17)), "Case 5") + + arktest.assertEQ(foo(null), "Case 4") + + arktest.assertEQ(foo(undefined), "Case 5") + arktest.assertEQ(foo(new Number(3.0)), "Case 5") +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/async-func-overload-and-type-infer.ets b/ets2panda/test/runtime/ets/overload_declaration/async-func-overload-and-type-infer.ets new file mode 100644 index 0000000000..0b99a3f81d --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/async-func-overload-and-type-infer.ets @@ -0,0 +1,41 @@ +/* + * 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. + */ + +async function multipleReturns2(flag: boolean, foo: int) { + if (flag) { + return foo; + } + + return "string1" +} + + +async function multipleReturns1(flag: boolean): Promise { + if (flag) { + return 2; + } + + return "string2" +} + +async overload multipleReturns{ multipleReturns1, multipleReturns2 } + +function main() { + let a: int | string = await multipleReturns(true, 42); + let b: int | string = await multipleReturns(false); + + arktest.assertEQ(a, 42) + arktest.assertEQ(b, "string2") +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/async_method_with_same_name02.ets b/ets2panda/test/runtime/ets/overload_declaration/async_method_with_same_name02.ets new file mode 100644 index 0000000000..fd075cefcb --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/async_method_with_same_name02.ets @@ -0,0 +1,31 @@ +/* + * 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. + */ + +class A { + static async getData1() { + return "I'm a static method1 with name 'getData'"; + } + static async getData2(s: string) { + return s; + } + static async overload getData{ getData1, getData2 } +} + +function main() { + let res1: string = await A.getData() + let res2: string = await A.getData("I'm a static method2 with name 'getData'") + arktest.assertEQ(res1, "I'm a static method1 with name 'getData'") + arktest.assertEQ(res2, "I'm a static method2 with name 'getData'") +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/conditionalExpressionLUB.ets b/ets2panda/test/runtime/ets/overload_declaration/conditionalExpressionLUB.ets new file mode 100644 index 0000000000..d0487c8f89 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/conditionalExpressionLUB.ets @@ -0,0 +1,94 @@ +/* + * 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. + */ + +interface I { } + +class A { } +class B extends A implements I { } +final class C extends A implements I { } +final class D extends A { } +final class F extends B { } + +function foo6(p: Object): int { + return 1; +} + +function foo5(p: A): int { + return 2; +} + +function foo4(p: B): int { + return 3; +} + +function foo3(p: C): int { + return 4; +} + +function foo2(p: D): int { + return 5; +} + +function foo1(p: F): int { + return 6; +} + +overload foo{ foo1, foo2, foo3, foo4, foo5, foo6 } + +function getTrue(): boolean { + return true +} + +// #15276 foo(Object|null) and foo(Object) overloads +function foo7(p: Object | null): int { + return 7; +} + +function main(): void { + sameTypeLUB(); + objectLUB(); + forkSubtypeLUB(); +} + +function sameTypeLUB(): void { + let a: A = new A(); + let b: A = new A(); + let c = getTrue() ? a : b; + arktest.assertEQ(foo(c), 2) +} + +function objectLUB(): void { + let a: A = new A(); + let b: Int = 2; + let c = getTrue() ? a : b; + arktest.assertEQ(foo(c), 1) + + let arr: Int[] | null = null; + let d = getTrue() ? a : arr; + arktest.assertEQ(foo7(d), 7) +} + +function forkSubtypeLUB(): void { + let a: F = new F(); + let b: D = new D(); + let c = getTrue() ? a : b; + arktest.assertEQ(foo(c), 2) + let d: A = new A(); + let e = getTrue() ? a : b; + arktest.assertEQ(foo(e), 2) + let f: B = new B(); + let g = getTrue() ? a : f; + arktest.assertEQ(foo(g), 3) +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/constructor-issue.ets b/ets2panda/test/runtime/ets/overload_declaration/constructor-issue.ets new file mode 100644 index 0000000000..88efbb6747 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/constructor-issue.ets @@ -0,0 +1,61 @@ +/* + * 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. + */ + +class A { + field: int = 5 + + constructor constructor1(arg: boolean) { + } + + constructor constructor2(arg?: int) { + if (arg == undefined) { + this.field += 20 + } else { + this.field += arg; + return; // Return statement is necessary to reproduce stack overflow and invalid constructor generation issue. + } + } + + overload constructor{ constructor1, constructor2 } +} + +class B { + field: int = 5; + + constructor constructor2(arg: boolean) { + } + + constructor constructor3(arg: int) { + this.field += arg; + return; // Return statement is necessary to reproduce stack overflow issue. + } + + constructor constructor1() { + this(15); + this.field += 30; + } + + overload constructor{ constructor1, constructor2, constructor3 } +} + +function main(): void { + arktest.assertEQ(new A(true).field, 5); // field = 5 + arktest.assertEQ(new A(10).field, 15); // field = 5 + 10 + arktest.assertEQ(new A().field, 25); // field = 5 + 20 + + arktest.assertEQ(new B(true).field, 5); // field = 5 + arktest.assertEQ(new B(20).field, 25); // field = 5 + 20 + arktest.assertEQ(new B().field, 50); // field = 5 + 15 + 30 +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/constructor_overload_sig_with_ref_type.ets b/ets2panda/test/runtime/ets/overload_declaration/constructor_overload_sig_with_ref_type.ets new file mode 100644 index 0000000000..30a8088418 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/constructor_overload_sig_with_ref_type.ets @@ -0,0 +1,41 @@ +/* + * 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. + */ + +class A{ + a:Int = 1 + constructor constructor1(){} + constructor constructor2(a:Int){} + overload constructor{ constructor1, constructor2 } +} + +class B{ + a:Number = 1 + constructor(){} + constructor constructor1(a:Number){} + overload constructor{ constructor1 } +} + +class C{ + a:String = "1" + constructor constructor1(){} + constructor constructor2(a:String){} + overload constructor{ constructor1, constructor2 } +} + +function main() : void { + let a = new A(5); + let b = new B(5); + let c = new C("5"); +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/default_parameter1.ets b/ets2panda/test/runtime/ets/overload_declaration/default_parameter1.ets new file mode 100644 index 0000000000..73ef400a6b --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/default_parameter1.ets @@ -0,0 +1,28 @@ +/* + * 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. + */ + +function main(): void { + arktest.assertEQ(foo(5), 5); +} + +function foo2(a: int, b: int = 10): int { + return a + b; +} + +function foo1(a: int): int { + return a; +} + +overload foo{ foo1, foo2 } diff --git a/ets2panda/test/runtime/ets/overload_declaration/first_match_method_with_rest_param_2.ets b/ets2panda/test/runtime/ets/overload_declaration/first_match_method_with_rest_param_2.ets new file mode 100644 index 0000000000..4a89994fc9 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/first_match_method_with_rest_param_2.ets @@ -0,0 +1,27 @@ +/* + * 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. + */ + +function foo1(...x: FixedArray) { + return 1; +} + +function foo2(...x: FixedArray) { + return 2; +} + +overload foo{ foo1, foo2 } + +arktest.assertEQ(foo("bar"), 1) +arktest.assertEQ(foo(1), 2) diff --git a/ets2panda/test/runtime/ets/overload_declaration/first_match_method_with_rest_param_3.ets b/ets2panda/test/runtime/ets/overload_declaration/first_match_method_with_rest_param_3.ets new file mode 100644 index 0000000000..4026b56634 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/first_match_method_with_rest_param_3.ets @@ -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. + */ + +type B = Object | null; +function foo2(...b : B[]) { return 1; } +function foo1(str: String) { return 2; } +overload foo{ foo1, foo2 } + +arktest.assertEQ(foo(new String()), 2) diff --git a/ets2panda/test/runtime/ets/overload_declaration/generic-set.ets b/ets2panda/test/runtime/ets/overload_declaration/generic-set.ets new file mode 100644 index 0000000000..d701efae93 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/generic-set.ets @@ -0,0 +1,96 @@ +/* + * 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. + */ + +interface MyStack { + getTop(): Item | null + pop(): Item | null + push(item: Item): void + isEmpty(): boolean + size(): int +} + +class MyArrayStack implements MyStack { + private container: (Item | undefined)[]; + private top: int = -1; + private readonly DEFAULT_SIZE: int = 100; + constructor constructor1() { + let x = new Object(); + this.container = new (Item | undefined)[this.DEFAULT_SIZE]; + this.top = -1; + } + + constructor constructor2(size: int) { + this.container = new (Item | undefined)[size]; + } + + overload constructor{ constructor1, constructor2 } + override getTop(): Item | null { + if (this.top == -1) { + return null; + } + return this.container[this.top]!; + } + + override pop(): Item | null { + if (this.top == -1) { + return null; + } + return this.container[this.top--]!; + } + + override push(item: Item): void { + this.container[++this.top] = item; + } + + override isEmpty(): boolean { + return (this.top == -1); + } + + override size(): int { + return (this.top + 1); + } +} + +function main(): void { + let stack1: MyArrayStack; + stack1 = new MyArrayStack(); + arktest.assertEQ(stack1.isEmpty(), true) + arktest.assertEQ(stack1.size(), 0) + + stack1.push(new Int(10)); + arktest.assertEQ(stack1.isEmpty(), false) + arktest.assertEQ(stack1.size(), 1) + arktest.assertEQ((stack1.getTop() as Int), 10) + + stack1.push(new Int(20)); + stack1.push(new Int(30)); + arktest.assertEQ(stack1.isEmpty(), false) + arktest.assertEQ(stack1.size(), 3) + arktest.assertEQ((stack1.getTop() as Int), 30) + + arktest.assertEQ((stack1.pop() as Int), 30) + arktest.assertEQ(stack1.size(), 2) + arktest.assertEQ((stack1.pop() as Int), 20) + arktest.assertEQ(stack1.size(), 1) + arktest.assertEQ((stack1.pop() as Int), 10) + arktest.assertEQ(stack1.size(), 0) + arktest.assertEQ(stack1.isEmpty(), true) + + arktest.assertEQ(stack1.getTop(), null) + arktest.assertEQ(stack1.pop(), null) + arktest.assertEQ(stack1.size(), 0) + arktest.assertEQ(stack1.isEmpty(), true) + +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/keyword_get_set_as_identfier2.ets b/ets2panda/test/runtime/ets/overload_declaration/keyword_get_set_as_identfier2.ets new file mode 100644 index 0000000000..e3e07aee1f --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/keyword_get_set_as_identfier2.ets @@ -0,0 +1,31 @@ +/* + * 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. + */ + +export class set { + constructor constructor1() { } + constructor constructor2(a: int) { }; + overload constructor{ constructor1, constructor2 } + get set(): int { return 1; } + $_get(index: number): set { return new set } + $_set(index: number, value: set) { } +} + +let get: set +get = new set(); + +new + set(1) + +get[get.set] = get[0] diff --git a/ets2panda/test/runtime/ets/overload_declaration/notNull.ets b/ets2panda/test/runtime/ets/overload_declaration/notNull.ets new file mode 100644 index 0000000000..837a42a528 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/notNull.ets @@ -0,0 +1,169 @@ +/* + * 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. + */ + +function main() { + testLocalIdentifier() + testArgument() + testCallExpression() + testNPE() + testFieldAccess() + testFieldAccess2() +} + +function typeOf1(i: Int): int { + return 1; +} + +function typeOf2(o: Object): int { + return -1; +} + +overload typeOf{ typeOf1, typeOf2 } + +function dummy(): Int | null { + return 5; +} + +function testLocalIdentifier(): void { + let a: Int | null = dummy(); + let b = a!; + + arktest.assertEQ(typeOf(b), 1, "b must be type Int") + arktest.assertEQ(b, 5, "b must be 5") + + let c = b + a! * 7; + + arktest.assertEQ(c, 40, "c should be 40") + + arktest.assertEQ(a!, (a)!) +} + +function bar(arg: Int | null): Int { + return arg!; +} + +function testArgument(): void { + let a: Int | null = 7; + let b = bar(a); + + arktest.assertEQ(typeOf(b), 1, "b must be type Int") + arktest.assertEQ(b, 7) +} + +function foo(): Double | null { + return new Double(3.1415); +} + +class Foo { + foo(): Float | null { + return Float.DELTA; + } +} + +function testCallExpression() { + let d = foo()! + + arktest.assertTrue(d instanceof Double, "d must be type Double") + arktest.assertEQ(d, 3.1415, "d must be 3.1415") + + let sd = foo()!.toString() + + arktest.assertTrue("3.1415".equals(sd), "s must be '3.1415'") + + let f = new Foo().foo()! + + arktest.assertTrue(f instanceof Float, "f must be type Float") + arktest.assertEQ(f, Float.DELTA, "f must be Float.DELTA") +} + +function baz(): Byte | null { + return null; +} + +function aux(): Object | null { + return null; +} + +function testNPE(): void { + let o: Object | null = aux(); + let npe_caught = false; + + try { + (o as Object | null)!; + arktest.assertTrue(false, "this must not be executed") + } catch (ex: NullPointerError) { + npe_caught = true; + } + + arktest.assertTrue(npe_caught, "NPE must be caught") + + try { + baz()!; + arktest.assertTrue(false, "this must not be executed") + } catch (ex: NullPointerError) { + npe_caught = true; + } + + arktest.assertTrue(npe_caught, "NPE must be caught") +} + +class A { + public static c: Char | null = c'C'; + public d: Char | null = c'D' +} + +class B { + public a: A | null; + + constructor(a: A | null) { + this.a = a; + } + + public setA(a: A) { + this.a = a; + } + + public getA(): A { + return this.a!; + } +} + +function testFieldAccess(): void { + let ac = A.c!; + arktest.assertEQ(ac, c'C', "ac should be 'C'") + + let a_orig = new A(); + let b = new B(a_orig); + + let a = b.a!; + + arktest.assertEQ(a, a_orig, "a should be the object referenced by a_orig") + + let d = b.a!.d!; + + arktest.assertEQ(d, c'D', "d should be 'D'") +} + +function testFieldAccess2(): void { + let a = new A(); + let b = new B(a); + + arktest.assertEQ(b.getA(), a, "getA should return the same object that was given to the constructor") + + let a2 = new A(); + b.setA(a2); + + arktest.assertEQ(b.getA(), a2, "getA should return the same object that was given to setA") +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/objectLiteral.ets b/ets2panda/test/runtime/ets/overload_declaration/objectLiteral.ets new file mode 100644 index 0000000000..2ed459a68b --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/objectLiteral.ets @@ -0,0 +1,75 @@ +/* + * 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. + */ + +class Base { + f: int +} + +class InnerValue { + v: int +} + +class C extends Base { + x: Int = 5 + s: String = "" + iv: InnerValue = {} +} + +function returnC(): C { + return { x: 99, f: 44, s: "qq", iv: { v: 77 } } // return statement +} + +function test1(c: int, f: int, x: int, s: String, ivv: int) { } // should not prevent calling the next fun +function test2(c: C, f: int, x: int, s: String, ivv: int) { + arktest.assertEQ(c.f, f) + arktest.assertEQ(c.x, x) + arktest.assertEQ(c.s, s) + arktest.assertEQ(c.iv.v, ivv) +} + +overload test{ test1, test2 } + +function main(): int { + let c: C = { // variable definition + "x": 7, + s: "sss", + }; + test(c, 0, 7, "sss", 0) + + let c2 = { // as construction + f: 4, + s: "qq" + } as C; + test(c2, 4, 5, "qq", 0) + + c = { f: 5, s: "zzz" } // assignment + test(c, 5, 5, "zzz", 0) + + test({ // function argument + f: 3, + x: 8, + s: "uhuh", + iv: { // object literal field + v: 55 + } + }, 3, 8, "uhuh", 55) + + test(returnC(), 44, 99, "qq", 77) + + let ca: C[] = [{ f: 42, s: "first" }, { f: 128, s: "second" }] // array elements + test(ca[1], 128, 5, "second", 0) + + return 0 +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/overload-primitive-and-object.ets b/ets2panda/test/runtime/ets/overload_declaration/overload-primitive-and-object.ets new file mode 100644 index 0000000000..e27d5f1368 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/overload-primitive-and-object.ets @@ -0,0 +1,41 @@ +/* + * 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. + */ + +let res: number = 0; +function foo1(i: int, j: int): void { + res = 19; +} +function foo2(i: number, j: Number): void { + res = 21; +} + +overload foo{ foo1, foo2 } + +function boo1(x: Number, y: number) { + res = 34; +} +function boo2(x: number, y: Number) { + res = 47; +} + +overload boo{ boo1, boo2 } + +function main(): void { + let n: Number = new Number(); + foo(1, n); + arktest.assertEQ(res, 21); + boo(6 as Number, 8); + arktest.assertEQ(res, 34); +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/overload-resolution-rest-1.ets b/ets2panda/test/runtime/ets/overload_declaration/overload-resolution-rest-1.ets new file mode 100644 index 0000000000..bdbdab815a --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/overload-resolution-rest-1.ets @@ -0,0 +1,37 @@ +/* + * 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. + */ + +interface I { + s: string; +} + +let res = 0; +function foo2(f1: number, ...args: (Object | null | undefined)[]) { + res = 1; +} + +function foo1(f1: number, i: I, ...args: (Object | null | undefined)[]) { + res = 2; +} + +overload foo{ foo1, foo2 } + +function main(): void { + const i: I = { s: "sss" }; + foo(1, "sss"); + arktest.assertEQ(res, 1); + foo(1, i as I, "sss"); + arktest.assertEQ(res, 2); +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/overload_declaration/overload-resolution-rest-2.ets b/ets2panda/test/runtime/ets/overload_declaration/overload-resolution-rest-2.ets new file mode 100644 index 0000000000..4fdae60b93 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/overload-resolution-rest-2.ets @@ -0,0 +1,28 @@ +/* + * 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. + */ + +class Base { } +class Derived extends Base { } +type BaseOrDerived = Base | Derived; +let res = 0; + +function bar2(p1: Base, p2: Derived, p3: BaseOrDerived) { res = 1; } +function bar1(p1: Derived, p2: Base, p3: BaseOrDerived) { res = 2; } +function bar3(p1: Base, p2: Base, ...p3: BaseOrDerived[]) { res = 3; } + +overload bar{ bar1, bar2, bar3 } + +bar(new Derived, new Base, new Derived); +arktest.assertEQ(res, 2); \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/overload_declaration/overload_1.ets b/ets2panda/test/runtime/ets/overload_declaration/overload_1.ets new file mode 100644 index 0000000000..74a348cbe4 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/overload_1.ets @@ -0,0 +1,25 @@ +/* + * 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. + */ + +class C { + static $_invoke1() { return C('abc') } + static $_invoke2(p: string) { return p } + static overload $_invoke{ $_invoke1, $_invoke2 } +} + +function main(): int { + if (C() != 'abc') return 1 + return 0 +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/overload_call_1.ets b/ets2panda/test/runtime/ets/overload_declaration/overload_call_1.ets new file mode 100644 index 0000000000..ff5f6e139b --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/overload_call_1.ets @@ -0,0 +1,39 @@ +/* + * 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. + */ + +class A{} +class B{} +class C{} + +class Test1 { + foo110(a: A): A { + return a; + } + foo112(a: B): B { + return a; + } + + foo113(a: C): C { + console.log(a) + return a; + } + overload foo111{foo110,foo112,foo113} +} + +function main() { + let a: Test1 = new Test1(); + let b = new B(); + a.foo111(b); +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/signature_match_lambda.ets b/ets2panda/test/runtime/ets/overload_declaration/signature_match_lambda.ets new file mode 100644 index 0000000000..c19baccda9 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/signature_match_lambda.ets @@ -0,0 +1,43 @@ +/* + * 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. + */ + +class A { + catch1(onRejected: () => U | PromiseLike): string { + onRejected() + return "first catch is matched" + } + catch2(onRejected: (error: Error) => U | PromiseLike): string { + onRejected(new Error()) + return "second catch is matched" + } + catch3(onRejected: (a: Error, b: Error) => U | PromiseLike): string { + onRejected(new Error(), new Error()) + return "third catch is matched" + } + catch4(onRejected: (a: Error, b: Error, c: Error) => U | PromiseLike): string { + onRejected(new Error(), new Error(), new Error()) + return "fourth catch is matched" + } + overload catch{ catch1, catch2, catch3, catch4 } +} + +function main() { + let a = new A() + arktest.assertEQ(a.catch(() => { }), "first catch is matched") + arktest.assertEQ(a.catch((e: Error | undefined | null) => { }), "second catch is matched") + arktest.assertEQ(a.catch((e: Error) => { }), "second catch is matched") + arktest.assertEQ(a.catch((e: Error, e2: Error) => { }), "third catch is matched") + arktest.assertEQ(a.catch((e: Error, e2: Error, e3: Error) => { }), "fourth catch is matched") +} diff --git a/ets2panda/test/runtime/ets/overload_declaration/visible_signatures.ets b/ets2panda/test/runtime/ets/overload_declaration/visible_signatures.ets new file mode 100644 index 0000000000..d665366294 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/visible_signatures.ets @@ -0,0 +1,59 @@ +/* + * 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. + */ + +class A { + foo11(a: Long): Int { + return 1; + } + private foo12(a: Int): Int { + return 0; + } + + overload foo{ foo11, foo12 } + + foo21(a: Int): Int { + return 1; + } + private foo22(a: Long): Int { + return 0; + } + + overload foo2{ foo21, foo22 } + + foo31(a: Long): Int { + return 1; + } + private foo32(a: Int): Int { + return 0; + } + + overload foo3{ foo31, foo32 } + + foo41(a: Int): Int { + return 1; + } + protected foo42(a: Long): Int { + return 0; + } + + overload foo4{ foo41, foo42 } +} + +function main(): void { + arktest.assertEQ(new A().foo(3), 1) + arktest.assertEQ(new A().foo2(3), 1) + arktest.assertEQ(new A().foo3(3), 1) + arktest.assertEQ(new A().foo4(3), 1) +} diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 4c4ae2e28e..903ca5e740 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -1514,3 +1514,43 @@ semantic: - name: DYMANIC_INIT_WITH_OBJEXPR id: 382 message: "Dymanic Type {} cannot be initialize with an object expression" + +- name: OVERLOAD_NAME_MUST_BE_IDENTIFIER + id: 383 + message: "The name of overload declaration should be an identifier." + +- name: OVERLOADED_NAME_MUST_FUNCTION + id: 384 + message: "overloaded name must refer to an accessible method." + +- name: DUPLICATE_OVERLOADED_NAME + id: 385 + message: "Duplicate overloaded method." + +- name: OVERLOAD_SAME_ACCESS_MODIFIERS + id: 386 + message: "Overload alias and overloaded method name must have exactly the same modifiers (public, private, protected)." + +- name: OVERLOAD_SAME_ACCESS_MODIFIERS_STATIC_ASYNC + id: 387 + message: "Overload alias and overloaded method name must have exactly the same modifiers (static, async)." + +- name: OVERLOAD_MUST_BOTH_CONSTRUCT + id: 388 + message: "The overload alias and the overloaded method must either both be constructors or both be non-constructors." + +- name: OVERLOADED_NAME_REFER_TO_OVERLOAD_FUNCTION + id: 389 + message: "The overloaded name '{}' can't refer to a function with overload signatures." + +- name: OVERLOADED_NAME_MUST_ALSO_EXPORTED + id: 390 + message: "Overload alias is exported, then overload functions must also be exported." + +- name: OVERLOADED_UNION_CALL + id: 391 + message: "Overload declaration cannot be called by union." + +- name: OVERLOAD_MODIFIERS_ABSTRACT + id: 392 + message: "overload declaration cannot contain abstract methods." diff --git a/ets2panda/util/diagnostic/syntax.yaml b/ets2panda/util/diagnostic/syntax.yaml index 43a5a991a0..707be9029a 100644 --- a/ets2panda/util/diagnostic/syntax.yaml +++ b/ets2panda/util/diagnostic/syntax.yaml @@ -1295,3 +1295,15 @@ syntax: - name: INIT_MODULE_DECLARATION_POSITION id: 322 message: "initModule() must only be called immediately after the import statement, and before any other declarations or statements." + +- name: OVERLOAD_MODIFIERS + id: 323 + message: "Overload Declaration only allow use modifier 'static' | 'async'." + +- name: CLASS_INTERFACE_METHOD_OVERLOADED_NAME_MUST_IDENT + id: 324 + message: "The overloaded method name in class/interface method overload declaration must be identifier." + +- name: FUNCTION_OVERLOADED_NAME_MUST_QUALIFIED_NAME + id: 325 + message: "The overloaded method name in function overload declaration must be qualified name." \ No newline at end of file diff --git a/ets2panda/util/diagnosticEngine.cpp b/ets2panda/util/diagnosticEngine.cpp index 9e294a8cf8..6f92ba5cd0 100644 --- a/ets2panda/util/diagnosticEngine.cpp +++ b/ets2panda/util/diagnosticEngine.cpp @@ -37,6 +37,29 @@ const DiagnosticStorage &DiagnosticEngine::GetDiagnosticStorage(DiagnosticType t return diagnostics_[type]; } +[[nodiscard]] DiagnosticCheckpoint DiagnosticEngine::Save() const +{ + DiagnosticCheckpoint cp; + for (size_t i = 0; i < diagnostics_.size(); i++) { + cp[i] = diagnostics_[i].size(); + } + return cp; +} + +void DiagnosticEngine::Rollback(const DiagnosticCheckpoint &checkpoint) +{ + for (size_t i = 0; i < diagnostics_.size(); i++) { + diagnostics_[i].resize(checkpoint[i]); + } +} + +void DiagnosticEngine::UndoRange(const DiagnosticCheckpoint &from, const DiagnosticCheckpoint &to) +{ + for (size_t i = 0; i < diagnostics_.size(); i++) { + diagnostics_[i].erase(diagnostics_[i].begin() + from[i], diagnostics_[i].begin() + to[i]); + } +} + [[noreturn]] void DiagnosticEngine::Throw(ThrowableDiagnostic diag) const { throw diag; diff --git a/ets2panda/util/diagnosticEngine.h b/ets2panda/util/diagnosticEngine.h index 015dc4d6ad..d50fd12b24 100644 --- a/ets2panda/util/diagnosticEngine.h +++ b/ets2panda/util/diagnosticEngine.h @@ -48,6 +48,8 @@ public: using DiagnosticStorage = std::vector>; +using DiagnosticCheckpoint = std::array; + class DiagnosticEngine { public: explicit DiagnosticEngine() : printer_(std::make_unique()) @@ -65,6 +67,12 @@ public: // NOTE(schernykh): should be removed const DiagnosticBase &GetAnyError() const; + DiagnosticCheckpoint Save() const; + + void Rollback(const DiagnosticCheckpoint &checkpoint); + + void UndoRange(const DiagnosticCheckpoint &from, const DiagnosticCheckpoint &to); + [[nodiscard]] bool IsAnyError() const noexcept; template diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index 0cfc10ccce..10db15de91 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -432,6 +432,11 @@ void ETSBinder::ResolveMethodDefinition(ir::MethodDefinition *methodDef) thisParam->Declaration()->BindNode(thisParam_); } +void ETSBinder::BuildOverloadDeclaration(ir::OverloadDeclaration *overloadDef) +{ + overloadDef->ResolveReferences([this](auto *childNode) { ResolveReference(childNode); }); +} + void ETSBinder::BuildMemberExpression(ir::MemberExpression *memberExpr) { ResolveReference(memberExpr->Object()); @@ -1156,6 +1161,9 @@ void ETSBinder::HandleCustomNodes(ir::AstNode *childNode) case ir::AstNodeType::METHOD_DEFINITION: { return BuildMethodDefinition(childNode->AsMethodDefinition()); } + case ir::AstNodeType::OVERLOAD_DECLARATION: { + return BuildOverloadDeclaration(childNode->AsOverloadDeclaration()); + } case ir::AstNodeType::ETS_NEW_CLASS_INSTANCE_EXPRESSION: { return BuildETSNewClassInstanceExpression(childNode->AsETSNewClassInstanceExpression()); } @@ -1242,10 +1250,11 @@ void ETSBinder::BuildFunctionName(const ir::ScriptFunction *func) const << compiler::Signatures::METHOD_SEPARATOR; const auto *signature = func->Signature(); + const auto funcName = util::Helpers::FunctionName(Allocator(), func); if (func->IsStaticBlock()) { ss << compiler::Signatures::CCTOR; - } else if (func->IsConstructor()) { + } else if (func->IsConstructor() && funcName.Is(compiler::Signatures::CONSTRUCTOR_NAME)) { ss << compiler::Signatures::CTOR; } else { if (func->IsGetter()) { @@ -1253,7 +1262,7 @@ void ETSBinder::BuildFunctionName(const ir::ScriptFunction *func) const } else if (func->IsSetter()) { ss << compiler::Signatures::SETTER_BEGIN; } - ss << util::Helpers::FunctionName(Allocator(), func); + ss << funcName; } signature->ToAssemblerType(ss); diff --git a/ets2panda/varbinder/ETSBinder.h b/ets2panda/varbinder/ETSBinder.h index d5b6e9888d..001a02cb10 100644 --- a/ets2panda/varbinder/ETSBinder.h +++ b/ets2panda/varbinder/ETSBinder.h @@ -137,6 +137,7 @@ public: void BuildInterfaceDeclaration(ir::TSInterfaceDeclaration *decl); void BuildMemberExpression(ir::MemberExpression *memberExpr); void BuildMethodDefinition(ir::MethodDefinition *methodDef); + void BuildOverloadDeclaration(ir::OverloadDeclaration *overloadDef); void BuildAnnotationDeclaration(ir::AnnotationDeclaration *annoDecl); void BuildAnnotationUsage(ir::AnnotationUsage *annoUsage); void BuildImportDeclaration(ir::ETSImportDeclaration *decl); diff --git a/ets2panda/varbinder/variableFlags.h b/ets2panda/varbinder/variableFlags.h index 5ec081c2e6..12d8b6ff8c 100644 --- a/ets2panda/varbinder/variableFlags.h +++ b/ets2panda/varbinder/variableFlags.h @@ -166,6 +166,7 @@ enum class VariableFlags : uint64_t { NAMESPACE = 1ULL << 35ULL, INIT_IN_STATIC_BLOCK = 1ULL << 36ULL, DYNAMIC = 1ULL << 37ULL, + OVERLOAD = 1ULL << 38ULL, HOIST_VAR = HOIST | VAR, CLASS_OR_INTERFACE = CLASS | INTERFACE, -- Gitee From 645f759e9feb207d34dfa3f2316a8a5353f37989 Mon Sep 17 00:00:00 2001 From: tengtengh Date: Wed, 25 Jun 2025 22:40:59 +0800 Subject: [PATCH 2/3] Implement new java style overload Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICHP8P support overload declaration of $_set and $_get . Signed-off-by: tengtengh --- .../lowering/ets/objectIndexAccess.cpp | 8 ++++ .../lowering/ets/overloadMappingLowering.cpp | 31 ++------------- ets2panda/compiler/lowering/util.cpp | 25 ++++++++++++ ets2panda/compiler/lowering/util.h | 2 + .../ets/overload_declaration/dollar_get_1.ets | 32 +++++++++++++++ .../ets/overload_declaration/dollar_set_1.ets | 39 +++++++++++++++++++ 6 files changed, 109 insertions(+), 28 deletions(-) create mode 100644 ets2panda/test/runtime/ets/overload_declaration/dollar_get_1.ets create mode 100644 ets2panda/test/runtime/ets/overload_declaration/dollar_set_1.ets diff --git a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp index 8382b1dd2c..8c7a4373cf 100644 --- a/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp +++ b/ets2panda/compiler/lowering/ets/objectIndexAccess.cpp @@ -79,6 +79,10 @@ ir::Expression *ObjectIndexLowering::ProcessIndexSetAccess(parser::ETSParser *pa CheckLoweredNode(checker->VarBinder()->AsETSBinder(), checker, loweringResult); loweringResult->SetParent(assignmentExpression->Parent()); loweringResult->AddModifier(ir::ModifierFlags::SETTER); + + ES2PANDA_ASSERT(setter->IsCallExpression()); + TransformOverloadMethodCall(checker, setter->AsCallExpression()); + return loweringResult; } @@ -98,6 +102,10 @@ ir::Expression *ObjectIndexLowering::ProcessIndexGetAccess(parser::ETSParser *pa loweringResult->SetRange(memberExpression->Range()); CheckLoweredNode(checker->VarBinder()->AsETSBinder(), checker, loweringResult); + + ES2PANDA_ASSERT(loweringResult->IsCallExpression()); + TransformOverloadMethodCall(checker, loweringResult->AsCallExpression()); + return loweringResult; } diff --git a/ets2panda/compiler/lowering/ets/overloadMappingLowering.cpp b/ets2panda/compiler/lowering/ets/overloadMappingLowering.cpp index a72a5c6517..cfd132dcfd 100644 --- a/ets2panda/compiler/lowering/ets/overloadMappingLowering.cpp +++ b/ets2panda/compiler/lowering/ets/overloadMappingLowering.cpp @@ -26,33 +26,6 @@ std::string_view OverloadMappingLowering::Name() const return "OverloadMappingLowering"; } -static ir::CallExpression *MethodMapping(public_lib::Context *ctx, ir::CallExpression *callExpression) -{ - auto *checker = ctx->GetChecker()->AsETSChecker(); - auto *allocator = ctx->Allocator(); - - auto *signature = callExpression->Signature(); - ES2PANDA_ASSERT(signature->OwnerVar()->Declaration()->Node()->IsMethodDefinition()); - auto *methodDef = signature->OwnerVar()->Declaration()->Node()->AsMethodDefinition(); - - ir::AstNode *callee = callExpression->Callee(); - while (callee->IsMemberExpression()) { - callee = callee->AsMemberExpression()->Property(); - } - auto *ident = callee->AsIdentifier(); - ident->SetName(methodDef->Id()->Name()); - - varbinder::LocalVariable *syntheticVariable = allocator->New( - varbinder::VariableFlags::SYNTHETIC | varbinder::VariableFlags::METHOD); - ident->SetVariable(syntheticVariable); - checker::ETSFunctionType *funcType = - checker->CreateETSMethodType(methodDef->Id()->Name(), {{}, allocator->Adapter()}); - funcType->AddCallSignature(signature); - syntheticVariable->SetTsType(funcType); - - return callExpression; -} - static bool IsOverloadDeclarationCall(ir::Expression *expr) { while (expr->IsMemberExpression()) { @@ -70,8 +43,10 @@ bool OverloadMappingLowering::PerformForModule(public_lib::Context *ctx, parser: program->Ast()->TransformChildrenRecursively( // CC-OFFNXT(G.FMT.14-CPP) project code style [ctx](ir::AstNode *const node) -> AstNodePtr { + auto *checker = ctx->GetChecker()->AsETSChecker(); + if (node->IsCallExpression() && IsOverloadDeclarationCall(node->AsCallExpression()->Callee())) { - return MethodMapping(ctx, node->AsCallExpression()); + return TransformOverloadMethodCall(checker, node->AsCallExpression()); } return node; }, diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index a175fe9007..7cbe5276cb 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -408,4 +408,29 @@ bool ClassDefinitionIsEnumTransformed(const ir::AstNode *node) { return node != nullptr && node->IsClassDefinition() && node->AsClassDefinition()->IsEnumTransformed(); } + +ir::CallExpression *TransformOverloadMethodCall(checker::ETSChecker *const checker, ir::CallExpression *callExpression) +{ + auto *signature = callExpression->Signature(); + ES2PANDA_ASSERT(signature->OwnerVar()->Declaration()->Node()->IsMethodDefinition()); + auto *methodDef = signature->OwnerVar()->Declaration()->Node()->AsMethodDefinition(); + + ir::AstNode *callee = callExpression->Callee(); + while (callee->IsMemberExpression()) { + callee = callee->AsMemberExpression()->Property(); + } + auto *ident = callee->AsIdentifier(); + ident->SetName(methodDef->Id()->Name()); + + varbinder::LocalVariable *syntheticVariable = checker->Allocator()->New( + varbinder::VariableFlags::SYNTHETIC | varbinder::VariableFlags::METHOD); + ident->SetVariable(syntheticVariable); + checker::ETSFunctionType *funcType = + checker->CreateETSMethodType(methodDef->Id()->Name(), {{}, checker->Allocator()->Adapter()}); + funcType->AddCallSignature(signature); + syntheticVariable->SetTsType(funcType); + + return callExpression; +} + } // namespace ark::es2panda::compiler diff --git a/ets2panda/compiler/lowering/util.h b/ets2panda/compiler/lowering/util.h index 8f5202f4aa..f0519b36a3 100644 --- a/ets2panda/compiler/lowering/util.h +++ b/ets2panda/compiler/lowering/util.h @@ -57,6 +57,8 @@ parser::Program *SearchExternalProgramInImport(const parser::Program::DirectExte bool IsAnonymousClassType(const checker::Type *type); bool ClassDefinitionIsEnumTransformed(const ir::AstNode *node); + +ir::CallExpression *TransformOverloadMethodCall(checker::ETSChecker *checker, ir::CallExpression *callExpression); } // namespace ark::es2panda::compiler #endif // ES2PANDA_COMPILER_LOWERING_UTIL_H diff --git a/ets2panda/test/runtime/ets/overload_declaration/dollar_get_1.ets b/ets2panda/test/runtime/ets/overload_declaration/dollar_get_1.ets new file mode 100644 index 0000000000..b3148d5084 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/dollar_get_1.ets @@ -0,0 +1,32 @@ +/* + * 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. + */ + +class A { + $_get1(x: number): int { + return x.toInt(); + } + + $_get2(x: string): string { + return x; + } + + overload $_get { $_get1, $_get2 } +} + +let a = new A(); + +arktest.assertEQ(a[1], 1) +arktest.assertEQ(a["abc"], "abc") + diff --git a/ets2panda/test/runtime/ets/overload_declaration/dollar_set_1.ets b/ets2panda/test/runtime/ets/overload_declaration/dollar_set_1.ets new file mode 100644 index 0000000000..9f38023357 --- /dev/null +++ b/ets2panda/test/runtime/ets/overload_declaration/dollar_set_1.ets @@ -0,0 +1,39 @@ +/* + * 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. + */ + +let s = "abc" +class A { + $_set1(idx: int, val: number) { + s = "$_set1 " + idx.toString() + " " + val.toString(); + } + + $_set2(idx: int, val: string) { + s = "$_set2 " + idx.toString() + " " + val; + } + + overload $_set {$_set1, $_set2} +} + +let a = new A(); + + +a[1] = 1234 +const result1 = "$_set1 1 1234" +arktest.assertEQ(s, result1) + +a[2] = "aaa" +const result2 = "$_set2 2 aaa" +arktest.assertEQ(s, result2) + -- Gitee From 43997647237c3c04cc874af6510fcdc4d2e4356d Mon Sep 17 00:00:00 2001 From: zengzengran Date: Fri, 27 Jun 2025 09:24:13 +0800 Subject: [PATCH 3/3] fix same name --- ets2panda/checker/ETSAnalyzer.cpp | 26 ++++++ ets2panda/checker/ets/object.cpp | 7 +- ets2panda/checker/ets/typeCheckingHelpers.cpp | 19 +++- ets2panda/checker/types/ets/etsObjectType.cpp | 90 +++++++++++++------ ets2panda/checker/types/ets/etsObjectType.h | 7 +- .../lowering/scopesInit/scopesInitPhase.cpp | 66 +++++++------- .../lowering/scopesInit/scopesInitPhase.h | 4 +- .../compiler/ets/first_match/same_name.ets | 32 +++++++ .../runtime/ets/first_match/same_name.ets | 31 +++++++ .../runtime/ets/first_match/same_name2.ets | 35 ++++++++ .../runtime/ets/first_match/same_name3.ets | 29 ++++++ .../runtime/ets/first_match/same_name4.ets | 41 +++++++++ ets2panda/util/diagnostic/semantic.yaml | 6 +- 13 files changed, 319 insertions(+), 74 deletions(-) create mode 100644 ets2panda/test/ast/compiler/ets/first_match/same_name.ets create mode 100644 ets2panda/test/runtime/ets/first_match/same_name.ets create mode 100644 ets2panda/test/runtime/ets/first_match/same_name2.ets create mode 100644 ets2panda/test/runtime/ets/first_match/same_name3.ets create mode 100644 ets2panda/test/runtime/ets/first_match/same_name4.ets diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index d2febf0224..5af176889c 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -342,6 +342,31 @@ static void CheckDuplicationInOverloadDeclaration(ETSChecker *const checker, ir: } } +static void CheckOverloadSameNameMethod(ETSChecker *const checker, ir::OverloadDeclaration *const overloadDecl) +{ + Type *objectType = overloadDecl->Parent()->IsClassDefinition() + ? overloadDecl->Parent()->AsClassDefinition()->TsType() + : overloadDecl->Parent()->Parent()->AsTSInterfaceDeclaration()->TsType(); + ES2PANDA_ASSERT(objectType->IsETSObjectType()); + + PropertySearchFlags searchFlags = overloadDecl->IsStatic() ? PropertySearchFlags::SEARCH_STATIC_METHOD + : PropertySearchFlags::SEARCH_INSTANCE_METHOD; + auto *sameNameMethod = objectType->AsETSObjectType()->GetProperty(overloadDecl->Id()->Name(), searchFlags); + if (sameNameMethod == nullptr) { + return; + } + + auto serachName = overloadDecl->Id()->Name().Mutf8(); + auto hasSameNameMethod = + std::find_if(overloadDecl->OverloadedList().begin(), overloadDecl->OverloadedList().end(), + [serachName](ir::Expression *overloadId) { + return overloadId->IsIdentifier() && overloadId->AsIdentifier()->Name().Is(serachName); + }); + if (hasSameNameMethod == overloadDecl->OverloadedList().end()) { + checker->LogError(diagnostic::OVERLOAD_SAME_NAME_METHOD, {serachName}, overloadDecl->Start()); + } +} + checker::Type *ETSAnalyzer::Check(ir::OverloadDeclaration *node) const { ETSChecker *checker = GetETSChecker(); @@ -349,6 +374,7 @@ checker::Type *ETSAnalyzer::Check(ir::OverloadDeclaration *node) const ES2PANDA_ASSERT(node->Key()); CheckDuplicationInOverloadDeclaration(checker, node); + CheckOverloadSameNameMethod(checker,node); if (!node->Key()->IsIdentifier()) { checker->LogError(diagnostic::OVERLOAD_NAME_MUST_BE_IDENTIFIER, {}, node->Key()->Start()); diff --git a/ets2panda/checker/ets/object.cpp b/ets2panda/checker/ets/object.cpp index 2a283129c7..884176cd95 100644 --- a/ets2panda/checker/ets/object.cpp +++ b/ets2panda/checker/ets/object.cpp @@ -84,11 +84,16 @@ static bool CheckGetterSetterDecl(varbinder::LocalVariable const *child, varbind static bool CheckOverloadDecl(varbinder::LocalVariable *child, varbinder::LocalVariable *parent) { - if (!child->Declaration()->Node()->IsOverloadDeclaration() || + if (!child->Declaration()->Node()->IsOverloadDeclaration() && !parent->Declaration()->Node()->IsOverloadDeclaration()) { return false; } + if (!child->Declaration()->Node()->IsOverloadDeclaration() || + !parent->Declaration()->Node()->IsOverloadDeclaration()) { + return true; + } + auto *childOverload = child->Declaration()->Node()->AsOverloadDeclaration(); auto *parentOverload = parent->Declaration()->Node()->AsOverloadDeclaration(); for (auto *baseMethodName : parentOverload->OverloadedList()) { diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index 7fae85b785..fe648df51b 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -1774,9 +1774,22 @@ void ETSChecker::CheckInterfaceMethodOverloadDeclaration(ETSChecker *checker, ir } ir::Identifier *ident = overloadedName->AsIdentifier(); - // SUPPRESS_CSA_NEXTLINE(alpha.core.AllocatorETSCheckerHint) - Type *identType = checker->ResolveIdentifier(ident); - ident->SetTsType(identType); + Type *interfaceType = node->Parent()->Parent()->AsTSInterfaceDeclaration()->TsType(); + ES2PANDA_ASSERT(interfaceType->IsETSObjectType()); + + PropertySearchFlags searchFlags = PropertySearchFlags::SEARCH_METHOD | PropertySearchFlags::SEARCH_IN_BASE | + PropertySearchFlags::SEARCH_IN_INTERFACES | PropertySearchFlags::IS_GETTER; + auto *variable = + checker->ResolveOverloadReference(ident->AsIdentifier(), interfaceType->AsETSObjectType(), searchFlags); + if (variable == nullptr) { + checker->LogError(diagnostic::OVERLOADED_NAME_MUST_FUNCTION, {}, ident->Start()); + ident->SetTsType(checker->GlobalTypeError()); + continue; + } + + ident->SetTsType(variable->TsType()); + ident->SetVariable(variable); + if (!CheckOverloadedName(checker, node, overloadedName)) { continue; } diff --git a/ets2panda/checker/types/ets/etsObjectType.cpp b/ets2panda/checker/types/ets/etsObjectType.cpp index 2a920a8376..aafdbde20c 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -220,15 +220,48 @@ static void UpdateDeclarationForGetterSetter(varbinder::LocalVariable *res, cons res->Reset(decl, var->Flags()); } +static PropertySearchFlags UpdateOverloadDeclarationSearchFlags(const PropertySearchFlags &flags) +{ + PropertySearchFlags SyntheticFlags = flags; + if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) != 0) { + SyntheticFlags &= ~PropertySearchFlags::SEARCH_INSTANCE_METHOD; + SyntheticFlags |= PropertySearchFlags::SEARCH_INSTANCE_DECL; + } + if ((flags & PropertySearchFlags::SEARCH_STATIC_METHOD) != 0) { + SyntheticFlags &= ~PropertySearchFlags::SEARCH_STATIC_METHOD; + SyntheticFlags |= PropertySearchFlags::SEARCH_STATIC_DECL; + } + return SyntheticFlags; +} + +static PropertySearchFlags UpdateMethodSearchFlags(const PropertySearchFlags &flags) +{ + PropertySearchFlags SyntheticFlags = flags; + if ((flags & PropertySearchFlags::SEARCH_INSTANCE_DECL) != 0) { + SyntheticFlags &= ~PropertySearchFlags::SEARCH_INSTANCE_DECL; + SyntheticFlags |= PropertySearchFlags::SEARCH_INSTANCE_METHOD; + } + if ((flags & PropertySearchFlags::SEARCH_STATIC_DECL) != 0) { + SyntheticFlags &= ~PropertySearchFlags::SEARCH_STATIC_DECL; + SyntheticFlags |= PropertySearchFlags::SEARCH_STATIC_METHOD; + } + return SyntheticFlags; +} + varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(const util::StringView &name, PropertySearchFlags flags) const { std::vector signatures; // Since both "first match" and "best match" exist at present, overloadDeclarationCall is temporarily used. After // "best match" removed, this marking needs to be removed. - bool overloadDeclarationCall = false; + auto *overloadDeclaration = SearchFieldsDecls(name, (flags & PropertySearchFlags::SEARCH_STATIC) != 0 + ? PropertySearchFlags::SEARCH_STATIC_DECL + : PropertySearchFlags::SEARCH_INSTANCE_DECL); + bool overloadDeclarationCall = overloadDeclaration != nullptr; + PropertySearchFlags SyntheticFlags = overloadDeclarationCall ? UpdateOverloadDeclarationSearchFlags(flags) : flags; + varbinder::LocalVariable *functionalInterface = - CollectSignaturesForSyntheticType(signatures, name, flags, overloadDeclarationCall); + CollectSignaturesForSyntheticType(signatures, name, SyntheticFlags); // #22952: the called function *always* returns nullptr ES2PANDA_ASSERT(functionalInterface == nullptr); (void)functionalInterface; @@ -286,6 +319,11 @@ bool ETSObjectType::ReplaceArgumentInSignature(std::vector &signatu void ETSObjectType::AddSignatureFromFunction(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, varbinder::LocalVariable *found) const { + if (found == nullptr || found->TsType()->IsTypeError()) { + return; + } + + ES2PANDA_ASSERT(found->TsType()->IsETSFunctionType()); for (auto *it : found->TsType()->AsETSFunctionType()->CallSignatures()) { if (std::find(signatures.begin(), signatures.end(), it) != signatures.end()) { continue; @@ -301,15 +339,19 @@ void ETSObjectType::AddSignatureFromFunction(std::vector &signature } void ETSObjectType::AddSignatureFromOverload(std::vector &signatures, PropertySearchFlags flags, - varbinder::LocalVariable *found, bool &overloadDeclarationCall) const + varbinder::LocalVariable *found) const { + if (found == nullptr || !found->HasFlag(varbinder::VariableFlags::OVERLOAD)) { + return; + } + + ES2PANDA_ASSERT(found->Declaration()->Node()->IsOverloadDeclaration()); auto *overloadDeclaration = found->Declaration()->Node()->AsOverloadDeclaration(); std::vector methodSignature; if (overloadDeclaration->Id()->IsErrorPlaceHolder()) { return; } - overloadDeclarationCall |= true; if (overloadDeclaration->IsConstructorOverloadDeclaration()) { return AddSignatureFromConstructor(signatures, found); } @@ -319,7 +361,7 @@ void ETSObjectType::AddSignatureFromOverload(std::vector &signature methodSignature.clear(); util::StringView methodName = method->IsIdentifier() ? method->AsIdentifier()->Name() : method->AsTSQualifiedName()->Right()->Name(); - CollectSignaturesForSyntheticType(methodSignature, methodName, flags, overloadDeclarationCall); + CollectSignaturesForSyntheticType(methodSignature, methodName, UpdateMethodSearchFlags(flags)); if (!methodSignature.empty()) { signatures.emplace_back(methodSignature.front()); } @@ -346,48 +388,44 @@ void ETSObjectType::AddSignatureFromConstructor(std::vector &signat } } -void ETSObjectType::AddSignature(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, - varbinder::LocalVariable *found, bool &overloadDeclarationCall) const -{ - if (found != nullptr && found->HasFlag(varbinder::VariableFlags::OVERLOAD)) { - if (!found->Declaration()->Node()->IsOverloadDeclaration()) { - return; - } - AddSignatureFromOverload(signatures, flags, found, overloadDeclarationCall); - } else if (found != nullptr && !found->TsType()->IsTypeError()) { - ES2PANDA_ASSERT(found->TsType()->IsETSFunctionType()); - AddSignatureFromFunction(signatures, flags, checker, found); - } -} - varbinder::LocalVariable *ETSObjectType::CollectSignaturesForSyntheticType(std::vector &signatures, const util::StringView &name, - PropertySearchFlags flags, - bool &overloadDeclarationCall) const + PropertySearchFlags flags) const { auto *checker = GetRelation()->GetChecker()->AsETSChecker(); if ((flags & PropertySearchFlags::SEARCH_STATIC_METHOD) != 0) { auto *found = GetOwnProperty(name); - AddSignature(signatures, flags, checker, found, overloadDeclarationCall); + AddSignatureFromFunction(signatures, flags, checker, found); } if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) != 0) { auto *found = GetOwnProperty(name); - AddSignature(signatures, flags, checker, found, overloadDeclarationCall); + AddSignatureFromFunction(signatures, flags, checker, found); + } + + if ((flags & PropertySearchFlags::SEARCH_STATIC_DECL) != 0) { + auto *found = GetOwnProperty(name); + AddSignatureFromOverload(signatures, flags, found); + } + + if ((flags & PropertySearchFlags::SEARCH_INSTANCE_DECL) != 0) { + auto *found = GetOwnProperty(name); + AddSignatureFromOverload(signatures, flags, found); } - if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) == 0) { + if ((flags & PropertySearchFlags::SEARCH_INSTANCE_METHOD) == 0 && + (flags & PropertySearchFlags::SEARCH_INSTANCE_DECL) == 0) { return nullptr; } if (superType_ != nullptr && ((flags & PropertySearchFlags::SEARCH_IN_BASE) != 0)) { - superType_->CollectSignaturesForSyntheticType(signatures, name, flags, overloadDeclarationCall); + superType_->CollectSignaturesForSyntheticType(signatures, name, flags); } if ((flags & PropertySearchFlags::SEARCH_IN_INTERFACES) != 0) { for (auto *interface : Interfaces()) { - interface->CollectSignaturesForSyntheticType(signatures, name, flags, overloadDeclarationCall); + interface->CollectSignaturesForSyntheticType(signatures, name, flags); } } diff --git a/ets2panda/checker/types/ets/etsObjectType.h b/ets2panda/checker/types/ets/etsObjectType.h index a56cf8fd0e..bb25487855 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -346,14 +346,11 @@ public: varbinder::LocalVariable *CreateSyntheticVarFromEverySignature(const util::StringView &name, PropertySearchFlags flags) const; varbinder::LocalVariable *CollectSignaturesForSyntheticType(std::vector &signatures, - const util::StringView &name, PropertySearchFlags flags, - bool &overloadDeclarationCall) const; - void AddSignature(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, - varbinder::LocalVariable *found, bool &overloadDeclarationCall) const; + const util::StringView &name, PropertySearchFlags flags) const; void AddSignatureFromFunction(std::vector &signatures, PropertySearchFlags flags, ETSChecker *checker, varbinder::LocalVariable *found) const; void AddSignatureFromOverload(std::vector &signatures, PropertySearchFlags flags, - varbinder::LocalVariable *found, bool &overloadDeclarationCall) const; + varbinder::LocalVariable *found) const; void AddSignatureFromConstructor(std::vector &signatures, varbinder::LocalVariable *found) const; bool ReplaceArgumentInSignature(std::vector &signatures, Signature *sigToInsert, TypeRelation *relation) const; diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index c5a51475ae..e1207963e0 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -1050,75 +1050,69 @@ void InitScopesPhaseETS::MaybeAddOverload(ir::MethodDefinition *method, ir::Iden void InitScopesPhaseETS::VisitOverloadDeclaration(ir::OverloadDeclaration *overload) { - auto *curScope = VarBinder()->GetScope(); + auto *const clsScope = VarBinder()->GetScope()->AsClassScope(); const auto overloadName = overload->Id(); - auto res = - curScope->Find(overloadName->Name(), overload->IsStatic() ? varbinder::ResolveBindingOptions::ALL_STATIC - : varbinder::ResolveBindingOptions::ALL_NON_STATIC); - if (res.variable != nullptr) { - VarBinder()->ThrowRedeclaration(overloadName->Start(), res.name, varbinder::DeclType::METHOD); - } + auto options = + (overload->IsStatic() || overload->IsConstructorOverloadDeclaration()) + ? varbinder::ResolveBindingOptions::STATIC_VARIABLES | varbinder::ResolveBindingOptions::STATIC_DECLARATION + : varbinder::ResolveBindingOptions::VARIABLES | varbinder::ResolveBindingOptions::DECLARATION; - auto result = curScope->FindLocal(overloadName->Name(), varbinder::ResolveBindingOptions::ALL_DECLARATION); - if (result != nullptr) { - VarBinder()->ThrowLocalRedeclaration(overloadName->Start(), result->Name()); + auto variable = clsScope->FindLocal(overloadName->Name(), options); + if (variable != nullptr) { + VarBinder()->ThrowRedeclaration(overloadName->Start(), overloadName->Name(), variable->Declaration()->Type()); } Iterate(overload); DeclareClassOverload(overload); } -varbinder::LocalScope *InitScopesPhaseETS::OverloadTargetScope(ir::OverloadDeclaration *overloadDef, +varbinder::LocalScope *InitScopesPhaseETS::OverloadTargetScope(ir::OverloadDeclaration *overloaddecl, varbinder::ClassScope *clsScope) { varbinder::LocalScope *targetScope {}; - if (overloadDef->IsConstructorOverloadDeclaration()) { - targetScope = clsScope->StaticMethodScope(); + if (overloaddecl->IsConstructorOverloadDeclaration()) { + targetScope = clsScope->StaticDeclScope(); - auto *found = targetScope->FindLocal(Signatures::CONSTRUCTOR_NAME, varbinder::ResolveBindingOptions::BINDINGS); + auto *found = clsScope->StaticMethodScope()->FindLocal(Signatures::CONSTRUCTOR_NAME, + varbinder::ResolveBindingOptions::BINDINGS); if (found == nullptr || - (!overloadDef->OverloadedList().empty() && overloadDef->OverloadedList().front()->IsIdentifier() && - overloadDef->OverloadedList().front()->AsIdentifier()->Name().Is(Signatures::CONSTRUCTOR_NAME))) { + (!overloaddecl->OverloadedList().empty() && overloaddecl->OverloadedList().front()->IsIdentifier() && + overloaddecl->OverloadedList().front()->AsIdentifier()->Name().Is(Signatures::CONSTRUCTOR_NAME))) { return targetScope; } ir::Identifier *anonyConstructor = Allocator()->New(Signatures::CONSTRUCTOR_NAME, Allocator()); - overloadDef->PushFront(anonyConstructor); - anonyConstructor->SetParent(overloadDef); + overloaddecl->PushFront(anonyConstructor); + anonyConstructor->SetParent(overloaddecl); } else { - targetScope = overloadDef->IsStatic() ? clsScope->StaticMethodScope() : clsScope->InstanceMethodScope(); + targetScope = overloaddecl->IsStatic() ? clsScope->StaticDeclScope() : clsScope->InstanceDeclScope(); } return targetScope; } -void InitScopesPhaseETS::DeclareClassOverload(ir::OverloadDeclaration *overloadDef) +void InitScopesPhaseETS::DeclareClassOverload(ir::OverloadDeclaration *overloaddecl) { ES2PANDA_ASSERT(VarBinder()->GetScope()->IsClassScope()); - const auto overloadName = overloadDef->Id(); + const auto overloadName = overloaddecl->Id(); auto *const clsScope = VarBinder()->GetScope()->AsClassScope(); - auto options = - overloadDef->IsStatic() - ? varbinder::ResolveBindingOptions::STATIC_VARIABLES | varbinder::ResolveBindingOptions::STATIC_DECLARATION - : varbinder::ResolveBindingOptions::VARIABLES | varbinder::ResolveBindingOptions::DECLARATION; - auto variable = clsScope->FindLocal(overloadName->Name(), options); - if (variable != nullptr) { - VarBinder()->ThrowRedeclaration(overloadName->Start(), overloadName->Name(), variable->Declaration()->Type()); - } - varbinder::LocalScope *targetScope = OverloadTargetScope(overloadDef, clsScope); - for (auto *methodName : overloadDef->OverloadedList()) { + varbinder::LocalScope *targetScope = OverloadTargetScope(overloaddecl, clsScope); + varbinder::LocalScope *serachMethodScope = + (overloaddecl->IsStatic() || overloaddecl->IsConstructorOverloadDeclaration()) + ? clsScope->StaticMethodScope() + : clsScope->InstanceMethodScope(); + + for (auto *methodName : overloaddecl->OverloadedList()) { if (!methodName->IsIdentifier()) { continue; } - auto *found = - targetScope->FindLocal(methodName->AsIdentifier()->Name(), varbinder::ResolveBindingOptions::BINDINGS); - + auto *found = serachMethodScope->FindLocal(methodName->AsIdentifier()->Name(), + varbinder::ResolveBindingOptions::BINDINGS); if (found == nullptr) { continue; } - if (!found->Declaration()->Node()->IsMethodDefinition()) { VarBinder()->ThrowError(methodName->Start(), diagnostic::OVERLOADED_NAME_MUST_FUNCTION); continue; @@ -1129,7 +1123,7 @@ void InitScopesPhaseETS::DeclareClassOverload(ir::OverloadDeclaration *overloadD auto classCtx = varbinder::LexicalScope::Enter(VarBinder(), targetScope); auto var = std::get<1>(VarBinder()->NewVarDecl(overloadName->Start(), Allocator(), - overloadName->Name(), overloadDef)); + overloadName->Name(), overloaddecl)); var->SetScope(clsScope); if (targetScope->HasFlag(varbinder::ScopeFlags::STATIC)) { var->AddFlag(varbinder::VariableFlags::STATIC); diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h index 75f98406d4..47799937df 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.h @@ -344,8 +344,8 @@ private: void DeclareClassMethod(ir::MethodDefinition *method); void MaybeAddOverload(ir::MethodDefinition *method, ir::Identifier *methodName, varbinder::Variable *found, varbinder::ClassScope *clsScope, varbinder::LocalScope *targetScope); - void DeclareClassOverload(ir::OverloadDeclaration *overloadDef); - varbinder::LocalScope *OverloadTargetScope(ir::OverloadDeclaration *overloadDef, varbinder::ClassScope *clsScope); + void DeclareClassOverload(ir::OverloadDeclaration *overloaddecl); + varbinder::LocalScope *OverloadTargetScope(ir::OverloadDeclaration *overloaddecl, varbinder::ClassScope *clsScope); void VisitClassStaticBlock(ir::ClassStaticBlock *staticBlock) override; void VisitBlockExpression(ir::BlockExpression *blockExpr) override; diff --git a/ets2panda/test/ast/compiler/ets/first_match/same_name.ets b/ets2panda/test/ast/compiler/ets/first_match/same_name.ets new file mode 100644 index 0000000000..eb374bd8f0 --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/same_name.ets @@ -0,0 +1,32 @@ +/* + * 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. + */ + +class C{ + foo(n:number){} + fooString(n:string){} + fooBoolean(n:boolean){} + + overload foo{foo,fooString,fooBoolean} +} + +class D{ + foo(n:number){} + fooString(n:string){} + fooBoolean(n:boolean){} + + overload foo{fooString,fooBoolean} +} + +/* @@? 29:5 Error SyntaxError: Overload declaration must list same name method 'foo'. */ diff --git a/ets2panda/test/runtime/ets/first_match/same_name.ets b/ets2panda/test/runtime/ets/first_match/same_name.ets new file mode 100644 index 0000000000..4d66912346 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/same_name.ets @@ -0,0 +1,31 @@ +/* + * 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. + */ + +class C{ + foo(a:number):void{console.log("invoke1")} +} + +class D extends C{ + fooString(a:string):void{console.log("invoke2")} + overload foo{foo,fooString}; +} + +function main(){ + let d = new D(); + let c:C = d; + d.foo(1); + d.foo("abc"); + c.foo(1); +} diff --git a/ets2panda/test/runtime/ets/first_match/same_name2.ets b/ets2panda/test/runtime/ets/first_match/same_name2.ets new file mode 100644 index 0000000000..22d2b94b36 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/same_name2.ets @@ -0,0 +1,35 @@ +/* + * 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. + */ + +class C{ + foo(a:number):void{console.log("invoke1")} +} + +class D extends C{ + foo(a:number):void{console.log("invoke2")} + fooString(a:string):void{console.log("invoke3")} + overload foo{foo,fooString}; +} + +function main(){ + let d = new D(); + let c:C = d; + d.foo(1); + d.foo("abc"); + c.foo(1); + + let c2 = new C(); + c2.foo(1) +} diff --git a/ets2panda/test/runtime/ets/first_match/same_name3.ets b/ets2panda/test/runtime/ets/first_match/same_name3.ets new file mode 100644 index 0000000000..083217ded5 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/same_name3.ets @@ -0,0 +1,29 @@ +/* + * 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. + */ + +class C{ + foo(n:number):void{console.log("invoke1")} +} + +class D extends C{ + fooString(n:string):void{console.log("invole2")} + overload foo{foo,fooString} +} + +function main(){ + let d = new D(); + d.foo(1) + d.foo("abc") +} diff --git a/ets2panda/test/runtime/ets/first_match/same_name4.ets b/ets2panda/test/runtime/ets/first_match/same_name4.ets new file mode 100644 index 0000000000..b12e143b4a --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/same_name4.ets @@ -0,0 +1,41 @@ +/* + * 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. + */ + + +interface I{ + foo(a:number):void{console.log("invoke1")} +} + +interface J extends I{ + fooString(a:string):void + overload foo{foo,fooString} +} + +class C implements I{ + foo(a:number):void{console.log("invoke2")} + fooString(a:string):void{console.log("invoke3")} + overload foo{foo,fooString} +} + +function foo(param:J){ + param.foo(1); + param.foo("abc") +} + +function main(){ + let c = new C(); + c.foo(1); + c.foo("abc"); +} diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 903ca5e740..fa24d634dc 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -1553,4 +1553,8 @@ semantic: - name: OVERLOAD_MODIFIERS_ABSTRACT id: 392 - message: "overload declaration cannot contain abstract methods." + message: "Overload declaration cannot contain abstract methods." + +- name: OVERLOAD_SAME_NAME_METHOD + id: 393 + message: "Overload declaration must list same name method '{}'." -- Gitee