diff --git a/libabckit/include/libabckit/c/extensions/arkts/metadata_arkts.h b/libabckit/include/libabckit/c/extensions/arkts/metadata_arkts.h index 5d023f0a81f9888d95f3542e1494a9a762f2b7a8..f99dfe4a212cc8de29c780aebb92be39cc2fcb33 100644 --- a/libabckit/include/libabckit/c/extensions/arkts/metadata_arkts.h +++ b/libabckit/include/libabckit/c/extensions/arkts/metadata_arkts.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -885,7 +885,7 @@ struct CAPI_EXPORT AbckitArktsModifyApi { * @param [ in ] name - Name of the class to be created. * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `name` is NULL. */ - AbckitArktsClass *(*createClass)(const char *name); + AbckitArktsClass *(*createClass)(AbckitArktsModule *m, const char *name); /** * @brief Sets owning module for class `klass`. @@ -1010,7 +1010,7 @@ struct CAPI_EXPORT AbckitArktsModifyApi { * @param [ in ] name - Name of the interface to be created. * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `name` is NULL. */ - AbckitArktsInterface *(*createInterface)(const char *name); + AbckitArktsInterface *(*createInterface)(AbckitArktsModule *m, const char *name); /* ======================================== * Enum diff --git a/libabckit/include/libabckit/cpp/headers/arkts/class.h b/libabckit/include/libabckit/cpp/headers/arkts/class.h index c31e6c3c9a10354fd6ab97243db3f00fa2f8aba9..51ee8589e66102cf9d080b90582f9134694a4c58 100644 --- a/libabckit/include/libabckit/cpp/headers/arkts/class.h +++ b/libabckit/include/libabckit/cpp/headers/arkts/class.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -82,6 +82,24 @@ public: */ bool SetName(const std::string &name) const; + /** + * @brief Add field to the class. + * @return `true` on success. + * @param [ in ] field - Field to be added. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if field is false. + */ + bool AddField(const ClassField &field) const; + + /** + * @brief Sets owning module for class. + * @return `true` on success. + * @param [ in ] module - Module to be set. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if module is false. + */ + bool SetOwningModule(const Module &module) const; + /** * @brief Remove annotation from the class declaration. * @param [ in ] anno - Annotation to remove. @@ -103,6 +121,71 @@ public: */ Annotation AddAnnotation(AnnotationInterface ai); + /** + * @brief Adds interface `iface` to the class declaration. + * @return `true` on success. + * @param [ in ] iface - Interface to be added. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is NULL. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `iface` is NULL. + */ + bool AddInterface(arkts::Interface iface); + + /** + * @brief Removes interface `iface` from the class declaration. + * @return `true` on success. + * @param [ in ] iface - Interface to be removed. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is NULL. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `iface` is NULL. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `iface` is not an interface of the class. + */ + bool RemoveInterface(arkts::Interface iface); + + /** + * @brief Set super class `superClass` for the class declaration. + * @return `true` on success. + * @param [ in ] superClass - Super class to be set. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is NULL. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `superClass` is NULL. + */ + bool SetSuperClass(arkts::Class superClass); + + /** + * @brief Creates a new class with name `name`. + * @return The newly created Class object. + * @param [ in ] m - The module in which to create the class. + * @param [ in ] name - The name of the class to create. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `m` is NULL. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `name` is NULL. + */ + static Class CreateClass(Module m, const std::string &name); + + /** + * @brief Remove class field from the class declaration. + * @param [ in ] field - class field to remove. + * @return `true` on success. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if current `Class` is false. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `field` is false. + */ + bool RemoveField(arkts::ClassField field) const; + + /** + * @brief Add function to the class declaration. + * @param [ in ] function - the function is added to the class. + * @return `true` on success. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if current `Class` is false. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `function` is false. + */ + bool AddMethod(arkts::Function function); + + /** + * @brief Removes method `method` from the list of methods for the class declaration. + * @return `true` on success. + * @param [ in ] method - Method to be removed. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is NULL. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `method` is NULL. + */ + bool RemoveMethod(arkts::Function method); + private: /** * @brief Converts class from Core to Arkts target diff --git a/libabckit/include/libabckit/cpp/headers/arkts/class_impl.h b/libabckit/include/libabckit/cpp/headers/arkts/class_impl.h index 9504c218e4ca2fdb4f156efe43acdf905a747044..6fbba3d43082d42027377e8135078eec5036d435 100644 --- a/libabckit/include/libabckit/cpp/headers/arkts/class_impl.h +++ b/libabckit/include/libabckit/cpp/headers/arkts/class_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -16,9 +16,13 @@ #ifndef CPP_ABCKIT_ARKTS_CLASS_IMPL_H #define CPP_ABCKIT_ARKTS_CLASS_IMPL_H -#include "class.h" #include "annotation.h" #include "annotation_interface.h" +#include "class.h" +#include "field.h" +#include "function.h" +#include "interface.h" +#include "module.h" // NOLINTBEGIN(performance-unnecessary-value-param) namespace abckit::arkts { @@ -39,6 +43,34 @@ inline bool Class::SetName(const std::string &name) const return ret; } +inline bool Class::RemoveField(arkts::ClassField field) const +{ + const auto ret = GetApiConfig()->cArktsMapi_->classRemoveField(TargetCast(), field.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Class::AddMethod(arkts::Function function) +{ + const auto ret = GetApiConfig()->cArktsMapi_->classAddMethod(TargetCast(), function.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Class::AddField(const ClassField &field) const +{ + const auto ret = GetApiConfig()->cArktsMapi_->classAddField(TargetCast(), field.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Class::SetOwningModule(const Module &module) const +{ + const auto ret = GetApiConfig()->cArktsMapi_->classSetOwningModule(TargetCast(), module.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + inline Class Class::RemoveAnnotation(arkts::Annotation anno) const { GetApiConfig()->cArktsMapi_->classRemoveAnnotation(TargetCast(), anno.TargetCast()); @@ -60,6 +92,46 @@ inline Annotation Class::AddAnnotation(AnnotationInterface ai) return Annotation(core::Annotation(coreAnno, GetApiConfig(), GetResource())); } +inline bool Class::AddInterface(arkts::Interface iface) +{ + const auto ret = GetApiConfig()->cArktsMapi_->classAddInterface(TargetCast(), iface.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Class::RemoveInterface(arkts::Interface iface) +{ + const auto ret = GetApiConfig()->cArktsMapi_->classRemoveInterface(TargetCast(), iface.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Class::SetSuperClass(arkts::Class superClass) +{ + const auto ret = GetApiConfig()->cArktsMapi_->classSetSuperClass(TargetCast(), superClass.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Class::RemoveMethod(arkts::Function method) +{ + const auto ret = GetApiConfig()->cArktsMapi_->classRemoveMethod(TargetCast(), method.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline Class Class::CreateClass(Module m, const std::string &name) +{ + auto klass = m.GetApiConfig()->cArktsMapi_->createClass(m.TargetCast(), name.c_str()); + CheckError(m.GetApiConfig()); + + auto coreClass = + core::Class(m.GetApiConfig()->cArktsIapi_->arktsClassToCoreClass(klass), m.GetApiConfig(), m.GetResource()); + CheckError(m.GetApiConfig()); + + return Class(coreClass); +} + } // namespace abckit::arkts // NOLINTEND(performance-unnecessary-value-param) diff --git a/libabckit/include/libabckit/cpp/headers/arkts/field.h b/libabckit/include/libabckit/cpp/headers/arkts/field.h index 84a951fd907c11554860f702c1237e3f11ce8981..3ceecb54cd3611bfd659a86abdd69d926c6988ab 100644 --- a/libabckit/include/libabckit/cpp/headers/arkts/field.h +++ b/libabckit/include/libabckit/cpp/headers/arkts/field.h @@ -167,6 +167,8 @@ class ClassField final : public core::ClassField { // We restrict constructors in order to prevent C/C++ API mix-up by user. /// @brief abckit::DefaultHash friend class abckit::DefaultHash; + /// @brief to access private constructor + friend class Class; /// @brief to access private TargetCast friend class abckit::traits::TargetCheckCast; @@ -238,6 +240,8 @@ class InterfaceField final : public core::InterfaceField { friend class abckit::DefaultHash; /// @brief to access private TargetCast friend class abckit::traits::TargetCheckCast; + /// @brief to access private constructor + friend class abckit::arkts::Interface; public: /** diff --git a/libabckit/include/libabckit/cpp/headers/arkts/function.h b/libabckit/include/libabckit/cpp/headers/arkts/function.h index 111e48972deed20f71bef7ffa305640f0a055738..cdc0fc6d4a0fba75977aa5817486585016facbe8 100644 --- a/libabckit/include/libabckit/cpp/headers/arkts/function.h +++ b/libabckit/include/libabckit/cpp/headers/arkts/function.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -30,6 +30,8 @@ class Function final : public core::Function { friend class Class; /// @brief to access private constructor friend class Namespace; + /// @brief to access private constructor + friend class Interface; /// @brief abckit::DefaultHash friend class abckit::DefaultHash; /// @brief to access private TargetCast diff --git a/libabckit/include/libabckit/cpp/headers/arkts/interface.h b/libabckit/include/libabckit/cpp/headers/arkts/interface.h index 8f72ac7a612b7de1d11ffbb0116797f0d868f88c..735f9092e86556431bb121dfef49178fa5e7f1c3 100644 --- a/libabckit/include/libabckit/cpp/headers/arkts/interface.h +++ b/libabckit/include/libabckit/cpp/headers/arkts/interface.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -28,6 +28,8 @@ class Interface final : public core::Interface { // To access private constructor. // We restrict constructors in order to prevent C/C++ API mix-up by user. /// @brief to access private constructor + friend class arkts::Class; + /// @brief to access private constructor friend class Module; /// @brief to access private constructor friend class Namespace; @@ -82,6 +84,76 @@ public: */ bool SetName(const std::string &name) const; + /** + * @brief Remove field for interface + * @return `true` on success. + * @param [ in ] field - Field to be remove. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + */ + bool RemoveField(arkts::InterfaceField field) const; + + /** + * @brief Creates a new Interface with name `name`. + * @return The newly created Interface object. + * @param [ in ] m - The module in which to create the Interface. + * @param [ in ] name - The name of the Interface to create. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `m` is NULL. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if `name` is NULL. + */ + static Interface CreateInterface(Module m, const std::string &name); + + /** + * @brief add field for interface + * @return `true` on success. + * @param [ in ] field - Field to be add. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + */ + bool AddField(arkts::InterfaceField field); + + /** + * @brief add function for interface + * @return `true` on success. + * @param [ in ] function - Function to be add. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + */ + bool AddMethod(arkts::Function function); + + /** + * @brief Add superinterface to the interface + * @return `true` on success. + * @param [ in ] iface - Interface to be added. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if iface is false. + */ + bool AddSuperInterface(const Interface &iface) const; + + /** + * @brief Remove superinterface from the interface + * @return `true` on success. + * @param [ in ] iface - Interface to be removed. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if iface is false. + */ + bool RemoveSuperInterface(const Interface &iface) const; + + /** + * @brief Remove method from the interface + * @return `true` on success. + * @param [ in ] method - Function to be removed. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if method is false. + */ + bool RemoveMethod(const Function &method) const; + + /** + * @brief Sets owning module for interface + * @return `true` on success. + * @param [ in ] module - Module to be set. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if view itself is false. + * @note Set `ABCKIT_STATUS_BAD_ARGUMENT` error if module is false. + */ + bool SetOwningModule(const Module &module) const; + private: /** * @brief Converts interface from Core to Arkts target diff --git a/libabckit/include/libabckit/cpp/headers/arkts/interface_impl.h b/libabckit/include/libabckit/cpp/headers/arkts/interface_impl.h index 520db7246d343a9bb10e5b9fb34e2838745993d3..a0f2fa9b7da62279fbd540af534279d80bd83c92 100644 --- a/libabckit/include/libabckit/cpp/headers/arkts/interface_impl.h +++ b/libabckit/include/libabckit/cpp/headers/arkts/interface_impl.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -16,7 +16,10 @@ #ifndef CPP_ABCKIT_ARKTS_INTERFACE_IMPL_H #define CPP_ABCKIT_ARKTS_INTERFACE_IMPL_H +#include "field.h" +#include "function.h" #include "interface.h" +#include "module.h" // NOLINTBEGIN(performance-unnecessary-value-param) namespace abckit::arkts { @@ -37,6 +40,67 @@ inline bool Interface::SetName(const std::string &name) const return ret; } +inline bool Interface::RemoveField(arkts::InterfaceField field) const +{ + const auto ret = GetApiConfig()->cArktsMapi_->interfaceRemoveField(TargetCast(), field.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline Interface Interface::CreateInterface(Module m, const std::string &name) +{ + auto iface = m.GetApiConfig()->cArktsMapi_->createInterface(m.TargetCast(), name.c_str()); + CheckError(m.GetApiConfig()); + + auto coreIface = core::Interface(m.GetApiConfig()->cArktsIapi_->arktsInterfaceToCoreInterface(iface), + m.GetApiConfig(), m.GetResource()); + CheckError(m.GetApiConfig()); + + return Interface(coreIface); +} + +inline bool Interface::AddField(arkts::InterfaceField field) +{ + const auto ret = GetApiConfig()->cArktsMapi_->interfaceAddField(TargetCast(), field.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Interface::AddMethod(arkts::Function function) +{ + const auto ret = GetApiConfig()->cArktsMapi_->interfaceAddMethod(TargetCast(), function.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Interface::AddSuperInterface(const Interface &iface) const +{ + const auto ret = GetApiConfig()->cArktsMapi_->interfaceAddSuperInterface(TargetCast(), iface.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Interface::RemoveSuperInterface(const Interface &iface) const +{ + const auto ret = GetApiConfig()->cArktsMapi_->interfaceRemoveSuperInterface(TargetCast(), iface.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Interface::RemoveMethod(const Function &method) const +{ + const auto ret = GetApiConfig()->cArktsMapi_->interfaceRemoveMethod(TargetCast(), method.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + +inline bool Interface::SetOwningModule(const Module &module) const +{ + const auto ret = GetApiConfig()->cArktsMapi_->interfaceSetOwningModule(TargetCast(), module.TargetCast()); + CheckError(GetApiConfig()); + return ret; +} + } // namespace abckit::arkts // NOLINTEND(performance-unnecessary-value-param) diff --git a/libabckit/include/libabckit/cpp/headers/arkts/module.h b/libabckit/include/libabckit/cpp/headers/arkts/module.h index 18898f5f941e0bb2cd71b1cd5b9b3bdeac7df4b8..900b6c637be0a2488b8e53aa776ac87a6da5ee8b 100644 --- a/libabckit/include/libabckit/cpp/headers/arkts/module.h +++ b/libabckit/include/libabckit/cpp/headers/arkts/module.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -34,6 +34,10 @@ class Module final : public core::Module { // We restrict constructors in order to prevent C/C++ API mix-up by user. /// @brief to access private constructor friend class abckit::File; + /// @brief to access private constructor + friend class Class; + /// @brief to access private constructor + friend class Interface; /// @brief abckit::DefaultHash friend class abckit::DefaultHash; /// @brief to access private TargetCast diff --git a/libabckit/include/libabckit/cpp/headers/core/class.h b/libabckit/include/libabckit/cpp/headers/core/class.h index 36292497bc813520646932d770efd09641201cbf..3837f743a0d8d7301063e3cc2b150bd80104ccd3 100644 --- a/libabckit/include/libabckit/cpp/headers/core/class.h +++ b/libabckit/include/libabckit/cpp/headers/core/class.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -41,6 +41,8 @@ class Class : public ViewInResource { friend class core::ClassField; /// @brief to access private constructor friend class abckit::Type; + /// @brief to access private constructor + friend class arkts::Class; /// @brief abckit::DefaultHash friend class abckit::DefaultHash; /// @brief to access private constructor diff --git a/libabckit/include/libabckit/cpp/headers/core/field.h b/libabckit/include/libabckit/cpp/headers/core/field.h index dd723feede2cc1b49838d33cd5dbe903459d3525..867dcbe941684b2ac8a73be3b86814eb14d1c30d 100644 --- a/libabckit/include/libabckit/cpp/headers/core/field.h +++ b/libabckit/include/libabckit/cpp/headers/core/field.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -228,7 +228,7 @@ public: * @brief Construct a new ClassField object * @param other */ - ClassField(const ClassField &other) = default; + ClassField(const ClassField &other) = default; // CC-OFF(G.CLS.07): design decision, detail: base_concepts.h /** * @brief Constructor @@ -241,7 +241,7 @@ public: * @brief Construct a new Field object * @param other */ - ClassField(ClassField &&other) = default; + ClassField(ClassField &&other) = default; // CC-OFF(G.CLS.07): design decision, detail: base_concepts.h /** * @brief Constructor @@ -370,7 +370,8 @@ public: * @brief Construct a new InterfaceField object * @param other */ - InterfaceField(const InterfaceField &other) = default; + InterfaceField(const InterfaceField &other) = + default; // CC-OFF(G.CLS.07): design decision, detail: base_concepts.h /** * @brief Constructor @@ -383,7 +384,7 @@ public: * @brief Construct a new InterfaceField object * @param other */ - InterfaceField(InterfaceField &&other) = default; + InterfaceField(InterfaceField &&other) = default; // CC-OFF(G.CLS.07): design decision, detail: base_concepts.h /** * @brief Constructor diff --git a/libabckit/include/libabckit/cpp/headers/core/interface.h b/libabckit/include/libabckit/cpp/headers/core/interface.h index 6fa2c80b8973da8854f1a9bf67abe05090e3550c..540e48f472d0ee5b710a40e6c1a92d38e7099277 100644 --- a/libabckit/include/libabckit/cpp/headers/core/interface.h +++ b/libabckit/include/libabckit/cpp/headers/core/interface.h @@ -40,6 +40,8 @@ class Interface : public ViewInResource { friend abckit::DefaultHash; /// @brief to access private constructor friend class abckit::File; + /// @brief to access private constructor + friend class arkts::Interface; protected: /// @brief Core API View type diff --git a/libabckit/src/adapter_static/abckit_static.h b/libabckit/src/adapter_static/abckit_static.h index 08ee32b701fab324b3873bda2910161a12607cca..b63cbc7a689c640b493d5bfc4317c7754abef799 100644 --- a/libabckit/src/adapter_static/abckit_static.h +++ b/libabckit/src/adapter_static/abckit_static.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -18,6 +18,10 @@ #include "libabckit/c/ir_core.h" #include "libabckit/c/metadata_core.h" +#include "libabckit/src/metadata_inspect_impl.h" + +#include +#include namespace libabckit { @@ -25,7 +29,10 @@ AbckitFile *OpenAbcStatic(const char *path, size_t len); void WriteAbcStatic(AbckitFile *file, const char *path, size_t len); void DestroyGraphStatic(AbckitGraph *graph); void CloseFileStatic(AbckitFile *file); - +std::unique_ptr CollectFunction( + AbckitFile *file, std::unordered_map> &nameToModule, + std::unordered_map &nameToNamespace, const std::string &functionName, + ark::pandasm::Function &functionImpl); } // namespace libabckit #endif diff --git a/libabckit/src/adapter_static/metadata_modify_static.cpp b/libabckit/src/adapter_static/metadata_modify_static.cpp index d58ae83e73549afbaef4dba20650875527065e70..8f8be659cb868a9f0538e936cae4f6934887baa9 100644 --- a/libabckit/src/adapter_static/metadata_modify_static.cpp +++ b/libabckit/src/adapter_static/metadata_modify_static.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -27,7 +27,10 @@ #include "src/adapter_static/metadata_inspect_static.h" #include "src/adapter_static/abckit_static.h" #include "src/adapter_static/helpers_static.h" +#include "static_core/assembler/assembly-field.h" #include "static_core/assembler/assembly-program.h" +#include "static_core/assembler/assembly-record.h" +#include "static_core/assembler/meta.h" #include "static_core/compiler/optimizer/ir/graph_checker.h" #include "static_core/compiler/optimizer/ir/graph_cloner.h" @@ -36,11 +39,16 @@ #include "static_core/compiler/optimizer/optimizations/move_constants.h" #include "static_core/compiler/optimizer/optimizations/lowering.h" #include "static_core/bytecode_optimizer/reg_encoder.h" +#include "static_core/plugins/ets/assembler/extension/ets_meta.h" +#include "static_core/plugins/ets/runtime/types/ets_type.h" #include "utils/function_util.h" #include #include +static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkI = AbckitGetArktsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); + // CC-OFFNXT(WordsTool.95) sensitive word conflict // NOLINTNEXTLINE(google-build-using-namespace) using namespace ark; @@ -391,6 +399,966 @@ bool FunctionSetReturnTypeStatic(AbckitArktsFunction *func, AbckitType *abckitTy ReplaceInstructionIds(prog, funcImpl, oldMangleName, newMangleName); UpdateFileMap(coreFunc->owningModule->file, oldMangleName, newMangleName); + + return true; +} + +// ======================================== +// Class +// ======================================== +AbckitArktsClass *CreateClassStatic(AbckitCoreModule *m, const char *name) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(m->file->GetStaticProgram(), nullptr); + LIBABCKIT_INTERNAL_ERROR(m->moduleName, nullptr); + + auto fullName = std::string(m->moduleName->impl) + '.' + name; + auto prog = m->file->GetStaticProgram(); + auto progRecord = pandasm::Record(fullName, prog->lang); + progRecord.metadata->SetAttributeValue("ets.extends", "std.core.Object"); + progRecord.metadata->SetAttributeValue("access.record", "public"); + prog->recordTable.try_emplace(fullName, std::move(progRecord)); + pandasm::Record &record = prog->recordTable.find(fullName)->second; + auto klass = std::make_unique(m, AbckitArktsClass(&record)); + + m->ct.try_emplace(name, std::move(klass)); + return (m->ct)[name]->GetArkTSImpl(); +} + +bool ClassRemoveMethodStatic(AbckitCoreClass *klass, AbckitCoreFunction *core) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(klass->owningModule->file->GetStaticProgram(), false); + + auto &methods = klass->methods; + auto func = core->GetArkTSImpl()->GetStaticImpl(); + auto iter = std::find_if(methods.begin(), methods.end(), + [&func](auto &funcIt) { return funcIt->GetArkTSImpl()->GetStaticImpl() == func; }); + if (iter == methods.end()) { + LIBABCKIT_LOG(ERROR) << "Can not find the methods to delete\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + methods.erase(iter); + + auto removeFromFunctionMap = [&func](auto &functionMap, const char *tableName) { + bool removed = false; + for (auto it = functionMap.begin(); it != functionMap.end();) { + if ((&(it->second)) == func) { + it = functionMap.erase(it); + removed = true; + } else { + ++it; + } + } + if (removed) { + LIBABCKIT_LOG(DEBUG) << "find method in tableName: " << tableName << "\n"; + } + }; + ark::pandasm::Program *prog = klass->owningModule->file->GetStaticProgram(); + removeFromFunctionMap(prog->functionStaticTable, "functionStaticTable"); + removeFromFunctionMap(prog->functionInstanceTable, "functionInstanceTable"); + auto removeFromFileMap = [&core](auto &coreFuncMap, const char *mapName) { + bool removed = false; + for (auto it = coreFuncMap.begin(); it != coreFuncMap.end();) { + if (it->second == core) { + it = coreFuncMap.erase(it); + removed = true; + } else { + ++it; + } + } + if (removed) { + LIBABCKIT_LOG(DEBUG) << "find method in coreFuncMap: " << mapName << std::endl; + } + }; + + auto &file = *klass->owningModule->file; + removeFromFileMap(file.nameToFunctionStatic, "nameToFunctionStatic"); + removeFromFileMap(file.nameToFunctionInstance, "nameToFunctionInstance"); + + return true; +} + +bool ClassAddInterfaceStatic(AbckitArktsClass *klass, AbckitArktsInterface *iface) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(klass->impl.GetStaticClass(), false); + LIBABCKIT_INTERNAL_ERROR(klass->impl.GetStaticClass()->metadata, false); + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule->file->GetStaticProgram(), false); + LIBABCKIT_INTERNAL_ERROR(iface->impl.GetStaticClass(), false); + + AbckitCoreInterface *ifaceCore = iface->core; + ark::pandasm::Record *record = klass->impl.GetStaticClass(); + std::string fullName = iface->impl.GetStaticClass()->name; + + // if the target interface is not in the program, add it + auto ifaceRecord = iface->impl.GetStaticClass(); + ark::pandasm::Program *prog = klass->core->owningModule->file->GetStaticProgram(); + if (prog->recordTable.find(fullName) == prog->recordTable.end()) { + prog->recordTable.emplace(fullName, std::move(*ifaceRecord)); + iface->impl.cl = &(prog->recordTable.find(fullName)->second); + } + + auto it = record->metadata->GetInterfaces(); + if (std::find(it.begin(), it.end(), fullName) == it.end()) { + auto res = record->metadata->AddInterface(fullName); + if (!res) { + LIBABCKIT_LOG(ERROR) << "Failed to add interface\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + } + } else { + LIBABCKIT_LOG(ERROR) << "The interface already exists\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + } + + auto &interfaces = klass->core->interfaces; + auto interfaceName = std::get<1>(ClassGetNames(fullName)); + auto iter = std::find_if(interfaces.begin(), interfaces.end(), [&interfaceName](auto &interIt) { + return interfaceName == InterfaceGetNameStatic(interIt)->impl; + }); + if (iter == interfaces.end()) { + interfaces.push_back(ifaceCore); + } else { + LIBABCKIT_LOG(ERROR) << "The interface already exists\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + } + + return statuses::GetLastError() == AbckitStatus::ABCKIT_STATUS_NO_ERROR; +} + +bool ClassRemoveInterfaceStatic(AbckitArktsClass *klass, AbckitArktsInterface *iface) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(klass->impl.GetStaticClass(), false); + LIBABCKIT_INTERNAL_ERROR(klass->impl.GetStaticClass()->metadata, false); + LIBABCKIT_INTERNAL_ERROR(iface->impl.GetStaticClass(), false); + + ark::pandasm::Record *record = klass->impl.GetStaticClass(); + std::string fullName = iface->impl.GetStaticClass()->name; + auto interfaceName = std::get<1>(ClassGetNames(fullName)); + + auto &interfaces = klass->core->interfaces; + auto iter = std::find_if(interfaces.begin(), interfaces.end(), [&interfaceName](auto &interIt) { + return interfaceName == InterfaceGetNameStatic(interIt)->impl; + }); + if (iter != interfaces.end()) { + interfaces.erase(iter); + } else { + LIBABCKIT_LOG(ERROR) << "Can not find the interface to delete\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + } + + auto res = record->metadata->RemoveInterface(fullName); + if (!res) { + LIBABCKIT_LOG(ERROR) << "Failed to remove the interface from metadata\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + } + + return statuses::GetLastError() == AbckitStatus::ABCKIT_STATUS_NO_ERROR; +} + +bool ClassSetSuperClassStatic(AbckitArktsClass *klass, AbckitArktsClass *superClass) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(klass->impl.GetStaticClass(), false); + LIBABCKIT_INTERNAL_ERROR(klass->impl.GetStaticClass()->metadata, false); + LIBABCKIT_INTERNAL_ERROR(superClass->impl.GetStaticClass(), false); + + if ((klass->core->superClass != nullptr) && + (klass->core->superClass->GetArkTSImpl()->impl.GetStaticClass()->name != "std.core.Object")) { + LIBABCKIT_LOG(ERROR) << "Class already has a super class\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + + klass->core->superClass = superClass->core; + + auto superClassName = superClass->impl.GetStaticClass()->name; + ark::pandasm::Record *record = klass->impl.GetStaticClass(); + auto res = record->metadata->SetBase(superClassName); + if (!res) { + LIBABCKIT_LOG(ERROR) << "Failed to set super class in metadata\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + + return true; +} + +static void UpdateClassNameInFuncParams(std::vector ¶ms, + const std::string &oldName, const std::string &setNewName) +{ + for (auto ¶m : params) { + if (param.type.GetComponentName().find(oldName) != std::string::npos) { + param.type = pandasm::Type(setNewName, param.type.GetRank()); + } + } +} + +bool CheckIsNeedAddMethod(ark::pandasm::Program *program, AbckitArktsFunction *method, + const std::string &moduleClassName) +{ + LIBABCKIT_INTERNAL_ERROR(program, false); + LIBABCKIT_INTERNAL_ERROR(method, false); + auto funcNameCropModule = std::string(g_implI->functionGetName(method->core)->impl.data()); + auto isStatic = method->GetStaticImpl()->IsStatic(); + if (isStatic) { + auto funcName = std::string(moduleClassName) + "." + funcNameCropModule; + auto &funcStaticTable = program->functionStaticTable; + if (funcStaticTable.find(funcName) != funcStaticTable.end()) { + return false; + } + } else { + size_t colon_pos = funcNameCropModule.find(':'); + if (colon_pos != std::string::npos) { + std::string paras = funcNameCropModule.substr(colon_pos + 1); + size_t semicolon_pos = paras.find(';'); + if (semicolon_pos != std::string::npos) { + paras.replace(0, semicolon_pos, moduleClassName); + } + auto funcName = moduleClassName + "." + funcNameCropModule.substr(0, colon_pos) + ":" + paras; + auto &funcInstanceTable = program->functionInstanceTable; + if (funcInstanceTable.find(funcName) != funcInstanceTable.end()) { + return false; + } + } + } + return true; +} + +std::unique_ptr CreateCoreFunction(AbckitFile *file, AbckitCoreNamespace *ns, + ark::pandasm::Function &function, std::string funcMangledName) +{ + std::unordered_map nameToNameSpace; + if (ns != nullptr) { + nameToNameSpace.emplace(ns->GetArkTSImpl()->impl.GetStaticClass()->name, ns); + } + + return libabckit::CollectFunction(file, file->localModules, nameToNameSpace, funcMangledName, function); +} + +template +std::unique_ptr CreatePandasmFunction(AbckitArktsType *instance, AbckitArktsFunction *method, + const std::string &newFuncName) +{ + auto funcData = method->GetStaticImpl(); + size_t colonPos = newFuncName.find(':'); + auto newFunction = std::make_unique(newFuncName.substr(0, colonPos), funcData->language); + newFunction->returnType = funcData->returnType; + newFunction->sourceFile = funcData->sourceFile; + newFunction->metadata->SetAccessFlags(funcData->metadata->GetAccessFlags()); + + for (auto ¶m : funcData->params) { + newFunction->params.emplace_back(param.type, param.lang); + } + if (!funcData->IsStatic()) { + auto thisType = pandasm::Type(instance->impl.GetStaticClass()->name, 0); + newFunction->params[0] = pandasm::Function::Parameter(thisType, instance->impl.GetStaticClass()->language); + } + auto &setAttributes = funcData->metadata->GetBoolAttributes(); + for (auto &sa : setAttributes) { + newFunction->metadata->SetAttribute(sa); + } + auto &attributes = funcData->metadata->GetAttributes(); + for (auto &[key, valueVec] : attributes) { + for (auto &value : valueVec) { + newFunction->metadata->SetAttributeValue(key, value); + } + } + if (funcData->HasImplementation()) { + for (auto &tmpIns : funcData->ins) { + ark::pandasm::Ins clone = tmpIns.Clone(); + newFunction->ins.emplace_back(std::move(clone)); + } + newFunction->regsNum = funcData->regsNum; + for (auto &tmpBlock : funcData->catchBlocks) { + newFunction->catchBlocks.emplace_back(tmpBlock); + } + } + return newFunction; +} + +static void UpdateClassName(std::string &input, const std::string &oldName, const std::string &newName) +{ + size_t pos = 0; + while ((pos = input.find(oldName, pos)) != std::string::npos) { + input.replace(pos, oldName.length(), newName); + pos += newName.length(); + } +} + +static void UpdateClassNameInFuncIns(std::vector &ins, const std::string &oldName, + const std::string &setNewName) +{ + for (auto &tmpIns : ins) { +#if defined(NOT_OPTIMIZE_PERFORMANCE) + for (auto &tmpIds : tmpIns.ids) { + if (tmpIds.find(oldName) != std::string::npos) { + UpdateClassName(tmpIds, oldName, setNewName); + } + } +#else + std::size_t count = tmpIns.IDSize(); + for (std::size_t i = 0; i < count; i++) { + if (tmpIns.GetID(i).find(oldName) != std::string::npos) { + auto &str = const_cast(tmpIns.GetID(i)); + UpdateClassName(str, oldName, setNewName); + tmpIns.SetID(i, str); + } + } +#endif + } +} + +bool ClassAddMethodStatic(AbckitArktsClass *klass, AbckitArktsFunction *method) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(klass, false); + LIBABCKIT_INTERNAL_ERROR(method, false); + if (klass->core == method->core->parentClass) { + LIBABCKIT_LOG(ERROR) << "method have been in klass.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_BAD_ARGUMENT); + return false; + } + auto program = klass->core->owningModule->file->GetStaticProgram(); + auto moduleClassName = klass->impl.GetStaticClass()->name; + // Check whether the method exists + // method name, method parameters, return type and method attributes are the same + if (CheckIsNeedAddMethod(program, method, moduleClassName) == false) { + LIBABCKIT_LOG(ERROR) << "Method already exists\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_BAD_ARGUMENT); + return false; + } + auto isStaticFunc = method->GetStaticImpl()->IsStatic(); + std::unordered_map &nameToFuncMap = + isStaticFunc ? method->core->owningModule->file->nameToFunctionStatic + : method->core->owningModule->file->nameToFunctionInstance; + + std::map &funcTable = + isStaticFunc ? method->core->owningModule->file->GetStaticProgram()->functionStaticTable + : method->core->owningModule->file->GetStaticProgram()->functionInstanceTable; + std::string funcMangledName = GetMangleFuncName(method->core); + ASSERT(funcMangledName != "__ABCKIT_INVALID__"); + auto funcModuleName = funcMangledName.substr(0, funcMangledName.find(':')); + auto oldModuleClassName = funcModuleName.substr(0, funcModuleName.rfind('.')); + UpdateClassName(funcMangledName, oldModuleClassName, moduleClassName); + + auto funcData = CreatePandasmFunction(klass, method, funcMangledName); + UpdateClassNameInFuncIns(funcData.get()->ins, oldModuleClassName, moduleClassName); + funcTable.insert(std::make_pair(funcMangledName, std::move(*funcData))); + + auto newCoreFunc = CreateCoreFunction(klass->core->owningModule->file, klass->core->parentNamespace, + funcTable.at(funcMangledName), funcMangledName); + nameToFuncMap.emplace(funcMangledName, newCoreFunc.get()); + klass->core->methods.emplace_back(std::move(newCoreFunc)); + return true; +} + +bool ClassRemoveFieldStatic(AbckitArktsClass *klass, AbckitCoreClassField *field) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(klass, false); + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(klass->impl.GetStaticClass(), false); + + LIBABCKIT_INTERNAL_ERROR(field, false); + + auto name = field->name; + if (name == nullptr) { + LIBABCKIT_LOG(ERROR) << "The 'field' parameter is incorrect\n"; + statuses::SetLastError(ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + auto nameStr = name->impl; + auto iter = std::find_if(klass->core->fields.begin(), klass->core->fields.end(), + [&nameStr](auto &tempfieldIter) { return nameStr == tempfieldIter.get()->name->impl; }); + if (iter == klass->core->fields.end()) { + LIBABCKIT_LOG(ERROR) << "Can not find the field to delete\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + klass->core->fields.erase(iter); + + auto fieldIter = + std::find_if(klass->impl.GetStaticClass()->fieldList.begin(), klass->impl.GetStaticClass()->fieldList.end(), + [&nameStr](auto &tempIter) { return nameStr == tempIter.name; }); + if (fieldIter == klass->impl.GetStaticClass()->fieldList.end()) { + LIBABCKIT_LOG(ERROR) << "Can not find the field to delete\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + klass->impl.GetStaticClass()->fieldList.erase(fieldIter); + return true; +} + +template +static void UpdateClassNameInFuncTable(FuncTblProgram &table, const std::string &oldName, const std::string &setNewName) +{ + FuncTblProgram tmpTable; + for (auto iter = table.begin(); iter != table.end();) { + if (iter->first.find(oldName) != std::string::npos) { + auto node = table.extract(iter++); + UpdateClassName(node.key(), oldName, setNewName); + UpdateClassName(node.mapped().name, oldName, setNewName); + UpdateClassNameInFuncParams(node.mapped().params, oldName, setNewName); + UpdateClassNameInFuncIns(node.mapped().ins, oldName, setNewName); + tmpTable.insert(std::move(node)); + } else { + UpdateClassNameInFuncParams(iter->second.params, oldName, setNewName); + UpdateClassNameInFuncIns(iter->second.ins, oldName, setNewName); + ++iter; + } + } + + for (auto it = tmpTable.begin(); it != tmpTable.end();) { + auto node = tmpTable.extract(it++); + table.insert(std::move(node)); + } +} + +template +static void UpdateClassNameInCommonTbl(CommonTbl &table, const std::string &oldName, const std::string &setNewName) +{ + CommonTbl tmpTable; + for (auto iter = table.begin(); iter != table.end();) { + if (iter->first.find(oldName) != std::string::npos) { + auto node = table.extract(iter++); + UpdateClassName(node.key(), oldName, setNewName); + tmpTable.insert(std::move(node)); + } else { + ++iter; + } + } + table.insert(std::make_move_iterator(tmpTable.begin()), std::make_move_iterator(tmpTable.end())); +} + +static void UpdateModuleAndClassName(AbckitFile *file, const std::string &oldName, const std::string &setNewName) +{ + LIBABCKIT_INTERNAL_ERROR_VOID(file); + auto program = file->GetStaticProgram(); + auto iter = std::find_if(program->recordTable.begin(), program->recordTable.end(), + [&oldName](const auto &pair) { return pair.first == oldName; }); + if (iter != program->recordTable.end()) { + auto node = program->recordTable.extract(iter); + node.key() = setNewName; + node.mapped().name = setNewName; + program->recordTable.insert(std::move(node)); + } + UpdateClassNameInFuncTable(program->functionStaticTable, oldName, setNewName); + UpdateClassNameInFuncTable(program->functionInstanceTable, oldName, setNewName); + UpdateClassNameInCommonTbl(file->nameToFunctionStatic, oldName, setNewName); + UpdateClassNameInCommonTbl(file->nameToFunctionInstance, oldName, setNewName); +} + +static void UpdateExtendsInfo(AbckitFile *file, const std::string &oldName, const std::string &setNewName) +{ + LIBABCKIT_INTERNAL_ERROR_VOID(file); + for (auto &[name, record] : file->GetStaticProgram()->recordTable) { + auto baseStr = record.metadata->GetBase(); + if (baseStr == oldName) { + record.metadata->RemoveAttributeValue("ets.extends", oldName); + record.metadata->SetAttributeValue("ets.extends", setNewName); + } + } +} + +bool ClassSetNameStatic(AbckitCoreClass *klass, const char *name) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(name, false); + LIBABCKIT_INTERNAL_ERROR(klass->owningModule, false); + + auto oldClassName = g_implI->abckitStringToString(g_implI->classGetName(klass)); + ark::pandasm::Record *record = klass->GetArkTSImpl()->impl.GetStaticClass(); + auto [tmpModuleName, tmpClassName] = ClassGetNames(record->name); + auto moduleName = tmpModuleName; + auto setNewName = std::string(moduleName) + "." + name; + auto oldName = std::string(moduleName) + "." + oldClassName; + if (std::string(setNewName) == std::string(oldName)) { + LIBABCKIT_LOG(ERROR) << "class name already exist.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_BAD_ARGUMENT); + return false; + } + UpdateModuleAndClassName(klass->owningModule->file, oldName, setNewName); + UpdateClassNameInCommonTbl(klass->owningModule->ct, oldClassName, name); + // if kclass is parent, modify derived class's ets.extends info + UpdateExtendsInfo(klass->owningModule->file, oldName, setNewName); + return true; +} + +bool ClassAddFieldStatic(AbckitCoreClass *klass, AbckitCoreClassField *coreClassField) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(coreClassField, false); + + auto record = klass->GetArkTSImpl()->impl.GetStaticClass(); + auto pandaField = coreClassField->GetArkTSImpl()->GetStaticImpl(); + auto it = std::find_if(record->fieldList.begin(), record->fieldList.end(), + [&pandaField](auto &field) { return field.name == pandaField->name; }); + if (it != record->fieldList.end()) { + LIBABCKIT_LOG(ERROR) << "field name already exist.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_BAD_ARGUMENT); + return false; + } + ark::pandasm::Field tmpField(ark::SourceLanguage::ETS); + tmpField.name = pandaField->name; + tmpField.type = ark::pandasm::Type(pandaField->type.GetComponentName(), pandaField->type.GetRank()); + auto &setAttributes = pandaField->metadata->GetBoolAttributes(); + for (auto &sa : setAttributes) { + tmpField.metadata->SetAttribute(sa); + } + auto &attributes = pandaField->metadata->GetAttributes(); + for (auto &[key, valueVec] : attributes) { + for (auto &value : valueVec) { + tmpField.metadata->SetAttributeValue(key, value); + } + } + auto value = pandaField->metadata->GetValue(); + if (value.has_value()) { + tmpField.metadata->SetValue(value.value()); + } + record->fieldList.emplace_back(std::move(tmpField)); + // record->fieldList's emplace_back operation may lead to memory reallocation, pandasm::Field's address may change + klass->fields.clear(); + for (auto &tmpField : record->fieldList) { + auto classField = std::make_unique(klass, &tmpField); + classField->name = CreateStringStatic(klass->owningModule->file, tmpField.name.c_str(), tmpField.name.length()); + klass->fields.emplace_back(std::move(classField)); + } return true; } + +template +static void UpdateClassInfoToNewModule(tblType &table1, tblType &table2, const std::string &name) +{ + for (auto iter = table1.begin(); iter != table1.end();) { + if (iter->first.find(name) != std::string::npos) { + auto node = table1.extract(iter++); + table2.insert(std::move(node)); + } else { + ++iter; + } + } +} + +template +static void UpdateOwningModuleInfo(vecType &vec, AbckitCoreModule *module) +{ + for (auto &item : vec) { + item->owningModule = module; + } +} + +bool ClassSetOwningModuleStatic(AbckitCoreClass *klass, AbckitCoreModule *module) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(module, false); + LIBABCKIT_INTERNAL_ERROR(klass->owningModule, false); + + if ((klass->owningModule->file) != (module->file)) { + LIBABCKIT_LOG(ERROR) << "new module and current module should be in same AbckitFile.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_UNSUPPORTED); + return false; + } + auto className = g_implI->abckitStringToString(g_implI->classGetName(klass)); + ark::pandasm::Record *record = klass->GetArkTSImpl()->impl.GetStaticClass(); + auto [tmpModuleName, tmpClassName] = ClassGetNames(record->name); + auto oldModuleName = tmpModuleName; + auto newModuleName = g_implI->abckitStringToString(module->moduleName); + auto setNewName = std::string(newModuleName) + "." + className; + auto oldName = std::string(oldModuleName) + "." + className; + if (newModuleName == oldModuleName) { + LIBABCKIT_LOG(ERROR) << "same module. No need to setOwningModule\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_BAD_ARGUMENT); + return false; + } + auto file = module->file; + UpdateModuleAndClassName(file, oldName, setNewName); + UpdateClassInfoToNewModule(klass->owningModule->ct, module->ct, className); + UpdateExtendsInfo(klass->owningModule->file, oldName, setNewName); + UpdateOwningModuleInfo(klass->methods, module); + UpdateOwningModuleInfo(klass->interfaces, module); + klass->owningModule = module; + return true; +} + +// ======================================== +// Interface +// ======================================== +template +static void RemoveFuncInTable(tblType &table, const std::string &interfaceName, const std::string &name) +{ + std::string cleanFieldName = name; + const std::string propertyPrefix = ""; + if (cleanFieldName.find(propertyPrefix) == 0) { + cleanFieldName = cleanFieldName.substr(propertyPrefix.length()); + } + + for (auto iter = table.begin(); iter != table.end();) { + if (iter->first.find(cleanFieldName + ":") != std::string::npos && + iter->first.find(std::string(interfaceName)) != std::string::npos) { + iter = table.erase(iter); + } else { + ++iter; + } + } +} + +bool InterfaceRemoveFieldStatic(AbckitArktsInterface *iface, AbckitCoreInterfaceField *field) +{ + LIBABCKIT_LOG_FUNC; + + if (field->name == nullptr) { + LIBABCKIT_LOG(ERROR) << "Field name is nullptr\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + auto fieldName = field->name->impl; + auto fieldIt = std::find_if(iface->core->fields.begin(), iface->core->fields.end(), + [&fieldName](auto &field) { return field.first == fieldName; }); + if (fieldIt == iface->core->fields.end()) { + LIBABCKIT_LOG(ERROR) << "Field does not exist\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + iface->core->fields.erase(fieldIt); + + auto interfaceName = g_implI->interfaceGetName(iface->core)->impl; + RemoveFuncInTable(iface->core->owningModule->file->GetStaticProgram()->functionInstanceTable, + std::string(interfaceName), std::string(fieldName)); + RemoveFuncInTable(iface->core->owningModule->file->nameToFunctionInstance, std::string(interfaceName), + std::string(fieldName)); + return true; +} + +AbckitArktsInterface *CreateInterfaceStatic(AbckitArktsModule *m, const char *name) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(m->core->file->GetStaticProgram(), nullptr); + LIBABCKIT_INTERNAL_ERROR(m->core->moduleName, nullptr); + + auto prog = m->core->file->GetStaticProgram(); + auto fullName = std::string(m->core->moduleName->impl) + '.' + name; + auto record = pandasm::Record(fullName, prog->lang); + record.metadata->SetAttribute("ets.interface"); + record.metadata->SetAttribute("ets.abstract"); + record.metadata->SetAttributeValue("ets.extends", "std.core.Object"); + record.metadata->SetAttributeValue("access.record", "public"); + prog->recordTable.try_emplace(fullName, std::move(record)); + + auto recordPtr = &prog->recordTable.find(fullName)->second; + auto interface = std::make_unique(m->core, AbckitArktsInterface(recordPtr)); + interface->name = CreateStringStatic(m->core->file, name, strlen(name)); + auto &interfaces = m->core->it; + interfaces.try_emplace(name, std::move(interface)); + + return interfaces[name]->GetArkTSImpl(); +} + +void UpdateImplementList(std::map &records, const std::string &ifaceNameOrigin, + const std::string &ifaceNameNew) +{ + for (auto &[_, record] : records) { + if (record.metadata->RemoveInterface(ifaceNameOrigin)) { + record.metadata->AddInterface(ifaceNameNew); + } + } +} + +bool InterfaceSetNameStatic(AbckitArktsInterface *iface, const char *name) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(name, false); + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule->file, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule->file->GetStaticProgram(), false); + + auto fullNameOrigin = iface->impl.GetStaticClass()->name; + auto [moduleName, ifaceNameOrigin] = ClassGetNames(fullNameOrigin); + auto fullNameNew = moduleName + "." + std::string(name); + + UpdateModuleAndClassName(iface->core->owningModule->file, fullNameOrigin, fullNameNew); + UpdateClassNameInCommonTbl(iface->core->owningModule->it, ifaceNameOrigin, name); + UpdateImplementList(iface->core->owningModule->file->GetStaticProgram()->recordTable, fullNameOrigin, fullNameNew); + return true; +} + +std::unique_ptr CloneInterfaceField(AbckitArktsInterface *iface, + AbckitCoreInterfaceField *field) +{ + auto newField = std::make_unique(); + newField->name = field->name; + newField->owner = iface->core; + newField->flag = field->flag; + newField->type = field->type; + newField->impl = std::make_unique(); + newField->GetArkTSImpl()->core = newField.get(); + return newField; +} + +std::string InterfaceFieldNameSplit(AbckitCoreInterfaceField *field) +{ + auto fieldName = field->name->impl; + std::string splitedFieldName; + + if (fieldName.find(ark::ets::PROPERTY) == 0) { + splitedFieldName = fieldName.substr(ark::ets::PROPERTY_PREFIX_LENGTH); + } else { + LIBABCKIT_LOG(ERROR) << "The input field's name is invalid.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return ""; + } + return splitedFieldName; +} + +bool InterfaceAddFieldAccessors(AbckitArktsInterface *iface, AbckitCoreInterfaceField *field) +{ + auto splitedFieldName = InterfaceFieldNameSplit(field); + if (splitedFieldName.empty()) { + return false; + } + + auto getMethodName = ark::ets::GETTER_BEGIN + splitedFieldName; + auto setMethodName = ark::ets::SETTER_BEGIN + splitedFieldName; + bool addGetter = (field->flag & ACC_PUBLIC); + bool addSetter = !(field->flag & ACC_READONLY); + bool existSetter = false; + bool existGetter = false; + + auto &methods = field->owner->methods; + for (auto &method : methods) { + auto methodName = g_implI->functionGetName(method.get())->impl; + if (addGetter && (methodName.compare(0, getMethodName.length(), getMethodName) == 0)) { + InterfaceAddMethodStatic(iface, method.get()->GetArkTSImpl()); + existGetter = true; + } + if (addSetter && (methodName.compare(0, setMethodName.length(), setMethodName) == 0)) { + InterfaceAddMethodStatic(iface, method.get()->GetArkTSImpl()); + existSetter = true; + } + } + + if ((addSetter && !existSetter) || (addGetter && !existGetter)) { + LIBABCKIT_LOG(ERROR) << "The input field is missing Get or Set method\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + + return true; +} + +bool InterfaceAddFieldStatic(AbckitArktsInterface *iface, AbckitCoreInterfaceField *field) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->impl.GetStaticClass(), false); + + LIBABCKIT_INTERNAL_ERROR(field->name, false); + LIBABCKIT_INTERNAL_ERROR(field->owner, false); + + auto &fieldList = iface->impl.GetStaticClass()->fieldList; + auto fieldName = field->name->impl; + auto it = std::find_if(fieldList.begin(), fieldList.end(), + [&fieldName](const ark::pandasm::Field &field) { return field.name == fieldName; }); + if (it != fieldList.end()) { + LIBABCKIT_LOG(ERROR) << "The field already exists in the interface\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + + if (InterfaceAddFieldAccessors(iface, field)) { + auto newField = CloneInterfaceField(iface, field); + iface->core->fields.emplace(fieldName, std::move(newField)); + return true; + } + + return false; +} + +bool InterfaceAddMethodStatic(AbckitArktsInterface *iface, AbckitArktsFunction *method) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule->file, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule->file->GetStaticProgram(), false); + LIBABCKIT_INTERNAL_ERROR(iface->impl.GetStaticClass(), false); + + LIBABCKIT_INTERNAL_ERROR(method->GetStaticImpl(), false); + LIBABCKIT_INTERNAL_ERROR(method->core, false); + LIBABCKIT_INTERNAL_ERROR(method->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(method->core->owningModule->file, false); + LIBABCKIT_INTERNAL_ERROR(method->core->owningModule->file->GetStaticProgram(), false); + + if (method->GetStaticImpl()->IsStatic()) { + LIBABCKIT_LOG(ERROR) << "Static method should not be added to the interface.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + + if (!CheckIsNeedAddMethod(iface->core->owningModule->file->GetStaticProgram(), method, + iface->impl.GetStaticClass()->name)) { + LIBABCKIT_LOG(ERROR) << "Method already exists in the interface\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + + std::string funcMangledName = GetMangleFuncName(method->core); + ASSERT(funcMangledName != "__ABCKIT_INVALID__"); + + auto funcModuleName = funcMangledName.substr(0, funcMangledName.find(':')); + auto oldModuleClassName = funcModuleName.substr(0, funcModuleName.rfind('.')); + UpdateClassName(funcMangledName, oldModuleClassName, iface->impl.GetStaticClass()->name); + + auto funcData = CreatePandasmFunction(iface, method, funcMangledName); + auto &funcInstanceTab = iface->core->owningModule->file->GetStaticProgram()->functionInstanceTable; + funcInstanceTab.emplace(funcMangledName, std::move(*funcData)); + auto newCoreFunc = CreateCoreFunction(iface->core->owningModule->file, iface->core->parentNamespace, + funcInstanceTab.at(funcMangledName), funcMangledName); + iface->core->owningModule->file->nameToFunctionInstance.emplace(funcMangledName, newCoreFunc.get()); + iface->core->methods.emplace_back(std::move(newCoreFunc)); + return true; +} + +bool InterfaceAddSuperInterfaceStatic(AbckitCoreInterface *iface, AbckitCoreInterface *superIface) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(superIface, false); + + auto superIfaceName = g_implI->abckitStringToString(g_implI->interfaceGetName(superIface)); + auto it = std::find_if(iface->superInterfaces.begin(), iface->superInterfaces.end(), + [&superIfaceName](auto &tmpSuperIface) { + auto name = g_implI->abckitStringToString(g_implI->interfaceGetName(tmpSuperIface)); + return std::string(name) == std::string(superIfaceName); + }); + if (it != iface->superInterfaces.end()) { + LIBABCKIT_LOG(ERROR) << "same superInterface already exits.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + iface->superInterfaces.emplace_back(superIface); + auto record = iface->GetArkTSImpl()->impl.GetStaticClass(); + auto superIfaceFulldName = superIface->GetArkTSImpl()->impl.GetStaticClass()->name; + auto res = record->metadata->AddInterface(superIfaceFulldName); + if (!res) { + LIBABCKIT_LOG(ERROR) << "failed to add superiface in metadata.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + return true; +} + +bool InterfaceRemoveSuperInterfaceStatic(AbckitCoreInterface *iface, AbckitCoreInterface *superIface) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(superIface, false); + + auto superIfaceName = g_implI->abckitStringToString(g_implI->interfaceGetName(superIface)); + auto it = std::find_if(iface->superInterfaces.begin(), iface->superInterfaces.end(), + [&superIfaceName](auto &tmpSuperIface) { + auto name = g_implI->abckitStringToString(g_implI->interfaceGetName(tmpSuperIface)); + return std::string(name) == std::string(superIfaceName); + }); + if (it == iface->superInterfaces.end()) { + LIBABCKIT_LOG(ERROR) << "same superInterface not exits.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + iface->superInterfaces.erase(it); + + auto record = iface->GetArkTSImpl()->impl.GetStaticClass(); + auto superIfaceFulldName = superIface->GetArkTSImpl()->impl.GetStaticClass()->name; + auto res = record->metadata->RemoveInterface(superIfaceFulldName); + if (!res) { + LIBABCKIT_LOG(ERROR) << "failed to remove superiface in metadata.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + return true; +} + +template +static void RemoveFuncInTable(tblType &table, const std::string &name) +{ + for (auto iter = table.begin(); iter != table.end();) { + if (iter->first.find(name) != std::string::npos) { + iter = table.erase(iter); + } else { + ++iter; + } + } +} + +bool InterfaceRemoveMethodStatic(AbckitCoreInterface *iface, AbckitCoreFunction *method) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(method, false); + LIBABCKIT_INTERNAL_ERROR(iface->owningModule, false); + + auto funcNameWithParas = GetMangleFuncName(method); + auto file = iface->owningModule->file; + auto it = std::find_if(iface->methods.begin(), iface->methods.end(), [&funcNameWithParas](auto &tmpMethod) { + return GetMangleFuncName(tmpMethod.get()) == funcNameWithParas; + }); + if (it == iface->methods.end()) { + LIBABCKIT_LOG(ERROR) << "same method not exits.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR); + return false; + } + iface->methods.erase(it); + RemoveFuncInTable(file->GetStaticProgram()->functionInstanceTable, funcNameWithParas); + RemoveFuncInTable(file->GetStaticProgram()->functionStaticTable, funcNameWithParas); + RemoveFuncInTable(file->nameToFunctionStatic, funcNameWithParas); + RemoveFuncInTable(file->nameToFunctionInstance, funcNameWithParas); + return true; +} + +bool InterfaceSetOwningModuleStatic(AbckitCoreInterface *iface, AbckitCoreModule *module) +{ + LIBABCKIT_LOG_FUNC; + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(module, false); + LIBABCKIT_INTERNAL_ERROR(iface->owningModule, false); + + if ((iface->owningModule->file) != (module->file)) { + LIBABCKIT_LOG(ERROR) << "new module and current module should be in same AbckitFile.\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_UNSUPPORTED); + return false; + } + auto ifaceModuleName = g_implI->abckitStringToString(iface->owningModule->moduleName); + auto newModuleName = g_implI->abckitStringToString(module->moduleName); + if (ifaceModuleName == newModuleName) { + LIBABCKIT_LOG(ERROR) << "same module. No need to setOwningModule\n"; + statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_BAD_ARGUMENT); + return false; + } + auto fullInterfaceName = iface->GetArkTSImpl()->impl.GetStaticClass()->name; + auto setNewInterfaceName = fullInterfaceName; + auto ifaceName = g_implI->abckitStringToString(g_implI->interfaceGetName(iface)); + auto file = iface->owningModule->file; + UpdateClassName(setNewInterfaceName, ifaceModuleName, newModuleName); + UpdateModuleAndClassName(file, fullInterfaceName, setNewInterfaceName); + UpdateClassInfoToNewModule(iface->owningModule->it, module->it, ifaceName); + UpdateOwningModuleInfo(iface->methods, module); + // modify derived class/interface's info + for (auto &[name, record] : file->GetStaticProgram()->recordTable) { + auto InterfaceVec = record.metadata->GetInterfaces(); + if (std::find(InterfaceVec.begin(), InterfaceVec.end(), fullInterfaceName) != InterfaceVec.end()) { + record.metadata->RemoveInterface(fullInterfaceName); + record.metadata->AddInterface(setNewInterfaceName); + } + } + iface->owningModule = module; + return true; +} + } // namespace libabckit diff --git a/libabckit/src/adapter_static/metadata_modify_static.h b/libabckit/src/adapter_static/metadata_modify_static.h index 6e74ffdf38641ba3258e844abe287c8377eabd35..ccaf5c4a5c83fadb8af724306deda7de1253c7ac 100644 --- a/libabckit/src/adapter_static/metadata_modify_static.h +++ b/libabckit/src/adapter_static/metadata_modify_static.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -45,6 +45,7 @@ AbckitLiteralArray *CreateLiteralArrayStatic(AbckitFile *file, AbckitLiteral **v AbckitValue *FindOrCreateValueU1Static(AbckitFile *file, bool value); AbckitValue *FindOrCreateValueDoubleStatic(AbckitFile *file, double value); AbckitValue *FindOrCreateValueStringStatic(AbckitFile *file, const char *value, size_t len); + // ======================================== // Function // ======================================== @@ -52,6 +53,33 @@ bool FunctionSetNameStatic(AbckitArktsFunction *function, const char *name); bool FunctionAddParameterStatic(AbckitArktsFunction *func, AbckitArktsFunctionParam *param); bool FunctionSetReturnTypeStatic(AbckitArktsFunction *func, AbckitType *type); bool FunctionRemoveParameterStatic(AbckitArktsFunction *func, size_t index); + +// ======================================== +// Class +// ======================================== +AbckitArktsClass *CreateClassStatic(AbckitCoreModule *core, const char *name); +bool ClassRemoveMethodStatic(AbckitCoreClass *klass, AbckitCoreFunction *core); +bool ClassAddInterfaceStatic(AbckitArktsClass *klass, AbckitArktsInterface *iface); +bool ClassRemoveInterfaceStatic(AbckitArktsClass *klass, AbckitArktsInterface *iface); +bool ClassSetSuperClassStatic(AbckitArktsClass *klass, AbckitArktsClass *superClass); +bool ClassAddMethodStatic(AbckitArktsClass *klass, AbckitArktsFunction *method); +bool ClassRemoveFieldStatic(AbckitArktsClass *klass, AbckitCoreClassField *function); +bool ClassSetNameStatic(AbckitCoreClass *klass, const char *name); +bool ClassAddFieldStatic(AbckitCoreClass *klass, AbckitCoreClassField *coreClassField); +bool ClassSetOwningModuleStatic(AbckitCoreClass *klass, AbckitCoreModule *module); + +// ======================================== +// Interface +// ======================================== +bool InterfaceRemoveFieldStatic(AbckitArktsInterface *iface, AbckitCoreInterfaceField *field); +AbckitArktsInterface *CreateInterfaceStatic(AbckitArktsModule *m, const char *name); +bool InterfaceSetNameStatic(AbckitArktsInterface *iface, const char *name); +bool InterfaceAddFieldStatic(AbckitArktsInterface *iface, AbckitCoreInterfaceField *field); +bool InterfaceAddMethodStatic(AbckitArktsInterface *iface, AbckitArktsFunction *method); +bool InterfaceAddSuperInterfaceStatic(AbckitCoreInterface *iface, AbckitCoreInterface *superIface); +bool InterfaceRemoveSuperInterfaceStatic(AbckitCoreInterface *iface, AbckitCoreInterface *superIface); +bool InterfaceRemoveMethodStatic(AbckitCoreInterface *iface, AbckitCoreFunction *method); +bool InterfaceSetOwningModuleStatic(AbckitCoreInterface *iface, AbckitCoreModule *module); } // namespace libabckit #endif diff --git a/libabckit/src/macros.h b/libabckit/src/macros.h index 042f54c7e2d4251f1e888a6627f83bd98fb0e546..113bafc4824c1572e492db8a9062ddd89213c4a2 100644 --- a/libabckit/src/macros.h +++ b/libabckit/src/macros.h @@ -33,7 +33,6 @@ #define LIBABCKIT_BAD_ARGUMENT(argument, returnvalue) \ if ((argument) == nullptr) { \ statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT); \ - /* CC-OFFNXT(G.PRE.05) code generation */ \ return returnvalue; \ } // CC-OFFNXT(G.PRE.02) code readability diff --git a/libabckit/src/metadata_arkts_inspect_impl.cpp b/libabckit/src/metadata_arkts_inspect_impl.cpp index 3a4022b707fac7913f030a64499da7b296ef6553..806714fcdf72ee9e718ef55ea42bf18944933626 100644 --- a/libabckit/src/metadata_arkts_inspect_impl.cpp +++ b/libabckit/src/metadata_arkts_inspect_impl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -200,9 +200,12 @@ extern "C" AbckitCoreInterface *ArktsInterfaceToCoreInterface(AbckitArktsInterfa extern "C" AbckitArktsInterface *CoreInterfaceToArktsInterface(AbckitCoreInterface *iface) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - return nullptr; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + LIBABCKIT_BAD_ARGUMENT(iface, nullptr); + LIBABCKIT_CHECK_ARKTS_TARGET(iface->owningModule); + return iface->GetArkTSImpl(); } /* ======================================== @@ -272,9 +275,10 @@ extern "C" AbckitCoreClassField *ArktsClassFieldToCoreClassField(AbckitArktsClas extern "C" AbckitArktsClassField *CoreClassFieldToArktsClassField(AbckitCoreClassField *field) { - LIBABCKIT_UNIMPLEMENTED; - (void)field; - return nullptr; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_BAD_ARGUMENT(field, nullptr); + return field->GetArkTSImpl(); } extern "C" bool ArktsClassFieldIsReadonly(AbckitArktsClassField *field) @@ -297,9 +301,11 @@ extern "C" AbckitCoreInterfaceField *ArktsInterfaceFieldToCoreInterfaceField(Abc extern "C" AbckitArktsInterfaceField *CoreInterfaceFieldToArktsInterfaceField(AbckitCoreInterfaceField *field) { - LIBABCKIT_UNIMPLEMENTED; - (void)field; - return nullptr; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + LIBABCKIT_BAD_ARGUMENT(field, nullptr); + return field->GetArkTSImpl(); } extern "C" bool ArktsInterfaceFieldIsReadonly(AbckitArktsInterfaceField *field) diff --git a/libabckit/src/metadata_arkts_modify_impl.cpp b/libabckit/src/metadata_arkts_modify_impl.cpp index 5852673a1b5da50096183cfa60e90f1d94b28de8..e1b38edbdbfcd48e24ae8b120db90af9cc82accb 100644 --- a/libabckit/src/metadata_arkts_modify_impl.cpp +++ b/libabckit/src/metadata_arkts_modify_impl.cpp @@ -1,5 +1,5 @@ /** - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -42,6 +42,15 @@ return; \ } +// CC-OFFNXT(G.PRE.02) code readability +// NOLINTNEXTLINE(cppcoreguidelines-macro-usage) +#define LIBABCKIT_CHECK_SAME_TARGET_RETURN(target1, target2, value) \ + if ((target1) != (target2)) { \ + libabckit::statuses::SetLastError(ABCKIT_STATUS_WRONG_TARGET); \ + /* CC-OFFNXT(G.PRE.05) code generation */ \ + return value; \ + } + namespace libabckit { // ======================================== @@ -316,81 +325,283 @@ extern "C" void ClassRemoveAnnotation(AbckitArktsClass *klass, AbckitArktsAnnota extern "C" bool ClassAddInterface(AbckitArktsClass *klass, AbckitArktsInterface *iface) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)iface; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(iface, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule->file, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule->file, false); + + auto kt = klass->core->owningModule->target; + auto it = iface->core->owningModule->target; + + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, it, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassAddInterfaceStatic(klass, iface); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool ClassRemoveInterface(AbckitArktsClass *klass, AbckitArktsInterface *iface) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)iface; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(iface, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule->file, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule->file, false); + + auto kt = klass->core->owningModule->target; + auto it = iface->core->owningModule->target; + + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, it, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassRemoveInterfaceStatic(klass, iface); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool ClassSetSuperClass(AbckitArktsClass *klass, AbckitArktsClass *superClass) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)superClass; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(superClass, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(superClass->core, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(superClass->core->owningModule, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule->file, false); + LIBABCKIT_INTERNAL_ERROR(superClass->core->owningModule->file, false); + + auto kt = klass->core->owningModule->target; + auto st = superClass->core->owningModule->target; + + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, st, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassSetSuperClassStatic(klass, superClass); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool ClassSetName(AbckitArktsClass *klass, const char *name) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)name; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(name, false); + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule, false); + + auto kt = klass->core->owningModule->target; + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassSetNameStatic(klass->core, name); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool ClassAddField(AbckitArktsClass *klass, AbckitArktsClassField *field) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)field; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(field, false); + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(field->core, false); + LIBABCKIT_INTERNAL_ERROR(field->core->owner, false); + LIBABCKIT_INTERNAL_ERROR(field->core->owner->owningModule, false); + + auto kt = klass->core->owningModule->target; + auto at = field->core->owner->owningModule->target; + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassAddFieldStatic(klass->core, field->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool ClassRemoveField(AbckitArktsClass *klass, AbckitArktsClassField *field) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)field; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(field, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(field->core, false); + + auto kt = klass->core->owningModule->target; + auto at = field->core->owner->owningModule->target; + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassRemoveFieldStatic(klass, field->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool ClassAddMethod(AbckitArktsClass *klass, AbckitArktsFunction *method) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)method; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(method, false); + + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(method->core, false); + + auto kt = klass->core->owningModule->target; + auto at = method->core->owningModule->target; + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassAddMethodStatic(klass, method); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool ClassRemoveMethod(AbckitArktsClass *klass, AbckitArktsFunction *method) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)method; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(method, false); + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(method->core, false); + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(method->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule->file, false); + LIBABCKIT_INTERNAL_ERROR(method->core->owningModule->file, false); + + auto kt = klass->core->owningModule->target; + auto mt = method->core->owningModule->target; + + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, mt, false); + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + break; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassRemoveMethodStatic(klass->core, method->core); + default: + LIBABCKIT_UNREACHABLE; + } return false; } -extern "C" AbckitArktsClass *CreateClass(const char *name) +extern "C" AbckitArktsClass *CreateClass(AbckitArktsModule *m, const char *name) { - LIBABCKIT_UNIMPLEMENTED; - (void)name; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_BAD_ARGUMENT(m, nullptr); + LIBABCKIT_BAD_ARGUMENT(name, nullptr); + LIBABCKIT_INTERNAL_ERROR(m->core, nullptr); + LIBABCKIT_INTERNAL_ERROR(m->core->file, nullptr); + + switch (m->core->target) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + break; + case ABCKIT_TARGET_ARK_TS_V2: + return CreateClassStatic(m->core, name); + default: + LIBABCKIT_UNREACHABLE; + } return nullptr; } extern "C" bool ClassSetOwningModule(AbckitArktsClass *klass, AbckitArktsModule *module) { - LIBABCKIT_UNIMPLEMENTED; - (void)klass; - (void)module; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(klass, false); + LIBABCKIT_BAD_ARGUMENT(module, false); + LIBABCKIT_INTERNAL_ERROR(klass->core, false); + LIBABCKIT_INTERNAL_ERROR(klass->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(module->core, false); + + auto kt = klass->core->owningModule->target; + auto at = module->core->target; + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return ClassSetOwningModuleStatic(klass->core, module->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool ClassSetParentFunction(AbckitArktsClass *klass, AbckitArktsFunction *func) @@ -407,66 +618,220 @@ extern "C" bool ClassSetParentFunction(AbckitArktsClass *klass, AbckitArktsFunct extern "C" bool InterfaceAddSuperInterface(AbckitArktsInterface *iface, AbckitArktsInterface *superIface) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - (void)superIface; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(superIface, false); + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(superIface->core, false); + LIBABCKIT_INTERNAL_ERROR(superIface->core->owningModule, false); + + auto kt = iface->core->owningModule->target; + auto at = superIface->core->owningModule->target; + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return InterfaceAddSuperInterfaceStatic(iface->core, superIface->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool InterfaceRemoveSuperInterface(AbckitArktsInterface *iface, AbckitArktsInterface *superIface) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - (void)superIface; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(superIface, false); + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(superIface->core, false); + LIBABCKIT_INTERNAL_ERROR(superIface->core->owningModule, false); + + auto kt = iface->core->owningModule->target; + auto at = superIface->core->owningModule->target; + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return InterfaceRemoveSuperInterfaceStatic(iface->core, superIface->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool InterfaceSetName(AbckitArktsInterface *iface, const char *name) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - (void)name; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(name, false); + + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + + auto kt = iface->core->owningModule->target; + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return InterfaceSetNameStatic(iface, name); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool InterfaceAddField(AbckitArktsInterface *iface, AbckitArktsInterfaceField *field) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - (void)field; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(field, false); + + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(field->core, false); + + auto kt = iface->core->owningModule->target; + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return InterfaceAddFieldStatic(iface, field->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool InterfaceRemoveField(AbckitArktsInterface *iface, AbckitArktsInterfaceField *field) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - (void)field; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(field, false); + + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(field->core, false); + + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(field->core->owner, false); + LIBABCKIT_INTERNAL_ERROR(field->core->owner->owningModule, false); + + auto kt = iface->core->owningModule->target; + auto at = field->core->owner->owningModule->target; + + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return InterfaceRemoveFieldStatic(iface, field->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool InterfaceAddMethod(AbckitArktsInterface *iface, AbckitArktsFunction *method) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - (void)method; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(method, false); + + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(method->core, false); + + auto kt = iface->core->owningModule->target; + auto at = method->core->owningModule->target; + + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return InterfaceAddMethodStatic(iface, method); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool InterfaceRemoveMethod(AbckitArktsInterface *iface, AbckitArktsFunction *method) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - (void)method; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(method, false); + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(method->core, false); + LIBABCKIT_INTERNAL_ERROR(method->core->owningModule, false); + + auto kt = iface->core->owningModule->target; + auto at = method->core->owningModule->target; + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return InterfaceRemoveMethodStatic(iface->core, method->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool InterfaceSetOwningModule(AbckitArktsInterface *iface, AbckitArktsModule *module) { - LIBABCKIT_UNIMPLEMENTED; - (void)iface; - (void)module; - return false; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + LIBABCKIT_TIME_EXEC; + + LIBABCKIT_BAD_ARGUMENT(iface, false); + LIBABCKIT_BAD_ARGUMENT(module, false); + LIBABCKIT_INTERNAL_ERROR(iface->core, false); + LIBABCKIT_INTERNAL_ERROR(iface->core->owningModule, false); + LIBABCKIT_INTERNAL_ERROR(module->core, false); + + auto kt = iface->core->owningModule->target; + auto at = module->core->target; + LIBABCKIT_CHECK_SAME_TARGET_RETURN(kt, at, false); + + switch (kt) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return false; + case ABCKIT_TARGET_ARK_TS_V2: + return InterfaceSetOwningModuleStatic(iface->core, module->core); + default: + LIBABCKIT_UNREACHABLE; + } } extern "C" bool InterfaceSetParentFunction(AbckitArktsInterface *iface, AbckitArktsFunction *func) @@ -477,11 +842,24 @@ extern "C" bool InterfaceSetParentFunction(AbckitArktsInterface *iface, AbckitAr return false; } -extern "C" AbckitArktsInterface *CreateInterface(const char *name) +extern "C" AbckitArktsInterface *CreateInterface(AbckitArktsModule *m, const char *name) { - LIBABCKIT_UNIMPLEMENTED; - (void)name; - return nullptr; + LIBABCKIT_CLEAR_LAST_ERROR; + LIBABCKIT_IMPLEMENTED; + + LIBABCKIT_BAD_ARGUMENT(m, nullptr); + LIBABCKIT_BAD_ARGUMENT(name, nullptr); + LIBABCKIT_INTERNAL_ERROR(m->core, nullptr); + + switch (m->core->target) { + case ABCKIT_TARGET_ARK_TS_V1: + statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED); + return nullptr; + case ABCKIT_TARGET_ARK_TS_V2: + return CreateInterfaceStatic(m, name); + default: + LIBABCKIT_UNREACHABLE; + } } // ======================================== diff --git a/libabckit/tests/BUILD.gn b/libabckit/tests/BUILD.gn index d46879f919c6026a90bdb34e17ac69ad3e9c79cf..102380c0fb0b1747d55642c1e44024828c4a8a2f 100644 --- a/libabckit/tests/BUILD.gn +++ b/libabckit/tests/BUILD.gn @@ -43,6 +43,7 @@ template("create_merge_file") { } abckit_gtests_sources = [ + "ut/extensions/arkts/modify_api/interfaces/interface_test.cpp", "adapter_static/ir_static_test.cpp", "adapter_static/runtime_adapter_static_test.cpp", "clean_scenarios/c_api/dynamic/add_log/add_log_dynamic_test.cpp", @@ -113,6 +114,12 @@ abckit_gtests_sources = [ "ut/extensions/arkts/inspect_api/namespace/namespace_arkts.cpp", "ut/extensions/arkts/inspect_api/helpers/helpers_static_test.cpp", "ut/extensions/arkts/modify_api/annotations/annotations_test.cpp", + "ut/extensions/arkts/modify_api/class/class_api_modify_static.cpp", + "ut/extensions/arkts/modify_api/class/class_static_modify_test.cpp", + "ut/extensions/arkts/modify_api/interface/interface_static_test.cpp", + "ut/extensions/arkts/modify_api/interfaces/interface_add_field_static.cpp", + "ut/extensions/arkts/modify_api/interfaces/interfaces_static_modify_test.cpp", + "ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.cpp", "ut/extensions/arkts/modify_api/modules/modules_dynamic_modify_test.cpp", "ut/extensions/js/inspect_api/api_casts/api_casts.cpp", "ut/extensions/js/inspect_api/enumerators/enumerators_test.cpp", @@ -439,6 +446,7 @@ test_ts_files = [ "ut/extensions/arkts/inspect_api/api_casts/api_casts", "ut/extensions/arkts/inspect_api/namespace/namespace_arkts_dynamic", "ut/extensions/arkts/inspect_api/helpers/helpers_dynamic_test", + "ut/extensions/arkts/modify_api/class/myclass", "regression/issue_IB1YEI/issue_IB1YEI", "regression/issue_IB2T4M/issue_IB2T4M", ] @@ -521,6 +529,25 @@ test_ets_files = [ "ut/extensions/arkts/inspect_api/methods/methods_static", "ut/extensions/arkts/modify_api/modules/modules_static_modify", "ut/extensions/arkts/inspect_api/helpers/helpers_static_test", + "ut/extensions/arkts/modify_api/class/class_add_method_static", + "ut/extensions/arkts/modify_api/class/class_add_method_static_extral", + "ut/extensions/arkts/modify_api/class/class_interface", + "ut/extensions/arkts/modify_api/class/class_remove_field", + "ut/extensions/arkts/modify_api/class/class_remove_field_static_delete", + "ut/extensions/arkts/modify_api/class/class_static_modify", + "ut/extensions/arkts/modify_api/class/classset_static", + "ut/extensions/arkts/modify_api/class/interface", + "ut/extensions/arkts/modify_api/class/suclass", + "ut/extensions/arkts/modify_api/class/super_class", + "ut/extensions/arkts/modify_api/interface/addsuperinterface", + "ut/extensions/arkts/modify_api/interface/interfaceset_static", + "ut/extensions/arkts/modify_api/interface/removesuperinterface", + "ut/extensions/arkts/modify_api/interfaces/interface", + "ut/extensions/arkts/modify_api/interfaces/interface_add_field_static", + "ut/extensions/arkts/modify_api/interfaces/interface_add_method_static", + "ut/extensions/arkts/modify_api/interfaces/interface_add_method_static_extral", + "ut/extensions/arkts/modify_api/interfaces/interface_remove_field_static", + "ut/extensions/arkts/modify_api/interfaces/static_interface_set_name", "internal/implementation_api/abc_static", "internal/mem_manager/abc_static_1", @@ -850,6 +877,7 @@ libabckit_host_unittest_action("abckit_mock_gtests") { "mock/tests/arkts/cpp_api_annotation_interface.cpp", "mock/tests/arkts/cpp_api_class.cpp", "mock/tests/arkts/cpp_api_function.cpp", + "mock/tests/arkts/cpp_api_interface.cpp", "mock/tests/arkts/cpp_api_module.cpp", "mock/tests/arkts/cpp_api_namespace.cpp", "mock/tests/core/cpp_api_annotation.cpp", diff --git a/libabckit/tests/helpers/helpers.cpp b/libabckit/tests/helpers/helpers.cpp index 24320c94bef32d6473f16c2281c2bda7a1ac8bc3..b642452b87cd6246424ff8c6d77fa06179753263 100644 --- a/libabckit/tests/helpers/helpers.cpp +++ b/libabckit/tests/helpers/helpers.cpp @@ -436,6 +436,15 @@ void AssertExportVisitor([[maybe_unused]] AbckitCoreExportDescriptor *ed, [[mayb EXPECT_TRUE(data != nullptr); } +void AssertFieldVisitor(AbckitCoreClassField *field, void *data) +{ + EXPECT_TRUE(field != nullptr); + EXPECT_TRUE(field->owner != nullptr); + EXPECT_TRUE(field->owner->owningModule != nullptr); + EXPECT_TRUE(field->owner->owningModule->file != nullptr); + EXPECT_TRUE(data != nullptr); +} + void AssertClassVisitor([[maybe_unused]] AbckitCoreClass *klass, [[maybe_unused]] void *data) { EXPECT_TRUE(klass != nullptr); @@ -495,6 +504,19 @@ bool ClassByNameFinder(AbckitCoreClass *klass, void *data) return true; } +bool ClassFieldFinder(AbckitCoreClassField *field, void *data) +{ + AssertFieldVisitor(field, data); + + auto ctxFinder = reinterpret_cast(data); + auto name = helpers::AbckitStringToString(g_implI->classFieldGetName(field)); + if (name == ctxFinder->name) { + ctxFinder->filed = field; + return false; + } + return true; +} + bool NamespaceByNameFinder(AbckitCoreNamespace *n, void *data) { AssertNamespaceVisitor(n, data); @@ -529,14 +551,14 @@ bool InterfaceByNameFinder(AbckitCoreInterface *iface, void *data) auto ctxFinder = reinterpret_cast(data); auto name = helpers::AbckitStringToString(g_implI->interfaceGetName(iface)); if (name == ctxFinder->name) { - ctxFinder->face = iface; + ctxFinder->iface = iface; return false; } return true; } -bool FiledByNameFinder(AbckitCoreInterfaceField *field, void *data) +bool FieldByNameFinder(AbckitCoreInterfaceField *field, void *data) { AssertFieldVisitor(field, data); diff --git a/libabckit/tests/helpers/helpers.h b/libabckit/tests/helpers/helpers.h index 8d8e965083a22cb795f821290810fd527352bb1c..aaed28ad15a375962d4981896427e155303a4520 100644 --- a/libabckit/tests/helpers/helpers.h +++ b/libabckit/tests/helpers/helpers.h @@ -257,7 +257,7 @@ struct AnnotationByNameContext { }; struct InterfaceByNameContext { - AbckitCoreInterface *face; + AbckitCoreInterface *iface; const char *name; }; @@ -265,12 +265,18 @@ struct FieldByNameContext { AbckitCoreInterfaceField *field; const char *name; }; +struct CoreClassField { + AbckitCoreClassField *filed; + const char *name; +}; + AbckitCoreFunction *FindMethodByName(AbckitFile *file, const std::string &name); AbckitCoreNamespace *FindNamespaceByName(AbckitFile *file, const std::string &name); bool ModuleByNameFinder(AbckitCoreModule *module, void *data); bool ImportByAliasFinder(AbckitCoreImportDescriptor *id, void *data); bool ExportByAliasFinder(AbckitCoreExportDescriptor *ed, void *data); bool ClassByNameFinder(AbckitCoreClass *klass, void *data); +bool InterfaceByNameFinder(AbckitCoreInterface *iface, void *data); bool NamespaceByNameFinder(AbckitCoreNamespace *n, void *data); bool MethodByNameFinder(AbckitCoreFunction *method, void *data); bool AnnotationInterfaceByNameFinder(AbckitCoreAnnotationInterface *ai, void *data); @@ -294,7 +300,8 @@ std::optional GetNamespaceByName(const abckit::core::Mo std::optional GetFunctionByName(const abckit::core::Module &module, const std::string &name); bool InterfaceByNameFinder(AbckitCoreInterface *iface, void *data); -bool FiledByNameFinder(AbckitCoreInterfaceField *field, void *data); +bool FieldByNameFinder(AbckitCoreInterfaceField *field, void *data); +bool ClassFieldFinder(AbckitCoreClassField *field, void *data); } // namespace libabckit::test::helpers #endif // LIBABCKIT_TESTS_HELPERS diff --git a/libabckit/tests/helpers/helpers_nullptr.cpp b/libabckit/tests/helpers/helpers_nullptr.cpp index 56d0a6d337e55b69ed64ea3490a68b0fda2353d9..cc91c1b636d4fe0c5670d052ca7495d2c2bded53 100644 --- a/libabckit/tests/helpers/helpers_nullptr.cpp +++ b/libabckit/tests/helpers/helpers_nullptr.cpp @@ -42,6 +42,10 @@ namespace libabckit::test::helpers_nullptr { [[maybe_unused]] static AbckitArktsClass *g_abckitArktsClass = reinterpret_cast(0x1); [[maybe_unused]] static AbckitArktsExportDescriptor *g_abckitArktsExportdescriptor = reinterpret_cast(0x1); +[[maybe_unused]] static AbckitArktsClassField *g_abckitArktsClassField = reinterpret_cast(0x1); +[[maybe_unused]] static AbckitArktsInterface *g_abckitArktsInterface = reinterpret_cast(0x1); +[[maybe_unused]] static AbckitArktsInterfaceField *g_abckitArktsInterfaceField = + reinterpret_cast(0x1); [[maybe_unused]] static AbckitArktsImportDescriptor *g_abckitArktsImportdescriptor = reinterpret_cast(0x1); [[maybe_unused]] static AbckitArktsFunction *g_abckitArktsMethod = reinterpret_cast(0x1); @@ -569,6 +573,78 @@ void TestNullptr(void (*apiToCheck)(AbckitArktsClass *, AbckitArktsAnnotation *) apiToCheck(klass.get(), anno.get()); ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_WRONG_TARGET); } +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsFunction *)) +{ + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsMethod), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsClass, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsClassField *)) +{ + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsClassField), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsClass, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, const char *)) +{ + ASSERT_EQ(apiToCheck(nullptr, GetConstChar()), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsInterface, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, AbckitArktsFunction *)) +{ + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsMethod), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsInterface, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, AbckitArktsInterfaceField *)) +{ + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsInterfaceField), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsInterface, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, const char *)) +{ + ASSERT_EQ(apiToCheck(nullptr, GetConstChar()), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsClass, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsModule *)) +{ + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsModule), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsClass, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, AbckitArktsInterface *)) +{ + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsInterface), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsInterface, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, AbckitArktsModule *)) +{ + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsModule), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsInterface, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} void TestNullptr(AbckitArktsAnnotation *(*apiToCheck)(AbckitArktsFunction *, const AbckitArktsAnnotationCreateParams *)) { ASSERT_EQ(apiToCheck(nullptr, g_constAbckitArktsAnnotationcreateparams), nullptr); @@ -3133,4 +3209,49 @@ void TestNullptr(const AbckitIsaApiDynamic *(*apiToCheck)(AbckitApiVersion versi ASSERT_EQ(apiToCheck(static_cast(-1)), nullptr); ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_UNKNOWN_API_VERSION); } +void TestNullptr(AbckitArktsClass *(*apiToCheck)(AbckitArktsModule *, const char *)) +{ + ASSERT_EQ(apiToCheck(nullptr, nullptr), nullptr); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsModule, nullptr), nullptr); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(nullptr, "test"), nullptr); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsInterface *)) +{ + ASSERT_EQ(apiToCheck(nullptr, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsClass, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsInterface), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsClass *)) +{ + ASSERT_EQ(apiToCheck(nullptr, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsClass, nullptr), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(nullptr, g_abckitArktsClass), false); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} +void TestNullptr(AbckitArktsInterface *(*apiToCheck)(AbckitArktsModule *, const char *)) +{ + ASSERT_EQ(apiToCheck(nullptr, nullptr), nullptr); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(g_abckitArktsModule, nullptr), nullptr); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + + ASSERT_EQ(apiToCheck(nullptr, "test"), nullptr); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); +} + } // namespace libabckit::test::helpers_nullptr diff --git a/libabckit/tests/helpers/helpers_nullptr.h b/libabckit/tests/helpers/helpers_nullptr.h index 32118b1dc5c7329d50219122937016226828c5fe..45c904214dd586358e88d4322b363aee10ba6a43 100644 --- a/libabckit/tests/helpers/helpers_nullptr.h +++ b/libabckit/tests/helpers/helpers_nullptr.h @@ -55,8 +55,17 @@ void TestNullptr(void (*apiToCheck)(AbckitArktsAnnotationInterface *, AbckitArkt void TestNullptr(void (*apiToCheck)(AbckitArktsAnnotation *, AbckitArktsAnnotationElement *)); void TestNullptr(AbckitArktsAnnotation *(*apiToCheck)(AbckitArktsClass *, const AbckitArktsAnnotationCreateParams *)); void TestNullptr(void (*apiToCheck)(AbckitArktsClass *, AbckitArktsAnnotation *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, const char *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsClassField *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsModule *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, AbckitArktsInterface *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, AbckitArktsFunction *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, AbckitArktsModule *)); void TestNullptr(AbckitArktsAnnotation *(*apiToCheck)(AbckitArktsFunction *, const AbckitArktsAnnotationCreateParams *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsFunction *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, const char *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsInterface *, AbckitArktsInterfaceField *)); void TestNullptr(void (*apiToCheck)(AbckitArktsFunction *, AbckitArktsAnnotation *)); void TestNullptr(AbckitArktsAnnotationInterface *(*apiToCheck)(AbckitArktsModule *, const AbckitArktsAnnotationInterfaceCreateParams *)); @@ -362,6 +371,10 @@ void TestNullptr(AbckitType *(*apiToCheck)(AbckitCoreNamespaceField *)); void TestNullptr(const AbckitInspectApi *(*apiToCheck)(AbckitApiVersion version)); void TestNullptr(const AbckitApi *(*apiToCheck)(AbckitApiVersion version)); void TestNullptr(const AbckitIsaApiDynamic *(*apiToCheck)(AbckitApiVersion version)); +void TestNullptr(AbckitArktsClass *(*apiToCheck)(AbckitArktsModule *, const char *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsInterface *)); +void TestNullptr(bool (*apiToCheck)(AbckitArktsClass *, AbckitArktsClass *)); +void TestNullptr(AbckitArktsInterface *(*apiToCheck)(AbckitArktsModule *, const char *)); } // namespace libabckit::test::helpers_nullptr diff --git a/libabckit/tests/mock/arkts_modify_api_impl_mock.cpp b/libabckit/tests/mock/arkts_modify_api_impl_mock.cpp index 29b2e3cb129e70602b82a48dae478301722e82c4..227b3841e226b075b76a09b1cbbb0ebba7984b00 100644 --- a/libabckit/tests/mock/arkts_modify_api_impl_mock.cpp +++ b/libabckit/tests/mock/arkts_modify_api_impl_mock.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -152,7 +152,7 @@ bool ClassSetName(AbckitArktsClass *klass, const char *name) { g_calledFuncs.push(__func__); EXPECT_TRUE(klass == DEFAULT_ARKTS_CLASS); - EXPECT_TRUE(name == DEFAULT_CONST_CHAR); + EXPECT_TRUE(strncmp(name, DEFAULT_CONST_CHAR, DEFAULT_CONST_CHAR_SIZE) == 0); return DEFAULT_BOOL; } @@ -188,10 +188,11 @@ bool ClassRemoveMethod(AbckitArktsClass *klass, AbckitArktsFunction *method) return DEFAULT_BOOL; } -AbckitArktsClass *CreateClass(const char *name) +AbckitArktsClass *CreateClass(AbckitArktsModule *m, const char *name) { g_calledFuncs.push(__func__); - EXPECT_TRUE(name == DEFAULT_CONST_CHAR); + EXPECT_TRUE(m == DEFAULT_ARKTS_MODULE); + EXPECT_TRUE(strcmp(name, DEFAULT_CONST_CHAR) == 0); return DEFAULT_ARKTS_CLASS; } @@ -231,7 +232,7 @@ bool InterfaceSetName(AbckitArktsInterface *iface, const char *name) { g_calledFuncs.push(__func__); EXPECT_TRUE(iface == DEFAULT_ARKTS_INTERFACE); - EXPECT_TRUE(name == DEFAULT_CONST_CHAR); + EXPECT_TRUE(strcmp(name, DEFAULT_CONST_CHAR) == 0); return DEFAULT_BOOL; } @@ -283,10 +284,11 @@ bool InterfaceSetParentFunction(AbckitArktsInterface *iface, AbckitArktsFunction return DEFAULT_BOOL; } -AbckitArktsInterface *CreateInterface(const char *name) +AbckitArktsInterface *CreateInterface(AbckitArktsModule *md, const char *name) { g_calledFuncs.push(__func__); - EXPECT_TRUE(name == DEFAULT_CONST_CHAR); + EXPECT_TRUE(md == DEFAULT_ARKTS_MODULE); + EXPECT_TRUE(strcmp(name, DEFAULT_CONST_CHAR) == 0); return DEFAULT_ARKTS_INTERFACE; } diff --git a/libabckit/tests/mock/cpp_helpers_mock.h b/libabckit/tests/mock/cpp_helpers_mock.h index a5761336a342f256da6c81f96e8c56a2d8a8dac1..1e21aaa2beae0d4c8d6062fd31e8df6ce3461a45 100644 --- a/libabckit/tests/mock/cpp_helpers_mock.h +++ b/libabckit/tests/mock/cpp_helpers_mock.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -116,6 +116,13 @@ inline abckit::core::Interface GetMockCoreInterface(const abckit::File &file) return interfaces.front(); } +inline abckit::arkts::Interface GetMockArktsInterface(const abckit::File &file) +{ + auto i = abckit::arkts::Interface(GetMockCoreInterface(file)); + EXPECT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + return i; +} + inline abckit::core::Enum GetMockCoreEnum(const abckit::File &file) { abckit::core::Module cmd = GetMockCoreModule(file); @@ -132,6 +139,24 @@ inline abckit::core::Enum GetMockCoreEnum(const abckit::File &file) return enums.front(); } +inline abckit::core::Function GetMockCoreInterfaceMethod(const abckit::File &file) +{ + auto cf = GetMockCoreInterface(file); + std::vector functions = cf.GetAllMethods(); + + EXPECT_TRUE(CheckMockedApi("InterfaceEnumerateMethods")); + + return functions.front(); +} + +inline abckit::arkts::Function GetMockArktsInterfaceMethod(const abckit::File &file) +{ + auto cf = GetMockCoreInterfaceMethod(file); + auto fn = abckit::arkts::Function(cf); + EXPECT_TRUE(CheckMockedApi("CoreFunctionToArktsFunction")); + return fn; +} + inline abckit::core::Function GetMockCoreFunction(const abckit::File &file) { abckit::core::Class cls = GetMockCoreClass(file); @@ -176,6 +201,22 @@ inline abckit::arkts::Annotation GetMockArktsAnnotation(const abckit::File &file return a; } +inline abckit::core::ClassField GetMockCoreClassField(const abckit::File &file) +{ + abckit::core::Class cls = GetMockCoreClass(file); + std::vector fields = cls.GetFields(); + + EXPECT_TRUE(CheckMockedApi("ClassEnumerateFields")); + return fields.front(); +} + +inline abckit::arkts::ClassField GetMockArktsFiled(const abckit::File &file) +{ + auto a = abckit::arkts::ClassField(GetMockCoreClassField(file)); + EXPECT_TRUE(CheckMockedApi("CoreClassFieldToArktsClassField")); + return a; +} + inline abckit::Graph GetMockGraph(const abckit::File &file) { abckit::core::Function func = GetMockCoreFunction(file); @@ -239,6 +280,20 @@ inline abckit::LiteralArray GetMockLiteralArray(const abckit::File &file) return litarr; } +inline abckit::arkts::ClassField GetMockArktsClassField(const abckit::File &file) +{ + auto cf = abckit::arkts::ClassField(GetMockCoreClassField(file)); + EXPECT_TRUE(CheckMockedApi("CoreClassFieldToArktsClassField")); + return cf; +} + +inline abckit::arkts::Function GetMockArktsClassMothed(const abckit::File &file) +{ + auto fn = abckit::arkts::Function(GetMockCoreFunction(file)); + EXPECT_TRUE(CheckMockedApi("CoreFunctionToArktsFunction")); + return fn; +} + inline abckit::Type GetMockType(const abckit::File &file) { abckit::Type t = file.CreateType(DEFAULT_TYPE_ID); @@ -412,6 +467,23 @@ inline abckit::arkts::AnnotationInterfaceField GetMockArktsAnnotationInterfaceFi return aif; } +inline abckit::core::InterfaceField GetMockCoreInterfaceField(const abckit::File &file) +{ + auto iface = GetMockCoreInterface(file); + std::vector fields; + + fields = iface.GetFields(); + EXPECT_TRUE(CheckMockedApi("InterfaceEnumerateFields")); + return fields.front(); +} + +inline abckit::arkts::InterfaceField GetMockArktsInterfaceField(const abckit::File &file) +{ + auto fd = abckit::arkts::InterfaceField(GetMockCoreInterfaceField(file)); + EXPECT_TRUE(CheckMockedApi("CoreInterfaceFieldToArktsInterfaceField")); + return fd; +} + // NOLINTEND(performance-unnecessary-value-param) } // namespace abckit::mock::helpers diff --git a/libabckit/tests/mock/tests/arkts/cpp_api_class.cpp b/libabckit/tests/mock/tests/arkts/cpp_api_class.cpp index e4610c2fc3343fb96fc510fdba0d31f2633e063c..6b167ad159881236077e0b9b6702ce24631cb2d0 100644 --- a/libabckit/tests/mock/tests/arkts/cpp_api_class.cpp +++ b/libabckit/tests/mock/tests/arkts/cpp_api_class.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024 Huawei Device Co., Ltd. + * Copyright (c) 2024-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 @@ -58,4 +58,164 @@ TEST_F(LibAbcKitCppMockArktsTestClass, Class_AddAnnotation) ASSERT_TRUE(CheckMockedStackEmpty()); } +// Test: test-kind=mock, api=Class::AddInterface, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_AddInterface) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsClass(f).AddInterface(abckit::mock::helpers::GetMockArktsInterface(f)); + ASSERT_TRUE(CheckMockedApi("ClassAddInterface")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::RemoveInterface, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_RemoveInterface) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsClass(f).RemoveInterface(abckit::mock::helpers::GetMockArktsInterface(f)); + ASSERT_TRUE(CheckMockedApi("ClassRemoveInterface")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::SetSuperClass, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_SetSuperClass) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsClass(f).SetSuperClass(abckit::mock::helpers::GetMockArktsClass(f)); + ASSERT_TRUE(CheckMockedApi("ClassSetSuperClass")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::AddMethod, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_AddMethod) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsClass(f).AddMethod(abckit::mock::helpers::GetMockArktsFunction(f)); + ASSERT_TRUE(CheckMockedApi("ClassAddMethod")); + ASSERT_TRUE(CheckMockedApi("CoreFunctionToArktsFunction")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::RemoveMethod, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_RemoveMethod) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsClass(f).RemoveMethod(abckit::mock::helpers::GetMockArktsFunction(f)); + ASSERT_TRUE(CheckMockedApi("ClassRemoveMethod")); + ASSERT_TRUE(CheckMockedApi("CoreFunctionToArktsFunction")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::CreateClass, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_CreateClass) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::arkts::Class::CreateClass(abckit::mock::helpers::GetMockArktsModule(f), DEFAULT_CONST_CHAR); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + ASSERT_TRUE(CheckMockedApi("ArktsClassToCoreClass")); + ASSERT_TRUE(CheckMockedApi("CreateClass")); + ASSERT_TRUE(CheckMockedApi("CoreModuleToArktsModule")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::RemoveField, abc-kind=ArkTS1, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_RemoveField) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + auto ae = abckit::mock::helpers::GetMockArktsClassField(f); + abckit::mock::helpers::GetMockArktsClass(f).RemoveField(ae); + ASSERT_TRUE(CheckMockedApi("ClassRemoveField")); + ASSERT_TRUE(CheckMockedApi("CoreClassFieldToArktsClassField")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::SetName, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_SetName) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsClass(f).SetName(DEFAULT_CONST_CHAR); + ASSERT_TRUE(CheckMockedApi("ClassSetName")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::AddField, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_AddField) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsClass(f).AddField(abckit::mock::helpers::GetMockArktsFiled(f)); + ASSERT_TRUE(CheckMockedApi("ClassAddField")); + ASSERT_TRUE(CheckMockedApi("CoreClassFieldToArktsClassField")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Class::SetOwningModule, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestClass, Class_SetOwningModule) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsClass(f).SetOwningModule(abckit::mock::helpers::GetMockArktsModule(f)); + ASSERT_TRUE(CheckMockedApi("ClassSetOwningModule")); + ASSERT_TRUE(CheckMockedApi("CoreModuleToArktsModule")); + ASSERT_TRUE(CheckMockedApi("CoreClassToArktsClass")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} } // namespace libabckit::cpp_test \ No newline at end of file diff --git a/libabckit/tests/mock/tests/arkts/cpp_api_interface.cpp b/libabckit/tests/mock/tests/arkts/cpp_api_interface.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e6a133a7c2a390ee8040a9d19a8972ffb119e12c --- /dev/null +++ b/libabckit/tests/mock/tests/arkts/cpp_api_interface.cpp @@ -0,0 +1,176 @@ +/* + * 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/libabckit/cpp/abckit_cpp.h" +#include "src/mock/mock_values.h" +#include "tests/mock/check_mock.h" +#include "tests/mock/cpp_helpers_mock.h" + +namespace libabckit::cpp_test { + +class LibAbcKitCppMockArktsTestInterface : public ::testing::Test {}; + +// Test: test-kind=mock, api=Interface::RemoveField, abc-kind=ArkTS1, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_RemoveField) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + auto ae = abckit::mock::helpers::GetMockArktsInterfaceField(f); + abckit::mock::helpers::GetMockArktsInterface(f).RemoveField(ae); + ASSERT_TRUE(CheckMockedApi("InterfaceRemoveField")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceFieldToArktsInterfaceField")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Interface::CreateInterface, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_CreateInterface) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::arkts::Interface::CreateInterface(abckit::mock::helpers::GetMockArktsModule(f), DEFAULT_CONST_CHAR); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + ASSERT_TRUE(CheckMockedApi("ArktsInterfaceToCoreInterface")); + ASSERT_TRUE(CheckMockedApi("CreateInterface")); + ASSERT_TRUE(CheckMockedApi("CoreModuleToArktsModule")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Interface::SetName, abc-kind=ArkTS1, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_SetName) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsInterface(f).SetName(DEFAULT_CONST_CHAR); + ASSERT_TRUE(CheckMockedApi("InterfaceSetName")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Interface::AddField, abc-kind=ArkTS1, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_AddField) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + auto ae = abckit::mock::helpers::GetMockArktsInterfaceField(f); + abckit::mock::helpers::GetMockArktsInterface(f).AddField(ae); + ASSERT_TRUE(CheckMockedApi("InterfaceAddField")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceFieldToArktsInterfaceField")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Interface::AddMethod, abc-kind=ArkTS1, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_AddMethod) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + auto ae = abckit::mock::helpers::GetMockArktsInterfaceMethod(f); + abckit::mock::helpers::GetMockArktsInterface(f).AddMethod(ae); + ASSERT_TRUE(CheckMockedApi("InterfaceAddMethod")); + ASSERT_TRUE(CheckMockedApi("CoreFunctionToArktsFunction")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Interface::AddSuperInterface, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_AddSuperInterface) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsInterface(f).AddSuperInterface( + abckit::mock::helpers::GetMockArktsInterface(f)); + ASSERT_TRUE(CheckMockedApi("InterfaceAddSuperInterface")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Interface::RemoveSuperInterface, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_RemoveSuperInterface) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsInterface(f).RemoveSuperInterface( + abckit::mock::helpers::GetMockArktsInterface(f)); + ASSERT_TRUE(CheckMockedApi("InterfaceRemoveSuperInterface")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Interface::RemoveMethod, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_RemoveMethod) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsInterface(f).RemoveMethod(abckit::mock::helpers::GetMockArktsFunction(f)); + ASSERT_TRUE(CheckMockedApi("InterfaceRemoveMethod")); + ASSERT_TRUE(CheckMockedApi("CoreFunctionToArktsFunction")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +// Test: test-kind=mock, api=Interface::SetOwningModule, abc-kind=ArkTS2, category=internal, extension=cpp +TEST_F(LibAbcKitCppMockArktsTestInterface, Interface_SetOwningModule) +{ + ASSERT_TRUE(CheckMockedStackEmpty()); + { + abckit::File f(DEFAULT_PATH); + ASSERT_TRUE(CheckMockedApi("OpenAbc")); + abckit::mock::helpers::GetMockArktsInterface(f).SetOwningModule(abckit::mock::helpers::GetMockArktsModule(f)); + ASSERT_TRUE(CheckMockedApi("InterfaceSetOwningModule")); + ASSERT_TRUE(CheckMockedApi("CoreModuleToArktsModule")); + ASSERT_TRUE(CheckMockedApi("CoreInterfaceToArktsInterface")); + } + ASSERT_TRUE(CheckMockedApi("CloseFile")); + ASSERT_TRUE(CheckMockedStackEmpty()); +} + +} // namespace libabckit::cpp_test diff --git a/libabckit/tests/null_args_tests/null_args_tests_ArktsModifyApiImpl_0.cpp b/libabckit/tests/null_args_tests/null_args_tests_ArktsModifyApiImpl_0.cpp index 7e5c05b0516e5e81d2db632a10715ceb52d70134..c7b95c497291374b46aa384f9dbf129bece89d0d 100644 --- a/libabckit/tests/null_args_tests/null_args_tests_ArktsModifyApiImpl_0.cpp +++ b/libabckit/tests/null_args_tests/null_args_tests_ArktsModifyApiImpl_0.cpp @@ -76,6 +76,83 @@ TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classRemoveAnnotation) helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classRemoveAnnotation); } +// Test: test-kind=api, api=ArktsModifyApiImpl::classRemoveField, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classRemoveField) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classRemoveField); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classAddMethod, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classAddMethod) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classAddMethod); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::interfaceAddField, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, interfaceAddField) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->interfaceAddField); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::interfaceAddMethod, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, interfaceAddMethod) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->interfaceAddMethod); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classSetName, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classSetName) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classSetName); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classAddField, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classAddField) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classAddField); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classSetOwningModule, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classSetOwningModule) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classSetOwningModule); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::interfaceAddSuperInterface, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, interfaceAddSuperInterface) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->interfaceAddSuperInterface); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::interfaceRemoveSuperInterface, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, interfaceRemoveSuperInterface) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->interfaceRemoveSuperInterface); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::interfaceRemoveMethod, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, interfaceRemoveMethod) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->interfaceRemoveMethod); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::interfaceSetOwningModule, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, interfaceSetOwningModule) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->interfaceSetOwningModule); +} + // Test: test-kind=api, api=ArktsModifyApiImpl::fileAddExternalModuleArktsV1, // abc-kind=NoABC, category=negative-nullptr, extension=c TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, fileAddExternalModuleArktsV1) @@ -90,6 +167,13 @@ TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, functionAddAnnotation) helpers_nullptr::TestNullptr(g_arktsModifyApiImp->functionAddAnnotation); } +// Test: test-kind=api, api=ArktsModifyApiImpl::interfaceSetName, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, interfaceSetName) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->interfaceSetName); +} + // Test: test-kind=api, api=ArktsModifyApiImpl::functionRemoveAnnotation, // abc-kind=NoABC, category=negative-nullptr, extension=c TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, functionRemoveAnnotation) @@ -139,4 +223,53 @@ TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, AbckitGetArktsModifyApiImpl) helpers_nullptr::TestNullptr(AbckitGetArktsModifyApiImpl); } +// Test: test-kind=api, api=ArktsModifyApiImpl::interfaceRemoveField, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, interfaceRemoveField) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->interfaceRemoveField); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::createClass, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, createClass) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->createClass); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classRemoveMethod, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classRemoveMethod) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classRemoveMethod); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classAddInterface, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classAddInterface) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classAddInterface); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classRemoveInterface, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classRemoveInterface) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classRemoveInterface); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classSetSuperClass, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, classSetSuperClass) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->classSetSuperClass); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::createInterface, +// abc-kind=NoABC, category=negative-nullptr, extension=c +TEST_F(LibAbcKitNullptrTestsArktsModifyApiImpl0, createInterface) +{ + helpers_nullptr::TestNullptr(g_arktsModifyApiImp->createInterface); +} + } // namespace libabckit::test diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/class_add_method_static.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_add_method_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..95b658a828767a68f85e3bd777cea05876e7db9e --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_add_method_static.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. + */ + +function sayHello(num: number): void { + return; +} + +class Person { + age: number; + private _id: number; + + constructor(age: number) { + this.age = age; + this._id = Math.random(); + } + + static sayHello(): void { + console.log('hello'); + } + + // Getter/Setter + public get id(): number { + return this._id; + } +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/class_add_method_static_extral.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_add_method_static_extral.ets new file mode 100644 index 0000000000000000000000000000000000000000..26a835f229abdc029712647917e47e6270493d06 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_add_method_static_extral.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. + */ + +function sayHello(): void { + console.log('hello'); +} + +class Person { +} + +function main() { + console.log('hi'); +} + diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/class_api_modify_static.cpp b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_api_modify_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9aed545d6291aeaa2354b5881ca31f34c77c9723 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_api_modify_static.cpp @@ -0,0 +1,232 @@ +/** + * 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 +#include +#include + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "libabckit/include/libabckit/c/abckit.h" +#include "libabckit/include/libabckit/c/declarations.h" +#include "libabckit/include/libabckit/c/extensions/arkts/metadata_arkts.h" +#include "libabckit/include/libabckit/c/metadata_core.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/logger.h" +#include "libabckit/src/metadata_inspect_impl.h" + +namespace libabckit::test { + +static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkI = AbckitGetArktsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkM = AbckitGetArktsModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_staticG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0); + +class LibAbcKitModifyClassApiTests : public ::testing::Test {}; + +struct CaptureData { + AbckitGraph *graph = nullptr; + AbckitCoreFunction *mainFunc = nullptr; + AbckitCoreFunction *targetFunc = nullptr; +}; + +void ClassAddIfaceTransformMainIr(AbckitCoreFunction *mainFunction, AbckitCoreFunction *targetFunc) +{ + AbckitGraph *graph = g_implI->createGraphFromFunction(mainFunction); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + CaptureData capData; + capData.graph = graph; + capData.targetFunc = targetFunc; + g_implG->gVisitBlocksRpo(graph, &capData, [](AbckitBasicBlock *bb, void *data) -> bool { + CaptureData *capData = reinterpret_cast(data); + for (auto inst = g_implG->bbGetFirstInst(bb); inst != nullptr; inst = g_implG->iGetNext(inst)) { + if (g_staticG->iGetOpcode(inst) == ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID) { + auto newInst = g_staticG->iCreateCallStatic(capData->graph, capData->targetFunc, 0); + g_implG->iInsertBefore(newInst, inst); + } + } + return true; + }); + + g_implM->functionSetGraph(mainFunction, graph); + g_impl->destroyGraph(graph); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); +} + +TEST_F(LibAbcKitModifyClassApiTests, ClassRemoveFieldTest0) +{ + std::string input1 = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_remove_field_static_delete.abc"; + std::string removeCallPath = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_remove_field_static_del.abc"; + std::string removeCallPath1 = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_remove_field_static_del_1.abc"; + std::string output1 = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_remove_field_static_del_out.abc"; + + auto outPutRst = helpers::ExecuteStaticAbc(input1, "class_remove_field_static_delete", "main"); + EXPECT_TRUE(helpers::Match(outPutRst, "yyy\n")); + helpers::TransformMethod(input1, removeCallPath, "sayHello:class_remove_field_static_delete.Student;void;", + [](AbckitFile *, AbckitCoreFunction *, AbckitGraph *graph) { + auto *call = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_LOADOBJECT); + g_implG->iRemove(call); + auto *ret = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID); + auto preInst = g_implG->iGetPrev(ret); + g_implG->iRemove(preInst); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + }); + helpers::TransformMethod(removeCallPath, removeCallPath1, "_ctor_:class_remove_field_static_delete.Student;void;", + [](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) {}); + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(removeCallPath1.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_remove_field_static_delete"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "Student"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &ctxClassFinder, helpers::ClassByNameFinder); + + helpers::CoreClassField ctxClassFieldFinder = {nullptr, "addr"}; + g_implI->classEnumerateFields(ctxClassFinder.klass, &ctxClassFieldFinder, helpers::ClassFieldFinder); + + auto arkKlass = g_implArkI->coreClassToArktsClass(ctxClassFinder.klass); + auto arkField = g_implArkI->coreClassFieldToArktsClassField(ctxClassFieldFinder.filed); + g_implArkM->classRemoveField(arkKlass, arkField); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->writeAbc(file, output1.c_str(), output1.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + outPutRst = helpers::ExecuteStaticAbc(output1, "class_remove_field_static_delete", "main"); + EXPECT_TRUE(helpers::Match(outPutRst, "")); +} + +TEST_F(LibAbcKitModifyClassApiTests, ClassRemoveFieldTest1) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_remove_field.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_remove_field_static_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_remove_field"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "Anm"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &ctxClassFinder, helpers::ClassByNameFinder); + + helpers::CoreClassField ctxClassFieldFinder = {nullptr, "age"}; + g_implI->classEnumerateFields(ctxClassFinder.klass, &ctxClassFieldFinder, helpers::ClassFieldFinder); + + auto arkKlass = g_implArkI->coreClassToArktsClass(ctxClassFinder.klass); + auto arkField = g_implArkI->coreClassFieldToArktsClassField(ctxClassFieldFinder.filed); + g_implArkM->classRemoveField(arkKlass, arkField); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); +} + +TEST_F(LibAbcKitModifyClassApiTests, ClassAddMethodTest0) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_add_method_static.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_add_method_static_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_add_method_static"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::MethodByNameContext ctxMethodFinder = {nullptr, "sayHello:f64;void;", true}; + g_implI->moduleEnumerateTopLevelFunctions(ctxFinder.module, &ctxMethodFinder, helpers::MethodByNameFinder); + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "Person"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &ctxClassFinder, helpers::ClassByNameFinder); + + auto arkKlass = g_implArkI->coreClassToArktsClass(ctxClassFinder.klass); + auto arkFunc = g_implArkI->coreFunctionToArktsFunction(ctxMethodFinder.method); + + g_implArkM->classAddMethod(arkKlass, arkFunc); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); +} + +TEST_F(LibAbcKitModifyClassApiTests, ClassAddMethodTest1) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_add_method_static_extral.abc"; + std::string first = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_add_method_static_extral_first.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_add_method_static_extral_out.abc"; + + auto outputRst = helpers::ExecuteStaticAbc(input, "class_add_method_static_extral", "main"); + EXPECT_TRUE(helpers::Match(outputRst, "hi\n")); + // open input file + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_add_method_static_extral"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::MethodByNameContext ctxMethodFinder = {nullptr, "sayHello"}; + g_implI->moduleEnumerateTopLevelFunctions(ctxFinder.module, &ctxMethodFinder, helpers::MethodByNameFinder); + + helpers::ClassByNameContext ctxClassFinder = {nullptr, "Person"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &ctxClassFinder, helpers::ClassByNameFinder); + + auto arkKlass = g_implArkI->coreClassToArktsClass(ctxClassFinder.klass); + auto arkFunc = g_implArkI->coreFunctionToArktsFunction(ctxMethodFinder.method); + + g_implArkM->classAddMethod(arkKlass, arkFunc); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->writeAbc(file, first.c_str(), first.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + // open first file + helpers::AssertOpenAbc(first.c_str(), &file); + ctxFinder = {nullptr, "class_add_method_static_extral"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::MethodByNameContext mainCtxFinder = {nullptr, "main"}; + g_implI->moduleEnumerateTopLevelFunctions(ctxFinder.module, &mainCtxFinder, helpers::MethodByNameFinder); + + ctxClassFinder = {nullptr, "Person"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &ctxClassFinder, helpers::ClassByNameFinder); + + helpers::MethodByNameContext targetCtxFinder = {nullptr, "sayHello"}; + g_implI->classEnumerateMethods(ctxClassFinder.klass, &targetCtxFinder, helpers::MethodByNameFinder); + + ClassAddIfaceTransformMainIr(mainCtxFinder.method, targetCtxFinder.method); + + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + outputRst = helpers::ExecuteStaticAbc(output, "class_add_method_static_extral", "main"); + EXPECT_TRUE(helpers::Match(outputRst, "hi\nhello\n")); +} +} // namespace libabckit::test diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/class_interface.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_interface.ets new file mode 100644 index 0000000000000000000000000000000000000000..27e60489084484ab8efb5b9c00759fe9000165b5 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_interface.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. + */ + +interface MyInterface { + key: string; + value: number; + handle(): void; +} + +interface TestInterface { + testKey: string; + testValue: number; + testHandle(): void; +} + +class TestClass { + testHandle(): void + { + console.log("testHandle called"); + } +} + +class MyClass implements MyInterface { + key: string; + value: number; + + constructor(key: string, value: number) { + this.key = key; + this.value = value; + } + + handle(): void { + console.log("key: " + this.key + ", value: " + this.value); + } +} + +function main() { + let c = new MyClass("key", 0); + c.handle(); +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/class_remove_field.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_remove_field.ets new file mode 100644 index 0000000000000000000000000000000000000000..0e53b31dd237fdb1617da98e560f5b2bab1f58c5 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_remove_field.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 Anm { + name: string; + age: number; + private _id: number; + + constructor(name: string) { + this.name = name; + this._id = Math.random(); + } + + sayHello(name: string): void { + console.log('hello' + name); + } + + // Getter/Setter + get id(): number { + return this._id; + } +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/class_remove_field_static_delete.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_remove_field_static_delete.ets new file mode 100644 index 0000000000000000000000000000000000000000..4a07bd960a44eaa5df457d9343a0c46cff293b97 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_remove_field_static_delete.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 Student { + addr: string = "yyy"; + sayHello(): void { + console.log(this.addr); + } +} +function main() { + let per = new Student(); + per.sayHello(); +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/class_static_modify.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_static_modify.ets new file mode 100644 index 0000000000000000000000000000000000000000..58202581765ac165956b477659be95d483b19cc4 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_static_modify.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. + */ + +class Test { + handleUseRm() + { + console.log("handleUseRm") + } + + handleNoUseRm() + { + console.log("handleNoUseRm") + } + + test() + { + console.log("test") + } +} + +function main() { + const test = new Test() + test.handleUseRm() + test.test() +} diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/class_static_modify_test.cpp b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_static_modify_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..8f8945de32300028df3f45a3bc12ec0235ca86c2 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/class_static_modify_test.cpp @@ -0,0 +1,769 @@ +/** + * 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 "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "libabckit/c/abckit.h" +#include "libabckit/c/extensions/arkts/metadata_arkts.h" +#include "libabckit/c/isa/isa_static.h" +#include "libabckit/c/metadata_core.h" +#include "libabckit/src/adapter_static/ir_static.h" +#include "libabckit/src/adapter_static/metadata_modify_static.h" +#include "libabckit/src/metadata_inspect_impl.h" + +namespace libabckit::test { + +static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkI = AbckitGetArktsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkM = AbckitGetArktsModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_statG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); + +class LibAbcKitArkTSModifyApiClassTests : public ::testing::Test {}; + +struct CaptureData { + AbckitGraph *graph = nullptr; + AbckitCoreFunction *targetFunc = nullptr; +}; + +void SuperClassTransformCtorIr(AbckitFile *file) +{ + helpers::ModuleByNameContext ctxFinder = {nullptr, "super_class"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::MethodByNameContext funcFinder = {nullptr, "_ctor_"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &funcFinder, helpers::MethodByNameFinder); + + classCtxFinder = {nullptr, "SuClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::MethodByNameContext targetFuncFinder = {nullptr, "_ctor_"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &targetFuncFinder, helpers::MethodByNameFinder); + + AbckitGraph *graph = g_implI->createGraphFromFunction(funcFinder.method); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + CaptureData capData; + capData.graph = graph; + capData.targetFunc = targetFuncFinder.method; + g_implG->gVisitBlocksRpo(graph, &capData, [](AbckitBasicBlock *bb, void *data) -> bool { + auto *capData = reinterpret_cast(data); + for (auto inst = g_implG->bbGetFirstInst(bb); inst != nullptr; inst = g_implG->iGetNext(inst)) { + if (g_statG->iGetOpcode(inst) == ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC) { + auto newInst = g_statG->iCreateCallStatic(capData->graph, capData->targetFunc, 0); + g_implG->iInsertBefore(newInst, inst); + g_implG->iRemove(inst); + } + } + return true; + }); + + g_implM->functionSetGraph(funcFinder.method, graph); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->destroyGraph(graph); +} + +bool CallSuHandleCb(AbckitBasicBlock *bb, void *data) +{ + auto *capData = reinterpret_cast(data); + for (auto inst = g_implG->bbGetFirstInst(bb); inst != nullptr; inst = g_implG->iGetNext(inst)) { + if (g_statG->iGetOpcode(inst) == ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID) { + auto preInst = g_implG->iGetPrev(inst); + auto objRef = g_implG->iGetInput(preInst, 0); + g_implG->iRemove(preInst); + auto newInst = g_statG->iCreateCallVirtual(capData->graph, objRef, capData->targetFunc, 0); + g_implG->iInsertBefore(newInst, inst); + } + } + return true; +} + +void SuperClassTransformMainIr(AbckitFile *file) +{ + auto transformCb = [](AbckitFile *file, AbckitCoreFunction *func, AbckitGraph *graph) { + helpers::ModuleByNameContext ctxFinder = {nullptr, "super_class"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder = {nullptr, "SuClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::MethodByNameContext targetFuncFinder = {nullptr, "suHandle"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &targetFuncFinder, helpers::MethodByNameFinder); + + CaptureData capData; + capData.graph = graph; + capData.targetFunc = targetFuncFinder.method; + g_implG->gVisitBlocksRpo(graph, &capData, CallSuHandleCb); + }; + + helpers::TransformMethod(file, "main", transformCb); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::createClass, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, CreateClassTest0) +{ + auto inputPath = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify.abc"; + auto outputPath = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/create_class_out.abc"; + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(inputPath, &file); + + helpers::ModuleByNameContext mdlFinder = {nullptr, "class_static_modify"}; + g_implI->fileEnumerateModules(file, &mdlFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdlFinder.module, nullptr); + auto *module = mdlFinder.module; + + const char *className = "NewClass"; + AbckitArktsClass *arktsClass = g_implArkM->createClass(module->GetArkTSImpl(), className); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(arktsClass, nullptr); + ASSERT_NE(arktsClass->core, nullptr); + ASSERT_NE(arktsClass->core->owningModule, nullptr); + ASSERT_EQ(arktsClass->core->owningModule->target, ABCKIT_TARGET_ARK_TS_V2); + ASSERT_NE(module->ct.find(className), module->ct.end()); + ASSERT_NE(module->ct.find(className)->second, nullptr); + + g_impl->writeAbc(file, outputPath, strlen(outputPath)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(outputPath, &file); + mdlFinder = {nullptr, "class_static_modify"}; + g_implI->fileEnumerateModules(file, &mdlFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classFinder = {nullptr, className}; + g_implI->moduleEnumerateClasses(mdlFinder.module, &classFinder, helpers::ClassByNameFinder); + EXPECT_NE(classFinder.klass, nullptr); + + g_impl->closeFile(file); +} + +void ClassRemoveMethod(AbckitCoreFunction *method) +{ + auto klass = g_implI->functionGetParentClass(method); + ASSERT_TRUE(g_impl->getLastError() == ABCKIT_STATUS_NO_ERROR); + + ASSERT_TRUE(g_implArkM->classRemoveMethod(g_implArkI->coreClassToArktsClass(klass), + g_implArkI->coreFunctionToArktsFunction(method))); + ASSERT_TRUE(g_impl->getLastError() == ABCKIT_STATUS_NO_ERROR); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classRemoveMethod, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassRemoveMethodHandleNoUseRm) +{ + auto inputPath = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify.abc"; + auto outputPath = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify_handleNullptr.abc"; + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(inputPath, &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_static_modify"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder = {nullptr, "Test"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::MethodByNameContext methodCtxFinder = {nullptr, "handleNoUseRm"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::MethodByNameFinder); + EXPECT_NE(methodCtxFinder.method, nullptr); + + ClassRemoveMethod(methodCtxFinder.method); + + methodCtxFinder = {nullptr, "handleNoUseRm"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::MethodByNameFinder); + EXPECT_EQ(methodCtxFinder.method, nullptr); + + g_impl->writeAbc(file, outputPath, strlen(outputPath)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(outputPath, &file); + + ctxFinder = {nullptr, "class_static_modify"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + classCtxFinder = {nullptr, "Test"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + methodCtxFinder = {nullptr, "handleNoUseRm"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::MethodByNameFinder); + EXPECT_EQ(methodCtxFinder.method, nullptr); + + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classRemoveMethod, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassRemoveMethodHandleUseRm) +{ + auto inputPath = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify.abc"; + auto outputPath = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_remove_method_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(inputPath, &file); + helpers::TransformMethod(file, "main", + [](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) { + auto *call = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CALL_VIRTUAL); + g_implG->iRemove(call); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + }); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_static_modify"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder = {nullptr, "Test"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::MethodByNameContext methodCtxFinder = {nullptr, "handleUseRm"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::MethodByNameFinder); + EXPECT_NE(methodCtxFinder.method, nullptr); + + ClassRemoveMethod(methodCtxFinder.method); + + methodCtxFinder = {nullptr, "handleUseRm"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::MethodByNameFinder); + EXPECT_EQ(methodCtxFinder.method, nullptr); + + g_impl->writeAbc(file, outputPath, strlen(outputPath)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(outputPath, &file); + + ctxFinder = {nullptr, "class_static_modify"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + classCtxFinder = {nullptr, "Test"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + methodCtxFinder = {nullptr, "handleUseRm"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &methodCtxFinder, helpers::MethodByNameFinder); + EXPECT_EQ(methodCtxFinder.method, nullptr); + + g_impl->closeFile(file); + + auto output = helpers::ExecuteStaticAbc(inputPath, "class_static_modify", "main"); + EXPECT_TRUE(helpers::Match(output, "handleUseRm\ntest\n")); + + output = helpers::ExecuteStaticAbc(outputPath, "class_static_modify", "main"); + EXPECT_TRUE(helpers::Match(output, "test\n")); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classAddInterface, abc-kind=ArkTS2, category=negative, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassAddInterfaceTest0) +{ + std::string input0 = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/myclass.abc"; + std::string input1 = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/interface.abc"; + + AbckitFile *file0 = nullptr; + AbckitFile *file1 = nullptr; + helpers::AssertOpenAbc(input0.c_str(), &file0); + helpers::AssertOpenAbc(input1.c_str(), &file1); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "myclass"}; + g_implI->fileEnumerateModules(file0, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinderTs = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinderTs, helpers::ClassByNameFinder); + + ctxFinder = {nullptr, "interface"}; + g_implI->fileEnumerateModules(file1, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::InterfaceByNameContext ifaceCtxFinderEts = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinderEts, helpers::InterfaceByNameFinder); + + g_implArkM->classAddInterface(classCtxFinderTs.klass->GetArkTSImpl(), ifaceCtxFinderEts.iface->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_WRONG_TARGET); + + ifaceCtxFinderEts.iface->owningModule->target = ABCKIT_TARGET_ARK_TS_V1; + g_implArkM->classAddInterface(classCtxFinderTs.klass->GetArkTSImpl(), ifaceCtxFinderEts.iface->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_UNSUPPORTED); + + g_impl->closeFile(file0); + g_impl->closeFile(file1); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classAddInterface, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassAddInterfaceTest1) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_interface.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_add_interface_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_interface"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "TestInterface"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + + g_implArkM->classAddInterface(classCtxFinder.klass->GetArkTSImpl(), ifaceCtxFinder.iface->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + ifaceCtxFinder = {nullptr, "TestInterface"}; + g_implI->classEnumerateInterfaces(classCtxFinder.klass, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + EXPECT_NE(ifaceCtxFinder.iface, nullptr); + + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(output.c_str(), &file); + ctxFinder = {nullptr, "class_interface"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + classCtxFinder = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + ifaceCtxFinder = {nullptr, "TestInterface"}; + g_implI->classEnumerateInterfaces(classCtxFinder.klass, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + EXPECT_NE(ifaceCtxFinder.iface, nullptr); + + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classRemoveInterface, abc-kind=ArkTS2, category=negative, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassRemoveInterfaceTest0) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_interface.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_interface"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "TestInterface"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + + g_implArkM->classRemoveInterface(classCtxFinder.klass->GetArkTSImpl(), ifaceCtxFinder.iface->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_INTERNAL_ERROR); + + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classRemoveInterface, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassRemoveInterfaceTest1) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_interface.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_remove_interface_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "class_interface"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "MyInterface"}; + g_implI->classEnumerateInterfaces(classCtxFinder.klass, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + EXPECT_NE(ifaceCtxFinder.iface, nullptr); + + g_implArkM->classRemoveInterface(classCtxFinder.klass->GetArkTSImpl(), ifaceCtxFinder.iface->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + ifaceCtxFinder = {nullptr, "MyInterface"}; + g_implI->classEnumerateInterfaces(classCtxFinder.klass, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + EXPECT_EQ(ifaceCtxFinder.iface, nullptr); + + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(output.c_str(), &file); + + ctxFinder = {nullptr, "class_interface"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + classCtxFinder = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + ifaceCtxFinder = {nullptr, "MyInterface"}; + g_implI->classEnumerateInterfaces(classCtxFinder.klass, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + EXPECT_EQ(ifaceCtxFinder.iface, nullptr); + + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classSetSuperClass, abc-kind=ArkTS2, category=negative, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassSetSuperClassTest0) +{ + std::string input0 = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/super_class.abc"; + std::string input1 = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/myclass.abc"; + std::string input2 = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/suclass.abc"; + + AbckitFile *file0 = nullptr; + AbckitFile *file1 = nullptr; + AbckitFile *file2 = nullptr; + helpers::AssertOpenAbc(input0.c_str(), &file0); + helpers::AssertOpenAbc(input1.c_str(), &file1); + helpers::AssertOpenAbc(input2.c_str(), &file2); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "super_class"}; + g_implI->fileEnumerateModules(file0, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder0 = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder0, helpers::ClassByNameFinder); + + helpers::ClassByNameContext classCtxFinder1 = {nullptr, "SuClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder1, helpers::ClassByNameFinder); + + ctxFinder = {nullptr, "myclass"}; + g_implI->fileEnumerateModules(file1, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinderTs = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinderTs, helpers::ClassByNameFinder); + + ctxFinder = {nullptr, "suclass"}; + g_implI->fileEnumerateModules(file2, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinderEts = {nullptr, "SuClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinderEts, helpers::ClassByNameFinder); + + g_implArkM->classSetSuperClass(classCtxFinderTs.klass->GetArkTSImpl(), classCtxFinderEts.klass->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_WRONG_TARGET); + + classCtxFinder0.klass->owningModule->target = ABCKIT_TARGET_ARK_TS_V1; + g_implArkM->classSetSuperClass(classCtxFinder0.klass->GetArkTSImpl(), classCtxFinder1.klass->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_UNSUPPORTED); + + g_impl->closeFile(file0); + g_impl->closeFile(file1); + g_impl->closeFile(file2); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::classSetSuperClass, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassSetSuperClassTest1) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/super_class.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/super_class_out.abc"; + std::string transform = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/super_class_trans.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "super_class"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::ClassByNameContext classCtxFinder0 = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder0, helpers::ClassByNameFinder); + + helpers::ClassByNameContext classCtxFinder1 = {nullptr, "SuClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder1, helpers::ClassByNameFinder); + + ASSERT_TRUE( + g_implArkM->classSetSuperClass(classCtxFinder0.klass->GetArkTSImpl(), classCtxFinder1.klass->GetArkTSImpl())); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + EXPECT_EQ(classCtxFinder0.klass->superClass, classCtxFinder1.klass); + + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(output.c_str(), &file); + + ctxFinder = {nullptr, "super_class"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + classCtxFinder0 = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder0, helpers::ClassByNameFinder); + + classCtxFinder1 = {nullptr, "SuClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder1, helpers::ClassByNameFinder); + + EXPECT_EQ(classCtxFinder0.klass->superClass, classCtxFinder1.klass); + + SuperClassTransformCtorIr(file); + SuperClassTransformMainIr(file); + + g_impl->writeAbc(file, transform.c_str(), transform.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + auto result = helpers::ExecuteStaticAbc(input, "super_class", "main"); + EXPECT_TRUE(helpers::Match(result, "key: key value: 0\n")); + result = helpers::ExecuteStaticAbc(output, "super_class", "main"); + EXPECT_TRUE(helpers::Match(result, "key: key value: 0\n")); + result = helpers::ExecuteStaticAbc(transform, "super_class", "main"); + EXPECT_TRUE(helpers::Match(result, "key: sukey value: 1\n")); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::ClassSetName, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassSetName1) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", &file); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", + "classset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Alice\n")); + + helpers::ModuleByNameContext mdFinder = {nullptr, "classset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + + helpers::ClassByNameContext clsFinder = {nullptr, "PersonTest"}; + g_implI->moduleEnumerateClasses(module, &clsFinder, helpers::ClassByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(clsFinder.klass, nullptr); + auto *klass = clsFinder.klass; + + auto className = "Person"; + bool ret = g_implArkM->classSetName(g_implArkI->coreClassToArktsClass(klass), className); + auto getClassName = g_implI->abckitStringToString(g_implI->classGetName(klass)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + ASSERT_EQ(std::string(getClassName), "Person"); + + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify_classSetName_1.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + output = helpers::ExecuteStaticAbc(OUTPUT_PATH, "classset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Alice\n")); + helpers::AssertOpenAbc(OUTPUT_PATH, &file); + mdFinder = {nullptr, "classset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_NE(mdFinder.module, nullptr); + module = mdFinder.module; + clsFinder = {nullptr, "PersonTest"}; + g_implI->moduleEnumerateClasses(module, &clsFinder, helpers::ClassByNameFinder); + ASSERT_EQ(clsFinder.klass, nullptr); + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::ClassSetName, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassSetName2) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", &file); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", + "classset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Alice\n")); + + helpers::ModuleByNameContext mdFinder = {nullptr, "classset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + + helpers::ClassByNameContext clsFinder = {nullptr, "ParentTest"}; + g_implI->moduleEnumerateClasses(module, &clsFinder, helpers::ClassByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(clsFinder.klass, nullptr); + auto *klass = clsFinder.klass; + + auto className = "Parent"; + auto ret = g_implArkM->classSetName(g_implArkI->coreClassToArktsClass(klass), className); + auto getClassName = g_implI->abckitStringToString(g_implI->classGetName(klass)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + ASSERT_EQ(std::string(getClassName), "Parent"); + + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify_classSetName_2.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + output = helpers::ExecuteStaticAbc(OUTPUT_PATH, "classset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Alice\n")); + helpers::AssertOpenAbc(OUTPUT_PATH, &file); + mdFinder = {nullptr, "classset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_NE(mdFinder.module, nullptr); + module = mdFinder.module; + clsFinder = {nullptr, "ParentTest"}; + g_implI->moduleEnumerateClasses(module, &clsFinder, helpers::ClassByNameFinder); + ASSERT_EQ(clsFinder.klass, nullptr); + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::ClassAddField, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassAddField) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", &file); + + helpers::ModuleByNameContext mdFinder = {nullptr, "classset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + + helpers::ClassByNameContext clsFinder = {nullptr, "PersonTest"}; + g_implI->moduleEnumerateClasses(module, &clsFinder, helpers::ClassByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(clsFinder.klass, nullptr); + auto *klass = clsFinder.klass; + + helpers::ClassByNameContext clsFinderTest = {nullptr, "MyClass"}; + g_implI->moduleEnumerateClasses(module, &clsFinderTest, helpers::ClassByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(clsFinderTest.klass, nullptr); + auto *klassTest = clsFinderTest.klass; + + for (auto &field : klassTest->fields) { + bool ret = g_implArkM->classAddField(g_implArkI->coreClassToArktsClass(klass), field.get()->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + } + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify_ClassAddField.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(OUTPUT_PATH, &file); + mdFinder = {nullptr, "classset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_NE(mdFinder.module, nullptr); + module = mdFinder.module; + clsFinder = {nullptr, "PersonTest"}; + g_implI->moduleEnumerateClasses(module, &clsFinder, helpers::ClassByNameFinder); + ASSERT_NE(clsFinder.klass, nullptr); + klass = clsFinder.klass; + std::vector FieldNames; + g_implI->classEnumerateFields(klass, &FieldNames, [](AbckitCoreClassField *field, void *data) { + auto ctx = static_cast *>(data); + auto filedName = g_implI->abckitStringToString(g_implI->classFieldGetName(field)); + (*ctx).emplace_back(filedName); + return true; + }); + sort(FieldNames.begin(), FieldNames.end()); + std::vector actualFieldNames = {"age", "levelArray", "myEnum", "myMap", + "mySet", "name", "score", "testObj"}; + ASSERT_EQ(FieldNames, actualFieldNames); + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::ClassSetOwningModule, abc-kind=ArkTS2, category=positive, +// extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassSetOwningModule1) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", &file); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", + "classset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Alice\n")); + + helpers::ModuleByNameContext mdFinder = {nullptr, "classset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + + helpers::ClassByNameContext clsFinder = {nullptr, "PersonTest"}; + g_implI->moduleEnumerateClasses(module, &clsFinder, helpers::ClassByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(clsFinder.klass, nullptr); + auto *klass = clsFinder.klass; + + auto moduleTest = std::make_unique(); + const char *moduleName = "LocalModule"; + moduleTest->file = file; + moduleTest->moduleName = libabckit::CreateStringStatic(file, moduleName, strlen(moduleName)); + moduleTest->isExternal = false; + moduleTest->target = ABCKIT_TARGET_ARK_TS_V2; + moduleTest->impl = std::make_unique(); + moduleTest->GetArkTSImpl()->core = moduleTest.get(); + + bool ret = g_implArkM->classSetOwningModule(g_implArkI->coreClassToArktsClass(klass), + g_implArkI->coreModuleToArktsModule(moduleTest.get())); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + auto setNewModuleName = g_implI->abckitStringToString(klass->owningModule->moduleName); + ASSERT_EQ(std::string(setNewModuleName), "LocalModule"); + + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify_ClassSetOwningModule_1.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + output = helpers::ExecuteStaticAbc(OUTPUT_PATH, "classset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Alice\n")); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::ClassSetOwningModule, abc-kind=ArkTS2, category=positive, +// extension=c +TEST_F(LibAbcKitArkTSModifyApiClassTests, ClassSetOwningModule2) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", &file); + + auto output = helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/classset_static.abc", + "classset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Alice\n")); + + helpers::ModuleByNameContext mdFinder = {nullptr, "classset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + + helpers::ClassByNameContext clsFinder = {nullptr, "ParentTest"}; + g_implI->moduleEnumerateClasses(module, &clsFinder, helpers::ClassByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(clsFinder.klass, nullptr); + auto *klass = clsFinder.klass; + + auto moduleTest = std::make_unique(); + const char *moduleName = "LocalModule"; + moduleTest->file = file; + moduleTest->moduleName = libabckit::CreateStringStatic(file, moduleName, strlen(moduleName)); + moduleTest->isExternal = false; + moduleTest->target = ABCKIT_TARGET_ARK_TS_V2; + moduleTest->impl = std::make_unique(); + moduleTest->GetArkTSImpl()->core = moduleTest.get(); + + auto ret = g_implArkM->classSetOwningModule(g_implArkI->coreClassToArktsClass(klass), + g_implArkI->coreModuleToArktsModule(moduleTest.get())); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + auto setNewModuleName = g_implI->abckitStringToString(klass->owningModule->moduleName); + ASSERT_EQ(std::string(setNewModuleName), "LocalModule"); + + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/class/class_static_modify_ClassSetOwningModule_2.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + output = helpers::ExecuteStaticAbc(OUTPUT_PATH, "classset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Alice\n")); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/classset_static.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/classset_static.ets new file mode 100755 index 0000000000000000000000000000000000000000..23405e25403a5ab1ffaf10a688825252594ab6d1 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/classset_static.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 TestClass {} +enum ColorSet { Red, Green, Blue } +class MyClass { + public score: string = "good"; + protected testObj: TestClass = new TestClass(); + private levelArray: string[] = ['A', 'B', 'C']; + static myEnum: ColorSet = ColorSet.Red; + private static myMap: Map = new Map(); + mySet: Set = new Set(); +} + +class ParentTest { + id: string = "001"; +} + +class PersonTest extends ParentTest { + name: string = "Alice"; + age: number = 30; + + showName() { + console.log(this.name); + } +} + +function main() { + let c = new PersonTest(); + c.showName(); +} + diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/interface.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/interface.ets new file mode 100644 index 0000000000000000000000000000000000000000..bb08fdbd3fce92c29475a72bc7abbda700c8c292 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/interface.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. + */ + +interface MyInterface { + key: string; + value: number; + handle(): void; +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/myclass.ts b/libabckit/tests/ut/extensions/arkts/modify_api/class/myclass.ts new file mode 100644 index 0000000000000000000000000000000000000000..53c910c8607c6e5615124c06c4db28613d5f6469 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/myclass.ts @@ -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 MyClass { + key: string; + value: number; + + constructor() { + this.key = "key"; + this.value = 0; + } + + handle(): void { + console.log("key: " + this.key + " value: " + this.value); + } +} + +function main() { + let c = new MyClass(); + c.handle(); +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/suclass.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/suclass.ets new file mode 100644 index 0000000000000000000000000000000000000000..016bcafe0374811cd550d89fa32b7d5ae11a9bc3 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/suclass.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 SuClass { + suKey: string; + suValue: number; + + constructor() { + this.suKey = "sukey"; + this.suValue = 1; + } + + suHandle(): void { + console.log("key: " + this.suKey + " value: " + this.suValue); + } +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/class/super_class.ets b/libabckit/tests/ut/extensions/arkts/modify_api/class/super_class.ets new file mode 100644 index 0000000000000000000000000000000000000000..6f3094d430698a1fc0c7f47ec9c2958d58692392 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/class/super_class.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 SuClass { + suKey: string; + suValue: number; + + constructor() { + this.suKey = "sukey"; + this.suValue = 1; + } + + suHandle(): void { + console.log("key: " + this.suKey + " value: " + this.suValue); + } +} + +class MyClass { + key: string; + value: number; + + constructor() { + this.key = "key"; + this.value = 0; + } + + handle(): void { + console.log("key: " + this.key + " value: " + this.value); + } +} + +function main() { + let c = new MyClass(); + c.handle(); +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interface/addsuperinterface.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interface/addsuperinterface.ets new file mode 100755 index 0000000000000000000000000000000000000000..88567db815747a893eee0af3f414b9337e026701 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interface/addsuperinterface.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. + */ + +interface Style { + color: string; + showColor():void; +} + +interface ExtendedStyle { + width: number; + calculateAreaSize(): number; +} + +class RectangleSize implements ExtendedStyle { + width: number; + height: number; + constructor(w: number, h:number) { + this.width = w; + this.height = h; + } + calculateAreaSize(): number { + return this.width * this.height; + } +} + +function main() { + let c = new RectangleSize(20, 30); + console.log(c.calculateAreaSize()); +} + diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interface/interface_static_test.cpp b/libabckit/tests/ut/extensions/arkts/modify_api/interface/interface_static_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..fb3a983543dd4a5ce84d62e2565725a323f54c24 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interface/interface_static_test.cpp @@ -0,0 +1,249 @@ +/** + * 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 "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "libabckit/c/abckit.h" +#include "libabckit/c/extensions/arkts/metadata_arkts.h" +#include "libabckit/c/metadata_core.h" +#include "libabckit/src/adapter_static/metadata_modify_static.h" +#include "libabckit/src/metadata_inspect_impl.h" + +namespace libabckit::test { + +static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkI = AbckitGetArktsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkM = AbckitGetArktsModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); + +class LibAbcKitArkTSModifyApiInterfaceTests : public ::testing::Test {}; + +// Test: test-kind=api, api=ArktsModifyApiImpl::InterfaceAddSuperInterface, abc-kind=ArkTS2, category=positive, +// extension=c +TEST_F(LibAbcKitArkTSModifyApiInterfaceTests, InterfaceAddSuperInterface) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/addsuperinterface.abc", &file); + auto output = helpers::ExecuteStaticAbc( + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/addsuperinterface.abc", "addsuperinterface", "main"); + EXPECT_TRUE(helpers::Match(output, "600\n")); + + helpers::ModuleByNameContext mdFinder = {nullptr, "addsuperinterface"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + + helpers::InterfaceByNameContext ifaceFinder = {nullptr, "ExtendedStyle"}; + g_implI->moduleEnumerateInterfaces(module, &ifaceFinder, helpers::InterfaceByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(ifaceFinder.iface, nullptr); + auto *iface = ifaceFinder.iface; + + helpers::InterfaceByNameContext superifaceFinder = {nullptr, "Style"}; + g_implI->moduleEnumerateInterfaces(module, &superifaceFinder, helpers::InterfaceByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(superifaceFinder.iface, nullptr); + auto *superIface = superifaceFinder.iface; + + bool ret = g_implArkM->interfaceAddSuperInterface(iface->GetArkTSImpl(), superIface->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interface_static_modify_AddSuperInterface.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + output = helpers::ExecuteStaticAbc(OUTPUT_PATH, "addsuperinterface", "main"); + EXPECT_TRUE(helpers::Match(output, "600\n")); + helpers::AssertOpenAbc(OUTPUT_PATH, &file); + mdFinder = {nullptr, "addsuperinterface"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_NE(mdFinder.module, nullptr); + module = mdFinder.module; + ifaceFinder = {nullptr, "ExtendedStyle"}; + g_implI->moduleEnumerateInterfaces(module, &ifaceFinder, helpers::InterfaceByNameFinder); + ASSERT_NE(ifaceFinder.iface, nullptr); + iface = ifaceFinder.iface; + ASSERT_EQ(iface->superInterfaces.size(), 1); + auto name = g_implI->abckitStringToString(g_implI->interfaceGetName(iface->superInterfaces[0])); + ASSERT_EQ(std::string(name), "Style"); + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::InterfaceRemoveSuperInterface, abc-kind=ArkTS2, category=positive, +// extension=c +TEST_F(LibAbcKitArkTSModifyApiInterfaceTests, InterfaceRemoveSuperInterface) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/removesuperinterface.abc", &file); + auto output = + helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/removesuperinterface.abc", + "removesuperinterface", "main"); + EXPECT_TRUE(helpers::Match(output, "600\nred\n")); + + helpers::ModuleByNameContext mdFinder = {nullptr, "removesuperinterface"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + helpers::InterfaceByNameContext ifaceFinder = {nullptr, "ExtendedStyle"}; + g_implI->moduleEnumerateInterfaces(module, &ifaceFinder, helpers::InterfaceByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(ifaceFinder.iface, nullptr); + auto *iface = ifaceFinder.iface; + + helpers::InterfaceByNameContext superifaceFinder = {nullptr, "Style"}; + g_implI->moduleEnumerateInterfaces(module, &superifaceFinder, helpers::InterfaceByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(superifaceFinder.iface, nullptr); + auto *superIface = superifaceFinder.iface; + + bool ret = g_implArkM->interfaceRemoveSuperInterface(iface->GetArkTSImpl(), superIface->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interface_static_modify_RemoveSuperInterface.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(OUTPUT_PATH, &file); + mdFinder = {nullptr, "removesuperinterface"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_NE(mdFinder.module, nullptr); + module = mdFinder.module; + ifaceFinder = {nullptr, "ExtendedStyle"}; + g_implI->moduleEnumerateInterfaces(module, &ifaceFinder, helpers::InterfaceByNameFinder); + ASSERT_NE(ifaceFinder.iface, nullptr); + iface = ifaceFinder.iface; + ASSERT_EQ(iface->superInterfaces.size(), 0); + g_impl->closeFile(file); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::InterfaceRemoveMethod, abc-kind=ArkTS2, category=positive, +// extension=c +TEST_F(LibAbcKitArkTSModifyApiInterfaceTests, InterfaceRemoveMethod) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interfaceset_static.abc", &file); + + auto output = + helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interfaceset_static.abc", + "interfaceset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "red\n")); + + helpers::ModuleByNameContext mdFinder = {nullptr, "interfaceset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + + helpers::InterfaceByNameContext ifaceFinder = {nullptr, "ExtendedStyle"}; + g_implI->moduleEnumerateInterfaces(module, &ifaceFinder, helpers::InterfaceByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(ifaceFinder.iface, nullptr); + auto *iface = ifaceFinder.iface; + + helpers::MethodByNameContext methodCtxFinder = {nullptr, "showColor"}; + g_implI->interfaceEnumerateMethods(iface, &methodCtxFinder, helpers::MethodByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(methodCtxFinder.method, nullptr); + auto *method = methodCtxFinder.method; + + bool ret = g_implArkM->interfaceRemoveMethod(iface->GetArkTSImpl(), method->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interface_static_modify_RemoveMethod.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + output = helpers::ExecuteStaticAbc(OUTPUT_PATH, "interfaceset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "red\n")); + constexpr auto OUTPUT_PATH_1 = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interface_static_modify_RemoveMethod_1.abc"; + + helpers::TransformMethod(OUTPUT_PATH, OUTPUT_PATH_1, "main", + [](AbckitFile *file, AbckitCoreFunction *method, AbckitGraph *graph) { + auto *call = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CALL_VIRTUAL); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_implG->iRemove(call); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + }); + output = helpers::ExecuteStaticAbc(OUTPUT_PATH_1, "interfaceset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "")); +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::InterfaceSetOwningModule, abc-kind=ArkTS2, category=positive, +// extension=c +TEST_F(LibAbcKitArkTSModifyApiInterfaceTests, InterfaceSetOwningModule) +{ + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interfaceset_static.abc", &file); + auto output = + helpers::ExecuteStaticAbc(ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interfaceset_static.abc", + "interfaceset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "red\n")); + + helpers::ModuleByNameContext mdFinder = {nullptr, "interfaceset_static"}; + g_implI->fileEnumerateModules(file, &mdFinder, helpers::ModuleByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(mdFinder.module, nullptr); + auto *module = mdFinder.module; + + helpers::InterfaceByNameContext ifaceFinder = {nullptr, "ExtendedStyle"}; + g_implI->moduleEnumerateInterfaces(module, &ifaceFinder, helpers::InterfaceByNameFinder); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_NE(ifaceFinder.iface, nullptr); + auto *iface = ifaceFinder.iface; + + // create a new module + auto m = std::make_unique(); + m->file = file; + m->target = ABCKIT_TARGET_ARK_TS_V2; + const char *moduleName = "LocalModule"; + m->moduleName = CreateStringStatic(file, moduleName, strlen(moduleName)); + m->impl = std::make_unique(); + m->GetArkTSImpl()->core = m.get(); + + bool ret = g_implArkM->interfaceSetOwningModule(nullptr, m.get()->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + ASSERT_FALSE(ret); + ret = g_implArkM->interfaceSetOwningModule(iface->GetArkTSImpl(), nullptr); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_BAD_ARGUMENT); + ASSERT_FALSE(ret); + ret = g_implArkM->interfaceSetOwningModule(iface->GetArkTSImpl(), m.get()->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + constexpr auto OUTPUT_PATH = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interface/interface_static_modify_SetOwningModule.abc"; + g_impl->writeAbc(file, OUTPUT_PATH, strlen(OUTPUT_PATH)); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + output = helpers::ExecuteStaticAbc(OUTPUT_PATH, "interfaceset_static", "main"); + EXPECT_TRUE(helpers::Match(output, "red\n")); +} +} // namespace libabckit::test diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interface/interfaceset_static.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interface/interfaceset_static.ets new file mode 100755 index 0000000000000000000000000000000000000000..de5907b1933951844e90c03d4387450d009c5921 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interface/interfaceset_static.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. + */ + +interface ExtendedStyle { + color: string; + showColor(): void; +} + +class RectangleSize implements ExtendedStyle { + color: string; + width: number; + height: number; + constructor(c: string, w: number, h:number) { + this.color = c; + this.width = w; + this.height = h; + } + calculateAreaSize(): number { + return this.width * this.height; + } + showColor() { + console.log(this.color); + } +} + +function main() { + let c = new RectangleSize("red", 20, 30); + c.showColor(); +} + diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interface/removesuperinterface.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interface/removesuperinterface.ets new file mode 100755 index 0000000000000000000000000000000000000000..de98fdaef75c5729ce05ab0b56f798e2b1f6ac2d --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interface/removesuperinterface.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. + */ + +interface Style { + color: string; + showColor():void; +} + +interface ExtendedStyle extends Style { + width: number; + calculateAreaSize(): number; +} + +class RectangleSize implements ExtendedStyle { + color: string; + width: number; + height: number; + constructor(c: string, w: number, h:number) { + this.color = c; + this.width = w; + this.height = h; + } + calculateAreaSize(): number { + return this.width * this.height; + } + showColor() { + console.log(this.color); + } +} + +function main() { + let c = new RectangleSize("red", 20, 30); + console.log(c.calculateAreaSize()); + c.showColor(); +} + diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface.ets new file mode 100644 index 0000000000000000000000000000000000000000..0e64ab20216cd8ecf5d985c2adcfdb6733aae5b5 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface.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. + */ + +interface MyInterface { + key: string; + value: number; + handle(key: string, value: number): void; +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_field_static.cpp b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_field_static.cpp new file mode 100644 index 0000000000000000000000000000000000000000..425f17e48bdcaea6947214f491540982a82f3aef --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_field_static.cpp @@ -0,0 +1,233 @@ +/** + * 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 +#include +#include + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "libabckit/include/libabckit/c/abckit.h" +#include "libabckit/include/libabckit/c/declarations.h" +#include "libabckit/include/libabckit/c/extensions/arkts/metadata_arkts.h" +#include "libabckit/include/libabckit/c/metadata_core.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/logger.h" +#include "libabckit/src/metadata_inspect_impl.h" + +namespace libabckit::test { + +static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkI = AbckitGetArktsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkM = AbckitGetArktsModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_staticG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0); + +class LibAbcKitModifyApiIfaceTests : public ::testing::Test {}; + +struct CaptureData { + AbckitGraph *graph = nullptr; + AbckitCoreFunction *mainFunc = nullptr; + AbckitCoreFunction *targetFunc = nullptr; +}; + +void ClassAddInterfaceTransformMainIr(AbckitCoreFunction *mainFunction, AbckitCoreFunction *targetFunc) +{ + AbckitGraph *graph = g_implI->createGraphFromFunction(mainFunction); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + CaptureData capData; + capData.graph = graph; + capData.targetFunc = targetFunc; + g_implG->gVisitBlocksRpo(graph, &capData, [](AbckitBasicBlock *bb, void *data) -> bool { + CaptureData *capData = reinterpret_cast(data); + for (auto inst = g_implG->bbGetFirstInst(bb); inst != nullptr; inst = g_implG->iGetNext(inst)) { + if (g_staticG->iGetOpcode(inst) == ABCKIT_ISA_API_STATIC_OPCODE_RETURN_VOID) { + auto preInst = g_implG->iGetPrev(inst); + auto objRef = g_implG->iGetInput(preInst, 0); + auto newInst = g_staticG->iCreateCallVirtual(capData->graph, objRef, capData->targetFunc, 0); + g_implG->iInsertBefore(newInst, inst); + } + } + return true; + }); + + g_implM->functionSetGraph(mainFunction, graph); + g_impl->destroyGraph(graph); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); +} + +TEST_F(LibAbcKitModifyApiIfaceTests, InterfaceAddFieldTest0) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_add_field_static.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_add_field_static_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + helpers::ModuleByNameContext ctxFinder = {nullptr, "interface_add_field_static"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + + helpers::InterfaceByNameContext testIfaceCtxFinder = {nullptr, "Test"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &testIfaceCtxFinder, helpers::InterfaceByNameFinder); + + auto arktsInterface = g_implArkI->coreInterfaceToArktsInterface(ifaceCtxFinder.iface); + + const auto &it = testIfaceCtxFinder.iface->fields.begin(); + auto atktsInterfaceField = g_implArkI->coreInterfaceFieldToArktsInterfaceField(it->second.get()); + + g_implArkM->interfaceAddField(arktsInterface, atktsInterfaceField); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + // open output file + helpers::AssertOpenAbc(output.c_str(), &file); + ctxFinder = {nullptr, "interface_add_field_static"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + ifaceCtxFinder = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + + std::vector FieldNames; + g_implI->interfaceEnumerateFields( + ifaceCtxFinder.iface, &FieldNames, [](AbckitCoreInterfaceField *field, void *data) { + auto ctx = static_cast *>(data); + auto filedName = g_implI->abckitStringToString(g_implI->interfaceFieldGetName(field)); + (*ctx).emplace_back(filedName); + return true; + }); + std::vector testFileds = {"key", "age"}; + ASSERT_EQ(FieldNames, testFileds); + g_impl->closeFile(file); +} + +TEST_F(LibAbcKitModifyApiIfaceTests, InterfaceAddMethodTest0) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_add_method_static.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_add_field_static_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "interface_add_method_static"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "Test"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + + helpers::InterfaceByNameContext ifaceCtxFinder1 = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder1, helpers::InterfaceByNameFinder); + + helpers::MethodByNameContext methodCtxFinder = {nullptr, "sayHello:interface_add_method_static.Test;f64;void;", + true}; + g_implI->interfaceEnumerateMethods(ifaceCtxFinder.iface, &methodCtxFinder, helpers::MethodByNameFinder); + + auto arkInterface = g_implArkI->coreInterfaceToArktsInterface(ifaceCtxFinder1.iface); + auto arkFunc = g_implArkI->coreFunctionToArktsFunction(methodCtxFinder.method); + g_implArkM->interfaceAddMethod(arkInterface, arkFunc); + + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); +} + +static void UpdateMainFunction(const std::string &second, AbckitFile *file, std::string &rst) +{ + helpers::AssertOpenAbc(second.c_str(), &file); + helpers::ModuleByNameContext ctxFinder = {nullptr, "interface_add_method_static_extral"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + helpers::MethodByNameContext mainCtxFinder = {nullptr, "main"}; + g_implI->moduleEnumerateTopLevelFunctions(ctxFinder.module, &mainCtxFinder, helpers::MethodByNameFinder); + + helpers::ClassByNameContext classCtxFinder = {nullptr, "NewClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + + helpers::MethodByNameContext targetCtxFinder = {nullptr, "sayHello"}; + g_implI->classEnumerateMethods(classCtxFinder.klass, &targetCtxFinder, helpers::MethodByNameFinder); + + ClassAddInterfaceTransformMainIr(mainCtxFinder.method, targetCtxFinder.method); + + g_impl->writeAbc(file, rst.c_str(), rst.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); +} + +TEST_F(LibAbcKitModifyApiIfaceTests, InterfaceAddMethodTest1) +{ + std::string input = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_add_method_static_extral.abc"; + std::string first = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_add_method_static_extral_first.abc"; + std::string second = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_add_method_static_extral_second.abc"; + std::string rst = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_add_method_static_rst.abc"; + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + helpers::ModuleByNameContext ctxFinder = {nullptr, "interface_add_method_static_extral"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "Test"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + helpers::InterfaceByNameContext ifaceCtxFinder1 = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder1, helpers::InterfaceByNameFinder); + helpers::MethodByNameContext methodCtxFinder = {nullptr, "sayHello"}; + g_implI->interfaceEnumerateMethods(ifaceCtxFinder.iface, &methodCtxFinder, helpers::MethodByNameFinder); + auto arkInterface = g_implArkI->coreInterfaceToArktsInterface(ifaceCtxFinder1.iface); + auto arkFunc = g_implArkI->coreFunctionToArktsFunction(methodCtxFinder.method); + g_implArkM->interfaceAddMethod(arkInterface, arkFunc); + g_impl->writeAbc(file, first.c_str(), first.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + helpers::AssertOpenAbc(first.c_str(), &file); + ctxFinder = {nullptr, "interface_add_method_static_extral"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + // Get NewClass + helpers::ClassByNameContext classCtxFinder = {nullptr, "NewClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &classCtxFinder, helpers::ClassByNameFinder); + // Get TestInterfaceClass + helpers::ClassByNameContext testClassCtxFinder = {nullptr, "TestInterfaceClass"}; + g_implI->moduleEnumerateClasses(ctxFinder.module, &testClassCtxFinder, helpers::ClassByNameFinder); + // Get TestInterfaceClass mothed + helpers::MethodByNameContext funcCtxFinder = {nullptr, "sayHello"}; + g_implI->classEnumerateMethods(testClassCtxFinder.klass, &funcCtxFinder, helpers::MethodByNameFinder); + g_implArkM->classAddMethod(classCtxFinder.klass->GetArkTSImpl(), funcCtxFinder.method->GetArkTSImpl()); + g_impl->writeAbc(file, second.c_str(), second.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + UpdateMainFunction(second, file, rst); + + auto result = helpers::ExecuteStaticAbc(input, "interface_add_method_static_extral", "main"); + EXPECT_TRUE(helpers::Match(result, "aaa\n")); + result = helpers::ExecuteStaticAbc(rst, "interface_add_method_static_extral", "main"); + EXPECT_TRUE(helpers::Match(result, "aaa\nbbb\n")); +} +} // namespace libabckit::test \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_field_static.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_field_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..dab166a75a808fb1372aa500ea0673315362152f --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_field_static.ets @@ -0,0 +1,22 @@ +/** + * 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 Test { + age: number; +} + +interface MyInterface { + key: string; +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_method_static.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_method_static.ets new file mode 100644 index 0000000000000000000000000000000000000000..f10bbe9351b5f546c9706f3dca91d3da732cbc4c --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_method_static.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. + */ + +interface Test{ + sayHello(num: number): void; +} + +interface MyInterface{ + getName(): string; + calculate(a: number, b: number): number; +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_method_static_extral.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_method_static_extral.ets new file mode 100644 index 0000000000000000000000000000000000000000..b3cdc43d915af30d322f2f09109c13ba1b5b2c93 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_add_method_static_extral.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 TestInterfaceClass { + sayHello(): void { + console.log("bbb"); + } +} + +interface Test { + sayHello(): void; +} + +interface MyInterface { + showName(): void; +} + +class NewClass implements MyInterface { + showName(): void { + console.log("aaa"); + } +} + +function main() { + let n = new NewClass(); + n.showName(); +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_remove_field_static.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_remove_field_static.ets new file mode 100755 index 0000000000000000000000000000000000000000..524a1156286d55345dd5c24ec7e09a4ef0c8822c --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_remove_field_static.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. + */ + +interface MyInterface { + key: string; + value: number; +} + +interface MyInterface2 { + key2: string; + value2: number; +} + +class MyClass implements MyInterface { + key: string = "test"; + value: number = 42; + + printKey(): void { + console.log("Key: " + this.key); + } +} + +function useInterfaceField(obj: MyClass): void { + console.log("Accessing key: " + obj.key); +} + +function main(): void { + const obj = new MyClass(); + obj.printKey(); + useInterfaceField(obj); + console.log("Value: " + obj.value); +} \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_test.cpp b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_test.cpp new file mode 100755 index 0000000000000000000000000000000000000000..95617db66daa50f6e2cb408e20ec6b45cb404aca --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interface_test.cpp @@ -0,0 +1,139 @@ +/** + * 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 "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "libabckit/include/libabckit/c/extensions/arkts/metadata_arkts.h" +#include "libabckit/src/metadata_inspect_impl.h" + +namespace libabckit::test { +static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkI = AbckitGetArktsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkM = AbckitGetArktsModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_staticG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0); + +class LibAbcKitModifyApiIfaceTests : public ::testing::Test {}; + +// Test: test-kind=api, api=ArktsModifyApiImpl::InterfaceRemoveField, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitModifyApiIfaceTests, InterfaceRemoveFieldTest0) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_remove_field_static.abc"; + std::string output = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_remove_field_static_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext moduleCtx = {nullptr, "interface_remove_field_static"}; + g_implI->fileEnumerateModules(file, &moduleCtx, helpers::ModuleByNameFinder); + + helpers::InterfaceByNameContext interfaceCtx = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(moduleCtx.module, &interfaceCtx, helpers::InterfaceByNameFinder); + helpers::InterfaceByNameContext interfaceCtx2 = {nullptr, "MyInterface2"}; + g_implI->moduleEnumerateInterfaces(moduleCtx.module, &interfaceCtx2, helpers::InterfaceByNameFinder); + + helpers::FieldByNameContext fieldCtx = {nullptr, "key"}; + g_implI->interfaceEnumerateFields(interfaceCtx.iface, &fieldCtx, helpers::FieldByNameFinder); + ASSERT_TRUE(fieldCtx.field != nullptr); + + bool ret = g_implArkM->interfaceRemoveField(interfaceCtx2.iface->GetArkTSImpl(), fieldCtx.field->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_INTERNAL_ERROR); + ASSERT_FALSE(ret); + + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + helpers::AssertOpenAbc(output.c_str(), &file); + helpers::ModuleByNameContext moduleCtx2 = {nullptr, "interface_remove_field_static"}; + g_implI->fileEnumerateModules(file, &moduleCtx2, helpers::ModuleByNameFinder); + helpers::InterfaceByNameContext interfaceCtx3 = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(moduleCtx2.module, &interfaceCtx3, helpers::InterfaceByNameFinder); + helpers::FieldByNameContext checkFieldCtx = {nullptr, "key"}; + g_implI->interfaceEnumerateFields(interfaceCtx3.iface, &checkFieldCtx, helpers::FieldByNameFinder); + ASSERT_TRUE(checkFieldCtx.field != nullptr); + + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); +} + +static void TransformInterfaceRemoveField(AbckitGraph *graph) +{ + auto *staticCall = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC); + if (staticCall != nullptr) { + g_implG->iRemove(staticCall); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + } + + auto *virtualCall = helpers::FindFirstInst(graph, ABCKIT_ISA_API_STATIC_OPCODE_CALL_VIRTUAL); + if (virtualCall != nullptr) { + g_implG->iRemove(virtualCall); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + } +} + +// Test: test-kind=api, api=ArktsModifyApiImpl::InterfaceRemoveField, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitModifyApiIfaceTests, InterfaceRemoveFieldTest2) +{ + auto inputPath = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_remove_field_static.abc"; + auto outputPath = + ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_remove_field_static_output.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(inputPath, &file); + helpers::TransformMethod(file, "main", + [](AbckitFile * /*file*/, AbckitCoreFunction * /*method*/, AbckitGraph *graph) { + TransformInterfaceRemoveField(graph); + }); + + helpers::ModuleByNameContext moduleCtx = {nullptr, "interface_remove_field_static"}; + g_implI->fileEnumerateModules(file, &moduleCtx, helpers::ModuleByNameFinder); + + helpers::InterfaceByNameContext interfaceCtx = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(moduleCtx.module, &interfaceCtx, helpers::InterfaceByNameFinder); + + helpers::FieldByNameContext fieldCtx = {nullptr, "key"}; + g_implI->interfaceEnumerateFields(interfaceCtx.iface, &fieldCtx, helpers::FieldByNameFinder); + ASSERT_TRUE(fieldCtx.field != nullptr); + bool ret = g_implArkM->interfaceRemoveField(interfaceCtx.iface->GetArkTSImpl(), fieldCtx.field->GetArkTSImpl()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + ASSERT_TRUE(ret); + + g_impl->writeAbc(file, outputPath, strlen(outputPath)); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + helpers::AssertOpenAbc(outputPath, &file); + helpers::ModuleByNameContext moduleCtx2 = {nullptr, "interface_remove_field_static"}; + g_implI->fileEnumerateModules(file, &moduleCtx2, helpers::ModuleByNameFinder); + + helpers::InterfaceByNameContext interfaceCtx2 = {nullptr, "MyInterface"}; + g_implI->moduleEnumerateInterfaces(moduleCtx2.module, &interfaceCtx2, helpers::InterfaceByNameFinder); + helpers::FieldByNameContext checkFieldCtx = {nullptr, "key"}; + g_implI->interfaceEnumerateFields(interfaceCtx2.iface, &checkFieldCtx, helpers::FieldByNameFinder); + ASSERT_TRUE(checkFieldCtx.field == nullptr); + g_impl->closeFile(file); + + auto output = helpers::ExecuteStaticAbc(inputPath, "interface_remove_field_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Key: test\nAccessing key: test\nValue: 42\n")); + output = helpers::ExecuteStaticAbc(outputPath, "interface_remove_field_static", "main"); + EXPECT_TRUE(helpers::Match(output, "Value: 42\n")); +} +} // namespace libabckit::test \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interfaces_static_modify_test.cpp b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interfaces_static_modify_test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..759a0ecaaed3d3ce5e9b21cdb6d750c28d0b2a9a --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/interfaces_static_modify_test.cpp @@ -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. + */ + +#include +#include + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "libabckit/c/abckit.h" +#include "libabckit/c/extensions/arkts/metadata_arkts.h" +#include "libabckit/c/isa/isa_static.h" +#include "libabckit/c/metadata_core.h" +#include "libabckit/src/adapter_static/metadata_modify_static.h" +#include "libabckit/src/metadata_inspect_impl.h" + +namespace libabckit::test { + +static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkI = AbckitGetArktsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkM = AbckitGetArktsModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); + +class LibAbcKitArkTSModifyApiIfaceTests : public ::testing::Test {}; + +// Test: test-kind=api, api=ArktsModifyApiImpl::createInterface, abc-kind=ArkTS2, category=positive, extension=c +TEST_F(LibAbcKitArkTSModifyApiIfaceTests, CreatInterfaceTest0) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/interface_out.abc"; + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "interface"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + std::string ifName = "CreateInterface"; + auto interface = g_implArkM->createInterface(ctxFinder.module->GetArkTSImpl(), ifName.c_str()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + EXPECT_TRUE(g_implI->interfaceGetName(interface->core)->impl == ifName); + + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, ifName.c_str()}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + EXPECT_EQ(ifaceCtxFinder.iface, interface->core); + + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + + helpers::AssertOpenAbc(output.c_str(), &file); + + ctxFinder = {nullptr, "interface"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + ifaceCtxFinder = {nullptr, ifName.c_str()}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + EXPECT_NE(ifaceCtxFinder.iface, nullptr); + + g_impl->closeFile(file); +} + +} // namespace libabckit::test diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.cpp b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.cpp new file mode 100644 index 0000000000000000000000000000000000000000..50cdeb765484d83e833f5e842c26e72a3cf0fc3e --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.cpp @@ -0,0 +1,105 @@ +/** + * 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 +#include +#include + +#include "helpers/helpers.h" +#include "helpers/helpers_runtime.h" +#include "libabckit/include/libabckit/c/abckit.h" +#include "libabckit/include/libabckit/c/declarations.h" +#include "libabckit/include/libabckit/c/extensions/arkts/metadata_arkts.h" +#include "libabckit/include/libabckit/c/metadata_core.h" +#include "libabckit/src/ir_impl.h" +#include "libabckit/src/logger.h" +#include "libabckit/src/metadata_inspect_impl.h" + +namespace libabckit::test { + +static auto g_impl = AbckitGetApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implI = AbckitGetInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkI = AbckitGetArktsInspectApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implArkM = AbckitGetArktsModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implM = AbckitGetModifyApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_implG = AbckitGetGraphApiImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_dynG = AbckitGetIsaApiDynamicImpl(ABCKIT_VERSION_RELEASE_1_0_0); +static auto g_staticG = AbckitGetIsaApiStaticImpl(ABCKIT_VERSION_RELEASE_1_0_0); + +class LibAbcKitModifyApiIfaceNameTests : public ::testing::Test {}; + +TEST_F(LibAbcKitModifyApiIfaceNameTests, InterfaceSetNameTest0) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/static_interface_set_name_out.abc"; + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + + helpers::ModuleByNameContext ctxFinder = {nullptr, "static_interface_set_name"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "User"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + + auto arktsIntrface = g_implArkI->coreInterfaceToArktsInterface(ifaceCtxFinder.iface); + g_implArkM->interfaceSetName(arktsIntrface, "abc"); + + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + helpers::AssertOpenAbc(output.c_str(), &file); + ctxFinder = {nullptr, "static_interface_set_name"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + + ifaceCtxFinder = {nullptr, "abc"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + ASSERT_NE(ifaceCtxFinder.iface, nullptr); + g_impl->closeFile(file); +} + +TEST_F(LibAbcKitModifyApiIfaceNameTests, InterfaceSetNameTest1) +{ + std::string input = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.abc"; + std::string output = ABCKIT_ABC_DIR "ut/extensions/arkts/modify_api/interfaces/static_interface_set_name_out.abc"; + + auto outputRst = helpers::ExecuteStaticAbc(input, "static_interface_set_name", "main"); + EXPECT_TRUE(helpers::Match(outputRst, "b\n")); + + AbckitFile *file = nullptr; + helpers::AssertOpenAbc(input.c_str(), &file); + helpers::ModuleByNameContext ctxFinder = {nullptr, "static_interface_set_name"}; + g_implI->fileEnumerateModules(file, &ctxFinder, helpers::ModuleByNameFinder); + helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "User"}; + g_implI->moduleEnumerateInterfaces(ctxFinder.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); + + auto arktsIntrface = g_implArkI->coreInterfaceToArktsInterface(ifaceCtxFinder.iface); + g_implArkM->interfaceSetName(arktsIntrface, "abc"); + + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->writeAbc(file, output.c_str(), output.length()); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + g_impl->closeFile(file); + ASSERT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); + + outputRst = helpers::ExecuteStaticAbc(output, "static_interface_set_name", "main"); + EXPECT_TRUE(helpers::Match(outputRst, "b\n")); +} +} // namespace libabckit::test \ No newline at end of file diff --git a/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.ets b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.ets new file mode 100644 index 0000000000000000000000000000000000000000..e500ad4d24cb83f844cef94d6bd60eefe745b099 --- /dev/null +++ b/libabckit/tests/ut/extensions/arkts/modify_api/interfaces/static_interface_set_name.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. + */ + +interface User { + id: number; + name: string; + age?: number; +} + +class Persion implements User { + id: number = 0; + name: string = "aaa"; + age?: number = 1; + show(): void { + console.log("b"); + } +} + +function printUser(user: User) { + console.log(`ID: ${user.id}, NAME: ${user.name}`); +} + +function main() +{ + let p = new Persion(); + p.show(); +} \ No newline at end of file diff --git a/libabckit/tests/ut/metadata_core/inspect_api/interfaces/interfaces_static_test.cpp b/libabckit/tests/ut/metadata_core/inspect_api/interfaces/interfaces_static_test.cpp index 246244b338985ef2ae6bb158469b809d7f3a85f6..33b85b45076a6461ff74482c20b134603700ce35 100644 --- a/libabckit/tests/ut/metadata_core/inspect_api/interfaces/interfaces_static_test.cpp +++ b/libabckit/tests/ut/metadata_core/inspect_api/interfaces/interfaces_static_test.cpp @@ -222,7 +222,7 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceGetFile) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "Animal"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); - auto abcFile = g_implI->interfaceGetFile(ifaceCtxFinder.face); + auto abcFile = g_implI->interfaceGetFile(ifaceCtxFinder.iface); ASSERT_NE(abcFile, nullptr); g_impl->closeFile(file); @@ -243,7 +243,7 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceGetModule) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "Animal"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); - auto module = g_implI->interfaceGetModule(ifaceCtxFinder.face); + auto module = g_implI->interfaceGetModule(ifaceCtxFinder.iface); ASSERT_NE(module, nullptr); g_impl->closeFile(file); @@ -264,8 +264,8 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceGetName) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "Animal"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); - ifaceCtxFinder.face->owningModule->target = ABCKIT_TARGET_ARK_TS_V1; - auto name = g_implI->interfaceGetName(ifaceCtxFinder.face); + ifaceCtxFinder.iface->owningModule->target = ABCKIT_TARGET_ARK_TS_V1; + auto name = g_implI->interfaceGetName(ifaceCtxFinder.iface); ASSERT_EQ(name, nullptr); g_impl->closeFile(file); @@ -289,7 +289,7 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceGetParentNamespace) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "MyInterface"}; g_implI->namespaceEnumerateInterfaces(nameSapceCtx.n, &ifaceCtxFinder, helpers::InterfaceByNameFinder); - auto petNamespace = g_implI->interfaceGetParentNamespace(ifaceCtxFinder.face); + auto petNamespace = g_implI->interfaceGetParentNamespace(ifaceCtxFinder.iface); ASSERT_NE(petNamespace, nullptr); g_impl->closeFile(file); @@ -310,10 +310,10 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceEnumerateSuperInterfaces) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "ChildInterface"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); - ifaceCtxFinder.face->owningModule->target = ABCKIT_TARGET_UNKNOWN; + ifaceCtxFinder.iface->owningModule->target = ABCKIT_TARGET_UNKNOWN; void *data = nullptr; - auto ret = g_implI->interfaceEnumerateSuperInterfaces(ifaceCtxFinder.face, data, helpers::InterfaceByNameFinder); + auto ret = g_implI->interfaceEnumerateSuperInterfaces(ifaceCtxFinder.iface, data, helpers::InterfaceByNameFinder); ASSERT_FALSE(ret); g_impl->closeFile(file); @@ -334,9 +334,9 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceEnumerateSubInterfaces) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "Animal"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); - ifaceCtxFinder.face->owningModule->target = ABCKIT_TARGET_UNKNOWN; + ifaceCtxFinder.iface->owningModule->target = ABCKIT_TARGET_UNKNOWN; void *data = nullptr; - auto ret = g_implI->interfaceEnumerateSubInterfaces(ifaceCtxFinder.face, data, helpers::InterfaceByNameFinder); + auto ret = g_implI->interfaceEnumerateSubInterfaces(ifaceCtxFinder.iface, data, helpers::InterfaceByNameFinder); ASSERT_FALSE(ret); g_impl->closeFile(file); @@ -357,9 +357,9 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceEnumerateClasses) helpers::InterfaceByNameContext ifaceCtx = {nullptr, "Clickable"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtx, helpers::InterfaceByNameFinder); - ifaceCtx.face->owningModule->target = ABCKIT_TARGET_UNKNOWN; + ifaceCtx.iface->owningModule->target = ABCKIT_TARGET_UNKNOWN; helpers::ClassByNameContext classCtx = {nullptr, "MyButton"}; - auto ret = g_implI->interfaceEnumerateClasses(ifaceCtx.face, &classCtx, helpers::ClassByNameFinder); + auto ret = g_implI->interfaceEnumerateClasses(ifaceCtx.iface, &classCtx, helpers::ClassByNameFinder); ASSERT_FALSE(ret); g_impl->closeFile(file); EXPECT_EQ(g_impl->getLastError(), ABCKIT_STATUS_NO_ERROR); @@ -379,10 +379,10 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceEnumerateMethods) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "Animal"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); - ifaceCtxFinder.face->owningModule->target = ABCKIT_TARGET_UNKNOWN; + ifaceCtxFinder.iface->owningModule->target = ABCKIT_TARGET_UNKNOWN; helpers::MethodByNameContext methodCtx = {nullptr, ""}; - auto ret = g_implI->interfaceEnumerateMethods(ifaceCtxFinder.face, &methodCtx, helpers::MethodByNameFinder); + auto ret = g_implI->interfaceEnumerateMethods(ifaceCtxFinder.iface, &methodCtx, helpers::MethodByNameFinder); ASSERT_FALSE(ret); g_impl->closeFile(file); @@ -403,11 +403,11 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceEnumerateAnnotations) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, "Animal"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtxFinder, helpers::InterfaceByNameFinder); - ifaceCtxFinder.face->owningModule->target = ABCKIT_TARGET_UNKNOWN; + ifaceCtxFinder.iface->owningModule->target = ABCKIT_TARGET_UNKNOWN; helpers::AnnotationByNameContext annotationCtx = {nullptr, ""}; auto ret = - g_implI->interfaceEnumerateAnnotations(ifaceCtxFinder.face, &annotationCtx, helpers::AnnotationByNameFinder); + g_implI->interfaceEnumerateAnnotations(ifaceCtxFinder.iface, &annotationCtx, helpers::AnnotationByNameFinder); ASSERT_FALSE(ret); g_impl->closeFile(file); @@ -428,9 +428,9 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceEnumerateFields) helpers::InterfaceByNameContext ifaceCtx = {nullptr, "Animal"}; g_implI->moduleEnumerateInterfaces(ctx.module, &ifaceCtx, helpers::InterfaceByNameFinder); - ifaceCtx.face->owningModule->target = ABCKIT_TARGET_UNKNOWN; + ifaceCtx.iface->owningModule->target = ABCKIT_TARGET_UNKNOWN; helpers::FieldByNameContext fieldCtx = {nullptr, ""}; - auto ret = g_implI->interfaceEnumerateFields(ifaceCtx.face, &fieldCtx, helpers::FiledByNameFinder); + auto ret = g_implI->interfaceEnumerateFields(ifaceCtx.iface, &fieldCtx, helpers::FieldByNameFinder); ASSERT_FALSE(ret); g_impl->closeFile(file); @@ -450,7 +450,7 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceGetFile02) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, ""}; - auto abcFile = g_implI->interfaceGetFile(ifaceCtxFinder.face); + auto abcFile = g_implI->interfaceGetFile(ifaceCtxFinder.iface); ASSERT_EQ(abcFile, nullptr); g_impl->closeFile(file); @@ -470,7 +470,7 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceGetModule02) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, ""}; - auto module = g_implI->interfaceGetModule(ifaceCtxFinder.face); + auto module = g_implI->interfaceGetModule(ifaceCtxFinder.iface); ASSERT_EQ(module, nullptr); g_impl->closeFile(file); @@ -493,7 +493,7 @@ TEST_F(LibAbcKitInspectApiInterfacesTest, InterfaceGetParentNamespace02) helpers::InterfaceByNameContext ifaceCtxFinder = {nullptr, ""}; - auto petNamespace = g_implI->interfaceGetParentNamespace(ifaceCtxFinder.face); + auto petNamespace = g_implI->interfaceGetParentNamespace(ifaceCtxFinder.iface); ASSERT_EQ(petNamespace, nullptr); g_impl->closeFile(file); diff --git a/static_core/assembler/meta.cpp b/static_core/assembler/meta.cpp index 1382e168b18a753c00edaa311d137030dab2bd33..5305fbe610ac57f737f4208a66a23a14d02242e7 100644 --- a/static_core/assembler/meta.cpp +++ b/static_core/assembler/meta.cpp @@ -447,11 +447,26 @@ std::string RecordMetadata::GetBase() const return ""; } +bool RecordMetadata::SetBase(std::string_view /* unusedParam */) +{ + return false; +} + std::vector RecordMetadata::GetInterfaces() const { return {}; } +bool RecordMetadata::AddInterface(std::string_view /* unusedParam */) +{ + return false; +} + +bool RecordMetadata::RemoveInterface(std::string_view /* unusedParam */) +{ + return false; +} + bool RecordMetadata::IsAnnotation() const { return false; diff --git a/static_core/assembler/meta.h b/static_core/assembler/meta.h index e8002ca586f39c637675d7b264520153e47a5f95..c8bbde2648546cedc96775b771a91117e3346145 100644 --- a/static_core/assembler/meta.h +++ b/static_core/assembler/meta.h @@ -88,11 +88,35 @@ public: setAttributes_.erase(attribute); } + std::optional RemoveAttributeValue(std::string_view attribute, std::string_view value) + { + return RemoveValue(attribute, value); + } + bool GetAttribute(const std::string &attribute) const { return setAttributes_.find(attribute) != setAttributes_.cend(); } + virtual std::optional RemoveValue(std::string_view attribute, std::string_view value) + { + std::string key(attribute); + auto it = attributes_.find(key); + if (it == attributes_.cend()) { + return Error("attribute does not exist.", Error::Type::MISSING_ATTRIBUTE); + } + + std::string valueS(value); + + auto valueIt = std::find(it->second.begin(), it->second.end(), valueS); + if (valueIt == it->second.cend()) { + return Error("value does not exist.", Error::Type::MISSING_VALUE); + } + + it->second.erase(valueIt); + return {}; + } + std::optional SetAttributeValue(std::string_view attribute, std::string_view value) { auto err = Validate(attribute, value); @@ -500,8 +524,14 @@ class RecordMetadata : public ItemMetadata { public: virtual std::string GetBase() const; + virtual bool SetBase(std::string_view base); + virtual std::vector GetInterfaces() const; + virtual bool AddInterface(std::string_view value); + + virtual bool RemoveInterface(std::string_view value); + virtual bool IsAnnotation() const; virtual bool IsRuntimeAnnotation() const; diff --git a/static_core/plugins/ets/assembler/extension/ets_meta.h b/static_core/plugins/ets/assembler/extension/ets_meta.h index 7498b61af85fcf0d88a15c30a270aa3d9893da6b..a14377a90e7a5c0c8a19714459d581167e17a59f 100644 --- a/static_core/plugins/ets/assembler/extension/ets_meta.h +++ b/static_core/plugins/ets/assembler/extension/ets_meta.h @@ -1,5 +1,5 @@ /** - * Copyright (c) 2021-2024 Huawei Device Co., Ltd. + * Copyright (c) 2021-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 @@ -65,11 +65,31 @@ public: return ""; } + bool SetBase(std::string_view base) override + { + if (GetBase() != "std.core.Object") { + return false; + } + + RemoveAttributeValue("ets.extends", "std.core.Object"); + return !SetAttributeValue("ets.extends", base); + } + std::vector GetInterfaces() const override { return GetAttributeValues("ets.implements"); } + bool AddInterface(std::string_view value) override + { + return !SetAttributeValue("ets.implements", value); + } + + bool RemoveInterface(std::string_view value) override + { + return !RemoveAttributeValue("ets.implements", value); + } + bool IsAnnotation() const override { return (GetAccessFlags() & ACC_ANNOTATION) != 0;