diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index f4fc39afe2cbbbfa87ae49415e1b620b75fec8d2..2974d4837ab88b71e6f86bfe1c4e7025f4df0356 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -327,6 +327,32 @@ 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()->Check(checker) + : overloadDecl->Parent()->Parent()->AsTSInterfaceDeclaration()->Check(checker); + ES2PANDA_ASSERT(objectType->IsETSObjectType()); + + PropertySearchFlags searchFlags = PropertySearchFlags::DISALLOW_SYNTHETIC_METHOD_CREATION | + (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(); @@ -334,34 +360,25 @@ checker::Type *ETSAnalyzer::Check(ir::OverloadDeclaration *node) const ES2PANDA_ASSERT(node->Key()); CheckDuplicationInOverloadDeclaration(checker, node); + CheckOverloadSameNameMethod(checker, node); if (node->IsConstructorOverloadDeclaration()) { ES2PANDA_ASSERT(node->Parent()->IsClassDefinition()); checker->CheckConstructorOverloadDeclaration(checker, node); - return nullptr; - } - - if (node->IsFunctionOverloadDeclaration()) { + } else if (node->IsFunctionOverloadDeclaration()) { ES2PANDA_ASSERT( node->Parent()->IsClassDefinition() && (compiler::HasGlobalClassParent(node) || node->Parent()->AsClassDefinition()->IsNamespaceTransformed())); checker->CheckFunctionOverloadDeclaration(checker, node); - return nullptr; - } - - if (node->IsClassMethodOverloadDeclaration()) { + } else if (node->IsClassMethodOverloadDeclaration()) { ES2PANDA_ASSERT(node->Parent()->IsClassDefinition()); checker->CheckClassMethodOverloadDeclaration(checker, node); - return nullptr; - } - - if (node->IsInterfaceMethodOverloadDeclaration()) { + } else if (node->IsInterfaceMethodOverloadDeclaration()) { ES2PANDA_ASSERT(node->Parent()->Parent()->IsTSInterfaceDeclaration()); checker->CheckInterfaceMethodOverloadDeclaration(checker, node); - return nullptr; } - return nullptr; + return checker->CreateSyntheticTypeFromOverload(node->Id()->Variable()); } checker::Type *ETSAnalyzer::Check([[maybe_unused]] ir::Property *expr) const @@ -1624,6 +1641,25 @@ checker::Type *ETSAnalyzer::GetCallExpressionReturnType(ir::CallExpression *expr // NOTE(vpukhov): #14902 substituted signature is not updated } +static void CheckOverloadCall(ETSChecker *checker, ir::CallExpression *expr) +{ + if (!expr->Callee()->IsMemberExpression() || !OverloadDeclaration(expr->Callee())) { + return; + } + + auto *sig = expr->Signature(); + auto *functionNode = sig->OwnerVar()->Declaration()->Node(); + ir::AstNode *parent = functionNode->Parent(); + + bool isExported = functionNode->IsExported() || functionNode->IsDefaultExported(); + if (parent != nullptr && parent->IsClassDefinition() && parent->AsClassDefinition()->IsNamespaceTransformed() && + !parent->AsClassDefinition()->IsDeclare() && !isExported) { + checker->LogError(diagnostic::NOT_EXPORTED, + {sig->OwnerVar()->Declaration()->Name(), parent->AsClassDefinition()->Ident()->Name()}, + expr->Start()); + } +} + checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const { ETSChecker *checker = GetETSChecker(); @@ -1674,6 +1710,7 @@ checker::Type *ETSAnalyzer::Check(ir::CallExpression *expr) const return expr->TsType(); } + CheckOverloadCall(checker, expr); CheckVoidTypeExpression(checker, expr); CheckAbstractCall(checker, expr); return expr->TsType(); diff --git a/ets2panda/checker/ETSchecker.h b/ets2panda/checker/ETSchecker.h index 738c24b8aae73349d53fddff33082fef1c8cf324..d27cf96faa3f0628ccc6b076f3179333d1f937c9 100644 --- a/ets2panda/checker/ETSchecker.h +++ b/ets2panda/checker/ETSchecker.h @@ -907,6 +907,7 @@ public: void LogUnresolvedReferenceError(ir::Identifier *ident); void WrongContextErrorClassifyByType(ir::Identifier *ident); + Type *CreateSyntheticTypeFromOverload(varbinder::Variable *const var); void CreateOverloadSigContainer(Signature *overloadHelperSig) { @@ -1018,7 +1019,6 @@ private: PropertySearchFlags GetSearchFlags(const ir::MemberExpression *memberExpr, const varbinder::Variable *targetRef); PropertySearchFlags GetInitialSearchFlags(const ir::MemberExpression *memberExpr); Type *GetTypeOfSetterGetter([[maybe_unused]] varbinder::Variable *var); - Type *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/ets/function.cpp b/ets2panda/checker/ets/function.cpp index 53741e08a368c58d95d14380066221ed3084c3d6..44b4e29a22d724720b2bfc03a4337f07eeacc67a 100644 --- a/ets2panda/checker/ets/function.cpp +++ b/ets2panda/checker/ets/function.cpp @@ -1388,8 +1388,7 @@ Signature *ETSChecker::ResolveCallExpressionAndTrailingLambda(ArenaVector &arguments, const lexer::SourcePosition &pos) { - auto *var = type->GetProperty(compiler::Signatures::CONSTRUCTOR_OVERLOAD_DEFINITION_NAME, - PropertySearchFlags::SEARCH_STATIC_METHOD); + auto *var = type->GetProperty(compiler::Signatures::CONSTRUCTOR_NAME, PropertySearchFlags::SEARCH_STATIC_METHOD); if (var != nullptr && var->TsType()->IsETSFunctionType()) { return MatchOrderSignatures(var->TsType()->AsETSFunctionType()->CallSignatures(), nullptr, arguments, pos, TypeRelationFlag::NONE); diff --git a/ets2panda/checker/ets/helpers.cpp b/ets2panda/checker/ets/helpers.cpp index d7eb47097e04a64ef0fdde55a514c51c1444f146..bf9c6c2c56219190165b6ee9e0a46968961690db 100644 --- a/ets2panda/checker/ets/helpers.cpp +++ b/ets2panda/checker/ets/helpers.cpp @@ -325,10 +325,6 @@ 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 f53671473d9603dc92b6f435f40a9bde29a9cbfe..e88dc37f377a4878c695a4bb06ad6d332d445cbb 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()) { @@ -1876,7 +1881,7 @@ void ETSChecker::ValidateNamespaceProperty(varbinder::Variable *property, const { ir::AstNode *parent = nullptr; if (property->TsType() != nullptr && !property->TsType()->IsTypeError()) { - if (property->TsType()->IsETSMethodType()) { + if (property->TsType()->IsETSMethodType() && !property->HasFlag(varbinder::VariableFlags::OVERLOAD)) { auto funcType = property->TsType()->AsETSFunctionType(); property = funcType->CallSignatures()[0]->OwnerVar(); ES2PANDA_ASSERT(property != nullptr); diff --git a/ets2panda/checker/ets/typeCheckingHelpers.cpp b/ets2panda/checker/ets/typeCheckingHelpers.cpp index bd526d218ded7c4dd18060506b552657d7582dc1..52897f93bebbb4ffd78adf28e824aaa9764f3004 100644 --- a/ets2panda/checker/ets/typeCheckingHelpers.cpp +++ b/ets2panda/checker/ets/typeCheckingHelpers.cpp @@ -492,10 +492,11 @@ Type *ETSChecker::CreateSyntheticTypeFromOverload(varbinder::Variable *const var for (auto *overloadFunction : overloadDeclaration->OverloadedList()) { Type *functionType = overloadFunction->Check(this); - if (!functionType->IsETSFunctionType()) { - var->SetTsType(GlobalTypeError()); - return GlobalTypeError(); + if (functionType->IsTypeError()) { + overloadDeclaration->SetTsType(GetGlobalTypesHolder()->GlobalTypeError()); + return GetGlobalTypesHolder()->GlobalTypeError(); } + ES2PANDA_ASSERT(functionType->IsETSFunctionType()); auto *signature = functionType->AsETSFunctionType()->CallSignatures().front(); if (std::find(signatures.begin(), signatures.end(), signature) != signatures.end()) { continue; @@ -507,6 +508,9 @@ Type *ETSChecker::CreateSyntheticTypeFromOverload(varbinder::Variable *const var syntheticFunctionType->AddCallSignature(s); } + syntheticFunctionType->SetVariable(var); + var->SetTsType(syntheticFunctionType); + overloadDeclaration->SetTsType(syntheticFunctionType); return syntheticFunctionType; } @@ -689,6 +693,7 @@ Type *ETSChecker::GuaranteedTypeForUncheckedPropertyAccess(varbinder::Variable * case ir::AstNodeType::METHOD_DEFINITION: case ir::AstNodeType::CLASS_DEFINITION: return GetTypeOfVariable(prop); + case ir::AstNodeType::OVERLOAD_DECLARATION: case ir::AstNodeType::TS_ENUM_DECLARATION: return nullptr; default: @@ -1671,11 +1676,6 @@ static bool CheckAccessModifierForOverloadDeclaration(ETSChecker *const checker, const ir::ModifierFlags &overloadedMethodFlags, const lexer::SourcePosition &pos) { - if ((overloadedMethodFlags & (ir::ModifierFlags::ABSTRACT)) != 0) { - checker->LogError(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; @@ -1686,11 +1686,6 @@ static bool CheckAccessModifierForOverloadDeclaration(ETSChecker *const checker, 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; } @@ -1759,6 +1754,11 @@ void ETSChecker::CheckFunctionOverloadDeclaration(ETSChecker *checker, ir::Overl void ETSChecker::CheckClassMethodOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const { + PropertySearchFlags searchFlags = + PropertySearchFlags::SEARCH_IN_BASE | PropertySearchFlags::SEARCH_IN_INTERFACES | + PropertySearchFlags::IS_GETTER | PropertySearchFlags::IGNORE_OVERLOAD | + (node->IsStatic() ? PropertySearchFlags::SEARCH_STATIC_METHOD : PropertySearchFlags::SEARCH_INSTANCE_METHOD); + for (auto *overloadedName : node->OverloadedList()) { if (!overloadedName->IsIdentifier()) { overloadedName->SetTsType(checker->GlobalTypeError()); @@ -1769,10 +1769,15 @@ void ETSChecker::CheckClassMethodOverloadDeclaration(ETSChecker *checker, ir::Ov 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->ResolveOverloadReference(ident->AsIdentifier(), classType->AsETSObjectType(), + searchFlags | PropertySearchFlags::SEARCH_METHOD) != nullptr) { + checker->LogError(diagnostic::OVERLOAD_SAME_ACCESS_MODIFIERS_STATIC_ASYNC, {}, ident->Start()); + continue; + } if (variable == nullptr) { checker->LogError(diagnostic::OVERLOADED_NAME_MUST_FUNCTION, {}, ident->Start()); ident->SetTsType(checker->GlobalTypeError()); @@ -1790,6 +1795,10 @@ void ETSChecker::CheckClassMethodOverloadDeclaration(ETSChecker *checker, ir::Ov void ETSChecker::CheckInterfaceMethodOverloadDeclaration(ETSChecker *checker, ir::OverloadDeclaration *node) const { + PropertySearchFlags searchFlags = + PropertySearchFlags::SEARCH_IN_BASE | PropertySearchFlags::SEARCH_IN_INTERFACES | + PropertySearchFlags::IS_GETTER | PropertySearchFlags::IGNORE_OVERLOAD | + (node->IsStatic() ? PropertySearchFlags::SEARCH_STATIC_METHOD : PropertySearchFlags::SEARCH_INSTANCE_METHOD); for (auto *overloadedName : node->OverloadedList()) { if (!overloadedName->IsIdentifier()) { overloadedName->SetTsType(checker->GlobalTypeError()); @@ -1797,9 +1806,26 @@ 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()); + auto *variable = + checker->ResolveOverloadReference(ident->AsIdentifier(), interfaceType->AsETSObjectType(), searchFlags); + + if (variable == nullptr && + checker->ResolveOverloadReference(ident->AsIdentifier(), interfaceType->AsETSObjectType(), + searchFlags | PropertySearchFlags::SEARCH_METHOD) != nullptr) { + checker->LogError(diagnostic::OVERLOAD_SAME_ACCESS_MODIFIERS_STATIC_ASYNC, {}, ident->Start()); + continue; + } + 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 177a0c679a909e84d1e36a2aff4228362d92df78..ebca1b901cbae2ac7679e86607c71a64d59e8c0f 100644 --- a/ets2panda/checker/types/ets/etsObjectType.cpp +++ b/ets2panda/checker/types/ets/etsObjectType.cpp @@ -211,15 +211,51 @@ static void UpdateDeclarationForGetterSetter(varbinder::LocalVariable *res, cons res->Reset(decl, var->Flags()); } +static PropertySearchFlags UpdateOverloadDeclarationSearchFlags(const PropertySearchFlags &flags) +{ + if ((flags & PropertySearchFlags::IGNORE_OVERLOAD) != 0) { + return 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) +{ + if ((flags & PropertySearchFlags::IGNORE_OVERLOAD) != 0) { + return 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; - varbinder::LocalVariable *functionalInterface = - CollectSignaturesForSyntheticType(signatures, name, flags, overloadDeclarationCall); + auto *overloadDeclaration = SearchFieldsDecls(name, UpdateOverloadDeclarationSearchFlags(flags)); + bool overloadDeclarationCall = overloadDeclaration != nullptr; + PropertySearchFlags syntheticFlags = overloadDeclarationCall ? UpdateOverloadDeclarationSearchFlags(flags) : flags; + + varbinder::LocalVariable *functionalInterface = CollectSignaturesForSyntheticType(signatures, name, syntheticFlags); // #22952: the called function *always* returns nullptr ES2PANDA_ASSERT(functionalInterface == nullptr); (void)functionalInterface; @@ -243,6 +279,10 @@ varbinder::LocalVariable *ETSObjectType::CreateSyntheticVarFromEverySignature(co res->SetTsType(funcType); funcType->SetVariable(res); + if (overloadDeclarationCall) { + res->Reset(overloadDeclaration->Declaration(), res->Flags()); + } + UpdateDeclarationForGetterSetter(res, funcType, flags); return res; @@ -279,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; @@ -294,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); } @@ -312,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()); } @@ -339,48 +388,43 @@ 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_METHOD) == 0 && (flags & PropertySearchFlags::SEARCH_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 2f81c4be7c98481b663be75eb3c0a94a6bb28383..bb5d8dc1f327a68c1c02fd4b7facdd8ff4f2caa4 100644 --- a/ets2panda/checker/types/ets/etsObjectType.h +++ b/ets2panda/checker/types/ets/etsObjectType.h @@ -348,14 +348,12 @@ 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/checker/types/ets/etsObjectTypeConstants.h b/ets2panda/checker/types/ets/etsObjectTypeConstants.h index 007a89a06d9b3bb70caddc99126922e721d91a30..4392ca7dbd53dfb40073cc0e9904eb7d79306df3 100644 --- a/ets2panda/checker/types/ets/etsObjectTypeConstants.h +++ b/ets2panda/checker/types/ets/etsObjectTypeConstants.h @@ -100,6 +100,7 @@ enum class PropertySearchFlags : std::uint32_t { DISALLOW_SYNTHETIC_METHOD_CREATION = 1U << 10U, IS_SETTER = 1U << 11U, IS_GETTER = 1U << 12U, + IGNORE_OVERLOAD = 1U << 13U, SEARCH_INSTANCE = SEARCH_INSTANCE_FIELD | SEARCH_INSTANCE_METHOD | SEARCH_INSTANCE_DECL, SEARCH_STATIC = SEARCH_STATIC_FIELD | SEARCH_STATIC_METHOD | SEARCH_STATIC_DECL, diff --git a/ets2panda/compiler/lowering/phase.cpp b/ets2panda/compiler/lowering/phase.cpp index bc06d4dca05f3330a9e819c17f7670afad16f645..4dd62cd22f43e0431bce0cac6462659346fa8501 100644 --- a/ets2panda/compiler/lowering/phase.cpp +++ b/ets2panda/compiler/lowering/phase.cpp @@ -135,7 +135,6 @@ std::vector GetETSPhaseList() new AnnotationCopyPostLowering, new AsyncMethodLowering, new DeclareOverloadLowering, - new OverloadMappingLowering, new EnumPostCheckLoweringPhase, new SpreadConstructionPhase, new RestArgsLowering, @@ -149,6 +148,7 @@ std::vector GetETSPhaseList() new RecordLowering, new ObjectIndexLowering, new ObjectIteratorLowering, + new OverloadMappingLowering, new LambdaConversionPhase, new UnionLowering, new ExpandBracketsPhase, diff --git a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp index 94db1887d7a1c843dd3d7155e8df1401b3c4a36c..120bb9dc25c0147c872db890418a45b3e3794a79 100644 --- a/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp +++ b/ets2panda/compiler/lowering/scopesInit/scopesInitPhase.cpp @@ -1057,75 +1057,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; @@ -1136,7 +1130,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 75f98406d4f832a901e3e902d7bf4d758de11fa2..47799937df0a6e1da0916ffbdab3b1ee38a209a1 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/compiler/scripts/signatures.yaml b/ets2panda/compiler/scripts/signatures.yaml index 15dfcdbfe96bd5c3900cd74d7e3162fbbc665e31..623d21e1f9414f8a71b6ce90acbf654cb97f7aec 100644 --- a/ets2panda/compiler/scripts/signatures.yaml +++ b/ets2panda/compiler/scripts/signatures.yaml @@ -255,8 +255,6 @@ defines: 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/parser/ETSparserClasses.cpp b/ets2panda/parser/ETSparserClasses.cpp index d930394c1df7ac09878dc5b2bb96bee4ca0a9b0f..43208e7e2d627a218736c4061296cd188dbb4524 100644 --- a/ets2panda/parser/ETSparserClasses.cpp +++ b/ets2panda/parser/ETSparserClasses.cpp @@ -542,8 +542,7 @@ ir::OverloadDeclaration *ETSParser::ParseClassOverloadDeclaration(ir::ModifierFl // 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()); + overloadName = AllocNode(compiler::Signatures::CONSTRUCTOR_NAME, Allocator()); modifiers |= ir::ModifierFlags::CONSTRUCTOR; Lexer()->NextToken(); } else { diff --git a/ets2panda/test/ast/compiler/ets/first_match/abstract_method.ets b/ets2panda/test/ast/compiler/ets/first_match/abstract_method.ets index c79e3ffb023ffe70e2e8944f0721c25e29113bad..2178322e65317b0220380a30f75519977a86a9a3 100644 --- a/ets2panda/test/ast/compiler/ets/first_match/abstract_method.ets +++ b/ets2panda/test/ast/compiler/ets/first_match/abstract_method.ets @@ -16,8 +16,5 @@ abstract class Base { abstract fooNumber(a: number): string; abstract fooString(a: string): string; - overload foo {/* @@ label1 */fooNumber,/* @@ label2 */fooString } + overload foo {fooNumber,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 index 46cd5f3a1508f0b19bc235a02ab5c147a3500717..4b2ca22d2237ede77d490dff5c8ca604fd5bbfb4 100644 --- a/ets2panda/test/ast/compiler/ets/first_match/access_modifiers.ets +++ b/ets2panda/test/ast/compiler/ets/first_match/access_modifiers.ets @@ -29,7 +29,7 @@ class Base { class Sub extends Base { bar() { - /* @@ label1 */this.foo("abc"); + /* @@ label */this.foo(/* @@ label1 */"abc"); this.foo(1); this.foo(true); } @@ -42,8 +42,10 @@ function main() { 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") */ +/* @@@ label Error TypeError: Signature fooPrivate(x: String): void is not visible here. */ +/* @@@ label Error TypeError: No matching call signature for fooPrivate("abc") */ +/* @@@ label1 Error TypeError: Type '"abc"' is not compatible with type 'Double' at index 1 */ +/* @@@ label1 Error TypeError: Type '"abc"' is not compatible with type 'Boolean' at index 1 */ /* @@@ 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. */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/invalid_identifier.ets b/ets2panda/test/ast/compiler/ets/first_match/invalid_identifier.ets index ae4fa8c99034df45a516c1c07df188bfc069a50c..597ad29e1a5d28de16e8d6f818b30dbc7bc1b145 100644 --- a/ets2panda/test/ast/compiler/ets/first_match/invalid_identifier.ets +++ b/ets2panda/test/ast/compiler/ets/first_match/invalid_identifier.ets @@ -32,12 +32,12 @@ function main(){ /* @@? 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:25 Error SyntaxError: Field type annotation expected. */ /* @@? 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:35 Error SyntaxError: Field type annotation expected. */ /* @@? 21:36 Error SyntaxError: Unexpected token '{'. */ /* @@? 22:20 Error SyntaxError: Unexpected token, expected '{'. */ /* @@? 22:20 Error SyntaxError: Unexpected token, expected an identifier. */ @@ -49,4 +49,3 @@ function main(){ /* @@? 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 index ab6be8fcab6e4ee1f5380ca84e87f214399db112..9e6faafbe0955c7fe3ed9eeb4ce616870c9db287 100644 --- a/ets2panda/test/ast/compiler/ets/first_match/invalid_paramter.ets +++ b/ets2panda/test/ast/compiler/ets/first_match/invalid_paramter.ets @@ -35,6 +35,3 @@ function main() { /* @@? 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_static.ets b/ets2panda/test/ast/compiler/ets/first_match/modifier_static.ets index 216411ca48f5cc376a44c73b54b209a23cd02a59..28ab388f03bf34d17247229e6183ef07e8f07fa6 100644 --- a/ets2panda/test/ast/compiler/ets/first_match/modifier_static.ets +++ b/ets2panda/test/ast/compiler/ets/first_match/modifier_static.ets @@ -26,4 +26,6 @@ class Base2 { } /* @@@ label1 Error TypeError: Overload alias and overloaded method name must have exactly the same modifiers (static, async). */ +/* @@@ label1 Error TypeError: Static property 'fooNumber' must be accessed through it's class 'Base1' */ /* @@@ label2 Error TypeError: Overload alias and overloaded method name must have exactly the same modifiers (static, async). */ +/* @@@ label2 Error TypeError: Property 'fooString' must be accessed through 'this' */ diff --git a/ets2panda/test/ast/compiler/ets/first_match/namespace.ets b/ets2panda/test/ast/compiler/ets/first_match/namespace.ets new file mode 100644 index 0000000000000000000000000000000000000000..562555e43fd2f058a7686cb22849741a9e8b7c6c --- /dev/null +++ b/ets2panda/test/ast/compiler/ets/first_match/namespace.ets @@ -0,0 +1,72 @@ +/* + * 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 { + function foo1(a: number) { + console.log("invoke foo1"); + } + + function foo2(a: string) { + console.log("invoke foo2"); + } + + export overload overloadfoo{ foo1, foo2 } + + export function foo3(a: number) { + console.log("invoke foo1"); + } + + function foo4(a: string) { + console.log("invoke foo2"); + } + + export overload overloadfoo2{ foo3, foo4 } + + export function foo5(a: number) { + console.log("invoke foo1"); + } + + function foo6(a: string) { + console.log("invoke foo2"); + } + + overload overloadfoo3{ foo5, foo6 } +} + +function main(){ + NS.foo1(1); + NS.foo2("abc"); + NS.foo3(1); + NS.foo4("abc"); + + NS.overloadfoo(1); + NS.overloadfoo("abc"); + + NS.overloadfoo2(1); + NS.overloadfoo2("abc"); + + NS.overloadfoo3(1); + NS.overloadfoo3("abc"); +} + +/* @@? 49:8 Error TypeError: 'foo1' is not exported in 'NS' */ +/* @@? 50:8 Error TypeError: 'foo2' is not exported in 'NS' */ +/* @@? 52:8 Error TypeError: 'foo4' is not exported in 'NS' */ +/* @@? 54:5 Error TypeError: 'foo1' is not exported in 'NS' */ +/* @@? 55:5 Error TypeError: 'foo2' is not exported in 'NS' */ +/* @@? 58:5 Error TypeError: 'foo4' is not exported in 'NS' */ +/* @@? 60:8 Error TypeError: 'overloadfoo3' is not exported in 'NS' */ +/* @@? 61:5 Error TypeError: 'foo6' is not exported in 'NS' */ +/* @@? 61:8 Error TypeError: 'overloadfoo3' is not exported in 'NS' */ 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 0000000000000000000000000000000000000000..22a1f98fa777f615d63f25ca9ba53a77e5afcc65 --- /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 TypeError: Method with the same name as overload declaration 'foo', overloadlist must list this medhod. */ 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 index 95eddfc644cd08ca50e6576711bb5a441f58b58e..d5a1d45da91831f60376e7d0956a1d2e3f3607a0 100644 --- 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 @@ -16,11 +16,10 @@ class Base { foo/* @@ label1 */(a: number) : string foo(a: string) : string - overload /* @@ label2 */foo {/* @@ label3 */foo, /* @@ label4 */foo} + overload foo {/* @@ label2 */foo, /* @@ label3 */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. */ +/* @@@ label2 Error TypeError: The overloaded name 'foo' can't refer to a function with overload signatures. */ +/* @@@ label3 Error TypeError: Duplicate overloaded method. */ +/* @@@ label3 Error TypeError: The overloaded name 'foo' can't refer to a function with overload signatures. */ 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 index b5511a3f9e899f24cd54486d6aab6534793f1eb8..1510e3ff407d418b93f7ffe436fd07df66385cfd 100644 --- a/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_method_exported.ets +++ b/ets2panda/test/ast/compiler/ets/overload/overload_overloaded_method_exported.ets @@ -15,6 +15,4 @@ 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. */ +export overload foo {foo1, foo2} 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 index 19db7f31f9cfe295d39ea17eac7873be5ec35d34..79401623d249b1af4deaf68041bac458edf77bdf 100644 --- 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 @@ -13,15 +13,9 @@ * 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/runtime/ets/first_match/dollar_get.ets b/ets2panda/test/runtime/ets/first_match/dollar_get.ets new file mode 100644 index 0000000000000000000000000000000000000000..a8bede5ffedf1d13a808b7741ce35ffd61e751c5 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/dollar_get.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 { + $_get1(x: number): int { + return x.toInt(); + } + + $_get2(x: string): string { + return x; + } + + overload $_get { $_get1, $_get2 } +} + +function main() { + let a = new A(); + + arktest.assertEQ(a[1], 1) + arktest.assertEQ(a["abc"], "abc") +} diff --git a/ets2panda/test/runtime/ets/first_match/dollar_get2.ets b/ets2panda/test/runtime/ets/first_match/dollar_get2.ets new file mode 100644 index 0000000000000000000000000000000000000000..ed148522cdb36d020f14ce8a56954c6917df8bd6 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/dollar_get2.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 { + $_get(x: number): int { + return x.toInt(); + } + + $_get2(x: string): string { + return x; + } + + overload $_get { $_get, $_get2 } +} + +class B { + $_get1(x: number): int { + return x.toInt(); + } + + $_get(x: string): string { + return x; + } + + overload $_get { $_get1, $_get } +} + +function main() { + let a = new A(); + let b = new B(); + + arktest.assertEQ(a[1], 1) + arktest.assertEQ(a["abc"], "abc") + arktest.assertEQ(b[1], 1) + arktest.assertEQ(b["abc"], "abc") +} diff --git a/ets2panda/test/runtime/ets/first_match/dollar_invoke.ets b/ets2panda/test/runtime/ets/first_match/dollar_invoke.ets new file mode 100644 index 0000000000000000000000000000000000000000..dab6e3cecbb31cd6540c8f6baebcfd63d432aff3 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/dollar_invoke.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 A { + static overload $_invoke{ $_invoke1, $_invoke2 } + static $_invoke1(a: number) { + return "invoke1" + } + static $_invoke2(a: string) { + return "invoke2" + } +} + +function main(): void { + arktest.assertEQ(A(123), "invoke1") + arktest.assertEQ(A("abc"), "invoke2") +} diff --git a/ets2panda/test/runtime/ets/first_match/dollar_iterator.ets b/ets2panda/test/runtime/ets/first_match/dollar_iterator.ets new file mode 100644 index 0000000000000000000000000000000000000000..d8c5cd75d9ae595be18ca0bbd5dae124eb7d60d8 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/dollar_iterator.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 A { + data: string[] = ['a', 'b', 'c']; + overload $_iterator{$_iterator1} + $_iterator1() { + return new CIterator(this); + } +} + +class CIterator implements Iterator { + index = 0; + base: A; + constructor (base: A) { + this.base = base; + } + next(): IteratorResult { + if (this.index >= this.base.data.length) { + return { + done: true, + value: undefined + } + } + return { + done: this.index >= this.base.data.length, + value: this.base.data[this.index++] + } + } +} + +function main(): void { + let res = ""; + let a = new A(); + for (let x of a) res += x; + arktest.assertEQ(res, "abc") +} diff --git a/ets2panda/test/runtime/ets/first_match/dollar_set.ets b/ets2panda/test/runtime/ets/first_match/dollar_set.ets new file mode 100644 index 0000000000000000000000000000000000000000..3d68b924a9055baa57284effb9ce34592b4938ea --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/dollar_set.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. + */ + +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 } +} + +function main() { + 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) +} diff --git a/ets2panda/test/runtime/ets/first_match/multi_overload.ets b/ets2panda/test/runtime/ets/first_match/multi_overload.ets new file mode 100644 index 0000000000000000000000000000000000000000..c96f49262b0b559e959f6e8bad9ef0beb44681c9 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/multi_overload.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 C { + foo(a: number): string { + return "invoke1"; + } +} + +class D extends C { + fooNumber(a: number): string { + return "invoke2"; + } + fooString(a: string): string { + return "invoke3" + } + overload foo1{ foo, fooString }; + overload foo2{ fooNumber, fooString }; + overload foo3{ foo, fooString }; +} + +function main() { + let test = new D(); + arktest.assertEQ(test.foo1(123), "invoke1") + arktest.assertEQ(test.foo1("abc"), "invoke3") + arktest.assertEQ(test.foo2(123), "invoke2") + arktest.assertEQ(test.foo2("abc"), "invoke3") + arktest.assertEQ(test.foo3(123), "invoke1") + arktest.assertEQ(test.foo3("123"), "invoke3") +} diff --git a/ets2panda/test/runtime/ets/first_match/namespace5.ets b/ets2panda/test/runtime/ets/first_match/namespace5.ets new file mode 100644 index 0000000000000000000000000000000000000000..b7d53c5871ec868758e9abe0f5aba3cafd3d88d3 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/namespace5.ets @@ -0,0 +1,30 @@ +/* + * 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: number) { + return "invoke1"; + } + + function foo2(a: string) { + return "invoke2"; + } + + export overload overloadfoo{ foo1, foo2 } +} + +function main() { + arktest.assertEQ(NS.overloadfoo(1), "invoke1"); +} diff --git a/ets2panda/test/runtime/ets/first_match/native_method.ets b/ets2panda/test/runtime/ets/first_match/native_method.ets new file mode 100644 index 0000000000000000000000000000000000000000..82c3e1e60f32a1606bf931cd3cb5bd9981d2803f --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/native_method.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 { + native foo1(x: number): void; + foo2(x: string) { + return "invoke1" + } + overload foo{ foo1, foo2 } +} + +namespace NS { + native function foo1(x: number): void; + export function foo2(x: string) { + return "invoke2" + } + export overload foo{ foo1, foo2 } +} + +native function foo1(x: number): void; +function foo2(x: string) { + return "invoke3" +} +overload foo{ foo1, foo2 } + +function main() { + let a = new A(); + arktest.assertEQ(a.foo("abc"), "invoke1"); + arktest.assertEQ(NS.foo("abc"), "invoke2"); + arktest.assertEQ(foo("abc"), "invoke3"); +} diff --git a/ets2panda/test/runtime/ets/first_match/native_method2.ets b/ets2panda/test/runtime/ets/first_match/native_method2.ets new file mode 100644 index 0000000000000000000000000000000000000000..209333377db30ba92cff887fb531257943fff9c8 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/native_method2.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 { + native foo1(x: number): void; + foo2(x: string) { + return "invoke1" + } + native foo3(): void; + foo4(x: boolean) { + return "invoke2" + } + overload foo{ foo1, foo2, foo3, foo4 } +} + + +function main() { + let a = new A(); + arktest.assertEQ(a.foo("abc"), "invoke1"); + arktest.assertEQ(a.foo(true), "invoke2"); +} 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 0000000000000000000000000000000000000000..aa31e6940d158bb176c6dbe9c227e0b026cd7189 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/same_name.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): string { + return "invoke1"; + } +} + +class D extends C { + fooString(a: string): string { + return "invoke2" + } + overload foo{ foo, fooString }; +} + +function main() { + let d = new D(); + let c: C = d; + arktest.assertEQ(d.foo(1), "invoke1") + arktest.assertEQ(d.foo("abc"), "invoke2") + arktest.assertEQ(c.foo(1), "invoke1") +} 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 0000000000000000000000000000000000000000..891f6b7cf9bc2f46748d232fcd50d3f7173d2f04 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/same_name2.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 C { + foo(a: number) { + return "invoke1" + } +} + +class D extends C { + foo(a: number) { + return "invoke2" + } + fooString(a: string) { + return "invoke3" + } + overload foo{ foo, fooString }; +} + +function main() { + let d = new D(); + let c: C = d; + arktest.assertEQ(d.foo(1), "invoke2"); + arktest.assertEQ(d.foo("abc"), "invoke3"); + arktest.assertEQ(c.foo(1), "invoke2"); + + let c2 = new C(); + arktest.assertEQ(c2.foo(1), "invoke1"); +} 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 0000000000000000000000000000000000000000..68171d5863bb16b3d80b690f6af32b772219e67b --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/same_name3.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 C { + foo(n: number) { + return "invoke1" + } +} + +class D extends C { + fooString(n: string) { + return "invoke2" + } + overload foo{ foo, fooString } +} + +function main() { + let d = new D(); + arktest.assertEQ(d.foo(1), "invoke1") + arktest.assertEQ(d.foo("abc"), "invoke2") +} 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 0000000000000000000000000000000000000000..7f386a73ec14cbada176a066d3fa148716189433 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/same_name4.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. + */ + +interface I { + foo(a: number){ + return "invoke1" +} +} + +interface J extends I { + fooString(a: string): string + overload foo{ foo, fooString } +} + +class C implements I { + foo(a: number) { + return "invoke2" + } + fooString(a: string) { + return "invoke3" + } + overload foo{ foo, fooString } +} + +function foo(param: J) { + param.foo(1); + param.foo("abc") +} + +function main() { + let c = new C(); + arktest.assertEQ(c.foo(1), "invoke2"); + arktest.assertEQ(c.foo("abc"), "invoke3"); +} diff --git a/ets2panda/test/runtime/ets/first_match/static_same_name.ets b/ets2panda/test/runtime/ets/first_match/static_same_name.ets new file mode 100644 index 0000000000000000000000000000000000000000..f30f9206b6998cba2acb32322d3ee520079ac35e --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/static_same_name.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 C { + static foo111(a: number): string { + return "static invoke1"; + } +} + +class D extends C { + static fooString(a: string): string { + return "static invoke2" + } + static overload foo111{ foo111, fooString }; +} + +function main() { + arktest.assertEQ(D.foo111(1), "static invoke1") + arktest.assertEQ(D.foo111("abc"), "static invoke2") + arktest.assertEQ(C.foo111(1), "static invoke1") +} diff --git a/ets2panda/test/runtime/ets/first_match/static_same_name2.ets b/ets2panda/test/runtime/ets/first_match/static_same_name2.ets new file mode 100644 index 0000000000000000000000000000000000000000..e192514d6ffa5c1074310c499362aa91fa1583e7 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/static_same_name2.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 C { + static foo(a: number) { + return "static invoke1" + } +} + +class D extends C { + static foo(a: number) { + return "static invoke2" + } + static fooString(a: string) { + return "static invoke3" + } + static overload foo{ foo, fooString }; +} + +function main() { + arktest.assertEQ(D.foo(1), "static invoke2"); + arktest.assertEQ(D.foo("abc"), "static invoke3"); + arktest.assertEQ(C.foo(1), "static invoke1"); +} diff --git a/ets2panda/test/runtime/ets/first_match/static_same_name3.ets b/ets2panda/test/runtime/ets/first_match/static_same_name3.ets new file mode 100644 index 0000000000000000000000000000000000000000..d895c48afe2ee3b28f42affb7c328ae7c35527a7 --- /dev/null +++ b/ets2panda/test/runtime/ets/first_match/static_same_name3.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 { + static foo(n: number) { + return "static invoke1" + } +} + +class D extends C { + static fooString(n: string) { + return "static invoke2" + } + static overload foo{ foo, fooString } +} + +function main() { + arktest.assertEQ(D.foo(1), "static invoke1"); + arktest.assertEQ(D.foo("abc"), "static invoke2"); +} diff --git a/ets2panda/util/diagnostic/semantic.yaml b/ets2panda/util/diagnostic/semantic.yaml index 4912fbec17903d28fc79828c7370fd4ffdfc5cfd..6e0ff93cc77c2040bd153b5daa93493d70ab3a99 100644 --- a/ets2panda/util/diagnostic/semantic.yaml +++ b/ets2panda/util/diagnostic/semantic.yaml @@ -1143,10 +1143,6 @@ semantic: id: 391 message: "Overload declaration cannot be called by union." -- name: OVERLOAD_MODIFIERS_ABSTRACT - id: 392 - message: "overload declaration cannot contain abstract methods." - - 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." @@ -1163,6 +1159,10 @@ semantic: id: 387 message: "Overload alias and overloaded method name must have exactly the same modifiers (static, async)." +- name: OVERLOAD_SAME_NAME_METHOD + id: 397 + message: "Method with the same name as overload declaration '{}', overloadlist must list this medhod." + - name: OVERRIDE_DOESNT_OVERRIDE id: 136 message: "Method {}{} in {} not overriding any method" @@ -1587,6 +1587,7 @@ semantic: id: 347 message: "Wrong operand type for unary expression" + graveyard: - 8 - 29 diff --git a/ets2panda/varbinder/ETSBinder.cpp b/ets2panda/varbinder/ETSBinder.cpp index ff783ab4364579225a9b8a5dc79ab89975be4002..d9cb8a738b58cf826eb18c5ba84b4faf0ce3071d 100644 --- a/ets2panda/varbinder/ETSBinder.cpp +++ b/ets2panda/varbinder/ETSBinder.cpp @@ -743,6 +743,11 @@ Variable *ETSBinder::FindImportSpecifiersVariable(const util::StringView &import if (foundVar != staticMethodBindings.end()) { return foundVar->second; } + const auto &staticDeclBindings = records[0]->GlobalClassScope()->StaticDeclScope()->Bindings(); + foundVar = staticDeclBindings.find(imported); + if (foundVar != staticDeclBindings.end()) { + return foundVar->second; + } bool found = false; for (auto res : records) { const auto &staticFieldBindings = res->GlobalClassScope()->StaticFieldScope()->Bindings();