diff --git a/ets2panda/checker/ETSAnalyzerHelpers.cpp b/ets2panda/checker/ETSAnalyzerHelpers.cpp index 79bccc53d1c0b0f6654d8be8c9d07e7cbbbac367..9e9aa36592d00bae94ac92856490c063a59fae2c 100644 --- a/ets2panda/checker/ETSAnalyzerHelpers.cpp +++ b/ets2panda/checker/ETSAnalyzerHelpers.cpp @@ -18,6 +18,24 @@ namespace ark::es2panda::checker { +static bool IsValidReceiverParameter(Type *const thisType) +{ + if (thisType == nullptr) { + return false; + } + + if (thisType->IsETSArrayType() || thisType->IsETSTypeParameter()) { + return true; + } + + if (!thisType->IsETSObjectType()) { + return false; + } + + auto *const thisObjectType = thisType->AsETSObjectType(); + return thisObjectType->HasObjectFlag(ETSObjectFlags::CLASS | ETSObjectFlags::INTERFACE); +} + void CheckExtensionIsShadowedInCurrentClassOrInterface(checker::ETSChecker *checker, checker::ETSObjectType *objType, ir::ScriptFunction *extensionFunc, checker::Signature *signature) { @@ -118,14 +136,11 @@ void CheckExtensionMethod(checker::ETSChecker *checker, ir::ScriptFunction *exte auto *const thisType = !extensionFunc->Signature()->Params().empty() ? extensionFunc->Signature()->Params()[0]->TsType() : nullptr; - // "Extension Functions" are only allowed for classes, interfaces, and arrays. - if (thisType != nullptr && - (thisType->IsETSArrayType() || - (thisType->IsETSObjectType() && thisType->AsETSObjectType()->HasObjectFlag( - // CC-OFFNXT(G.FMT.06-CPP) project code style - checker::ETSObjectFlags::CLASS | checker::ETSObjectFlags::INTERFACE)))) { + // "Extension Functions" are only allowed for classes, interfaces, arrays and type parameters extends from object. + if (IsValidReceiverParameter(thisType)) { // Skip for arrays (array does not contain a class definition) and checked class definition. - if (!thisType->IsETSArrayType() && thisType->Variable()->Declaration()->Node()->IsClassDefinition() && + if (!thisType->IsETSArrayType() && !thisType->IsETSTypeParameter() && + thisType->Variable()->Declaration()->Node()->IsClassDefinition() && !thisType->Variable()->Declaration()->Node()->AsClassDefinition()->IsClassDefinitionChecked()) { thisType->Variable()->Declaration()->Node()->Check(checker); } diff --git a/ets2panda/test/runtime/ets/extension_function_with_generic/receiver_type_is_type_parameter1.sts b/ets2panda/test/runtime/ets/extension_function_with_generic/receiver_type_is_type_parameter1.sts new file mode 100644 index 0000000000000000000000000000000000000000..50a78ac81a9c3b64a97ee44bbae61ede7884c207 --- /dev/null +++ b/ets2panda/test/runtime/ets/extension_function_with_generic/receiver_type_is_type_parameter1.sts @@ -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 { + prop: number = 1 +} + +function foo(this: T) { + return this.prop +} + +function demo(p1: A) { + return p1.foo() +} + +function main() { + let a1 = new A() + assertTrue(demo(a1) == 1) +} \ No newline at end of file diff --git a/ets2panda/test/runtime/ets/extension_function_with_generic/receiver_type_is_type_parameter2.sts b/ets2panda/test/runtime/ets/extension_function_with_generic/receiver_type_is_type_parameter2.sts new file mode 100644 index 0000000000000000000000000000000000000000..0f4f00557af46a5c0bedb0b1d412c27c7f982736 --- /dev/null +++ b/ets2panda/test/runtime/ets/extension_function_with_generic/receiver_type_is_type_parameter2.sts @@ -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. + */ + +interface A { + name: string +} + +function foo(this: T) { + return 1 +} + +function demo(p1: A) { + assertTrue(p1.foo() == 1) +} \ No newline at end of file