From 0296837203de291e4a0cd8f73496c0f04532353b Mon Sep 17 00:00:00 2001 From: xingshunxiang Date: Wed, 23 Jul 2025 17:28:42 +0800 Subject: [PATCH] tmp Signed-off-by: xingshunxiang --- ets2panda/checker/ETSAnalyzer.cpp | 4 +- ets2panda/compiler/lowering/util.cpp | 46 ++++++ ets2panda/compiler/lowering/util.h | 1 + ets2panda/public/es2panda_lib.cpp | 10 ++ ets2panda/public/es2panda_lib.h | 1 + ets2panda/public/es2panda_lib.idl.erb | 1 + ets2panda/test/unit/plugin/CMakeLists.txt | 1 + ...state_check_recheck_create_opaque_type.cpp | 152 ++++++++++++++++++ 8 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 ets2panda/test/unit/plugin/plugin_proceed_to_state_check_recheck_create_opaque_type.cpp diff --git a/ets2panda/checker/ETSAnalyzer.cpp b/ets2panda/checker/ETSAnalyzer.cpp index 74631ae976..937b599668 100644 --- a/ets2panda/checker/ETSAnalyzer.cpp +++ b/ets2panda/checker/ETSAnalyzer.cpp @@ -111,7 +111,6 @@ checker::Type *ETSAnalyzer::Check(ir::ClassProperty *st) const } ES2PANDA_ASSERT(st->Id()->Variable() != nullptr); - checker->CheckAnnotations(st->Annotations()); if (st->TypeAnnotation() != nullptr) { st->TypeAnnotation()->Check(checker); @@ -130,6 +129,9 @@ checker::Type *ETSAnalyzer::Check(ir::ClassProperty *st) const propertyType = propertyType != nullptr ? propertyType : checker->GlobalTypeError(); st->SetTsType(propertyType); + if (st->Id()->Name().Is("c") || st->Id()->Name().Is("d")) { + std::cout << "xsx" << std::endl; + } if (st->IsDefinite() && st->TsType()->PossiblyETSNullish()) { checker->LogError(diagnostic::LATE_INITIALIZATION_FIELD_HAS_INVALID_TYPE, st->TypeAnnotation()->Start()); } diff --git a/ets2panda/compiler/lowering/util.cpp b/ets2panda/compiler/lowering/util.cpp index bed24872a8..9e5628dd40 100644 --- a/ets2panda/compiler/lowering/util.cpp +++ b/ets2panda/compiler/lowering/util.cpp @@ -337,6 +337,52 @@ ir::AstNode *DeclarationFromIdentifier(const ir::Identifier *node) return decl->Node(); } +using UAlloc = util::NodeAllocator; +static ir::TypeNode *CreateTypeNodeFromETSObjectType(ThreadSafeArenaAllocator *allocator, + const checker::ETSObjectType *tsType) +{ + ir::TSTypeParameterInstantiation *typeParam = nullptr; + if (!tsType->TypeArguments().empty()) { + ArenaVector typeNodes(allocator->Adapter()); + for (auto const *tp : tsType->AsETSObjectType()->TypeArguments()) { + typeNodes.emplace_back(CreateTypeNodeFromTsType(allocator, tp)); + } + typeParam = UAlloc::ForceSetParent(allocator, std::move(typeNodes)); + } + + auto typeName = tsType->AsETSObjectType()->Name(); + auto typeId = UAlloc::ForceSetParent(allocator, typeName, allocator); + auto typeRefPart = + UAlloc::ForceSetParent(allocator, typeId, typeParam, nullptr, allocator); + return UAlloc::ForceSetParent(allocator, typeRefPart, allocator); +} + +static ir::TypeNode *CreateTypeNodeFromETSFunctionType(ThreadSafeArenaAllocator *allocator, + const checker::ETSFunctionType *tsType) +{ + + return nullptr; +} + +ir::TypeNode *CreateTypeNodeFromTsType(ThreadSafeArenaAllocator *allocator, const checker::Type *tsType) +{ + if (tsType == nullptr) { + std::cout << "[[xsx stub]]: null tsType input!" << std::endl; + return nullptr; + } + + if (tsType->IsETSObjectType()) { + return CreateTypeNodeFromETSObjectType(allocator, tsType->AsETSObjectType()); + } + + if (tsType->IsETSFunctionType()) { + return CreateTypeNodeFromETSFunctionType(allocator, tsType->AsETSFunctionType()); + } + + std::cout << "[[xsx stub]]: such a type is in implementation" << std::endl; + return nullptr; +} + // NOTE: used to get the license string from the input root node. util::StringView GetLicenseFromRootNode(const ir::AstNode *node) { diff --git a/ets2panda/compiler/lowering/util.h b/ets2panda/compiler/lowering/util.h index 4e84d94298..02650fd5d7 100644 --- a/ets2panda/compiler/lowering/util.h +++ b/ets2panda/compiler/lowering/util.h @@ -43,6 +43,7 @@ void Recheck(PhaseManager *phaseManager, varbinder::ETSBinder *varBinder, checke // NOTE: used to get the declaration from identifier in Plugin API and LSP ir::AstNode *DeclarationFromIdentifier(const ir::Identifier *node); +ir::TypeNode *CreateTypeNodeFromTsType(ThreadSafeArenaAllocator *allocator, const checker::Type *tsType); // NOTE: used to get the declaration name in Plugin API and LSP std::optional GetNameOfDeclaration(const ir::AstNode *node); // NOTE: used to get the license string from the input root node. diff --git a/ets2panda/public/es2panda_lib.cpp b/ets2panda/public/es2panda_lib.cpp index e8ec8a9a3f..0e1b629631 100644 --- a/ets2panda/public/es2panda_lib.cpp +++ b/ets2panda/public/es2panda_lib.cpp @@ -1124,6 +1124,15 @@ extern "C" bool IsImportTypeKind([[maybe_unused]] es2panda_Context *context, es2 return false; } +extern "C" es2panda_AstNode *CreateTypeNodeFromTsType(es2panda_Context *context, es2panda_Type *tsType) +{ + auto *typeE2p = reinterpret_cast(tsType); + auto *ctx = reinterpret_cast(context); + auto *astNode = compiler::CreateTypeNodeFromTsType(ctx->allocator, typeE2p); + astNode->AddAstNodeFlags(ir::AstNodeFlags::NOCLEANUP); + return reinterpret_cast(astNode); +} + extern "C" char *GetLicenseFromRootNode(es2panda_Context *ctx, es2panda_AstNode *node) { auto E2pNode = reinterpret_cast(node); @@ -1404,6 +1413,7 @@ es2panda_Impl g_impl = { Es2pandaEnumToString, DeclarationFromIdentifier, IsImportTypeKind, + CreateTypeNodeFromTsType, JsdocStringFromDeclaration, GetLicenseFromRootNode, FirstDeclarationByNameFromNode, diff --git a/ets2panda/public/es2panda_lib.h b/ets2panda/public/es2panda_lib.h index 4e287ec06a..20f3bdce31 100644 --- a/ets2panda/public/es2panda_lib.h +++ b/ets2panda/public/es2panda_lib.h @@ -257,6 +257,7 @@ struct CAPI_EXPORT es2panda_Impl { char *(*Es2pandaEnumToString)(es2panda_Context *ctx, Es2pandaEnum id); es2panda_AstNode *(*DeclarationFromIdentifier)(es2panda_Context *ctx, es2panda_AstNode *node); bool (*IsImportTypeKind)(es2panda_Context *ctx, es2panda_AstNode *node); + es2panda_AstNode *(*CreateTypeNodeFromTsType)(es2panda_Context *context, es2panda_Type *tsType); char *(*JsdocStringFromDeclaration)(es2panda_Context *ctx, es2panda_AstNode *node); char *(*GetLicenseFromRootNode)(es2panda_Context *ctx, es2panda_AstNode *node); es2panda_AstNode *(*FirstDeclarationByNameFromNode)(es2panda_Context *ctx, const es2panda_AstNode *node, diff --git a/ets2panda/public/es2panda_lib.idl.erb b/ets2panda/public/es2panda_lib.idl.erb index 88794e5282..adf09a44ff 100644 --- a/ets2panda/public/es2panda_lib.idl.erb +++ b/ets2panda/public/es2panda_lib.idl.erb @@ -218,6 +218,7 @@ interface es2panda_Impl { String Es2pandaEnumToString(es2panda_Context ctx, Es2pandaEnum id); ir.AstNode DeclarationFromIdentifier(es2panda_Context ctx, ir.Identifier node); boolean IsImportTypeKind(es2panda_Context ctx, ir.AstNode node); + ir.AstNode CreateTypeNodeFromTsType(es2panda_Context context, es2panda_Type tsType); String JsdocStringFromDeclaration(es2panda_Context ctx, ir.AstNode node); String GetLicenseFromRootNode(es2panda_Context ctx, ir.AstNode node); ir.AstNode FirstDeclarationByNameFromNode(es2panda_Context ctx, ir.AstNode node, String name); diff --git a/ets2panda/test/unit/plugin/CMakeLists.txt b/ets2panda/test/unit/plugin/CMakeLists.txt index 477c1a61e2..e376aadce1 100644 --- a/ets2panda/test/unit/plugin/CMakeLists.txt +++ b/ets2panda/test/unit/plugin/CMakeLists.txt @@ -107,6 +107,7 @@ set(PLUGIN_TESTS "plugin_proceed_to_state_log_diagnostic_with_suggestion compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "use_plugin_to_test_column_number compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_check_jsdoc compile.ets ${EXPECTED_MODE} cpp ${EXECUTABLE_PLUGIN}" + "plugin_proceed_to_state_check_recheck_create_opaque_type compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_check_recheck_trailinglambda compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_test_global_func_call_dump compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" "plugin_proceed_to_state_test_interface_duplicate_setter compile.ets ${COMPILE_MODE} cpp ${EXECUTABLE_PLUGIN}" diff --git a/ets2panda/test/unit/plugin/plugin_proceed_to_state_check_recheck_create_opaque_type.cpp b/ets2panda/test/unit/plugin/plugin_proceed_to_state_check_recheck_create_opaque_type.cpp new file mode 100644 index 0000000000..a0889a93f2 --- /dev/null +++ b/ets2panda/test/unit/plugin/plugin_proceed_to_state_check_recheck_create_opaque_type.cpp @@ -0,0 +1,152 @@ +/** + * 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 +#include +#include +#include "public/es2panda_lib.h" +#include "util.h" + +// NOLINTBEGIN +static std::string source = R"( +class A {} + +namespace NS { + export class A {} + export namespace MS { + export class B {} + } +} + +function foo(): A { + return new A(); +} + +function goo(): string { + return ""; +} + +function zoo(): NS.MS.B { + return new NS.MS.B(); +} +let a: Array = new Array(); +let b = new Array(); + +function forEach(arr: ()=>Array) {} +forEach(() => {return new Array}) + +//let c: (p1: Number, p2: A) => A = (p1:Number, p2: A):A => {return new A()} +//let d = c +let c: (p1: T1, p2: T2) => void = (p1: T1, p2: T2): void => {} +let d: (p1: number, p2: A) => void = c +)"; + +static es2panda_Impl *impl = nullptr; +es2panda_Context *context = nullptr; +es2panda_AstNode *propA = nullptr; +es2panda_AstNode *propB = nullptr; +es2panda_AstNode *funcCall = nullptr; +es2panda_AstNode *lambdaExpression = nullptr; +es2panda_AstNode *scriptFuncOfLambda = nullptr; + +static void FindTargetAst(es2panda_AstNode *ast, [[maybe_unused]] void *ctx) +{ + if (!impl->IsClassProperty(ast)) { + return; + } + + auto id = impl->ClassElementId(context, ast); + if (id == nullptr) { + return; + } + + auto name = std::string(impl->IdentifierName(context, id)); + if (name == "a") { + propA = ast; + } + + if (name == "b") { + propB = ast; + } +} + +static void FindTargetFunctionCallAst(es2panda_AstNode *ast, [[maybe_unused]] void *ctx) +{ + if (!impl->IsCallExpression(ast)) { + return; + } + + auto callee = impl->CallExpressionCallee(context, ast); + if (callee == nullptr || !impl->IsIdentifier(callee)) { + return; + } + + auto name = std::string(impl->IdentifierName(context, callee)); + if (name != "forEach") { + return; + } + size_t len = 0; + funcCall = ast; + es2panda_AstNode **arguments = impl->CallExpressionArguments(context, funcCall, &len); + lambdaExpression = arguments[0]; +} + +static void FindAndSetTypeAnnotation(es2panda_AstNode *ast, [[maybe_unused]] void *ctx) +{ + impl->AstNodeForEach(ast, FindTargetAst, context); + impl->AstNodeForEach(ast, FindTargetFunctionCallAst, context); + ASSERT(propA != nullptr && propB != nullptr); + auto tsType = impl->TypedTsType(context, propA); + ASSERT(tsType != nullptr); + auto typeAnno = impl->CreateTypeNodeFromTsType(context, tsType); + impl->ClassPropertySetTypeAnnotation(context, propB, typeAnno); + + auto typeAnno2 = impl->CreateTypeNodeFromTsType(context, tsType); + scriptFuncOfLambda = impl->ArrowFunctionExpressionFunction(context, lambdaExpression); + impl->ScriptFunctionSetReturnTypeAnnotation(context, scriptFuncOfLambda, typeAnno2); +} + +int main(int argc, char **argv) +{ + if (argc < MIN_ARGC) { + return INVALID_ARGC_ERROR_CODE; + } + + if (GetImpl() == nullptr) { + return NULLPTR_IMPL_ERROR_CODE; + } + impl = GetImpl(); + + const char **args = const_cast(&(argv[1])); + auto config = impl->CreateConfig(argc - 1, args); + context = impl->CreateContextFromString(config, source.data(), argv[argc - 1]); + if (context == nullptr) { + return NULLPTR_CONTEXT_ERROR_CODE; + } + impl->ProceedToState(context, ES2PANDA_STATE_CHECKED); + CheckForErrors("CHECKED", context); + + auto *program = impl->ContextProgram(context); + es2panda_AstNode *programNode = impl->ProgramAst(context, program); + FindAndSetTypeAnnotation(programNode, context); + + impl->AstNodeRecheck(context, programNode); + CheckForErrors("RECHECKED", context); + + impl->DestroyConfig(config); + return 0; +} + +// NOLINTEND \ No newline at end of file -- Gitee